@lemoncode/lemony 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -14
- package/catalog/VERSION +1 -1
- package/catalog/agents/architect.md +3 -1
- package/catalog/agents/implementer.md +43 -5
- package/catalog/agents/orchestrator.md +519 -60
- package/catalog/agents/partition.md +316 -0
- package/catalog/agents/reviewer.md +279 -67
- package/catalog/agents/spec-author.md +12 -3
- package/catalog/agents/triage.md +8 -5
- package/catalog/commands/add-capability.md +4 -4
- package/catalog/commands/define.md +7 -0
- package/catalog/commands/hotfix.md +15 -1
- package/catalog/commands/pause.md +5 -0
- package/catalog/commands/resume.md +37 -9
- package/catalog/commands/triage.md +2 -1
- package/catalog/harness.config.schema.json +40 -0
- package/catalog/hooks/lib/merge-pr.sh +699 -0
- package/catalog/skills/mutation-testing/SKILL.md +78 -21
- package/catalog/skills/prd-to-spec/SKILL.md +48 -2
- package/catalog/skills/raise-discovery/SKILL.md +6 -0
- package/catalog/skills/resolve-discovery/SKILL.md +6 -5
- package/catalog/skills/security-review/SKILL.md +119 -6
- package/catalog/skills/spec-to-issue/SKILL.md +7 -1
- package/catalog/skills/task-closeout/SKILL.md +82 -18
- package/catalog/skills/triage-issue/SKILL.md +65 -4
- package/catalog/templates/claude-code/agents.md.tpl +41 -12
- package/catalog/templates/claude-code/harness.config.yml.tpl +33 -0
- package/dist/cli.mjs +737 -36
- package/package.json +10 -6
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Partition — oversized features into independently mergeable parts — Orchestrator companion
|
|
2
|
+
|
|
3
|
+
> Vendor companion to `.claude/agents/orchestrator.md` (the hat). **Read on
|
|
4
|
+
> demand, never at boot**: when a grill closes a PRD that looks like it bundles
|
|
5
|
+
> separable wants (the define's closing question), when RESUME or ORIENT lands on
|
|
6
|
+
> an issue carrying `harness:partition-plan`, or when a sub-agent raises an
|
|
7
|
+
> oversize discovery.
|
|
8
|
+
|
|
9
|
+
The task-fit dial already handles the **floor** — a task too small for the ceremony
|
|
10
|
+
is nudged toward `/triage` or `/bypass`. This companion is the **ceiling**: a
|
|
11
|
+
thorough define can produce one enormous task that, however well its groups are
|
|
12
|
+
cut inside, lands on **one branch and one PR**. When the work splits into several
|
|
13
|
+
**independently mergeable** units, the define should produce several issues —
|
|
14
|
+
each with its own branch, PR, merge gate, and revert — instead of one.
|
|
15
|
+
|
|
16
|
+
## The boundary: an issue is a merge unit
|
|
17
|
+
|
|
18
|
+
- A **group** (a `tasks.md` step header) is review/checkpoint cadence **inside** one
|
|
19
|
+
merge unit: its tasks share a branch, everything lands in one PR, one revert takes
|
|
20
|
+
it all.
|
|
21
|
+
- An **issue** is an **independent merge unit**: its own branch from its base, its
|
|
22
|
+
own PR, merge gate, CI, and revert. Part 1 can be in the default branch while
|
|
23
|
+
Part 2 is being built.
|
|
24
|
+
- **Promotion rule** — a group cut promotes to an issue cut **iff both sides are
|
|
25
|
+
independently mergeable**: each side leaves the default branch green and shippable
|
|
26
|
+
without the other (or with only earlier chain links merged). A cut that cannot
|
|
27
|
+
produce independently mergeable units is **not a partition**; forcing it buys
|
|
28
|
+
stacked-PR pain with no benefit.
|
|
29
|
+
- **Size is the symptom that triggers looking; mergeability is the criterion that
|
|
30
|
+
decides.** A genuinely inseparable monolith is not partitioned — it is accepted as
|
|
31
|
+
one task, or the feature is renegotiated with the human (an honest define outcome).
|
|
32
|
+
- **The partition is a design decision, always proposed to the human**, who
|
|
33
|
+
approves, amends, rejects — or proposes different cuts. Never partition silently.
|
|
34
|
+
|
|
35
|
+
Partition is an **L1** affair: it rides the PRD → task transition of the full-SDD
|
|
36
|
+
round-trip. A triage (L2) task is small by construction and is never partitioned.
|
|
37
|
+
|
|
38
|
+
## When to look — soft heuristics, no threshold
|
|
39
|
+
|
|
40
|
+
Judgment, with named cues and **no binding number** (a mechanical trigger would
|
|
41
|
+
measure something other than what matters):
|
|
42
|
+
|
|
43
|
+
- the PRD bundles **separable wants** — capabilities a user could receive one
|
|
44
|
+
without the other;
|
|
45
|
+
- the natural `tasks.md` grouping would exceed **~4–5 groups**;
|
|
46
|
+
- the grill closed decisions that **don't touch each other** — distinct seams, distinct
|
|
47
|
+
files, distinct risks.
|
|
48
|
+
|
|
49
|
+
The human gate absorbs the imprecision: an over-proposal costs one "no, it goes
|
|
50
|
+
together"; an under-proposal is visible at the spec gate (a huge `tasks.md`), where
|
|
51
|
+
the human can ask. The residual failure — never proposed, never asked — is today's
|
|
52
|
+
behaviour; nothing gets worse.
|
|
53
|
+
|
|
54
|
+
## The closing question of the define
|
|
55
|
+
|
|
56
|
+
After the PRD closes and **before opening the task** (the Orchestrator's §L1
|
|
57
|
+
full-SDD round-trip, between the grill and opening the task):
|
|
58
|
+
|
|
59
|
+
1. **Look.** Weigh the cues above against the PRD's closed decisions — that is where
|
|
60
|
+
the big seams show. No cue fires → continue the round-trip as today, silently.
|
|
61
|
+
There is no question to ask when nothing looks separable.
|
|
62
|
+
2. **Propose, at a glance.** When a cut looks real, build the proposal so it can be
|
|
63
|
+
approved without re-reading the PRD: the slices, what each merges independently
|
|
64
|
+
of, what each cut buys, and the **dependency shape** —
|
|
65
|
+
- **siblings** — each part branches from the default branch, any order;
|
|
66
|
+
- **chain** — part k+1 assumes part k merged;
|
|
67
|
+
- **DAG** — a mix; name the edges.
|
|
68
|
+
|
|
69
|
+
Present it as a compact table (the parent body's `## Plan` below is the shape) and
|
|
70
|
+
ask **one** question: _approve this cut, amend it, reject it (one task as today),
|
|
71
|
+
or propose different cuts?_ This is the closing question of the define
|
|
72
|
+
conversation — one more question inside an existing one, not a new gate.
|
|
73
|
+
|
|
74
|
+
3. **Act on the answer.** Reject → open the single task as today. Approve (or an
|
|
75
|
+
amended cut the human has OK'd) → create the **parent partition-plan issue**
|
|
76
|
+
below, then open **Part 1** as a normal task in this same session (the child
|
|
77
|
+
procedure below) and continue the round-trip from there — Part 1 is the task the
|
|
78
|
+
define hands off.
|
|
79
|
+
|
|
80
|
+
## The parent partition-plan issue
|
|
81
|
+
|
|
82
|
+
One issue per partitioned feature: the feature's cover sheet and its at-a-glance
|
|
83
|
+
state. Create it with `gh issue create` — title `Partition plan — <feature>`, labels
|
|
84
|
+
`harness:managed` + **`harness:partition-plan`**, and **no** `harness:status:*`, no
|
|
85
|
+
`harness:sdd`: it is **not a task**. It never gets a branch, a spec, `progress.md`,
|
|
86
|
+
or an implementation; the label is the mechanical marker that keeps the task-fit
|
|
87
|
+
assessment and RESUME from ever treating it as implementable. Its body:
|
|
88
|
+
|
|
89
|
+
```markdown
|
|
90
|
+
# Partition plan — <feature>
|
|
91
|
+
|
|
92
|
+
PRD: `docs/prds/<topic>-<date>.md`
|
|
93
|
+
|
|
94
|
+
## Plan (approved <YYYY-MM-DD>)
|
|
95
|
+
|
|
96
|
+
| Part | Slice | Merges independently of | Depends on | What the cut buys |
|
|
97
|
+
| ---- | ---------------------- | ----------------------- | -------------- | ----------------- |
|
|
98
|
+
| 1 | <what this part ships> | Parts 2, 3 | — | <the benefit> |
|
|
99
|
+
| 2 | <what this part ships> | Part 3 | Part 1 (chain) | <the benefit> |
|
|
100
|
+
|
|
101
|
+
Dependency shape: <siblings | chain | DAG — the edges are the `Depends on` column>.
|
|
102
|
+
|
|
103
|
+
## Status
|
|
104
|
+
|
|
105
|
+
- [ ] Part 1 — <slice> (not started)
|
|
106
|
+
- [ ] Part 2 — <slice> (not started)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Precondition**: the `harness:partition-plan` label must exist on the remote —
|
|
110
|
+
`install`/`update`/`repair` create it during label sync; an install that predates it
|
|
111
|
+
needs one `lemony repair` first (a raw `gh issue create --label` has no self-heal: `gh`
|
|
112
|
+
fails clean on "label not found", nothing half-created).
|
|
113
|
+
|
|
114
|
+
Each `## Status` row is edited in place with `gh issue edit --body-file` and moves through
|
|
115
|
+
these states: `- [ ] Part <k> — <slice> (not started)` → `- [ ] Part <k> — <slice> → #<id>
|
|
116
|
+
<status at opening>` when the part is opened → `- [x] Part <k> — <slice> → #<id> merged`
|
|
117
|
+
at the part's closeout. A part the human drops (an amendment, or partial abandonment)
|
|
118
|
+
becomes `- [x] Part <k> — <slice> — dropped <YYYY-MM-DD> (<why>)` — **ticked, never
|
|
119
|
+
deleted**, so the close rule below still fires and the plan stays readable as history (a
|
|
120
|
+
drop is recorded in the row alone). Amendments — changes to the cut itself — append to
|
|
121
|
+
`## Plan` as `Amended <YYYY-MM-DD>: <what changed and why>`; never silently rewritten. **The rows are a cache, not the truth**: the middle state is the
|
|
122
|
+
status at opening and is refreshed only at closeout, so before a decision that depends
|
|
123
|
+
on a part's state (sequential vs stacked, which part is next) confirm it against GitHub —
|
|
124
|
+
the child's issue state and its PR (`gh pr view <pr> --json state,mergedAt`). **Every
|
|
125
|
+
edit is read-modify-write**: read the parent body immediately before editing
|
|
126
|
+
(`gh issue view <parent> --json body`), replace only the row(s) you own, write, then
|
|
127
|
+
re-read to confirm your change is present — if another row moved underneath you (two
|
|
128
|
+
siblings closing out on two machines), redo the edit **once** on the fresh body; still
|
|
129
|
+
absent → stop and ask (match rows tolerant of a trailing `\r`: a body edited on the web
|
|
130
|
+
may carry CRLF). A parent whose body has no parseable `## Status` is not yours to guess
|
|
131
|
+
at: stop and ask the human.
|
|
132
|
+
|
|
133
|
+
## Children: normal tasks, opened at their turn
|
|
134
|
+
|
|
135
|
+
A part is opened **when its turn comes**, not at approval — mirroring the lazy spec:
|
|
136
|
+
a row that is never opened is a cheap exit (dropping Part 3 after shipping 1–2
|
|
137
|
+
costs nothing unpaid). Opening a part is the round-trip's "open the task" step
|
|
138
|
+
**exactly as today** — `gh issue create` with the skeleton body, labels
|
|
139
|
+
`harness:managed` + `harness:sdd` + `harness:status:spec-in-progress`, the branch
|
|
140
|
+
`harness/<id>-<slug>` — plus **trace lines at the top of the skeleton body**, which
|
|
141
|
+
the Spec Author's `spec-to-issue` preserves when it replaces the skeleton:
|
|
142
|
+
|
|
143
|
+
```markdown
|
|
144
|
+
Part <k> of #<parent> — <slice>
|
|
145
|
+
Depends on #<sibling> (merged | stacked — assumes it lands as-is)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
(A root part — Part 1, or a sibling with no dependency — carries only the first line.)
|
|
149
|
+
Then update the parent row to `→ #<id> spec-in-progress`. From here the child's
|
|
150
|
+
lifecycle — `harness:status:*` labels, spec gate, implementation, review, merge
|
|
151
|
+
gate, closeout — is **unchanged**.
|
|
152
|
+
|
|
153
|
+
**The spec is authored lazily, at the part's turn**, from the PRD (the shared truth)
|
|
154
|
+
plus the part's **effective base** — the default branch, or, when stacked, the
|
|
155
|
+
previous part's head. Hand the Spec Author, by reference: the PRD path, the parent
|
|
156
|
+
issue, the part's row (its slice), and the effective base. The spec covers **that
|
|
157
|
+
slice only**; PRD decisions outside it are constraints, not scope. No spec exists
|
|
158
|
+
for a part before its turn, so an earlier part's landing can never invalidate one.
|
|
159
|
+
|
|
160
|
+
## Starting the next part: re-validate the cut
|
|
161
|
+
|
|
162
|
+
At each part's start, **before** opening its issue, re-read the parent and check the cut **against the current base** (cheap): do the remaining
|
|
163
|
+
slices still merge independently? Did an earlier part absorb or obsolete a later
|
|
164
|
+
slice? Did a review move the seam? The cut holds → open the part. It doesn't →
|
|
165
|
+
present the amendment to the human — the plan is theirs, changing it needs their
|
|
166
|
+
OK — and only then edit the parent (`Amended …` line + the `## Status` rows). What
|
|
167
|
+
can be invalidated is the **plan**; the per-part specs don't exist yet.
|
|
168
|
+
|
|
169
|
+
## Chain start modes — part k+1 while part k is unmerged
|
|
170
|
+
|
|
171
|
+
When the next part's dependency k is at **`in-review`** (its PR open — e.g. waiting on
|
|
172
|
+
another human's merge), the human chooses how to start — ask, don't assume. An earlier k
|
|
173
|
+
(`spec-in-progress`, `in-progress`) has nothing to stack on: there is nothing to start;
|
|
174
|
+
offer to resume it (`/resume #<k-id>`) in this session. A k already merged
|
|
175
|
+
(closeout parked or not — confirm on GitHub) makes k+1 an ordinary sequential part.
|
|
176
|
+
|
|
177
|
+
- **Sequential post-merge** (the safe default): part k+1 starts when part k is in the
|
|
178
|
+
default branch. Nothing special.
|
|
179
|
+
- **Stacked start** (an explicit human choice, with **the assumption named at choice
|
|
180
|
+
time**: stacking bets that part k lands substantially as-is — if k's review forces
|
|
181
|
+
big changes, k+1 is built on sand; the developer takes that bet informed):
|
|
182
|
+
- branch from **k's head**:
|
|
183
|
+
`git fetch && git checkout -b harness/<id>-<slug> origin/harness/<k-id>-<k-slug>`;
|
|
184
|
+
- the lazy spec is authored against the effective base = PRD + k's head;
|
|
185
|
+
- at the review step, while k is still unmerged, the PR targets **k's branch as base**
|
|
186
|
+
— `gh pr create --base harness/<k-id>-<k-slug>` — and the Reviewer is handed **that
|
|
187
|
+
base** for its stale-approve record (the record's base is the PR's base **at review
|
|
188
|
+
time**; a later base change is not by itself a content change — the landing move
|
|
189
|
+
below); if k
|
|
190
|
+
has merged by then, do the landing move below first and open the PR against the
|
|
191
|
+
default branch as usual (`gh pr create --base` on a deleted branch fails);
|
|
192
|
+
- updates from k flow by **merging in, never rebasing** — a rebase needs a force-push on
|
|
193
|
+
a task branch (human-gated by house rules); merge is uglier history but safe. While k
|
|
194
|
+
is unmerged the source is `origin/harness/<k-id>-<k-slug>`. The merge-in is **your**
|
|
195
|
+
move at a checkpoint boundary (or the Implementer's on re-invoke, named in the spawn
|
|
196
|
+
prompt), never inside a staging save-point; under pre-commit review ON it goes right
|
|
197
|
+
after a checkpoint OK commit;
|
|
198
|
+
- record it in the child's trace line (`stacked — assumes it lands as-is`) and the
|
|
199
|
+
parent row (`→ #<id> spec-in-progress (stacked on #<k-id>)` — the status at opening,
|
|
200
|
+
as every row).
|
|
201
|
+
|
|
202
|
+
**The landing move — once k is merged (confirmed on GitHub, never inferred from the PR
|
|
203
|
+
base), at the next boundary the merge-in rule above allows:** (1) if k+1's PR still
|
|
204
|
+
targets `harness/<k-id>-…`, **retarget it
|
|
205
|
+
yourself** — `gh pr edit <pr> --base <default>` (the platform's automatic retarget
|
|
206
|
+
fires only when k's branch is deleted, whenever that happens — at k's closeout finalize,
|
|
207
|
+
or at once if the human merged with auto-delete; do not depend on it either way); (2)
|
|
208
|
+
`git fetch && git merge origin/<default>` into k+1 and push — the executor squashes, so
|
|
209
|
+
k's commits are not ancestors of the default branch and without this merge-in k+1's
|
|
210
|
+
merge-base is the old fork point and the stale-approve guard sees k's content as
|
|
211
|
+
unreviewed; k's squashed changes reconcile as identical hunks; (3) update the child's
|
|
212
|
+
trace line to `Depends on #<k-id> (merged)`. Do this **before** the (re-)review whenever
|
|
213
|
+
k has already merged, so review and gate share a base. The merge-in is an
|
|
214
|
+
**update-branch**: a standing APPROVE stays valid unless the PR's own diff against the
|
|
215
|
+
new base changed (a hand-resolved conflict touched k+1's hunks) — then route to
|
|
216
|
+
re-review; otherwise run the executor and let its stale-approve guard arbitrate.
|
|
217
|
+
|
|
218
|
+
**Merge-gate invariant: a part reaches its merge gate only when its PR base is the
|
|
219
|
+
default branch.** Before surfacing the gate of a stacked child — live, or on a
|
|
220
|
+
`/resume` of an `in-review` one — check `gh pr view <pr> --json baseRefName`. Base still
|
|
221
|
+
`harness/<k-id>-…` and k unmerged → k+1 **waits at `in-review`**, and say so to the
|
|
222
|
+
human: _"Part k+1 is approved but stacked on #<k-id>, still unmerged — it waits; don't
|
|
223
|
+
merge it in the GitHub UI, its base is k's branch"_ (the rule binds your merge; the
|
|
224
|
+
human's click needs the warning). Never merge a part into a sibling's branch: the code
|
|
225
|
+
would never reach the default branch, `Closes #<id>` would not fire, and closeout would
|
|
226
|
+
archive a task that never landed. k merged → the landing move above, then surface the
|
|
227
|
+
gate.
|
|
228
|
+
|
|
229
|
+
If k's review does force big changes, surface it at once — the human decides:
|
|
230
|
+
rework k+1 on the new k, wait, or drop it.
|
|
231
|
+
|
|
232
|
+
## The discovery safety net
|
|
233
|
+
|
|
234
|
+
The primary split happens at the PRD → task transition, where no artifacts exist yet
|
|
235
|
+
to restructure. The safety net is the existing discovery machinery: when the **Spec
|
|
236
|
+
Author** (structuring a child) or an **Implementer** (mid-flight) finds the scope
|
|
237
|
+
hides **≥2 independently mergeable units the PRD didn't reveal**, that is a
|
|
238
|
+
legitimate discovery — raised with `raise-discovery` as **T2 UNSPECIFIED_DECISION**
|
|
239
|
+
(the plan is silent on the cut; partition or keep-together is the human's call) and
|
|
240
|
+
mediated with `resolve-discovery` as any other (the Orchestrator's §Discovery
|
|
241
|
+
mediation). On **"keep together"**: record the resolution and resume. On
|
|
242
|
+
**"partition"** in an L1 task the current task keeps the **first** unit and you run, in
|
|
243
|
+
this order:
|
|
244
|
+
|
|
245
|
+
1. **Ask the second half in the same mediation** — later-unit work already on the branch
|
|
246
|
+
(commits; under pre-commit review ON, staged save-points): keep it or drop it? Name
|
|
247
|
+
the commits. (A second fork that only exists because of the first answer: record it in
|
|
248
|
+
the same `**Resolution**` block, no second entry.)
|
|
249
|
+
2. **Create the parent** partition-plan issue with the current task as Part 1 (row
|
|
250
|
+
`→ #<id> <paused_from>` — `in-progress`, or `spec-in-progress` when the Spec Author
|
|
251
|
+
raised it) and the remaining units as later parts.
|
|
252
|
+
3. **Add the trace lines at the top of the child's issue body yourself**
|
|
253
|
+
(read-modify-write; the body is the externalized spec — or still the skeleton, when
|
|
254
|
+
the Spec Author raised it at spec time).
|
|
255
|
+
4. **Route the narrowing to the Spec Author** (`resolve-discovery` step 3, with the
|
|
256
|
+
decision and the parent row): it narrows the spec to the slice and re-runs
|
|
257
|
+
`spec-to-issue`, which preserves the trace lines you just added. In step-by-step mode
|
|
258
|
+
the narrowed `tasks.md` is re-presented at the next checkpoint — no new gate.
|
|
259
|
+
5. **Record and resume**: the Implementer re-invoke carries the keep/drop answer — it
|
|
260
|
+
performs the `git revert`s by commit (never a force-push), or discards the staged
|
|
261
|
+
later-unit changes under pre-commit review ON — and resumes on the narrowed slice.
|
|
262
|
+
|
|
263
|
+
On an **L2 (triage) task** — no PRD — "partition" means the task was mis-levelled: keep
|
|
264
|
+
the triage on its first unit (you narrow its fix plan in the issue body, read-modify-write)
|
|
265
|
+
and capture the rest as `/spinoff` stubs (or a `/define` when it is a real feature); **no
|
|
266
|
+
parent is opened** — the parent/part mechanics are L1-only. Never partition silently from
|
|
267
|
+
inside a task.
|
|
268
|
+
|
|
269
|
+
## RESUME and ORIENT on a partition parent
|
|
270
|
+
|
|
271
|
+
The queue listing `/resume` runs with no args includes
|
|
272
|
+
`gh issue list -l harness:partition-plan`. An open parent with unticked rows
|
|
273
|
+
surfaces as **"partition in progress: next part per the plan — Part <k>: <slice>"**, or
|
|
274
|
+
as **"partition in progress — waiting on #<id> (Part <j>)"** when the next row is blocked
|
|
275
|
+
by an in-flight child (add `, in-review — stacked start possible` when that child's PR is
|
|
276
|
+
open). The next part is the first row still **`(not started)`** whose
|
|
277
|
+
`Depends on` parts are merged — confirmed on GitHub, not from the row
|
|
278
|
+
(`gh issue view <id> --json state` and the child's PR, recovered from its branch
|
|
279
|
+
`harness/<id>-*`) — or at `in-review`, when the human takes a stacked start (above). A
|
|
280
|
+
row carrying `→ #<id>` is an **in-flight child, never re-opened**: it resumes **as today**
|
|
281
|
+
by its own id — offer to resume it (`/resume #<id>`) in this session; the parent is only
|
|
282
|
+
the map. If that child's issue is closed and its PR merged, the row missed its closeout
|
|
283
|
+
tick: if its
|
|
284
|
+
closeout never ran (label still `in-review`, no `_archive/<id>/` on the base) run
|
|
285
|
+
`task-closeout` for it first — it ticks the row itself; otherwise tick it now (and close
|
|
286
|
+
the parent if that was the last row) and move on. **No eligible row → nothing to start
|
|
287
|
+
from the parent**: say so, name the blocking child,
|
|
288
|
+
offer to resume it. Resuming the parent itself means **starting the next part**: the
|
|
289
|
+
re-validation above, then the child procedure, then the round-trip continues from its
|
|
290
|
+
UI-design gate and Spec Author dispatch onward, unchanged.
|
|
291
|
+
|
|
292
|
+
## Closing the parent
|
|
293
|
+
|
|
294
|
+
- **Mechanical, at the last child's closeout.** `task-closeout`'s finalize step, on
|
|
295
|
+
a task whose body carries `Part <k> of #<parent>`, ticks that row and — when every row
|
|
296
|
+
is ticked, merged or dropped — closes the parent with a summary comment. No human
|
|
297
|
+
prompt: each merge already passed the human gate. The skill owns the mechanics
|
|
298
|
+
(read-modify-write, idempotent on a retried finalize, closed-parent no-op).
|
|
299
|
+
- **Partial abandonment — a human close.** When the human drops the remaining
|
|
300
|
+
parts, mark their rows dropped and close the parent yourself recording what shipped
|
|
301
|
+
and what was dropped and why
|
|
302
|
+
(`gh issue close <parent> --comment "Shipped: parts … · Dropped: parts … — <why>"`).
|
|
303
|
+
Unopened rows cost nothing. An opened-but-unmerged child that is dropped is closed
|
|
304
|
+
like any abandoned task: close its issue with a comment recording the drop, delete
|
|
305
|
+
its branch, no closeout (there is nothing merged to record).
|
|
306
|
+
|
|
307
|
+
## Human touchpoints — zero new gate machinery
|
|
308
|
+
|
|
309
|
+
1. **Partition approval** — the only new touch: one more question at the define's
|
|
310
|
+
close (cuts + dependency shape).
|
|
311
|
+
2. **Spec gate per child** — unchanged, at each child's turn.
|
|
312
|
+
3. **Stacked-start choice** — with the assumption named.
|
|
313
|
+
4. **Plan amendments** — re-validation or discovery → presented, human approves.
|
|
314
|
+
5. **Abandonment / parent close** — human; the mechanical close rides the last
|
|
315
|
+
merge gate.
|
|
316
|
+
6. **Merge gates per child** — unchanged.
|