feat(contract-schema): add depends_on/related_to relation fields and cross-reference validation#18
Merged
Merged
Conversation
Confirms the already-implemented clause_id field is not dropped when model_dump(exclude_none=True) is called — the path used by ConstraintsContract.to_json_file(). Closes the end-to-end serialization gap in the existing TestClauseIdGeneration coverage.
…Matter Establishes the schema foundation for inter-ADR relationship tracking. These fields enable ADRs to declare explicit dependencies and non-hierarchical relationships, which downstream tooling (relationship computation, impact analysis) can consume. Empty lists are normalised to None by extending the existing ensure_list_or_none validator rather than adding a new one.
…ng properties Schema validators and documentation tooling need explicit property definitions to understand relation fields; relying on additionalProperties: true would accept the fields silently but provide no type information or docs. Explicit definitions follow the same pattern as superseded_by.
During contract compilation, ConstraintsContractBuilder now collects all parsed ADRs (not just accepted ones) and calls _validate_relation_references() to surface depends_on/related_to entries that point to unknown ADR IDs. Warnings are printed alongside the existing malformed-ADR warnings, keeping the strict=False philosophy — contract output is unchanged, only advisory messages are added. all_ids is built from the full parse set so that references to proposed ADRs do not produce false positives.
…kflow ADRFrontMatter gained two new required fields (depends_on, related_to) but the construction site in creation.py was not updated, causing mypy errors.
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.
Why
ADRs often depend on or relate to other decisions, but there was no structured way to express these links in front matter. Without explicit relation fields, downstream tooling (impact analysis, relationship graphs) cannot discover these dependencies, and authors have no schema-enforced way to record them. This work adds the schema foundation and surfaces dangling references at contract-compile time before they become silent data quality issues.
Approach
Two new optional array-of-string fields (
depends_on,related_to) were added toADRFrontMatter, following the same pattern assuperseded_by. The existingensure_list_or_nonevalidator was extended to normalise empty lists toNone, keeping serialised output clean. The JSON schema received explicit property definitions (rather than relying onadditionalProperties: true) so tooling gets type information.Cross-reference validation was added to
ConstraintsContractBuilder: it now collects all parsed ADRs (not just accepted ones) before calling_validate_relation_references(). Warnings are printed alongside existing malformed-ADR warnings. The strict=False philosophy is preserved — the contract file is unchanged, only advisory messages are added. References to proposed ADRs are not flagged as broken.A regression test verifies that
clause_idis not dropped duringmodel_dump(exclude_none=True)— the serialisation path used byConstraintsContract.to_json_file().What Was Tested
clause_idserialisation underexclude_none=True(regression test)depends_on/related_toround-trip through parse → model → serialiseADRFrontMatterconstruction in creation workflow passes mypy with the new required fieldsRisks
Additive changes only. Existing ADRs without
depends_on/related_toare unaffected (fields default toNone). The only new user-visible behaviour is advisory warning output during contract compilation, which does not alter the compiled contract.