Skip to content

docs(schema): reconcile ADR-150, ADR-083, the design, and docs with the engine [roadmap:deterministic-substrate] - #496

Merged
tcballard merged 5 commits into
mainfrom
claude/spec-corpus-corrections
Sep 22, 2026
Merged

tcballard merged 5 commits into
mainfrom
claude/spec-corpus-corrections

Conversation

@tcballard

@tcballard tcballard commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This is PR F, the last in the post-merge review series: corpus and documentation corrections, plus one small engine fix that the docs pass surfaced.

Engine fix. decided-mcp named a federation composition failure's stable code twice when composition failed mid-session, for example corpus-federation-artifact-type-conflict: corpus-federation-artifact-type-conflict: source …. Both serving composition sites in derived_cache.rs (v1 and v2) wrapped an error whose display already leads with the code in a Composition error that prefixes it again. I reproduced it live. It happens with and without the cache: the existing test's starts_with("…conflict: ") assertion also matched the doubled form, so it never caught it.

ADR-150 (wording amended to match the accepted intent and the implementation; no decision changes):

  • Decision 1 said "a node unions its parents' type sets, then adds its own. A name already present is skipped". That contradicted both its own first sentence (own elements first) and decision 2 (first-wins is rejected). It now says own-first bottom-up, with identical content a silent duplicate and different content decision 2's conflict, "never a skip".
  • Decision 6 is headed "per source" (was "per element") and says an entry is emitted per source that pins a bundle, whether or not its elements survive.
  • The Consequences no longer claim schema --list differs by closure without --corpus, or that an override can un-inherit a type. An override only settles a collision.
  • The amendment notes that order fixes the classification tie-break (ADR-083 decision 8).

ADR-083:

  • A dated amendment in Status records that ADR-150 replaces decision 9's federation scoping.
  • The amendment also records how decided-mcp meets decision 9's "watched" clause: it re-syncs the registry per call, not through the file-freshness watch list.
  • Decision 9 is marked amended.
  • adr-150 joins Related Decisions, which clears the unlinked-reference doctor finding.

Design (third-party-artifact-extensibility):

  • A duplicate override name is artifact-spec-bundle-config-invalid, not corpus-federation-invalid-override. The test already pins this.
  • Bundle-level failures are hard errors, not "one warning … find and resolve exit 0".
  • The nonexistent artifact-spec-bundle-skipped code is removed.
  • The MCP freshness, parent-order tie-break, un-inheriting, digest-bump rationale and memo-leak wording now match the code.

docs/validation.md:

  • MCP freshness is stated accurately.
  • schema/templates with --corpus is documented; the old line said they take no corpus directory.
  • validate --json reports artifact_spec_bundles for an unfederated bundle too.

Tests:

  • The live-collision MCP test runs cached and uncached and asserts one code prefix.
  • A type alias clears the clippy::type_complexity lint that --all-targets reports on decided/tests/spec_federation.rs.

Roadmap / ADR Trace

  • Roadmap: decisions/roadmaps/deterministic-substrate.md (Tranche C)
  • ADR-150, ADR-083 (wording amendments; the decisions are unchanged)
  • ADR-047: agent-facing and corpus artifacts stay truthful to the engine

Scope

  • rust/rac-engine/src/derived_cache.rs: FederatedCacheError::from_composition_display at both composition sites.
  • rust/decided-mcp/tests/spec_federation.rs: cached and uncached live collision.
  • rust/decided/tests/spec_federation.rs: OverrideCase alias.
  • decisions/decisions/adr-150-…md, decisions/decisions/adr-083-…md, decisions/designs/third-party-artifact-extensibility.md.
  • docs/validation.md, CHANGELOG.md.

Product / Architecture Decisions

User-Facing Contract

  • decided-mcp error text for a mid-session composition failure loses its duplicated code prefix. The code, isError, and the detail are unchanged.
  • No other output changes. The CLI golden battery (135 cases) and MCP golden battery are byte-identical to main on the same tree.

Verification

  • cargo fmt --check; cargo clippy --workspace --release --no-deps -- -D warnings (the CI invocation) and --all-targets: clean; cargo test --workspace --release: pass.
  • Mutation check: restoring the old constructor makes both the cached and the uncached live-collision tests fail.
  • Conformance certification 11/11; live-corpus invariants PASS.
  • Corpus gates: validate, relationships --validate, review (no P1/P2), export --agent-rules --check, watchkeeper --base origin/main: all exit 0.

Review Path

  1. derived_cache.rs (one constructor, two call sites).
  2. ADR-150 and ADR-083 diffs.
  3. The design diff.
  4. docs/validation.md, then the tests.

Notes For Reviewer

Implementation Process

Implemented with AI assistance under the roadmap contract; final scope, review, and acceptance decisions were made by the maintainer.

…deterministic-substrate]

Implements decisions/roadmaps/deterministic-substrate.md (Tranche C).

The v1 and v2 serving composition sites wrapped an error whose display
already leads with its stable code in a Composition error that prefixes
the code again, so decided-mcp reported, for example,
"corpus-federation-artifact-type-conflict: corpus-federation-artifact-
type-conflict: ..." with or without the cache. Strip the leading code
once when wrapping.
…ot [roadmap:deterministic-substrate]

Implements decisions/roadmaps/deterministic-substrate.md (Tranche C).

Runs the live-collision scenario with and without the cache and asserts
the finding text continues with its detail after one code prefix; the
previous prefix-only assertion also matched the doubled form.
…tic-substrate]

Implements decisions/roadmaps/deterministic-substrate.md (Tranche C).

A type alias for the case table clears the clippy type_complexity lint
that cargo clippy --all-targets reports on the test target.
…n with the engine [roadmap:deterministic-substrate]

Implements decisions/roadmaps/deterministic-substrate.md (Tranche C).

- ADR-150: decision 1 states own-first bottom-up composition and that a
  different-content duplicate is decision 2's conflict, not a skip;
  decision 6 is per source; the Consequences match schema --corpus and
  that an override cannot un-inherit an uncontested type; the amendment
  notes that order fixes the classification tie-break.
- ADR-083: a dated amendment records that ADR-150 replaces decision 9's
  federation scoping and how decided-mcp meets the "watched" clause;
  decision 9 is marked; adr-150 joins Related Decisions.
- Design: a duplicate override name is artifact-spec-bundle-config-invalid;
  bundle-level failures are hard errors, not warnings, and the
  nonexistent artifact-spec-bundle-skipped code is gone; MCP freshness,
  parent-order, un-inheriting, digest-bump, and memo-leak wording match
  the implementation.
… docs [roadmap:deterministic-substrate]

Implements decisions/roadmaps/deterministic-substrate.md (Tranche C).

States how a running decided-mcp follows a re-pin, that schema and
templates list the effective registry given --corpus, and that
validate --json reports artifact_spec_bundles for an unfederated bundle
too; records the doubled-prefix fix in the changelog.
@tcballard
tcballard force-pushed the claude/spec-corpus-corrections branch from 2be95b6 to f913cf8 Compare September 22, 2026 21:53
@tcballard
tcballard merged commit 13c01f4 into main Sep 22, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant