Spec Studio

A bound example runs its contract steps against a fresh world

spec:extraction.example-runnerUse Case / Behavior · featureready floor ready

Changed since the base graph base b5e0a8b: rule.handlerDispatch

Base input: schema 0.12.0, 456 Specs.

Packs: pack:self-hosting-v1

Design: 1 design entry · 1 pinned declaration · no decisions

Findings: no errors, no warnings

specs/extraction/example-runner.sdp.md

No open questions and no blocking questions; implementation binding present, verifier binding present, and expected-outcome oracle none.

Intent
problem
A bound test must execute a Spec's own steps without the executing core learning any test framework.
outcome
Run a generated contract's steps in authored order and make a red step name itself in the Spec's own words.
value
A failing example reads as the Spec that failed rather than as an anonymous assertion.
Behavior
rule.contractOrder line 22 · specs/extraction/example-runner.sdp.md:22
The core plans every contract step in authored order and runs it against the world the caller hands in; creating a fresh world per example is the adapter's lifecycle, never the core's.

spec:extraction.example-runner.step-order · enabled

rule.worldCleanup line 23 · specs/extraction/example-runner.sdp.md:23
Once the Vitest adapter creates a world, it awaits the optional after hook whether the steps pass or fail. A step failure stays the test's failure and an error from after is then discarded; when the steps pass, an error from after fails the test. A world factory that throws creates no world, so after does not run.

no example exercises it

rule.oneHandlerPerStep line 24 · specs/extraction/example-runner.sdp.md:24
Duplicate step text within one example binds one handler, and every occurrence runs it; an occurrence that binds a slot to a different value is a conflicting re-binding, named at generation, and every occurrence runs with the first binding, because an example is one point.

spec:extraction.example-runner.step-order · enabled

rule.redStepNamesItself line 25 · specs/extraction/example-runner.sdp.md:25
A red step names itself before the assertion detail: the failure message leads with the step's natural reading — the Spec's own words with bound values inlined — and the original error is preserved, carried as cause when it cannot be re-messaged, and wrapped when the thrown value is not an error.

spec:extraction.example-runner.red-step-naming · enabled

rule.handlerDispatch line 26 · specs/extraction/example-runner.sdp.md:26
The bindings type covers every step and only the steps, so missing or stale handlers fail typechecking. At execution, dispatch looks up the contract key on the bindings and then their prototype chain, calling the first function found with the bindings as this and the world, parameters and contract step as arguments. An inherited owner is excluded, and traversal stops before it, when its prototype is null or when it is callable and its prototype's prototype is null; these boundaries exclude Object.prototype and Function.prototype from any realm while preserving inherited instance and static class methods. Own handlers remain eligible even on null-prototype or callable bindings. Methods of built-in parent classes such as Map, Array and Promise remain eligible before those boundaries. An inherited constructor, a missing handler or a first value that is not a function fails at execution with no handler bound for step key "<key>"; dispatch never skips that value to find a later function.

no example exercises it

rule line 27 · specs/extraction/example-runner.sdp.md:27
The core contributes unspecified, the one outcome no Spec ever states, so an uncovered region of an example space has an honest answer rather than a manufactured one.

1 unkeyed rule.

Verifying examples

A red step names itself before the assertion detail · spec:extraction.example-runner.red-step-naming · ready floor ready

Executable Spec

Given a contract whose given step repeats {occurrences: 2} times before one when step and one then step
Given the handler bound to the {failingPhase: "when"} step throws {thrown: "boom"}
When the bound plan runs against a fresh world
Then the run {outcome: "fails"}
Then the failure names the step in the Spec's own words as {failureLabel: "at step: When the cart is submitted"}
Then the failure preserves the original detail {detail: "boom"}

Open example

A repeated step runs its one handler at each occurrence, in contract order · spec:extraction.example-runner.step-order · ready floor ready

Executable Spec

Given a contract whose given step repeats {occurrences: 2} times before one when step and one then step
When the bound plan runs against a fresh world
Then the world records the handler trace {trace: "given 2 | given 2 | when | then"}
Then the run {outcome: "completes"}

Open example

Example space

Given a contract whose given step repeats {occurrences:number} times before one when step and one then step
Given the handler bound to the {failingPhase:"given"|"when"|"then"} step throws {thrown:string}
When the bound plan runs against a fresh world
Then the world records the handler trace {trace:string}
Then the run {outcome:"completes"|"fails"}
Then the failure names the step in the Spec's own words as {failureLabel:string}
Then the failure preserves the original detail {detail:string}
Design

Ports and adapters. The runner accepts a generated contract, step handlers, and a caller-owned world. The Vitest adapter registers tests and creates each world before calling the runner. Framework dependencies point from the adapter toward the runner; the runner remains usable without a test framework. Step ordering and failure labels belong to the core, while test registration and world lifecycle belong to the adapter.

failureMessage line 44 · specs/extraction/example-runner.sdp.md:44
"at step: " + naturalReading + "\n" + originalMessage is the message expression; naturalReading is the rendered contract step and originalMessage is the original error message or the string form of a non-Error throw.

no citation recorded

Verification

Verifier bindings

  • spec:extraction.example-runner.red-step-naming · A red step names itself before the assertion detail · declared · example enabled · specs/extraction/example-runner.red-step-naming.sdp.md

    External run evidence from test/self-hosting-extraction.test.ts

    Test anchors: test:protocol.build-pipeline.same-invocation, test:protocol.example-runner.red-step-naming, test:protocol.example-runner.step-order, test:protocol.excludes.refused-path, test:protocol.excludes.segment-boundary, test:protocol.executable-contracts.case-colliding-path, test:protocol.executable-contracts.concreteness-refusal, test:protocol.executable-contracts.multi-entry-example, test:protocol.schema-versioning.declared-version. Specs verified by those bindings: spec:extraction.build-pipeline, spec:extraction.build-pipeline.same-invocation, spec:extraction.example-runner, spec:extraction.example-runner.red-step-naming, spec:extraction.example-runner.step-order, spec:extraction.excludes, spec:extraction.excludes.refused-path, spec:extraction.excludes.segment-boundary, spec:extraction.executable-contracts, spec:extraction.executable-contracts.case-colliding-path, spec:extraction.executable-contracts.concreteness-refusal, spec:extraction.executable-contracts.multi-entry-example, spec:extraction.schema-versioning, spec:extraction.schema-versioning.declared-version.

    Run 1: external run evidence from vitest 4.1.10

    Build: CI 433 · Branch: fix/second-review-pass · Commit: 6375b6e431a7cf885a49befec76d7876cd3e538c · Start: 2026-11-04T07:12:23.076Z · Stop: 2026-11-04T07:15:49.695Z

    NameSuiteResultDuration
    executes the bound example against a fresh worldOne query invocation shares its extracted graph and validation result (spec:extraction.build-pipeline.same-invocation)passed32.2 ms
    executes the bound example against a fresh worldA prefix excludes its own tree and leaves a similar sibling standing (spec:extraction.excludes.segment-boundary)passed2.42 ms
    executes the bound example against a fresh worldA Windows-drive absolute path is refused rather than normalized (spec:extraction.excludes.refused-path)passed1.57 ms
    executes the bound example against a fresh worldA derived payload carries a schema version its consumer can read (spec:extraction.schema-versioning.declared-version)passed0.85 ms
    executes the bound example against a fresh worldAn unbound slot in a used step earns no step contract (spec:extraction.executable-contracts.concreteness-refusal)passed2.86 ms
    executes the bound example against a fresh worldA second structured entry is named, never left silently inert (spec:extraction.executable-contracts.multi-entry-example)passed4.27 ms
    executes the bound example against a fresh worldA case-only path collision withholds the whole contracts tree (spec:extraction.executable-contracts.case-colliding-path)passed1.68 ms
    executes the bound example against a fresh worldA repeated step runs its one handler at each occurrence, in contract order (spec:extraction.example-runner.step-order)passed0.7 ms
    executes the bound example against a fresh worldA red step names itself before the assertion detail (spec:extraction.example-runner.red-step-naming)passed0.88 ms
  • spec:extraction.example-runner.step-order · A repeated step runs its one handler at each occurrence, in contract order · declared · example enabled · specs/extraction/example-runner.step-order.sdp.md
  • test:protocol.example-runner-cleanup · the Vitest adapter cleans up a world whether its steps pass or fail · anchored · test anchor binding present · test/vitest-adapter.test.ts:19

    External run evidence from test/vitest-adapter.test.ts

    Test anchors: test:protocol.example-runner-cleanup. Specs verified by those bindings: spec:extraction.example-runner.

    Run 1: external run evidence from vitest 4.1.10

    Build: CI 433 · Branch: fix/second-review-pass · Commit: 6375b6e431a7cf885a49befec76d7876cd3e538c · Start: 2026-11-04T07:12:23.076Z · Stop: 2026-11-04T07:15:49.695Z

    NameSuiteResultDuration
    awaits cleanup after a failing step, cleanup also fails: falsenot recordedpassed4.59 ms
    awaits cleanup after a failing step, cleanup also fails: truenot recordedpassed0.58 ms
    fails with cleanup's error when the steps passnot recordedpassed0.48 ms
    awaits cleanup after passing stepsnot recordedpassed0.99 ms
    preserves a factory failure without invoking cleanupnot recordedpassed1.15 ms

Example space

  • occurrences · number · declared by a contract whose given step repeats {occurrences} times before one when step and one then step
  • failingPhase · "given" | "when" | "then" · declared by the handler bound to the {failingPhase} step throws {thrown}
  • thrown · string · declared by the handler bound to the {failingPhase} step throws {thrown}

Bound points

ExampleoccurrencesfailingPhasethrown
spec:extraction.example-runner.red-step-naming2"when""boom"
spec:extraction.example-runner.step-order2unboundunbound

Oracle binding: none

Coverage

occurrences: 2 · spec:extraction.example-runner.red-step-naming, spec:extraction.example-runner.step-order · not enumerable

failingPhase
Declared valueExamples
"given"no example
"when"spec:extraction.example-runner.red-step-naming
"then"no example

thrown: "boom" · spec:extraction.example-runner.red-step-naming · not enumerable

Unbound

Design view

Requirement drawing

Requirement drawing for spec:extraction.example-runner
The diagram as text
  • spec:extraction.example-runner: A bound example runs its contract steps against a fresh world · declared Spec
  • spec:extraction.example-runner.red-step-naming: A red step names itself before the assertion detail · declared Spec
  • spec:extraction.example-runner.step-order: A repeated step runs its one handler at each occurrence, in contract order · declared Spec
  • spec:extraction.runnable-modules: Derived runnable modules freeze the registrar interface · declared Spec
  • spec:decisions.adopted-registrars-committed: Adopted runnable registrars are committed · declared Spec
  • spec:extraction.executable-examples: Bound examples execute their authored steps · declared Spec
  • component:protocol.adapters: external runtime and source adapters · anchored code · src/adapters/vitest.ts:23
  • component:protocol.codegen: contracts and registrar output · anchored code · src/codegen/contracts.ts:671
  • component:protocol.runner: provider-neutral example execution · anchored code · src/runner/index.ts:103
  • component:protocol.testing: the generated registrar runtime · anchored code · src/testing/index.ts:38
  • impl:protocol.example-runner: plans and executes a bound example against the caller's world · anchored code · src/runner/index.ts:112
  • impl:protocol.example-runner-adapter: registers one test per example and owns the fresh world lifecycle · anchored code · src/adapters/vitest.ts:32
  • impl:protocol.example-testing-helpers: adapter-lifecycle and oracle-comparison helpers for bound examples · anchored code · src/testing/index.ts:50
  • impl:protocol.runnable-modules: derives and publishes runnable registrar modules from the graph · anchored code · src/codegen/contracts.ts:696
  • test:protocol.example-runner-cleanup: the Vitest adapter cleans up a world whether its steps pass or fail · anchored test binding · binding present · test/vitest-adapter.test.ts:19
  • test:protocol.example-runner.red-step-naming: the red-step point verifies the self-naming failure law · anchored test binding · binding present · test/self-hosting-extraction.test.ts:798
  • test:protocol.example-runner.step-order: the step-order point verifies contract order and the one handler per step · anchored test binding · binding present · test/self-hosting-extraction.test.ts:789
  • test:protocol.runnable-modules: verifies generated runnable-module registration and runtime semantics · anchored test binding · binding present · test/testing.test.ts:58
  • test:protocol.runnable-modules-generation: checks registrar generation, sibling paths and competing suite paths · anchored test binding · binding present · test/codegen.test.ts:39
  • test:protocol.runnable-modules-types: checks registrar skeletons and required authored adapters · anchored test binding · binding present · test/runnable-modules.typecheck.ts:5
  • spec:decisions.adopted-registrars-committed refines spec:extraction.runnable-modules · declared
  • spec:extraction.example-runner refines spec:extraction.executable-examples · declared — step dispatch and failure rendering execute a bound example
  • spec:extraction.example-runner.red-step-naming refines spec:extraction.example-runner · declared
  • spec:extraction.example-runner.red-step-naming verifies spec:extraction.example-runner · declared
  • spec:extraction.example-runner.step-order refines spec:extraction.example-runner · declared
  • spec:extraction.example-runner.step-order verifies spec:extraction.example-runner · declared
  • spec:extraction.runnable-modules refines spec:extraction.example-runner · declared
  • component:protocol.adapters satisfies spec:extraction.example-runner · anchored
  • component:protocol.codegen satisfies spec:extraction.runnable-modules · anchored
  • component:protocol.runner satisfies spec:extraction.example-runner · anchored
  • component:protocol.testing satisfies spec:extraction.runnable-modules · anchored
  • impl:protocol.example-runner satisfies spec:extraction.example-runner · anchored
  • impl:protocol.example-runner-adapter satisfies spec:extraction.example-runner · anchored
  • impl:protocol.example-testing-helpers satisfies spec:extraction.runnable-modules · anchored
  • impl:protocol.runnable-modules satisfies spec:extraction.runnable-modules · anchored
  • test:protocol.example-runner-cleanup verifies spec:extraction.example-runner · anchored
  • test:protocol.example-runner.red-step-naming verifies spec:extraction.example-runner.red-step-naming · anchored
  • test:protocol.example-runner.step-order verifies spec:extraction.example-runner.step-order · anchored
  • test:protocol.runnable-modules verifies spec:extraction.runnable-modules · anchored
  • test:protocol.runnable-modules-generation verifies spec:extraction.runnable-modules · anchored
  • test:protocol.runnable-modules-types verifies spec:extraction.runnable-modules · anchored
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: requirementDiagram. Chosen syntax: flowchart TB because folds require exact labels unavailable in requirement syntax.

Decisions

No decision record named.

Runtime
  • component:protocol.adapters · external runtime and source adapters · src/adapters/vitest.ts:23 · layer adapter · context protocol

    Uses

    • component:protocol.runner · provider-neutral example execution · src/runner/index.ts:103 · layer application · context protocol
  • component:protocol.runner · provider-neutral example execution · src/runner/index.ts:103 · layer application · context protocol

    Uses

  • impl:protocol.example-runner · plans and executes a bound example against the caller's world · src/runner/index.ts:112

    Component: component:protocol.runner · provider-neutral example execution · src/runner/index.ts:103 · layer application · context protocol

    Uses

    None.

  • impl:protocol.example-runner-adapter · registers one test per example and owns the fresh world lifecycle · src/adapters/vitest.ts:32

    Component: component:protocol.adapters · external runtime and source adapters · src/adapters/vitest.ts:23 · layer adapter · context protocol

    Uses

    • impl:protocol.example-runner · plans and executes a bound example against the caller's world · src/runner/index.ts:112

Runtime observation: not tracked.

Evidence

Runtime observation: not tracked.

Build attestations: not tracked.

Deployments: not tracked.

Bills of materials: not tracked.

Impact
Relations of spec:extraction.example-runner
The diagram as text
  • spec:extraction.example-runner: A bound example runs its contract steps against a fresh world
  • spec:extraction.example-runner.red-step-naming: A red step names itself before the assertion detail
  • spec:extraction.example-runner.step-order: A repeated step runs its one handler at each occurrence, in contract order
  • spec:extraction.executable-contracts: The build derives step and space contracts from graph examples
  • spec:extraction.executable-examples: Bound examples execute their authored steps
  • spec:extraction.runnable-modules: Derived runnable modules freeze the registrar interface
  • spec:extraction.example-runner dependsOn spec:extraction.executable-contracts · declared — runs the step contracts the build emits
  • spec:extraction.example-runner refines spec:extraction.executable-examples · declared — step dispatch and failure rendering execute a bound example
  • spec:extraction.example-runner.red-step-naming refines spec:extraction.example-runner · declared
  • spec:extraction.example-runner.step-order refines spec:extraction.example-runner · declared
  • spec:extraction.runnable-modules refines spec:extraction.example-runner · declared
  • spec:extraction.example-runner.red-step-naming verifies spec:extraction.example-runner · declared
  • spec:extraction.example-runner.step-order verifies spec:extraction.example-runner · declared
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: flowchart. Chosen syntax: labelled flowchart, preserving exact relations, claims and folds.

Rests on

Rested on by

Distance 1

Distance 2

Relations

Relation and directionOther endClaimReasonExercised keys
dependsOn · outgoingThe build derives step and space contracts from graph examples
spec:extraction.executable-contracts · resolves
declaredruns the step contracts the build emitsNone
refines · outgoingBound examples execute their authored steps
spec:extraction.executable-examples · resolves
declaredstep dispatch and failure rendering execute a bound exampleNone
refines · incomingA red step names itself before the assertion detail
spec:extraction.example-runner.red-step-naming · resolves
declaredNoneNone
refines · incomingA repeated step runs its one handler at each occurrence, in contract order
spec:extraction.example-runner.step-order · resolves
declaredNoneNone
refines · incomingDerived runnable modules freeze the registrar interface
spec:extraction.runnable-modules · resolves
declaredNoneNone
verifies · incomingA red step names itself before the assertion detail
spec:extraction.example-runner.red-step-naming · resolves
declaredNoneredStepNamesItself
verifies · incomingA repeated step runs its one handler at each occurrence, in contract order
spec:extraction.example-runner.step-order · resolves
declaredNonecontractOrder, oneHandlerPerStep

Bindings

Implementation binding: present

  • component:protocol.adapters · external runtime and source adapters · src/adapters/vitest.ts:23 · role adapter · layer adapter · context protocol
  • component:protocol.runner · provider-neutral example execution · src/runner/index.ts:103 · role service · layer application · context protocol
  • impl:protocol.example-runner · plans and executes a bound example against the caller's world · src/runner/index.ts:112 · role service · component component:protocol.runner · layer application · context protocol
  • impl:protocol.example-runner-adapter · registers one test per example and owns the fresh world lifecycle · src/adapters/vitest.ts:32 · role adapter · component component:protocol.adapters · layer adapter · context protocol

Design reference: none

Verifier binding: present

  • spec:extraction.example-runner.red-step-naming · A red step names itself before the assertion detail · declared · specs/extraction/example-runner.red-step-naming.sdp.md · example enabled
  • spec:extraction.example-runner.step-order · A repeated step runs its one handler at each occurrence, in contract order · declared · specs/extraction/example-runner.step-order.sdp.md · example enabled
  • test:protocol.example-runner-cleanup · the Vitest adapter cleans up a world whether its steps pass or fail · anchored · test/vitest-adapter.test.ts:19 · test anchor

Expected-outcome oracle: none

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.