The wave-* planning docs record their wave, not current state. Add a
consistent "Historical record — superseded" banner to each, pointing to
README (Current Status), UI-UX-GUIDE, and the route registry as the live
sources. wave-1/R/M-worthiness/M-consolidation covered.
Docs only.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Bring the four living workbench docs up to date with what actually
shipped, and document the TruncatedCell full-content reveal.
- README: route count 14 -> 16; add Lived Life (Evidence) and CORE-Logos
(Substrate) to the shipped-surfaces table; full Trace tab list; add the
TruncatedCell reveal to cross-cutting; link the visual-evidence handoff;
bump status date.
- UI-UX-GUIDE: §12 now reflects the built read-only /logos reader vs the
unbuilt Studio; §13 moves the cognitive-pipeline visualizer, field/
versor_condition reader, and identity-continuity items from "absent" to
"shipped"; new §14 documents the truncated-cell reveal pattern + the
<a>/<Link> non-nesting boundary; bump date.
- ui-component-map: add TruncatedCell to shared data viewers.
- design-system: add the Truncated Cell Reveal shared-component note.
Docs only; no code change.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Add a handoff brief with five screenshots captured by driving the real
vite-preview build with Playwright (mocked API), confirming the
full-content reveal works across the originally reported proposal queue
table, the trace propagation edges, and the trace selection rails — with
the row staying unselected on reveal (stopPropagation holds).
Verification only; no code change. Records the harness gotcha that a
role-by-name query resolves to the row, not the icon trigger.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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).
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
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>
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>
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).
The 'one continuous life' telos had three built pieces (turn loop, Shape B+ resume,
idle_tick learning) but no process holding the engine alive+learning over uptime. This
adds that heartbeat loop: chat/always_on.run_continuous ticks idle_tick on a cadence so
the engine LIVES and LEARNS even when no one is talking to it, READS (never repairs) the
closure invariant as evidence each beat, and persists so the life survives interruption
and resumes as the SAME life.
Proven by 3 falsifiable soak tests (non-vacuous): lives (closure observed + held, real
field excited, ~7x under the 1e-6 ceiling); learns while idle (Step-D consolidation
DERIVES and STORES member(socrates,mortal) during idle — absent before the heartbeat,
present after); converges (saturated life stops churning); survives interruption as the
SAME life (strict identity guard enforces it on reboot + the consolidated STORED record
survives, not mere re-derivation); never repairs (field byte-identical after the run).
Safety by composition, no new authority: idle_tick stays proposal-only (HITL untouched)
+ sound proof-gated SPECULATIVE session-memory consolidation; closure owned by
algebra/versor.py (heartbeat only reads versor_condition — no hot-path repair).
Adversarial 3-reviewer panel: no-hot-path-repair PASS, wrong=0 PASS; the panel's
proof-quality findings are fixed — removed the tautological identity_continuous claim
(engine identity is config-derived, invariant by construction), reframed the resume test
to prove ACCUMULATED learning survived (stored record, not re-derivation) under the strict
identity guard, surfaced final_checkpoint_ok (no silent swallow), and softened the
docstring (this is the heartbeat LOOP a daemon runs; the daemon shell is a follow-up).
Scope: the reusable loop ships; a production daemon (CLI entry, real cadence, signals)
is a thin follow-up. Purely additive (no existing file touched).
First phase of the domain-general compositional reading layer (the comprehension
coverage wall is composition — docs/analysis/comprehension-coverage-wall-map-2026-06-14.md).
M1 is a pure PARITY refactor on the flagship logic path, no new capability:
- new generate/composition/ package: LogicChainPlan (plan.py) + lower_logic_chain
(lower_logic.py), the is-a chain lowering extracted BYTE-IDENTICALLY from
determine.py::_verify_subsumption.
- _verify_subsumption now builds a plan -> lowers it -> routes through the UNCHANGED
evaluate_entailment gate. The composer proposes structure; the sound ROBDD gate
remains the sole wrong=0 firewall.
- only the logic instantiation ships; no math lowering, no join-op vocabulary
(defer-substrate-vocab-commitment — the chain discriminates on its relational
predicate, an explicit join-op field lands when a second op dispatches on it).
Verification: byte-identical lowering (3-reviewer adversarial panel: byte-parity PASS
char-for-char, wrong=0 PASS — the instance-of-fallacy refusal mutation-proven
load-bearing); 5 new non-vacuous lowering tests; 28 determine/transitive/consolidation
+ 163-test broad sweep (incl. gsm8k serving + ADR-0218) green; cognition eval 100%.
Evidence-based map of the comprehension coverage wall (the C decision). GSM8K
diagnostic: 4/0/46, no single barrier >10%, ~24 fragmented primary barriers with
heavy multi-barrier co-occurrence (compound+comparative+fraction+coreference stack
on the same cases). Capability lanes are narrow curated-gold conformance
(combined-rate: 6 solvable shapes, 19/19 oracle). Single-shape recognizers are
proven metric-inert (4th confirmation). Diagnosis: shape-recognizers don't COMPOSE
within compound statements / across coreference. Leverage: Tier 1 recognizer
additions ~+5 cases then cap; Tier 2 compositional reading is the only real lever
(architectural, must stay wrong=0). Recommendation: don't add isolated recognizers;
design a compositional reader.
The only genuine epistemic lever (per the finding). Scopes the ADR-0218 path: it
is the inductive step (coherent premises + verified proof -> coherent conclusion),
fail-closed and sound, but needs a curator-certified COHERENT base that nothing
mints today (bootstrapping). Wiring buys an honesty/disclosure upgrade (verified
for proven propositional conclusions), NOT a learning fix. wrong=0 risk shifts
entirely to the curator-certified base. Three options framed (wire narrowly /
record curator-mediated-by-design / defer) with recommendation.
7-agent architecture audit + adversarial verification refutes the intuition that
all-speculative packs cap the model's learning. The reasoning/learning loop is
blind to epistemic_status (recall_realized ignores it; speculative facts chain to
deductive-closure fixed point). Lexicon-status promotion is compile-and-display-only
(runtime epistemic state comes from grounding_source, not the lexical row). The
verified/as_told distinction is honesty-disclosure-only and intentional. All three
coherence-promoters are dormant (proof-carrying demo-only, energy-policy default-off,
review never sets coherent). Conclusion: do NOT promote-to-coherent for learning
(cosmetic at best, false-verified wrong=0 hazard for facts); the only genuine lever
is wiring the sound, fail-closed proof-carrying path — a separate deliberate decision.
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.
Measuring the holonomy tri-language resonance (intended for a Studio proof-card)
showed it is NOT a robust proof: the engine's own holonomy_similarity (CGA inner
product) anti-correlates, and the Euclidean 'aligned closer than misaligned'
claim passes only via averaging in the close Hebrew distance + one cherry-picked
negative (1.3% margin) — the aligned Greek clause is itself farther than the
negative, and the verdict flips ±20-55% under other negatives. Decoration, not
proof (CLAUDE.md, Schema-Defined Proof Obligations).
- docs/analysis/holonomy-resonance-proof-not-robust-2026-06-14.md: the rigorous
finding (numbers), why a Holonomy proof tab cannot be built honestly yet
(stays missing_evidence), and bounded research questions.
- Downgrade the two clause-resonance decoration tests to honest tripwires that
assert the true state and fail (pointing to the doc) if the resonance becomes
real. Token-pair cga_inner tests left intact + flagged as a separate, un-audited
claim.
70 holonomy-adjacent tests pass.
- New docs/workbench/EVALUATOR.md: a falsifiable 10-minute guided path for an
external technical evaluator (tour -> replay hash -> wrong=0 ledger ->
calibration arena -> logos geometry), an honest-scope section (verified
flagship = propositional entailment; GSM8K diagnostic; field = coherence-gate
not reasoner; holonomy = roadmap), and a 'verify, don't trust' section. Every
reference points at a real file/surface (checked).
- README: 'fourteen' -> 'fifteen' routes + add CORE-Logos (LG-2/3/4 drift fix);
point new evaluators at EVALUATOR.md.
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.
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.
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.
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.
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.
Clears the long-standing B4 block: the leeway decision was already made on the
serving path (chat/runtime.py::_surface_estimate has a real LicenseDecision +
the ReachPolicy) and then DISCARDED — never threaded to the result, and the
workbench can't import reliability_gate. This wires it through.
Producer (observational, never authorizing):
- core/cognition/leeway.py: LeewayRecord + build_leeway_record(reach_level,
license_decision) — duck-typed on the decision, zero new cross-package
coupling. Maps to: no decision -> "unknown" (STRICT, no latitude); denied
-> "blocked" (gate consulted, said no); licensed SERVE/PROPOSE widening ->
the real class / theta / "[approximate]" disclosure. "verified" is never
emitted (RESERVED state). source_digest content-addresses the decision
(deterministic, no wall-clock).
- core/cognition/result.py: additive `leeway: LeewayRecord | None = None` on
CognitiveTurnResult.
- core/cognition/pipeline.py: build it at result construction from the data
the runtime ALREADY exposes (response.reach_level +
runtime.last_turn_accrual().license). chat/runtime.py is UNTOUCHED.
- workbench/api.py: _leeway_evidence_from_result maps result.leeway ->
LeewayEvidence (pure projection; no reliability_gate import — firewall
intact). The journal already persists it; the B4a UI (Replay / Proposals /
RightInspector) already renders it — no frontend or schema change needed.
Safety (this touches the serving path, so proven, not asserted):
- trace_hash is a NAMED-field hash (core/cognition/trace.py); `leeway` is not
in it -> byte-identical serving. All provenance/trace tests pass.
- response_governance STRICT stays byte-identical (375 governance/serving/
provenance tests green, incl. the live-wiring + estimation-lane + ADR-0206
seam tests).
- core eval cognition: 13 cases, 100% intent / groundedness / versor closure.
- replay determinism holds (leeway is in CRITICAL_FIELDS; deterministic).
Tests: engine (build_leeway_record: strict/blocked/SERVE/PROPOSE, no "verified",
deterministic digest) + workbench mapping (field-for-field, honest absence,
invalid-enum clamp) + integration (a real turn now carries an honest leeway
record, not the null "No evidence recorded"). 151 workbench/leeway Python + 68
frontend (leeway/replay/proposals/schemaDrift) green; schema-snapshot unchanged.
Docs: gate cleared (b4-leeway-feasibility-gate.md), residue ledger flipped to
implemented, scope brief is b4-leeway-producer-scope-2026-06-13.md.
The leeway decision already exists at chat/runtime.py::_surface_estimate
(accrual.license is a real LicenseDecision) but is discarded — never threaded to
CognitiveTurnResult, and the workbench can't import reliability_gate. Brief lays
out: the exact producer seam, the LicenseDecision/ReachPolicy -> LeewayEvidence
mapping, two honest layers (STRICT-now / earned-APPROXIMATE), the firewall-safe
workbench mapping, constraints, a minimal additive Layer-1 first PR, and 4 open
questions.
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.