@rallycry/conveyor-skills 1.0.5 → 1.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rallycry/conveyor-skills",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Shared Claude Code skills for Conveyor consumer repos, linked into .claude/skills via the conveyor-skills CLI",
5
5
  "keywords": [
6
6
  "claude",
@@ -33,10 +33,9 @@ out in an **Environment** note — never assume; check which one you are in.
33
33
  - **Never boot another environment for work you are doing.** Locally that
34
34
  means never `mcp__conveyor__start_task` (it exists only on the local/MCP
35
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.
36
+ pack there is no tool that fires a child build at all — you implement the
37
+ children yourself, serially. A pack has one execution model in both
38
+ environments: one session owns all the state.
40
39
 
41
40
  ## Goal and finish line
42
41
 
@@ -216,6 +215,27 @@ behavior — do not go looking for why "unrelated" tests are running.
216
215
  > more broadly; if it does, let CI finish before merging. Confirm which case
217
216
  > you are in rather than assuming, since the two lead to opposite behavior.
218
217
 
218
+ ## A plan that turns on an unsettled question
219
+
220
+ A plan you cannot execute correctly because a product choice was never made is
221
+ not a blocker by itself. Check `list_decisions(card: "<slug>")` and the owning
222
+ tag's overview first — the answer is often already there, and citing it is the
223
+ whole point of the type. When it genuinely is not:
224
+
225
+ - **Most of the time, decide and say so.** Write the choice into the plan as a
226
+ GIVEN / WHEN / THEN line under "Assumed behaviours" and keep building. A
227
+ reviewer who disagrees says so, and it costs one comment.
228
+ - **Raise a decision when the answer changes what you build** and getting it
229
+ wrong means rework rather than a follow-up commit. `create_decision` blocks
230
+ this card by default, so proceed on the decision's default option and mark
231
+ the plan `Planned: <default> pending <decision url>` — the answer is written
232
+ back onto this card's plan when it settles.
233
+ - **Park only when building on the default would be thrown away.** That is the
234
+ Blocked path below.
235
+
236
+ The bar, and how to write options somebody can actually choose between, is in
237
+ [../conveyor-plan/references/product-decisions.md](../conveyor-plan/references/product-decisions.md).
238
+
219
239
  ## Not every task ends in a PR
220
240
 
221
241
  `create_pull_request` is for work that changes code. Plenty of cards don't:
@@ -19,7 +19,8 @@ alternative is where pack incidents come from.
19
19
  parent already InProgress/ReviewPR has a coordinator — report and stop
20
20
  rather than compete.
21
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
22
+ if set; otherwise cut `ft/<parent-slug>` from `origin/<base>` (the card's base
23
+ branch — usually `dev`), push `-u`, and
23
24
  IMMEDIATELY record it: `mcp__conveyor__update_task` with
24
25
  `githubBranch: <branch>`.
25
26
 
@@ -162,6 +163,12 @@ spell the argument differently (`base:` locally, `baseBranch:` in a pod).
162
163
  > always opens the PR for the card the session is bound to, so mid-pack it would
163
164
  > open the PARENT's PR early and strand every remaining child. One commit per
164
165
  > child keeps the single final PR reviewable child by child.
166
+ >
167
+ > Every child status write carries the child's id: claim with
168
+ > `mcp__conveyor__update_task(task_id: <child>, status: "InProgress")` and land
169
+ > with `update_task(task_id: <child>, status: "ReviewDev")`. Without `task_id`
170
+ > the write targets the PARENT card you are bound to. No per-child build fires
171
+ > in a pod, so a status you do not write is a board that silently lies.
165
172
 
166
173
  Before opening the child's PR, re-check the parent's status. If it went
167
174
  InProgress or ReviewPR, a coordinator took over: post that you are yielding,
@@ -224,12 +231,11 @@ leave the branch pushed, and stop.
224
231
  `githubBranch: <pack>`), advance the child by hand (`update_task` →
225
232
  `ReviewDev`), and post the drift to parent chat so it is visible.
226
233
  3. **Sync `dev` into the pack branch — yours to do, in either environment.**
227
- (The fan-out cloud path had the server do this before each child launch; a
228
- session driving the pack itself gets no such help and resolves conflicts
229
- in-session.)
234
+ Nothing server-side syncs the pack branch for you; a session driving the
235
+ pack resolves conflicts in-session.
230
236
 
231
237
  ```bash
232
- git checkout <pack> && git pull && git fetch origin dev && git merge origin/dev --no-edit && git push
238
+ git checkout <pack> && git pull && git fetch origin <base> && git merge origin/<base> --no-edit && git push
233
239
  ```
234
240
 
235
241
  **Merge, never rebase** — the pack branch is shared with open child PRs and
@@ -238,7 +244,7 @@ leave the branch pushed, and stop.
238
244
 
239
245
  If the merge drags in unrelated changes or errors, `dev` may have been
240
246
  rewound (a revert or force-push). Verify the previous sync point is still an
241
- ancestor of `origin/dev` (`git merge-base --is-ancestor`); if it is not,
247
+ ancestor of `origin/<base>` (`git merge-base --is-ancestor`); if it is not,
242
248
  abort the merge and escalate rather than chasing the noise.
243
249
  4. Report the merge to parent chat in a line or two.
244
250
 
@@ -248,7 +254,7 @@ leave the branch pushed, and stop.
248
254
  pack branch's actual state against the acceptance and verification criteria
249
255
  — a real checklist pass, not a vibe. Small gap → fix on the pack branch.
250
256
  Substantial gap → a new child card with a plan, and the loop continues.
251
- 2. Pre-PR protocol on the pack branch: sync `origin/dev` FIRST, then ONE
257
+ 2. Pre-PR protocol on the pack branch: sync `origin/<base>` FIRST, then ONE
252
258
  verification pass scoped to the pack's cumulative diff against `dev`
253
259
  (cross-package packs earn the full suite).
254
260
  3. `mcp__conveyor__create_pull_request` on the PARENT: `head:` the pack branch,
@@ -30,7 +30,8 @@ Announce a one-line plan naming the sources you found, then sweep. **Say what yo
30
30
  | Source | How |
31
31
  | ------ | --- |
32
32
  | Work channels | `read_channel_messages` per registered readable channel, paging back with `olderCursor` until the window covers the question. `authorIsBot` separates the team's discussion from Conveyor's own card feed — check it before treating a message as a teammate's. Read thread replies (`threadTs`) where a thread carries the argument. |
33
- | Conveyor cards | `search_tasks` with ALL `typeFilters` (task, incident, suggestion) and several keyword variants — the term, the term plus symptom words, the adjacent nouns people actually use. Incidents carry fingerprint dedup, so an incident's upvote count is itself a frequency signal. Check whether a decision card already exists; the doc is usually its input. |
33
+ | Conveyor cards | `search_tasks` with ALL `typeFilters` (task, incident, suggestion) and several keyword variants — the term, the term plus symptom words, the adjacent nouns people actually use. Incidents carry fingerprint dedup, so an incident's upvote count is itself a frequency signal. |
34
+ | Decisions | `list_decisions` — open ones are the questions on the table, Decided ones carry their resolution and are the project's own record of what it already settled. A verdict that contradicts a Decided decision has to say so and say why. `list_project_integrations` reports `decisions.openCount` / `decidedCount`, so you know whether there is a log here before you search it. |
34
35
  | Tags | `list_tags` then `get_tag` on the relevant ones — the overview is the project's own domain vocabulary, and it names the subsystems your categories should line up with. |
35
36
  | Card chat | `read_task_chat` on the cards the search surfaced. The argument usually lives in the chat, not the description. |
36
37
  | Meetings | If the meeting tools exist, list and read the ones in the window. A transcript is the densest source of "what people actually said" you will find. |
@@ -83,6 +84,48 @@ Chart rules that repeatedly matter: plain div/CSS charts over JS; one strong cha
83
84
  4. **Local sessions may also publish an Artifact** for a shareable URL, and `SendUserFile` the HTML — both are additive. In a pod neither exists; the attachment is the deliverable.
84
85
  5. **Revisions re-upload to the SAME card.** The doc is living; never fork it into `report-v2.html`.
85
86
 
87
+ ## Decision mode
88
+
89
+ When the argument IS a decision card — the user named one, or the sweep found
90
+ an open decision that this question is about — the shape changes. The doc is
91
+ not a survey of opinion; it is the input to settling a specific question that
92
+ has options, a deadline, and a default that wins if nobody acts.
93
+
94
+ **Sources, in place of the Phase 1 table:**
95
+
96
+ | Source | How |
97
+ | ------ | --- |
98
+ | The decision | `get_decision` — the context, every option's GIVEN / WHEN / THEN, every vote with who cast it and why, the running tally, and the cards it blocks. |
99
+ | The thread | `read_task_chat` on the decision. The Slack and Discord replies already mirror here, so this is the whole discussion in one read. |
100
+ | The impacted cards | Their plans say what each option would cost to build. A clean option that nobody can implement is not the cheap one. |
101
+ | Everything else | The ordinary sweep above, scoped to the question. |
102
+
103
+ **Weigh reasons, not counts.** Two people giving the same reason are one
104
+ argument. A single vote with a concrete failure case outranks three with none.
105
+ Say so explicitly in the verdict — a decision settled on a head count that
106
+ contradicted the reasoning is the thing this mode exists to prevent.
107
+
108
+ **Then settle it, in this order:**
109
+
110
+ 1. Attach the verdict HTML. **Where it lands depends on the surface**, and the
111
+ difference matters: a local MCP session's `upload_attachment` takes a
112
+ `taskId`, so send it to the DECISION card, titled with the question. The
113
+ in-pod tool takes no card argument and always posts to the session's own
114
+ card — so in a pod, attach it there and put the link in the resolution
115
+ notes rather than pretending it reached the decision.
116
+ 2. `resolve_decision` with the winning option, a resolution of one or two
117
+ plain sentences (255 characters), and `notes` linking wherever the
118
+ attachment actually landed.
119
+
120
+ Step 2 is what makes it real: the resolution is written into the plan and the
121
+ chat of every card the decision blocked and into the owning tags' overviews,
122
+ and those cards become startable. Do not stop at the doc.
123
+
124
+ **If the evidence does not settle it**, say that and do not resolve. Extend the
125
+ deadline with `update_decision` and post what would settle it. A verdict of
126
+ "this needs one more data point, and here is which" is a real answer; picking
127
+ an option to look decisive is not.
128
+
86
129
  ## Phase 5: the consensus loop
87
130
 
88
131
  The doc is the midpoint, not the end. Expect and serve:
@@ -121,6 +121,17 @@ Ask the user only decisions that change the plan's shape — scope cuts, UX
121
121
  choices, irreversible tradeoffs. Batch them in one round; never drip. Facts
122
122
  the repo can answer are yours to find, not theirs.
123
123
 
124
+ **Search the decision log first, and raise one when the user is not there.**
125
+ `list_decisions(status: "Decided", tag: "<tag>")` often answers the question
126
+ outright — an answered decision is the answer, and re-asking it is the waste
127
+ this exists to stop. When it does not, and you are running headless, prefer
128
+ `create_decision` over blocking on `AskUserQuestion`: a decision has a
129
+ deadline, so it settles on its default rather than stalling, and it links the
130
+ cards it blocks. Most forks are not decisions at all — see
131
+ [references/product-decisions.md](references/product-decisions.md) for the bar,
132
+ how to write options a person can actually choose between, and how to keep
133
+ building while one is open.
134
+
124
135
  ## Phase 3 — Draft the plan
125
136
 
126
137
  Use the plan format in [references/plan-format.md](references/plan-format.md):
@@ -0,0 +1,103 @@
1
+ # Product decisions
2
+
3
+ A product decision is a fork the plan cannot be right without — where two
4
+ answers lead to two different, both-defensible builds, and picking one silently
5
+ means somebody finds out at review. Conveyor has a card type for it:
6
+ `create_decision` raises one with two or three options, a default, and a
7
+ deadline; `list_decisions` finds the answer next time.
8
+
9
+ Shared by the plan, triage, build, and review skills. The rules are the same
10
+ wherever you are.
11
+
12
+ ## 1. Search before you ask
13
+
14
+ A decision that was settled once must never be re-litigated. Before planning
15
+ anything in an area:
16
+
17
+ 1. Read the owning tag's overview (`get_tag`) — a settled decision is written
18
+ into a `## Decisions` section there.
19
+ 2. `list_decisions(status: "Decided", tag: "<tag>")` — every row carries its
20
+ resolution, so the list IS the decision log.
21
+ 3. `list_decisions(card: "<slug>")` — what is blocking this card right now.
22
+
23
+ Cite what you find. "We decided this on 2026-09-19: <resolution>" ends the
24
+ question; re-opening it without new information wastes everybody's time.
25
+
26
+ ## 2. Most forks are not decisions
27
+
28
+ The common case is an assumption you can simply state. Write it in the plan
29
+ under **Assumed behaviours**, one GIVEN / WHEN / THEN line each:
30
+
31
+ ```
32
+ ## Assumed behaviours
33
+ - GIVEN a decision with no votes, WHEN its deadline passes, THEN the default option wins.
34
+ ```
35
+
36
+ A reviewer who disagrees says so, and it costs one comment. That is cheaper
37
+ than a card, a deadline, and three people's attention.
38
+
39
+ Raise a decision only when **all** of these hold:
40
+
41
+ - Two or three options are genuinely defensible — you cannot pick on merit.
42
+ - Getting it wrong means rework, not a follow-up commit.
43
+ - Somebody other than you has to live with the answer.
44
+
45
+ ## 3. Writing one that is answerable
46
+
47
+ - **The question is one plain sentence**, ending in a question mark. If it
48
+ needs two, it is two decisions.
49
+ - **Two or three options.** More than three means the question is not framed
50
+ yet: narrow it, or split it.
51
+ - **Each option is GIVEN / WHEN / THEN** — what the product does, concretely,
52
+ if this option wins. "Option B: use a queue" is not an option; "GIVEN a
53
+ second build request, WHEN one is already running, THEN it queues rather
54
+ than being refused" is.
55
+ - **Mark the status quo.** The option describing what the code does today gets
56
+ `kind: "current"`; an already-agreed-but-unbuilt one gets `kind: "planned"`.
57
+ A reader six months later needs to know whether the winner was a change.
58
+ - **Name the default and what it costs if wrong.** The default wins on
59
+ silence. If silence would be dangerous, say so in the context — and set a
60
+ shorter deadline.
61
+ - **Link the cards it blocks.** They cannot start until it settles, and they
62
+ un-block the moment it does. In a pod this includes your own card by
63
+ default.
64
+ - **Tag it.** The settled answer is written into each tag's overview, which is
65
+ how the next agent finds it without knowing the decision exists.
66
+
67
+ ## 4. Keep moving
68
+
69
+ Raising a decision is not a reason to stop. Either:
70
+
71
+ - **Proceed on the default.** Mark the plan: `Planned: <default option>
72
+ pending <decision url>`. If the decision settles differently, the write-back
73
+ lands on this card's plan and the card is un-blocked with the correct answer.
74
+ - **Park**, per the parked protocol in
75
+ `conveyor-build/references/pack-path.md`, when building on the default would
76
+ be actively unsafe or would be thrown away.
77
+
78
+ Never sit idle waiting for a vote.
79
+
80
+ ## 5. Settling one
81
+
82
+ `resolve_decision` is not a formality. The resolution is written into the plan
83
+ and the chat of every card the decision blocked, and into the overview of every
84
+ tag it carries — and those cards become startable. So:
85
+
86
+ - Write the resolution as one or two plain sentences a non-engineer can read.
87
+ A reader months later should not have to open the thread.
88
+ - Weigh the reasons, not the count. Two people with the same reason are one
89
+ argument.
90
+ - Put the reasoning in `notes`, and link any verdict attachment there.
91
+
92
+ **A reviewer does not settle decisions.** A review runs against a diff that
93
+ already exists. If the diff turns on an unsettled decision, say so on the PR
94
+ and cite it — `resolve_decision` is refused in review mode for that reason.
95
+
96
+ ## 6. When nobody answers
97
+
98
+ At the deadline, the sweeper settles it: the plurality winner, or the default
99
+ on a tie or an empty ballot, stamped `resolvedHow: "deadline"`. Silence becomes
100
+ a decision rather than a stall. A reminder lands in the thread a day before.
101
+
102
+ That is why the default is required, and why it has to be the answer you can
103
+ live with.
@@ -115,6 +115,17 @@ You have write access. Use it in proportion:
115
115
 
116
116
  Fixing something you do not fully understand is worse than flagging it.
117
117
 
118
+ **A finding that turns on a product choice is neither.** When the diff is
119
+ defensible and the disagreement is really "should the product do X or Y", check
120
+ `list_decisions` first: if it was settled, cite the resolution and the diff is
121
+ either right or wrong on the record. If it was never settled, say so in the
122
+ verdict and name the fork — do NOT settle it yourself. `resolve_decision` is
123
+ refused in review mode for that reason: a review runs on a fixed budget against
124
+ a diff that already exists, and settling a decision writes that answer into
125
+ every card it was blocking. Raising one is fine if the fork is real; the author
126
+ or a moderator settles it. See
127
+ [../conveyor-plan/references/product-decisions.md](../conveyor-plan/references/product-decisions.md).
128
+
118
129
  ## The verdict
119
130
 
120
131
  > **Environment — the tools differ, and only one pair exists per surface.**
@@ -151,8 +162,8 @@ which no pod reviewer could follow. Same defect the story-points paragraph below
151
162
  already records.
152
163
 
153
164
  Story points are deliberately NOT yours to change. `update_task`'s agent
154
- surface omits `storyPointValue` on purpose, and a pod review session has no
155
- tool that carries it — so this used to be an instruction no reviewer could
165
+ surface omits `storyPointValue` on purpose, and no pod tool carries the card's
166
+ OWN story points — so this used to be an instruction no reviewer could
156
167
  follow. It is also a gate you sit behind rather than above: story points set
157
168
  the card's graduated merge minimum, so a reviewer that could lower them would
158
169
  be lowering the bar for merging the very PR under review. Flag a mis-sized
@@ -173,6 +184,19 @@ is the reviewer, and the independent review happens later on the pack's PR into
173
184
  - You wrote this code, which makes self-review the weak point. An independent
174
185
  reviewer with the diff and no memory of writing it catches what you cannot.
175
186
 
187
+ ## Reviewing a pack's finale PR
188
+
189
+ A pack parent's PR into the base branch is an ordinary review of the pack's
190
+ cumulative diff — there is no coordination job. The parent's own session
191
+ implemented every child, so read the whole diff against the base and render one
192
+ verdict as above. Child cards have no merge gate of their own, so correcting a
193
+ CHILD's story points with `mcp__conveyor__update_subtask` (`storyPointValue`)
194
+ when the actual work diverged from the estimate is legitimate here, in either
195
+ direction — where the tool exists: a pod's review runner and a local session
196
+ carry it, a task session flipped to review does not (flag the mis-size in the
197
+ verdict instead). The parent card's own story points stay off-limits per the
198
+ note above.
199
+
176
200
  ## Blocked
177
201
 
178
202
  If the PR cannot be reviewed as it stands — the plan is missing, the diff is
@@ -144,6 +144,14 @@ is still unknown — including what evidence would resolve it. Then move it to
144
144
  `Open`. "Needs a repro with the console open" is an actionable handoff;
145
145
  "couldn't reproduce" is not.
146
146
 
147
+ **When the unknown is a product choice, not missing evidence**, the handoff is
148
+ a decision rather than a triage note. "The code does X, the reporter expected
149
+ Y, and both are defensible" is not something more logs will settle — raise it
150
+ with `create_decision`, two or three options written GIVEN / WHEN / THEN, and
151
+ link this card as impacted so it un-blocks the moment the question is answered.
152
+ See
153
+ [../conveyor-plan/references/product-decisions.md](../conveyor-plan/references/product-decisions.md).
154
+
147
155
  **Cancelling:** explain the actual behavior, then cancel.
148
156
 
149
157
  ## 7. File at least one suggestion — always
@@ -38,9 +38,22 @@ and let Conveyor's own automation do the linking.
38
38
  it (post your context to its chat) rather than forking a duplicate.
39
39
  - **Classify**: buildable work → `mcp__conveyor__create_task`; an
40
40
  idea/improvement you are NOT committing to build →
41
- `mcp__conveyor__create_suggestion`; incidents (production breakage) are
42
- filed by monitoring and users through Conveyor's incident tooling — you
43
- will usually *work* incident cards, not create them.
41
+ `mcp__conveyor__create_suggestion`; a product fork that has to be settled
42
+ before the work can be planned correctly → `mcp__conveyor__create_decision`;
43
+ incidents
44
+ (production breakage) are filed by monitoring and users through Conveyor's
45
+ incident tooling — you will usually *work* incident cards, not create them.
46
+ - **Decisions**: a decision card holds one question, two or three options
47
+ written GIVEN / WHEN / THEN, a default that wins on silence, and a deadline.
48
+ It BLOCKS the cards it names until it settles, and un-blocks them the moment
49
+ it does — the answer is written into each of their plans and into the owning
50
+ tags' overviews, so the next agent finds it without knowing the decision
51
+ existed. Search with `mcp__conveyor__list_decisions` BEFORE planning in an
52
+ area: a settled
53
+ decision is the answer, and re-asking it is the waste the type exists to
54
+ stop. Most forks are not decisions — an assumption you can simply state
55
+ belongs in the plan as a GIVEN / WHEN / THEN line. The full bar is in
56
+ [../conveyor-plan/references/product-decisions.md](../conveyor-plan/references/product-decisions.md).
44
57
  - **Mechanics**: `create_task` takes the title, description, `plan`
45
58
  (markdown), and optional status/tags; cards start in `Planning`. Every
46
59
  status change you make goes through `mcp__conveyor__update_task`