Files
inter-hub/docs/phase2-summary.md
Bernd Worsch 840b0e5c7b feat(P2+P3): IHF Phase 2 complete; register Phase 3 workplan
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>
2026-03-29 10:42:56 +00:00

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`.