Commit graph

73 commits

Author SHA1 Message Date
Shay
8d1eb8af5d Lane 5: UI Trace Updates for Geometric Invariants 2026-07-04 15:12:48 -07:00
Shay
29ca5524d0
feat(workbench-ui): add Apple UMA report card route (#912)
* feat(workbench-ui): add Apple UMA report card route

* feat(workbench-ui): register Apple UMA route

* feat(workbench-ui): expose Apple UMA route path

* feat(workbench-ui): wire Apple UMA report card into route registry

* test(workbench-ui): fix UI and keyboard tests for Apple UMA route integration
2026-06-24 15:33:42 -07:00
Shay
27341dc4ae
feat(workbench-ui): wire Trace practice evidence tab (#902) 2026-06-24 12:10:21 -07:00
Shay
d3df22e24a
feat(workbench-ui): add Trace practice evidence panel scaffold (#901) 2026-06-23 23:45:48 -07:00
Shay
ff1ef10bd7
feat(workbench-ui): expand Trace construction evidence inspection
Expand the Trace Construction panel from a summary scaffold into a read-only evidence inspection surface.

Adds detail sections for construction proposals, mentions, mention bindings, bound relations, contract assessments, and source-span exactness rows. Preserves the proposal/contract authority boundary: proposals remain diagnostic and contract assessments determine runnable/blocker disposition.

Validation: workbench-ui, smoke, and lane-shas GitHub Actions passed on PR head d20d143b5744d15d73d07a515b466143af6a2d52.
2026-06-23 15:03:38 -07:00
Shay
a19acac320
test(workbench-ui): lock trace construction tab wiring (#897) 2026-06-23 14:25:09 -07:00
Shay
56512aa070
feat(workbench-ui): add Trace construction panel scaffold (#894)
* feat(workbench-ui): add construction evidence panel model

* test(workbench-ui): cover construction evidence panel model

* feat(workbench-ui): add construction evidence panel component

* fix(workbench-ui): address construction panel review nits

* fix(workbench-ui): type injected construction fetcher test
2026-06-23 14:08:54 -07:00
Shay
d7a809e82a
feat(workbench): wire construction evidence into Trace route (#895) 2026-06-23 13:28:17 -07:00
Shay
4c23aa4b00
feat(workbench): prepare construction evidence endpoint seam (#893)
* feat(workbench): add construction endpoint handler seam

* test(workbench): cover construction endpoint handler seam

* feat(workbench-ui): add construction evidence endpoint helpers

* test(workbench-ui): cover construction endpoint helpers
2026-06-23 10:11:21 -07:00
Shay
2c8258fe1a
feat(workbench): add UI catch-up evidence scaffolding (#891)
* feat(workbench): add construction evidence read model scaffolding

* feat(workbench-ui): add construction evidence TS types

* feat(workbench): add construction evidence journal projector

* test(workbench): cover construction evidence read model

* feat(workbench-ui): add construction evidence view helpers

* test(workbench-ui): cover construction evidence view helpers

* feat(workbench): add generalization audit evidence scaffolding

* test(workbench): cover generalization audit evidence view

* feat(workbench-ui): add generalization evidence TS types

* feat(workbench-ui): add generalization evidence view helpers

* test(workbench-ui): cover generalization evidence helpers

* feat(workbench): add proposal artifact authority scaffolding

* test(workbench): cover proposal artifact authority rules

* feat(workbench-ui): add proposal artifact TS types

* feat(workbench-ui): add proposal artifact view helpers

* test(workbench-ui): cover proposal artifact view helpers

* feat(workbench): add demo narrative evidence scaffolding

* test(workbench): cover demo narrative scaffolding

* feat(workbench-ui): add demo narrative TS types

* feat(workbench-ui): add demo narrative view helpers

* test(workbench-ui): cover demo narrative view helpers

* fix(evals): resolve discovery_candidates.jsonl via EngineStateStore
2026-06-23 10:09:45 -07:00
Shay
172afc2d9e
docs(workbench): align UI catch-up plan and route docs (#890)
* docs(workbench): refresh UI route inventory

* docs(workbench): add master UI catch-up plan

* docs(workbench): add UI guide catch-up addendum

* docs(workbench): add construction read model implementation brief

* docs(workbench): add trace construction tab implementation brief

* docs(workbench): add generalization audit UI brief

* docs(workbench): add proposal artifact and demo theater brief

* docs: remove trailing whitespaces
2026-06-23 10:02:17 -07:00
Shay
69febc6c0e
feat(workbench): reconcile capability mastery surfaces (#826)
* feat(workbench): reconcile capability mastery surfaces onto main

Reconcile draft PR 821 onto current origin/main after PR 824 without
porting stale queries/types deletions or fake live API wiring.

- Add Experience Flywheel panel with honest empty state and CLI guidance
- Add Capability Paradigm panel with documented gate ladder A2e–A2q
- Integrate CapabilityMasterySection into EvalsRoute landing and lane view
- Preserve ADR-0160/0162 evidence-first posture; no mutation endpoints
- Add capability-mastery-implementation-plan and panel tests

Invariant protected: wrong_total == 0 serving honesty — documented
24/26/0 from lookbacks, never fabricated as live workbench metrics.

* fix(workbench): keep eval landing guidance above mastery panels

* fix(workbench): document capability milestones through sprint12

* fix(workbench): render capability ladder through sprint12

* test(workbench): assert sprint12 capability milestones

* docs(workbench): update capability mastery plan through sprint12

* fix(workbench): make flywheel empty-state command runnable

* test(workbench): expect runnable flywheel command

* docs(workbench): use runnable flywheel command
2026-06-18 15:40:01 -07:00
Shay
71eed1b73d
workbench(vault): exact-CGA recall evidence for persisted entries (#766)
Close the deferred Vault item 4: a read-only endpoint proving a selected
vault entry is recallable by CORE's actual exact CGA machinery, surfaced
in the entry inspector.

Backend (read-only, cold-persisted only):
- GET /vault/entries/{index}/recall rehydrates the persisted VaultStore
  (VaultStore.from_dict — bit-exact versors, no reprojection) and runs the
  real VaultStore.recall using the entry's own stored versor as the query.
  Exact cga_inner scan — never ANN / cosine / approximate.
- recall's +inf exact-self-match sentinel never crosses the boundary: the
  genuine finite cga_inner is reported plus an exact_self_match flag. The
  raw versor never leaves the engine — only content-addressed digests.
- Trust boundary: caller-controlled index -> 404 (out of range / non-int);
  absent persisted snapshot -> 501. The file is never written; the live
  runtime is never touched; recall is deterministic over persisted bytes.

Frontend:
- "Exact CGA Recall" inspector panel, collapsed by default so the read is
  opt-in (the query hook only mounts on expand). Copy says "exact CGA
  recall" / cga_inner — never similarity / relevance / score / ANN /
  cosine. Honestly surfaces that a byte-identical self-match is promoted
  ahead of metric ranking (CGA null-vector self inner-product ~0).

INV-24: register workbench/readers.py in VAULT_RECALL_SITES as
EVIDENCE_TELEMETRY (operator inspection evidence, not claim-shaping), and
tighten the recall-site detector to recognise VaultStore.from_dict factory
bindings so the obligation is real rather than silently bypassed.

Tests: backend 501/404/self-recall/determinism/no-mutation/JSON-safety +
API status codes; frontend collapsed-doctrine + expanded self-recall
evidence. Full workbench suite (192) + architectural invariants (61) +
vault-touching vitest (70) all green.
2026-06-15 02:28:37 -07:00
Shay
b1708a76d5
workbench(vault): give the evidence rail an honest vault-entry progression (#764)
Stop the rail reading as a wall of 'not applicable to vault entries':

- each dim stage now carries a specific honest reason (intent: a stored
  field has no originating user intent; authority: vault recall is
  read-only; action: no emission)
- replay lights on the recorded versor_digest exactly as a turn lights
  on its trace_hash — a content-addressable fingerprint, NOT a verified
  replay claim (honesty contract sanctioned)
- provenance/admissibility derivations enriched (versor_digest + metadata;
  epistemic_state / epistemic_status)

Fixed 7-stage spine and honesty contract preserved; labels unchanged.
Strengthened the meaningfully-fail test to cover replay + dim stages.
2026-06-15 01:49:54 -07:00
Shay
3e8f40b685
workbench(vault): filter entries by status, metadata text, and facets (#763)
Make a populated vault navigable beyond opaque digests:

- status facet: 'all' + the distinct epistemic_status values present in
  the loaded entries (derived, never a hardcoded closed set — the status
  vocabulary is engine-owned)
- text search now reaches metadata keys/values, not just the epistemic
  labels + index
- boolean facets: 'Has proposition' (propositional_form) and 'Has
  promotion digest' (promotion_certificate_digest); dropped 'has replay
  hash' — no such field exists
- filter-empty stays filter-empty (not persistence guidance)

No new endpoint; filters operate on already-loaded entries.
2026-06-15 01:38:09 -07:00
Shay
74dc7c7a3e
workbench(vault): deepen vault entry inspector + raw metadata drawer (#762)
Surface a selected vault entry's real evidence instead of just
epistemic_state + a digest:

- widen VaultEntrySubjectData to carry epistemic_status + the full
  metadata dict (data already reaches the inspector at runtime; this is
  a type-only unlock, no new fetch/endpoint)
- inspector shows epistemic_status and epistemic_state distinctly, core
  identity rows (turn, role) with honest 'not recorded' when absent,
  present-only rows (corrected, energy_*, promotion_certificate_digest),
  a propositional_form headline when present, copyable vault:<index> and
  versor_digest handles, and a collapsible key-sorted raw metadata drawer
- curated rows key off fields that actually exist on vault entries; the
  raw drawer is the catch-all as the open metadata schema grows

Exact-recall doctrine preserved: no similarity/relevance/score text.
2026-06-15 01:29:12 -07:00
Shay
4522e5b1cf
workbench(vault): frame empty and unavailable vault states honestly (#760) 2026-06-15 01:05:50 -07:00
Shay
18e25580f3 feat(l10): always-on daemon/CLI — the process that runs the continuous-life heartbeat
The L10 heartbeat loop (run_continuous) had no process to drive it; `core always-on`
is that process — the T-experience spine made runnable. It ticks idle_tick on a wall-clock
cadence so the engine LIVES and LEARNS with no user turn, persists lived_life.json (the
workbench Lived Life surface) + the checkpoint, and resumes the SAME life on restart.

- chat/always_on.py: run_continuous gains unbounded operation (heartbeats=None, runs until
  stop) + an interruptible inter-beat wait (_sleep_until_stop) so shutdown latency is one
  slice, not the cadence interval. Persists the run's identity pack ids (resume-verdict
  faithfulness). on_heartbeat is now best-effort (a broken log pipe can't kill the life).
- chat/always_on_daemon.py (new): the daemon shell — a single-instance OS lock (fcntl.flock:
  kernel-held, atomic, auto-released on death — no stale window, no PID-reuse, no half-written
  race), SIGINT/SIGTERM -> graceful stop (handlers saved/restored), the continuous-life config
  FORCED on, ephemeral (--no-load-state) writes no durable artifact. Foreground + explicit:
  no hidden background execution (CLAUDE.md); only writes the engine-state dir it was given.
- core/cli.py: `core always-on [--interval --max-beats --no-load-state --quiet]` with per-beat
  + summary logging; validates --interval; reports IdentityContinuityError / IncompatibleEngine
  StateError (the "different life / newer build" cases) as clean refusals, not tracebacks.
- workbench/readers.py: ENGINE_STATE_ROOT now honors CORE_ENGINE_STATE_DIR (= the daemon's
  resolved dir), so the workbench can't be split-brained (reading REPO_ROOT/engine_state while
  the daemon writes elsewhere); the Lived Life resume verdict recomputes from the persisted
  pack config, not a default config (no false substrate_changed for a non-default-pack life).
- Lived Life absence state now points at the real `core always-on` command (loop closed).

Adversarial 4-lens review (lock/concurrency, signals/shutdown, invariants/trust-boundary,
test-vacuity/CLI) caught 16 findings; this fixes all real ones — the HIGH lock races (two
daemons over one life), the env split-brain, the IO-kill, the uncaught identity/schema errors,
the unvalidated interval, the ephemeral-artifact shadow, and the resume-verdict pack-id bug —
and closes the two test-coverage gaps it flagged (real SIGTERM path + config-forcing-at-the-
runtime boundary).

Tests (non-vacuous): 11 daemon (flock live-holder refusal, leftover-lock reclaim, unbounded+
stop, interruptible sleep, forced-config-at-boundary, no-load-state guard, REAL SIGTERM
subprocess) + the reader pack-id discrimination test (fails under the old default-config bug).
245 workbench+invariants+always-on Python green; frontend tsc + vitest green; `core always-on`
verified end-to-end (bounded, real SIGTERM graceful stop, interval rejection).

engine_state/always_on.lock is runtime state (gitignored, ADR-0146 pattern).
2026-06-14 17:33:37 -07:00
Shay
0cb01ee3f1
Merge pull request #751 from AssetOverflow/feat/workbench-health-footer
feat(workbench): wire /health liveness probe into the status footer
2026-06-14 17:23:57 -07:00
Shay
0bdc2eef6d feat(workbench): wire /health liveness probe into the status footer
The /health endpoint was the only W-026 API route with no UI consumer.
Surface it as a liveness indicator (colored dot + label) in the status
footer, isolated from /runtime/status so a live server still reads
"Healthy" even when runtime status is degraded.

- types: HealthStatus matching the server's {"status":"ok"} payload
- client: fetchHealth() with a short 3s timeout for fast failure
- queries: useHealth() polling every 15s, retry disabled
- footer: HealthIndicator rendered in both normal and degraded branches;
  any non-ok status fails safe to "Unhealthy"
- tests: healthy / errored / non-ok / checking / survives-runtime-failure
2026-06-14 17:16:43 -07:00
Shay
de2d5da4f3
feat(workbench): extend TruncatedCell to trace edges and selection rails (#750)
Follow-up to #749, which deliberately scoped TruncatedCell to the
non-virtualized columnar tables and left trace edges + single-column
selection rails as-is. Wire it into those too so every truncated data
cell in the workbench has the same full-content reveal (popover +
copy + modal-for-long).

Component:
- Add `align` prop ("start" | "end"). `end` hugs the right edge and
  right-justifies the display, for right-aligned columns like the trace
  `to_stage` cell. Defaults to "start" (unchanged).

Wiring:
- Trace propagation edges: from_stage / to_stage (to_stage align=end).
- Trace pipeline stage rail: stage label + summary.
- Trace turns rail: prompt + surface excerpts.
- Runs rail: session_id. Replay rail: prompt excerpt. Packs rail:
  pack_id. CORE-Logos pack rail: pack_id. Logos alignment rail: edge
  (rich source→target display, plain-text value for copy/reveal).
- Contemplation run rail: run_id; stage-evidence ids.
- Demos rail: title; scenario trace hash.
- Proposal detail: replay-equivalence hash, evidence hashes;
  proposal chain provenance.

Two row elements that were real <button>s (trace stage rail,
contemplation run row) are converted to <div role="button"> with an
Enter/Space onKeyDown handler — the codebase's established selectable-row
pattern (ProposalTable, RowShell) — so nesting TruncatedCell's button
trigger is valid HTML rather than a button-in-button.

Intentionally left as-is (documented):
- RunsRoute TurnRefRow is an <a>/<Link> row; nesting an interactive
  trigger inside an anchor is invalid HTML. The surface excerpt is
  reachable by following the link.
- Digests everywhere keep DigestBadge (already copy + full-value title).
- Section headings (e.g. the trace stage-detail <h3>) are not data cells.

Evidence: workbench-ui `pnpm build` (tsc -b) green; full vitest suite
535 passed / 60 files, incl. a new align assertion on TruncatedCell.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 17:11:47 -07:00
Shay
99a52746ae
Merge pull request #748 from AssetOverflow/codex/lived-life-surface
feat(workbench): Lived Life surface — the always-on heartbeat made felt
2026-06-14 16:55:54 -07:00
Shay
9b3c291d22
feat(workbench): full-content reveal for truncated table cells (#749)
Workbench grid tables truncate dense cells (proposal ids, source kinds,
case ids/reasons, lexicon/morphology rows, artifact paths) with `...`,
leaving the full value unreachable except via a native title tooltip.

Add a reusable `TruncatedCell` (design/components): keeps the compact
display, attaches one hover/focus-revealed trigger that opens an
accessible Radix popover with the complete value (selectable, scrollable)
plus one-click copy, and — for long/structured values — an "Open full
view" button into a dynamic Radix Dialog modal. One component delivers
both the lightweight reveal and the interactive modal.

The reveal trigger calls stopPropagation, so it never steals a row's
click/select behaviour — revealing a value and selecting the row stay
independent. Digests keep `DigestBadge` (already copy + full-value title).

Wired into the non-virtualized + contents grid tables: Proposal queue
(id, source), eval wrong=0 case ledger (case id, reason), CORE-Logos
lexicon/glosses/morphology rows, and proposal artifact paths. Trace
propagation edges (short, right-aligned stage names) and single-column
selection rails / detail cards keep current behaviour.

Evidence: workbench-ui `pnpm build` (tsc -b) green; full vitest suite
525 passed / 59 files, including 5 new TruncatedCell tests (display +
title, popover reveal + copy, modal-only-for-long, no row-click bubble).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 16:53:01 -07:00
Shay
7ead395eeb feat(workbench): Lived Life surface — the always-on heartbeat made felt (read-only, persist-first)
The L10 heartbeat (chat/always_on, #747) holds CORE alive over uptime but had no
surface. This adds the read-only Lived Life route that renders the continuous-life
evidence: the heartbeat over uptime + the resume-as-same-life verdict — both halves
of "one continuous life" on one surface.

Persist-first, never recompute engine-owned values:
- chat/always_on: serialize_report + write_lived_life persist a run deterministically
  (sorted keys) to engine_state/lived_life.json; run_continuous gains an opt-in
  report_path so a real continuous-life run leaves its evidence where the workbench
  reads it. closure_ceiling is persisted so the artifact is self-describing.
- workbench/lived_life.py: projection + a fail-closed validate() gate — the wrong=0
  analogue for the continuity surface: closure_held/closure_observed/totals/converged
  are each re-checked against the per-beat measurements, and resume_status is re-checked
  against identity-vs-current-substrate, so a tampered artifact RAISES rather than
  rendering a false claim (a beat lying about a breached ceiling, an inflated closure,
  a miscounted total, a falsely-claimed resume).
- workbench/readers.lived_life(): reads the artifact, computes the resume verdict from
  the persisted identity vs the canonical engine_identity_for_config (fail-soft ->
  "unknown", like IdentityContinuity). Honest absence when no run has been persisted.
- GET /lived-life + LivedLife/LivedLifeHeartbeat schemas (snapshot regenerated; the
  schema-drift gate proves every field is mirrored in src/types/api.ts).

The resume verdict made felt: would_resume / substrate_changed / unknown IS the L11
reboot guarantee (a reboot recomputes identity and refuses if it differs) — so the
surface shows this life wakes up as ITSELF, not a copy. The per-reboot lineage chain
stays owned by Runs > Identity (honest cross-link).

Frontend: /lived-life route (Evidence section, route count 15 -> 16). Renders the
headline (heartbeats, closure-held-by-construction, learned-while-idle, at-rest, resume
pill), the summary, the heartbeat timeline (closure flat below the ceiling — read, never
repaired), and the resume verdict. Honest absence + ADR-0162 route conformance
(loading/error/empty), fail-closed like Vault/Calibration.

Tests (non-vacuous): 12 backend (every tamper case raises; resume tracks identity vs
substrate; run_continuous(report_path) round-trips a readable+valid artifact) + 4
frontend render tests (recorded life renders; a breached beat shows the warning, never a
false "held"; a changed substrate shows would-refuse, never a false resume; absent shows
honest absence). All workbench Python (167) + affected vitest (167) + tsc + vite build
green; architectural invariants green.

engine_state/lived_life.json is runtime state (gitignored, ADR-0146 pattern).
2026-06-14 16:45:03 -07:00
Shay
5def106401 fix(logos): declare the full collapse-anchor set so cross-language alignment resolves + show real manifest
A1 (substrate fix, not UI): en_collapse_anchors_v1 declared only love/peace/justice,
but the logos packs reference covenant_love/shalom/tzedek + heart/soul/breath/holy/time.
Declare all 8 with their real ADR-0073 provenance (source-concept names where they
exist) and recompute the lexicon checksum. Now every cross_lang.no_english_collapse
edge resolves to a real declared entry — grc_logos_cognition_v1 and he_core_cognition_v1
go from 7 invalid targets to 0 (verdict warning -> unknown; never CLEAR while holonomy
proof is absent). The geometry resolves; the check is NOT suppressed (the LG-1
relation/prefix carve-out stays removed). Test updated to assert real resolution;
invalid-detection branch still covered by the ghost-target fixture.

A2: Identity tab shows the real pack manifest (now fetched via /contents) instead of
an overview projection — the actual passport, data already present.

NOTE (curation follow-up): love (Greek agape collapse) and covenant_love (Hebrew chesed
collapse) may be intentionally distinct per-language anchors or duplicates of one
concept — left both declared rather than gamble on consolidating curated theology.

Backend 25 + frontend 520 tests pass; tsc + build clean.
2026-06-14 14:38:00 -07:00
Shay
8303c3c51e fix(workbench): DAG natural-height fit for dense graphs + consistent click-to-copy feedback
Two UX wrinkles surfaced while exercising the CORE-Logos Studio:

- DAG viewport: tall, few-layer graphs (e.g. the 408x1890, 2-layer/55-node
  alignment fan) were squished by viewBox-meet into an unreadable sliver. Render
  at natural height (scale ~1) inside a bounded, scrollable box; small graphs are
  unaffected (>= the caller height). Golden layout unchanged (layoutDag untouched).
- Click-to-copy: new shared useCopyToClipboard hook gives every copy affordance a
  tooltip + transient confirmation. StatusFooter SHA now confirms 'Copied' (was a
  silent copy that read as 'does nothing'); 'Read Only' is labeled a non-interactive
  status (not a toggle); checkpoint-revision gains an explanatory tooltip.
  DigestBadge + MetadataTable copy buttons route through the hook + gain titles.

Full workbench-ui vitest: 520 passed (+4), clean exit; tsc + build clean.
2026-06-14 13:31:43 -07:00
Shay
5474a15205 feat(workbench): CORE-Logos Studio LG-4 — Alignment tab + holonomy-absent guard
The trilingual resonance centerpiece, read-only over GET /logos/packs/{id}/alignment:
- deterministic DagViewer (he -> grc -> en longest-path) + selectable edge list;
  alignmentToDag is a pure projection pinned by a golden-file layout test
- invalid alignment targets surfaced honestly (the undeclared en-collapse-*
  anchors render a warning, never smoothed over)
- logos_alignment_edge evidence subject (logos_alignment_edge:<packId>/<edgeId>)
  with RightInspector projection + EvidenceChainRail derivation
- holonomy stays absent: no tab, no proof card, no success element (guard test)

Full workbench-ui vitest: 516 passed, clean exit; build clean.
2026-06-14 12:59:35 -07:00
Shay
bcba7cba1e feat(workbench): CORE-Logos Studio LG-3 — Lexicon / Glosses / Morphology contents tabs
Read-only contents tabs over GET /logos/packs/{id}/contents:
- Lexicon (VirtualizedList + SearchInput + status/domain filters; dangling-link
  flag cross-referenced from the safety report, never recomputed)
- Glosses (linked entry ids) and Morphology (operator chain rendered in schema
  order — root/prefix/stem/suffix never re-sorted)
- three pack-scoped evidence subjects (logos_entry/gloss/morphology) with
  logos_*:<packId>/<subId> address grammar, RightInspector projections, and
  EvidenceChainRail derivations
- contents fetched eagerly on pack-select; /alignment stays deferred to LG-4

Full workbench-ui vitest: 506 passed, clean exit; build clean.
2026-06-14 12:51:08 -07:00
Shay
5ac6dbe3c5 fix(workbench): sync route-count assertions + UI/UX guide for /logos (15 routes)
Registering /logos bumped the registry to 15 routes. Update the stale
hardcoded counts and the registry-driven guide doc:
- Shell.test.tsx: LeftNav 14 -> 15 + CORE-Logos in section-grouped order
- CommandPalette.keyboard.test.tsx: palette nav items 14 -> 15
- docs/workbench/UI-UX-GUIDE.md: route count 15 + Substrate CORE-Logos row

Full workbench-ui vitest suite: 494 passed, exits clean.
2026-06-14 12:20:11 -07:00
Shay
af0b4f707b feat(workbench): CORE-Logos Studio LG-2 — /logos route shell + Overview/Identity/Safety
Read-only /logos frontend route (Wave M CORE-Logos read-only wave, LG-2):
- route registered via WORKBENCH_ROUTES + lazy ROUTE_ELEMENTS (Substrate section)
- Overview / Identity / Safety tabs over live /logos/packs, /{id}, /safety only
  (no /contents or /alignment — those are LG-3 / LG-4)
- 10 Logos* TS interfaces mirrored; NOT_YET_MIRRORED shrunk back to empty
- SafetyVerdict UI badge + dump-enums.py source + enum-snapshot + coverage test
- logos_pack evidence subject (logos:<pack_id>) + round-trip
- bottom strip "proposal mode: none — read-only"; holonomy rendered as
  missing_evidence (no tab, no proof card); invalid alignment targets surfaced
  honestly in Safety; verdict never mapped to "clear" for warning/unknown

Depends on LG-1 (#737). No mutation endpoints, no engine math in the UI.
2026-06-14 12:12:47 -07:00
Shay
c5b30f68e4 feat(workbench): add read-only core-logos readers 2026-06-14 11:43:39 -07:00
Shay
a791b23008 docs(workbench): refresh READMEs to shipped reality (index + surfaces)
The workbench READMEs were frozen in the W-026..W-031 planning era. Bring them
current after the Wave 1 / R / M arc:

- docs/workbench/README.md (index): add the 5 unindexed docs (wave-1-evidence-
  spine, wave-R-mastery-revamp, wave-M-worthiness, b4-leeway-producer-scope,
  design-system); replace the false "Current Status" (which still pointed at the
  superseded feat/w026 prototype) with the shipped state + a 14-route surface
  table; mark the W-026..W-031 queue delivered; note Wave M complete (B+C+D+B4),
  Phase E + parallel tracks remaining.
- workbench-ui/README.md: fix the stale one-line surface list and the "src/routes
  placeholder components" description (routes are registry-driven in src/app/;
  routes.ts is the single source). Left the dump-api-schemas.py reference intact
  (it exists, distinct from dump-schemas.py).
- README.md (top level): the workbench section said "eleven routes" — now
  fourteen, naming Tour, Contemplation, and Calibration and the per-turn
  pipeline/field/leeway/bundle evidence.

Docs-only; no code or gate touched. UI-UX-GUIDE (the routes.docs.test-gated
route table) is unchanged and already at 14.
2026-06-13 20:37:29 -07:00
Shay
7cf78d97e0 feat(workbench): Wave M D1+D2 — guided determinism tour (provider-agnostic)
The "they'd want to use it" first-run surface: a curated narrative that makes
the engine's discipline legible to a newcomer — bring a claim from any model and
watch it get decided, refused, or replayed. Proposer authority ignored.

Honest by construction (the risk with a narrative surface is theater):
  - workbench/tour.py determinism_tour() is a curated ordered narrative BOUND to
    the real demo registry. Intro (provider-agnostic thesis) → three demo steps
    (deductive entailment decides only on engine+oracle agreement; epistemic
    truth-state refuses a wrong proposer; proof-carrying promotion ignores
    proposer authority) → payoff (replay-to-same-hash + the citable evidence
    bundle).
  - Each demo step's what_this_proves / what_this_does_not_prove cards and the
    demo title are PULLED FROM THE REAL DEMO SPEC — never re-authored — so the
    tour can never claim more than the demo it points at.
  - A step referencing a missing demo FAILS CLOSED (KeyError), not a dead link.
    Tests assert both (cards == spec; phantom demo raises).

Backend: schemas.py DeterminismTour/TourStep; GET /tour. schema-snapshot regen.
Frontend: /tour route registered in the registry (Determinism section, 14
routes; nav/palette/guide counts updated); TourRoute — thesis hero + ordered
step cards with the honesty cards + links to the real demos / replay.

Validation: 140 workbench Python tests incl. tour drift guards; 472/472 frontend
incl. routes/routeConformance/routes.docs (guide↔registry), Shell+palette counts
(14), schemaDrift, and the tour UI test; pnpm build clean; git diff --check
clean. No serving-path imports.
2026-06-13 19:39:41 -07:00
Shay
5061a0804b feat(workbench): Wave M D3 — shareable evidence bundles (reproducibility as a deliverable)
The "they'd want to use it" deliverable: a turn's evidence exported as ONE
deterministic, content-addressed, citable artifact — composing the Phase-C
evidence (pipeline + field) with the trace and the calibration leeway verdict.

Backend (read-only, no engine execution):
  - schemas.py: EvidenceBundle.
  - workbench/evidence_bundle.py: build_evidence_bundle(entry) assembles a turn
    journal entry into the bundle and computes bundle_digest. The digest
    content-addresses the DETERMINISTIC cognitive evidence only — journal
    position + wall-clock (turn_id, journal_digest, replay_reproducer,
    generated_from) are carried for provenance but EXCLUDED, so the same turn
    content reproduces the same digest regardless of journal position.
  - api.py: GET /trace/{turn_id}/bundle. schema-snapshot.json regenerated.

The bundle carries a replay *reproducer* command (how to verify) rather than a
live-run replay, so the artifact itself stays deterministic — verification is
the consumer's step: re-run the prompt sealed, confirm trace_hash, recompute the
bundle, check the digest.

Frontend:
  - types/api.ts EvidenceBundle; client/query hook; Trace route **Bundle** tab —
    citable digest, "what this proves / does not prove" honesty note, the
    reproducer, and a deterministic JSON download (Blob anchor, leak-safe).

Validation: 135 workbench Python tests incl. non-vacuous bundle guards (digest
reproducible, journal-position/wall-clock excluded, any evidence change flips
the digest, missing Phase-C evidence honest); 468/468 frontend incl. schemaDrift
+ the citable-download bundle test; pnpm build clean; git diff --check clean. No
serving-path imports.
2026-06-13 17:26:26 -07:00
Shay
f68b395620 feat(workbench): Wave M C2-b — contemplation as a legible staged process
C2-a surfaced contemplation runs but rendered each scene as a flat JSON dump —
outputs, not process. C2-b makes the loop legible: every scene is now a typed
stage in the canonical ADR-0172 arc.

Reader-first (no theater):
  - schemas.py: ContemplationScene gains a typed loop projection — stage_role
    (cold_attempt | engine_enrichment | engine_proposal | operator_ratifies |
    grounded | other) plus the connective ids (proposal_id, candidate_id,
    proposal_state, grounding_source). New ContemplationStageRole Literal.
  - readers.py: _contemplation_scenes derives stage_role from the scene id
    (closed set, "other" fallback) and pulls the connective ids out of the raw
    detail. schema-snapshot.json regenerated.

UI:
  - ContemplationRoute: the run detail now renders the arc as a staged process —
    "attempt → enrich → propose → ratify → grounded" with named stage roles,
    cold→grounded bookends (surfaces pulled out of before/after), the connective
    ids as evidence, and the raw detail tucked into a collapsible (not lost).

Honest wrinkle (surfaced, not faked): the fixture proposals do NOT resolve in
the live proposal log (source_kinds exemplar_corpus/operator, none
contemplation), so the proposal id is shown as evidence but is intentionally
NOT a clickable cross-route link — a dead link would be theater. Live
Proposals/Calibration navigation is deferred to reader-verified linking once
real contemplation proposals reach the log.

Validation: 128 workbench Python tests + new reader-projection tests (canonical
arc → roles, unknown → "other", id extraction, detail preserved); 466/466
frontend incl. schemaDrift + the staged-process / no-dead-link test; pnpm build
clean; git diff --check clean. No serving-path imports.
2026-06-13 16:58:26 -07:00
Shay
53ff9359a8 feat(workbench): Wave M C3 field substrate — persist-first field evidence
Makes the CL(4,1) field geometry legible, honestly. The engine owns the field;
this surfaces ONLY the exact scalar invariants it computes — never the raw
multivector — so the workbench shows "this is the geometry, it's exact, it
can't fake coherence" without a decorative blob or any motion.

Persist-first (the C3 gating work was Python, not React): the honest scalars
were computed live per turn but discarded. Now captured per turn into the
journal so a read-only surface has real evidence.

Backend:
  - workbench/field_evidence.py: FieldEvidence computed from the engine result —
    exact versor_condition, field_valid (vs the 1e-6 ceiling), a content-
    addressed field_digest (sha256 of the engine-canonical array bytes), and
    cga_inner(before, after) as the exact transition value. Raw field bytes
    never cross the boundary: only floats + digests. validate() is fail-closed —
    field_valid can never disagree with versor_condition vs the ceiling (the
    wrong=0 analogue for the geometry). No engine math re-implemented
    (versor_condition / cga_inner imported from algebra; bytes via array_codec).
  - workbench/schemas.py: FieldEvidence dataclass; field_evidence on
    ChatTurnResult + TurnJournalEntrySchema. schema-snapshot.json regenerated.
  - workbench/journal.py + api.py: persisted at from_chat_turn; first-class read
    endpoint GET /trace/{turn_id}/field (trace facet, consistent with /pipeline).
  - workbench/replay.py: field_evidence classified CRITICAL — replay now also
    proves field determinism (digest + scalars must match on re-execution).

Frontend:
  - types/api.ts FieldEvidence + field_evidence passthrough; client/query hook;
    FieldInvariantCard (measured value vs ceiling, cga_inner transition, digests;
    honest missing_evidence; no blob, no motion); Trace route Field tab.

Honest-empty for pre-widening journal rows (missing_evidence). Deferred:
cross-turn field-coherence trends, session-level field persistence.

Validation: 138 workbench/practice Python tests (incl. non-vacuous field guards
+ replay field-determinism); 465/465 frontend incl. schemaDrift; pnpm build
clean; git diff --check clean. No generate.derivation / reliability_gate /
stream / field.propagate / vault.store imports.
2026-06-13 16:26:46 -07:00
Shay
4cba6f488c feat(workbench): Wave M Phase C legibility — pipeline record, contemplation, identity continuity
Lands the Phase C "make cognition legible" slice plus Phase A residue, all
backend-reader-first over real engine data (no theater, read-only doctrine
intact, zero serving-path imports).

C1-a — Cognitive pipeline record (persistence-first, per #729 worthiness edit):
  - workbench/pipeline_record.py: curated CognitivePipelineRecord over the real
    CognitiveTurnResult (input → intent → proposition_graph → articulation_target
    → realizer → walk_telemetry → trace_hash). Raw field multivectors are
    DELIBERATELY excluded; _assert_no_raw_field_payload recursively rejects raw
    field keys, and validate_pipeline_record fails closed on missing/duplicate
    stages, non-recorded status, or dangling edges — the UI can never receive a
    partial record that claims to be complete.
  - test_workbench_pipeline_record.py: non-vacuous guards — missing stage,
    monkeypatched new required stage, and injected raw {"F": [...]} each raise.

C2-a — Contemplation as a process: /contemplation route over real persisted
  contemplation/runs/*.json (glob reader; honest-empty when absent).

C4-a — Identity continuity (L10/L11): RunDetail.identity_continuity + Runs
  Identity tab, sourced from the real core.engine_identity (engine_identity /
  parent_engine_identity lineage relation, re-derived to verify).

Demo Theater: renders backend-owned proof-promotion + entailment DAGs.

Phase A residue: density preference wired end-to-end (settings → shell → tokens);
  cross-route consistency touch-ups.

Infra: local API CORS now echoes only validated 127.0.0.1/localhost origins
  (hostname-checked, not arbitrary reflection) so Vite fallback ports work.
  Route chunk-split keeps the build warning-free.

Cleanup: corrected the stale ADR-0175 practice-lane assertions (build_report is
  6 correct / 0 wrong / 44 refused after the current serving lane; wrong=0 held)
  and the two registry-derived count tests (LeftNav + CommandPalette 12 → 13 for
  the new Contemplation route).

Docs: runtime_contracts.md (pipeline-record contract), UI-UX-GUIDE,
  api-contract-v1, data-shapes-v1, wave-M-worthiness, phase-a-residue-ledger.

Validation: 106 workbench/practice Python tests green (incl. wrong=0 lane +
  pipeline-record fail-closed guards); 459/459 frontend; pnpm build clean;
  git diff --check clean. No generate.derivation / reliability_gate / stream /
  field.propagate / vault.store imports.
2026-06-13 15:44:31 -07:00
Shay
bdb294eac3 feat(workbench): land B3.5-b/c/d/e — calibration evidence subject, B4a leeway gate, docs; runner-reproducible practice artifact
Completes the Wave M B3.5 consolidation slice (b–e), built on #728.

B3.5-b — calibration as a first-class evidence subject (`calibration_class`,
address `calibration:<class_name>`): RightInspector projection + Evidence
Chain Rail semantics (serving-discipline evidence, not runtime truth).

B3.5-c / B4a — nullable `LeewayEvidence` read model threaded through turn,
replay, cognition-proposal, and math-proposal surfaces, with a shared
absence-honest card. B4 is gated correctly: the tuple exists in typed data but
no producer populates it, so the card renders absence (verified: no non-null
producer in workbench/core/chat).

B3.5-d/e — UI-UX-GUIDE.md, b4-leeway-feasibility-gate.md, phase-a-residue-ledger.md.

Practice artifact — earn-it-for-real (runner-reproducible). The committed
`report.json` (additive earns PROPOSE @0.861, 95/5/50) is now emitted by a
deterministic runner rather than copied from the queue. `propose_runner`
gains `regenerate_practice_artifacts()`, which runs ONE sealed `resolve_pooled`
practice pass and writes BOTH report.json (the per-class ledger the calibration
reader consumes) and ratification_queue.json — two projections of one ledger,
coherent by construction and byte-reproducible. `runner.main()` delegates to
it (lazy import, no cycle), so both entry points produce the identical pair.
This closes the gap where a hand-copied report.json agreed with the queue but
no runner produced it. `resolve_pooled` is the aggressive sealed PROPOSE-regime
scorer (proposal-only/HITL, unsafe for serving, legitimate for
attempt-and-eliminate); wrong=5 is the sealed-practice learning signal, NOT the
serving wrong=0. No serving/derivation/reliability_gate source touched; the
practice lane is not in the serving-frozen SHA gate.

Validated:
- python -m pytest tests/test_workbench_{calibration,journal,replay,schemas}.py -> 31 passed
- python -m pytest tests/ -k "workbench or propose or learning_arena or practice"
  -> 190 passed (3 failing tests in test_adr_0175_phase2_practice_lane.py are
  PRE-EXISTING reds on clean origin/main: stale 4/0/46 assertions on build_report,
  which this change does not touch)
- report.json + ratification_queue.json: deterministic (run1==run2) and
  reproduced byte-identically by both `python -m ...runner` and `...propose_runner`
- pnpm build green; 144 UI tests across calibration/leeway/evidence/replay/
  doctrine-gates/routes-docs-drift all pass
2026-06-13 07:36:44 -07:00
Shay
494edeee90 feat(workbench): unify route truth into one registry (Wave M B3.5-a)
Adds `workbench-ui/src/app/routes.ts` as the single source of truth for
navigation routes. App, LeftNav, the command palette, ⌘-digit shortcuts,
and the landing-route preference now all derive from `WORKBENCH_ROUTES`.

Fixes the live palette-drift bug: the command palette's hand-maintained
NAV_COMMANDS listed 10 routes and silently dropped Demos and Calibration,
so they were unreachable via ⌘K. The landing-route tuple was likewise
missing Replay and Calibration. Deriving every list from one registry
makes that drift structurally impossible.

- routes.ts carries a `section` field for grouped wayfinding nav
  (Converse · Cognition · Determinism · Evidence · Discipline ·
  Substrate · Settings) — a display skin only; one workbench, one
  address space, one Evidence Chain Rail.
- App is data-driven via ROUTE_ELEMENTS (route id → element); a registry
  route without an element fails routes.test rather than rendering undefined.
- Honest keyboard model: ten routes pin ⌘1–0; Demos and Calibration are
  palette-only (no chord advertised).
- routes.test.tsx guards the contract: element-map parity, unique
  ids/paths/digits, landing-route coverage (Replay + Calibration), and
  palette reachability of every command-visible route.

Verified: pnpm build green; routes/Shell/CommandPalette/routeConformance/
prefs/Settings + hexScan/schemaDrift/enumCoverage suites all pass (108 tests).
2026-06-13 04:43:28 -07:00
Shay
c84127adf8 feat(workbench): wrong=0 as a felt global presence (Wave M B3)
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.)
2026-06-13 01:12:24 -07:00
Shay
138f95a2b0 feat(workbench): Calibration route — the gold-tether arena made visible (Wave M B2)
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.
2026-06-13 01:00:16 -07:00
Shay
1fe56e9b6f feat(workbench): calibration + serving-metrics readers — the gold-tether loop, visible (Wave M B1)
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.
2026-06-13 00:38:16 -07:00
Shay
fd0d7f1f6a finish wave r3 ui and trace integrity 2026-06-12 23:25:24 -07:00
Shay
4d8aa1dac9 feat(workbench): the Replay Moment — turn-keyed hero + retire W-026 artifact replay (Wave R3)
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).
2026-06-12 22:07:34 -07:00
Shay
0ff3e3b2c8 feat(workbench): Settings route — wired prefs + read-only runtime status (Wave R2, final route)
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.
2026-06-12 21:39:41 -07:00
Shay
ebb95a0541 feat(workbench): Vault route — fail-closed epistemic memory evidence (Wave R2)
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).
2026-06-12 21:29:18 -07:00
Shay
cfcd7dc9ec feat(workbench): Packs route + TreeView primitive — manifest & checksum evidence (Wave R2)
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).
2026-06-12 21:14:13 -07:00
Shay
2b13feab24 feat(workbench): Runs route — session evidence with trace cross-links (Wave R2)
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.
2026-06-12 20:58:55 -07:00
Shay
597c1bdb7d
Merge pull request #716 from AssetOverflow/feat/wb-r3-replay-backend
feat(workbench): sealed single-turn replay backend — GET /replay/{turn_id} (Wave R3)
2026-06-12 17:39:20 -07:00
Shay
80e02ce7de feat(workbench): sealed single-turn replay backend — GET /replay/{turn_id} (Wave R3)
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
2026-06-12 17:15:39 -07:00