# IHF Phase 7 Summary — Advanced Observability and Operational Integration ## What Was Built Phase 7 turns the accumulated interaction data into operational intelligence. Four new data artifacts and five new views/dashboards give hub leaders a clear picture of where friction is concentrated, where the governance pipeline is stalling, and how hub health is trending over time. ### Data Artifacts **FrictionScore** (`friction_scores`) - One row per widget (unique constraint on `widget_id`); upserted on recompute - Score formula (0–100): `min 100 (annotationCount*5 + errorEventCount*10 + regressionFlag?20:0 + staleCandidateCount*8)` - Bands: 0–19 green, 20–39 yellow, 40–59 amber, 60+ red - `Application/Helper/FrictionScore.hs` — `computeFrictionScore`, `scoreBand` **BottleneckRecord** (`bottleneck_records`) - Detected stalls at four pipeline stages - Severity: `medium` → `high` → `critical` based on how far past the threshold - `resolved_at` nullable — partial index on `WHERE resolved_at IS NULL` for fast active queries - `Application/Helper/BottleneckDetector.hs` — `detectBottlenecks` | Stage | Subject | Threshold | |-------|---------|-----------| | `candidate` | RequirementCandidate open | 30 days | | `requirement` | Requirement without DecisionRecord | 60 days | | `decision` | DecisionRecord without DeploymentRecord | 30 days | | `observation` | DeploymentRecord without OutcomeSignal | 14 days | **HubHealthSnapshot** (`hub_health_snapshots`) - Append-only; every `SnapshotHubHealthAction` inserts a new row - Score formula (0–100): `max 0 (100 - openCandidates*5 - regressedWidgets*10 - staleDecisions*8 - criticalBN*12 - highBN*6)` - `Application/Helper/HubHealth.hs` — `computeHubHealth`, `healthScoreBadge` **CrossHubPropagation** (`cross_hub_propagations`) - Status lifecycle: `open → acknowledged → resolved` - `Application/Helper/CrossHubPropagation.hs` — `detectPropagations` - Two heuristics: - `annotation_cluster`: same annotation category with ≥3 occurrences in ≥2 hubs within 14 days - `widget_type_friction`: same widget type with FrictionScore ≥40 in ≥2 hubs ### Views and Actions **Friction Heatmap** (`FrictionHeatmapAction { hubId }`) - Grid of widget cards, colour-coded by score band - "Recompute" button triggers `RecomputeFrictionAction` for all hub widgets - Linked from hub Show page as "Friction" **Bottleneck Dashboard** (`BottleneckDashboardAction { hubId }`) - Table grouped by pipeline stage; severity badge on each row - "Detect" button runs `DetectBottlenecksAction` - "Resolve" marks `resolved_at`; idempotent detection skips existing active records - Linked from hub Show page as "Bottlenecks" **Hub Health History** (`HubHealthHistoryAction { hubId }`) - Latest snapshot shown prominently with component breakdown - Full history table in reverse chronological order - "Take Snapshot" triggers `SnapshotHubHealthAction` - Linked from hub Show page as "Health" **Operational Review Board** (`OperationalReviewBoardAction`) - Global view, no hub scope — all hubs, all data - Panel 1: Hub health matrix — all hubs, latest score, link to history - Panel 2: Top 10 friction widgets across all hubs - Panel 3: Active bottleneck counts by pipeline stage - Panel 4: Open/acknowledged cross-hub propagation events - `autoRefresh` — live-updates - Linked from global nav as "Ops Review" **Cross-Hub Propagations** (`CrossHubPropagationsAction`) - Global list of all propagation events with status badges - "Detect" triggers `DetectPropagationsAction` (idempotent) - Acknowledge / Resolve actions per row - Linked from global nav as "Propagations" ## Known Limitations - **Friction scores are not append-only.** There is no friction history — only the current score per widget. Use `HubHealthSnapshot` for hub-level trends over time. - **Bottleneck detection requires manually triggering.** Phase 7 does not introduce scheduled jobs. Detection runs on demand via the UI or `curl`. A future phase can layer on a devenv cron task. - **Cross-hub detection requires current friction scores.** Run `RecomputeFrictionAction` on all relevant hubs before `DetectPropagationsAction`, or detection will use stale/absent scores. - **OperationalReviewBoard top-10 friction** is sorted globally — not scoped to a hub. A widget from a single hub could dominate the list if that hub has very high friction scores. - **`subjectId` in BottleneckRecord is untyped UUID.** The `subject_type` column disambiguates, but there is no FK constraint — subject records can be deleted without cascading. A future phase can add per-stage FK columns. ## Phase 8 Readiness Phase 8 (Federated Hub Maturity) can build on Phase 7: - `CrossHubPropagation` already models multi-hub patterns; Phase 8 routing can act on these - `HubHealthSnapshot` history provides a baseline for measuring federated governance quality - The `OperationalReviewBoard` is already global — Phase 8 can add per-organization or per-team scoping - Bottleneck thresholds are constants in helper modules — Phase 8 can make them configurable per hub via a `HubPolicy` table