# METRICS — the quantitative memory (schema + generation contract)

> **This is a generic template.** It hard-codes no project values; bindings come from `CLAUDE.md` (see
> `SPECIALIZE.md`). Governing law: `CONSTITUTION.md §10` — the memory trio (INSIGHTS / LESSONS / PROGRESS)
> plus this file's event stream form the **quartet**: qualitative memory says *what we learned*; METRICS says
> *what actually happens*, so prompt refinement (`PROMPT_TEMPLATES.md §I`) is ranked by evidence, not anecdote.
>
> **Companions:** `tools/Show-Metrics.ps1` (the reader: Pareto, retry leaderboard, duration medians) ·
> `tools/Metrics.Tests.ps1` + `tools/metrics.fixture.jsonl` (self-tests) · `progress.ps1 -Stats` (shortcut).

## Generation contract — how Claude fills this in

- **Single-writer rule (Law 3):** ONLY the orchestrator appends metrics lines — at integration points, from
  data it already holds (the persisted agent reports, its own timestamps, and — when the session ledger is
  wired (`RUN_STATE.<session>.json`, see `SESSION_SETUP.md`) — `stageTimes`). **No agent ever writes
  metrics**; an agent cannot inflate its own numbers.
- **Sharded, never monolithic:** one JSONL file per run under `docs/metrics/` — the shard name is the run id
  when a RUN_STATE exists, else `<kind>-<id>-<yyyyMMdd>` (e.g. `wave-3.jsonl`, `sweep-WF-INV-02-20260705.jsonl`).
  Non-run events (e.g. `housekeep`) go to `adhoc-<yyyy-MM>.jsonl`. Sharding means two concurrent orchestrator
  sessions can never tear one file. Readers glob the directory; humans never hand-read these files.
- **Append-only.** A wrong line is corrected by a subsequent line, never edited (same discipline as audit).
- **v1 event set is FROZEN until three waves of real data exist** — resist adding fields before the Pareto has
  told you what you actually need.
- **Durations:** derive `durMin` from RUN_STATE `stageTimes` at closure when available (bracket stages with
  `node .claude/hooks/session-ledger.js stage <name> start|end`); on a checkout without the session ledger,
  in-session wall-clock best-effort is acceptable and expected.

## Event schema (v1) — one JSON object per line, `"v":1` on every line

| `evt` | When appended | Required fields beyond `v,t,evt` |
|---|---|---|
| `sweep` | Sweep closes (workflow integrated) | `id` (WF id), `wave` (int or null), `durMin{enrich,build,gates,review,integrate}`, `gates{name:"pass"\|"fail"\|"fail>pass"}`, `retries{agent:n}`, `parked` (bool), `screens`, `affordances{wired,marked,gaps}`, `contractsAppended`, `migrationDestructive` |
| `wave` | Wave closes | `id` (wave-N), `sweeps` (int), `parked` (int), `folds` (int), `capstone` ("pass"\|"fail>pass") |
| `gate` | A gate FAILS outside a sweep line's scope (standalone re-run, fold gate) | `id`, `gate`, `result` ("fail"\|"fail>pass") |
| `retry` | Reserved (v1: retries live in the sweep line; do not double-count) | `id`, `agent` |
| `park` | A sweep is parked | `id`, `stage`, `inboxRef` |
| `flake` | A test failed then passed on immediate re-run (see the flake-ledger practice) | `id`, `test` |
| `housekeep` | `/housekeep --apply` completes | `scope`, `reaped`, `dirs`, `screenshots` |
| `design-gate` | Reserved for B2 (consistency-assertion / lint fails at birth) | `id`, `check`, `result` |
| `kit-verify` | `/kit-verify` completes (appended by the orchestrator, never the tool) | `kitVersion`, `ok`, `modified`, `conflict`, `stale`, `override` |

`"fail>pass"` = failed, then passed within the capped retry — the raw material of the failure Pareto.

**Canonical `sweep` line:**
```json
{"v":1,"t":"2026-07-05T12:00:00Z","evt":"sweep","id":"WF-<X>-NN","wave":3,
 "durMin":{"enrich":18,"build":74,"gates":22,"review":9,"integrate":11},
 "gates":{"xunit":"pass","contract":"pass","visual":"fail>pass","a11y":"pass","preflight":"pass","interaction":"pass"},
 "retries":{"module-wirer":1},"parked":false,
 "screens":6,"affordances":{"wired":41,"marked":3,"gaps":0},
 "contractsAppended":2,"migrationDestructive":false}
```

## The governance loop this powers

- **Ranked prompt refinement:** `Show-Metrics -Pareto` orders gate failures by frequency — the top of that list
  IS the prompt/skill-improvement backlog (`PROMPT_TEMPLATES.md §I`, now evidence-ranked).
- **Law 12 quantitative graduation trigger** (threshold binds from `CLAUDE.md`; default): *an owning agent with
  more than 40% of all retries across 3 consecutive waves → file a LESSONS row citing the metric, and its skill
  gains a trap entry.*
- **Checkpoint 2 digest line:** each wave's C2 digest includes one comparative line ("this wave vs last:
  median build −12%, visual-gate fails 3→1") — read by the human, produced by `Show-Metrics`.

## Reading it

```powershell
powershell -NoProfile -File .claude/tools/Show-Metrics.ps1                 # summary + Pareto + leaderboard
powershell -NoProfile -File .claude/tools/Show-Metrics.ps1 -Pareto        # gate-failure Pareto only
powershell -NoProfile -File .claude/tools/Show-Metrics.ps1 -ByAgent       # retry leaderboard only
powershell -NoProfile -File .claude/tools/progress.ps1 -Stats             # shortcut to the same reader
```
