From 1862bb295a22670008069ea780b8f6c4b2976a4b Mon Sep 17 00:00:00 2001 From: Bernd Worsch Date: Sun, 29 Mar 2026 14:17:59 +0000 Subject: [PATCH] chore: register Phase 5 workplan (IHUB-WP-0005) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Registers Phase 5 (Agent-Assisted Distillation) workplan with 9 tasks (T01–T09) covering schema, AgentProposalsController, Claude API integration, and agent audit dashboard. Updates CLAUDE.md to point to the Phase 5 workplan and adds IHP_ANTHROPIC_API_KEY to the required env vars table. Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 15 +- ...-ihf-phase5-agent-assisted-distillation.md | 420 ++++++++++++++++++ 2 files changed, 428 insertions(+), 7 deletions(-) create mode 100644 workplans/IHUB-WP-0005-ihf-phase5-agent-assisted-distillation.md diff --git a/CLAUDE.md b/CLAUDE.md index 8df8c52..949da48 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co **inter-hub** is the reference implementation of the **Interaction Hub Framework (IHF)** — a governed, observable interaction substrate for hub-based AI-enabled software systems. It treats every UI element as a governed artifact, creating a full traceability chain from rendered widget → user interaction → structured feedback → requirement candidate → decision record → implementation change → observed outcome. -**Current state:** Phases 1–3 complete. Phase 4 (Outcome Observation and Antifragility Loop) is the active implementation target. +**Current state:** Phases 1–4 complete. Phase 5 (Agent-Assisted Distillation and Suggestion) is the active implementation target. For situational context, read `SCOPE.md`. For architecture depth, read `specs/InteractionHubFrameworkSpecification_v0.1.md`. @@ -104,17 +104,18 @@ Key rules: | `IHP_SESSION_SECRET` | Session encryption key | | `DATABASE_URL` | Postgres connection string | | `IHP_BASEURL` | External URL (e.g., `https://example.com`) | +| `IHP_ANTHROPIC_API_KEY` | Anthropic API key for Phase 5 agent-assisted distillation | ## Active Workplan -Phase 4 work is tracked in `workplans/IHUB-WP-0004-ihf-phase4-outcome-observation-and-antifragility.md` (9 tasks, T01–T09). Use `/ralph-workplan workplans/IHUB-WP-0004-ihf-phase4-outcome-observation-and-antifragility.md` to drive implementation loops. +Phase 5 work is tracked in `workplans/IHUB-WP-0005-ihf-phase5-agent-assisted-distillation.md` (9 tasks, T01–T09). Use `/ralph-workplan workplans/IHUB-WP-0005-ihf-phase5-agent-assisted-distillation.md` to drive implementation loops. -Phase 4 exit criteria: -- The platform can determine whether a change improved outcomes -- Recurrent friction becomes visible -- The system supports evidence-based UI evolution +Phase 5 exit criteria: +- AI assistance reduces triage and synthesis burden +- Human reviewers remain in control +- AI outputs are auditable and attributable -Completed workplans: IHUB-WP-0001 (Phase 1), IHUB-WP-0002 (Phase 2), IHUB-WP-0003 (Phase 3). +Completed workplans: IHUB-WP-0001 (Phase 1), IHUB-WP-0002 (Phase 2), IHUB-WP-0003 (Phase 3), IHUB-WP-0004 (Phase 4). ## Key Reference Docs diff --git a/workplans/IHUB-WP-0005-ihf-phase5-agent-assisted-distillation.md b/workplans/IHUB-WP-0005-ihf-phase5-agent-assisted-distillation.md new file mode 100644 index 0000000..c76c573 --- /dev/null +++ b/workplans/IHUB-WP-0005-ihf-phase5-agent-assisted-distillation.md @@ -0,0 +1,420 @@ +--- +id: IHUB-WP-0005 +type: workplan +title: "IHF Phase 5 — Agent-Assisted Distillation and Suggestion" +domain: inter_hub +repo: inter-hub +status: active +owner: custodian +topic_slug: inter_hub +created: "2026-03-29" +updated: "2026-03-29" +state_hub_workstream_id: "535a6479-9852-4386-8ad0-f86397a018c5" +--- + +# IHF Phase 5 — Agent-Assisted Distillation and Suggestion + +## Goal + +Introduce bounded AI support into the interaction-governance loop. Phase 4 +established the antifragility loop — outcome signals, regression detection, +recurrence tracking. Phase 5 adds AI capability to reduce the cognitive burden +on human reviewers: cluster summaries, drafted requirement candidates, duplicate +detection, policy-sensitivity flagging, and implementation path proposals. + +All AI outputs are **attributable** (model_ref recorded), **reviewable** +(AgentReviewRecord), and **reversible** (proposals can be rejected). No +autonomous final decisions. No silent requirement promotion. + +## Background + +Phase 1 (IHUB-WP-0001) delivered the Minimal Interaction Core. Phase 2 +(IHUB-WP-0002) delivered Structured Feedback and Triage. Phase 3 +(IHUB-WP-0003) delivered Governance and Decision Linkage. Phase 4 +(IHUB-WP-0004) delivered Outcome Observation and Antifragility. All Phase 4 +exit criteria are met. + +Phase 5 is the fifth of eight phases in the IHF specification +(`specs/InteractionHubFrameworkSpecification_v0.1.md`, §14 Phase 5). + +**Technology stack:** IHP v1.5 (Haskell, Nix), PostgreSQL, Anthropic API +(claude-sonnet-4-6). Agent calls are synchronous HTTP in controller actions. +API key from `IHP_ANTHROPIC_API_KEY` environment variable. + +Reference: `docs/ihp-overview.md`, `docs/ihp-data-and-queries.md`, +`docs/ihp-controllers-views-forms.md`, `docs/ihp-realtime.md`. + +## Phase 5 Exit Criteria (from IHF spec §14 Phase 5) + +- AI assistance reduces triage and synthesis burden +- Human reviewers remain in control +- AI outputs are auditable and attributable + +## Data Artifacts Introduced (Phase 5) + +`AgentProposal`, `AgentReviewRecord`, `ConfidenceAnnotation` + +--- + +## Tasks + +### T01 — Schema: AgentProposal, AgentReviewRecord, ConfidenceAnnotation + +```task +id: IHUB-WP-0005-T01 +status: todo +priority: high +state_hub_task_id: "6e1a9d31-a7e9-4d71-a726-44eaf739371c" +``` + +Add Phase 5 tables to `Application/Schema.sql` and write migration: + +```sql +CREATE TABLE agent_proposals ( + id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL, + proposal_type TEXT NOT NULL, + -- proposal_type values: summary | requirement_draft | duplicate_flag | + -- policy_flag | impl_proposal + source_widget_id UUID REFERENCES widgets(id) ON DELETE SET NULL, + source_candidate_id UUID REFERENCES requirement_candidates(id) ON DELETE SET NULL, + source_thread_id UUID REFERENCES annotation_threads(id) ON DELETE SET NULL, + source_decision_id UUID REFERENCES decision_records(id) ON DELETE SET NULL, + content TEXT NOT NULL, + model_ref TEXT NOT NULL, -- e.g. "claude-sonnet-4-6" + confidence NUMERIC CHECK (confidence BETWEEN 0 AND 1), + status TEXT NOT NULL DEFAULT 'pending', + -- status values: pending | accepted | rejected | superseded + created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL +); + +CREATE INDEX agent_proposals_proposal_type_idx ON agent_proposals (proposal_type); +CREATE INDEX agent_proposals_status_idx ON agent_proposals (status); +CREATE INDEX agent_proposals_source_widget_id_idx ON agent_proposals (source_widget_id); +CREATE INDEX agent_proposals_created_at_idx ON agent_proposals (created_at DESC); + +-- One review record per proposal (human decision on AI output) +CREATE TABLE agent_review_records ( + id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL, + proposal_id UUID NOT NULL REFERENCES agent_proposals(id) ON DELETE CASCADE, + reviewer_id UUID REFERENCES users(id), + decision TEXT NOT NULL, -- accepted | rejected | modified + notes TEXT, + reviewed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL, + UNIQUE (proposal_id) +); + +CREATE INDEX agent_review_records_proposal_id_idx ON agent_review_records (proposal_id); + +-- Confidence annotations — per-dimension breakdown of AI confidence +CREATE TABLE confidence_annotations ( + id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL, + proposal_id UUID NOT NULL REFERENCES agent_proposals(id) ON DELETE CASCADE, + dimension TEXT NOT NULL, + -- dimension values: accuracy | relevance | completeness | policy_alignment + score NUMERIC NOT NULL CHECK (score BETWEEN 0 AND 1), + explanation TEXT, + created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL +); + +CREATE INDEX confidence_annotations_proposal_id_idx ON confidence_annotations (proposal_id); +``` + +- `agent_proposals.status` transitions: `pending → accepted | rejected | superseded` +- `agent_review_records` has UNIQUE on `proposal_id` — one review per proposal +- Add `IHP_ANTHROPIC_API_KEY` to CLAUDE.md required env vars table + +**Exit criteria:** `migrate` runs cleanly; all Phase 5 types available in GHCi. + +--- + +### T02 — AgentProposalsController and views + +```task +id: IHUB-WP-0005-T02 +status: todo +priority: high +state_hub_task_id: "5a9b9d51-dcdf-4dad-b449-08a7091e4563" +``` + +1. Scaffold `AgentProposalsController` +2. Actions: `index`, `show`, `AcceptProposalAction`, `RejectProposalAction` + (no update/delete — proposals are immutable audit artifacts) +3. Index: table filterable by `proposal_type` and `status`: + - type badge (color per type), source widget name, confidence bar, status, + created_at +4. Show: content panel + confidence dimension breakdown + review form + (decision select + notes textarea) + attribution footer (model_ref, created_at) +5. After accept/reject: redirect to proposal show with success message +6. Accept/reject is idempotent — if review record already exists, redirect + with "Already reviewed" message +7. Add nav link "Agent" to global nav in `FrontController.hs` + +**Proposal type colors:** +- `summary` → blue +- `requirement_draft` → indigo +- `duplicate_flag` → orange +- `policy_flag` → red +- `impl_proposal` → green + +**Exit criteria:** Proposals can be listed, viewed, accepted, and rejected; +review record created correctly; idempotent guard works. + +--- + +### T03 — Cluster summarization via Claude API + +```task +id: IHUB-WP-0005-T03 +status: todo +priority: high +state_hub_task_id: "630d8d95-a009-4406-82e2-27f62fabcd3c" +``` + +1. `SummarizeClusterAction { widgetId }` (POST from widget show page) +2. Fetch last 20 annotations + annotation threads for the widget +3. Build prompt: + - **System:** "You are a distillation assistant for a governed interaction + hub. Summarize the following user feedback cluster into a concise, + actionable summary (2–4 sentences). Be factual and neutral." + - **User:** formatted annotation text +4. Call Anthropic Messages API (`claude-sonnet-4-6`, `max_tokens=300`) +5. Create `AgentProposal`: + - `proposal_type = "summary"` + - `source_widget_id = widgetId` + - `model_ref = "claude-sonnet-4-6"` + - `content = response text` + - `confidence = NULL` (summaries have no numeric confidence) +6. On widget show page: "Summarize Feedback" button → POST; after POST + redirect back, show latest summary proposal in a collapsible panel +7. HTTP client: use `http-conduit` + `aeson`; API key from + `IHP_ANTHROPIC_API_KEY` env var (error if absent) +8. Handle API errors gracefully — set error flash, redirect back + +**Exit criteria:** Summary proposal created and visible on widget show page; +API errors produce a user-visible error message (not a 500). + +--- + +### T04 — AI-drafted requirement candidate + +```task +id: IHUB-WP-0005-T04 +status: todo +priority: high +state_hub_task_id: "4c9d23f7-1744-48c8-90b5-71854d9b7daf" +``` + +1. `DraftRequirementAction { widgetId }` (POST from widget show page) +2. Fetch last 20 annotations for the widget +3. Build prompt: + - **System:** "You are a requirements analyst. Given these friction + annotations, draft a single structured requirement candidate. Respond + with JSON: {\"title\": \"...\", \"description\": \"...\"}." + - **User:** formatted annotation text +4. Parse JSON response; create `AgentProposal`: + - `proposal_type = "requirement_draft"` + - `content = raw JSON string from response` +5. On `AcceptProposalAction` for a `requirement_draft` proposal: + - Parse `content` as JSON + - Create `RequirementCandidate`: + - `title` and `description` from parsed JSON + - `source_widget_id = proposal.source_widget_id` + - `category = "friction"` + - `status = "open"` + - Update proposal `status = "accepted"` + - Create `AgentReviewRecord` (decision = "accepted") + - Set success flash: "Requirement candidate created from AI draft" +6. "Draft Requirement" button on widget show page (only when ≥ 3 annotations) + +**Exit criteria:** Draft proposal created; acceptance creates a +`RequirementCandidate`; review record present; no candidate created without +human acceptance. + +--- + +### T05 — Duplicate candidate detection + +```task +id: IHUB-WP-0005-T05 +status: todo +priority: medium +state_hub_task_id: "969b7c7f-c3ba-4892-a1d0-faedf536d1c6" +``` + +1. `DetectDuplicatesAction { requirementCandidateId }` (POST from candidate + show page) +2. Fetch the candidate + all other `RequirementCandidate` records +3. Build prompt: + - **System:** "You are a deduplication assistant. Given a target candidate + and a list of existing candidates, identify likely duplicates. Respond + with JSON: {\"duplicates\": [{\"id\": \"uuid\", \"reason\": \"...\"}]}." + - **User:** target candidate + list of candidates (id, title, description) +4. Parse response; create `AgentProposal`: + - `proposal_type = "duplicate_flag"` + - `source_candidate_id = requirementCandidateId` + - `content = JSON string of duplicates array` +5. On candidate show page: "Check Duplicates" button → POST; show "Possible + Duplicates" panel with links to flagged candidates and rationale +6. Informational only — no automated merging or status changes + +**Exit criteria:** Duplicate proposal created; flagged candidates rendered as +links on candidate show page; empty duplicates array handled gracefully. + +--- + +### T06 — Policy-sensitive issue detection + +```task +id: IHUB-WP-0005-T06 +status: todo +priority: medium +state_hub_task_id: "475290e0-7842-4336-a57c-04fa62652094" +``` + +1. `DetectPolicySensitivityAction { requirementCandidateId }` (POST from + candidate show page) +2. Fetch candidate + widget `policy_scope` + existing `PolicyReference` + constraint notes for linked decisions +3. Build prompt: + - **System:** "You are a policy compliance assistant. Analyse this + requirement candidate for potential policy concerns. Valid scopes: + internal, external, regulatory, contractual, architectural. Respond + with JSON: {\"concerns\": [{\"scope\": \"...\", \"note\": \"...\"}], + \"severity\": \"low|medium|high\"}." + - **User:** candidate title/description + policy context +4. Create `AgentProposal`: + - `proposal_type = "policy_flag"` + - `content = JSON string` + - `confidence = severity mapped to numeric (low=0.3, medium=0.6, high=0.9)` +5. Create one `ConfidenceAnnotation` per concern scope dimension +6. On candidate show page: "Policy Check" panel — amber badge if concerns, + green badge if clean + +**Exit criteria:** Policy proposal created with confidence annotation; +concern severity rendered correctly; clean result (empty concerns) handled. + +--- + +### T07 — Implementation path proposal + +```task +id: IHUB-WP-0005-T07 +status: todo +priority: medium +state_hub_task_id: "7ee1274e-fa1b-4ae8-a360-4abafc1773f0" +``` + +1. `ProposeImplementationAction { decisionRecordId }` (POST from decision + show page) +2. Fetch decision + linked requirement + existing `ImplementationChangeReference` + records +3. Build prompt: + - **System:** "You are a traceability-aware implementation analyst. Propose + 1–3 concrete implementation paths for this decision. Each path should + include a work_item_ref (e.g. PROJ-123), a system (github|linear|jira), + and a rationale. Respond with JSON: {\"proposals\": [{\"work_item_ref\": + \"...\", \"system\": \"...\", \"rationale\": \"...\"}]}." + - **User:** decision title, rationale, outcome, requirement description, + existing impl refs +4. Create `AgentProposal`: + - `proposal_type = "impl_proposal"` + - `source_decision_id = decisionRecordId` + - `content = JSON string` +5. On decision show page: "Propose Implementation" button; accepted proposals + pre-fill the AddImplementationRef form (first proposal in the array) +6. Surface as collapsed "AI Suggestions" panel on decision show page + +**Exit criteria:** Impl proposal created; acceptance pre-fills the impl ref +form; multiple proposal paths rendered clearly. + +--- + +### T08 — Agent attribution and audit dashboard (AutoRefresh) + +```task +id: IHUB-WP-0005-T08 +status: todo +priority: high +state_hub_task_id: "53b58abb-cb50-4985-a1c0-b05da17dfc3f" +``` + +1. Add `AgentAuditDashboardAction { hubId }` to `HubsController` wrapped + with `autoRefresh do` +2. Dashboard panels: + - **KPI row**: total proposals / pending / acceptance rate / rejection rate + - **Proposals by type**: count breakdown per `proposal_type` + - **Unreviewed queue**: proposals with `status = "pending"`, oldest first, + with "Review" links + - **Recent proposals** (last 20): type badge, source widget, status, + confidence, age + - **Attribution log**: `model_ref × proposal_type` count matrix +3. Link from hub Show page alongside Triage / Governance / Antifragility +4. Add "Agent" link to global nav + +**Exit criteria:** Dashboard live-updates on proposal/review changes. All five +panels render with correct data. + +--- + +### T09 — Phase 5 gate: tests, consistency, docs + +```task +id: IHUB-WP-0005-T09 +status: todo +priority: high +state_hub_task_id: "c7b8aef0-b241-4038-99c0-494c45f226a6" +``` + +1. **Integration tests** (`Test/`): + - AgentProposal create + fetch (all fields) + - AcceptProposalAction for `requirement_draft` → creates `RequirementCandidate` + - RejectProposalAction → sets `status = "rejected"`, creates review record + - Review record idempotency (second accept/reject → "Already reviewed") + - ConfidenceAnnotation create + link to proposal + - Duplicate detection: proposal with empty duplicates array + - Agent audit dashboard data fetch: compiles and returns correct counts +2. **Consistency sync** via State Hub MCP: + `check_repo_consistency(repo_slug="inter-hub", fix=True)` +3. **Documentation updates:** + - Update `SCOPE.md` current state section: Phase 5 complete + - Write `docs/phase5-summary.md`: what was built, governance constraints + upheld, known limitations, Phase 6 readiness +4. **Smoke test checklist:** + - Summarize feedback cluster on a widget with annotations + - Draft a requirement from the summary + - Accept the draft → verify RequirementCandidate created + - Check duplicates on a candidate + - Run policy check on a candidate + - Confirm agent audit dashboard shows all panels + +**Exit criteria:** All tests pass; consistency sync reports no errors; smoke +test completed; SCOPE.md updated. + +--- + +## Phase 5 Dependencies + +- Phase 4 schema stable (Phase 4 tables needed as context for impl proposals) +- `http-conduit` and `aeson` available (already in IHP's Haskell ecosystem) +- `IHP_ANTHROPIC_API_KEY` set in environment +- Schema (T01) before all controller work (T02–T08) +- `AgentProposalsController` (T02) before all agent action tasks (T03–T07) +- All feature tasks (T01–T08) before gate (T09) + +## Notes + +- **All AI outputs are attributed.** `model_ref` is recorded on every + `AgentProposal`. Reviewers see exactly which model produced the output. +- **No silent promotion.** A `requirement_draft` proposal only becomes a + `RequirementCandidate` when a human explicitly accepts it via + `AcceptProposalAction`. The controller enforces this. +- **Review record is idempotent.** UNIQUE constraint on + `agent_review_records.proposal_id`. Second accept/reject redirects with + "Already reviewed" message. +- **API errors do not crash.** All Claude API calls are wrapped in error + handling; failures produce a user-visible flash message and redirect. +- **Confidence is optional for summaries.** `AgentProposal.confidence` is + nullable — summary proposals do not produce a numeric confidence score. + Policy flag proposals derive confidence from severity (low/medium/high). +- **No ML infrastructure.** All intelligence is delegated to the Anthropic + API. Phase 5 adds no local model serving, no embeddings storage.