generated from coulomb/repo-seed
Phase 2 — Structured Feedback and Triage (IHUB-WP-0002): - Schema: annotation_threads, requirement_candidates, triage_states, reviewer_assignments; annotations extended with severity + thread_id - AnnotationThreadsController: create threads, assign annotations - RequirementCandidatesController: CRUD, escalation, triage lifecycle, reviewer assignment, my-queue - Annotation severity (low/medium/high/critical) with Tailwind color cues - TriageDashboardAction on HubsController with autoRefresh - Integration tests (T01–T09), SCOPE.md updated, docs/phase2-summary.md Phase 3 — Governance and Decision Linkage (IHUB-WP-0003): - Workplan registered: 9 tasks, State Hub workstream 5f201ee3 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
120 lines
5.4 KiB
Markdown
120 lines
5.4 KiB
Markdown
# IHF Phase 2 — Structured Feedback and Triage: Summary
|
|
|
|
## What Was Built
|
|
|
|
Phase 2 transforms raw annotations into governable, triageable feedback. It delivers five
|
|
capabilities on top of the Phase 1 interaction core.
|
|
|
|
### 1. Annotation Severity (`T01`, `T02`)
|
|
|
|
Every annotation now carries a `severity` value (`low` / `medium` / `high` / `critical`,
|
|
default `medium`). Severity is validated on create, displayed with Tailwind color cues
|
|
(gray / blue / yellow / red), and visible throughout annotation index, show, and thread views.
|
|
|
|
### 2. Annotation Threads (`T03`)
|
|
|
|
`AnnotationThread` groups related annotations under a named thread scoped to a widget.
|
|
Operators create threads manually, then assign individual annotations to them via
|
|
`AssignAnnotationToThreadAction`. Thread views show a severity distribution bar and
|
|
dominant category badge, giving a quick signal about the nature of the cluster.
|
|
|
|
Routes: `/widgets/:widgetId/threads/`
|
|
|
|
### 3. Requirement Candidates (`T04`, `T05`)
|
|
|
|
`RequirementCandidate` is the first artifact in the IHF traceability chain beyond raw
|
|
feedback. It can be created:
|
|
|
|
- **Manually** via `/requirement-candidates/new` (operator selects widget, thread, category).
|
|
- **By escalation** from an annotation detail page — `EscalateAnnotationAction` creates a
|
|
candidate pre-populated from the annotation and links `source_annotation_id`. Escalation
|
|
is idempotent: a second click redirects to the existing candidate.
|
|
|
|
Candidates are never deleted; they can only be rejected or deferred to preserve the audit trail.
|
|
|
|
### 4. Triage Lifecycle (`T06`)
|
|
|
|
`TriageState` records every status transition as an append-only audit log. Allowed transitions:
|
|
|
|
```
|
|
open → in_review
|
|
in_review → accepted | rejected | deferred
|
|
deferred → in_review
|
|
```
|
|
|
|
`UpdateTriageStatusAction` validates the transition and returns 422 on invalid moves.
|
|
The candidate's `status` column is kept in sync as a denormalised read-optimised cache;
|
|
`triage_states` is the authoritative history.
|
|
|
|
### 5. Reviewer Assignment & My Queue (`T07`)
|
|
|
|
`ReviewerAssignment` tracks one reviewer per candidate (unique constraint). Assignment is
|
|
an upsert (old record deleted, new inserted). `MyQueueAction` shows the current user's
|
|
assigned open/in-review candidates.
|
|
|
|
### 6. Triage Dashboard (`T08`)
|
|
|
|
`TriageDashboardAction` (on `HubsController`) is wrapped with `autoRefresh do` for live
|
|
push updates. It renders:
|
|
|
|
- **KPI row** — counts per status (open / in\_review / accepted / rejected / deferred).
|
|
- **Triage queue** — open candidates for the hub's widgets, oldest first.
|
|
- **Recent escalations** — last 20 candidates across the hub.
|
|
- **Category breakdown** — annotation counts per category as a horizontal bar chart.
|
|
|
|
The `{autoRefreshMeta}` tag is emitted in the view head; morphdom.js handles DOM diffing
|
|
on each WebSocket push.
|
|
|
|
---
|
|
|
|
## Files Created / Modified
|
|
|
|
| Path | Change |
|
|
|------|--------|
|
|
| `Application/Schema.sql` | Added `annotation_threads`, `severity`/`thread_id` on `annotations`, `requirement_candidates`, `triage_states`, `reviewer_assignments` |
|
|
| `Application/Migration/1743120000-ihf-phase2-feedback-triage.sql` | Phase 2 migration |
|
|
| `Web/Types.hs` | Extended `AnnotationsController`; added `AnnotationThreadsController`, `RequirementCandidatesController`, `TriageDashboardAction` |
|
|
| `Web/Routes.hs` | Registered Phase 2 controllers |
|
|
| `Web/Controller/Annotations.hs` | Added `ShowAnnotationAction`, `EscalateAnnotationAction`, severity binding |
|
|
| `Web/Controller/AnnotationThreads.hs` | New |
|
|
| `Web/Controller/RequirementCandidates.hs` | New — full CRUD + triage + reviewer + my-queue |
|
|
| `Web/Controller/Hubs.hs` | Added `TriageDashboardAction` |
|
|
| `Web/View/Annotations/New.hs` | Added severity select |
|
|
| `Web/View/Annotations/Index.hs` | Severity badges, Escalate/Details link |
|
|
| `Web/View/Annotations/Show.hs` | New — annotation detail + escalation UI |
|
|
| `Web/View/AnnotationThreads/{Index,New,Show}.hs` | New |
|
|
| `Web/View/RequirementCandidates/{Index,New,Edit,Show}.hs` | New |
|
|
| `Web/View/Hubs/Show.hs` | Triage Dashboard link |
|
|
| `Web/View/Hubs/TriageDashboard.hs` | New |
|
|
| `Test/Integration.hs` | Phase 2 integration tests |
|
|
| `SCOPE.md` | Updated current state to Phase 2 complete |
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
- **No HTMX partial swaps** — triage and escalation actions use full redirects rather than
|
|
HTMX in-place swaps. The architecture supports HTMX (types are `data`-driven), but the
|
|
Phase 2 target was to deliver correct behaviour; HTMX enhancement is Phase 3 polish.
|
|
- **No duplicate-detection heuristics** — annotation threading is fully operator-driven.
|
|
Automated similarity/clustering is Phase 3+ scope per the workplan notes.
|
|
- **My Queue is not linked from the nav** — accessible via `/my-queue`. A nav link should
|
|
be added in a follow-up.
|
|
- **TriageState is never cleaned up** — by design (append-only audit trail). No archival
|
|
policy is defined yet.
|
|
|
|
---
|
|
|
|
## Phase 3 Readiness
|
|
|
|
Phase 2 exit criteria are met:
|
|
|
|
- [x] Feedback volume can be triaged rather than merely stored
|
|
- [x] Multiple related comments can converge into a structured candidate
|
|
- [x] Reviewers can track status and ownership
|
|
|
|
Phase 3 (Decision Records) can begin. Prerequisites already in place:
|
|
- `RequirementCandidate` with `accepted` status is the input artifact.
|
|
- `source_widget_id`, `source_thread_id`, `source_annotation_id` provide full traceability back.
|
|
- `triage_states` audit trail establishes provenance for any future `DecisionRecord`.
|