Repository navigation
Conversation
11 tasks done
doublewhy
marked this pull request as ready for review
October 9, 2026 11:41
doublewhy
marked this pull request as draft
October 9, 2026 17:15
9 of 11 tasks
doublewhy
force-pushed
the
712-contract-requirement-tracing
branch
from
October 12, 2026 01:49
ddb0cfb to
73ce3bd
Compare
…requirement Add tools/check_contract_requirement_tracing.py as the "policy / published contract requirement tracing" stage. A published schema is traced when an ACTIVE or DRAFT requirement record carries an IMPLEMENTS -> SPEC link to its exact path; CODE_FILE links, other link types, and DEPRECATED or ARCHIVED owners never count, and an unreadable record fails closed. Backfill the 72 published contracts that had no such link across 35 requirement records, and document the rule in docs/explain/reference/published-contract-requirement-tracing.md. Closes #712
…isode owner An IMPLEMENTS link to a schema path typed CONFIG, SCHEMA, or DOCUMENTATION does not count as ownership and is retyped to SPEC only where it records ownership. The reference page and the checker docstring no longer call every such link a classification error: the 19 that remain record a narrower relation on contracts that already have a SPEC owner, and stay as they are. RUN-311 gains IMPLEMENTS -> SPEC links to the two participant-episode schemas, which commit 9dbbb87 published for RUN-311. The reference page now says that a requirement-governed branch must keep the edited record inside the ownership roots of its governing requirement's phase, and counts the publishing commit as declaring evidence. The negative tests add TESTS links and IMPLEMENTS links typed SCHEMA or DOCUMENTATION, and assert that each record was read.
PR #1442 published mixed-backend-execution-binding-v1 and mixed-backend-stage-report-v1 after this branch was cut, so the tracing gate reported both as untraced once the branch was rebased onto dev. API-407 owns both. Issue #1371, which #1442 implements, asks to "Update API-407 contracts" for these carriers, and #1442 states the rules for both contracts under the API-407 section of specs/formal/runtime-contracts/participant-backend-contracts.md. The API-407 statement requires the installed mapping, bridge, time-coordination and readback services that the binding pins and the stage reports evidence to be checked in context, and API-407 already owns mixed-participant-composition-profile-v1 and links the issue #1355 runtime modules whose carriers #1442 published.
PR #1449 published inject-trigger-request-v1, inject-occurrence-v1, inject-occurrence-outcome-v1 and inject-occurrence-correlation-v1 after this branch was cut, so the tracing gate reported all four as untraced once the branch was rebased onto dev. Neither #1449 nor issue #1366 declared a requirement, so each owner follows from its statement and the governing specification. #1449's reference page names ADR-112 and EI-01 to EI-06 in specs/sdl/external-injects.md as the contracts' authority, and EI-06 says that DSL-111 owns authored narrative identity and the occurrence relation and DSL-142 owns optional participant binding. DSL-111 owns the request, occurrence and outcome contracts. Its statement requires authorized external requests to instantiate authored injects as independently identified occurrences, prevents duplicate logical execution through retry keys, occurrence identities and scheduled slots, and keeps admission, refusal, application, partial and indeterminate outcomes distinct. It already links ADR-112 and the EI specification. DSL-142 owns the correlation contract. Its statement requires a participant delivery composed with an externally triggered world effect to join that effect's exact occurrence and produced result, which is the identity set the correlation carries for participant consumers.
doublewhy
force-pushed
the
712-contract-requirement-tracing
branch
from
October 12, 2026 19:16
73ce3bd to
4001d9c
Compare
doublewhy
marked this pull request as ready for review
October 12, 2026 19:36
doublewhy
marked this pull request as draft
October 12, 2026 22:42
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A schema could be published, and stay published, with no requirement governing it.
experiment-authoring-input-v1was linked to EXP-736 only after review (#675, PR #711), andtools/check_requirement_governance.pychecks only the files a branch changes. This PR adds a whole-inventory policy gate,tools/check_contract_requirement_tracing.py, and backfills every link the gate found missing.A published contract is traced when an ACTIVE or DRAFT requirement record carries an
IMPLEMENTS → SPEClink to its exact schema path. Onorigin/devatb22f3b63, 61 of the 139 published contracts met that rule. This PR backfills the other 78 across 39 requirement records, so the current tree passes with no allowlist and no waiver. From now on, a PR that publishes a schema must add its owner link in the same change.The issue asked for these decisions:
CODE_FILElinks do not count.raes_contracts/contracts/bundle.pygenerates all 139 contracts, and seven requirements link it as aCODE_FILE. Accepting module links would therefore mark every contract traced.requirement_governance.pyrejects that same status set for implementation work. 9 contracts trace only to DRAFT owners. Three of those owners, API-411, API-418, and API-421, are the contract requirements for participant outcome reports, participant budgets, and time. The fourth, EXP-719, is the treatment and factor design requirement thatexperiment-binding-descriptors-v1serves.CONFIG,SCHEMA, orDOCUMENTATIONdoes not count as ownership either, and is retyped toSPEConly where it records ownership. This PR retypes the 6 such links on otherwise-untraced contracts (ACT-610, ASR-511, ASR-516 twice, ASR-535, and SEM-218). It leaves the other 19 unchanged: API-424 (1), DSL-130 (2), GOV-922 (6), SEM-212 (2), SEM-213 (4), SEM-219 (3), and SEM-226 (1). Each of those sits on a contract that already has aSPECowner, and descriptions such as "Published vocabulary validation" and "temporal contracts" record a narrower relation, not ownership.RepositoryRequirementClient, the repository source thattools/policy/requirement_order.yamlselects. The gate makes no Ground Control request, so it runs in every CI policy run aspolicy / published contract requirement tracing.contracts/schemas/**/*.json. The contracts lane already fails when that tree disagrees withschema_bundle()(check_generated_schemas.py) or with the publication manifest (check_schema_publication.py). A new test pins all three to one set.Requirement UIDs
Related Issues
Closes #712
ADR Impact
contracts/schemas/the normative authority. No ADR text changes.Changes
tools/check_contract_requirement_tracing.py(new): inventoriescontracts/schemas/**/*.jsonand loads everydocs/requirements/<UID>/requirement.mdthroughRepositoryRequirementClient. It reports[contract-requirement-trace-missing]for each published contract without a liveIMPLEMENTS → SPECowner. A record the parser rejects is reported as[contract-requirement-record-unreadable]and owns nothing.--reportlists each contract's owners and never gates.--jsonandtools/policy/exceptions.yamlwaivers behave as incheck_schema_coverage.py.tools/nox_support/policy_lanes.py: adds one_WORKING_TREE_POLICY_STAGESrow afterpolicy / published schema coverage. The gate therefore runs innox -s policy,verify-fast-feedback, and the CI policy lane, and is skipped under--stagedlike its siblings.docs/requirements/*/requirement.md(39 records): adds 74IMPLEMENTS → SPEClines and retypes 6 existing IMPLEMENTS lines toSPEC(3CONFIG, 2DOCUMENTATION, 1SCHEMA). Each of the 78 contracts gains one owner, except the two participant-episode schemas, which gain two (RUN-311 and API-417). API-417, API-418, and EXP-719 had no Traceability section, so each gains one. API-407's two lines ownmixed-backend-execution-binding-v1andmixed-backend-stage-report-v1, which feat(contracts): publish mixed-backend execution and readback contracts #1442 published after this branch was first cut. DSL-111's three lines and DSL-142's one line own the four inject contracts that feat(contracts): publish inject readback, correlation and backend declaration contracts #1449 published after that. The table below gives each owner.docs/explain/reference/published-contract-requirement-tracing.md(new): documents the rule, the decisions above, the evidence order for choosing an owner, and the phase ownership roots that requirement governance applies when a governed branch edits the owner's record.docs/explain/reference/README.mdindexes it.implementations/python/tests/test_issue_712_contract_requirement_tracing.py(new): 25 tests, described in the Test Plan.Backfilled owners for the 78 contracts
Evidence classes, strongest first:
Each publishing PR or commit below is the one that added the schema path, found with
git log --diff-filter=A(no--follow) and GitHub's commit-to-PR lookup.nist-csf-defensive-categories-source-v1(retyped)IMPLEMENTS → CONFIGon the schema pathfipa-communicative-acts-source-v1,w3c-activitystreams-activity-types-source-v1IMPLEMENTS → SPECon the matchingcontracts/concept-authority/source documentsevaluation-history-event-stream-v1,evaluation-result-envelope-v1,workflow-history-event-stream-v1,workflow-result-envelope-v1CONSTRAINSeach path; statement covers result and history contractsworkflow-cancellation-request-v1CONSTRAINSthe path; statement covers mutating control-plane operationsparticipant-lifecycle-event-v1,participant-observation-envelope-v1DOCUMENTSeach path; statement covers participant observations and state-change reportsparticipant-history-view-v1,participant-status-view-v1DOCUMENTSeach path; statement covers status and history retrievalparticipant-outcome-report-v1DOCUMENTSthe path; statement covers participant outcome reportingprocessor-manifest-v2CONSTRAINSthe path; statement is the processor manifestraes-semantic-invariants-v1IMPLEMENTS → CONFIGon the contract's publication entryvalidation-profile-catalog-v1(retyped)IMPLEMENTS → CONFIGon the schema pathauthoring-adapter-comparison-v1,authoring-adapter-vector-v1(both retyped)IMPLEMENTS → DOCUMENTATIONon each schema pathparticipant-opacity-model-check-evidence-v1(retyped)IMPLEMENTS → CONFIGon the schema pathscenario-instantiation-request-v1CONSTRAINSthe path; statement resolves parameters into an instantiated scenarioevaluation-plan-v1,orchestration-plan-v1,provisioning-plan-v1CONSTRAINSeach path; statement is planning semanticsrecursive-realization-constraint-v1(retyped)IMPLEMENTS → SCHEMAon the schema pathbackend-operation-capabilities-v1,backend-operation-control-v1,backend-operation-request-v1,backend-operation-response-v1mixed-backend-execution-binding-v1,mixed-backend-stage-report-v1specs/formal/runtime-contracts/participant-backend-contracts.md. Issue #1371 asks to update the API-407 contracts. API-407 already ownsmixed-participant-composition-profile-v1and links the issue #1355 runtime modules whose carriers these contracts publishtime-model-v1,time-runtime-state-v1,realized-time-model-v1API-421-time-contractsparticipant-boundary-flow-policy-v1validation-basis-disclosure-v1authoring-adapter-profile-v1exploit-path-analysis-evidence-v1participant-opacity-analysis-evidence-v1,participant-opacity-analysis-input-v1,behavioral-relation-profile-v1,participant-opacity-model-check-input-v1sdl-candidate-synthesis-input-v1,sdl-candidate-synthesis-profile-v1,sdl-candidate-synthesis-record-v1988-dsl-114-candidate-synthesisexperiment-capture-spec-v1experiment-derived-measure-v1sdl-semantic-migration-context-v1semantic-projection-report-v1987-gov-918-semantic-projection-reportsbehavioral-relations-v1,scientific-completeness-assessment-v1,scientific-completeness-taxonomy-v1participant-episode-history-event-stream-v1,participant-episode-state-envelope-v1test_run_311_participant_episode_lifecycle.py. API-417 also owns both, by statement: plain-data contracts for participant episode initialization, reset, completion, and restart observationplan-realization-profiles-v1,backend-realization-preparation-v1requirement_order.yamlgives its phase thecontracts/schemas/plansroot, and it records the siblingrecursive-realization-constraint-v1; ASR-532's statement is backend result validationparticipant-decision-surface-v2participant-execution-control-v1,participant-execution-service-state-v1participant-execution-binding-v1raes_contracts/contracts/participant_execution.py, as "Execution binding contract"participant-resource-budget-event-v1,participant-resource-budget-policy-v1,participant-resource-budget-state-v1,participant-resource-pool-capacity-v1inject-trigger-request-v1,inject-occurrence-v1,inject-occurrence-outcome-v1docs/explain/reference/inject-occurrence-contracts.md, names ADR-112 and EI-01 to EI-06 inspecs/sdl/external-injects.mdas their authority, and EI-06 says DSL-111 "owns authored narrative identity and this occurrence relation". DSL-111's statement covers authorized external requests that instantiate authored injects as independently identified occurrences, duplicate prevention through retry keys, occurrence identities and scheduled slots, and distinct admission, refusal, application, partial and indeterminate outcomes. It links ADR-112 and the EI specificationinject-occurrence-correlation-v1observation-demand-v1experiment-binding-descriptors-v1participant-configuration-result-v1sdl-lineage-ledger-v1test_sdl_lineage.pyassociated-artifact-manifest-v1domain-profile-admission-policy-v1,domain-profile-binding-v1,domain-profile-definition-v1,domain-profile-resolution-context-v1,domain-profile-support-declaration-v1proposition-truth-result-v1objective-semantics.md, documents backend-neutral propositions#1449's Requirement UIDs section calls DSL-111 and DSL-142 context only, because the
sdl-languagephase's ownership roots intools/policy/requirement_order.yamldo not includecontracts/schemas/control-plane/. That limits which files a branch governed by those requirements may change. This PR changes only their records, which are inside those roots, and the tracing gate does not read ownership roots. DSL-114 (alsosdl-language) owning thecandidate-synthesiscontracts and API-407 owning twocontrol-planecontracts are the same pattern.Test Plan
Rebase rounds: the branch was rebased from
35122105ontodevata4357f9a, which added the API-407 lines (73ce3bdd, nowf9980e09). It was then rebased froma4357f9aontodevatb22f3b63, the #1449 merge. The four earlier commits applied cleanly and are patch-identical (git range-diff a4357f9a..73ce3bdd origin/dev..HEAD~1reports=for each), and the checker, its tests, the lane wiring, and both docs pages are byte-identical to73ce3bdd. On the rebased tree the gate exited 1 with four findings, forinject-trigger-request-v1,inject-occurrence-v1,inject-occurrence-outcome-v1, andinject-occurrence-correlation-v1. With the DSL-111 and DSL-142 lines in4001d9c3it exits 0, and--reportlists DSL-111 as the owner of the first three, DSL-142 as the owner of the correlation contract, and no contract asUNTRACED. CI run 38296542965 on4001d9c3succeeded, as did the Docs (38296542599), Bootstrap qualification (38296542692), PR Title Lint, and PR Body Policy runs. All 14 required checks passed, includingsonar; 32 checks passed in total, and the only skipped one wasdeploy. Every result below was re-run on4001d9c3unless it names another commit.uv run --project implementations/python --frozen --all-extras python -m pytest implementations/python/tests/test_issue_712_contract_requirement_tracing.py -q -p no:cacheproviderpassed (25 passed). The module has no integration or fuzz cases:-m integrationand-m fuzzeach deselect all 25.The temporary-repository cases cover the following:
CODE_FILE,CONFIG,SCHEMA, orDOCUMENTATION, or CONSTRAINS, DOCUMENTS, TESTS, or VERIFIES typedSPEC. Neither doesIMPLEMENTS → SPECon the source document beside the schema. Each of these cases also asserts that no record was unreadable, so none can pass on a parse failure.--reportbehave as documented.A wiring test drives
_run_working_tree_policiesagainst a stand-innox, the patterntest_nox_shard_wiring.pyuses. It asserts that the stage runs on the working tree and is skipped under--staged. Two live-tree tests assert that the checked-in tree passes and that the gate's inventory equals both the publication catalog andschema_bundle().Regression checks:
docs/requirementstoorigin/dev, which removes only the backfill.python tools/check_contract_requirement_tracing.pythen exited 1 with 78contract-requirement-trace-missingfindings, and the module failed onlytest_checked_in_repository_traces_every_published_contract(1 failed, 24 passed). With the backfill restored, the gate exits 0 and all 25 tests pass.CODE_FILE,CONFIG,SCHEMA, andDOCUMENTATIONcases. Counting any link typedSPECfailed the CONSTRAINS, DOCUMENTS, TESTS, and VERIFIES cases. In both runs the other 5 cases of that test passed.Every
*_governance.pyand*_policy_ownership.pymodule (17) passed, along with three other modules that read requirement records,test_issue_1237_requirement_scope.py,test_issue_1185_api_404_profile_alignment.py, andtest_public_project_readiness.py, and the three modules that cover the DSL-111 and DSL-142 subjects,test_issue_1353_external_inject_design.py,test_dsl_142_participant_inject_delivery.py, andtest_issue_794_participant_io_adoption.py. The result was 319 passed, 1 deselected, and with-m integrationthe deselected case passed.test_repo_policy_tools.py,test_nox_shard_wiring.py,test_identity_cutover_policy.py, andtest_project_positioning.py, which cover the policy lanes, passed: 246 passed, 2 deselected. With-m integration, those 2 passed.nox -s verify-fast-feedback -- --base-rev origin/devpassed, with 27 stages passed and 3 skipped; the new stage took 0.39 s. The skipped stages were YAML syntax and JSON syntax, because no such file changed, andpolicy / requirement governance, which the runner skips because the branch carries no requirement UID and no scope file.nox -s lintandmake policypassed.Under its own tests and the project coverage config in
implementations/python/pyproject.toml, the checker has 98% line and branch coverage: 78 statements with 1 missed, and 20 branches with 1 partial (SonarCloud new-code coverage 98.0% atddb0cfbdand again at73ce3bdd; at4001d9c3SonarCloud reports new-code coverage 97.96%, 0 new issues, 0.0% duplication, and quality gate OK). The only missed line is thesys.pathinsert at line 49.vale --config .vale.inireported 0 errors, 0 warnings, and 0 suggestions on the new reference page, which the docs lane does not lint.The reference page's note on ownership roots rests on a probe of
evaluate_requirement_governanceandevaluate_requirement_scope. In each, a branch governed by GOV-918, RUN-311, or API-412 edited that requirement's own record. The scope runs bound every changed file to that requirement, and all six runs reportedrequirement-ownership-mismatchon the record. This probe ran atddb0cfbd. Since then,devhas changedtools/policy/requirement_order.yamlonly by adding eight issue #297 ownership roots, none of them a GOV-918, RUN-311, or API-412 record, and it did not change betweena4357f9aandb22f3b63.Ground Control Checks
make policyexited 0, and the only skipped stage was requirement governance.ebac3e65, now8b1cf134after the rebases) returned two blocking findings and three minor ones, and the third commit (ddb0cfbd, now9bdae90a) fixes all five. The blocking findings were an overbroad retyping rule and citation and classification errors in the backfill table. The minor ones were the coverage figure, the missing TESTS,SCHEMA, andDOCUMENTATIONnegative cases, and the ownership-roots note. The two rebase-round commits,f9980e09(formerly73ce3bdd, the two API-407 lines) and4001d9c3(the three DSL-111 lines and one DSL-142 line), were then reviewed independently at4001d9c3: the owners, their phase mapping and the gate on dev's schemas all hold.Traceability
tools/check_contract_requirement_tracing.py,tools/nox_support/policy_lanes.py,docs/explain/reference/published-contract-requirement-tracing.md, and 80IMPLEMENTS → SPEClinks owning the 78 contracts, in 39docs/requirements/<UID>/requirement.mdrecords, listed in the table aboveimplementations/python/tests/test_issue_712_contract_requirement_tracing.pyChecklist
RepositoryRequirementClient,PolicyFailure, and the shared waiver loader.contracts/schemas/is untouched.ci(policy), which does not cut a release.Documentation
Updated:
docs/explain/reference/published-contract-requirement-tracing.md(new) and the index indocs/explain/reference/README.md.