An always-present invariant in the TopBar chrome: the live serving triplet
(N correct · N refused · 0 wrong) aggregated across lanes from
/serving/metrics, the wrong count load-bearing — 0 in the verified token,
>0 in the contradicted token. It is a MIRROR, never a hard-coded zero:
renders a non-zero wrong honestly, and an honest 'metrics unavailable' when
the reports can't be read. Links to the Calibration route (the discipline
behind the number).
Tests: aggregate triplet + 0-wrong, non-zero-wrong-honest (not hard-coded),
metrics-unavailable-not-fake-zero. (Adds fetchServingMetrics/useServingMetrics
locally; unioned with B2 on rebase.)
Consumes the B1 readers (#724). The route where you SEE 'the engine earns
the right to guess' (ADR-0175).
- list (failures-first, server-ordered): per class a reliability bar
(Wilson floor vs the PROPOSE/SERVE θ markers — a class earns the right
when its fill crosses the marker), correct/refused/wrong counts (wrong in
the contradicted token), and a verdict pill (earned SERVE / earned
PROPOSE / not yet licensed)
- serving strip: the discipline's RESULT — live correct/refused/wrong per
lane, wrong=0 in the verified token, with source DigestBadges
- detail (Panel + TabBar): Counts / License math / Raw. The License-math
tab shows the honest derivation (measured ≥ θ → licensed) and states
the numbers come from core.reliability_gate, not the workbench
- fail-closed: an empty/absent arena ledger (501 evidence_unavailable)
renders the honest absence card pointing at the practice lane, not an
error
- nav entry (12th) + routeConformance row + Shell nav assertion updated
Token-only (hexScan green); VirtualizedList + j/k; full vitest 398 green.
First Wave M / Phase B piece (GATING): read-only backend that makes the
calibrated-learning / serving-discipline loop inspectable — 'the engine
earns the right to guess', ADR-0175.
The workbench computes NONE of these numbers:
- GET /calibration/classes — per-class gold-tether view from the persisted
practice arena ledger (evals/gsm8k_math/practice/v1/report.json per_class).
Each class's reliability_floor is the engine's own one-sided Wilson
conservative_floor (via ClassTally.reliability); PROPOSE (θ=0.85) / SERVE
(θ=0.99) license verdicts come from core.reliability_gate.license_for.
Failures-first ordering. A test proves the reader's floor equals a direct
conservative_floor() call — no re-implementation.
- GET /serving/metrics — the live correct/refused/wrong counts read unchanged
from the committed train_sample + holdout_dev report.json (currently
4/46/0 and 5/495/0 — wrong=0). Never re-runs a lane.
Honest current state: the committed practice ledger's three classes
(additive/divisive/multiplicative) are all below N_MIN=10, so none has
earned a license yet — the reader shows exactly that, no fake green light.
- workbench/calibration.py: pure readers; imports core.reliability_gate;
EvidenceUnavailableError -> 501 (fail-closed) when the artifact is absent.
- schemas + TS mirrors (CalibrationClass, ServingMetrics); both snapshots
regenerated (deterministic); both drift gates pass.
- trust boundary: read-only over committed artifacts + engine-owned
derivation; no execution, no mutation, no license ever changed.
Verified: 30 Python tests (incl. the no-reimplementation proof + fail-closed),
390 vitest, both schema drift gates, snapshots deterministic.
A teach-everything, indexed docs/workbench/UI-UX-GUIDE.md: thesis + evidence
model, the 11 routes (purpose/evidence/usage/states each), the design system
+ primitives, the full keyboard map, the doctrine gates as honesty proof,
replay-in-depth, glossary. Scoped for a mid-tier model: documentation over
shipped code, accuracy-over-completeness, Markdown-only, ground every claim
in the real components. Dispatch-ready.
scripts/workbench — a single robust entrypoint so a fresh clone runs the
Workbench the FIRST time, not sometimes:
- doctor: fail-loud preflight (uv, node>=20, pnpm via corepack, curl) — each
failure prints the exact fix, never a half-started UI
- setup: idempotent — uv venv + editable CORE install + pnpm frozen install,
only when actually missing; re-runs instant
- up: health-gated start of the stdlib API (:8765 /health) + Vite UI (:5173),
reuses already-healthy ports, invokes vite directly so Ctrl+C tears down
both cleanly (TERM-then-KILL, EXIT trap); logs to /tmp/core-workbench-*.log
- pure-Python backend (numpy) — no Rust build required to run the Workbench
- API_PORT / UI_PORT overridable
Tested end-to-end: up in ~5s (API /health 200, UI 200), clean teardown
frees both ports. README gains a 'CORE Workbench — one command' quick-start
as the most-discoverable visual entry, with the first-time-works guarantees
spelled out for an external evaluator.
Wave M takes the workbench to mastery and closes its biggest design gap:
it surfaces the teaching/ratification loop but is blind to the
calibrated-learning / serving-discipline loop (gold-tether arena, reliability
gate, Wilson floor vs θ ceiling, 'the engine earns the right to guess') and
to cognition itself (pipeline stages, field substrate, identity continuity).
Lens: Anthropic + xAI as target users who'd WANT to use it.
- wave-M-worthiness.md: full plan, Phases A–E, the missing-surfaces table,
the backend-reader-first / never-re-implement-engine-math disciplines,
execution order (B→C→D, A parallel).
- wave-M-phaseB-calibration-briefs: executable Phase B pack grounded in the
real core/reliability_gate shapes (ClassTally / conservative_floor /
license_for / Action θ) and the committed report.json evidence — B1
readers (GATING, Python), B2 Calibration route, B3 wrong=0 global frame,
B4 leeway wiring. Dependency DAG + STOP gates + no-theater rules.
First R3 (Theater) piece. Reworks the stale artifact-keyed ReplayRoute into
the turn-keyed hero over the #716 sealed-replay backend, and fully retires
the dead W-026 artifact-keyed machinery on both sides (the NOT_YET_MIRRORED
comment anticipated this).
The hero makes determinism *felt*: pick a journaled turn, CORE re-executes
its prompt in a sealed fresh runtime, and the result renders as a hash
verdict (≡ equivalent / ≠ diverged) + the original/replay DigestBadges + a
leaf diff (critical weighted above informational, each with a ≠ glyph). The
'What this proves' card surfaces comparison_basis + origin_state and states
the honest limit: a divergence means nondeterminism OR origin-state
influence, never rendered on its own as a determinism failure.
Retirement (verified zero serving uses):
- Python schemas.py: removed ReplayComparison/ReplayDivergence/ReplayStatus/
ReplayDivergenceSeverity; scripts/dump-enums.py drops the two replay enums;
both snapshots regenerated (deterministic: dump == committed)
- TS: removed ReplayComparison/ReplayDivergence/ReplayDivergenceSeverity;
added TurnReplayComparison/TurnReplayDivergence (+ basis/origin/severity
unions); NOT_YET_MIRRORED now empty (every engine schema mirrored)
- badges: removed ReplayStatusBadge + ReplayDivergenceSeverityBadge +
meta/enums + their enumCoverage cases (hero renders severity inline)
- api: fetchReplayComparison/useReplayComparison -> fetchTurnReplay/
useTurnReplay (/replay/<turnId>)
- deleted ArtifactList, ReplayComparisonPanel, ReplayDiffViewer,
ReplayMetadataTable, old replay.test.tsx
- App route /replay/:artifactId? -> /replay/:turnId?; conformance row
turn-keyed (loading 'Loading turns...', empty 'No turns recorded yet.')
Tests: ReplayRoute.test.tsx (equivalence hero + honesty card, diverged
critical leaf, informational-only label, replace-mode select, j/k spine).
Full vitest 358 green; workbench Python 34 green; both snapshots deterministic.
Follow-up flagged (not in this PR to keep it focused): the artifact query
hooks (useArtifacts/useArtifactDetail/fetchArtifacts*) are now orphaned but
entangled with the still-live artifact EvidenceSubject kind — a separate
cleanup once an Artifacts route or that subject's fate is decided.
Brief: docs/handoff/wave-R3-briefs-2026-06-13.md (all four R3 pieces).
Replaces SettingsRoutePlaceholder, completing all six placeholder routes.
- workbenchPrefs.ts: typed localStorage prefs with safe parse + live
same-tab sync (useWorkbenchPrefs). Every pref has a real consumer — no
toggle that does nothing:
* landingRoute -> consumed by the App index redirect (Navigate)
* inspectorDefaultOpen -> consumed by EvidenceProvider initial state
(EvidenceUrlSync still force-opens on a ?inspect= deep link)
- SettingsRoute: two panels. Preferences (landing route select + inspector
default switch, applied on next load, survive reload). Runtime (read-only
/runtime/status: backend, git_revision DigestBadge, engine_state_present,
checkpoint_revision, revision_warning with warning token, active_session_id,
mutation_mode) under the standing statement 'Engine configuration is
CLI-only. This page mutates nothing on the server.'
- no backend change, no new schema/subject, no NOT_YET_MIRRORED change, no
engine mutation of any kind
- bespoke conformance block (Settings has no empty state — the prefs panel
always renders); asserts the loading label + CLI-only statement + the
error contract over the status fetch
- tests: workbenchPrefs (defaults / persist+reload / invalid+malformed
fallback / partial merge) + SettingsRoute (both panels, landing-route
persistence, inspector toggle, error-without-mutation)
DEFERRED (flagged, not shipped as theater): list-density pref — honest
wiring requires threading a density token through every list row, a
separate change; shipping a control that does nothing would violate
ADR-0160 (audit-native, not analytics theater). Token-only styling
(hexScan green); full vitest 363 green.
Replaces VaultRoutePlaceholder with the real route over the R2-B
/vault read substrate (#712).
- TS mirrors VaultSummary/VaultEntry; both removed from NOT_YET_MIRRORED.
Also fixes a latent ErrorCode drift: adds 'evidence_unavailable' to the
TS union (present in Python schemas, missing in TS) — the route branches
on it.
- fail-closed is the design: a missing/unpersisted vault (the 501
evidence_unavailable signal, or persisted=false / entry_count=0) renders
the honest absence card as the PRIMARY state, naming the opt-in
RuntimeConfig.persist_session_state pointer — not a generic error, no
skeleton theater
- with data: summary strip (entry_count, store_count, reproject_interval,
max_entries, source_path) + VirtualizedList of entries with
epistemic_status / epistemic_state pills and versor_digest DigestBadge
- exact-recall doctrine: renders only backend fields; never computes or
displays a similarity/relevance proxy (runtime recall is exact cga_inner)
- selection publishes the vault_entry subject (inspect-param only, via
setSubject + setInspectorOpen; EvidenceUrlSync writes ?inspect=vault:N);
a URL-restored identity-only subject is hydrated once entries load
- Vault row added to routeConformance MOUNT_ROUTES — the fail-closed
absence asserted as the primary contract
- tests: fail-closed card (not error), summary+entries, no-similarity-score
doctrine, vault_entry subject publication, j/k spine
Token-only styling (hexScan green).
Replaces PacksRoutePlaceholder with the real triad route over the R2-B
/packs read substrate (#712).
- TS mirrors PackSource/PackSummary/PackDetail; PackSummary/PackDetail
removed from NOT_YET_MIRRORED (drift gate now enforces them)
- new design primitive TreeView (src/design/components/TreeView): a
deterministic, keyboard-driven JSON tree — object keys sorted, array
indices in order, no animation; ←/→ collapse/expand, ↑/↓ + j/k move,
Home/End jump, Enter toggles; registers its shortcuts only while focused
(KeyboardHelp never advertises tree controls when no tree is on screen)
- list pane: VirtualizedList + useListNavigation (j/k) + SearchInput; rows
show pack_id, source, version, language/modality, determinism_class pill
- detail pane: Panel + TabBar (Manifest / Checksums / Raw); Manifest renders
via TreeView; Checksums is the verify affordance — manifest_digest and
declared checksum as DigestBadges plus the per-field manifest checksums
table (the checksum-hashes-the-bytes-on-disk doctrine made visible); Raw
collapsed by default
- selection publishes the pack subject (R2-S), records /packs/<packId>
(replace), pushRecentItem on visit
- Packs row added to routeConformance MOUNT_ROUTES (loading 'Loading
packs...', error 'No packs mutation occurred.', empty 'No packs
discovered.' + core pack validate <path>)
- tests: TreeView (sorted/collapsed/expand/collapse/focus/click/empty) +
PacksRoute (list, replace-mode select + manifest tree, checksum verify
affordance, j/k spine)
Token-only styling (hexScan green).
Replaces the RunsRoutePlaceholder with the real triad route over the
R2-B /runs read substrate (#712).
- TS mirrors RunSource/RunSummary/RunTurnRef/RunDetail; all three classes
removed from NOT_YET_MIRRORED (drift gate now enforces them)
- list pane: VirtualizedList + useListNavigation (j/k) + SearchInput;
rows show source, session_id, turn_count, relative timestamp, a
checkpoint badge (present + revision vs 'no checkpoint'), and any
evidence_gap rendered honestly in-row (never hidden)
- detail pane: Panel + TabBar (Turns / Manifest / Raw); every turn row
is an anchor to /trace/<turn_id> (backend-provided trace_path) with the
trace_hash as a DigestBadge — the cross-link is the point of this route;
turn list pages via turn_limit ('Load more turns')
- selection publishes the run subject (R2-S) and records /runs/<sessionId>
in the URL (replace), pushRecentItem on visit
- Runs row added to routeConformance MOUNT_ROUTES (loading 'Loading
runs...', error 'No runs mutation occurred.', empty 'No runs recorded
yet.' + core chat)
- RunsRoute.test.tsx: list evidence, in-row gap, replace-mode URL select,
trace cross-link hrefs, manifest tab, j/k keyboard spine
Token-only styling (hexScan green); full vitest 339 green.
The multi-line git commit -m message had body lines at column 1, which
terminated the run: | literal block — GitHub could not load the workflow
file, producing a path-named failure run on EVERY push to every branch
since the file landed. Rewritten as paragraph-style -m flags; triggers
unchanged (workflow_dispatch only, CONTEMPLATION_ENABLED gate intact).
Replaces the W-026 501 stub. Re-executes a journaled prompt in a sealed
fresh runtime (ChatRuntime(no_load_state=True): no checkpoint load, no
checkpoint write, no proposal lineage) and compares the envelope
leaf-by-leaf against the recorded TurnJournalEntry.
Design correction vs the scoping doc (amended in-doc): journaled turns
each ran in a fresh ChatRuntime(), never one continuous session, so
genesis-PREFIX replay would manufacture spurious divergence; shipped
basis is sealed_fresh_runtime_single_turn (O(1)). origin_state:
"unrecorded" — the journal does not record whether the original turn's
runtime loaded a checkpoint, so divergence is reported as nondeterminism
OR origin-state influence, never disambiguated.
- workbench/replay.py: pure comparison + injected executor; every
TurnJournalEntry field classified critical/informational exactly once
(exhaustiveness enforced by test)
- api.py: route wiring under _CHAT_TURN_LOCK; runtime failure -> 500
runtime_unavailable, no comparison may be fabricated
- schemas: additive TurnReplayComparison/TurnReplayDivergence (W-026
artifact-keyed pair retires with the frontend Replay Moment PR)
- tests: 10 obligations incl. tamper-prompt, tamper-leaf precision,
no-execution-no-comparison, no-trace (journal + engine_state bytes),
wall-clock tolerance, sealed-construction proof
- snapshot regenerated; NOT_YET_MIRRORED debt entries for the two new
classes (mirrors land with the frontend PR)
- api-contract-v1.md § Replay rewritten for the turn-keyed shape
Decides sealed genesis-prefix replay semantics against the actual
constraints (single rolling post-turn checkpoint; journal appended only
by the workbench handler, so history completeness is unprovable today).
Response carries comparison_basis + history_complete so the UI never
oversells; typed refusals; five MEANINGFULLY-FAILS proof obligations.
Reconciles a stale local edit with the upstream roadmap: the deductive
entailment authority demo (PR #700) moves under Demonstrated with its
evidence caveat, and the merged-boundary count is corrected to five
(#687, #688, #690, #696, #700). Next proposed target: Embodied Authority
Simulation Demo.
- EvidenceChainRail: the spine's seven stages rendered per subject with
the honesty contract — lit/hollow/dim derive ONLY from carried fields
(a trace hash lights 'replay' as RECORDED, never as verified); pure
deriveStages() with meaningfully-fail tests (remove one field -> exactly
its stage hollows).
- Hash display standard: DigestBadge default 12-char + copy everywhere;
CopyableHash consolidated away (2 call sites swapped, file deleted).
- Typography: tabular-nums on MetadataTable values + eval metrics;
text-wrap balance on Panel titles + EmptyState statements.
- Selection unification: new --color-selected-bg/-border tokens; selected
(persistent) vs focused (transient) now visually distinct across
Proposals/Replay/Evals lists; focus-ring no longer doubles as selection.
- EmptyState gains a deterministic monochrome inline-SVG glyph.
- Panel adopted in Evals lane list + Proposals queue.
- Doctrine-as-tests: hexScan (no palette literals outside tokens.css/
generated tokens.ts) + schemaDrift gate (scripts/dump-schemas.py AST
walk -> schema-snapshot.json -> every dataclass field mirrored in
types/api.ts; explicit shrink-only NOT_YET_MIRRORED debt list).
The drift gate caught real drift on first run: ChatTurnResult.turn_id
existed in Python, missing from TS — now mirrored.
Verified: build green; vitest 36 files / 279 tests EXIT=0; playwright
12/12; dump-schemas.py runs clean.
Routes now publish selection as the evidence subject and read selection
from path params (R0c), so the ADR-0162 conformance harness mounts them
the way App.tsx declares them.
URL = subject: one codec (evidenceAddress.ts) owns the address grammar for
every EvidenceSubject kind, including kinds whose routes are placeholders.
urlToSubject is a total inverse — malformed input yields null, never throws.
- Route params: /trace/:turnId?, /proposals/:proposalId?, /evals/:laneId?,
/replay/:artifactId? (placeholders keep flat paths)
- ?inspect= carries inspector subject + open state; EvidenceUrlSync restores
deep links and write-through syncs with replace (selection churn never
pollutes history); malformed values are dropped from the URL
- Proposals/Evals/Replay restore selection from their param on load, write it
on selection change (replace), and publish the selected subject to the
evidence context (identity at once, detail when the query resolves)
- EvidenceSubject.data now optional; inspectors render an honest
'detail not loaded' state for identity-only subjects
- Cmd+Shift+C copies origin + subjectToUrl(subject); no-op without subject;
input-focus guard; transient inline 'Copied' on the inspector header
- Fix pre-existing unbounded re-render loop in RightInspector.test.tsx
(render-phase setSubject); subjects now set from effects