@rallycry/conveyor-agent 11.0.18 → 11.0.20
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-4ZNOCKFZ.js → boot-Z3EBJ7GX.js} +2 -2
- package/dist/{chunk-SR66HQKB.js → chunk-37J5MMQT.js} +1 -1
- package/dist/{chunk-WS7QRB37.js → chunk-JBGPARLG.js} +1 -1
- package/dist/{chunk-ZFHN7GO7.js → chunk-POK3QCGN.js} +465 -114
- package/dist/{chunk-GL2DIQEQ.js → chunk-Q4FQOJ7D.js} +23 -4
- package/dist/{chunk-GZRZGBIK.js → chunk-SKTNJNXQ.js} +2 -2
- package/dist/cli.js +11 -10
- package/dist/index.d.ts +18 -0
- package/dist/index.js +4 -4
- package/dist/{serve-boot-RU5BYIK4.js → serve-boot-4BUN4U44.js} +3 -3
- package/package.json +1 -1
- package/skills/conveyor-build/SKILL.md +36 -0
- package/skills/conveyor-build/references/pack-path.md +28 -7
- package/skills/conveyor-plan/SKILL.md +32 -1
- package/skills/conveyor-review/SKILL.md +28 -2
|
@@ -128,7 +128,7 @@ function errText(err) {
|
|
|
128
128
|
}
|
|
129
129
|
async function syncTaskBranchToRepo(deps, paths) {
|
|
130
130
|
const { git, log } = deps;
|
|
131
|
-
const { branch
|
|
131
|
+
const { branch } = deps.bundle.gitPlan;
|
|
132
132
|
try {
|
|
133
133
|
await git(["remote", "set-url", "origin", paths.remoteUrl], {
|
|
134
134
|
cwd: paths.repoDir,
|
|
@@ -140,6 +140,18 @@ async function syncTaskBranchToRepo(deps, paths) {
|
|
|
140
140
|
}
|
|
141
141
|
const credentialFailure = await persistCredentialHelper(deps, paths);
|
|
142
142
|
if (credentialFailure) return credentialFailure;
|
|
143
|
+
const [, resetSucceeded] = await Promise.all([
|
|
144
|
+
warmBaseBranch(deps, paths),
|
|
145
|
+
resetTrackedChanges(deps, paths)
|
|
146
|
+
]);
|
|
147
|
+
if (!resetSucceeded) return { state: "failed", reason: "pre-checkout reset failed" };
|
|
148
|
+
log.info(`[boot] Repo remote ready; agent will checkout ${branch}`);
|
|
149
|
+
return { state: "ready" };
|
|
150
|
+
}
|
|
151
|
+
async function warmBaseBranch(deps, paths) {
|
|
152
|
+
const { git, log } = deps;
|
|
153
|
+
const { baseBranch } = deps.bundle.gitPlan;
|
|
154
|
+
const started = performance.now();
|
|
143
155
|
try {
|
|
144
156
|
await git(["fetch", "origin", `+refs/heads/${baseBranch}:refs/remotes/origin/${baseBranch}`], {
|
|
145
157
|
cwd: paths.repoDir,
|
|
@@ -147,17 +159,24 @@ async function syncTaskBranchToRepo(deps, paths) {
|
|
|
147
159
|
});
|
|
148
160
|
} catch (err) {
|
|
149
161
|
log.warn(`[boot] WARN: fetch origin/${baseBranch} failed: ${errText(err)}`);
|
|
162
|
+
} finally {
|
|
163
|
+
log.info(`[boot] step=gitFetchBase ms=${Math.round(performance.now() - started)}`);
|
|
150
164
|
}
|
|
165
|
+
}
|
|
166
|
+
async function resetTrackedChanges(deps, paths) {
|
|
167
|
+
const { git, log } = deps;
|
|
168
|
+
const started = performance.now();
|
|
151
169
|
try {
|
|
152
170
|
await git(["reset", "--hard", "HEAD"], { cwd: paths.repoDir, timeoutMs: QUICK_GIT_TIMEOUT_MS });
|
|
171
|
+
return true;
|
|
153
172
|
} catch (err) {
|
|
154
173
|
log.error(
|
|
155
174
|
`[boot] ERROR: failed to clean tracked repo changes before checkout: ${errText(err)}`
|
|
156
175
|
);
|
|
157
|
-
return
|
|
176
|
+
return false;
|
|
177
|
+
} finally {
|
|
178
|
+
log.info(`[boot] step=gitResetTracked ms=${Math.round(performance.now() - started)}`);
|
|
158
179
|
}
|
|
159
|
-
log.info(`[boot] Repo remote ready; agent will checkout ${branch}`);
|
|
160
|
-
return { state: "ready" };
|
|
161
180
|
}
|
|
162
181
|
async function persistCredentialHelper(deps, paths) {
|
|
163
182
|
try {
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
readWorkspaceBytes,
|
|
6
6
|
statWorkspacePath,
|
|
7
7
|
workspacePathExists
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JBGPARLG.js";
|
|
9
9
|
import {
|
|
10
10
|
reportBootMilestone
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Q4FQOJ7D.js";
|
|
12
12
|
import {
|
|
13
13
|
runSetupCommand,
|
|
14
14
|
runStartCommand,
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WorkspaceCommandSupervisor,
|
|
8
8
|
startWorkspaceCommandsAfterConnect,
|
|
9
9
|
stopWorkspaceCommands
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SKTNJNXQ.js";
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_SONNET_MODEL,
|
|
13
13
|
PtyHarness,
|
|
@@ -26,9 +26,10 @@ import {
|
|
|
26
26
|
resolveTuiAdapter,
|
|
27
27
|
resolveTuiKindFromEnv,
|
|
28
28
|
runUsageProbe,
|
|
29
|
-
sampleKeyUsage
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
sampleKeyUsage,
|
|
30
|
+
usesNativeUsageReporting
|
|
31
|
+
} from "./chunk-POK3QCGN.js";
|
|
32
|
+
import "./chunk-37J5MMQT.js";
|
|
32
33
|
import {
|
|
33
34
|
inheritedEnv,
|
|
34
35
|
resolvePtySpawn,
|
|
@@ -44,8 +45,8 @@ import {
|
|
|
44
45
|
createServiceLogger,
|
|
45
46
|
fetchBootstrap,
|
|
46
47
|
loadConveyorConfig
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import "./chunk-
|
|
48
|
+
} from "./chunk-JBGPARLG.js";
|
|
49
|
+
import "./chunk-Q4FQOJ7D.js";
|
|
49
50
|
import "./chunk-W4LZ7R6Z.js";
|
|
50
51
|
import "./chunk-372R6E4C.js";
|
|
51
52
|
import "./chunk-IA45XHOA.js";
|
|
@@ -236,7 +237,7 @@ var ProjectSessionRunner = class {
|
|
|
236
237
|
/** Report the running subscription key's rate-limit utilization (same path as
|
|
237
238
|
* the task runner). Best-effort — never throws, no-op without an OAuth token. */
|
|
238
239
|
async sampleAndReportKeyUsage() {
|
|
239
|
-
if (this.stopped) return;
|
|
240
|
+
if (this.stopped || usesNativeUsageReporting()) return;
|
|
240
241
|
const codingAgentKeyId = process.env.CONVEYOR_CODING_AGENT_KEY_ID;
|
|
241
242
|
const { samples, unmeasurable } = await sampleKeyUsage(
|
|
242
243
|
process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
@@ -575,7 +576,7 @@ var AdhocSessionRunner = class {
|
|
|
575
576
|
}
|
|
576
577
|
/** Single-key fallback: sample only the key this pod booted under. */
|
|
577
578
|
async sampleAndReportOwnKey() {
|
|
578
|
-
if (this.stopped) return;
|
|
579
|
+
if (this.stopped || usesNativeUsageReporting()) return;
|
|
579
580
|
const codingAgentKeyId = process.env.CONVEYOR_CODING_AGENT_KEY_ID;
|
|
580
581
|
const { samples, unmeasurable } = await sampleKeyUsage(
|
|
581
582
|
process.env.CLAUDE_CODE_OAUTH_TOKEN,
|
|
@@ -1205,7 +1206,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
|
|
|
1205
1206
|
|
|
1206
1207
|
// src/cli.ts
|
|
1207
1208
|
if (process.argv[2] === "boot") {
|
|
1208
|
-
const { runBoot } = await import("./boot-
|
|
1209
|
+
const { runBoot } = await import("./boot-Z3EBJ7GX.js");
|
|
1209
1210
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1210
1211
|
}
|
|
1211
1212
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1458,7 +1459,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
|
|
|
1458
1459
|
process.exit(1);
|
|
1459
1460
|
}
|
|
1460
1461
|
if (CONVEYOR_MODE === "serving") {
|
|
1461
|
-
const { runServingSession } = await import("./serve-boot-
|
|
1462
|
+
const { runServingSession } = await import("./serve-boot-4BUN4U44.js");
|
|
1462
1463
|
exitContext.runnerMode = "serving";
|
|
1463
1464
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
|
|
1464
1465
|
const outcome = await runServingSession({
|
package/dist/index.d.ts
CHANGED
|
@@ -1107,6 +1107,20 @@ declare class SessionRunner {
|
|
|
1107
1107
|
* the tool starts work that outlives the turn. */
|
|
1108
1108
|
private noteToolUseForBackgroundWork;
|
|
1109
1109
|
private setState;
|
|
1110
|
+
/**
|
|
1111
|
+
* A submitted PTY query can park on an unexpected terminal dialog without
|
|
1112
|
+
* returning its turn. Keep the runner's local state (which drives heartbeat
|
|
1113
|
+
* liveness) in sync with that specific watchdog signal, but do not emit it
|
|
1114
|
+
* again: QueryBridge already sent it.
|
|
1115
|
+
*
|
|
1116
|
+
* Retry delays and pending questionnaires also report `waiting_for_input`,
|
|
1117
|
+
* but they retain their existing bounded liveness holds and must not change
|
|
1118
|
+
* `_state` here.
|
|
1119
|
+
*/
|
|
1120
|
+
private applySubmittedPtyParkedStatus;
|
|
1121
|
+
/** Forward an ordinary query status without changing liveness for transient
|
|
1122
|
+
* waiting states. The submitted-PTY watchdog calls its dedicated handler. */
|
|
1123
|
+
private handleQueryStatus;
|
|
1110
1124
|
/** Mark a fresh turn without emitting a duplicate status. QueryExecutor's
|
|
1111
1125
|
* prefilled PTY callback already emitted `running` before it reaches here. */
|
|
1112
1126
|
private beginRunningEpisode;
|
|
@@ -1165,6 +1179,10 @@ type UserQuestionSignal = {
|
|
|
1165
1179
|
interface AgentRunnerCallbacks {
|
|
1166
1180
|
onEvent: (event: Record<string, unknown>) => void | Promise<void>;
|
|
1167
1181
|
onStatusChange: (status: string) => void | Promise<void>;
|
|
1182
|
+
/** Fired only when a submitted PTY query stays silent past the parked-TUI
|
|
1183
|
+
* grace window. This differs from ordinary `waiting_for_input` reports:
|
|
1184
|
+
* retry delays and questionnaires keep the runner locally live. */
|
|
1185
|
+
onSubmittedPtyParked?: () => void;
|
|
1168
1186
|
/** Optional — fired on question-pending transitions (see UserQuestionSignal). */
|
|
1169
1187
|
onUserQuestion?: (signal: UserQuestionSignal) => void;
|
|
1170
1188
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SessionRunner,
|
|
3
3
|
unshallowRepo
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-POK3QCGN.js";
|
|
5
|
+
import "./chunk-37J5MMQT.js";
|
|
6
6
|
import "./chunk-W5INK3NE.js";
|
|
7
7
|
import {
|
|
8
8
|
AgentConnection,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
stageAndCommit,
|
|
18
18
|
updateRemoteToken,
|
|
19
19
|
workspacePathExists
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-JBGPARLG.js";
|
|
21
|
+
import "./chunk-Q4FQOJ7D.js";
|
|
22
22
|
import {
|
|
23
23
|
runAuthTokenCommand,
|
|
24
24
|
runSetupCommand,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkspaceCommandSupervisor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SKTNJNXQ.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentConnection,
|
|
6
6
|
CodespacePortVisibility,
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
createServiceLogger,
|
|
12
12
|
ensureOnTaskBranch,
|
|
13
13
|
loadConveyorConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-JBGPARLG.js";
|
|
15
|
+
import "./chunk-Q4FQOJ7D.js";
|
|
16
16
|
import "./chunk-W4LZ7R6Z.js";
|
|
17
17
|
import "./chunk-IA45XHOA.js";
|
|
18
18
|
import "./chunk-SQM2BQ7H.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.20",
|
|
4
4
|
"description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -38,6 +38,42 @@ out in an **Environment** note — never assume; check which one you are in.
|
|
|
38
38
|
serially. Parallel fan-out is a deliberate choice the user makes by pressing
|
|
39
39
|
Build on the parent, not something a build session opts into.
|
|
40
40
|
|
|
41
|
+
## Goal and finish line
|
|
42
|
+
|
|
43
|
+
Which goal applies depends on the route below. State it once, then hold it: a
|
|
44
|
+
run ends when its finish line is true, not earlier.
|
|
45
|
+
|
|
46
|
+
**Task path goal:** a pull request for this card.
|
|
47
|
+
**Finish line:** the card in ReviewPR, the PR open, CI started. Then aftercare
|
|
48
|
+
per `## Aftercare` — in a pod you stay wake-able; standalone locally you stop.
|
|
49
|
+
**A task turn may end only when:** a harness-tracked background gate is in
|
|
50
|
+
flight (Claude Code only); you are blocked on a human with the question posted;
|
|
51
|
+
or the finish line is true.
|
|
52
|
+
|
|
53
|
+
**Pack path goal:** the WHOLE pack, not one child. Per child the goal covers
|
|
54
|
+
the full cycle: plan reviewed and promoted → implemented on the pack branch →
|
|
55
|
+
gated → reviewer-of-record pass → merged (locally) or
|
|
56
|
+
`mcp__conveyor__update_task` → ReviewDev (pod) → base synced. Then
|
|
57
|
+
cross-reference, then the finale.
|
|
58
|
+
**Finish line:** every child is ReviewDev, Complete, or Cancelled AND the
|
|
59
|
+
parent's finale PR into the base branch is open with CI started. One child done
|
|
60
|
+
is not the finish line. A turn that ends with a ready child and no wake armed
|
|
61
|
+
is the failure this section exists to prevent.
|
|
62
|
+
**A pack turn may end only when:** a harness-tracked background gate is in
|
|
63
|
+
flight (Claude Code only — Codex holds the gate's command session open
|
|
64
|
+
instead); you are blocked on a human with the parked protocol posted; or the
|
|
65
|
+
finale PR is open and green-and-quiet. Nothing else. Anything else is a stalled
|
|
66
|
+
run, not a paused one.
|
|
67
|
+
|
|
68
|
+
**Runtime:** *Codex CLI* — before the first step (Setup step 1 on the pack
|
|
69
|
+
path), create a thread goal with your goal tool whose objective is the finish
|
|
70
|
+
line sentence for this route, naming the card slug. Call `update_goal` with
|
|
71
|
+
`complete` only when that finish line is true (for a pack: the finale PR is
|
|
72
|
+
open); `blocked` only per the parked protocol; never because the budget is
|
|
73
|
+
low. *Claude Code* — there is no goal tool; the pacing rule in
|
|
74
|
+
[references/pack-path.md](references/pack-path.md) is the loop, and its pack
|
|
75
|
+
heartbeat is the fallback.
|
|
76
|
+
|
|
41
77
|
## Environment
|
|
42
78
|
|
|
43
79
|
Resolve which one you are in before touching git or the filesystem.
|
|
@@ -96,18 +96,39 @@ End a turn with children remaining ONLY when a wake is guaranteed:
|
|
|
96
96
|
|
|
97
97
|
- **A background gate is in flight.** Its completion notification re-invokes
|
|
98
98
|
you. (Launch it with the harness's `run_in_background`; hand-rolled
|
|
99
|
-
backgrounding wakes nothing.)
|
|
99
|
+
backgrounding wakes nothing.) *Codex CLI substitution:* Codex has no
|
|
100
|
+
background gate. Hold the gate's command session open until it returns an
|
|
101
|
+
exit result, then continue in the same turn — ending the turn is not how a
|
|
102
|
+
Codex runner waits.
|
|
100
103
|
- **You are blocked on a human** — the parked protocol below. The user's chat
|
|
101
104
|
reply is the wake.
|
|
102
105
|
- **The finale PR is open and quiet** — the Babysit tier. Green and quiet is
|
|
103
106
|
the end.
|
|
104
107
|
|
|
105
|
-
Any other end-of-turn
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
pack
|
|
108
|
+
Any other end-of-turn is runtime-specific:
|
|
109
|
+
|
|
110
|
+
**Claude Code.** Arm `ScheduleWakeup` first: 60–90s, prompt restating which
|
|
111
|
+
child comes next. That is the pod-sanctioned mechanism (the pod prompt allows
|
|
112
|
+
`ScheduleWakeup` exactly when nothing else will notify you), and it is a rare
|
|
113
|
+
exception, not the cadence. On top of it, run a **pack heartbeat**: at Setup,
|
|
114
|
+
before the first child, arm ONE long fallback wake (`ScheduleWakeup`,
|
|
115
|
+
1200–1500s) whose prompt is the pack continuation — "re-derive with
|
|
116
|
+
`mcp__conveyor__list_subtasks` and take the next ready child; if nothing is
|
|
117
|
+
ready and no gate is in flight, stop" — and re-arm it at every child boundary
|
|
118
|
+
so exactly one is outstanding. A heartbeat that fires mid-work re-derives
|
|
119
|
+
state and is a no-op. This is NOT the "insurance wakeup" the pod prompt
|
|
120
|
+
forbids: that rule is about a background job's own completion notification,
|
|
121
|
+
which does fire. Nothing at all notifies a pack between children, so the
|
|
122
|
+
heartbeat is the only guaranteed wake a Claude pack has. Do not delete it.
|
|
123
|
+
|
|
124
|
+
**Codex CLI.** There is no `ScheduleWakeup` and no `/loop`. The thread goal
|
|
125
|
+
created per the SKILL.md *Goal and finish line* section is the continuation:
|
|
126
|
+
an idle thread is re-prompted to keep working toward it. The only way to leave
|
|
127
|
+
a child ready is therefore to keep working in the same turn — merge, next
|
|
128
|
+
child, merge. Mark the goal complete only when the finale PR is open.
|
|
129
|
+
|
|
130
|
+
Never end a turn "to report progress" — in either runtime, chat is where
|
|
131
|
+
progress goes, and posting there does not end the pack.
|
|
111
132
|
|
|
112
133
|
**Pre-exit invariant.** Before ending ANY turn, re-run
|
|
113
134
|
`mcp__conveyor__list_subtasks`. A child that is `Open` with its dependencies
|
|
@@ -19,6 +19,34 @@ identification decides.** Moving the card to Open fires identification
|
|
|
19
19
|
automatically (story points, icon, agent, and tags if you set none). Never set
|
|
20
20
|
icon or story points yourself, and never `start_task` unless the user asks.
|
|
21
21
|
|
|
22
|
+
## Goal and finish line
|
|
23
|
+
|
|
24
|
+
**Goal:** a plan on this card that a context-free executor can build, or one
|
|
25
|
+
batched round of questions for a human when scope is genuinely ambiguous.
|
|
26
|
+
**Finish line:** the plan is saved with `mcp__conveyor__update_task` AND the
|
|
27
|
+
recommendation is posted with `mcp__conveyor__post_to_chat` and
|
|
28
|
+
`milestone: "plan_ready"`. In a pod, story points and risk are also set
|
|
29
|
+
(`mcp__conveyor__update_task_properties`) and plan mode is exited.
|
|
30
|
+
**A turn may end only when:** (a) the finish line above is true, or (b) an
|
|
31
|
+
`AskUserQuestion` is pending. Nothing else. Anything else is a stalled run, not
|
|
32
|
+
a paused one.
|
|
33
|
+
|
|
34
|
+
**Never ask whether to start building, and never offer to.** Once the plan is
|
|
35
|
+
saved, the handoff is not yours: in the cloud the system spawns a separate
|
|
36
|
+
Builder session for the card, and locally a human runs `/conveyor-build` when
|
|
37
|
+
they are ready. Until one of those happens, every further turn on this card is
|
|
38
|
+
a plan iteration — read the feedback, revise, re-save, re-post `plan_ready`.
|
|
39
|
+
Do not claim the card, do not touch the tree, and do not invoke
|
|
40
|
+
`/conveyor-build` unprompted. (Locally the user may ask for it in the same
|
|
41
|
+
session; that request is the only trigger.)
|
|
42
|
+
|
|
43
|
+
**Runtime:** *Codex CLI* — before Phase 0, create a thread goal with your goal
|
|
44
|
+
tool whose objective is: "Save a plan on card <slug> that a context-free
|
|
45
|
+
builder can execute, or ask the blocking questions; do not start
|
|
46
|
+
implementation." Mark it complete only when the finish line is true, never
|
|
47
|
+
because the budget is low. *Claude Code* — there is no goal tool; the finish
|
|
48
|
+
line and the two turn endings above are the loop.
|
|
49
|
+
|
|
22
50
|
## Phase 0 — Resolve context
|
|
23
51
|
|
|
24
52
|
1. `mcp__conveyor__get_connection_context` (all Conveyor tools fully-qualified;
|
|
@@ -135,7 +163,10 @@ touching Conveyor, unless they asked you to just ship it.
|
|
|
135
163
|
> does not exist in a pod. In a pod, the card exists and you are on it: save
|
|
136
164
|
> the plan with `mcp__conveyor__update_task` (`plan`, and `description` if it
|
|
137
165
|
> needs sharpening), post the same recommendation message to chat with
|
|
138
|
-
> `milestone: "plan_ready"`, and stop
|
|
166
|
+
> `milestone: "plan_ready"`, and stop. "Stop" means end the turn with no
|
|
167
|
+
> question about starting work — per *Goal and finish line*, the Builder is a
|
|
168
|
+
> separate session the system spawns, and every later turn here is a plan
|
|
169
|
+
> iteration. A pod does not promote its own card to
|
|
139
170
|
> Open. A parked plan is never `blocked`: that milestone means you cannot
|
|
140
171
|
> continue until a human acts, and it pages nobody. To page a person, ask them
|
|
141
172
|
> with AskUserQuestion. If the pod also has to leave
|
|
@@ -26,6 +26,30 @@ process, this skill loses: a project's own rules outrank a general one.
|
|
|
26
26
|
PR touches are not this PR's job — note them in chat if they matter, or file
|
|
27
27
|
a suggestion, but do not block on them.
|
|
28
28
|
|
|
29
|
+
## Goal and finish line
|
|
30
|
+
|
|
31
|
+
**Goal:** one verdict on this PR.
|
|
32
|
+
**Finish line:** the environment's verdict tool returned success —
|
|
33
|
+
`mcp__conveyor__approve_code_review` / `mcp__conveyor__request_code_changes`
|
|
34
|
+
in a pod, `mcp__conveyor__approve_task` / `mcp__conveyor__request_changes`
|
|
35
|
+
locally — OR a blocked note is posted with the specific blocker and no verdict
|
|
36
|
+
(the `## Blocked` case).
|
|
37
|
+
**A turn may end only when:** (a) the verdict call succeeded — read the
|
|
38
|
+
response; a "superseded by a newer review cycle" error is not success; (b) the
|
|
39
|
+
blocked note is posted; or (c) you pushed your own fix and are waiting for CI
|
|
40
|
+
before approving. Nothing else. Findings posted with no verdict called is a
|
|
41
|
+
stalled review, not a paused one.
|
|
42
|
+
|
|
43
|
+
**Reviewer of record for a pack child** has no verdict tool: its finish line is
|
|
44
|
+
the merge (locally) or the `mcp__conveyor__update_task` → ReviewDev write
|
|
45
|
+
(pod), and the pack path's goal wording in conveyor-build governs instead.
|
|
46
|
+
|
|
47
|
+
**Runtime:** *Codex CLI* — before reading the change, create a thread goal with
|
|
48
|
+
your goal tool: "Render exactly one review verdict on PR <n> for card <slug>."
|
|
49
|
+
Mark it complete only after the verdict call succeeded, never because the
|
|
50
|
+
budget is low. *Claude Code* — there is no goal tool; the finish line above is
|
|
51
|
+
the loop.
|
|
52
|
+
|
|
29
53
|
## Read the change
|
|
30
54
|
|
|
31
55
|
1. `mcp__conveyor__get_task` for the plan — you cannot judge "does this do what
|
|
@@ -142,8 +166,10 @@ is the reviewer, and the independent review happens later on the pack's PR into
|
|
|
142
166
|
|
|
143
167
|
- Apply the same criteria above. The absence of an automated pass makes this
|
|
144
168
|
review more load-bearing, not less.
|
|
145
|
-
- There is **no verdict tool** — merging the child PR
|
|
146
|
-
|
|
169
|
+
- There is **no verdict tool** — merging the child PR (locally) or the
|
|
170
|
+
`mcp__conveyor__update_task` → ReviewDev write (pod) is the approval, and
|
|
171
|
+
that write or merge is this review's finish line; the pack path's goal
|
|
172
|
+
wording applies. Say what you checked in chat so the record exists.
|
|
147
173
|
- You wrote this code, which makes self-review the weak point. An independent
|
|
148
174
|
reviewer with the diff and no memory of writing it catches what you cannot.
|
|
149
175
|
|