Nuke Split
A small helper: 0–1 agents, no preflight, no run_dir (map: references/family-map.md — it sits between the spec producers and nuke-exec). Weaker implementers fail on oversized work long before they fail on hard work — a worker handed five files and a vague boundary drowns in context it cannot hold. This helper re-cuts an existing spec (nuke-audit's or nuke-review's fix-spec, nuke-spec's build spec, or any file following references/fix-spec-template.md) as fine as its seams allow: one concern ≈ one file per sub-task is the target; the executing tier's budget is the ceiling, never the goal. The original file is never modified. nuke-exec applies this same protocol inline at preflight when its own re-measure finds oversized tasks; standalone split exists to pre-cut a spec before handing it to a foreign executor or a fresh session.
The ceilings below say how big a piece may EVER be; the target says how small to aim; the seam rules say WHERE the knife lands. All three bind — a cut that fits the ceiling but crosses a seam is a bad cut, and a multi-file task no seam forces is an uncut task.
Size ceilings — countable, per executing tier
Mirrors references/fix-spec-template.md rule 8 — the template's table is canonical; a divergence here is a bug.
| Tier |
Per task (ceiling) |
Per batch |
| clerk |
1 file, ≤~300 lines of touched-file mass |
≤2 tasks |
| worker (default) |
≤3 files, ≤~1.5 KLOC of touched-file mass |
≤3 tasks |
| top |
as the spec wrote them — splitting is rarely worth it; still split any single task past ~10 files |
as specced |
The fine-cut target applies to clerk and worker; top passes through as specced. Knife direction, in order: file boundaries first, folder boundaries to group batches, regions (line ranges) only inside a single oversized file. A multi-file sub-task exists only where a seam forces it — a contract change ordered before its consumers, a definition traveling with its test.
Touched-file mass = sum of wc -l over the task's files (measure, never estimate from memory). An oversized file (a single file past the tier's line budget) is split by region: each sub-task names the file plus an explicit line range or symbol list (retry.ts:1-410 — the RetryQueue class), and gets its own mechanical Accept scoped to that region.
Seam rules — where the knife lands
- Cut along dependency seams, never through them. When a parent task changes a contract (a signature, schema, export, config shape) and updates its consumers, the contract change is one sub-task and the consumers are others — and the contract sub-task comes FIRST. Order the sub-tasks so no sub-task depends on the output of a later one.
- One concern per sub-task. A sub-task is describable in one sentence without "and". "Extract the backoff helper AND migrate poll.py to it" is two sub-tasks with an order between them.
- A definition and its test travel together. The sub-task that adds or changes behavior carries the test that proves it — never a separate "write the tests" sub-task for behavior another sub-task built (a whole-parent test that cannot decompose follows protocol rule 3's duplication note instead).
- Dependent sub-tasks never run side by side. Sub-tasks of one parent with an order between them go in the SAME batch (one implementer, executed in order) — or, when they cannot share a batch, into consecutive phases. Parallel batches are for independent work only.
- Region cuts land on symbol boundaries. A line-range sub-task starts and ends at a whole declaration (class, function, section) — never mid-symbol; the range is chosen so its Accept can be verified without reading the other regions.
Protocol
- Read the spec fully. Family spec (executor context, Gates table, phases, coverage map) → full protocol. Anything else — a plain task list, a TODO file — → degraded mode: apply the same budgets to a flat checklist, skip the coverage map step, and say so in the hand-back.
- Measure every task: files touched, touched-file mass (
wc -l, run now). Tasks already at the target — one concern, one file (or a seam-forced multi-file group), within ceiling — pass through byte-identical; splitting those is churn. Everything else gets the knife, oversized or not.
- Re-cut everything above the target — seam rules first, ceiling second: pick the seams (dependency order, one concern each, definition+test together), then cut to one file per sub-task wherever the seams permit, then by region within oversized files. Every sub-task carries: its parent's finding/requirement IDs, its own files-or-regions list, and its own Accept — mechanical per the template's rule 1, scoped so the sub-tasks' Accepts together imply the parent's. A parent Accept that cannot be decomposed mechanically (one test covering the whole change) is duplicated onto the last sub-task and noted.
- Re-batch: batches stay disjoint by file; two sub-tasks sharing a file share a batch; ordered sub-tasks share a batch or land in consecutive phases (seam rule 4); batch caps per the tier table. Phase order is never changed — splitting respects the template's dependency ordering.
- Update the coverage map: every F-### / REQ-### / U-### that mapped to a split task now maps to all its sub-tasks. A coverage entry lost in the re-cut is a splitter bug — recount both sides before writing (parent map count == new map count).
- Write
<original-name>.split.md next to the original — same template, header gains split-from: <path> · budget: <tier> — and hand back: tasks before → after, batches before → after, the oversized files that forced region splits, and the line to run next: nuke exec <path>.split.md.
Mandates
- Read-only except the single
.split.md output. No git commands, no source edits, no edits to the original spec.
- Never weaken an Accept: a sub-task inherits mechanical verification or the split is refused for that task — the hand-back names it and recommends the executing tier be raised instead.
- Counting over judgment: the target (one concern ≈ one file) and the ceilings above are the whole decision procedure; "this task feels big" is not a trigger and "it's probably fine" is not a pass.
When NOT to use
- The spec's tasks already sit at the target — single-concern, single-file (seam-forced groups aside) — run nuke-exec directly; a pass-through split is noise.
- The problem is ambiguity, not size (Accepts unclear, requirements contradictory) → nuke-spec territory; splitting a mushy task yields smaller mush.
- Sizing a NEW spec: the spec-architect should write right-sized tasks in the first place (references/fix-spec-template.md carries the same budgets); split exists for specs that arrive oversized.
1---2name: nuke-split3description: Use when a spec's tasks are too big for the agents that will execute them — "nuke split", "these tasks are too large", a fix-spec whose batches overflow cheap workers, a task touching a 3000-line file — re-cutting phases, batches, and tasks to a per-tier size budget while preserving acceptance criteria and the coverage map. Never executes anything.4---56# Nuke Split78A small helper: 0–1 agents, no preflight, no run_dir (map: references/family-map.md — it sits between the spec producers and nuke-exec). Weaker implementers fail on oversized work long before they fail on hard work — a worker handed five files and a vague boundary drowns in context it cannot hold. This helper re-cuts an existing spec (nuke-audit's or nuke-review's fix-spec, nuke-spec's build spec, or any file following references/fix-spec-template.md) as fine as its seams allow: **one concern ≈ one file per sub-task is the target; the executing tier's budget is the ceiling, never the goal**. The original file is never modified. nuke-exec applies this same protocol inline at preflight when its own re-measure finds oversized tasks; standalone split exists to pre-cut a spec before handing it to a foreign executor or a fresh session.910The ceilings below say how big a piece may EVER be; the target says how small to aim; the seam rules say WHERE the knife lands. All three bind — a cut that fits the ceiling but crosses a seam is a bad cut, and a multi-file task no seam forces is an uncut task.1112## Size ceilings — countable, per executing tier1314Mirrors references/fix-spec-template.md rule 8 — the template's table is canonical; a divergence here is a bug.1516| Tier | Per task (ceiling) | Per batch |17|---|---|---|18| clerk | 1 file, ≤~300 lines of touched-file mass | ≤2 tasks |19| worker (default) | ≤3 files, ≤~1.5 KLOC of touched-file mass | ≤3 tasks |20| top | as the spec wrote them — splitting is rarely worth it; still split any single task past ~10 files | as specced |2122The fine-cut target applies to clerk and worker; top passes through as specced. Knife direction, in order: file boundaries first, folder boundaries to group batches, regions (line ranges) only inside a single oversized file. A multi-file sub-task exists only where a seam forces it — a contract change ordered before its consumers, a definition traveling with its test.2324Touched-file mass = sum of `wc -l` over the task's files (measure, never estimate from memory). An **oversized file** (a single file past the tier's line budget) is split by region: each sub-task names the file plus an explicit line range or symbol list (`retry.ts:1-410 — the RetryQueue class`), and gets its own mechanical Accept scoped to that region.2526## Seam rules — where the knife lands27281. **Cut along dependency seams, never through them.** When a parent task changes a contract (a signature, schema, export, config shape) and updates its consumers, the contract change is one sub-task and the consumers are others — and the contract sub-task comes FIRST. Order the sub-tasks so no sub-task depends on the output of a later one.292. **One concern per sub-task.** A sub-task is describable in one sentence without "and". "Extract the backoff helper AND migrate poll.py to it" is two sub-tasks with an order between them.303. **A definition and its test travel together.** The sub-task that adds or changes behavior carries the test that proves it — never a separate "write the tests" sub-task for behavior another sub-task built (a whole-parent test that cannot decompose follows protocol rule 3's duplication note instead).314. **Dependent sub-tasks never run side by side.** Sub-tasks of one parent with an order between them go in the SAME batch (one implementer, executed in order) — or, when they cannot share a batch, into consecutive phases. Parallel batches are for independent work only.325. **Region cuts land on symbol boundaries.** A line-range sub-task starts and ends at a whole declaration (class, function, section) — never mid-symbol; the range is chosen so its Accept can be verified without reading the other regions.3334## Protocol35361. **Read the spec fully.** Family spec (executor context, Gates table, phases, coverage map) → full protocol. Anything else — a plain task list, a TODO file — → degraded mode: apply the same budgets to a flat checklist, skip the coverage map step, and say so in the hand-back.372. **Measure every task**: files touched, touched-file mass (`wc -l`, run now). Tasks already at the target — one concern, one file (or a seam-forced multi-file group), within ceiling — pass through byte-identical; splitting those is churn. Everything else gets the knife, oversized or not.383. **Re-cut everything above the target** — seam rules first, ceiling second: pick the seams (dependency order, one concern each, definition+test together), then cut to one file per sub-task wherever the seams permit, then by region within oversized files. Every sub-task carries: its parent's finding/requirement IDs, its own files-or-regions list, and its own Accept — mechanical per the template's rule 1, scoped so the sub-tasks' Accepts together imply the parent's. A parent Accept that cannot be decomposed mechanically (one test covering the whole change) is duplicated onto the last sub-task and noted.394. **Re-batch**: batches stay disjoint by file; two sub-tasks sharing a file share a batch; ordered sub-tasks share a batch or land in consecutive phases (seam rule 4); batch caps per the tier table. Phase order is never changed — splitting respects the template's dependency ordering.405. **Update the coverage map**: every F-### / REQ-### / U-### that mapped to a split task now maps to all its sub-tasks. A coverage entry lost in the re-cut is a splitter bug — recount both sides before writing (parent map count == new map count).416. **Write `<original-name>.split.md` next to the original** — same template, header gains `split-from: <path> · budget: <tier>` — and hand back: tasks before → after, batches before → after, the oversized files that forced region splits, and the line to run next: `nuke exec <path>.split.md`.4243## Mandates4445- Read-only except the single `.split.md` output. No git commands, no source edits, no edits to the original spec.46- Never weaken an Accept: a sub-task inherits mechanical verification or the split is refused for that task — the hand-back names it and recommends the executing tier be raised instead.47- Counting over judgment: the target (one concern ≈ one file) and the ceilings above are the whole decision procedure; "this task feels big" is not a trigger and "it's probably fine" is not a pass.4849## When NOT to use5051- The spec's tasks already sit at the target — single-concern, single-file (seam-forced groups aside) — run nuke-exec directly; a pass-through split is noise.52- The problem is ambiguity, not size (Accepts unclear, requirements contradictory) → nuke-spec territory; splitting a mushy task yields smaller mush.53- Sizing a NEW spec: the spec-architect should write right-sized tasks in the first place (references/fix-spec-template.md carries the same budgets); split exists for specs that arrive oversized.