change-splitting
Skill2 starsChanged 56 days agoMITView on GitHub
Use when committing or splitting a large change — tests whether it splits into easy-to-review smaller changes: mixed subjects, mechanical change, buried helper, broken bisect.
In this repository20 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- artifact-handoffSkill
- catalogSkill
- changelog-qualitySkill
- code-structureSkill
- comment-qualitySkill
- evidence-disciplineSkill
- factual-integritySkill
- language-style-samplingSkill
- llm-tellsSkill
- plan-iteration-gateSkill
- pre-commit-checkSkill
- project-discoverySkill
- repo-hygieneSkill
- self-review-gateSkill
- skill-authoringSkill
- socratic-specSkill
- systematic-debuggingSkill
- upstream-hygieneSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 7 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 23
Don't over-split: 500 edits one file as 500 commits is its own error.
- Distinctive: line 27
When single source file ≥200 changed lines, examine for separable seams — examination required, not auto-split:
- Distinctive: line 34
Document examination even when keeping together.
- Distinctive: line 43
When series/PR stack covers multiple themes, keep same-theme consecutive where dependencies/bisect allow, reviewer stays in context.
- Distinctive: line 45
Check: git log --oneline -20 grouping by keyword — would reviewer need to jump mental model back and forth?
- Distinctive: line 49
Before accepting N patches is ceiling because shared caller infra must change all at once, try narrowing:
- Distinctive: line 51
Keep old output channel alive unreached for not-yet-migrated callers
- Very specific: line 65
Never introduce bug in one patch fixed later same series — squash, note after --- if needed.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Change Splitting — One Logical Change Per Unit
Capability: reviewer can understand, build, test each unit in order without context-switching themes.
GC-30 — One logical change per commit/PR
- One logical change spanning many files = one commit.
- Two subjects same file = two commits (avoid "please split this up, don't mix SoC with evm stuff").
- Distinct transformation buried in larger one = own commit.
- Don't over-split: 500 edits one file as 500 commits is its own error.
GC-31 — 200-line trigger to examine for seams
When single source file ≥200 changed lines, examine for separable seams — examination required, not auto-split:
- Mechanical interface/type conversion vs behavioral change riding on top
- Code moved unchanged vs rewritten
- Case already handled correctly needing result reported differently vs genuinely new algorithm
- Helper extracted vs first caller of that helper
Document examination even when keeping together.
Verification:
git diff --numstat HEAD~1 | awk '$1+$2 >= 200 {print}' # --numstat puts added/deleted counts in $1/$2; --stat does notGC-32 — Thematic grouping, not interleaving
When series/PR stack covers multiple themes, keep same-theme consecutive where dependencies/bisect allow, reviewer stays in context. Counterpart to split-by-theme per-patch rule.
Check: git log --oneline -20 grouping by keyword — would reviewer need to jump mental model back and forth?
GC-33 — Incremental narrowing — parallel old and new
Before accepting N patches is ceiling because shared caller infra must change all at once, try narrowing:
- Keep old output channel alive unreached for not-yet-migrated callers
- Introduce new path for migrated ones
- Retire old only after all migrated
Standard introduce-new / migrate-one-at-a-time / remove-old. What often separates real ceiling from premature.
GC-34 — Bisectable, builds on own
Every intermediate:
- Builds
- Passes existing tests / boots minimal
- Behaviorally coherent (no leak until later, no unbalanced refcount alone, no last-use removed N and symbol N+1 — keep same patch or order so nothing dangles)
Never introduce bug in one patch fixed later same series — squash, note after --- if needed.
GC-35 — Cover letter / PR description owns ordering
State cross-patch ordering, prerequisites, dep notes in cover letter / PR description, not mechanics block middle of log going into history. Number patches N/M so order unambiguous.
GC-36 — A rename, a removal or a bulk edit is complete only when nothing points at the old name
A rename, a moved file, an extracted helper, a changed flag, a removed key or field: the change is finished when every reference has been updated — code, tests, docs, config, examples, comments — and every touched file still parses. Grep the whole tree for the old name rather than fixing the call sites that compiled loudly: the ones that fail silently (a string in a config, a name in documentation, a dynamic lookup) are exactly the ones a compiler will not find. Report the grep you ran and its result as the completion evidence.
A removal carries the reverse obligation: nothing may still ASSERT what was removed. A docstring promising a key the function no longer returns, or a comment justifying its own field by a diagnosis that was retracted elsewhere, is the same defect as a dangling call — the reader is sent after behaviour that does not exist. comment-quality GC-23 owns how the surviving text is worded; scripts/check-comment-drift.py reports the survivors mechanically.
4Q gate
(a) What's wrong? Does split mix subjects, break bisect, hide transformation, 200-line trigger unchecked without seam analysis? (b) Better way? Sweep N=2,3,4... concrete splits named patches scope dep order each builds. Materially better grouping? State explicitly if none beats with tradeoff correctness/simplicity/cost. (c) Missing? Rollback if middle reverted, ownership transfer, non-interference test suite name, failure notification if bisect fails, what unblocks downstream, what stays out of scope (non-goals with reason). (d) Boundaries explicit? CONTRIBUTING found for subject/trailer style, external dep version pinned, irreversible schema/migration guarded, scope positive: provides reviewable units so reviewer stays in context, not "not interleaved".
Converged = one full iteration no new finding across all 4. Trend shrinking -> keep going. Recurring same scale -> wrong altitude rescope.
Verification
./scripts/check-hygiene.sh HEAD
./scripts/phases.py --phase 2 --profile full 2>&1 | tail -n 20
# Churn check: per-commit summed additions vs series-net per file.
# sum+ >> net+ means an early patch introduced code a later patch
# removed — squash candidate (GC-34: never introduce-then-fix in-series).Related
changelog-qualityGC-10..GC-17 owns subject/bodycode-structureowns helper extraction by theme — this owns when extraction is own patchproject-discoveryStep0 finds upstream splitting conventionfactual-integrityowns never invent — cover letter claims verified vs actual patches
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

