Skip to content

gate: a skill that spawns subagents must state the scope contract - #307

Merged
mergify[bot] merged 2 commits into
mainfrom
subagent-scope-gate
Sep 10, 2026
Merged

gate: a skill that spawns subagents must state the scope contract#307
mergify[bot] merged 2 commits into
mainfrom
subagent-scope-gate

Conversation

@EdbertChan

@EdbertChan EdbertChan commented Sep 9, 2026

Copy link
Copy Markdown
Owner

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 in finding-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

policy

Review Unit

engine-runtime

Safety Invariant

No skill prose changes in this slice, so no agent behavior changes from it alone. The gate is additive: preflight.py gains 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-runtime and corpus-lesson cannot 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.txt exactly — 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

  • Does not rewrite the three grandfathered spawners.
  • Does not add a hardcoded list of known fan-out skills. That needs someone to remember the next one, which is the failure being fixed.
  • Does not match delegation-shaped wording in skill bodies that argues against delegating.

Test Plan

Test Plan

Fail-before / pass-after with the allowlist emptied (the state before this slice):

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

Restored:

ok	subagent scope contract
exit=0
  • python3 scripts/check_subagent_scope_contract.py --list → 7 spawners; 4 state the contract, 3 grandfathered
  • python3 -m unittest tests.test_subagent_scope_contractRan 9 tests ... OK
  • python3 -m unittest discover -s engine/skills/make-pr/testsOK

Regex 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
  • Safe to revert? Yes
  • Revert command: git revert <sha>
  • Post-revert steps: none
  • Data migration? No

🤖 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-scope or citing the contract in finding-shape.md.

New scripts/check_subagent_scope_contract.py scans 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-only subagent_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.

@cursor

cursor Bot commented Sep 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@cursor

cursor Bot commented Sep 9, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@EdbertChan
EdbertChan changed the base branch from subagent-scope to main September 9, 2026 21:20
@mergify

mergify Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Queued — the merge queue status continues in this comment ↓.

@EdbertChan

Copy link
Copy Markdown
Owner Author

Mergify repair stopped: required check failed: test. The retry cap was reached for current head f2c985f.

@cursor

cursor Bot commented Sep 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

edbert-bot and others added 2 commits September 9, 2026 21:34
- 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
@EdbertChan

Copy link
Copy Markdown
Owner Author

Mergify repair stopped: missing required check lint

@cursor

cursor Bot commented Sep 10, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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)

@EdbertChan

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify

mergify Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

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
  • check-success = lint
  • check-success = test

@mergify mergify Bot added the queued label Sep 10, 2026
@mergify
mergify Bot merged commit eccc9b1 into main Sep 10, 2026
4 checks passed
@mergify mergify Bot removed the queued label Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants