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 2: external run evidence from vitest 4.1.10
Build: CI 439 · Branch: docs/articles-refresh-1 · Commit: 61576184ea9f39b7f91c51fef5ff991b0bf2d0e6 · Start: 2026-11-04T07:59:39.962Z · Stop: 2026-11-04T08:03:39.928Z
Name Suite Result Duration names self-hosting generation before collecting its filtered tracer generated contract preflight passed 579.01 ms names checkout generation before collecting its filtered example generated contract preflight passed 480.2 ms names both generations when an unfiltered suite lacks both contract trees generated contract preflight passed 427.82 ms matches a Vitest substring filter before collecting the self-hosting tracer generated contract preflight passed 667.41 ms matches a ./-prefixed filter before collecting the self-hosting tracer generated contract preflight passed 437.58 ms matches an absolute-path filter before collecting the self-hosting tracer generated contract preflight passed 576.87 ms reads an option value ["--reporter","verbose"] as no file filter, so the whole suite's contracts are required generated contract preflight passed 369.9 ms reads an option value ["--maxWorkers","1"] as no file filter, so the whole suite's contracts are required generated contract preflight passed 435.55 ms reads an option value ["-t","duplicate"] as no file filter, so the whole suite's contracts are required generated contract preflight passed 409.28 ms matches a file:line filter by its file before collecting the self-hosting tracer generated contract preflight passed 416.24 ms requires every contract tree for `related`, whose source paths name no test file (present: ["examples/checkout-v1/generated/contracts"]) generated contract preflight passed 419.34 ms requires every contract tree for `related`, whose source paths name no test file (present: ["generated/contracts"]) generated contract preflight passed 385.36 ms does not require contracts for an unrelated Vitest filter generated contract preflight passed 578.46 ms proceeds for the unfiltered invocation once both contract trees are generated generated contract preflight passed 600.6 ms fails a pooled run that mutates repository-root generated state pooled root generated-state sentinel passed 590.16 ms keeps the dedicated CLI pass when an option carries a separate value, and forwards it there pooled root generated-state sentinel passed 648.54 ms routes ["--","test/bootstrap.test.ts"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 552.46 ms routes ["--","--reporter","dot"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 681.36 ms routes ["related","src/cli/validate-watch.ts"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 560.32 ms routes ["test/cli.test.ts:120"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 399.75 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 549.71 ms routes ["-h"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 400.66 ms routes ["--version"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 470.63 ms routes ["--","--help"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 546.12 ms routes ["--","-h"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 492.21 ms routes ["--","--","--help"] without running test/cli.test.ts in the pool pooled root generated-state sentinel passed 627.38 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 646.19 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 836.8 ms refuses coverage in a split run and says no coverage provider is installed pooled root generated-state sentinel passed 509.67 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 549.1 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 513.14 ms refuses a split run writing the blob report ["--reporter","blob"], which Vitest cannot merge into pooled root generated-state sentinel passed 568.34 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 468.19 ms refuses a split run whose configuration sets reporters: ["blob"] pooled root generated-state sentinel passed 692.5 ms refuses a split run whose configuration sets coverage: { enabled: true } pooled root generated-state sentinel passed 544.53 ms refuses a split run whose configuration sets reporters: ["html"] pooled root generated-state sentinel passed 461.01 ms leaves a configuration Vitest cannot load to the passes, reading the caller's options alone pooled root generated-state sentinel passed 612.78 ms hands each pass the caller's environment, untouched by reading the configuration pooled root generated-state sentinel passed 658.73 ms leaves each pass its configured reporters when none of them writes a report file pooled root generated-state sentinel passed 568.28 ms forwards the listing command ["list","--filesOnly"] once, without running the CLI suite pooled root generated-state sentinel passed 517.21 ms forwards the listing command ["--reporter","verbose","list","test/cli.test.ts"] once, without running the CLI suite pooled root generated-state sentinel passed 490.4 ms forwards the benchmark command ["bench"] once, with no CLI unit pass and no contract tree pooled root generated-state sentinel passed 527.7 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 583.68 ms forwards the benchmark command ["--","bench"] once, with no CLI unit pass and no contract tree pooled root generated-state sentinel passed 539.32 ms keeps the dedicated CLI pass for the executing command watch pooled root generated-state sentinel passed 630.64 ms keeps the dedicated CLI pass for the executing command dev pooled root generated-state sentinel passed 577.25 ms passes a pooled run that leaves repository-root generated state untouched pooled root generated-state sentinel passed 479.13 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 2241.23 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 2067.45 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 1142.89 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 2222.36 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 2084.54 ms writes one report holding both passes for ["--reporter","junit","--outputFile","report.xml"] the test wrapper over real Vitest passed 2348.31 ms writes one report holding both passes for ["--reporter=junit","--outputFile=report.xml"] the test wrapper over real Vitest passed 2563.84 ms writes one report holding both passes for ["--reporter=junit","--outputFile.junit=report.xml","-t","a"] the test wrapper over real Vitest passed 2553.09 ms writes one JUnit document to stdout when no output file is named the test wrapper over real Vitest passed 2786.99 ms merges both passes with the configuration file ["--config","custom.config.mjs"] they ran with the test wrapper over real Vitest passed 2782.51 ms merges both passes with the configuration file ["-c","custom.config.mjs"] they ran with the test wrapper over real Vitest passed 2606.61 ms merges both passes into the report file the configuration names with reporters: ["junit"], outputFile: "report.xml" the test wrapper over real Vitest passed 2582.37 ms merges both passes into the report file the configuration names with reporters: [["junit", { outputFile: "report.xml" }]] the test wrapper over real Vitest passed 2731.81 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 2844.28 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 3109.52 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 3168.47 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 2607.78 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 2433.7 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 2588.33 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 2648.22 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 2674.49 ms reports a failing pooled pass in the merged report and stops before the CLI pass the test wrapper over real Vitest passed 1911.05 ms prints usage for ["--","--help"] and runs no test the test wrapper over real Vitest passed 529.26 ms prints usage for ["--","-h"] and runs no test the test wrapper over real Vitest passed 486.62 ms derives the duplicate-ID verifier facts from the bound executable example not recorded passed 8248.83 ms executes the bound example against a fresh world TypeScript and Markdown duplicates are both refused (spec:validation.duplicate-ids.dual-carrier) passed 8.73 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.