From a0329ba95751f58566ed7ab484475917a68f1629 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 7 Jul 2026 16:32:47 +0100 Subject: [PATCH 1/3] =?UTF-8?q?to-issues:=20slice=20wide=20refactors=20by?= =?UTF-8?q?=20expand=E2=80=93contract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a wide-refactor exception to the tracer-bullet rule: a single mechanical change whose blast radius fans across the codebase can't land as one green vertical slice. Seed "wide refactor" / "blast radius" across the description, the explore step (detection), and the drafting step (strategy), and give the expand–contract sequence in prose. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/to-issues-wide-refactor.md | 5 +++++ docs/engineering/to-issues.md | 4 ++++ skills/engineering/to-issues/SKILL.md | 6 +++++- 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .changeset/to-issues-wide-refactor.md diff --git a/.changeset/to-issues-wide-refactor.md b/.changeset/to-issues-wide-refactor.md new file mode 100644 index 0000000..c95c29b --- /dev/null +++ b/.changeset/to-issues-wide-refactor.md @@ -0,0 +1,5 @@ +--- +"mattpocock-skills": minor +--- + +Teach the **`to-issues`** skill to handle a **wide refactor** — a single mechanical change (like renaming a column) whose **blast radius** fans across the whole codebase, breaking thousands of call sites at once so no vertical slice can land green. The skill now spots this while exploring and slices it as **expand–contract** — expand the new form beside the old, migrate call sites in batches sized by blast radius, then contract the old form away — keeping CI green batch to batch (or, when it can't, only at a final integrate-and-verify issue). The leading words are seeded across the description, the explore step, and the drafting step. diff --git a/docs/engineering/to-issues.md b/docs/engineering/to-issues.md index 4f81518..9439028 100644 --- a/docs/engineering/to-issues.md +++ b/docs/engineering/to-issues.md @@ -32,6 +32,10 @@ The whole skill turns on one distinction. A **horizontal** slice ships one layer Before slicing, `to-issues` looks for prefactoring — "make the change easy, then make the easy change" — and orders that work first. It then quizzes you on the breakdown (granularity, dependencies, what to merge or split) before writing anything, and publishes blockers first so each issue's "Blocked by" field can reference a real ticket. +## The wide-refactor exception + +One shape breaks the tracer-bullet rule: a **wide refactor** — a single mechanical change (rename a column, retype a shared symbol) whose **blast radius** fans across the whole codebase, so one edit breaks thousands of call sites at once and no vertical slice can land green. `to-issues` spots this while exploring and slices it as **expand–contract** instead: expand (add the new form beside the old so nothing breaks), migrate (move call sites over in batches sized by blast radius, one issue per batch, CI green throughout because the old form still exists), then contract (delete the old form once no caller remains). When even the batches can't stay green alone, they share an integration branch that all block a final integrate-and-verify issue, and green is promised only there. + ## Where it fits `to-issues` is a step in the main build chain: diff --git a/skills/engineering/to-issues/SKILL.md b/skills/engineering/to-issues/SKILL.md index 4a79f28..684699e 100644 --- a/skills/engineering/to-issues/SKILL.md +++ b/skills/engineering/to-issues/SKILL.md @@ -1,6 +1,6 @@ --- name: to-issues -description: Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices. +description: Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices — and slice wide mechanical refactors by expand–contract instead. disable-model-invocation: true --- @@ -22,6 +22,8 @@ If you have not already explored the codebase, do so to understand the current s Look for opportunities to prefactor the code to make the implementation easier. "Make the change easy, then make the easy change." +Watch too for a **wide refactor** hiding in the plan — a single mechanical change whose **blast radius** fans across the whole codebase — because it slices differently from a tracer bullet (step 3). + ### 3. Draft vertical slices Break the plan into **tracer bullet** issues. Each issue is a thin vertical slice that cuts through ALL integration layers end-to-end, NOT a horizontal slice of one layer. @@ -34,6 +36,8 @@ Break the plan into **tracer bullet** issues. Each issue is a thin vertical slic +The **wide refactor** you spotted in step 2 is the exception to the tracer-bullet rule: because a single edit breaks thousands of call sites at once, no one slice can land green. Don't force it into a tracer bullet — sequence it as **expand–contract**. First expand: add the new form beside the old so nothing breaks. Then migrate the call sites over in batches sized by blast radius (per package, per directory), each batch its own issue blocked by the expand, keeping CI green batch to batch because the old form still exists. Finally contract: delete the old form once no caller remains, in an issue blocked by every migrate batch. When even the batches can't stay green alone, keep the sequence but let them share an integration branch that all block a final integrate-and-verify issue — green is promised only there. + ### 4. Quiz the user Present the proposed breakdown as a numbered list. For each slice, show: From aa591116bf50ca37c49e0715cd2de4c4fc6c1726 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 7 Jul 2026 16:35:39 +0100 Subject: [PATCH 2/3] to-issues: split into Process + Reference tiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert the description change and keep the wide-refactor material in one place. Reshape the skill into a lean Process (steps) and a Reference section holding the vertical-slice rules, the wide-refactor expand–contract rules, and the issue body template as co-located blocks the steps point to. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/to-issues-wide-refactor.md | 2 +- docs/engineering/to-issues.md | 2 +- skills/engineering/to-issues/SKILL.md | 45 ++++++++++++++------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/.changeset/to-issues-wide-refactor.md b/.changeset/to-issues-wide-refactor.md index c95c29b..618b693 100644 --- a/.changeset/to-issues-wide-refactor.md +++ b/.changeset/to-issues-wide-refactor.md @@ -2,4 +2,4 @@ "mattpocock-skills": minor --- -Teach the **`to-issues`** skill to handle a **wide refactor** — a single mechanical change (like renaming a column) whose **blast radius** fans across the whole codebase, breaking thousands of call sites at once so no vertical slice can land green. The skill now spots this while exploring and slices it as **expand–contract** — expand the new form beside the old, migrate call sites in batches sized by blast radius, then contract the old form away — keeping CI green batch to batch (or, when it can't, only at a final integrate-and-verify issue). The leading words are seeded across the description, the explore step, and the drafting step. +Split the **`to-issues`** skill into a lean **Process** and a **Reference** section, and teach it to handle a **wide refactor** — a single mechanical change (like renaming a column) whose **blast radius** fans across the whole codebase, breaking thousands of call sites at once so no vertical slice can land green. The drafting step now points at two co-located reference blocks: the **Vertical slice rules** for ordinary tracer bullets, and **Wide refactors**, which slices the change by **expand–contract** (expand the new form beside the old, migrate call sites in batches sized by blast radius, then contract the old form away) so CI stays green batch to batch — or, when it can't, only at a final integrate-and-verify issue. The issue body template moves into Reference too. diff --git a/docs/engineering/to-issues.md b/docs/engineering/to-issues.md index 9439028..99624b5 100644 --- a/docs/engineering/to-issues.md +++ b/docs/engineering/to-issues.md @@ -34,7 +34,7 @@ Before slicing, `to-issues` looks for prefactoring — "make the change easy, th ## The wide-refactor exception -One shape breaks the tracer-bullet rule: a **wide refactor** — a single mechanical change (rename a column, retype a shared symbol) whose **blast radius** fans across the whole codebase, so one edit breaks thousands of call sites at once and no vertical slice can land green. `to-issues` spots this while exploring and slices it as **expand–contract** instead: expand (add the new form beside the old so nothing breaks), migrate (move call sites over in batches sized by blast radius, one issue per batch, CI green throughout because the old form still exists), then contract (delete the old form once no caller remains). When even the batches can't stay green alone, they share an integration branch that all block a final integrate-and-verify issue, and green is promised only there. +One shape breaks the tracer-bullet rule: a **wide refactor** — a single mechanical change (rename a column, retype a shared symbol) whose **blast radius** fans across the whole codebase, so one edit breaks thousands of call sites at once and no vertical slice can land green. `to-issues` slices it as **expand–contract** instead: expand (add the new form beside the old so nothing breaks), migrate (move call sites over in batches sized by blast radius, one issue per batch, CI green throughout because the old form still exists), then contract (delete the old form once no caller remains). When even the batches can't stay green alone, they share an integration branch that all block a final integrate-and-verify issue, and green is promised only there. ## Where it fits diff --git a/skills/engineering/to-issues/SKILL.md b/skills/engineering/to-issues/SKILL.md index 684699e..9ddf478 100644 --- a/skills/engineering/to-issues/SKILL.md +++ b/skills/engineering/to-issues/SKILL.md @@ -1,6 +1,6 @@ --- name: to-issues -description: Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices — and slice wide mechanical refactors by expand–contract instead. +description: Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices. disable-model-invocation: true --- @@ -22,21 +22,9 @@ If you have not already explored the codebase, do so to understand the current s Look for opportunities to prefactor the code to make the implementation easier. "Make the change easy, then make the easy change." -Watch too for a **wide refactor** hiding in the plan — a single mechanical change whose **blast radius** fans across the whole codebase — because it slices differently from a tracer bullet (step 3). +### 3. Draft the issues -### 3. Draft vertical slices - -Break the plan into **tracer bullet** issues. Each issue is a thin vertical slice that cuts through ALL integration layers end-to-end, NOT a horizontal slice of one layer. - - - -- Each slice delivers a narrow but COMPLETE path through every layer (schema, API, UI, tests) -- A completed slice is demoable or verifiable on its own -- Any prefactoring should be done first - - - -The **wide refactor** you spotted in step 2 is the exception to the tracer-bullet rule: because a single edit breaks thousands of call sites at once, no one slice can land green. Don't force it into a tracer bullet — sequence it as **expand–contract**. First expand: add the new form beside the old so nothing breaks. Then migrate the call sites over in batches sized by blast radius (per package, per directory), each batch its own issue blocked by the expand, keeping CI green batch to batch because the old form still exists. Finally contract: delete the old form once no caller remains, in an issue blocked by every migrate batch. When even the batches can't stay green alone, keep the sequence but let them share an integration branch that all block a final integrate-and-verify issue — green is promised only there. +Break the plan into **tracer bullet** issues, following the **Vertical slice rules**. A **wide refactor** is the exception to that rule — slice it by **expand–contract** instead (see **Wide refactors**). ### 4. Quiz the user @@ -56,11 +44,29 @@ Iterate until the user approves the breakdown. ### 5. Publish the issues to the issue tracker -For each approved slice, publish a new issue to the issue tracker. Use the issue body template below. These issues are considered ready for AFK agents, so publish them with the correct triage label unless instructed otherwise. +For each approved slice, publish a new issue to the issue tracker using the **Issue body template**. These issues are considered ready for AFK agents, so publish them with the correct triage label unless instructed otherwise. Publish issues in dependency order (blockers first) so you can reference real issue identifiers. Where the tracker supports it, link each slice to its parent as a native **sub-issue** and wire each blocker as a native **blocking edge** (mechanics in the issue-tracker doc); the `## Parent` and `## Blocked by` body sections are the fallback otherwise. - +Do NOT close or modify any parent issue. + +## Reference + +### Vertical slice rules + +Each issue is a thin vertical slice that cuts through ALL integration layers end-to-end, NOT a horizontal slice of one layer. + +- Each slice delivers a narrow but COMPLETE path through every layer (schema, API, UI, tests) +- A completed slice is demoable or verifiable on its own +- Any prefactoring should be done first + +### Wide refactors + +A **wide refactor** is one mechanical change — rename a column, retype a shared symbol — whose **blast radius** fans across the whole codebase, so a single edit breaks thousands of call sites at once and no vertical slice can land green. Don't force it into a tracer bullet; sequence it as **expand–contract**. First expand: add the new form beside the old so nothing breaks. Then migrate the call sites over in batches sized by blast radius (per package, per directory), each batch its own issue blocked by the expand, keeping CI green batch to batch because the old form still exists. Finally contract: delete the old form once no caller remains, in an issue blocked by every migrate batch. When even the batches can't stay green alone, keep the sequence but let them share an integration branch that all block a final integrate-and-verify issue — green is promised only there. + +### Issue body template + +```md ## Parent A reference to the parent issue on the issue tracker (if the source was an existing issue, otherwise omit this section). @@ -82,7 +88,4 @@ Avoid specific file paths or code snippets — they go stale fast. Exception: if - A reference to the blocking ticket (if any) Or "None - can start immediately" if no blockers. - - - -Do NOT close or modify any parent issue. +``` From f219e663795dd06357bfb1e1ce5b0afb4fd7d94f Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Tue, 7 Jul 2026 16:35:57 +0100 Subject: [PATCH 3/3] to-issues: wrap issue template in XML tags Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/engineering/to-issues/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skills/engineering/to-issues/SKILL.md b/skills/engineering/to-issues/SKILL.md index 9ddf478..657e311 100644 --- a/skills/engineering/to-issues/SKILL.md +++ b/skills/engineering/to-issues/SKILL.md @@ -66,7 +66,7 @@ A **wide refactor** is one mechanical change — rename a column, retype a share ### Issue body template -```md + ## Parent A reference to the parent issue on the issue tracker (if the source was an existing issue, otherwise omit this section). @@ -88,4 +88,4 @@ Avoid specific file paths or code snippets — they go stale fast. Exception: if - A reference to the blocking ticket (if any) Or "None - can start immediately" if no blockers. -``` +