dashboard: prominent KPI infobox, doc-overlay component, decisions reference page

KPI infobox
- Replace slim kpi-bar with a boxed card (border, shadow, 195–240px) floating
  right in a flex header alongside the live indicator
- Rows: avg resolve time (last ≤5 resolved) + avg open age (all open)
- avg open age colored via CSS var --oc: red/orange/black per threshold
- "no open decisions" shown as muted italic when queue is empty

doc-overlay component (src/components/doc-overlay.js)
- withDocHelp(element, docPath) — adds absolute-positioned ? button
  that is invisible until the parent is hovered; click opens overlay
- Overlay: fixed backdrop + animated box with iframe; closes on Esc,
  backdrop click, or the close button
- CSS injected once via style tag (STYLE_ID guard, same pattern as MultiSelect)

? buttons wired up in decisions.md
- KPI infobox → /docs/decisions-kpi
- Cumulative chart (wrapped in position:relative div) → /docs/decisions-kpi
- Filter & List section header → /docs/decisions-kpi

Reference page (src/docs/decisions-kpi.md)
- Standalone Observable Framework page at /docs/decisions-kpi
- Documents: KPI card (avg resolve, avg open age, color thresholds),
  Resolution History chart (cumulative, period→resolution mapping, filter
  interaction, timestamp logic), Filter & List (type/status/search, card
  age badge, escalation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 11:48:47 +01:00
parent d056c142df
commit 267e11bc17
3 changed files with 464 additions and 95 deletions

View File

@@ -0,0 +1,115 @@
---
title: Decisions — Reference
---
# Decisions — KPI & Visualization Reference
This page documents the metrics, chart, and list on the **Decisions** dashboard. All data is sourced from the State Hub API and refreshed every 15 seconds.
---
## Decision Health (KPI card)
The card in the top-right corner of the Decisions page shows two live health metrics for the decision process.
### Avg resolve time
The mean time elapsed from decision creation to resolution, computed across the **last five resolved decisions** (or fewer if fewer than five exist). A sample-size note (`n=3`) appears when fewer than five resolved decisions are available.
This is the **baseline** — the expected time for a decision to move from open to resolved. All color thresholds below compare against this value.
### Avg open age
The mean age of all currently **open and escalated** decisions. This uses the full unfiltered dataset (not affected by the type/status/search filters on the page), so it always reflects the real state of the decision backlog.
### Color coding
The **avg open age** value is colored to signal whether the backlog is healthy:
| Color | Meaning |
|---|---|
| **Black** | All open decisions are younger than the avg resolve time — backlog is on track |
| **Orange** | Mean open age is within baseline, but at least one individual decision has been open longer than the avg resolve time — an outlier exists |
| **Red** | Mean open age exceeds the avg resolve time — the whole open backlog is running behind |
Individual decision cards also show an **orange age badge** when that specific open decision has been waiting longer than the avg resolve time.
---
## Resolution History
A cumulative step chart showing how many decisions have accumulated in the filtered set over time.
### What "cumulative" means
The y-axis shows the running total of decisions, not the count per bucket. The line rises at each point where a new decision was added and stays flat otherwise. A steeper slope means higher decision velocity.
### Period selector
The radio buttons above the chart control the time window and the time resolution of the x-axis:
| Period | Window | X-axis buckets |
|---|---|---|
| Day | Today (midnight → now) | Hours |
| Week | Last 7 days | Days |
| Month | Current calendar month | Weeks |
| Quarter | Current calendar quarter | Months |
| YTD | 1 Jan → now | Months |
| Year | Rolling 12 months | Months |
| All | Earliest decision → now | Months |
### Timestamps used
- For **resolved or made** decisions: the decision's `decided_at` timestamp is used (when it was closed).
- For **pending or open** decisions: the `created_at` timestamp is used (when it was raised).
### Filter interaction
The chart reflects whatever is currently selected in the **Type**, **Status**, and **Search** filters. Changing the filter updates the chart immediately. This lets you compare, for example, resolution velocity of pending vs made decisions, or open vs resolved.
Dots on the line mark buckets where at least one decision occurred. Hovering a dot shows the count added (`+N`) and the running total.
---
## Filter & List
### Type filter
- **pending** — decisions that have been raised but not yet resolved; the queue that needs attention
- **made** — decisions that have been resolved or superseded
### Status filter
| Status | Meaning |
|---|---|
| open | Pending decision, awaiting resolution |
| escalated | Requires human sign-off before any action (constitution §4) |
| resolved | Decision has been made and closed |
| superseded | Replaced by a later decision |
### Search
Filters by decision title (case-insensitive substring match).
---
## Card age indicator
Each decision card shows a compact age badge in the header row:
- **`open Xd`** (or `Xh`, `Xw`, `Xmo`) — the decision has been waiting for this long with no resolution
- **`took Xd`** — the time elapsed from creation to resolution (for resolved/superseded decisions)
The age badge turns **orange** when an open decision has been waiting longer than the avg resolve time baseline. This mirrors the orange state of the KPI card but scoped to the individual decision.
---
## Escalation
Decisions with an escalation note are shown with a `⚠ escalated` badge and a highlighted note inline in the card. An escalation warning box at the bottom of the filtered list summarizes all escalated decisions requiring human approval.
Escalated decisions always appear at the top of the list regardless of deadline, per constitution §4.
---
*Data refreshes every 15 seconds. KPI metrics use the full unfiltered dataset; chart and list reflect the active filter.*