@rallycry/conveyor-agent 10.13.71 → 11.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/dist/{boot-PKHZUDAC.js → boot-PKQ2I66D.js} +56 -5
- package/dist/chunk-3F4ZZKCA.js +291 -0
- package/dist/{chunk-QU53HND5.js → chunk-GL2DIQEQ.js} +116 -47
- package/dist/chunk-JQVAWRVL.js +697 -0
- package/dist/chunk-N4WSUTGV.js +2564 -0
- package/dist/{chunk-7MMECTTJ.js → chunk-PEEGCZAR.js} +2257 -3701
- package/dist/{chunk-DOB2XE2I.js → chunk-UBDSLM44.js} +4 -2
- package/dist/{chunk-GJXAAPJ6.js → chunk-W4LZ7R6Z.js} +117 -400
- package/dist/chunk-XORJ6SII.js +46 -0
- package/dist/cli.js +304 -804
- package/dist/index.d.ts +170 -3
- package/dist/index.js +9 -5
- package/dist/serve-boot-YPAUKENG.js +225 -0
- package/dist/{server-CC7KUJOK.js → server-7XH7RYUX.js} +3 -2
- package/package.json +5 -4
- 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 +258 -0
- package/skills/conveyor-meeting-review/SKILL.md +72 -0
- package/skills/conveyor-plan/SKILL.md +177 -0
- package/skills/conveyor-plan/references/plan-format.md +134 -0
- 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 +195 -0
- package/skills/conveyor-workflows/references/mcp-setup.md +43 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<!-- Consensus doc skeleton. Proven treatment: observer-memo, banker-blue accent.
|
|
2
|
+
Swap palette/type ONLY if the subject demands a different identity.
|
|
3
|
+
Replace every UPPERCASE placeholder. Delete sections that don't apply; keep the order.
|
|
4
|
+
|
|
5
|
+
SELF-CONTAINED ON PURPOSE — do not add external references.
|
|
6
|
+
This file is uploaded to a card and served by the API under a sandbox CSP
|
|
7
|
+
("sandbox; default-src 'none'; style-src 'unsafe-inline'; img-src data:").
|
|
8
|
+
That blocks webfont stylesheets, external CSS/JS, and remote images. The
|
|
9
|
+
upstream grimoire template linked Google Fonts; it is replaced here with a
|
|
10
|
+
system stack, because under this CSP the link fails silently and the doc
|
|
11
|
+
renders in a fallback font with no error. Same rule for charts: the div/CSS
|
|
12
|
+
bars below work, a JS charting library cannot run at all.
|
|
13
|
+
|
|
14
|
+
Images, if you truly need one, must be data: URIs. -->
|
|
15
|
+
<title>DOC NAME</title>
|
|
16
|
+
<style>
|
|
17
|
+
:root {
|
|
18
|
+
--bg: #f7f9fb; --surface: #ffffff;
|
|
19
|
+
--ink: #16222e; --ink-2: #48596a; --ink-3: #74838f;
|
|
20
|
+
--line: #d9e0e7; --line-soft: #e8edf1;
|
|
21
|
+
--accent: #20618f; --accent-soft: #dcebf5;
|
|
22
|
+
--bar: #2e6f9e; --bar-hover: #20618f;
|
|
23
|
+
--good-ink: #176a44; --good-bg: #ddf0e5;
|
|
24
|
+
--warn-ink: #8a5d00; --warn-bg: #f6ecd2;
|
|
25
|
+
--miss-ink: #a13529; --miss-bg: #f9e2de;
|
|
26
|
+
--neutral-ink: #55606b; --neutral-bg: #e8ecf0;
|
|
27
|
+
--quote-rail: #c3d5e2;
|
|
28
|
+
}
|
|
29
|
+
/* Three-state theming: bare :root = light; media block guarded against explicit light; data-theme block wins for the toggle. */
|
|
30
|
+
@media (prefers-color-scheme: dark) {
|
|
31
|
+
:root:not([data-theme="light"]) {
|
|
32
|
+
--bg: #101720; --surface: #161f2a;
|
|
33
|
+
--ink: #e4ebf2; --ink-2: #a4b3c1; --ink-3: #7d8c9a;
|
|
34
|
+
--line: #2b3947; --line-soft: #223040;
|
|
35
|
+
--accent: #6fadd9; --accent-soft: #1d3346;
|
|
36
|
+
--bar: #4c88b4; --bar-hover: #6fadd9;
|
|
37
|
+
--good-ink: #57c48f; --good-bg: #16311f;
|
|
38
|
+
--warn-ink: #d9a94a; --warn-bg: #34290f;
|
|
39
|
+
--miss-ink: #e2857a; --miss-bg: #3a1d18;
|
|
40
|
+
--neutral-ink: #a4b3c1; --neutral-bg: #222d38;
|
|
41
|
+
--quote-rail: #33506a;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
:root[data-theme="dark"] {
|
|
45
|
+
--bg: #101720; --surface: #161f2a;
|
|
46
|
+
--ink: #e4ebf2; --ink-2: #a4b3c1; --ink-3: #7d8c9a;
|
|
47
|
+
--line: #2b3947; --line-soft: #223040;
|
|
48
|
+
--accent: #6fadd9; --accent-soft: #1d3346;
|
|
49
|
+
--bar: #4c88b4; --bar-hover: #6fadd9;
|
|
50
|
+
--good-ink: #57c48f; --good-bg: #16311f;
|
|
51
|
+
--warn-ink: #d9a94a; --warn-bg: #34290f;
|
|
52
|
+
--miss-ink: #e2857a; --miss-bg: #3a1d18;
|
|
53
|
+
--neutral-ink: #a4b3c1; --neutral-bg: #222d38;
|
|
54
|
+
--quote-rail: #33506a;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
body { background: var(--bg); color: var(--ink); font-family: ui-sans-serif, system-ui, "Segoe UI", "Helvetica Neue", Arial, sans-serif; font-size: 16px; line-height: 1.6; margin: 0; padding: 3rem 1.25rem 5rem; }
|
|
58
|
+
.doc { max-width: 46rem; margin: 0 auto; }
|
|
59
|
+
|
|
60
|
+
.eyebrow { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 0.75rem; }
|
|
61
|
+
h1 { font-family: ui-serif, Georgia, "Times New Roman", serif; font-weight: 700; font-size: 2.3rem; line-height: 1.15; margin: 0 0 0.5rem; text-wrap: balance; }
|
|
62
|
+
.dek { color: var(--ink-2); font-size: 1.05rem; max-width: 40rem; margin: 0 0 0.75rem; }
|
|
63
|
+
.meta { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.75rem; color: var(--ink-3); margin: 0 0 2.5rem; }
|
|
64
|
+
|
|
65
|
+
h2 { font-family: ui-serif, Georgia, "Times New Roman", serif; font-weight: 600; font-size: 1.45rem; line-height: 1.25; margin: 3rem 0 0.9rem; text-wrap: balance; }
|
|
66
|
+
h2 .sec { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-weight: 500; font-size: 0.78rem; color: var(--accent); display: block; letter-spacing: 0.12em; margin-bottom: 0.35rem; }
|
|
67
|
+
p { margin: 0 0 1rem; max-width: 42rem; }
|
|
68
|
+
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
|
|
69
|
+
strong { font-weight: 600; }
|
|
70
|
+
|
|
71
|
+
.tldr { background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 6px; padding: 1.15rem 1.35rem; margin: 0 0 1rem; }
|
|
72
|
+
.tldr p { margin: 0 0 0.7rem; }
|
|
73
|
+
.tldr p:last-child { margin: 0; }
|
|
74
|
+
|
|
75
|
+
figure { background: var(--surface); border: 1px solid var(--line); border-radius: 6px; margin: 1.5rem 0; padding: 1.25rem 1.35rem 1.1rem; }
|
|
76
|
+
figcaption { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 1rem; }
|
|
77
|
+
.fignote { font-size: 0.78rem; color: var(--ink-3); margin-top: 0.9rem; }
|
|
78
|
+
|
|
79
|
+
/* Frequency bar chart: single hue (one series = no legend), direct value labels, hover emphasis + title tooltips. */
|
|
80
|
+
.barchart { display: flex; flex-direction: column; gap: 7px; }
|
|
81
|
+
.barrow { display: grid; grid-template-columns: 13.5rem 1fr 2rem; gap: 0.7rem; align-items: center; font-size: 0.85rem; }
|
|
82
|
+
.barrow .lbl { color: var(--ink-2); text-align: right; line-height: 1.25; }
|
|
83
|
+
.track { background: var(--line-soft); border-radius: 3px; height: 16px; }
|
|
84
|
+
.fill { background: var(--bar); border-radius: 3px 4px 4px 3px; height: 100%; transition: background 120ms ease; }
|
|
85
|
+
.barrow:hover .fill { background: var(--bar-hover); }
|
|
86
|
+
.barrow .val { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-variant-numeric: tabular-nums; font-size: 0.8rem; color: var(--ink-2); }
|
|
87
|
+
.barrow:hover .lbl, .barrow:hover .val { color: var(--ink); }
|
|
88
|
+
|
|
89
|
+
/* Head-to-head stacked coverage bars, one row per proposal (+ a Merged row). */
|
|
90
|
+
.compare { display: flex; flex-direction: column; gap: 10px; }
|
|
91
|
+
.cmprow { display: grid; grid-template-columns: 8.5rem 1fr; gap: 0.8rem; align-items: center; }
|
|
92
|
+
.cmprow .who { font-size: 0.85rem; font-weight: 600; text-align: right; color: var(--ink-2); }
|
|
93
|
+
.scoreboard { display: flex; height: 26px; border-radius: 5px; overflow: hidden; gap: 2px; }
|
|
94
|
+
.scoreboard div { display: flex; align-items: center; justify-content: center; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.76rem; font-weight: 500; min-width: 1.4rem; }
|
|
95
|
+
.sc-good { background: var(--good-bg); color: var(--good-ink); }
|
|
96
|
+
.sc-warn { background: var(--warn-bg); color: var(--warn-ink); }
|
|
97
|
+
.sc-miss { background: var(--miss-bg); color: var(--miss-ink); }
|
|
98
|
+
.sc-legend { display: flex; gap: 1.4rem; margin-top: 0.8rem; font-size: 0.78rem; color: var(--ink-2); flex-wrap: wrap; }
|
|
99
|
+
.sc-legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
|
|
100
|
+
.swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
|
|
101
|
+
|
|
102
|
+
/* Verdict + feasibility chips: text always, never color alone. */
|
|
103
|
+
.chip { display: inline-block; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.68rem; font-weight: 500; letter-spacing: 0.06em; padding: 0.15rem 0.5rem; border-radius: 999px; white-space: nowrap; }
|
|
104
|
+
.chip-good { background: var(--good-bg); color: var(--good-ink); } /* COVERED / API ✓ */
|
|
105
|
+
.chip-warn { background: var(--warn-bg); color: var(--warn-ink); } /* PARTIAL */
|
|
106
|
+
.chip-miss { background: var(--miss-bg); color: var(--miss-ink); } /* MISSED / NOT POSSIBLE */
|
|
107
|
+
.chip-api { background: var(--accent-soft); color: var(--accent); } /* vendor-supported rulings */
|
|
108
|
+
.chip-ours { background: var(--neutral-bg); color: var(--neutral-ink); } /* OUR BUILD / CONFIG */
|
|
109
|
+
|
|
110
|
+
.tablewrap { overflow-x: auto; margin: 1.5rem 0; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); }
|
|
111
|
+
table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }
|
|
112
|
+
th { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; text-align: left; padding: 0.7rem 1rem; border-bottom: 1px solid var(--line); }
|
|
113
|
+
td { padding: 0.6rem 1rem; border-bottom: 1px solid var(--line-soft); vertical-align: top; color: var(--ink-2); }
|
|
114
|
+
td:first-child { color: var(--ink); font-weight: 600; }
|
|
115
|
+
tr:last-child td { border-bottom: none; }
|
|
116
|
+
td.nowrap { white-space: nowrap; }
|
|
117
|
+
|
|
118
|
+
blockquote { border-left: 3px solid var(--quote-rail); margin: 1.1rem 0; padding: 0.1rem 0 0.1rem 1.1rem; color: var(--ink-2); font-style: italic; max-width: 40rem; }
|
|
119
|
+
blockquote cite { display: block; font-style: normal; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.72rem; color: var(--ink-3); margin-top: 0.35rem; }
|
|
120
|
+
|
|
121
|
+
ol.twocents { padding-left: 1.3rem; max-width: 42rem; }
|
|
122
|
+
ol.twocents li { margin-bottom: 0.85rem; }
|
|
123
|
+
ol.twocents li::marker { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--accent); font-size: 0.85rem; }
|
|
124
|
+
|
|
125
|
+
.method { border-top: 1px solid var(--line); margin-top: 3.5rem; padding-top: 1.25rem; font-size: 0.8rem; color: var(--ink-3); max-width: 42rem; }
|
|
126
|
+
</style>
|
|
127
|
+
|
|
128
|
+
<div class="doc">
|
|
129
|
+
<p class="eyebrow">Outside read · No stake in the outcome</p>
|
|
130
|
+
<h1>DOC NAME</h1>
|
|
131
|
+
<p class="dek">ONE-SENTENCE FRAME: who pulled what, and what this doc rules on.</p>
|
|
132
|
+
<p class="meta">~N messages · DATE → DATE · N channels/sources · input to DECISION/CARD</p>
|
|
133
|
+
|
|
134
|
+
<div class="tldr">
|
|
135
|
+
<p><strong>VERDICT SENTENCE.</strong> Two to three bold-led paragraphs; a reader who stops here can act.</p>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<h2><span class="sec">01</span>What the evidence says</h2>
|
|
139
|
+
<p>How findings were binned; what a count means.</p>
|
|
140
|
+
<figure>
|
|
141
|
+
<figcaption>FINDINGS BY INCIDENT COUNT, RANGE</figcaption>
|
|
142
|
+
<div class="barchart">
|
|
143
|
+
<!-- width = count / max * 100%. title attr = one-line version for hover. -->
|
|
144
|
+
<div class="barrow" title="ONE-LINER"><span class="lbl">CATEGORY</span><div class="track"><div class="fill" style="width:100%"></div></div><span class="val">15</span></div>
|
|
145
|
+
<div class="barrow" title="ONE-LINER"><span class="lbl">CATEGORY</span><div class="track"><div class="fill" style="width:60%"></div></div><span class="val">9</span></div>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="fignote">Dominant sources; hover note.</div>
|
|
148
|
+
</figure>
|
|
149
|
+
<blockquote>"VERBATIM QUOTE"<cite>WHO · #channel · DATE</cite></blockquote>
|
|
150
|
+
|
|
151
|
+
<h2><span class="sec">02</span>What already exists</h2>
|
|
152
|
+
<p>Incumbent system, prior art, negative results ("no payout code in the repo").</p>
|
|
153
|
+
|
|
154
|
+
<h2><span class="sec">03</span>PROPOSAL A, scored</h2>
|
|
155
|
+
<div class="tablewrap">
|
|
156
|
+
<table>
|
|
157
|
+
<thead><tr><th>Pain / need</th><th>Verdict</th><th>Why</th></tr></thead>
|
|
158
|
+
<tbody>
|
|
159
|
+
<tr><td>ITEM</td><td class="nowrap"><span class="chip chip-good">COVERED</span></td><td>ONE SENTENCE.</td></tr>
|
|
160
|
+
<tr><td>ITEM</td><td class="nowrap"><span class="chip chip-warn">PARTIAL</span></td><td>Symptom yes, root cause no.</td></tr>
|
|
161
|
+
<tr><td>ITEM</td><td class="nowrap"><span class="chip chip-miss">MISSED</span></td><td>ONE SENTENCE.</td></tr>
|
|
162
|
+
</tbody>
|
|
163
|
+
</table>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<!-- Repeat 03 per proposal, then head-to-head: -->
|
|
167
|
+
<figure>
|
|
168
|
+
<figcaption>Head to head: N items each</figcaption>
|
|
169
|
+
<div class="compare">
|
|
170
|
+
<div class="cmprow"><span class="who">Proposal A</span>
|
|
171
|
+
<div class="scoreboard"><div class="sc-good" style="flex:3">3</div><div class="sc-warn" style="flex:5">5</div><div class="sc-miss" style="flex:3">3</div></div>
|
|
172
|
+
</div>
|
|
173
|
+
<div class="cmprow"><span class="who">Merged</span>
|
|
174
|
+
<div class="scoreboard"><div class="sc-good" style="flex:10">10</div><div class="sc-warn" style="flex:1">1</div></div>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
<div class="sc-legend">
|
|
178
|
+
<span><span class="swatch" style="background:var(--good-bg);border:1px solid var(--good-ink)"></span>covered</span>
|
|
179
|
+
<span><span class="swatch" style="background:var(--warn-bg);border:1px solid var(--warn-ink)"></span>symptom yes, root cause no</span>
|
|
180
|
+
<span><span class="swatch" style="background:var(--miss-bg);border:1px solid var(--miss-ink)"></span>not in the plan</span>
|
|
181
|
+
</div>
|
|
182
|
+
</figure>
|
|
183
|
+
|
|
184
|
+
<h2><span class="sec">04</span>The merged plan, with rulings</h2>
|
|
185
|
+
<div class="tablewrap">
|
|
186
|
+
<table>
|
|
187
|
+
<thead><tr><th>Blueprint item</th><th>Feasibility</th><th>Detail</th></tr></thead>
|
|
188
|
+
<tbody>
|
|
189
|
+
<tr><td>ITEM</td><td class="nowrap"><span class="chip chip-api">API ✓</span></td><td>Ruling + <a href="ENDPOINT-DOC-URL">endpoint link</a>.</td></tr>
|
|
190
|
+
<tr><td>ITEM</td><td class="nowrap"><span class="chip chip-ours">OUR BUILD</span></td><td>Ruling.</td></tr>
|
|
191
|
+
<tr><td>ITEM</td><td class="nowrap"><span class="chip chip-miss">NOT POSSIBLE</span></td><td>Why, and whether the impossibility is desirable.</td></tr>
|
|
192
|
+
</tbody>
|
|
193
|
+
</table>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<h2><span class="sec">05</span>The two cents</h2>
|
|
197
|
+
<ol class="twocents">
|
|
198
|
+
<li><strong>RECOMMENDATION.</strong> The argument for it.</li>
|
|
199
|
+
</ol>
|
|
200
|
+
|
|
201
|
+
<div class="method">
|
|
202
|
+
<p><strong>Method.</strong> Queries run, counts, date range, what was reviewed in full, what was verified against primary sources, and what was NOT done.</p>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: conveyor-local-loop
|
|
3
|
+
description: Run this machine as a serial local claudespace — pick the session owner's highest-priority Open Conveyor card, claim it, execute its plan to the PR finish line, repeat. Handles single cards AND whole packs (an Open pack parent is driven end-to-end per conveyor-build's pack path, then the loop moves on once the pack's final PR is open). One invocation = one iteration; run continuously with "/loop /conveyor-local-loop" (no interval) and it self-paces (~1-2 min between cards while the queue has work; when the queue is empty it blocks on live board events via conveyor-wait and wakes seconds after a card becomes claimable, with a ~25 min fallback poll). Use when the user says "/conveyor-local-loop", "start the local loop", "work my open cards locally", or wants planned cards executed with full local CPU/RAM instead of spawning claudespaces. For exactly one card, or one pack and nothing else, use conveyor-build.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Conveyor Local Loop
|
|
7
|
+
|
|
8
|
+
Turn a queue of researched Open cards (usually authored via `/conveyor-plan`)
|
|
9
|
+
into review-ready PRs using this machine, one card at a time. Behave exactly as
|
|
10
|
+
a claudespace agent would: the card IS the spec, task chat is the log, and the
|
|
11
|
+
host repo's CLAUDE.md governs gates, verification, and PR mechanics. This skill
|
|
12
|
+
adds only selection, claiming, cadence, and local-machine hygiene.
|
|
13
|
+
|
|
14
|
+
## Ground rules
|
|
15
|
+
|
|
16
|
+
- **Conveyor is the state store.** The loop session spans days and gets
|
|
17
|
+
compacted; at each iteration re-derive state from MCP reads, never from
|
|
18
|
+
conversation memory.
|
|
19
|
+
- **All Conveyor tools fully-qualified** (`mcp__conveyor__get_task`; bare names
|
|
20
|
+
fail).
|
|
21
|
+
- **WIP = 1.** At most one card claimed by this loop at a time.
|
|
22
|
+
- **Never `start_task`** — that boots a cloud pod and duplicates the work. Only
|
|
23
|
+
exception: the opt-in offload valve below.
|
|
24
|
+
- **Never approve or merge your own PRs.** Finish line = card in ReviewPR with
|
|
25
|
+
green CI; the user takes it from there.
|
|
26
|
+
- **Only cards created by the session owner** (match against
|
|
27
|
+
`mcp__conveyor__get_connection_context`), status Open, unassigned. Teammates'
|
|
28
|
+
cards and pod-claimed cards are off limits.
|
|
29
|
+
- **Pack cards: claim the whole pack; the parent card stays parked.** An Open
|
|
30
|
+
feature-branch pack parent that passes the claiming filters is claimable as
|
|
31
|
+
a PACK: enter pack mode (below) and drive every child to the final parent
|
|
32
|
+
PR per [conveyor-build's pack path](../conveyor-build/references/pack-path.md). Throughout,
|
|
33
|
+
the parent card itself stays PARKED — never Build/`start_task` it, never
|
|
34
|
+
set it InProgress; the finale `create_pull_request` is what moves it to
|
|
35
|
+
ReviewPR. A parent already InProgress/ReviewPR has (or had) an active
|
|
36
|
+
coordinator — hands off it AND its children: an actively-orchestrating
|
|
37
|
+
parent reads a headless InProgress child as a dead agent environment and
|
|
38
|
+
"recovers" it onto a cloud pod (observed 2026-07-28 — duplicate
|
|
39
|
+
implementation). A NON-feature-branch pack — children PR straight into dev,
|
|
40
|
+
so there is no pack branch to coordinate — is never claimed as a pack:
|
|
41
|
+
conveyor-build's pack path explicitly does not apply to it. Claim those children
|
|
42
|
+
individually, one per iteration, and only while the parent is parked.
|
|
43
|
+
- **Run in the main workspace checkout — never a git worktree.** The fully
|
|
44
|
+
provisioned main workspace (installed `node_modules`, `.env`/direnv auth
|
|
45
|
+
wiring, the running dev stack) is the whole value of local execution;
|
|
46
|
+
worktrees miss all of it and have consistently degraded agent sessions.
|
|
47
|
+
Clean tree before any branch switch is still a hard rule: dirty
|
|
48
|
+
`git status` at iteration start → touch nothing, report, and idle — the
|
|
49
|
+
resolution is the user committing or stashing, not a second checkout.
|
|
50
|
+
- **Push early.** There is no pod WIP-autosync locally; committed-and-pushed is
|
|
51
|
+
the only durable state. Push the branch (`-u origin`) as soon as it exists.
|
|
52
|
+
|
|
53
|
+
## Iteration order
|
|
54
|
+
|
|
55
|
+
Each invocation does the FIRST of these that produces work, then paces:
|
|
56
|
+
|
|
57
|
+
1. **Recover** — a card with my `[local-loop] claimed` chat marker still
|
|
58
|
+
InProgress without a PR? Resume it. The branch may already exist locally or
|
|
59
|
+
on origin — check both before re-implementing anything. A pack parent
|
|
60
|
+
whose chat carries my `[local-loop] claimed — driving this pack` marker
|
|
61
|
+
and isn't yet in ReviewPR? Resume pack mode — re-derive where it left off
|
|
62
|
+
from `mcp__conveyor__list_subtasks`, never from session memory. Skip a
|
|
63
|
+
parent whose LATEST marker is `[local-loop] parked:` with no human reply
|
|
64
|
+
after it — that pack yielded the WIP slot and stays yielded until the user
|
|
65
|
+
replies; fall through to the next tier.
|
|
66
|
+
2. **Babysit** — my loop-opened PRs (ReviewPR cards, pack finale PRs
|
|
67
|
+
included): red CI → fix now (on a pack finale, directly on the pack
|
|
68
|
+
branch); request-changes or unanswered review comments → address now;
|
|
69
|
+
green and quiet → leave alone.
|
|
70
|
+
3. **Claim** the next card (below).
|
|
71
|
+
4. **Idle** — nothing claimable: arm the board-event wake (below), then pace long.
|
|
72
|
+
|
|
73
|
+
## Claiming
|
|
74
|
+
|
|
75
|
+
1. `mcp__conveyor__list_tasks` with `status: "Open"` — results are already
|
|
76
|
+
priority-then-newest ordered; board priority IS the intelligence, don't
|
|
77
|
+
invent your own ranking. Walk top-down, `mcp__conveyor__get_task` each until
|
|
78
|
+
one passes: created by me, no assignee or active session, an executable
|
|
79
|
+
plan (a pack parent that still needs breakdown is fine — breakdown is
|
|
80
|
+
pack-mode work), all `mcp__conveyor__get_dependencies` blockers Complete,
|
|
81
|
+
no `[local-loop] parked:` chat marker without a later human reply (a reply
|
|
82
|
+
un-parks), and the pack rules hold: a FEATURE-BRANCH pack parent (children
|
|
83
|
+
branch from and PR into a pack branch — including one planned as a pack
|
|
84
|
+
that has no children yet) is claimed as a PACK → pack mode below; a
|
|
85
|
+
non-feature-branch parent, whose children PR straight into dev, is never
|
|
86
|
+
claimable — take its children one at a time instead; a card with a
|
|
87
|
+
`parentTaskId` only while the parent's status is neither InProgress nor
|
|
88
|
+
ReviewPR (see ground rules).
|
|
89
|
+
Skip `followParentStatus` mirror children. A blocker counts as met only
|
|
90
|
+
when merged-or-beyond (ReviewDev/ReviewLive/Complete) or Cancelled — a
|
|
91
|
+
blocker sitting in ReviewPR is NOT met until its PR merges.
|
|
92
|
+
2. Claim: re-confirm via `get_task` it is still Open, then
|
|
93
|
+
`mcp__conveyor__update_task` → `status: "InProgress"`, then
|
|
94
|
+
`mcp__conveyor__post_to_chat`: `[local-loop] claimed — working locally on
|
|
95
|
+
<hostname>`. Claiming a PACK is different — never set the parent
|
|
96
|
+
InProgress: leave it Open and post the pack claim marker instead (see Pack
|
|
97
|
+
mode). Status changed under you → someone else took it; next
|
|
98
|
+
candidate.
|
|
99
|
+
3. Plan missing or failing the context-free-reader bar → don't wing it: post
|
|
100
|
+
what's missing to chat, leave the card Open, skip it.
|
|
101
|
+
|
|
102
|
+
## Execute and finish
|
|
103
|
+
|
|
104
|
+
**Execution is [conveyor-build](../conveyor-build/SKILL.md)** — resolving the
|
|
105
|
+
card, branching from its base, working the plan, gating, and opening the PR
|
|
106
|
+
with an explicit `base:`. That skill is the source of truth; do not re-derive
|
|
107
|
+
its procedure here. It routes a childless card to its task path and a
|
|
108
|
+
feature-branch pack to its pack path automatically.
|
|
109
|
+
|
|
110
|
+
This section adds only what the LOOP changes:
|
|
111
|
+
|
|
112
|
+
- **Chat markers carry the loop's prefix**, `[local-loop]` rather than
|
|
113
|
+
`[build]`, because the Recover tier greps for them to find its own work.
|
|
114
|
+
- **A pack child yields to a live coordinator.** Before opening a child's PR,
|
|
115
|
+
re-check the parent's status; if it went InProgress or ReviewPR, post
|
|
116
|
+
`[local-loop] parked: pack coordinator active — yielding`, leave the branch
|
|
117
|
+
pushed, and let the coordinator take over.
|
|
118
|
+
- **Do not wait on CI.** Confirm it started (read-only `gh pr checks`) and end
|
|
119
|
+
the iteration — the Babysit tier owns it from there. This is the loop's one
|
|
120
|
+
real departure from a standalone build, which stays with its PR.
|
|
121
|
+
|
|
122
|
+
**Parked protocol** — after 2 genuinely different failed approaches, or on a
|
|
123
|
+
decision only the user can make: post `[local-loop] parked: <reason + the
|
|
124
|
+
specific question>`, set status back to `"Open"`, restore the tree
|
|
125
|
+
(`git checkout dev`), move on. The user's next chat reply is the un-park
|
|
126
|
+
signal.
|
|
127
|
+
|
|
128
|
+
## Pack mode
|
|
129
|
+
|
|
130
|
+
Claiming an Open pack parent means driving the ENTIRE pack, exactly per
|
|
131
|
+
[conveyor-build's pack path](../conveyor-build/references/pack-path.md) —
|
|
132
|
+
setup (pack branch on origin, the `githubBranch` write-through, child breakdown
|
|
133
|
+
if the parent has none yet), children serially in dependency order,
|
|
134
|
+
reviewer-of-record review + merge of each child PR into the pack branch,
|
|
135
|
+
dev→pack sync after every merge, cross-reference, then the finale parent PR
|
|
136
|
+
into dev. That reference is the source of truth for the procedure; this section
|
|
137
|
+
only defines how it embeds in the loop:
|
|
138
|
+
|
|
139
|
+
- The pack occupies the loop's single WIP slot from claim until the finale PR
|
|
140
|
+
opens. Do not interleave unrelated cards mid-pack — that thrashes branch
|
|
141
|
+
state.
|
|
142
|
+
- Claim marker goes to the PARENT chat: `[local-loop] claimed — driving this
|
|
143
|
+
pack locally on <hostname>, pack branch <branch>`. The parent's status
|
|
144
|
+
stays Open (parked); the marker is the claim.
|
|
145
|
+
- Once the finale PR is open (parent in ReviewPR), the pack leaves the WIP
|
|
146
|
+
slot: its PR joins the Babysit tier like any other loop-opened PR, and the
|
|
147
|
+
loop resumes claiming other cards. This is the one difference from
|
|
148
|
+
a standalone conveyor-build pack run, which stops when the pack is done.
|
|
149
|
+
- Parked children follow the pack path's parked protocol. If every
|
|
150
|
+
remaining child is blocked on the user, the pack yields the WIP slot: post
|
|
151
|
+
`[local-loop] parked: <what it is waiting on>` to the PARENT chat — that
|
|
152
|
+
marker is what makes the Recover tier skip the pack — and the loop claims
|
|
153
|
+
other cards. The user's chat reply un-parks it, and the next Recover tier
|
|
154
|
+
retakes the slot.
|
|
155
|
+
|
|
156
|
+
## Waking on board events
|
|
157
|
+
|
|
158
|
+
An empty queue is not a quiet board. Rather than sleeping blind for 25 minutes,
|
|
159
|
+
arm `conveyor-wait`: a CLI in `@rallycry/conveyor-mcp` that subscribes to the
|
|
160
|
+
project's live card stream and exits the moment a card ENTERS a claimable
|
|
161
|
+
state. A card created Open, a Cancelled card reopened, and a card reassigned to
|
|
162
|
+
you all count; an edit to a card that already matched does not.
|
|
163
|
+
|
|
164
|
+
Arm it on an idle iteration only (tier 4), and only when no wait from an earlier
|
|
165
|
+
iteration is still running:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
node_modules/.bin/conveyor-wait --scope mine,unclaimed --timeout 1740
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Launch it with Bash `run_in_background: true` and end the turn. Its completion
|
|
172
|
+
notification is the wake. The `ScheduleWakeup` you still arm is the fallback for
|
|
173
|
+
the case where the wait dies silently — use the pacing table's background-gate
|
|
174
|
+
row (1200–1800s), not a second, shorter timer.
|
|
175
|
+
|
|
176
|
+
- Prefer `node_modules/.bin/conveyor-wait`. If it is absent, use
|
|
177
|
+
`npx -y -p @rallycry/conveyor-mcp@latest conveyor-wait`. The `-p` form
|
|
178
|
+
matters: inside the conveyor monorepo a bare
|
|
179
|
+
`npx @rallycry/conveyor-mcp` misresolves.
|
|
180
|
+
- Narrow `--types` to whatever focus the user gave the loop invocation —
|
|
181
|
+
"focus on incidents" → `--types incident`. The default watches tasks,
|
|
182
|
+
incidents, and suggestions.
|
|
183
|
+
- `--scope mine,unclaimed` mirrors the claiming filter: cards assigned to the
|
|
184
|
+
session owner plus unassigned cards. Use `--scope all` only when the user
|
|
185
|
+
asked the loop to watch the whole board.
|
|
186
|
+
- `--statuses` defaults to `Open`, which is the claimable lane. Leave it alone
|
|
187
|
+
unless the user asked for something else.
|
|
188
|
+
- Credentials come from the environment, then any `.mcp.json` from the working
|
|
189
|
+
directory up, then `~/.claude.json`. An agent Bash shell does not inherit the
|
|
190
|
+
MCP server's environment, so that file fallback is what makes this work at
|
|
191
|
+
all. Exit 1 means the wait could not run: no credentials, a rejected token, or
|
|
192
|
+
a project it cannot read. Read the stderr line, report it once, fall back to
|
|
193
|
+
plain timed polling, and do not re-arm it every iteration.
|
|
194
|
+
|
|
195
|
+
**The result is advisory — the queue is still the source of truth.** The CLI
|
|
196
|
+
prints one line of JSON and exits 0 in every non-error case:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
{"reason":"event","card":{"id":…,"slug":…,"title":…,"type":…,"status":…,"assignedUserId":…}}
|
|
200
|
+
{"reason":"timeout"}
|
|
201
|
+
{"reason":"interrupted"}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
On wake, run a normal iteration and re-enumerate with
|
|
205
|
+
`mcp__conveyor__list_tasks`. By then the card may be claimed, cancelled, or
|
|
206
|
+
blocked by a dependency — never claim straight from the wait payload.
|
|
207
|
+
|
|
208
|
+
**Never arm a second wait.** On a wake where a wait process is still in flight
|
|
209
|
+
and the queue is still empty, re-arm the fallback `ScheduleWakeup` and end the
|
|
210
|
+
turn.
|
|
211
|
+
|
|
212
|
+
## Pacing (dynamic /loop only)
|
|
213
|
+
|
|
214
|
+
Under `/loop` with no interval, end EVERY iteration with exactly one
|
|
215
|
+
`ScheduleWakeup` (prompt = the original /loop input verbatim):
|
|
216
|
+
|
|
217
|
+
| State | Delay | Reason should say |
|
|
218
|
+
|-------|-------|-------------------|
|
|
219
|
+
| A background gate/agent/conveyor-wait is in flight — its completion notification is the real wake | 1200–1800s fallback | "fallback while <gate> runs — its notification wakes me sooner" |
|
|
220
|
+
| ANY actionable work exists: claimable cards or packs, a pack child to implement/merge, a PR still to open, red/pending CI, review comments | 60–90s | queue depth / which item is next |
|
|
221
|
+
| Queue enumerated as empty THIS iteration, all loop PRs green and quiet | 1200–1800s | queue empty; conveyor-wait armed, so this is only the fallback |
|
|
222
|
+
| Loop-fatal: MCP dead after 2 tries, dirty tree, broken repo | notify the user (PushNotification if available), then 1800s — or `stop: true` if continuing is unsafe | what is wrong |
|
|
223
|
+
|
|
224
|
+
The long idle tier is EARNED, never defaulted: it requires having enumerated
|
|
225
|
+
the queue this very iteration and found zero actionable work. When unsure
|
|
226
|
+
which tier applies, take the short one — a wasted 60s wake costs less than a
|
|
227
|
+
30-minute stall on live work.
|
|
228
|
+
|
|
229
|
+
Invoked bare (no /loop)? Run one iteration, report, and suggest
|
|
230
|
+
`/loop /conveyor-local-loop` — don't self-schedule.
|
|
231
|
+
|
|
232
|
+
## Offload valve (opt-in)
|
|
233
|
+
|
|
234
|
+
Only with an explicit `offload=N` argument: when 4+ claimable cards queue up,
|
|
235
|
+
`mcp__conveyor__start_task` up to N of the smallest into claudespaces and say
|
|
236
|
+
so in the iteration summary. Without the argument, never — just report backlog
|
|
237
|
+
depth each iteration so the user can offload manually.
|
|
238
|
+
|
|
239
|
+
## What this is not
|
|
240
|
+
|
|
241
|
+
- Not a reviewer of anything headed for `dev`: never `approve_task`,
|
|
242
|
+
`request_changes`, or `approve_and_merge_pr` on a PR into `dev` — including
|
|
243
|
+
a pack's final parent PR. **The one exception is a pack's CHILD PRs into the
|
|
244
|
+
pack branch**, where you are the reviewer of record because the automated
|
|
245
|
+
reviewer skips that target; the pack path spells out that duty.
|
|
246
|
+
- Not a pod: no sandbox, no WIP snapshots, and the dev DB + dev-server ports
|
|
247
|
+
are shared with the user's interactive sessions — no destructive
|
|
248
|
+
experiments, never reset the dev DB, reuse a running dev stack rather than
|
|
249
|
+
fighting over ports.
|
|
250
|
+
- Not a parallel executor: one card (or one pack) at a time is the point (the
|
|
251
|
+
full machine per gate). Backlogged? That is what claudespaces — or the
|
|
252
|
+
offload valve — are for.
|
|
253
|
+
|
|
254
|
+
## Improve This Skill
|
|
255
|
+
|
|
256
|
+
If this skill was insufficient or slowed the work down, file it with
|
|
257
|
+
`mcp__conveyor__create_suggestion` on the Conveyor project: the issue,
|
|
258
|
+
evidence, and proposed fix.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: conveyor-meeting-review
|
|
3
|
+
description: Turn a Conveyor meeting into confirmed cards, packs, and glossary updates — read the meeting and its transcript, cross-reference what already exists, draft proposals at the plan-quality bar, and create only what a human confirms item by item. Use when the user says "/conveyor-meeting-review <meeting>", "turn that meeting into cards", "what should we do about yesterday's call", or asks for the follow-ups from a meeting. Never creates anything unasked.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Conveyor Meeting Review
|
|
7
|
+
|
|
8
|
+
A meeting becomes work only when a person says which parts should. This skill does the reading, the cross-referencing, and the drafting — and then **stops and asks**.
|
|
9
|
+
|
|
10
|
+
## The one rule
|
|
11
|
+
|
|
12
|
+
**Never create, edit, or tag anything before a human confirms that specific item.** Not "shall I proceed?" and then everything — item by item, so "create 1 and 3, skip 2" is a normal answer.
|
|
13
|
+
|
|
14
|
+
This is not caution for its own sake. A meeting transcript is full of things that *sound* like decisions: someone thinking out loud, an idea that was argued down two minutes later, a "we should probably…" that nobody agreed to. An agent that creates cards from those is manufacturing work the team never chose, on a board they have to clean up. The summary's `## Proposed Next Steps` is a **starting point, not a mandate** — it was written by a model reading the same ambiguous transcript.
|
|
15
|
+
|
|
16
|
+
## 1 — Read
|
|
17
|
+
|
|
18
|
+
1. `mcp__conveyor__get_connection_context` — where you are. Same call in a pod and a local MCP session.
|
|
19
|
+
2. `mcp__conveyor__get_meeting` — the overview, the decisions, the proposed next steps, and the participants. **This usually answers the question.** It costs a fraction of the transcript.
|
|
20
|
+
3. `mcp__conveyor__read_meeting_transcript` — only when you need exact wording: a quote, a caveat, the reasoning behind a decision the summary merely states, or a check on whether something was actually agreed. Page with `offset`/`nextOffset` rather than pulling the whole thing.
|
|
21
|
+
|
|
22
|
+
If `status` is `processing` the summary is still being written — read the transcript, or say so and offer to come back. If `status` is `failed`, `summaryError` says why; the transcript is still complete and readable.
|
|
23
|
+
|
|
24
|
+
## 2 — Cross-reference before drafting anything
|
|
25
|
+
|
|
26
|
+
Skipping this is how a meeting review produces four cards that duplicate work already in flight.
|
|
27
|
+
|
|
28
|
+
- `mcp__conveyor__list_tags` — the project's vocabulary. Use its words in your proposals; a card that names the same thing differently is a card nobody finds.
|
|
29
|
+
- `mcp__conveyor__search_tasks` — **two or three keyword variants per proposed topic**, across `task`, `incident` and `suggestion`. One search misses the card that used the other word for it.
|
|
30
|
+
- `mcp__conveyor__read_task_chat` on anything that looks close. The overlap is usually in the discussion, not the title.
|
|
31
|
+
|
|
32
|
+
Then say what you found, including the negatives: "this one already exists as `fix-the-thing`", "nothing on the board covers this", "there is a suggestion arguing the opposite".
|
|
33
|
+
|
|
34
|
+
## 3 — Draft at the plan-quality bar
|
|
35
|
+
|
|
36
|
+
Each proposal a context-free reader could execute: what changes, where (file paths where you know them), and how it is verified. The `/conveyor-plan` skill's `references/plan-format.md` is the bar. A one-line card that says "improve onboarding" is not a proposal, it is a note.
|
|
37
|
+
|
|
38
|
+
Classify honestly:
|
|
39
|
+
|
|
40
|
+
- **A card** — one coherent piece of work.
|
|
41
|
+
- **A pack** — a parent plus children, when the work has real internal ordering. Do not inflate a card into a pack for ceremony.
|
|
42
|
+
- **An edit to an existing card** — usually better than a new one when something is already in flight. Say which card and what changes.
|
|
43
|
+
- **A tag update** — the glossary learned a word.
|
|
44
|
+
- **A suggestion** — the meeting raised something worth recording that nobody has decided to do. This is the honest home for "we should look into X someday", and it keeps the board clean.
|
|
45
|
+
- **Nothing** — some meetings produce no work. Say so rather than finding something.
|
|
46
|
+
|
|
47
|
+
## 4 — Present and wait
|
|
48
|
+
|
|
49
|
+
Number the proposals. For each: the type, the title, one sentence of what it is, and — critically — **what in the meeting supports it**, with a speaker and roughly when. A proposal whose evidence you cannot name is one you inferred, and it should be labelled as such or dropped.
|
|
50
|
+
|
|
51
|
+
Flag separately:
|
|
52
|
+
|
|
53
|
+
- **Decisions that need a human**, which a card cannot settle.
|
|
54
|
+
- **Contradictions** — where the meeting disagreed with itself, or with a card already on the board.
|
|
55
|
+
- **Things you deliberately did not propose**, and why. That is often the most useful part.
|
|
56
|
+
|
|
57
|
+
Then wait. If the reply is partial ("1 and 3"), create exactly those.
|
|
58
|
+
|
|
59
|
+
## 5 — Create, and stamp the provenance
|
|
60
|
+
|
|
61
|
+
Only the confirmed items, through the normal card tools — `create_task`, `create_subtask`, `add_dependency`, `update_task`, `manage_tags`, `create_suggestion`. There is no meeting-specific write path, on purpose: a card born from a meeting should be indistinguishable from any other card, and reviewable the same way.
|
|
62
|
+
|
|
63
|
+
**Stamp every created card with the meeting link** from `get_meeting`'s `url` field, in the description or the plan. Six weeks later "why does this card exist" is a real question, and the answer should be one click away.
|
|
64
|
+
|
|
65
|
+
Report back with what was created and what was skipped.
|
|
66
|
+
|
|
67
|
+
## Environment notes
|
|
68
|
+
|
|
69
|
+
- All Conveyor tools are **fully qualified** (`mcp__conveyor__get_meeting`); bare names fail.
|
|
70
|
+
- The meeting tools are **deferred** — reach them via ToolSearch rather than expecting them preloaded.
|
|
71
|
+
- They appear only for a project that HAS meetings. If they are absent, the project has none; say so instead of hunting.
|
|
72
|
+
- A pod and a local MCP session run this identically. The only difference is where you report: in a pod, card chat.
|