gate: a skill that spawns subagents must state the scope contract - #307
Conversation
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_034aef10-9e8c-4f74-9f6a-e24c7e91b48c) |
7abec37 to
6c3d416
Compare
fbdbda9 to
f2c985f
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_398b2d58-fc0f-4009-9a6d-f04018632ed7) |
|
Queued — the merge queue status continues in this comment ↓. |
|
Mergify repair stopped: required check failed: test. The retry cap was reached for current head f2c985f. |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_a64aded7-accb-45f4-9dd0-3c9c07eafce7) |
- Problem: principle-subagent-inherits-scope (previous slice) is prose, and the next fan-out skill someone writes will not remember it. A scope boundary that exists only in a principle nobody loads at spawn time is the tier-4-where-tier-3-applies failure that reflect/references/lenses.md's fix hierarchy warns about. - Trigger: landing that principle without a check would repeat the admin-bypass-sweep shape from PR #303 — prose asking for a behavior with nothing enforcing it. - Chose: a skill whose body instructs delegation must name principle-subagent-inherits-scope, or cite the scope contract in principle-prove-it/references/finding-shape.md. Two ways to satisfy it because the four investigation products already cite the reference and should not each repeat the principle's name. - Chose: grandfather the three pre-existing spawners in a shrink-only allowlist (scripts/subagent_scope_debt_allowlist.txt), mirroring scripts/skill_test_debt_allowlist.txt exactly. Rewriting reflect, independent-judge-swarm, and show-me-your-work to state the contract is a different review than adding the rule. - Rejected: a hardcoded list of known fan-out skills. Same objection as the trigger-policy gate — it needs someone to remember the next one. - Regex iteration, recorded because the first version was wrong in both directions. A loose pattern flagged three false positives: principle-build-the-lever says "don't fan out delegates", principle-trace-token-burn-loop prices "re-spawning the agent", and principle-guard-the-context-window costs out parallel Agent calls — all prose ABOUT delegation, not instructions to delegate. Tightening the verb to require an article ("spawn a|one|all ...") then went too far and lost why, alternatives-considered, and independent-judge-swarm, which are real spawners — false negatives are worse than false positives in a safety gate. The landed version keeps the broad verb patterns and adds a per-line negation guard, which drops all three false positives and keeps all seven real spawners. Both false positives are regression fixtures in the tests. - New: scripts/check_subagent_scope_contract.py, scripts/subagent_scope_debt_allowlist.txt, tests/test_subagent_scope_contract.py. - Modified: engine/skills/make-pr/scripts/preflight.py gains the gate (so future skill PRs run it) plus a colocated test for the gate list. - No skill prose changes, so no agent behavior changes from this slice alone. - Revertable with git revert. - Fail-before / pass-after with the allowlist emptied (the state before this slice), both outputs captured: fail engine/skills/reflect: instructs spawning subagents but names neither principle-subagent-inherits-scope nor the scope contract in finding-shape.md fail product/skills/independent-judge-swarm: ... same fail product/skills/show-me-your-work: ... same exit=1 with the allowlist restored: ok subagent scope contract exit=0 - python3 scripts/check_subagent_scope_contract.py --list -> 7 spawners, 4 ok (principle-prove-it, alternatives-considered, how, why), 3 grandfathered - python3 -m unittest tests.test_subagent_scope_contract -> Ran 9 tests, OK - python3 -m unittest discover -s engine/skills/make-pr/tests -> Ran 13, OK Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JQMWSLRArEfEm1psa7RKdD
check_no_new_comments.py rejected nine comment lines this branch added. Seven explained why SPAWNER_RE and NEGATED_RE are deliberately narrow; two named the corpus skills the test fixtures were copied from. The SPAWNER_RE/NEGATED_RE rationale moves into the module docstring, which the gate exempts. The two fixture-provenance lines are dropped: the test module docstring already names both skills and why they are there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013mDsvDgGuwaBuyRtYgvktd
|
Mergify repair stopped: missing required check lint |
74ee86d to
b128eff
Compare
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_7451cbb0-c26f-4412-968a-bcd59718602c) |
|
@Mergifyio queue |
Merge Queue Status
This pull request spent 3 minutes 53 seconds in the queue, including 2 minutes 55 seconds running CI. Required conditions to merge
|
Summary
The previous slice's rule is prose, and the next fan-out skill someone writes will not remember it. This adds the check: a skill whose body instructs delegation must name
principle-subagent-inherits-scope, or cite the scope contract infinding-shape.md.Three skills already spawned subagents before the rule existed —
reflect,independent-judge-swarm,show-me-your-work. They are grandfathered in a shrink-only allowlist rather than rewritten, because rewriting three established skills is a different review.Review Claim
A new skill that spawns subagents must state the scope those subagents inherit, enforced mechanically rather than by prose.
Review Lane
policyReview Unit
engine-runtimeSafety Invariant
No skill prose changes in this slice, so no agent behavior changes from it alone. The gate is additive:
preflight.pygains one command, and the allowlist preserves today's behavior for the three pre-existing spawners. Nothing the model can reach is widened.Slice Rationale
Split from the rule it enforces because
engine-runtimeandcorpus-lessoncannot mix. Landing the gate before the rule would fail closed on a principle that does not exist yet, so this sits on top.The allowlist mirrors
scripts/skill_test_debt_allowlist.txtexactly — the repo's established idiom for a new rule with pre-existing violations. Shrink-only: a skill graduates by stating the contract and removing its line.Non-goals
Test Plan
Test Plan
Fail-before / pass-after with the allowlist emptied (the state before this slice):
Restored:
python3 scripts/check_subagent_scope_contract.py --list→ 7 spawners; 4 state the contract, 3 grandfatheredpython3 -m unittest tests.test_subagent_scope_contract→Ran 9 tests ... OKpython3 -m unittest discover -s engine/skills/make-pr/tests→OKRegex iteration is recorded in the commit body: a loose pattern flagged three false positives (skills arguing against fan-out), and over-tightening then lost three real spawners. The landed version keeps broad verb patterns plus a per-line negation guard; both false positives are regression fixtures.
Revert Plan
Revert Plan
git revert <sha>🤖 Generated with Claude Code
https://claude.ai/code/session_01JQMWSLRArEfEm1psa7RKdD
Note
Low Risk
Additive policy enforcement and preflight wiring only; no skill prose changes and grandfathered skills preserve current behavior.
Overview
Adds a CI/preflight gate so any skill whose body instructs subagent fan-out must document the inherited scope—by naming
principle-subagent-inherits-scopeor citing the contract infinding-shape.md.New
scripts/check_subagent_scope_contract.pyscans skill bodies with a narrow spawner regex plus a per-line negation guard (so “don’t fan out” / “re-spawning” prose isn’t treated as delegation). Three legacy spawners (reflect,independent-judge-swarm,show-me-your-work) are grandfathered via a shrink-onlysubagent_scope_debt_allowlist.txt; new spawners must comply instead of joining the list.make-pr preflight runs this check on any skill-touching PR, with unit tests mirroring the existing trigger-policy gate wiring.
Reviewed by Cursor Bugbot for commit b128eff. Bugbot is set up for automated code reviews on this repo. Configure here.