outcomeTypeScript and Markdown duplicates are both refused
spec:validation.duplicate-ids.dual-carrierPacks: pack:self-hosting-v1
Design: no design entries · no pinned declarations · no decisions
Findings: no errors, no warnings
specs/validation/duplicate-ids.dual-carrier.sdp.md
No open questions and no blocking questions; implementation binding none, verifier binding present, and expected-outcome oracle none.
Given
a {firstCarrier: "TypeScript"} carrier declares {specId: "spec:fixture.duplicate"}
a {secondCarrier: "Markdown"} carrier declares {specId: "spec:fixture.duplicate"}When
the extraction root is read
Then
both sites report {findingId: "extract/duplicate-id"}
no graph node is emitted for {specId: "spec:fixture.duplicate"}Composing needs the script.
Intent
- Execute the duplicate-ID rule across both carrier surfaces.
Behavior
Examples
Given a {firstCarrier: "TypeScript"} carrier declares {specId: "spec:fixture.duplicate"}
Given a {secondCarrier: "Markdown"} carrier declares {specId: "spec:fixture.duplicate"}
When the extraction root is read
Then both sites report {findingId: "extract/duplicate-id"}
Then no graph node is emitted for {specId: "spec:fixture.duplicate"}Verification
Verifier bindings
- test:protocol.duplicate-ids.dual-carrier · dual-carrier duplicate-ID contract verifies carrier exclusion · anchored · test anchor binding present ·
test/self-hosting-duplicate-ids.test.ts:1155External run evidence from
test/self-hosting-duplicate-ids.test.tsTest anchors:
test:protocol.duplicate-ids.dual-carrier. Specs verified by those bindings: spec:validation.duplicate-ids, spec:validation.duplicate-ids.dual-carrier.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
Name Suite Result Duration names self-hosting generation before collecting its filtered tracer generated contract preflight passed 420.97 ms names checkout generation before collecting its filtered example generated contract preflight passed 406.66 ms names both generations when an unfiltered suite lacks both contract trees generated contract preflight passed 382.54 ms matches a Vitest substring filter before collecting the self-hosting tracer generated contract preflight passed 433.99 ms matches a ./-prefixed filter before collecting the self-hosting tracer generated contract preflight passed 419.01 ms matches an absolute-path filter before collecting the self-hosting tracer generated contract preflight passed 412.9 ms reads an option value ["--reporter","verbose"] as no file filter, so the whole suite's contracts are required generated contract preflight passed 489.56 ms reads an option value ["--maxWorkers","1"] as no file filter, so the whole suite's contracts are required generated contract preflight passed 447.65 ms reads an option value ["-t","duplicate"] as no file filter, so the whole suite's contracts are required generated contract preflight passed 448.61 ms matches a file:line filter by its file before collecting the self-hosting tracer generated contract preflight passed 470.09 ms requires every contract tree for `related`, whose source paths name no test file (present: ["examples/checkout-v1/generated/contracts"]) generated contract preflight passed 412.33 ms requires every contract tree for `related`, whose source paths name no test file (present: ["generated/contracts"]) generated contract preflight passed 437.48 ms does not require contracts for an unrelated Vitest filter generated contract preflight passed 487.81 ms proceeds for the unfiltered invocation once both contract trees are generated generated contract preflight passed 472.5 ms fails a pooled run that mutates repository-root generated state pooled root generated-state sentinel passed 447.55 ms keeps the dedicated CLI pass when an option carries a separate value, and forwards it there pooled root generated-state sentinel passed 526.97 ms routes ["--","test/bootstrap.test.ts"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 454.43 ms routes ["--","--reporter","dot"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 514.99 ms routes ["related","src/cli/validate-watch.ts"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 575.58 ms routes ["test/cli.test.ts:120"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 424.18 ms routes ["test/bootstrap.test.ts","test/cli.test.ts:120:3"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 542.15 ms routes ["-h"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 414.97 ms routes ["--version"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 428.24 ms routes ["--","--help"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 437.21 ms routes ["--","-h"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 518.06 ms routes ["--","--","--help"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 515.84 ms records each pass of a split run writing ["--reporter=junit","--outputFile=report.xml"] as a blob report and merges them pooled root generated-state sentinel passed 578.11 ms records each pass of a split run writing ["test/bootstrap.test.ts","test/cli.test.ts","--reporter","html","-t","alpha"] as a blob report and merges them pooled root generated-state sentinel passed 615.24 ms refuses coverage in a split run and says no coverage provider is installed pooled root generated-state sentinel passed 515.37 ms refuses a split run writing the html report ["--reporter=html"] before any pass while @vitest/ui is missing pooled root generated-state sentinel passed 504.27 ms refuses a split run writing the html report ["--reporter","html","--outputFile=report/index.html"] before any pass while @vitest/ui is missing pooled root generated-state sentinel passed 506.81 ms refuses a split run writing the blob report ["--reporter","blob"], which Vitest cannot merge into pooled root generated-state sentinel passed 510.18 ms refuses a split run writing the blob report ["--reporter=blob","--outputFile=blob.json"], which Vitest cannot merge into pooled root generated-state sentinel passed 475.62 ms refuses a split run whose configuration sets reporters: ["blob"] pooled root generated-state sentinel passed 431.94 ms refuses a split run whose configuration sets coverage: { enabled: true } pooled root generated-state sentinel passed 473.04 ms refuses a split run whose configuration sets reporters: ["html"] pooled root generated-state sentinel passed 464.31 ms leaves a configuration Vitest cannot load to the passes, reading the caller's options alone pooled root generated-state sentinel passed 521.9 ms hands each pass the caller's environment, untouched by reading the configuration pooled root generated-state sentinel passed 557.4 ms leaves each pass its configured reporters when none of them writes a report file pooled root generated-state sentinel passed 559.44 ms forwards the listing command ["list","--filesOnly"] once, without running the CLI suite pooled root generated-state sentinel passed 436.72 ms forwards the listing command ["--reporter","verbose","list","test/cli.test.ts"] once, without running the CLI suite pooled root generated-state sentinel passed 437.08 ms forwards the benchmark command ["bench"] once, with no CLI unit pass and no contract tree pooled root generated-state sentinel passed 445.66 ms forwards the benchmark command ["bench","test/cli.test.ts"] once, with no CLI unit pass and no contract tree pooled root generated-state sentinel passed 478.95 ms forwards the benchmark command ["--","bench"] once, with no CLI unit pass and no contract tree pooled root generated-state sentinel passed 454 ms keeps the dedicated CLI pass for the executing command watch pooled root generated-state sentinel passed 539.6 ms keeps the dedicated CLI pass for the executing command dev pooled root generated-state sentinel passed 537.51 ms passes a pooled run that leaves repository-root generated state untouched pooled root generated-state sentinel passed 444.56 ms runs ["-t","cli alpha"] as Vitest would select it, with the CLI suite only in its own pass the test wrapper over real Vitest passed 2358.05 ms runs ["--testNamePattern","gamma"] as Vitest would select it, with the CLI suite only in its own pass the test wrapper over real Vitest passed 2129.39 ms runs ["--","test/other.test.ts"] as Vitest would select it, with the CLI suite only in its own pass the test wrapper over real Vitest passed 1150.11 ms runs ["--","-t","beta"] as Vitest would select it, with the CLI suite only in its own pass the test wrapper over real Vitest passed 2091.28 ms runs ["--","--","test/other.test.ts"] as Vitest would select it, with the CLI suite only in its own pass the test wrapper over real Vitest passed 2308.33 ms writes one report holding both passes for ["--reporter","junit","--outputFile","report.xml"] the test wrapper over real Vitest passed 2583.74 ms writes one report holding both passes for ["--reporter=junit","--outputFile=report.xml"] the test wrapper over real Vitest passed 2225.96 ms writes one report holding both passes for ["--reporter=junit","--outputFile.junit=report.xml","-t","a"] the test wrapper over real Vitest passed 2675.32 ms writes one JUnit document to stdout when no output file is named the test wrapper over real Vitest passed 2514.93 ms merges both passes with the configuration file ["--config","custom.config.mjs"] they ran with the test wrapper over real Vitest passed 2545.94 ms merges both passes with the configuration file ["-c","custom.config.mjs"] they ran with the test wrapper over real Vitest passed 2479.93 ms merges both passes into the report file the configuration names with reporters: ["junit"], outputFile: "report.xml" the test wrapper over real Vitest passed 2722.9 ms merges both passes into the report file the configuration names with reporters: [["junit", { outputFile: "report.xml" }]] the test wrapper over real Vitest passed 2668.11 ms merges both passes into the report file a configuration names when it loads with the runner loader alone the test wrapper over real Vitest passed 3027.04 ms merges both passes into the report file a configuration from a package names through its main file the test wrapper over real Vitest passed 2327.72 ms merges both passes into the report file a configuration from a package names through its exports for import alone the test wrapper over real Vitest passed 2570.49 ms merges both passes into the report file a configuration from a package names through its exports for import, where require names another file the test wrapper over real Vitest passed 2619.16 ms reads a configuration that asks for a report file when process.env.NODE_ENV === "test" as the passes read it the test wrapper over real Vitest passed 2437.87 ms reads a configuration that asks for a report file when process.env.VITEST === "true" as the passes read it the test wrapper over real Vitest passed 2398.05 ms reads a configuration that asks for a report file when process.env.TEST === "true" as the passes read it the test wrapper over real Vitest passed 2377.94 ms reads a configuration that asks for a report file when process.env.NODE_ENV === "production" as the passes read it the test wrapper over real Vitest passed 2429.1 ms reports a failing pooled pass in the merged report and stops before the CLI pass the test wrapper over real Vitest passed 2081.83 ms prints usage for ["--","--help"] and runs no test the test wrapper over real Vitest passed 585.73 ms prints usage for ["--","-h"] and runs no test the test wrapper over real Vitest passed 464.05 ms derives the duplicate-ID verifier facts from the bound executable example not recorded passed 7299.21 ms executes the bound example against a fresh world TypeScript and Markdown duplicates are both refused (spec:validation.duplicate-ids.dual-carrier) passed 12.13 ms
Design view
Requirement drawing
- Satisfying or referencing units: no recorded binding.
The diagram as text
- spec:validation.duplicate-ids.dual-carrier: TypeScript and Markdown duplicates are both refused · declared Spec
- spec:validation.duplicate-ids: Duplicate carrier IDs are excluded loudly · declared Spec
- test:protocol.duplicate-ids.dual-carrier: dual-carrier duplicate-ID contract verifies carrier exclusion · anchored test binding · binding present ·
test/self-hosting-duplicate-ids.test.ts:1155 - spec:validation.duplicate-ids.dual-carrier refines spec:validation.duplicate-ids · declared
- spec:validation.duplicate-ids.dual-carrier verifies spec:validation.duplicate-ids · declared
- test:protocol.duplicate-ids.dual-carrier verifies spec:validation.duplicate-ids.dual-carrier · anchored
Mermaid source
Copyable source; the Studio draws static SVG.
Preferred and chosen syntax: requirementDiagram; exact refines, satisfies and verifies, with claim words in nodes and per-edge comments.
Decisions
No decision record named.
Runtime
No implementation neighborhood recorded.
Runtime observation: not tracked.
Evidence
Runtime observation: not tracked.
Build attestations: not tracked.
Deployments: not tracked.
Bills of materials: not tracked.
Impact
- E2: verifies · declared
The diagram as text
- spec:validation.duplicate-ids: Duplicate carrier IDs are excluded loudly
- spec:validation.duplicate-ids.dual-carrier: TypeScript and Markdown duplicates are both refused
- spec:validation.duplicate-ids.dual-carrier refines spec:validation.duplicate-ids · declared
- spec:validation.duplicate-ids.dual-carrier verifies spec:validation.duplicate-ids · 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
- refines · spec:validation.duplicate-ids · stated ready, floor ready
Rested on by
No Spec rests on this Spec.
Relations
| Relation and direction | Other end | Claim | Reason | Exercised keys |
|---|---|---|---|---|
| refines · outgoing | Duplicate carrier IDs are excluded loudlyspec:validation.duplicate-ids · resolves | declared | None | None |
| verifies · outgoing | Duplicate carrier IDs are excluded loudlyspec:validation.duplicate-ids · resolves | declared | None | None |
Bindings
Implementation binding: none
Design reference: none
Verifier binding: present
- test:protocol.duplicate-ids.dual-carrier · dual-carrier duplicate-ID contract verifies carrier exclusion · anchored ·
test/self-hosting-duplicate-ids.test.ts:1155· 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.