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.
This commit is contained in:
Shay 2026-06-13 19:39:41 -07:00
parent 376f564b96
commit 7cf78d97e0
17 changed files with 580 additions and 7 deletions

View file

@ -59,13 +59,14 @@ successful proof.
## 4. Current Route Map
The route registry in `workbench-ui/src/app/routes.ts` is the source of truth.
Current route count: 13.
Current route count: 14.
| Section | Route | Path | Shortcut | Purpose |
|---|---|---|---|---|
| Converse | Chat | `/chat` | `⌘1` | Execute a normal CORE turn and journal evidence. |
| Cognition | Trace | `/trace` | `⌘2` | Inspect turn surfaces, grounding, verdicts, and trace hashes. |
| Cognition | Contemplation | `/contemplation` | Palette | Inspect persisted contemplation process traces. |
| Determinism | Tour | `/tour` | Palette | Guided determinism tour: a curated narrative over the real demos with "what this proves / does not prove" honesty cards. |
| Determinism | Replay | `/replay` | `⌘3` | Re-execute journaled turns in a sealed fresh runtime and compare envelopes. |
| Determinism | Demos | `/demos` | Palette | Run registered determinism demos. |
| Evidence | Proposals | `/proposals` | `⌘4` | Review cognition and math proposal evidence. |

View file

@ -226,6 +226,38 @@ entry, no engine execution. Endpoint: `GET /trace/{turn_id}/bundle`. The Trace
route's **Bundle** tab shows the citable digest, a "what this proves / does not
prove" honesty note, the reproducer, and a deterministic JSON download.
## DeterminismTour (D1/D2 guided tour)
```ts
export type TourStepKind = "intro" | "demo" | "payoff";
export type TourStep = {
step_id: string;
order: number;
kind: TourStepKind;
headline: string; // authored narrative
narrative: string; // authored framing
demo_id: string | null; // a real registered demo
demo_title: string | null; // pulled from the demo spec
what_this_proves: string | null; // pulled from the demo spec
what_this_does_not_prove: string | null;// pulled from the demo spec
route_hint: string | null; // where to go deeper
};
export type DeterminismTour = {
schema_version: "determinism_tour_v1";
title: string;
thesis: string; // the provider-agnostic pitch
steps: TourStep[];
};
```
The first-run, provider-agnostic narrative. Authored headlines/narrative frame
the story, but every demo step is **bound to a real demo**: the honesty cards
(`what_this_proves` / `what_this_does_not_prove`) and `demo_title` are pulled
from the demo spec, never re-authored, and a step referencing a missing demo
fails closed. Read-only. Endpoint: `GET /tour`. Surfaced as the `/tour` route
(Determinism section) — thesis hero + ordered step cards with the honesty cards
and links to the real demos / replay.
---
# Proposal

View file

@ -210,6 +210,19 @@ Detailed brief pack: `docs/handoff/wave-M-phaseB-calibration-briefs-2026-06-13.m
your own model's claim; watch the deterministic engine decide, refuse, and
replay it." The Tool-Authority / Hybrid-Verification demos already embody
this; make it the tour's spine.
**D1+D2 implementation note (2026-06-13):** BUILT as the first-class `/tour`
route. `workbench/tour.py::determinism_tour()` is a curated, ordered narrative
bound to the **real** demo registry: intro (the provider-agnostic thesis) →
three demo steps (deductive entailment decides; epistemic truth-state refuses
a wrong proposer; proof-carrying promotion ignores proposer authority) →
payoff (replay-to-the-same-hash + the citable evidence bundle). **Honesty by
construction:** each demo step's `what_this_proves` / `what_this_does_not_prove`
cards are pulled from the real demo spec (never re-authored), and a step that
references a missing demo **fails closed** (`KeyError`) rather than becoming a
dead link — a test asserts both. The spine is the three substrate-capability
demos that exist today (the named Tool-Authority/Hybrid demos are not in the
registry); the thesis carries the bring-your-model framing. Read endpoint
`GET /tour`; route registered in the registry (Determinism section, 14 routes).
- **Shareable evidence bundles** — deterministic export of a turn + its
trace + replay + calibration verdict as a single citable artifact.
Reproducibility *as a deliverable*.

View file

@ -0,0 +1,56 @@
"""D1/D2 guided determinism tour — honesty + drift guards.
The tour is authored narrative, so the load-bearing guarantee is that it cannot
drift from the real demos: every demo step binds to a registered demo, the
honesty cards come from the demo spec (never re-authored), and a phantom demo id
fails closed rather than becoming a dead link.
"""
from __future__ import annotations
import pytest
from workbench.readers import DEMO_SPECS
from workbench.tour import _build_tour, determinism_tour
def test_every_demo_step_binds_to_a_registered_demo() -> None:
tour = determinism_tour()
demo_ids = [step.demo_id for step in tour.steps if step.demo_id is not None]
assert demo_ids, "tour should reference at least one real demo"
for demo_id in demo_ids:
assert demo_id in DEMO_SPECS
def test_honesty_cards_come_from_the_spec_not_re_authored() -> None:
# If a tour step re-worded what a demo proves, this fails — the tour can
# never claim more (or less) than the demo it points at.
for step in determinism_tour().steps:
if step.demo_id is None:
continue
spec = DEMO_SPECS[step.demo_id]
assert step.what_this_proves == spec.what_this_proves
assert step.what_this_does_not_prove == spec.what_this_does_not_prove
assert step.demo_title == spec.title
def test_non_demo_steps_carry_no_demo_claims() -> None:
for step in determinism_tour().steps:
if step.kind == "demo":
continue
assert step.demo_id is None
assert step.what_this_proves is None
assert step.what_this_does_not_prove is None
def test_phantom_demo_fails_closed() -> None:
with pytest.raises(KeyError, match="unknown demo"):
_build_tour((("x", "demo", "h", "n", "no_such_demo", "/x"),))
def test_steps_are_ordered_and_thesis_is_present() -> None:
tour = determinism_tour()
assert tour.schema_version == "determinism_tour_v1"
assert [step.order for step in tour.steps] == list(range(len(tour.steps)))
# D2 provider-agnostic framing is present and explicit.
assert "proposing model" in tour.thesis.lower() or "any model" in tour.thesis.lower()

View file

@ -166,6 +166,12 @@
"read_only",
"scenarios"
],
"DeterminismTour": [
"schema_version",
"title",
"thesis",
"steps"
],
"EvalLaneSummary": [
"lane",
"versions",
@ -347,6 +353,18 @@
"source_path",
"source_digest"
],
"TourStep": [
"step_id",
"order",
"kind",
"headline",
"narrative",
"demo_id",
"demo_title",
"what_this_proves",
"what_this_does_not_prove",
"route_hint"
],
"TurnJournalEntrySchema": [
"turn_id",
"timestamp",

View file

@ -24,6 +24,7 @@ import type {
CognitivePipelineRecord,
FieldEvidence,
EvidenceBundle,
DeterminismTour,
TurnJournalEntry,
TurnJournalSummary,
ContemplationRunDetail,
@ -200,6 +201,10 @@ export async function fetchTraceBundle(turnId: number): Promise<EvidenceBundle>
);
}
export async function fetchTour(): Promise<DeterminismTour> {
return apiFetch<DeterminismTour>("/tour");
}
export async function fetchAuditEvents(
limit?: number,
offset?: number,

View file

@ -28,6 +28,7 @@ import {
fetchTracePipeline,
fetchTraceField,
fetchTraceBundle,
fetchTour,
fetchTraceTurns,
fetchContemplationRun,
fetchContemplationRuns,
@ -59,6 +60,7 @@ import type {
CognitivePipelineRecord,
FieldEvidence,
EvidenceBundle,
DeterminismTour,
TurnJournalEntry,
TurnJournalSummary,
EvalLaneSummary,
@ -234,6 +236,15 @@ export function useTraceBundle(turnId?: number | null) {
});
}
export function useTour() {
return useQuery<DeterminismTour, WorkbenchApiError>({
queryKey: ["api", "tour"],
queryFn: fetchTour,
staleTime: 60_000,
refetchOnWindowFocus: false,
});
}
export function useAuditEvents(limit?: number, offset?: number) {
return useQuery<{ items: AuditEvent[] }, WorkbenchApiError>({
queryKey: ["api", "audit", "events", limit ?? null, offset ?? null],

View file

@ -21,6 +21,9 @@ const ContemplationRoute = lazy(() =>
const ReplayRoute = lazy(() =>
import("./replay/ReplayRoute").then((module) => ({ default: module.ReplayRoute })),
);
const TourRoute = lazy(() =>
import("./tour/TourRoute").then((module) => ({ default: module.TourRoute })),
);
const DemoTheaterRoute = lazy(() =>
import("./demos/DemoTheaterRoute").then((module) => ({
default: module.DemoTheaterRoute,
@ -76,6 +79,7 @@ export const ROUTE_ELEMENTS: RouteElementMap = {
chat: lazyRoute(<ChatRoute />),
trace: lazyRoute(<TraceRoute />),
contemplation: lazyRoute(<ContemplationRoute />),
tour: lazyRoute(<TourRoute />),
replay: lazyRoute(<ReplayRoute />),
demos: lazyRoute(<DemoTheaterRoute />),
proposals: lazyRoute(<ProposalsRoute />),

View file

@ -85,11 +85,11 @@ describe("Shell", () => {
expect(document.querySelector('[data-density="compact"]')).toBeInTheDocument();
});
it("LeftNav has exactly 13 items in section-grouped order", () => {
it("LeftNav has exactly 14 items in section-grouped order", () => {
renderShell();
const nav = document.querySelector('[data-region="leftnav"]')!;
const links = nav.querySelectorAll("a");
expect(links).toHaveLength(13);
expect(links).toHaveLength(14);
const labels = Array.from(links).map((l) => l.textContent);
// Grouped by section (Converse → Cognition → Determinism → Evidence →
// Discipline → Substrate → Settings), derived from the route registry.
@ -97,6 +97,7 @@ describe("Shell", () => {
"Chat",
"Trace",
"Contemplation",
"Tour",
"Replay",
"Demos",
"Proposals",

View file

@ -105,6 +105,19 @@ export const WORKBENCH_ROUTES: readonly WorkbenchRoute[] = [
keyboardDigit: null,
routeConformanceRequired: true,
},
{
id: "tour",
path: "/tour",
routePattern: "tour",
label: "Tour",
description: "Guided determinism tour over the real demos.",
section: "Determinism",
leftNavVisible: true,
commandPaletteVisible: true,
landingRouteAllowed: true,
keyboardDigit: null,
routeConformanceRequired: true,
},
{
id: "replay",
path: "/replay",

View file

@ -0,0 +1,104 @@
import { QueryClientProvider } from "@tanstack/react-query";
import { render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createTestQueryClient } from "../../test/createTestQueryClient";
import type { DeterminismTour } from "../../types/api";
import { TourRoute } from "./TourRoute";
const TOUR: DeterminismTour = {
schema_version: "determinism_tour_v1",
title: "The Determinism Tour",
thesis: "Bring a claim from any model and watch the engine decide, refuse, and replay it.",
steps: [
{
step_id: "intro",
order: 0,
kind: "intro",
headline: "Determinism you can check",
narrative: "Each step runs a real demo over pinned fixtures.",
demo_id: null,
demo_title: null,
what_this_proves: null,
what_this_does_not_prove: null,
route_hint: "/demos",
},
{
step_id: "decide",
order: 1,
kind: "demo",
headline: "Bring a claim — the engine decides",
narrative: "Served only when the pinned engine and an oracle agree.",
demo_id: "deductive_entailment_authority",
demo_title: "Deductive Entailment Authority",
what_this_proves: "CORE serves decisions only when engine and oracle agree.",
what_this_does_not_prove: "It does not claim open-domain theorem proving.",
route_hint: "/demos/deductive_entailment_authority",
},
{
step_id: "payoff",
order: 2,
kind: "payoff",
headline: "Replay to the same hash",
narrative: "Every decision replays to the same trace hash.",
demo_id: null,
demo_title: null,
what_this_proves: null,
what_this_does_not_prove: null,
route_hint: "/replay",
},
],
};
function stubFetch(tour: DeterminismTour = TOUR) {
vi.stubGlobal(
"fetch",
vi.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ ok: true, generated_at: "now", data: tour }),
}),
),
);
}
function renderRoute() {
return render(
<QueryClientProvider client={createTestQueryClient()}>
<MemoryRouter initialEntries={["/tour"]}>
<TourRoute />
</MemoryRouter>
</QueryClientProvider>,
);
}
describe("TourRoute", () => {
afterEach(() => {
vi.restoreAllMocks();
vi.unstubAllGlobals();
});
it("renders the provider-agnostic thesis and the ordered narrative", async () => {
stubFetch();
renderRoute();
expect(await screen.findByText(/Bring a claim from any model/)).toBeInTheDocument();
expect(screen.getByText("Determinism you can check")).toBeInTheDocument();
expect(screen.getByText("Bring a claim — the engine decides")).toBeInTheDocument();
expect(screen.getByText("Replay to the same hash")).toBeInTheDocument();
});
it("shows honest what-proves / what-does-not-prove cards on demo steps", async () => {
stubFetch();
renderRoute();
expect(await screen.findByText("what this proves")).toBeInTheDocument();
expect(screen.getByText(/engine and oracle agree/)).toBeInTheDocument();
expect(screen.getByText("what this does not prove")).toBeInTheDocument();
expect(screen.getByText(/does not claim open-domain/)).toBeInTheDocument();
// The demo step links to the real demo route.
expect(screen.getByTestId("tour-link-decide")).toHaveAttribute(
"href",
"/demos/deductive_entailment_authority",
);
});
});

View file

@ -0,0 +1,124 @@
import { Link } from "react-router-dom";
import { WorkbenchApiError } from "../../api/client";
import { useTour } from "../../api/queries";
import { Panel } from "../../design/components/Panel/Panel";
import { ErrorState } from "../../design/components/states/ErrorState";
import { LoadingState } from "../../design/components/states/LoadingState";
import type { TourStep } from "../../types/api";
function errorMessage(error: unknown): string {
return error instanceof WorkbenchApiError ? error.message : "Tour request failed.";
}
const KIND_LABEL: Record<TourStep["kind"], string> = {
intro: "Start here",
demo: "Live demo",
payoff: "The payoff",
};
function StepCard({ step }: { step: TourStep }) {
return (
<li className="grid grid-cols-[2.5rem_minmax(0,1fr)] gap-3">
<div className="flex justify-center">
<span className="flex h-7 w-7 items-center justify-center rounded-full border border-[var(--color-border-subtle)] bg-[var(--color-surface-inset)] font-mono text-xs text-[var(--color-text-secondary)]">
{step.order + 1}
</span>
</div>
<div className="min-w-0 border-l border-[var(--color-border-subtle)] pl-3 pb-2">
<div className="flex flex-wrap items-baseline gap-2">
<span className="text-sm font-semibold text-[var(--color-text-primary)]">
{step.headline}
</span>
<span className="rounded-sm bg-[var(--color-surface-inset)] px-1.5 py-0.5 text-[10px] uppercase tracking-wide text-[var(--color-text-muted)]">
{KIND_LABEL[step.kind]}
</span>
</div>
<p className="m-0 mt-1 text-sm text-[var(--color-text-secondary)] [text-wrap:balance]">
{step.narrative}
</p>
{step.demo_id && step.demo_title ? (
<p className="m-0 mt-2 text-xs text-[var(--color-text-muted)]">
demo: <span className="text-[var(--color-text-primary)]">{step.demo_title}</span>
</p>
) : null}
{step.what_this_proves ? (
<div className="mt-2 rounded-md border border-[var(--color-state-success-border)] bg-[var(--color-state-success-bg)] p-2">
<div className="text-[10px] font-semibold uppercase tracking-wide text-[var(--color-state-success-text)]">
what this proves
</div>
<p className="m-0 mt-1 text-xs text-[var(--color-text-primary)] [text-wrap:balance]">
{step.what_this_proves}
</p>
</div>
) : null}
{step.what_this_does_not_prove ? (
<div className="mt-2 rounded-md border border-[var(--color-state-warning-border)] bg-[var(--color-state-warning-bg)] p-2">
<div className="text-[10px] font-semibold uppercase tracking-wide text-[var(--color-state-warning-text)]">
what this does not prove
</div>
<p className="m-0 mt-1 text-xs text-[var(--color-text-primary)] [text-wrap:balance]">
{step.what_this_does_not_prove}
</p>
</div>
) : null}
{step.route_hint ? (
<Link
to={step.route_hint}
className="mt-2 inline-flex items-center gap-1 text-sm underline"
data-testid={`tour-link-${step.step_id}`}
>
{step.kind === "demo" ? "Run this demo" : "Go there"}
</Link>
) : null}
</div>
</li>
);
}
export function TourRoute() {
const tourQuery = useTour();
if (tourQuery.isLoading) {
return <LoadingState label="Loading the determinism tour..." />;
}
if (tourQuery.isError) {
return (
<ErrorState
whatFailed={errorMessage(tourQuery.error)}
mutationStatus="No mutation occurred."
reproducer="curl /tour"
retrySafety="Retry: safe"
/>
);
}
const tour = tourQuery.data;
if (!tour) {
return <LoadingState label="Loading the determinism tour..." />;
}
return (
<div className="h-full min-h-0 overflow-y-auto">
<Panel title={tour.title}>
<div className="grid gap-4">
<section className="rounded-md border border-[var(--color-state-info-border)] bg-[var(--color-state-info-bg)] p-3">
<h2 className="m-0 text-xs font-semibold uppercase tracking-wide text-[var(--color-state-info-text)]">
the pitch
</h2>
<p className="m-0 mt-2 text-sm text-[var(--color-text-primary)] [text-wrap:balance]">
{tour.thesis}
</p>
</section>
<ol className="m-0 grid list-none gap-4 p-0">
{tour.steps.map((step) => (
<StepCard key={step.step_id} step={step} />
))}
</ol>
</div>
</Panel>
</div>
);
}

View file

@ -52,11 +52,11 @@ describe("CommandPalette keyboard contract", () => {
expect(screen.getByRole("button", { name: "Open Trace" })).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Open Replay" })).toBeInTheDocument();
// One Navigate command per palette-visible route (13), derived from the
// route registry — Demos, Calibration, and Contemplation are included (the
// prior hand-maintained list of 10 dropped them).
// One Navigate command per palette-visible route (14), derived from the
// route registry — Demos, Calibration, Contemplation, and Tour are included
// (the prior hand-maintained list of 10 dropped them).
const items = dialog.querySelectorAll('[role="option"]');
expect(items.length).toBe(13);
expect(items.length).toBe(14);
const lastIndex = items.length - 1;
// Initially first item (index 0) is focused — check aria-selected

View file

@ -140,6 +140,33 @@ export interface EvidenceBundle {
bundle_digest: string;
}
export type TourStepKind = "intro" | "demo" | "payoff";
/**
* D1/D2 guided determinism tour a curated narrative over the real demos.
* `headline`/`narrative` are authored framing; for demo steps the honesty cards
* are pulled from the real demo spec, never re-authored.
*/
export interface TourStep {
step_id: string;
order: number;
kind: TourStepKind;
headline: string;
narrative: string;
demo_id: string | null;
demo_title: string | null;
what_this_proves: string | null;
what_this_does_not_prove: string | null;
route_hint: string | null;
}
export interface DeterminismTour {
schema_version: "determinism_tour_v1";
title: string;
thesis: string;
steps: TourStep[];
}
export type LeewayLicense = "PROPOSE" | "SERVE" | "blocked" | "unknown";
export type ClaimDisclosure = "approximate" | "verified" | "proposal_only" | "none";

View file

@ -21,6 +21,7 @@ from core.epistemic_state import (
from workbench import calibration, readers
from workbench.journal import DEFAULT_JOURNAL_DIR, TurnJournal, TurnJournalEntry
from workbench.evidence_bundle import build_evidence_bundle
from workbench.tour import determinism_tour
from workbench.field_evidence import (
field_evidence_from_journal_entry,
field_evidence_from_result,
@ -284,6 +285,8 @@ class WorkbenchApi:
)
if method == "GET" and path == "/demos":
return ApiResponse(200, ok({"items": readers.list_demos()}))
if method == "GET" and path == "/tour":
return ApiResponse(200, ok(determinism_tour()))
if method == "POST" and path.endswith("/run") and path.startswith("/demos/"):
demo_id = unquote(path.removeprefix("/demos/").removesuffix("/run"))
try:

View file

@ -203,6 +203,48 @@ class EvidenceBundle:
bundle_digest: str
TourStepKind = Literal["intro", "demo", "payoff"]
@dataclass(frozen=True, slots=True)
class TourStep:
"""One step of the guided determinism tour.
``headline`` / ``narrative`` are the authored, provider-agnostic framing.
For ``kind == "demo"`` steps the honesty cards (``what_this_proves`` /
``what_this_does_not_prove``) and ``demo_title`` are pulled from the REAL
demo spec at build time never re-authored so the tour cannot claim more
than the demo it points at. ``route_hint`` is where to go deeper.
"""
step_id: str
order: int
kind: TourStepKind
headline: str
narrative: str
demo_id: str | None
demo_title: str | None
what_this_proves: str | None
what_this_does_not_prove: str | None
route_hint: str | None
@dataclass(frozen=True, slots=True)
class DeterminismTour:
"""D1/D2 guided determinism tour — a curated narrative over real demos.
The ``thesis`` is the provider-agnostic pitch: bring a claim from any model
and watch the deterministic engine decide, refuse, and replay it proposer
authority ignored. ``steps`` are ordered and each demo step is bound to a
real entry in the demo registry (fail-closed if a demo id is missing).
"""
schema_version: Literal["determinism_tour_v1"]
title: str
thesis: str
steps: list[TourStep] = field(default_factory=list)
@dataclass(frozen=True, slots=True)
class ChatTurnResult:
prompt: str

119
workbench/tour.py Normal file
View file

@ -0,0 +1,119 @@
"""D1/D2 guided determinism tour — a curated narrative over the real demos.
The tour is the first-run, provider-agnostic story: bring a claim from any
model and watch the deterministic engine decide it, refuse it, or replay it
proposer authority ignored. Each demo step is BOUND to a real entry in the
demo registry: the honesty cards (``what_this_proves`` /
``what_this_does_not_prove``) and the demo title are pulled from the spec, never
re-authored, so the tour can never claim more than the demo it points at. A
step that references a missing demo is a fail-closed error, not a dead link.
"""
from __future__ import annotations
from workbench.readers import DEMO_SPECS
from workbench.schemas import DeterminismTour, TourStep, TourStepKind
_THESIS = (
"CORE is the deterministic engine the opaque transformer defines itself "
"against. Bring a claim — from any model, including your own — and watch the "
"engine decide it, refuse it, or replay it to the same hash. The proposing "
"model's authority is ignored; only verified evidence promotes."
)
# (step_id, kind, headline, narrative, demo_id, route_hint)
_TourPlanRow = tuple[str, TourStepKind, str, str, str | None, str | None]
_TOUR_PLAN: tuple[_TourPlanRow, ...] = (
(
"intro",
"intro",
"Determinism you can check",
"These are not screenshots or animations. Each step runs a real demo "
"over pinned fixtures, end to end. Watch the engine apply discipline you "
"can re-run and verify yourself.",
None,
"/demos",
),
(
"decide",
"demo",
"Bring a claim — the engine decides",
"A formal claim is served as entailed, refuted, or unknown only when the "
"pinned ROBDD engine and an independent oracle agree. Disagree, and it "
"refuses. The proposer never gets to assert the answer.",
"deductive_entailment_authority",
"/demos/deductive_entailment_authority",
),
(
"refuse",
"demo",
"A wrong proposer gets refused",
"When a proposer tries to smuggle an unsupported truth-state, the engine "
"rejects it. You are watching a wrong answer get refused rather than "
"served — the discipline that makes wrong=0 real.",
"epistemic_truth_state",
"/demos/epistemic_truth_state",
),
(
"promote",
"demo",
"Only a verified certificate promotes",
"Promotion into the vault happens only through an owner-applied verified "
"certificate. Proposer status is ignored entirely — authority lives in "
"the evidence, not the model.",
"proof_carrying_promotion",
"/demos/proof_carrying_promotion",
),
(
"payoff",
"payoff",
"Replay to the same hash, export the proof",
"Every decision above replays to the same trace hash, and any turn "
"exports as a content-addressed evidence bundle you can cite and "
"reproduce. Determinism isn't a claim here; it's a deliverable.",
None,
"/replay",
),
)
def _build_tour(plan: tuple[_TourPlanRow, ...]) -> DeterminismTour:
steps: list[TourStep] = []
for order, (step_id, kind, headline, narrative, demo_id, route_hint) in enumerate(plan):
demo_title = proves = not_proves = None
if demo_id is not None:
spec = DEMO_SPECS.get(demo_id)
if spec is None:
raise KeyError(
f"determinism tour references unknown demo: {demo_id}"
)
demo_title = spec.title
proves = spec.what_this_proves
not_proves = spec.what_this_does_not_prove
steps.append(
TourStep(
step_id=step_id,
order=order,
kind=kind,
headline=headline,
narrative=narrative,
demo_id=demo_id,
demo_title=demo_title,
what_this_proves=proves,
what_this_does_not_prove=not_proves,
route_hint=route_hint,
)
)
return DeterminismTour(
schema_version="determinism_tour_v1",
title="The Determinism Tour",
thesis=_THESIS,
steps=steps,
)
def determinism_tour() -> DeterminismTour:
"""Build the curated determinism tour, bound to the live demo registry."""
return _build_tour(_TOUR_PLAN)