@rallycry/conveyor-skills 0.1.4 → 1.0.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 -5
- package/package.json +1 -1
- package/skills/conveyor-build/SKILL.md +262 -0
- package/skills/conveyor-build/references/pack-path.md +224 -0
- package/skills/conveyor-build/references/task-path.md +67 -0
- package/skills/conveyor-consensus/SKILL.md +99 -0
- package/skills/conveyor-consensus/references/doc-template.html +204 -0
- package/skills/conveyor-local-loop/SKILL.md +34 -41
- package/skills/conveyor-meeting-review/SKILL.md +72 -0
- package/skills/conveyor-plan/SKILL.md +85 -12
- package/skills/conveyor-plan/references/plan-format.md +79 -3
- package/skills/conveyor-review/SKILL.md +161 -0
- package/skills/conveyor-start/SKILL.md +106 -0
- package/skills/conveyor-triage/SKILL.md +174 -0
- package/skills/conveyor-workflows/SKILL.md +31 -7
- package/skills/conveyor-local-pack/SKILL.md +0 -223
- package/skills/conveyor-local-task/SKILL.md +0 -92
package/README.md
CHANGED
|
@@ -3,19 +3,33 @@
|
|
|
3
3
|
Shared [Claude Code skills](https://code.claude.com/docs) for projects managed
|
|
4
4
|
with [Conveyor](https://github.com/rallycry/conveyor). Installing this package
|
|
5
5
|
and linking it once gives every Claude Code session in your repo the Conveyor
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
lifecycle verbs — **`/conveyor-plan` → `/conveyor-start` → `/conveyor-build` →
|
|
7
|
+
`/conveyor-review`** — plus triage and the local loop. Updates arrive through
|
|
8
|
+
normal dependency bumps: no git submodules, no manual syncing.
|
|
8
9
|
|
|
9
10
|
## Skills
|
|
10
11
|
|
|
11
12
|
| Skill | Invoke | What it does |
|
|
12
13
|
| --- | --- | --- |
|
|
13
14
|
| `conveyor-workflows` | auto-triggers on Conveyor questions | The guide: connect/repair the MCP, create and classify cards, packs, builds, the two PR paths, review flows, reliability gotchas |
|
|
14
|
-
| `conveyor-
|
|
15
|
-
| `conveyor-
|
|
16
|
-
| `conveyor-
|
|
15
|
+
| `conveyor-triage` | `/conveyor-triage <card>` | Investigate an unverified report to a named root cause, then hand off a planned card |
|
|
16
|
+
| `conveyor-plan` | `/conveyor-plan <idea>` | Research an idea into a context-free, immediately-buildable plan on a Conveyor card |
|
|
17
|
+
| `conveyor-start` | `/conveyor-start <card>` | Hand a planned card to a cloud pod, confirm the environment came up, report where to watch it (local surface only) |
|
|
18
|
+
| `conveyor-build` | `/conveyor-build <card>` | Execute a planned card to a PR — one task or a whole feature-branch pack |
|
|
19
|
+
| `conveyor-review` | `/conveyor-review <card>` | Review the PR against its plan and render one verdict, with risk |
|
|
20
|
+
| `conveyor-consensus` | `/conveyor-consensus <question>` | Sweep the sources a project actually has, count what happened, score the proposals against those counts, and attach an HTML verdict to the card |
|
|
17
21
|
| `conveyor-local-loop` | `/loop /conveyor-local-loop` | Run this machine as a serial local agent: claim Open cards and packs, build to PR, repeat |
|
|
18
22
|
|
|
23
|
+
**One skill per lifecycle phase:** triage an unverified report → plan the work →
|
|
24
|
+
start it in the cloud *or* build it here → review it. `start` and `build` are
|
|
25
|
+
the same phase reached two ways — hand it off, or do it in this checkout. Each reads identically in a cloud pod and a local
|
|
26
|
+
checkout; where the two environments genuinely differ — which verdict tools
|
|
27
|
+
exist, which log tooling is reachable, whether `create_pull_request` pushes for
|
|
28
|
+
you — the skill says so inline rather than assuming.
|
|
29
|
+
|
|
30
|
+
An incident goes through `conveyor-triage` **before** `conveyor-plan`: planning
|
|
31
|
+
a fix from a reported symptom is how the wrong thing gets built confidently.
|
|
32
|
+
|
|
19
33
|
## Install (once per repo)
|
|
20
34
|
|
|
21
35
|
```bash
|
package/package.json
CHANGED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: conveyor-build
|
|
3
|
+
description: Execute a planned Conveyor card to a pull request — one task or a whole feature-branch pack — then stay wake-able for review feedback and CI. Use when the user says "/conveyor-build <card>", "build this card", "implement this card", "run this pack", or when a claudespace session is told to follow its card's plan. Works identically in a cloud pod and in a local checkout; the card is the spec and task chat is the log. For producing the plan in the first place use conveyor-plan; to work a whole queue of Open cards use conveyor-local-loop.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Conveyor Build
|
|
7
|
+
|
|
8
|
+
Take a card that already has a plan and drive it to a pull request, then stay
|
|
9
|
+
reachable for review feedback and CI. The card IS the spec, task chat is the
|
|
10
|
+
log, and the host repo's CLAUDE.md governs gates, verification, and PR
|
|
11
|
+
mechanics. This skill adds routing, claiming, and the pack chain.
|
|
12
|
+
|
|
13
|
+
**One skill, two environments.** Everything below applies in a cloud pod and in
|
|
14
|
+
a local checkout alike. Where they genuinely differ, the difference is called
|
|
15
|
+
out in an **Environment** note — never assume; check which one you are in.
|
|
16
|
+
|
|
17
|
+
## Ground rules
|
|
18
|
+
|
|
19
|
+
- **Conveyor is the state store.** A build spans hours or days and the session
|
|
20
|
+
gets compacted. Re-derive state from `mcp__conveyor__get_task` +
|
|
21
|
+
`mcp__conveyor__list_subtasks` at every decision point, never from
|
|
22
|
+
conversation memory.
|
|
23
|
+
- **All Conveyor tools fully-qualified** — `mcp__conveyor__get_task`, not
|
|
24
|
+
`get_task`. Bare names fail.
|
|
25
|
+
- **The card must stand alone.** If you find yourself relying on session
|
|
26
|
+
memory or on this conversation, stop and re-read the card. A plan that fails
|
|
27
|
+
the context-free-reader bar is a blocker, not something to wing: post what is
|
|
28
|
+
missing to chat and stop.
|
|
29
|
+
- **Never approve or merge your own PR into `dev`.** Finish line = the card in
|
|
30
|
+
ReviewPR with CI started. The exception is narrow and lives in the pack path:
|
|
31
|
+
you ARE the reviewer of record for a pack's CHILD PRs into the pack branch,
|
|
32
|
+
because the automated reviewer skips those.
|
|
33
|
+
- **Never boot another environment for work you are doing.** Locally that
|
|
34
|
+
means never `mcp__conveyor__start_task` (it exists only on the local/MCP
|
|
35
|
+
surface, and it spawns a cloud pod that duplicates you). In a pod driving a
|
|
36
|
+
pack it means never `mcp__conveyor__start_child_cloud_build` /
|
|
37
|
+
`mcp__conveyor__stop_child_build` — you implement the children yourself,
|
|
38
|
+
serially. Parallel fan-out is a deliberate choice the user makes by pressing
|
|
39
|
+
Build on the parent, not something a build session opts into.
|
|
40
|
+
|
|
41
|
+
## Environment
|
|
42
|
+
|
|
43
|
+
Resolve which one you are in before touching git or the filesystem.
|
|
44
|
+
`mcp__conveyor__get_connection_context` answers it: a pod session reports a
|
|
45
|
+
task binding and no user account.
|
|
46
|
+
|
|
47
|
+
**In a pod:**
|
|
48
|
+
|
|
49
|
+
- Uncommitted work is auto-snapshotted to `conveyor-wip/<branch>` after every
|
|
50
|
+
turn, so a sleep or crash does not lose the tree. Commit and push anyway as
|
|
51
|
+
soon as a chunk is coherent — committed work never depends on that mechanism.
|
|
52
|
+
- `mcp__conveyor__create_pull_request` stages, commits, and pushes for you.
|
|
53
|
+
- Capture UI evidence with the repo's own harness (in this repo,
|
|
54
|
+
`scripts/agent/shot.ts`) and attach with `mcp__conveyor__upload_attachment`
|
|
55
|
+
before opening the PR.
|
|
56
|
+
- The database and dev server belong to this pod alone — experiment freely.
|
|
57
|
+
|
|
58
|
+
**Locally:**
|
|
59
|
+
|
|
60
|
+
- There is NO WIP autosync. Committed-and-pushed is the only durable state:
|
|
61
|
+
push the branch (`-u origin`) the moment it exists, and always before a long
|
|
62
|
+
background job or a wait.
|
|
63
|
+
- `mcp__conveyor__create_pull_request` opens a PR for a branch you have ALREADY
|
|
64
|
+
pushed. Push first.
|
|
65
|
+
- Work in the main checkout, **never a git worktree** — the provisioned
|
|
66
|
+
workspace (installed dependencies, env/direnv auth wiring, a running dev
|
|
67
|
+
stack) is the entire value of local execution, and worktrees have none of it.
|
|
68
|
+
A dirty `git status` before any branch switch is a hard stop: report and let
|
|
69
|
+
the user commit or stash. Do not solve it with a second checkout.
|
|
70
|
+
- The dev database and dev-server ports are shared with the user's own
|
|
71
|
+
sessions. No destructive experiments, never reset the dev DB, and reuse a
|
|
72
|
+
running dev stack rather than fighting over ports.
|
|
73
|
+
|
|
74
|
+
## Resolve and route
|
|
75
|
+
|
|
76
|
+
1. Resolve the card from the argument — slug, id, or URL. **None given → ask
|
|
77
|
+
which card.** Never infer one from the branch you happen to be on.
|
|
78
|
+
2. `mcp__conveyor__get_task` for the full plan and
|
|
79
|
+
`mcp__conveyor__read_task_chat` for addenda and user answers. Consult
|
|
80
|
+
`mcp__conveyor__get_tag` on the card's tags before diving in — a tag's
|
|
81
|
+
overview and linked files are the fast path into the subsystem.
|
|
82
|
+
3. Route on the card's shape:
|
|
83
|
+
|
|
84
|
+
| Card shape | Path |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| No children | **Task path** — [references/task-path.md](references/task-path.md) |
|
|
87
|
+
| Has children, children PR into a **feature branch** | **Pack path** — [references/pack-path.md](references/pack-path.md) |
|
|
88
|
+
| Has children that PR straight into `dev` | Not a pack chain. Build the children one at a time via the task path; leave the parent alone. |
|
|
89
|
+
| Has a `parentTaskId` | Task path, but **only while the parent is parked** (neither InProgress nor ReviewPR). The child's base is the parent's feature branch, never `dev`. |
|
|
90
|
+
|
|
91
|
+
> **Environment — a pod's pack runs one branch, not one branch per child.** The
|
|
92
|
+
> pod's `create_pull_request` takes no task argument: it always opens the PR for
|
|
93
|
+
> the card the session is bound to. A pod bound to the pack PARENT therefore
|
|
94
|
+
> cannot open a CHILD's pull request, and must not try. It implements each child
|
|
95
|
+
> directly on the pack branch, commits per child, moves the child's status with
|
|
96
|
+
> `mcp__conveyor__update_task` (`task_id` + `status`), and opens exactly ONE pull
|
|
97
|
+
> request at the end — the parent's, into `dev`.
|
|
98
|
+
>
|
|
99
|
+
> **Locally** each child gets its own branch and its own PR into the pack
|
|
100
|
+
> branch, which is what makes them individually reviewable. Read the pack path
|
|
101
|
+
> with that substitution in mind: everywhere it says "the child's PR", a pod
|
|
102
|
+
> means "the child's commits on the pack branch", and the merge step becomes a
|
|
103
|
+
> status write rather than a merge.
|
|
104
|
+
|
|
105
|
+
**The parked-parent rule is load-bearing, not bookkeeping.** An actively
|
|
106
|
+
orchestrating parent reads a headless InProgress child as a dead agent
|
|
107
|
+
environment and "recovers" it onto a cloud pod — duplicate implementation of
|
|
108
|
+
the same child. If the parent is InProgress or ReviewPR, decline the child and
|
|
109
|
+
say why.
|
|
110
|
+
|
|
111
|
+
## Claim
|
|
112
|
+
|
|
113
|
+
Re-confirm the card is still claimable, then `mcp__conveyor__update_task` →
|
|
114
|
+
`status: "InProgress"`, then `mcp__conveyor__post_to_chat` with a claim marker
|
|
115
|
+
naming where you are running. Status changed under you → someone else took it;
|
|
116
|
+
stop.
|
|
117
|
+
|
|
118
|
+
**A pack parent is claimed differently** — see the pack path. The parent stays
|
|
119
|
+
parked and the chat marker IS the claim.
|
|
120
|
+
|
|
121
|
+
## Work the plan
|
|
122
|
+
|
|
123
|
+
Post to chat at real milestones only — claim, a blocking discovery, gates
|
|
124
|
+
green, PR — never play-by-play. Your turn output is not visible to the team;
|
|
125
|
+
chat is.
|
|
126
|
+
|
|
127
|
+
**Saving the plan and card fields:** `mcp__conveyor__update_task` handles
|
|
128
|
+
title, description, plan, status, and `githubBranch` on both surfaces. Story
|
|
129
|
+
points and risk are the one split: the local `update_task` carries them, the
|
|
130
|
+
pod's does not — in a pod they go through
|
|
131
|
+
`mcp__conveyor__update_task_properties`. Correct them when the work turns out
|
|
132
|
+
materially bigger or smaller than the estimate, in either direction; a stale
|
|
133
|
+
estimate is worse than a corrected one. Never re-size a card to make a gate, a
|
|
134
|
+
transition, or a review pass.
|
|
135
|
+
|
|
136
|
+
> **Environment — exiting plan mode in a pod.** A pod in discovery mode cannot
|
|
137
|
+
> leave plan mode until the card has a plan, a title, story points, AND a risk
|
|
138
|
+
> level. `update_task` carries neither of the last two, so that step needs
|
|
139
|
+
> `mcp__conveyor__update_task_properties`. A pod exposes it in `discovery`,
|
|
140
|
+
> `auto`, `building` and `chat` modes — but NOT in `review`, and not to a pack
|
|
141
|
+
> parent. If you hold neither tool, you are not the session that is supposed to
|
|
142
|
+
> be sizing the card: say so in chat rather than trying to force the transition.
|
|
143
|
+
|
|
144
|
+
## Verify
|
|
145
|
+
|
|
146
|
+
Follow the host repo's CLAUDE.md verification policy — scope the gates to your
|
|
147
|
+
diff rather than running everything. Never open a PR with known-failing gates,
|
|
148
|
+
and never silence a failure with a filter, a `.skip`, or a "known flake" note:
|
|
149
|
+
either your diff broke it, or the test is broken or environment-dependent and
|
|
150
|
+
you fix the test.
|
|
151
|
+
|
|
152
|
+
**A UI-visible change needs visual proof before the PR**, in both environments:
|
|
153
|
+
capture a screenshot (static) or a short recording (interaction) with the host
|
|
154
|
+
repo's own tooling and attach it with `mcp__conveyor__upload_attachment`, then
|
|
155
|
+
embed the returned URL in the PR body. A UI PR without it is incomplete.
|
|
156
|
+
|
|
157
|
+
**On a deep pack the gate surface grows, and that is expected.**
|
|
158
|
+
`test:affected` diffs against `origin/dev`, so by the fourth child it also
|
|
159
|
+
covers the three already merged into the pack branch. That is correct
|
|
160
|
+
behavior — do not go looking for why "unrelated" tests are running.
|
|
161
|
+
|
|
162
|
+
> **Repo config, not an environment difference — check it, don't assume it.**
|
|
163
|
+
> Where CI is configured to run only on PRs into `dev`/`main` (this is the
|
|
164
|
+
> Conveyor repo's config), a child PR into a pack branch gets **no automated
|
|
165
|
+
> verification at all**, and your local gate pass is the ONLY gate before that
|
|
166
|
+
> child merges — mandatory, never skippable. A consumer repo may trigger CI
|
|
167
|
+
> more broadly; if it does, let CI finish before merging. Confirm which case
|
|
168
|
+
> you are in rather than assuming, since the two lead to opposite behavior.
|
|
169
|
+
|
|
170
|
+
## Not every task ends in a PR
|
|
171
|
+
|
|
172
|
+
`create_pull_request` is for work that changes code. Plenty of cards don't:
|
|
173
|
+
support requests, config or credential help, answering a question,
|
|
174
|
+
investigations, research whose deliverable is an answer or a file.
|
|
175
|
+
|
|
176
|
+
If you finish with **no code changes** — an empty `git diff <base>..HEAD` —
|
|
177
|
+
do NOT open a PR. An empty or throwaway PR exists only so a human can close it.
|
|
178
|
+
Instead: post the answer, config, or findings with
|
|
179
|
+
`mcp__conveyor__post_to_chat`, attach anything the user should keep with
|
|
180
|
+
`mcp__conveyor__upload_attachment` (any file type, up to 25MB), and complete
|
|
181
|
+
the card directly with `force_update_task_status("Complete")` — there is no PR
|
|
182
|
+
or review step for a no-code task. Never publish a deliverable as an off-card
|
|
183
|
+
link; the card is where it belongs.
|
|
184
|
+
|
|
185
|
+
When unsure, check the diff: a real diff means open a PR, no diff means finish
|
|
186
|
+
in chat and mark it Complete.
|
|
187
|
+
|
|
188
|
+
## Open the PR
|
|
189
|
+
|
|
190
|
+
Refresh against the card's base first, then gate, then open — in that order, so
|
|
191
|
+
nothing invalidates the verification you just did:
|
|
192
|
+
|
|
193
|
+
1. `git fetch origin <base> && git merge origin/<base> --no-edit`
|
|
194
|
+
2. One verification pass, scoped to the diff.
|
|
195
|
+
3. `mcp__conveyor__create_pull_request`, naming the base branch **explicitly**.
|
|
196
|
+
**The two surfaces spell these differently and unknown keys are silently
|
|
197
|
+
dropped, not rejected** — locally it is `head:` / `base:`; in a pod it is
|
|
198
|
+
`branch:` / `baseBranch:`. Passing the local names in a pod does not error,
|
|
199
|
+
it just leaves the base unset, and the server then falls back to the base
|
|
200
|
+
recorded on the card. That fallback is usually right and is exactly why the
|
|
201
|
+
mistake is invisible — until the card's recorded branch has drifted, and the
|
|
202
|
+
PR opens against `dev`.
|
|
203
|
+
4. **Publish the PR guide** with `mcp__conveyor__publish_review_guide`, right
|
|
204
|
+
after `create_pull_request` succeeds — it is part of opening a PR, not a
|
|
205
|
+
follow-up. `sections` is a top-level array argument, not prose stuffed into
|
|
206
|
+
`overview`; keep `overview` a short intro and order the sections with core
|
|
207
|
+
behavior first, tests and generated files later. Reference only files this
|
|
208
|
+
diff actually changed, never context you merely read. Anchors are optional
|
|
209
|
+
and strict — `{"path": "..."}` alone is the safe form. Republish for the new
|
|
210
|
+
head SHA after any later push, or the card's Guide tab shows stale. It is
|
|
211
|
+
best-effort: if it still fails after one corrected retry, carry on — it
|
|
212
|
+
never blocks opening or updating the PR.
|
|
213
|
+
5. Post a chat summary: what shipped, how it was verified, what a reviewer
|
|
214
|
+
should look at, and anything you did NOT do.
|
|
215
|
+
|
|
216
|
+
Then confirm CI actually started (read-only `gh pr checks`). Do not wait on it.
|
|
217
|
+
|
|
218
|
+
**Do not re-merge the base and do not re-run a gate that already passed.** If
|
|
219
|
+
the base moved while the gates ran, open the PR anyway — CI validates against
|
|
220
|
+
the merged base.
|
|
221
|
+
|
|
222
|
+
## Aftercare
|
|
223
|
+
|
|
224
|
+
The card is in ReviewPR. What happens next depends on who is driving:
|
|
225
|
+
|
|
226
|
+
> **Environment — a pod is woken; a standalone local run is not.** In a **pod**
|
|
227
|
+
> you stay wake-able: the system wakes you on CI results and review comments,
|
|
228
|
+
> so go idle rather than polling. In a **standalone local run** there is no
|
|
229
|
+
> wake mechanism — report the card and PR state to the user and STOP. No
|
|
230
|
+
> pacing, no loop, no babysitting; a follow-up CI fix is a fresh ask. Under
|
|
231
|
+
> `conveyor-local-loop` the loop's own Babysit tier owns aftercare instead, and
|
|
232
|
+
> its pacing rules govern.
|
|
233
|
+
|
|
234
|
+
When you are the one handling it:
|
|
235
|
+
|
|
236
|
+
- **Red CI** → fix it now, on the same branch. Read the failure before
|
|
237
|
+
concluding it is yours: a suite that fails on a file your diff never touched
|
|
238
|
+
is usually environment-dependent, and the honest fix is to the test, in the
|
|
239
|
+
same PR or a dedicated one.
|
|
240
|
+
- **Review comments or requested changes** → address them, then reply saying
|
|
241
|
+
what changed.
|
|
242
|
+
- **Green and quiet** → leave it alone. Do not poll.
|
|
243
|
+
|
|
244
|
+
## Blocked
|
|
245
|
+
|
|
246
|
+
After two genuinely different failed approaches, or on a decision only the user
|
|
247
|
+
can make: post the reason AND the specific question to chat, set the card back
|
|
248
|
+
to `"Open"`, restore the tree (locally, `git checkout dev` — leaving a shared
|
|
249
|
+
checkout parked on an abandoned feature branch is how the next session starts
|
|
250
|
+
from the wrong base), and stop. A vague "this is hard" is not a handoff; the
|
|
251
|
+
question is what makes it one.
|
|
252
|
+
|
|
253
|
+
**A thin plan is a different case, and it does not stop a pack.** A card whose
|
|
254
|
+
plan fails the context-free-reader bar: post what is missing to its chat and
|
|
255
|
+
stop — but inside a pack, skip that child and take the next ready one instead
|
|
256
|
+
of halting the whole chain.
|
|
257
|
+
|
|
258
|
+
## Improve This Skill
|
|
259
|
+
|
|
260
|
+
If this skill was insufficient or slowed the work down, file it with
|
|
261
|
+
`mcp__conveyor__create_suggestion` on the Conveyor project: the issue,
|
|
262
|
+
evidence, and proposed fix.
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Pack path — a feature-branch pack, start to one PR
|
|
2
|
+
|
|
3
|
+
The pack execution core of [conveyor-build](../SKILL.md). Read that first;
|
|
4
|
+
ground rules, environment differences, verification, and aftercare live there.
|
|
5
|
+
|
|
6
|
+
A feature-branch pack is a parent card whose children branch from and PR into a
|
|
7
|
+
shared **pack branch**, and which lands on `dev` as ONE final PR. Children that
|
|
8
|
+
PR straight into `dev` are not this — build those individually via the task
|
|
9
|
+
path.
|
|
10
|
+
|
|
11
|
+
**You are both the coordinator and every child's implementer.** One session
|
|
12
|
+
owns all the state, serially. That is the whole point: the distributed
|
|
13
|
+
alternative is where pack incidents come from.
|
|
14
|
+
|
|
15
|
+
## Setup (first iteration only)
|
|
16
|
+
|
|
17
|
+
1. Confirm the shape: the parent has (or will have) children, its status is
|
|
18
|
+
neither InProgress nor ReviewPR, and no agent session is live on it. A
|
|
19
|
+
parent already InProgress/ReviewPR has a coordinator — report and stop
|
|
20
|
+
rather than compete.
|
|
21
|
+
2. **Ensure the pack branch exists on origin.** Use the card's `githubBranch`
|
|
22
|
+
if set; otherwise cut `ft/<parent-slug>` from `origin/dev`, push `-u`, and
|
|
23
|
+
IMMEDIATELY record it: `mcp__conveyor__update_task` with
|
|
24
|
+
`githubBranch: <branch>`.
|
|
25
|
+
|
|
26
|
+
That write is load-bearing, not bookkeeping. Identification mints a
|
|
27
|
+
competing `conveyor/*` branch name onto any branchless card it processes,
|
|
28
|
+
and every pack-child merge handler keys on the card's recorded branch
|
|
29
|
+
matching the PRs' real base — a drifted record strands merged children in
|
|
30
|
+
ReviewPR.
|
|
31
|
+
|
|
32
|
+
**Push the branch first, and verify it yourself.** The local surface
|
|
33
|
+
validates the ref; the pod's `update_task` does NOT — it writes the value
|
|
34
|
+
through with no check that the branch exists on origin, and no guard
|
|
35
|
+
against repointing the record away from the branch the pod is actually
|
|
36
|
+
running on, which strands the compute. A successful write is not evidence
|
|
37
|
+
the branch is pushed.
|
|
38
|
+
3. **No children yet?** Break the work down first: explore, save the
|
|
39
|
+
parent-level plan with `mcp__conveyor__update_task`, then
|
|
40
|
+
`mcp__conveyor__create_subtask` each child with a standalone plan
|
|
41
|
+
(file:line citations, verification steps) and `dependsOn` edges wherever one
|
|
42
|
+
blocks another.
|
|
43
|
+
4. Post the claim marker to the PARENT chat, naming the pack branch. Use a
|
|
44
|
+
stable, greppable prefix — `[pack] claimed — …` — because the Recover tier
|
|
45
|
+
above finds your in-flight work by searching for it. (Under
|
|
46
|
+
`conveyor-local-loop`, its `[local-loop]` prefix replaces this.)
|
|
47
|
+
|
|
48
|
+
**Locally, the parent card stays PARKED for the entire run** — never set it
|
|
49
|
+
InProgress, never Build it; the final `create_pull_request` is what moves it to
|
|
50
|
+
ReviewPR. The mechanism: the pack watchdog and the child-event notifier both
|
|
51
|
+
ignore a parked parent, whereas an ACTIVE parent treats a headless InProgress
|
|
52
|
+
child as a dead agent environment and "recovers" it onto a cloud pod —
|
|
53
|
+
duplicate implementation of a child you are already writing (observed
|
|
54
|
+
2026-07-28).
|
|
55
|
+
|
|
56
|
+
> **Environment.** In a pod the parent is honestly InProgress with a live
|
|
57
|
+
> session, and this parking rule does not apply — it exists specifically to
|
|
58
|
+
> dodge cloud recovery of headless children, which is not a risk when the
|
|
59
|
+
> parent's own session is the thing implementing them.
|
|
60
|
+
|
|
61
|
+
## Each iteration: re-derive, then do the first thing that applies
|
|
62
|
+
|
|
63
|
+
Re-read the parent and `mcp__conveyor__list_subtasks` every time. Never trust
|
|
64
|
+
session memory for pack state.
|
|
65
|
+
|
|
66
|
+
1. **Recover** — a child carrying your claim marker, InProgress, with no PR.
|
|
67
|
+
Its branch may already exist locally or on origin; audit what landed before
|
|
68
|
+
re-implementing.
|
|
69
|
+
2. **Merge** — a child in ReviewPR. See "Merge a child" below.
|
|
70
|
+
3. **Promote** — a `Planning` child whose plan is solid →
|
|
71
|
+
`mcp__conveyor__update_subtask` to `Open`. Genuinely not plannable →
|
|
72
|
+
escalate to parent chat.
|
|
73
|
+
4. **Implement** — the next `Open` child whose dependencies are all met.
|
|
74
|
+
**A dependency counts as met only at ReviewDev/Complete (merged into the
|
|
75
|
+
pack) or Cancelled. ReviewPR is NOT met** — an unmerged PR is not a
|
|
76
|
+
foundation to build on. No `dependsOn` anywhere → ordinal order.
|
|
77
|
+
5. **Finale** — every child at ReviewDev/Complete. See below.
|
|
78
|
+
6. **Babysit** — the final PR is open. Fix red CI and answer review comments
|
|
79
|
+
directly on the pack branch; never claim or work children once the parent is
|
|
80
|
+
in ReviewPR. **Green and quiet is the end:** post the wrap-up to parent chat
|
|
81
|
+
and stop.
|
|
82
|
+
|
|
83
|
+
Work children **one at a time**. Interleaving them thrashes branch state.
|
|
84
|
+
|
|
85
|
+
## Pacing — a pack is many turns, not one
|
|
86
|
+
|
|
87
|
+
A pack of any size will not fit in a single turn, and there is no partial
|
|
88
|
+
credit for a tree left mid-child. Treat **one iteration = one step** (implement
|
|
89
|
+
one child, or merge one, or the finale) and end the turn on a committed,
|
|
90
|
+
pushed state.
|
|
91
|
+
|
|
92
|
+
- Driven by `/loop` (locally) or woken by events (in a pod): do one step, then
|
|
93
|
+
end the turn. Under `/loop` with no interval, arm the next wake before
|
|
94
|
+
ending — short (60–90s) while there is a child ready to work, long
|
|
95
|
+
(1200–1800s) while waiting on something external, and **stop the loop** once
|
|
96
|
+
the finale PR is open and quiet.
|
|
97
|
+
- Invoked bare with no loop: do one step, report where the pack stands and what
|
|
98
|
+
the next step is, and stop. Do not self-schedule.
|
|
99
|
+
|
|
100
|
+
`conveyor-local-loop` supplies its own pacing table and its own claim-marker
|
|
101
|
+
prefix; when running under it, those govern.
|
|
102
|
+
|
|
103
|
+
## Implement a child
|
|
104
|
+
|
|
105
|
+
Reload the child's full plan fresh every time (`mcp__conveyor__get_task` +
|
|
106
|
+
`read_task_chat`) — never work from what you remember of it. **A plan too thin
|
|
107
|
+
for a context-free reader does not halt the pack:** post what is missing to
|
|
108
|
+
parent chat, skip that child, and take the next ready one.
|
|
109
|
+
|
|
110
|
+
Then follow [task-path.md](task-path.md), with one substitution: the child
|
|
111
|
+
branches from the **pack branch**, not `dev`, and its PR's base is the pack
|
|
112
|
+
branch. Name that base explicitly — the default is `dev`, and the two surfaces
|
|
113
|
+
spell the argument differently (`base:` locally, `baseBranch:` in a pod).
|
|
114
|
+
|
|
115
|
+
> **Environment — a pod has no child branches and no child PRs.** Everything
|
|
116
|
+
> above describes the LOCAL model, where each child gets its own branch and its
|
|
117
|
+
> own PR into the pack branch. A pod pack runner has one checkout and one
|
|
118
|
+
> branch, so a child's work is simply **commits on the pack branch**. Do not cut
|
|
119
|
+
> a child branch, and do not call `create_pull_request` for a child: that call
|
|
120
|
+
> always opens the PR for the card the session is bound to, so mid-pack it would
|
|
121
|
+
> open the PARENT's PR early and strand every remaining child. One commit per
|
|
122
|
+
> child keeps the single final PR reviewable child by child.
|
|
123
|
+
|
|
124
|
+
Before opening the child's PR, re-check the parent's status. If it went
|
|
125
|
+
InProgress or ReviewPR, a coordinator took over: post that you are yielding,
|
|
126
|
+
leave the branch pushed, and stop.
|
|
127
|
+
|
|
128
|
+
## Merge a child
|
|
129
|
+
|
|
130
|
+
> **Environment — in a pod there is nothing to merge.** The child's commits are
|
|
131
|
+
> already on the pack branch, so "merge a child" collapses to one write:
|
|
132
|
+
> `update_task(task_id: <child>, status: "ReviewDev")`. Nothing else moves a
|
|
133
|
+
> child — no per-child build fires — so a status you do not write is a board
|
|
134
|
+
> that silently lies. The reviewer-of-record pass below still applies to the
|
|
135
|
+
> commits; only the PR mechanics drop away.
|
|
136
|
+
|
|
137
|
+
1. **Reviewer-of-record pass.** The automated reviewer skips PRs that target a
|
|
138
|
+
pack branch, so this is the only review that child gets — the independent
|
|
139
|
+
review happens later, on the pack's final PR into `dev`. Re-read the child's
|
|
140
|
+
plan, then read the FULL diff (`git diff origin/<pack>...origin/<child>`)
|
|
141
|
+
with reviewer eyes: plan coverage, stray files, pattern consistency, and
|
|
142
|
+
whether the gate pass actually happened. Found a real problem → fix it on
|
|
143
|
+
the child branch (you are also the implementer), re-gate, then continue.
|
|
144
|
+
|
|
145
|
+
You wrote this code, which makes self-review the weak point. Consider an
|
|
146
|
+
independent reviewer — a subagent with the diff and no memory of writing it
|
|
147
|
+
catches what you cannot.
|
|
148
|
+
2. **Merge** via `mcp__conveyor__approve_and_merge_pr`. That call QUEUES the
|
|
149
|
+
merge (a ~30s sweep) rather than merging inline, so always confirm the PR
|
|
150
|
+
actually landed instead of trusting the response.
|
|
151
|
+
|
|
152
|
+
A pack-branch PR carries no CI checks. **Give the queue a couple of minutes
|
|
153
|
+
before concluding it cannot land it** — `passesCheckGate` treats
|
|
154
|
+
`zero_checks` as passed once past `isPastZeroCheckSettling`, and the
|
|
155
|
+
pack-child skip writes a terminal `approved` that satisfies the review gate.
|
|
156
|
+
Confirmed 2026-08-20 (PR #4224, ~4 min) and again 2026-08-27 (two pack-child
|
|
157
|
+
PRs, ~2 min each). The `merge-queue` tag has carried this since 2026-08-20;
|
|
158
|
+
this file and the `pack` tag were the surfaces still asserting otherwise. Checking once
|
|
159
|
+
and falling back immediately costs a rejected push and a reset.
|
|
160
|
+
|
|
161
|
+
Note the merge is a **squash**, so the child's commits are not ancestors of
|
|
162
|
+
the pack branch: `git merge-base --is-ancestor` reads false even when every
|
|
163
|
+
byte landed. Compare content (`git diff origin/<pack> <child-head>`), not
|
|
164
|
+
ancestry.
|
|
165
|
+
|
|
166
|
+
If it genuinely stalls, merge locally instead — GitHub then marks the PR
|
|
167
|
+
merged:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
git checkout <pack> && git pull && git merge --no-ff <child-branch> && git push
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
(Observed 2026-08-26: zero-check pack-branch PRs merged straight through the
|
|
174
|
+
queue twice in a row, so treat the fallback as a fallback, not the expected
|
|
175
|
+
path. Older guidance said the queue could NEVER merge them; that is not what
|
|
176
|
+
the queue does today.)
|
|
177
|
+
|
|
178
|
+
Either way, CONFIRM the child reached ReviewDev (allow ~1 minute for the
|
|
179
|
+
merge webhook). **Still ReviewPR after a local merge is an escalation, not a
|
|
180
|
+
shrug** — it means the parent's recorded `githubBranch` has drifted from the
|
|
181
|
+
real pack branch. Fix the parent record (`mcp__conveyor__update_task` with
|
|
182
|
+
`githubBranch: <pack>`), advance the child by hand (`update_task` →
|
|
183
|
+
`ReviewDev`), and post the drift to parent chat so it is visible.
|
|
184
|
+
3. **Sync `dev` into the pack branch — yours to do, in either environment.**
|
|
185
|
+
(The fan-out cloud path had the server do this before each child launch; a
|
|
186
|
+
session driving the pack itself gets no such help and resolves conflicts
|
|
187
|
+
in-session.)
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
git checkout <pack> && git pull && git fetch origin dev && git merge origin/dev --no-edit && git push
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Merge, never rebase** — the pack branch is shared with open child PRs and
|
|
194
|
+
WIP refs, and rewriting it breaks them. Conflicts are yours to resolve
|
|
195
|
+
properly; you wrote the code.
|
|
196
|
+
|
|
197
|
+
If the merge drags in unrelated changes or errors, `dev` may have been
|
|
198
|
+
rewound (a revert or force-push). Verify the previous sync point is still an
|
|
199
|
+
ancestor of `origin/dev` (`git merge-base --is-ancestor`); if it is not,
|
|
200
|
+
abort the merge and escalate rather than chasing the noise.
|
|
201
|
+
4. Report the merge to parent chat in a line or two.
|
|
202
|
+
|
|
203
|
+
## Finale
|
|
204
|
+
|
|
205
|
+
1. **Cross-reference.** For the parent plan and EVERY child plan, check the
|
|
206
|
+
pack branch's actual state against the acceptance and verification criteria
|
|
207
|
+
— a real checklist pass, not a vibe. Small gap → fix on the pack branch.
|
|
208
|
+
Substantial gap → a new child card with a plan, and the loop continues.
|
|
209
|
+
2. Pre-PR protocol on the pack branch: sync `origin/dev` FIRST, then ONE
|
|
210
|
+
verification pass scoped to the pack's cumulative diff against `dev`
|
|
211
|
+
(cross-package packs earn the full suite).
|
|
212
|
+
3. `mcp__conveyor__create_pull_request` on the PARENT: `head:` the pack branch,
|
|
213
|
+
`base:` `dev`. The parent moves to ReviewPR. Post the pack summary: what
|
|
214
|
+
shipped per child, how it was verified, what reviewers should look at.
|
|
215
|
+
4. Confirm CI started. **Never approve or merge this PR** — it is the one that
|
|
216
|
+
gets independent review.
|
|
217
|
+
|
|
218
|
+
## Parked protocol
|
|
219
|
+
|
|
220
|
+
After two genuinely different failed approaches on a child, or a decision only
|
|
221
|
+
the user can make: post the reason and the specific question to the child AND
|
|
222
|
+
parent chats, set the child back to `Open`, restore the tree, and take the next
|
|
223
|
+
child whose dependency chain does not run through the parked one. Everything
|
|
224
|
+
remaining blocked → report and stop; the user's reply is the un-park signal.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Task path — one card to a PR
|
|
2
|
+
|
|
3
|
+
The single-card execution core of [conveyor-build](../SKILL.md). Read that
|
|
4
|
+
first: ground rules, environment differences, routing, verification, and
|
|
5
|
+
aftercare all live there and are not repeated here.
|
|
6
|
+
|
|
7
|
+
Use this path when the card has no children, or when it is a pack child whose
|
|
8
|
+
parent is parked.
|
|
9
|
+
|
|
10
|
+
## 1. Claim
|
|
11
|
+
|
|
12
|
+
Re-confirm via `mcp__conveyor__get_task` that the card is still claimable —
|
|
13
|
+
`Open` (or whatever status the user explicitly overrode), no assignee you do
|
|
14
|
+
not expect, no active session. Then:
|
|
15
|
+
|
|
16
|
+
1. `mcp__conveyor__update_task` → `status: "InProgress"`
|
|
17
|
+
2. `mcp__conveyor__post_to_chat` → `[build] claimed — <where you are running>`
|
|
18
|
+
|
|
19
|
+
If the status changed under you between the read and the write, someone else
|
|
20
|
+
took it. Stop rather than compete.
|
|
21
|
+
|
|
22
|
+
## 2. Branch from the card's base — never blindly `dev`
|
|
23
|
+
|
|
24
|
+
The base is the card's `baseBranch`. **A pack child's base is the parent's
|
|
25
|
+
feature branch**, and getting this wrong silently retargets the whole PR.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git fetch origin <base>
|
|
29
|
+
git checkout -B <feat|fix|chore>/<slug> origin/<base>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Two cases that are not a fresh branch:
|
|
33
|
+
|
|
34
|
+
- **The card already has a `githubBranch` with commits on origin.** Resume THAT
|
|
35
|
+
branch. A prior session may have landed real work — audit what is there
|
|
36
|
+
before re-implementing anything.
|
|
37
|
+
- **The remote-tracking ref does not exist locally.** Many checkouts only
|
|
38
|
+
auto-fetch `dev` and the task branch, so `origin/<pack-branch>` may be
|
|
39
|
+
absent even though the branch exists on the remote. Fetch it explicitly
|
|
40
|
+
(`git fetch origin <branch>`) rather than concluding the branch is missing —
|
|
41
|
+
and note that a failed `checkout` leaves you on your PREVIOUS branch, where a
|
|
42
|
+
follow-up `git push` will push the wrong thing.
|
|
43
|
+
|
|
44
|
+
Reinstall dependencies if the lockfile changed.
|
|
45
|
+
|
|
46
|
+
## 3. Implement
|
|
47
|
+
|
|
48
|
+
**Read the plan's closing `## Builder briefing` first, when it has one.** The
|
|
49
|
+
planner wrote it for you specifically — where to start, what is already decided
|
|
50
|
+
and must not be reopened, which traps look correct and are not, and the order to
|
|
51
|
+
verify in. It is the only part of the planner's context that crosses the handoff,
|
|
52
|
+
so reading it after you have picked an approach wastes the thing it exists for.
|
|
53
|
+
A plan without one is not a blocker; just work the plan.
|
|
54
|
+
|
|
55
|
+
Work the plan. Push early — locally that is the only durable state, and in a
|
|
56
|
+
pod it is still what survives independent of WIP autosync.
|
|
57
|
+
|
|
58
|
+
Chat at milestones, not per step.
|
|
59
|
+
|
|
60
|
+
## 4. Gate, PR, aftercare
|
|
61
|
+
|
|
62
|
+
These are identical to the SKILL.md sections of the same names. In particular:
|
|
63
|
+
sync the base BEFORE the verification pass, pass `base:` explicitly to
|
|
64
|
+
`mcp__conveyor__create_pull_request`, and confirm CI started without waiting on
|
|
65
|
+
it.
|
|
66
|
+
|
|
67
|
+
Finish line: the card in ReviewPR with CI started. You do not merge it.
|