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

5.4 KiB

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:

  • Feedback volume can be triaged rather than merely stored
  • Multiple related comments can converge into a structured candidate
  • 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.