split-scope · git:20260911.568b2b3 · 2026-09-11 · sha256 40e046035142430d
split-scope git:20260911.568b2b3A
Immutable. This exact content never changes and is served at /api/v1/blob/40e046035142430d.
--- name: split-scope description: > Shape code changes and PR stacks so each diff is easy to review: one local claim, one safety invariant, clear architectural effect, and an explicit reason for the slice. Trigger before authoring implementation work, PR stacks, or any multi-diff plan, or when asked to split/scope/compress a change into reviewable pieces. --- # split-scope Use this skill before authoring implementation work, PR stacks, or any multi-diff plan. Optimize for reviewer cognition, not smallest total patch. ## Core Rule Each diff or workflow should make one locally reviewable claim. A tired senior engineer should be able to answer: - What architectural thing changed? - Why does this slice exist? - Why is it safe? - What alternatives were rejected? ## Required Metadata Every implementation slice should carry these fields in task descriptions and PR bodies: - `Review claim:` one sentence the reviewer is being asked to approve. - `Review lane:` exactly one lane from your `drafter.config.json` taxonomy (default: `behavior`, `refactor`, `proof`, `cleanup`, `policy`, or `docs`). - `Safety invariant:` why this slice is safe to review locally. - `Slice rationale:` why this work is split here instead of bundled elsewhere. - `Architectural effect:` what changed in control flow, data flow, ownership, dependency direction, or public surface. - `Alternative considerations:` rejected designs or split shapes. - `Non-goals:` what this slice explicitly does not change. When stacking slices, a Non-goal that says "leave shared policy X alone" / "do not change doctor policy" means this slice inherits the prior magic number — it is not independent evidence that X was re-validated. If you need to change X, put that in its own claim; do not treat sibling Non-goals as a re-vote. For mechanical slices, these can be terse. For cross-boundary changes, explain the before/after architecture and why the split is acceptable. Each slice must still contain one conceptual unit; a validator (`classifyReviewScope()` in `@neko-catpital-labs/drafter-core`) can infer mixed units from the claim, rationale, implementation details, and change-type entries when you configure `drafter.config.json`'s text-pattern rules. ## Safety Invariant Confirmation Before finalizing an implementation plan or PR stack, propose the `Safety invariant:` for every slice and ask the user to confirm or correct it. Keep the existing heading and definition: it explains why the slice is safe to review locally. Mechanical slices may use terse invariants, but they still require user confirmation. This is a pure conversational convention — no code in this toolkit enforces that a human actually answered. Follow it because it's the right discipline, not because a validator will catch you skipping it. ## Ordering Rules - Evidence before change: add repros, benchmarks, or instrumentation before the fix when they prove the problem. - Refactor before behavior when the extraction is reusable and behavior-neutral. - Foundation before behavior: add schemas, types, helpers, migrations, flags, and dormant code before behavior changes. - Compatibility before exposure: include adapters with a lower-level change when needed to preserve existing behavior. - Behavior before cleanup: fix correctness or security first; rename and cleanup later. - Activate one surface or path per diff. - Delete after migration, in a separate deletion slice as soon as safely unused. Exception: a pure rehome/relocation of an already-cohesive unit (no decomposition) deletes the old path in the SAME slice as the move — see `playbooks/rehome-relocation.md`. ## Proof Must Match the Claim A `proof` slice (repro, regression test, benchmark) exists to demonstrate one specific claim. Before writing it, name the exact property the bug report or Review Claim describes, then check the assertion tests that literal property — not a nearby signal that is easier to check but proves a different thing. "The panel stayed visible" is not evidence for "the camera did not move"; "the request returned 200" is not evidence for "the record was written correctly." A proxy assertion can pass while the real behavior described in the claim is still broken, which lets a broken fix ship as proven. When authoring or reviewing a `proof` slice, ask: if I only read this assertion's name and expect, would I know it tests the same thing the Review Claim states? If not, rewrite the assertion against the literal property, even if that property is harder to check. See `corpus/skills/principle-prove-it/SKILL.md` for the same rule applied to PR bodies and live system claims, not just tests. ## Boundary Rules Split across architectural boundaries unless the downstream edit is required to preserve existing behavior. Common boundaries: - DB migration, write path, read/API exposure, UI use, old column deletion. - Core behavior, API exposure, UI behavior. - Contract, handler, UI. - CLI, API, UI. - Mechanical rename, module reorganization. - Helper extraction, usage migrations. Exception: directly affected tests and compatibility adapters stay with the change that requires them. Unrelated test stabilization and optional cleanup are separate slices. ## Grouping Rules Group changes only when they share the same review claim: - generated output with the source schema change - docs explaining the changed behavior, API, or default - visual proof with the UI behavior change - dependency bump with required adaptation - exact same mechanical migration across many files - pure repo-wide import-path rename Split changes when they introduce a different claim: - optional cleanup - special cases inside a mechanical migration - stale unrelated screenshots - behavior fix plus rename - default flip plus dead-path removal - refactor/extraction plus new fields or other behavior changes - benchmark/repro/proof harness plus the fix it is meant to justify - product code plus planning/policy/docs updates - broad mechanical moves too large to inspect comfortably - multiple distinct extractions from one file (one top-level symbol move per slice) - a reader plus the file or format it reads (a hook plus the skill doc it parses): stack them, producer first "B only exists to read A's new shape" is an ordering fact, not a shared claim. It decides which PR lands first; it never merges the two. The same holds for slices a plan already split: if a workflow or merge step folds parallel slices back into one PR, the split is undone, so publish them as a stack instead. Stacking dependent changes is the standard answer (Google Engineering Practices, "Small CLs", 2019, https://google.github.io/eng-practices/review/developer/small-cls.html). Before publishing, run the repo's own unit check (catstack: `engine/skills/make-pr/scripts/preflight.py`). It fails on any mix of review units and prints the split. A PR body that says "needs splitting" is a failed check, not a caveat. ## Refactor playbooks Two detailed, Fowler/Tidy-First-grounded sequencing playbooks live alongside this file — read the one that applies before sequencing a refactor-lane stack: - `playbooks/decomposition-extraction.md` — splitting one file's symbols across multiple NEW modules (one top-level symbol per PR). - `playbooks/rehome-relocation.md` — moving an already-cohesive unit (a whole file or package) to a new location with content materially unchanged. Both playbooks end with `## Naming the Technique`'s rule (see `references/technique-catalog.md`): every `refactor`-lane PR names its single Fowler/refactoring.guru technique in the form `<Technique>: <what moved>`. ## PR Body Guidance Do not summarize the patch file-by-file. Compress the human judgment: - state the review claim - state the safety invariant - describe architectural effect in plain English - call out why this slice exists - include alternatives for non-obvious or cross-boundary choices ## Checking your Review Unit against a rehome's old path If a `drafter.config.json` path rule classifies paths by directory convention (for example `scripts/**` as `tooling-policy`), and your validator rejects a PR whose changed files span more than the declared Review Unit: when rehoming a file whose old path has a classification, declare the Review Unit that matches the OLD path unless the new path is independently classified the same way — check `classifyReviewUnitsForPath()` for both paths before authoring the PR body.