Skip to content

Commit 2684677

Browse files
docs(plan-rollout): restructure dogfood as PLAN_ROLLOUT_V0.md
Match the versioned design-doc convention in docs/designs/ (PLAN_TUNING_V0.md, PLAN_TUNING_V1.md, SELF_LEARNING_V0.md, PACING_UPDATES_V0.md). The original PLAN_ROLLOUT_DOGFOOD.md filename introduced a new "_DOGFOOD" suffix that didn't match any existing pattern and read like an evidence appendix rather than a design doc. Restructure: - New "Design" section at the top describing what /plan-rollout is, what v0 ships, and what's deferred to v1.1+ - "Dogfood: PR garrytan#1241" section retains the worked example (file breakdown, reader-time estimate, verdict, findings) - New "v1.1 roadmap" section consolidates the four follow-up todos All original dogfood content preserved verbatim under its new section heading. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5fd693e commit 2684677

2 files changed

Lines changed: 188 additions & 148 deletions

File tree

docs/designs/PLAN_ROLLOUT_DOGFOOD.md

Lines changed: 0 additions & 148 deletions
This file was deleted.

docs/designs/PLAN_ROLLOUT_V0.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# PLAN_ROLLOUT_V0 — decomposition-as-artifact
2+
3+
**Status:** SHIPPED (v0.1.0)
4+
**Skill:** `/plan-rollout` (`plan-rollout/SKILL.md.tmpl`)
5+
**Schema:** `docs/SYSTEM_MD.md`
6+
7+
## The problem
8+
9+
LLM-assisted coding compresses implementation by 10-100x. It does not
10+
compress *review*. A reviewer still reads code at human speed. A
11+
2,000-line diff across 15 files becomes unreviewable — scope creep
12+
hides, reviewers skim, bugs ship.
13+
14+
gstack's other planning skills scope or review the *plan*. None ask of
15+
the actual diff: "is this one PR, or several?"
16+
17+
## The design
18+
19+
`/plan-rollout` reads the working diff (committed + staged + unstaged +
20+
untracked) plus `SYSTEM.md` if present, then writes one artifact:
21+
`decomposition.md`. The artifact contains per-slice file lists,
22+
reader-time estimates, dependency edges, and (when `SYSTEM.md` is
23+
present) contract-graph reconciliation flags. It does not split
24+
branches, does not implement, does not push.
25+
26+
The skill is verdict-first. If the diff is one PR's worth, the artifact
27+
says so in one line and stops. False slicing is worse than no slicing.
28+
29+
`SYSTEM.md` is optional. It declares the semantic contract graph —
30+
role-level relationships between components, including `breaks-if` and
31+
`rollout-edge` annotations. Distinct from the package/import graph,
32+
which is discovered at runtime. When present, it sharpens slice
33+
ordering and surfaces coordinated-deploy edges. When absent, the skill
34+
falls back to path heuristics plus light-touch import discovery.
35+
36+
## What v0 ships
37+
38+
| File | Purpose |
39+
|------|---------|
40+
| `plan-rollout/SKILL.md.tmpl` | The skill template (290 lines). |
41+
| `plan-rollout/SKILL.md` | Generated from the template. |
42+
| `docs/SYSTEM_MD.md` | The optional schema spec (215 lines). |
43+
| `docs/designs/PLAN_ROLLOUT_V0.md` | This doc — design + dogfood. |
44+
| `AGENTS.md`, `docs/skills.md` | One-line registry entries. |
45+
46+
Out of v0 scope (deferred):
47+
48+
- `rollout.md` (rollout/rollback strategy + inverse-rollback auto-gen)
49+
- A spill-check skill for in-progress diffs against the declared slice
50+
- Integrations into `/ship` and `/review`
51+
- A `SYSTEM.md` scaffolder
52+
53+
The boundary is intentional. If the primitive doesn't fit gstack,
54+
`git rm -r plan-rollout/ docs/SYSTEM_MD.md docs/designs/PLAN_ROLLOUT_V0.md`
55+
is the entire revert.
56+
57+
## Dogfood: PR #1241
58+
59+
**Target:** [garrytan/gstack#1241](https://github.com/garrytan/gstack/pull/1241)
60+
`fix(ask-user): keep question payloads compact`. 41 files, +661 / -282.
61+
**Operator:** manual walkthrough against the documented Step-by-Step flow.
62+
63+
41 files in one PR is the canonical "one PR or three?" surface — the
64+
most informative test of the verdict logic, even though (spoiler) the
65+
right answer turns out to be one PR.
66+
67+
### File breakdown (skill Step 2)
68+
69+
Bucketed by top-level dir (path-heuristic fallback, no `SYSTEM.md`):
70+
71+
| Bucket | Files | Lines |
72+
|--------|------:|------:|
73+
| `*/SKILL.md` (36 skill regenerations) | 36 | +576 / -252 |
74+
| `scripts/resolvers/preamble/` (the actual fix) | 1 | +16 / -7 |
75+
| `test/fixtures/golden/` (3 golden regenerations) | 3 | +54 / -27 |
76+
| `test/` (2 test files) | 2 | +31 / -3 |
77+
78+
### Reader-time estimate (skill Step 4)
79+
80+
`ceil(943 / 80) + ceil(41 / 5) = 12 + 9 = 21 min`. Under the 30-min cap.
81+
82+
Honest only if you treat the 36 SKILL.md regenerations as skim-time, not
83+
read-time. A reviewer who actually reads each one would burn far longer.
84+
The skill's heuristic does not currently model "mechanical regeneration"
85+
— see Finding 1.
86+
87+
### Verdict the skill should emit
88+
89+
> **This is one PR. No decomposition needed.**
90+
>
91+
> 39 of 41 files are deterministic regenerations of one source change
92+
> (`scripts/resolvers/preamble/generate-ask-user-format.ts`). They are
93+
> not independently shippable — splitting them off would leave Slice 2
94+
> with no standalone value and Slice 1 with broken downstream goldens
95+
> until Slice 2 lands. Boil it.
96+
>
97+
> **Reader guide for the single PR:**
98+
> 1. Read `scripts/resolvers/preamble/generate-ask-user-format.ts`
99+
> (+16 / -7). This is the entire substantive change.
100+
> 2. Spot-check 2-3 of the regenerated `*/SKILL.md` files to verify
101+
> the new format is applied as intended.
102+
> 3. Read `test/resolver-ask-user-format.test.ts` (+22 / -3) and
103+
> `test/gen-skill-docs.test.ts` (+9 / -0). These pin the new
104+
> behavior.
105+
> 4. Goldens (`test/fixtures/golden/*-ship-SKILL.md`) are diff-only;
106+
> skim if curious.
107+
108+
### Findings (v1.1 todos)
109+
110+
**Finding 1 — Path heuristics can't detect "regenerated output."**
111+
112+
Without `SYSTEM.md`, the skill buckets by top-level directory. With this
113+
PR it would produce roughly:
114+
115+
- Slice 0: `scripts/resolvers/preamble/...` (the fix)
116+
- Slice 1: `*/SKILL.md` (the regenerations)
117+
- Slice 2: `test/fixtures/golden/*` (also regenerations)
118+
- Slice 3: `test/*.test.ts` (the tests)
119+
120+
The verdict logic *should* catch this because Slice 1 and Slice 2 have
121+
no import edges back to anything except the build script — they can't
122+
ship before Slice 0. The topological-order check would collapse them.
123+
But the file count is high enough that a naive operator might still
124+
ship "Source fix" + "Regenerated outputs" as two PRs. The skill needs
125+
a deterministic-regeneration detector: if a slice's only diff is
126+
mechanical output of another slice's source change, merge them. v1
127+
doesn't have this.
128+
129+
**Finding 2 — Reader-time is wrong for regeneration-heavy diffs.**
130+
131+
21 minutes is the right number for "skim 36 generated files + read the
132+
source." It would be the wrong number if a reviewer read each
133+
`SKILL.md`. The heuristic treats lines uniformly. A `regen-multiplier`
134+
flag on slices that match build-output patterns
135+
(`*/SKILL.md` adjacent to a build script, `test/fixtures/golden/*`)
136+
would adjust this — v1.1.
137+
138+
**Finding 3 — `SYSTEM.md` wouldn't have helped here.**
139+
140+
A gstack-shaped `SYSTEM.md` with `scripts/resolvers/` marked as a
141+
component and `*/SKILL.md` files marked as `leaf-util` wouldn't have
142+
changed the verdict. The actual signal needed is "this file is a build
143+
output of that file," closer to a Makefile-style dependency than a
144+
contract graph. `SYSTEM.md` is not the right primitive for catching
145+
this. Don't promise it is.
146+
147+
**Finding 4 — The skill needs an `--explain` mode.**
148+
149+
A reviewer looking at the verdict "this is one PR" deserves to see why:
150+
how many files were classified as regeneration, which source change
151+
they depend on, what would happen if you tried to slice anyway. v1's
152+
verdict is a one-liner. v1.1 should print the rejected slicing
153+
alternatives and why they were rejected.
154+
155+
### What v0 got right
156+
157+
- **Verdict-first design.** The skill is structured to ALWAYS output a
158+
verdict line. Even when the right answer is "one PR," the artifact
159+
produces value: a written record of "we looked, and slicing was
160+
considered and rejected because of these signals."
161+
- **Honest about reader-time.** 21 min is the right number under
162+
reasonable skim assumptions. Calibrated for typical PR reading, not
163+
pathological "read every regenerated file."
164+
- **No silent slicing.** The Step 7 self-check ("If the entire diff
165+
fits comfortably in one slice ... say so plainly") catches the case
166+
where naive bucket-counting would propose 3 slices but the verdict
167+
logic should collapse them.
168+
169+
## v1.1 roadmap
170+
171+
1. **Deterministic-regeneration detector.** Heuristic match on filename
172+
patterns (`SKILL.md` adjacent to `SKILL.md.tmpl`,
173+
`test/fixtures/golden/*`) plus an optional `regeneration-of:` field
174+
in `SYSTEM.md`.
175+
2. **Regen-multiplier on reader-time.** Scale regenerated-output line
176+
counts by ~0.1 (skim-reading speed).
177+
3. **`--explain` mode.** When the verdict is "one PR," print the
178+
rejected slicing alternatives and the signals that rejected them.
179+
4. **Calibration loop.** Log predicted vs actual reader-time on the
180+
first ~10 real invocations to ground v2 heuristics in data.
181+
182+
## What v0 proves
183+
184+
The skill is honest about the cases where it can produce useful output
185+
(real multi-component diffs with clear seams) and the cases where it
186+
can't (regeneration-heavy diffs, single-source-fan-out patterns). One
187+
PR's worth of analysis on a real diff caught four real limits worth
188+
fixing in v1.1. That's the bar a skill should clear before shipping.

0 commit comments

Comments
 (0)