Skip to content

feat(spec-loop): add spec-scope deterministic mapper for the update beat - #930

Open
justinmclean wants to merge 2 commits into
apache:mainfrom
justinmclean:spec-scope
Open

feat(spec-loop): add spec-scope deterministic mapper for the update beat#930
justinmclean wants to merge 2 commits into
apache:mainfrom
justinmclean:spec-scope

Conversation

@justinmclean

Copy link
Copy Markdown
Member

Summary

Add a spec-scope entry point to tools/spec-inventory that maps a list of changed file paths to the spec files most likely relevant to those changes. The update beat now pipes the output of git diff --name-only through spec-scope so the agent receives a pre-computed list of specs to inspect instead of deriving the mapping itself -- closing the known gap in specs/spec-loop-runner.md.

Pattern extraction reads each spec Where it lives section: backtick-quoted tokens containing a slash become path-prefix patterns, and Skill: name bullets produce skills/ patterns. .claude/skills/magpie- symlink entries are expanded to skills/ aliases so skill-name patterns resolve correctly.

Ships 18 new unit tests covering extract_path_patterns, _changed_path_candidates, scope_map, and the scope_main CLI. loop.sh is updated to call spec-scope inside update_scope_context and include the result in the context block for the update beat prompt. Failures from the mapper are non-fatal (advisory only).

Generated-by: Claude (claude-sonnet-4-6)

Type of change

  • Skill change (.claude/skills/<name>/) — eval fixtures updated below
  • Tool / bridge contract (tools/<system>/*.md)
  • Python package (tools/*/ with pyproject.toml)
  • Groovy reference impl
  • Cross-cutting (RFC, AGENTS.md, sandbox, privacy-LLM)
  • Documentation (docs/, README.md, CONTRIBUTING.md)
  • Project template (projects/_template/)
  • CI / dev loop (prek, workflows, validators)
  • Other:

Test plan

  • prek run --all-files passes
  • For Python packages touched: uv run pytest / ruff check / mypy passes
  • For Groovy bridges touched: command-line invocation tested end-to-end
  • For skill changes: eval suite passes for the affected skill
    (PYTHONPATH=tools/skill-evals/src python3 -m skill_evals.runner tools/skill-evals/evals/<skill>/)
  • For skill behaviour changes: a new or updated eval fixture is included in this PR
    (a regression test for the bug fixed / the behaviour added — see CONTRIBUTING.md)
  • Other:

Add a spec-scope entry point to tools/spec-inventory that maps a list of
changed file paths to the spec files most likely relevant to those changes.
The update beat now pipes the output of git diff --name-only through
spec-scope so the agent receives a pre-computed list of specs to inspect
instead of deriving the mapping itself -- closing the known gap in
specs/spec-loop-runner.md.

Pattern extraction reads each spec Where it lives section: backtick-quoted
tokens containing a slash become path-prefix patterns, and Skill: name bullets
produce skills/<name> patterns. .claude/skills/magpie-<name> symlink entries
are expanded to skills/<name> aliases so skill-name patterns resolve correctly.

Ships 18 new unit tests covering extract_path_patterns, _changed_path_candidates,
scope_map, and the scope_main CLI. loop.sh is updated to call spec-scope inside
update_scope_context and include the result in the context block for the update
beat prompt. Failures from the mapper are non-fatal (advisory only).

Generated-by: Claude (claude-sonnet-4-6)
@justinmclean justinmclean self-assigned this Jul 27, 2026
The mapper silently returned no patterns for four specs.

_SKILL_KEYWORD_RE required a colon directly after 'Skill', so the plural
form 'Skills:' never matched. Those bullets list bare skill names with no
slash, so the backtick branch skipped them too — no error, just a missing
spec, which is what the mapper exists to prevent. Affected:
adoption-and-setup.md:38, agent-isolation-sandbox.md:58,
meta-and-quality-tooling.md:79, security-issue-lifecycle.md:32.

All 18 original tests used the singular form, so the suite passed while
the feature was broken for the shape that actually occurs in the tree.

Within a skill bullet, a token starting with '-' is shorthand for a
sibling of the preceding name, and the tree needs both expansions:
setup-isolated-setup-install + -update is setup-isolated-setup-update
(last segment replaced), while security-issue-import + -from-pr is
security-issue-import-from-pr (appended). Both are emitted; a pattern
matching no real path is inert, whereas picking one rule drops half the
skills.

Verified against the live tree — all four specs now resolve:
  skills/security-issue-import      -> security-issue-lifecycle.md
  skills/setup-isolated-setup-verify -> adoption-and-setup.md,
                                        agent-isolation-sandbox.md
  skills/write-skill                 -> meta-and-quality-tooling.md,
                                        skill-reconciler.md

Adds six tests; the four covering the plural forms fail on the previous
implementation with an empty frozenset. The two bare-top-level-directory
tests pin existing correct behaviour rather than fixing a defect: the
trailing slash is stripped before the slash test, so a bare 'tools/' is
already dropped. Reordering those steps would regress it.

Also corrects the scope_main docstring, which claimed the exit code is
always 0 while carrying a sys.exit(1) for an unresolvable repo root.

Generated-by: Claude Code (Opus 5)
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.

2 participants