feat(relationships): add decision applies-to scope and path lookup [roadmap:decision-to-code-proximity]#251
Closed
tcballard wants to merge 11 commits into
Closed
feat(relationships): add decision applies-to scope and path lookup [roadmap:decision-to-code-proximity]#251tcballard wants to merge 11 commits into
tcballard wants to merge 11 commits into
Conversation
…[roadmap:decision-to-code-proximity] Implements the graduation step required by rac/roadmaps/deterministic-substrate.md (Tranche A, rank 1): the item moves out of future/, gains its execution ticket (ADR-093) and its requirement link (rac-decision-applies-to-scope, gap 7 of the relationship-vocabulary programme), and joins the substrate programme's Related Roadmaps.
…map:decision-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (contract step). Settles: the ## Applies To section on decisions (path globs or component labels), the entry grammar and fnmatchcase dialect, the blocking format lint vs advisory tree-match split (reconciling the gap-7 requirement with the ADR-087/096 exemption precedent), and the lookup contract — rac decisions PATH plus the sixth pinned MCP tool decisions_for_path (ADR-030 change, ADR-033 budget). Accepts rac-decision-applies-to-scope.
…obs [roadmap:decision-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md, Initiative 1 (ADR-098). Adds: - core/applies_to.py — the entry grammar (path glob vs component label), normalisation, format-lint reasons, and the fnmatchcase governs() matcher - the applies_to external edge in the relationship registry, mirroring verified_by (external, directional, no provider) - the section on the decision spec (append-only) and its schema description - the malformed-applies-to validate lint, syntactic and config-free Adding 'applies to' to EXTERNAL_SECTIONS routes the edge through every existing external-exempt branch: resolution, range, and status checks skip it; the graph export carries it unresolved.
…d --validate [roadmap:decision-to-code-proximity] Implements rac/roadmaps/decision-to-code-proximity.md (ADR-098 advisory lane). A declared ## Applies To path scope matching nothing in the working tree is surfaced two ways: an additive advisories list on the relationship validation result (JSON key and human block present only when non-empty, excluded from ok and the exit code) and a warning finding in rac doctor. The pass discovers the repository root via the nearest .rac config and skips silently on bare corpora, so fixtures and gates are untouched; advisories stay out of SARIF by construction.
…roximity] Implements rac/roadmaps/decision-to-code-proximity.md, Initiative 2 (service layer, ADR-098). One corpus walk; liveness and status reuse the agent-rules seam; matching uses the pinned governs dialect; component labels never match; results sorted by artifact path with the matching scopes carried as evidence. Bindings, never verdicts (ADR-067).
…e-proximity] Implements rac/roadmaps/decision-to-code-proximity.md, Initiative 2 (CLI surface, ADR-098). rac decisions PATH [DIRECTORY] [--json] [--top-level]: exit 2 on a bad directory or empty path, exit 0 on any completed query including an empty result. Dedicated human and JSON renderers; the JSON shape is the ADR-098 contract the MCP tool mirrors.
Implements rac/roadmaps/decision-to-code-proximity.md, Initiative 2 (MCP surface, ADR-098). The sixth pinned tool: scoped grounding through the same decisions_for_path service the CLI uses, with the pinned description recorded in ADR-098 (ADR-030 contract change) and the matches list inheriting ADR-033 whole-item budget truncation.
…and MCP tool [roadmap:decision-to-code-proximity] Implements the ADR-098 test battery: - test_applies_to.py pins the entry grammar and the exact fnmatchcase dialect (subtree rule, star-crosses-separators, double-star, case sensitivity, character classes, no false prefix) so stdlib drift fails loudly - test_decisions_for_path.py covers the service and CLI faces (liveness filter, label never matches, empty-result exit 0, JSON contract, byte-determinism) - advisory tests prove unmatched scopes warn without blocking: relationships --validate stays exit 0, the advisories JSON key is absent when empty, bare corpora skip the tree pass - doctor warns on stale scopes and still exits zero - MCP: sixth-tool shape, one-source-of-truth vs the service, retired exclusion, determinism parametrisation - new goldens (decisions_human/json, empty) over a config-free fixture corpus; existing goldens byte-identical; both new files join the CI battery matrix
…:decision-to-code-proximity] Adds the rac decisions command reference (inputs, options, exit codes, JSON shape), the Applies-to scope section in the relationship docs (grammar, the format-lint vs advisory split), and brings the MCP tool table up to the actual six pinned tools — it had lagged at four, missing find_decisions as well as the new decisions_for_path.
…map:decision-to-code-proximity] The five decisions the gap-7 requirement names as evidence now declare their scope as data: adr-018 governs rac/, adr-023 src/rac/, adr-027 .github/workflows/, adr-033 src/rac/mcp/, and adr-035 carries the two component labels its prose stated. Also removes a stray trailing code fence in adr-018 that had been silently swallowing the document's tail. rac decisions src/rac/mcp/server.py rac/ now answers with ADR-023 and ADR-033 — the requirement's success metric, demonstrated on this repository's own corpus.
Collaborator
Author
|
Closing as superseded: the decision-to-code-proximity programme landed on main via epic #273 (PRs #284/#285/#286) with the ratified contract — Generated by Claude Code |
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
rac/roadmaps/decision-to-code-proximity.md— Tranche A, rank 1 of the deterministic-substrate programme (epic #248) and gap 7 of the relationship-vocabulary programme (epic #236) in one change, under the new ADR-098.Adds:
## Applies Toon decisions: declared path globs or component labels naming the code a decision governs, registered as theapplies_toexternal edge.rac decisions PATH [DIRECTORY]— the deterministic "which decisions govern this path" lookup.decisions_for_path— the sixth pinned MCP tool, same service underneath.malformed-applies-to) inrac validate, and an advisory — never blocking — unmatched-scope warning inrac relationships --validateandrac doctor.Roadmap / ADR Trace
Roadmap:
rac/roadmaps/decision-to-code-proximity.md(graduated fromfuture/in this PR, per the deterministic-substrate success measures)Decisions:
rac/decisions/adr-098-decision-applies-to-scope-and-path-lookup.md(new) — the entry grammar, the fnmatchcase dialect pin, the lint-vs-advisory split, the lookup contract, and the five-to-six MCP tool change (ADR-030)Requirement:
rac/requirements/rac-decision-applies-to-scope.md— Status Proposed to Accepted; all four REQs deliveredScope
Included
applies_toEdgeSpec (external, directional, no provider) — oneEXTERNAL_SECTIONSentry routes it through every existing resolution/range/status exemption and the graph export.core/applies_to.py: normalisation, path-vs-label discrimination (whitespace = label; separator or glob char = path;./opts a root file into path-hood), malformed reasons, and thegovernsmatcher (fnmatchcase, case-sensitive, directory scope governs its subtree).advisorieslist on the relationship validation result — excluded fromok, the exit code, and SARIF; JSON key and human block appear only when non-empty; the tree pass discovers the repo root via the nearest.racconfig and skips silently on bare corpora.decisions_for_pathservice inservices/resolve.py: one corpus walk, liveness and status from the agent-rules seam (never forked), results sorted by artifact path with matched scopes as evidence.rac/, adr-023src/rac/, adr-027.github/workflows/, adr-033src/rac/mcp/, adr-035 carries its two component labels.Excluded
freshness-and-drift-detection(Tranche A, rank 2).**behaves as*in this dialect, pinned by tests.Product / Architecture Decisions
RelationshipValidation.okfails on ANY recorded issue regardless of severity, so unmatched scopes live in a separateadvisorieslist rather than a severity level — the reviewed reconciliation of the gap-7 "existence-checked by--validate" requirement with the ADR-096 resolution-exemption precedent.fnmatchcaseat the Python 3.11 floor;*crosses/; the test battery fails loudly if the standard library ever shifts semantics.## Applies Tois gap 7's proposed section, so the substrate feature and the relationship-vocabulary gap cannot diverge.User-Facing Contract
CLI
New command:
rac decisions PATH [DIRECTORY] [--json] [--top-level]. Exit 0 on any completed lookup including empty; exit 2 on a bad directory or empty path. No existing command changes.JSON Output
rac decisions --json:schema_version,path,type,match_count,matches[{id,type,title,status,path,scopes}].rac relationships --validate --json: additiveadvisorieskey, present only when non-empty — existing output byte-identical otherwise.rac schema decision --json:applies_toappended tooptional(append-only).MCP
Sixth pinned tool
decisions_for_path(description recorded in ADR-098); payload mirrorsfind_decisionsand inherits ADR-033 whole-item truncation.Exit Codes
Unchanged meanings; the advisory never alters any exit code.
Verification
Ran
python -m pytest -q— 1789 passed, 1 skipped (60 tests added)ruff check src/ tests/,mypy(strict) — cleanrac validate rac/,rac relationships rac/ --validate(1705 checked, 0 issues),rac review rac/(no priority 1-2, health 94),rac export rac/ --agent-rules --check,rac gate rac/— all exit 0rac decisions src/rac/mcp/server.py rac/returns ADR-023 (viasrc/rac/) and ADR-033 (viasrc/rac/mcp/) — the requirement's success metricCovered
tests/test_applies_to.py(31): grammar, normalisation, malformed reasons, and the full dialect battery — subtree rule, star-crosses-separators, double-star equivalence, case sensitivity, character classes, no false prefix (racnever governsrac-localview/), empty-query refusal.tests/test_decisions_for_path.py(15): liveness filter (Superseded twin never returned), glob scopes, labels never match, query normalisation (./, backslashes, trailing slash), empty result exit 0, JSON contract, byte-determinism.relationships --validatestays exit 0 andgateunaffected;advisorieskey absent when empty; bare corpora (no.racconfig) skip the tree pass; component labels never advise; doctor warns and exits 0.filterkey (one source of truth), retired exclusion, determinism parametrisation; isolation battery green.Review Path
rac/decisions/adr-098-decision-applies-to-scope-and-path-lookup.md— the contract everything else implements.src/rac/core/applies_to.py— grammar + matcher (the normative core).src/rac/services/relationships.py— the advisories list and the tree pass (the never-blocking guarantee).src/rac/services/resolve.py— the lookup service.src/rac/cli.py,src/rac/mcp/server.py,src/rac/output/*— the two faces.Notes For Reviewer
decision-to-code-proximityitem on epic Epic: deterministic-substrate — the council-ranked substrate programme #248 and note gap 7's delivery on epic Epic: relationship-vocabulary — close the traceability gaps #236; freshness-and-drift-detection (rank 2) is now unblocked.Implementation Process
Implemented with AI assistance under the roadmap contract and the maintainer-ratified ADR-098 choices (advisory match check;
## Applies To, decisions-only); final scope, review, and acceptance decisions are the maintainer's, via this review.