--- id: IHUB-WP-0002 type: workplan title: "IHF Phase 2 — Structured Feedback and Triage" domain: custodian repo: inter-hub status: done owner: custodian topic_slug: custodian created: "2026-03-28" updated: "2026-03-28" state_hub_workstream_id: "25d4c92c-b213-4c33-9404-822192899de7" --- # IHF Phase 2 — Structured Feedback and Triage ## Goal Transform raw annotations into structured, operable feedback. Introduces AnnotationThread (grouping), RequirementCandidate (escalation), TriageState (lifecycle), and ReviewerAssignment (ownership). Operator triage dashboard with AutoRefresh. ## Background Phase 1 delivered the minimal interaction core: widget registry, interaction event capture, annotation system, and hub-level operator dashboard. Phase 2 closes the gap between raw observation and structured, actionable feedback — enabling operators to group annotations, escalate them into requirement candidates, and drive them through a triage lifecycle. **Entry criteria:** Phase 1 complete (T01–T12 all done, WP-0001 status=done). Reference: `docs/ihp-overview.md`, `docs/ihp-data-and-queries.md`, `docs/ihp-controllers-views-forms.md`, `docs/ihp-realtime.md`, `docs/ihp-ihf-mapping.md`. ## Phase 2 Exit Criteria - Annotations can be grouped into AnnotationThreads - Annotations can be escalated into RequirementCandidates - RequirementCandidates have a full triage lifecycle (open → in_review → accepted/rejected/deferred) - Reviewers can be assigned to candidates - Operator triage dashboard live-updates via AutoRefresh - All integration tests passing - SCOPE.md updated to reflect Phase 2 completion ## Data Artifacts Introduced (Phase 2) `AnnotationThread`, `RequirementCandidate`, `TriageState`, `ReviewerAssignment` --- ## Tasks ### T01 — Schema: AnnotationThread, RequirementCandidate, TriageState, ReviewerAssignment ```task id: IHUB-WP-0002-T01 status: done priority: high state_hub_task_id: "eb267a9e-7e80-4913-b7a3-7f5adb04a0f2" ``` Add Phase 2 tables to `Application/Schema.sql` and write migration. Add severity/intensity field to annotations table. Define: - `AnnotationThread` — grouping of related annotations - `RequirementCandidate` — escalated feedback record - `TriageState` — per-candidate lifecycle row - `ReviewerAssignment` — ownership record Generate IHP types via the IDE code generator. **Exit criteria:** `migrate` succeeds; IHP generated types compile cleanly. --- ### T02 — Severity markers on Annotation ```task id: IHUB-WP-0002-T02 status: done priority: high state_hub_task_id: "fdcbf823-484e-4f0f-a0ca-28f9222520af" ``` Add severity field (low/medium/high/critical) to annotations table via migration. Update `AnnotationsController` `CreateAnnotationAction` to accept and validate severity. Update annotation form and list/show views to display severity with appropriate visual cues (Tailwind color roles per spec). **Exit criteria:** Annotations can be created with a severity; severity renders with correct color coding in list and show views. --- ### T03 — AnnotationThread controller (duplicate grouping) ```task id: IHUB-WP-0002-T03 status: done priority: high state_hub_task_id: "35b989a0-5e2a-4300-990b-f43d67de0727" ``` Scaffold `AnnotationThreadsController`. Allow operator to create a named thread and manually assign annotations to it (many-to-one via `annotation.thread_id` FK). Thread list view shows member annotation count, severity distribution, and dominant category. Enables duplicate/similar-observation grouping. **Exit criteria:** Threads can be created; annotations can be assigned to a thread; thread list shows per-thread aggregates. --- ### T04 — RequirementCandidate controller and views ```task id: IHUB-WP-0002-T04 status: done priority: high state_hub_task_id: "4eb2a51c-1b3f-4b36-b945-6bfb14c2e680" ``` Scaffold `RequirementCandidatesController`. CRUD: index, show, new/create, edit/update (no delete). Fields: title, description, source_widget_id, source_thread_id (optional), category, status (open). Index: list with status, widget, category, reviewer. Show: full detail + linked annotations + triage history. **Exit criteria:** Candidates can be created manually; index and show pages render correctly. --- ### T05 — Escalation action: Annotation(s) → RequirementCandidate ```task id: IHUB-WP-0002-T05 status: done priority: high state_hub_task_id: "5c3a154b-38e0-4e40-9e97-57aae1dbc95d" ``` Add `EscalateAnnotationAction` (HTMX POST) on the annotation show/list page. Pre-populates a new RequirementCandidate form with the annotation body and category. On submit, creates the candidate and records `source_annotation_id`. Add a visual indicator on escalated annotations. **Exit criteria:** Operator can escalate an annotation to a candidate in one action; escalated annotations show a visual marker. --- ### T06 — TriageState lifecycle per RequirementCandidate ```task id: IHUB-WP-0002-T06 status: done priority: high state_hub_task_id: "cd8c3ef1-e0f7-435f-ae20-e0760df5da83" ``` Implement TriageState table (candidate_id, status, changed_by, changed_at, notes). Status lifecycle: open → in_review → accepted | rejected | deferred. Add `UpdateTriageStatusAction` (HTMX). Show full triage history on RequirementCandidate show page. Validate allowed transitions. **Exit criteria:** Status transitions work; invalid transitions are rejected; full history visible on candidate show page. --- ### T07 — ReviewerAssignment: ownership on RequirementCandidate ```task id: IHUB-WP-0002-T07 status: done priority: medium state_hub_task_id: "3dc9bfdb-06d0-48a5-8973-2e39c6e0f78a" ``` Implement ReviewerAssignment (candidate_id, user_id, assigned_by, assigned_at). Add `AssignReviewerAction`. Show current reviewer on candidate index and show pages. Filter index by assignee. Reviewer can see their open candidates via a "My Queue" view under their session. **Exit criteria:** Reviewer can be assigned; "My Queue" shows open candidates for the logged-in reviewer. --- ### T08 — Operator triage dashboard (AutoRefresh) ```task id: IHUB-WP-0002-T08 status: done priority: high state_hub_task_id: "82498422-1626-4479-9daa-3d7c7e088d8e" ``` Extend or add a dedicated triage dashboard action wrapped with `autoRefresh do`. Shows: open RequirementCandidates (count by status), triage queue (oldest open first), recent escalations (last 20), candidates by category breakdown. Live-updates on any candidate/triage state change. **Exit criteria:** Dashboard renders; live-updates on candidate creation and triage status change without page reload. --- ### T09 — Phase 2 gate: tests, consistency, docs ```task id: IHUB-WP-0002-T09 status: done priority: high state_hub_task_id: "935de4d7-867f-49aa-bddf-6ff9435215de" ``` Integration tests: AnnotationThread CRUD; escalation happy path; triage state transitions (valid + invalid); reviewer assignment; dashboard AutoRefresh wrapper present. Consistency sync. Update `SCOPE.md` current state. Write `docs/phase2-summary.md`. Smoke test: create thread, escalate annotation, triage candidate, confirm dashboard updates. **Exit criteria:** All integration tests pass; `SCOPE.md` reflects Phase 2 completion; consistency check passes.