diff --git a/.claude/ralph-loop.local.md b/.claude/ralph-loop.local.md
deleted file mode 100644
index 4debf7f..0000000
--- a/.claude/ralph-loop.local.md
+++ /dev/null
@@ -1,433 +0,0 @@
----
-active: true
-iteration: 1
-session_id:
-max_iterations: 20
-completion_promise: "HEUREKA"
-workplan_id: IHUB-WP-0007
-workplan_file: workplans/IHUB-WP-0007-ihf-phase7-advanced-observability-and-operational-integration.md
-started_at: "2026-03-29T21:41:13Z"
----
-
-## Workplan Status Check — Do This First, Every Iteration
-
-Read the workplan file at: `workplans/IHUB-WP-0007-ihf-phase7-advanced-observability-and-operational-integration.md`
-
-Count the task blocks (fenced code blocks with language tag `task`):
-- How many tasks exist in total?
-- How many have `status: done`?
-
-If **every task** has `status: done` AND the frontmatter `status` is `done`:
- The workplan is complete. Output exactly: HEUREKA
- Do nothing else. Stop here.
-
-Otherwise: continue with the implementation below.
-
----
-
-## Workplan: IHUB-WP-0007 — IHF Phase 7 — Advanced Observability and Operational Integration
-**File:** `workplans/IHUB-WP-0007-ihf-phase7-advanced-observability-and-operational-integration.md`
-
-
-# IHF Phase 7 — Advanced Observability and Operational Integration
-
-## Goal
-
-Integrate interaction governance with broader operational intelligence. Phase 6
-established cross-framework widget participation. Phase 7 turns the accumulated
-interaction data into operational intelligence: friction heatmaps, pipeline
-bottleneck detection, per-hub health scores, and cross-hub pattern propagation.
-The capstone is an Operational Review Board dashboard that gives hub leaders a
-unified view across all hubs.
-
-## Background
-
-Phases 1–6 are complete. The IHF core (widget registry, interaction events,
-annotations, requirements, decisions, outcomes, agent assistance,
-cross-framework adapters) is stable and extensible.
-
-The spec (§Phase 7) calls for:
-- Hub health correlation
-- Policy violation correlation
-- Workflow bottleneck analysis
-- Interaction pain heatmaps
-- Queue and job linkage
-- Cross-hub issue propagation analysis
-
-Artifacts introduced: `FrictionScore`, `BottleneckRecord`, `HubHealthSnapshot`,
-`CrossHubPropagation`.
-
-Reference: `specs/InteractionHubFrameworkSpecification_v0.1.md` §Phase 7,
-`docs/phase6-summary.md`, `docs/ihp-controllers-views-forms.md`.
-
-## Phase 7 Exit Criteria (from IHF spec §Phase 7)
-
-- Interaction data informs operational decision-making
-- Hub leaders can inspect systemic friction patterns
-- The platform supports cross-domain learning
-
-## Data Artifacts Introduced (Phase 7)
-
-`FrictionScore`, `BottleneckRecord`, `HubHealthSnapshot`, `CrossHubPropagation`
-
-
-## Tasks
-
-### T01 — Schema: FrictionScore, BottleneckRecord, HubHealthSnapshot, CrossHubPropagation
-
-```task
-id: IHUB-WP-0007-T01
-status: todo
-priority: high
-state_hub_task_id: "86e31f8b-62a3-4176-9b10-2fe7a8dbcc23"
-```
-
-Add Phase 7 tables to `Application/Schema.sql` and write migration:
-
-```sql
--- Aggregated pain score per widget, recomputed on demand or scheduled.
-CREATE TABLE friction_scores (
- id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
- widget_id UUID NOT NULL REFERENCES widgets(id),
- score INTEGER NOT NULL DEFAULT 0,
- -- 0–100; higher = more friction
- annotation_count INTEGER NOT NULL DEFAULT 0,
- error_event_count INTEGER NOT NULL DEFAULT 0,
- regression_flag BOOLEAN NOT NULL DEFAULT FALSE,
- stale_candidate_count INTEGER NOT NULL DEFAULT 0,
- last_computed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
- UNIQUE (widget_id)
-);
-
-CREATE INDEX friction_scores_widget_id_idx ON friction_scores (widget_id);
-CREATE INDEX friction_scores_score_idx ON friction_scores (score DESC);
-
--- Detected stalls at specific pipeline stages.
-CREATE TABLE bottleneck_records (
- id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
- hub_id UUID NOT NULL REFERENCES hubs(id),
- stage TEXT NOT NULL,
- -- 'candidate' | 'requirement' | 'decision' | 'observation'
- subject_type TEXT NOT NULL,
- -- 'RequirementCandidate' | 'Requirement' | 'DecisionRecord' | 'DeploymentRecord'
- subject_id UUID NOT NULL,
- stalled_since TIMESTAMP WITH TIME ZONE NOT NULL,
- severity TEXT NOT NULL DEFAULT 'medium',
- -- 'low' | 'medium' | 'high' | 'critical'
- resolved_at TIMESTAMP WITH TIME ZONE,
- notes TEXT,
- created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
-);
-
-CREATE INDEX bottleneck_records_hub_id_idx ON bottleneck_records (hub_id);
-CREATE INDEX bottleneck_records_stage_idx ON bottleneck_records (stage);
-CREATE INDEX bottleneck_records_resolved_idx ON bottleneck_records (resolved_at)
- WHERE resolved_at IS NULL;
-
--- Periodic health snapshots for trend tracking.
-CREATE TABLE hub_health_snapshots (
- id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
- hub_id UUID NOT NULL REFERENCES hubs(id),
- health_score INTEGER NOT NULL,
- -- 0–100
- open_candidates INTEGER NOT NULL DEFAULT 0,
- regressed_widgets INTEGER NOT NULL DEFAULT 0,
- stale_decisions INTEGER NOT NULL DEFAULT 0,
- active_bottlenecks INTEGER NOT NULL DEFAULT 0,
- computed_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
-);
-
-CREATE INDEX hub_health_snapshots_hub_id_idx ON hub_health_snapshots (hub_id);
-CREATE INDEX hub_health_snapshots_computed_at_idx
- ON hub_health_snapshots (hub_id, computed_at DESC);
-
--- Patterns detected across multiple hubs.
-CREATE TABLE cross_hub_propagations (
- id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
- pattern_type TEXT NOT NULL,
- -- 'annotation_cluster' | 'widget_type_friction'
- source_hub_id UUID REFERENCES hubs(id),
- affected_hub_ids JSONB NOT NULL DEFAULT '[]',
- -- array of hub UUIDs
- summary TEXT NOT NULL,
- detected_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
- status TEXT NOT NULL DEFAULT 'open',
- -- 'open' | 'acknowledged' | 'resolved'
- notes TEXT
-);
-
-CREATE INDEX cross_hub_propagations_status_idx ON cross_hub_propagations (status);
-CREATE INDEX cross_hub_propagations_pattern_idx ON cross_hub_propagations (pattern_type);
-```
-
-**Exit criteria:** `migrate` runs cleanly; all Phase 7 types available in GHCi.
-
-
-### T02 — Widget Pain Heatmap: friction scoring and per-hub heatmap view
-
-```task
-id: IHUB-WP-0007-T02
-status: todo
-priority: high
-state_hub_task_id: "3a5ecd28-17c2-4258-bfd9-b3eaecf52135"
-```
-
-1. Add `Application/Helper/FrictionScore.hs` with `computeFrictionScore`:
- - `annotation_count` — total annotations for widget
- - `error_event_count` — events with `event_type = 'errored'`
- - `regression_flag` — `True` if widget appears in `regressedWidgetIds`
- - `stale_candidate_count` — open candidates older than 30 days
- - Score formula (documented in module header):
- ```
- score = min 100 $
- annotationCount * 5
- + errorEventCount * 10
- + (if regressionFlag then 20 else 0)
- + staleCandidateCount * 8
- ```
- - Upserts into `friction_scores` (UPDATE if exists, INSERT otherwise)
-2. Add `RecomputeFrictionAction { hubId }` to `HubsController`:
- - Recomputes scores for all widgets in the hub
- - Redirects back to heatmap view
-3. Add `FrictionHeatmapAction { hubId }` view:
- - Grid of widget cards, colour-coded by score band:
- - 0–19: green (`bg-green-100`)
- - 20–39: yellow (`bg-yellow-100`)
- - 40–59: amber (`bg-orange-100`)
- - 60+: red (`bg-red-100`)
- - Each card: widget name, score, link to widget show
- - "Recompute" button triggers `RecomputeFrictionAction`
-4. Link from hub Show page as "Friction Heatmap"
-
-**Exit criteria:** Scores compute correctly for test fixtures; heatmap renders
-with correct colour bands; recompute updates scores.
-
-
-### T03 — Workflow Bottleneck Analysis: stall detection across the pipeline
-
-```task
-id: IHUB-WP-0007-T03
-status: todo
-priority: high
-state_hub_task_id: "ada0347a-880b-454e-843f-4a9135ea8739"
-```
-
-1. Add `Application/Helper/BottleneckDetector.hs` with `detectBottlenecks`:
- - Stage 1 — `candidate`: `RequirementCandidate` with `status='open'` and
- `created_at < now() - interval '30 days'`
- - Stage 2 — `requirement`: `Requirement` with no linked `DecisionRecord` and
- `created_at < now() - interval '60 days'`
- - Stage 3 — `decision`: `DecisionRecord` with no linked `DeploymentRecord`
- and `decided_at < now() - interval '30 days'`
- - Stage 4 — `observation`: `DeploymentRecord` with no linked `OutcomeSignal`
- and `deployed_at < now() - interval '14 days'`
- - Severity: `critical` if age > 2× threshold, else `high` if > 1.5×, else `medium`
- - Upserts `BottleneckRecord` (skip if already exists for same subject)
-2. Add `DetectBottlenecksAction { hubId }` — runs detector, redirects to dashboard
-3. Add `BottleneckDashboardAction { hubId }` view:
- - Table grouped by pipeline stage
- - Columns: subject (linked), stalled since, age, severity badge
- - "Resolve" button → `ResolveBottleneckAction { bottleneckRecordId }`
- - "Detect" button triggers fresh detection
-4. Link from hub Show page as "Bottlenecks"
-
-**Exit criteria:** Stale candidates create bottleneck records; dashboard renders
-and groups correctly; resolve marks `resolved_at`.
-
-
-### T04 — Hub Health Correlation: composite health score and history
-
-```task
-id: IHUB-WP-0007-T04
-status: todo
-priority: high
-state_hub_task_id: "b0c932c5-fdb7-47b6-adc7-b4f8ed5555e6"
-```
-
-1. Add `Application/Helper/HubHealth.hs` with `computeHubHealth`:
- - Deduction table (documented in module):
- ```
- -5 per open RequirementCandidate
- -10 per regressed widget
- -8 per stale DecisionRecord (decided > 30 days, no deployment)
- -12 per active critical BottleneckRecord
- -6 per active high BottleneckRecord
- floor at 0
- ```
- - Inserts new `HubHealthSnapshot` (never updates — history is append-only)
-2. Add `SnapshotHubHealthAction { hubId }` — computes and redirects to history
-3. Add `HubHealthHistoryAction { hubId }` view:
- - Table of snapshots: timestamp, score (colour-coded), component breakdown
- - Latest score shown prominently at top
-4. Show health score badge on hub Show page (next to dashboard links):
- - Fetch latest snapshot; display colour-coded score pill
- - If no snapshot: "–" with link to take first snapshot
-
-**Exit criteria:** Snapshot computes correct score against test fixtures; history
-table renders in order; badge appears on hub Show page.
-
-
-### T05 — Cross-Hub Propagation Analysis: pattern detection across hubs
-
-```task
-id: IHUB-WP-0007-T05
-status: todo
-priority: medium
-state_hub_task_id: "7a860b9f-a835-47d6-96d8-2964ae37b12d"
-```
-
-1. Add `Application/Helper/CrossHubPropagation.hs` with `detectPropagations`:
- - **Annotation cluster heuristic**: for each annotation `category`, count
- distinct hubs with ≥3 annotations in that category in the last 14 days.
- If ≥2 hubs qualify, emit a `CrossHubPropagation` with
- `pattern_type='annotation_cluster'` and a generated summary.
- - **Widget type friction heuristic**: for each `widget_type`, count hubs
- where the max `FrictionScore` for that type is ≥40. If ≥2 hubs qualify,
- emit `pattern_type='widget_type_friction'`.
- - Skip if a matching open/acknowledged propagation already exists
- (idempotent detection)
-2. Add `DetectPropagationsAction` (global, no hubId) — runs detector
-3. Add `CrossHubPropagationsAction` view (global):
- - Table: pattern type, source hub, affected hubs (comma list), summary,
- detected at, status badge
- - "Acknowledge" and "Resolve" actions
-4. Link from global nav (alongside "Adapters", "Ops Review")
-
-**Exit criteria:** Detection creates propagation records for qualifying patterns;
-duplicate runs are idempotent; acknowledge/resolve transitions work.
-
-
-### T06 — Operational Review Board Dashboard: cross-hub unified view
-
-```task
-id: IHUB-WP-0007-T06
-status: todo
-priority: medium
-state_hub_task_id: "ffabc4d1-c166-4b7d-8bec-55365cbe0666"
-```
-
-1. Add `OperationalReviewBoardAction` to a new `OperationsController`
- (or `HubsController` as a global action — no `hubId` parameter):
- - **Panel 1 — Hub health matrix**: all hubs, latest health score (or "–"),
- colour-coded row, link to hub and to health history
- - **Panel 2 — Top friction widgets**: top 10 across all hubs by
- `FrictionScore.score DESC`; columns: widget name, hub, score band, link
- - **Panel 3 — Active bottlenecks by stage**: count of unresolved bottlenecks
- per stage across all hubs; click-through to hub bottleneck dashboard
- - **Panel 4 — Open cross-hub propagations**: list of open/acknowledged
- propagation events with pattern type and affected hub count
-2. `autoRefresh` — live-updates
-3. Link from global nav as "Ops Review"
-4. Link from global nav cross-hub propagation count badge if > 0
-
-**Exit criteria:** Dashboard renders all four panels; health matrix shows all
-hubs; top friction list is correctly sorted; live-updates on data change.
-
-
-### T07 — Phase 7 gate: tests, consistency, docs
-
-```task
-id: IHUB-WP-0007-T07
-status: todo
-priority: high
-state_hub_task_id: "a14b94f8-3b27-4f0c-9949-60fb65a57a05"
-```
-
-1. **Integration tests** (`Test/`):
- - `FrictionScore` compute formula: widget with known annotation count →
- expected score
- - `BottleneckRecord` create + resolve: stale candidate → bottleneck detected;
- resolve sets `resolved_at`
- - `HubHealthSnapshot` compute: hub with known candidates/regressions → expected
- score; history fetch returns in order
- - `CrossHubPropagation` create + acknowledge + resolve
- - `OperationalReviewBoard` action: compiles, fetches all hubs, returns 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 7 complete
- - Write `docs/phase7-summary.md`: what was built, scoring formulae, bottleneck
- thresholds, cross-hub heuristics, known limitations, Phase 8 readiness
-4. **Smoke test checklist:**
- - Create two hubs with widgets and annotations; run friction recompute; verify
- heatmap colours
- - Age a candidate by force-setting `created_at`; run detect bottlenecks;
- verify record appears
- - Snapshot health for both hubs; verify Ops Review Board health matrix
- - Trigger cross-hub propagation detection; verify propagation record
- - Open Ops Review Board; confirm all four panels populate
-
-**Exit criteria:** All tests pass; consistency sync reports no errors; smoke
-test completed; SCOPE.md updated.
-
-
-## Phase 7 Dependencies
-
-- Phases 1–6 schema stable (widget registry, interaction events, annotations,
- requirements, decisions, outcomes, agent proposals, adapter specs)
-- `friction_scores` requires widgets (T01 before T02)
-- `bottleneck_records` requires hubs, candidates, requirements, decisions,
- deployments (T01 before T03)
-- `hub_health_snapshots` requires hubs and reads from bottleneck_records
- (T03 before T04)
-- `cross_hub_propagations` requires hub friction scores (T02 before T05)
-- Operational Review Board aggregates all Phase 7 data (T02–T05 before T06)
-- All feature tasks (T01–T06) before gate (T07)
-
-## Notes
-
-- **Friction scores are recomputed, not append-only.** Each widget has at most
- one `FrictionScore` row (unique constraint on `widget_id`). Historical trend
- is not tracked at the friction level — use `HubHealthSnapshot` for trends.
-- **Bottleneck detection is idempotent.** Re-running the detector skips records
- where an unresolved bottleneck already exists for the same subject.
-- **Health snapshots are append-only.** Every `SnapshotHubHealthAction` call
- inserts a new row. This preserves the health history for trend analysis.
-- **Cross-hub detection requires FrictionScores to be current.** Run
- `RecomputeFrictionAction` for all hubs before `DetectPropagationsAction`.
-- **No scheduled jobs in Phase 7.** Detection and recomputation are triggered
- manually via UI or curl. Phase 8 can layer on a cron/job system.
-- **Severity thresholds and score weights are constants in the helper modules.**
- They are intentionally not stored in the DB to avoid config drift — change
- them in code and recompute.
-
----
-
-## How to Work
-
-- Stay strictly within the scope of the workplan above
-- Work through tasks in priority order (high → medium → low)
-- Use TDD where applicable: write a failing test, make it pass, then refactor
-- Use whatever test runner, linter, and build tools this repository already uses
-- Consult existing documentation (README, docs/, wiki/, specs/) for context
-- Document significant architecture decisions as ADRs if the project uses them
-
-## Updating Task Status
-
-As you complete each task, edit the workplan file to update its status:
-
-```
-status: todo → status: in_progress (when you start it)
-status: in_progress → status: done (when it is verified complete)
-```
-
-When **every task** is `done`, also update the workplan frontmatter:
-
-```
-status: active → status: done
-```
-
-## Success Criteria
-
-Before marking the workplan done and outputting `HEUREKA`,
-verify all of the following are true:
-
-1. Every task block in `workplans/IHUB-WP-0007-ihf-phase7-advanced-observability-and-operational-integration.md` has `status: done`
-2. The workplan frontmatter `status` is `done`
-3. The full test suite passes with no failures
-4. The codebase passes the project's standard code-quality checks
- (linting, type checking, formatting — whatever applies to this project)
-5. Documentation reflects the implemented behaviour
-
-Output `HEUREKA` only when all five are genuinely true.
-