feat(relationships): add decision code-scope Applies To vocabulary [roadmap:decision-to-code-proximity]#284
Merged
Conversation
…ision-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (Initiative 1, #274), adopting rac-decision-applies-to-scope. Adds the optional `## Applies To` section to the Decision schema and a first-class `applies_to` relationship edge. Unlike the format-linted external edges (related_tickets/verified_by), the edge carries a new declarative `filesystem_scoped` flag: its literal path entries are existence-checked against the working tree rather than resolved by identifier. Additive and append-only (ADR-007); classification-neutral.
…ecision-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (Initiative 1, #274). `rac relationships --validate` now checks each decision's `## Applies To` entries against the repository file tree, anchored to the nearest `.rac/` (ADR-018). Deterministic slash-or-glob classification: literal path/directory entries are existence-checked (missing ones raise the new `applies-to-target-not-found` error); glob patterns are recorded for the lookup (#275); component-name labels are recorded without resolution. Paths normalise to POSIX repo-relative form so results are byte-identical across platforms (ADR-002); absolute or escaping entries cannot name an in-repo scope and are reported not-found. Declared, never inferred (ADR-065/066); the human and SARIF renderers gain a suffix/reason for the new code.
…ion-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (Initiative 1, #274). Adds boundary coverage for the code-scope edge: existing paths/directories resolve; missing literal paths raise `applies-to-target-not-found`; glob and component-name entries are recorded without existence-checking; absolute and repo-escaping entries are reported not-found; `./`-prefixed entries normalise. Adjacent-type guard: a non-decision declaring `## Applies To` is an unsupported edge, not a scope check, and the section never shifts decision classification. CLI/JSON/human faces are exercised. Updates the schema-, edge-registry-, and cross-consumer-agreement pins to include the additive member.
…ecision-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (Initiative 1, #274). Dogfoods the new code-scope vocabulary: the four evidence decisions declare checkable `## Applies To` scope existence-checked by `rac relationships --validate` — adr-018 → `rac/`, adr-023 → `src/rac/`, adr-027 → `.github/workflows/`, adr-033 → `src/rac/mcp/` (a stray unbalanced code fence at the end of adr-018 is closed in passing). Marks rac-decision-applies-to-scope Accepted now its vocabulary, validation, and forward `get_related` surfacing ship; the querying lookup remains rac-path-decisions-lookup (#275). Closes the decision-scope box on #236.
…-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (Initiative 1, #274). Adds a "Code scope" section covering the decision-only `## Applies To` vocabulary — the slash-or-glob entry classification, existence-checking of literal paths, POSIX normalisation, and the graph-export representation — and lists the new `applies-to-target-not-found` issue code.
…ecision-to-code-proximity] Collapse two hand-wrapped single-argument calls the formatter keeps on one line; behaviour unchanged.
This was referenced Jul 3, 2026
Merged
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
Implements Initiative 1 of the
decision-to-code-proximityroadmap (epic #273, sub-issue #274), adopting therac-decision-applies-to-scoperequirement. A decision can now declare the code paths or components it governs, andrac relationships --validateexistence-checks those declarations against the repository — closing the "which recorded decisions govern the file I'm editing?" gap as corpus data rather than prose.Adds:
## Applies Tosection on decisions, modelled as a first-classapplies_torelationship edge.rac relationships --validate, with a newapplies-to-target-not-foundissue code.Roadmap / ADR Trace
Roadmap:
rac/roadmaps/decision-to-code-proximity.md(Initiative 1)Requirement:
rac/requirements/rac-decision-applies-to-scope.md(gap 7 of the traceability audit; delivery here closes its decision-scope box on Epic: relationship-vocabulary — close the traceability gaps #236)Relevant ADRs:
adr-007— additive JSON contract (new optional section, new issue code; existing corpora byte-identical)adr-018— RAC directory as canonical root (the.rac/anchor for path resolution)adr-019— asset referencesadr-065/adr-066— declared, never inferred; a pure function of declared references and the file treeadr-002— deterministic, offline (POSIX-normalised, no database)adr-034— reports which decisions bind, never a compliance judgementScope
Included
## Applies Torecognised and extracted on decisions only; additive and append-only; classification-neutral./) is existence-checked; a glob (*/?/[) is recorded as a declared pattern; a component name (no/, no glob) is a recorded label..rac/(ADR-018), POSIX-normalised so results are byte-identical across platforms; absolute or repo-escaping entries cannot name an in-repo scope and are reported not-found.get_related,inspect,rac export --graph) as an external, unresolved, filesystem-scoped edge.rac/, adr-023 →src/rac/, adr-027 →.github/workflows/, adr-033 →src/rac/mcp/).Excluded
pathargument onfind_decisions, plus the deliberate ADR-030 pinned-description revision. That israc-path-decisions-lookup/ decision-to-code-proximity: path→decisions lookup — CLI subcommand plus additive find_decisions path argument #275, a separate change;find_decisionsis byte-identical here to preserve that boundary.Product / Architecture Decisions
## Applies Tois registered inRELATIONSHIP_SECTIONSwith anapplies_toEdgeSpec, so it auto-surfaces throughget_related/inspect/graph — one vocabulary read by every consumer, per the roadmap's "authored once, read everywhere". This keeps the freshness drift gate and Explorer joining on the same reference rather than a parallel one.filesystem_scopedflag onEdgeSpecdistinguishes this edge from the format-linted external edges (related_tickets,verified_by). Like them it skips id resolution, range, and status checks; unlike them its literal entries are existence-checked. No existing edge did filesystem checking (evenverified_by, whose targets are file paths, is format-linted, never checked), so this is a new resolution mode rather than an extension of one.applies-to-target-not-found, severityerror. It fails--validatelike the other referential-integrity breakages and is additive to the JSON contract.relationships_checked, consistent with how the external edges are excluded — the metric stays the id-resolution count and is unchanged for existing corpora.docs/artifacts.mdleft unchanged: its optional-section lists deliberately abridge the external-reference family (Related Tickets / Verified By are already omitted and documented inrelationships.md), soApplies Tois documented alongside them there, not added to the per-type list.User-Facing Contract
CLI
No new command in this change.
rac relationships DIR --validategains the code-scope check:A missing literal path is reported; a glob or component name is not.
Human Output
A flagged entry renders under Broken Relationships as
✗ PATH path not found.JSON Output
rac relationships --validate --jsonemits the existing issue shape{source_path, relationship, target, code}withcode: "applies-to-target-not-found"andrelationship: "applies_to". SARIF carries the reason "declared path does not exist in the repository". No existing field changes;find_decisionsoutput is byte-identical.Exit Codes
0: every reference (and declared literal path) resolves.1: one or more validation issues, including a missing## Applies Topath.2: path not found (usage).Verification
Ran
rac validate rac/→PASS — 362 valid, 0 invalid.rac relationships rac/ --validate→ exit0,2049relationships checked,0issues (the four dogfood ADRs' paths all exist).rac review rac/→95/100, no priority 1–2 findings.pytest tests/test_relationship_validation.py tests/test_relationship_graph.py tests/test_schema.py tests/test_schema_agreement.py→ 78 passed. Full non-TUI suite: 1616 passed (the two failures —test_explorer_app,test_hook— reproduce on the pristine tree and are environment gaps: an incompatibletextualandracnot onPATH).Covered
applies-to-target-not-found(target + source preserved).src/**/*.py) and component name (RAC Core,Explorer) recorded, never flagged./etc/passwd) and escaping (../outside/) entries reported not-found rather than followed out of tree../-prefixed entry normalises and resolves.## Applies Toisrelationship-edge-unsupported, not a scope check; the section never shifts decision classification.Review Path
src/rac/core/artifacts.py,src/rac/core/relationship_types.py— the schema section and theapplies_toedge (filesystem_scoped).src/rac/services/relationships.py— the classifier, repo-root/POSIX-normalise helpers, and the existence-check pass wired into_validate.src/rac/output/human.py,src/rac/output/sarif.py— rendering for the new code.tests/test_relationship_validation.py(+ the three pin updates) — behaviour coverage.rac/requirements/rac-decision-applies-to-scope.md,docs/relationships.md— dogfood, status, and docs.Notes For Reviewer
rac-decision-applies-to-scopeis markedAcceptednow its vocabulary, validation, and forwardget_relatedsurfacing ship; the querying lookup stays open asrac-path-decisions-lookup(decision-to-code-proximity: path→decisions lookup — CLI subcommand plus additive find_decisions path argument #275).CHANGELOG.mduntouched — it is organised strictly by shipped release with no "Unreleased" section, so the entry belongs to release time (CalVer, ADR-076).Implementation Process
Implemented with AI assistance under the roadmap contract; the implementation contract (edge modelling and the slash-or-glob classifier) was ratified, and final scope, review, and acceptance decisions were made by the maintainer.