@rallycry/conveyor-agent 7.1.0 → 7.1.1

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.
@@ -503,7 +503,7 @@ var ModeController = class {
503
503
  }
504
504
  get isReadOnly() {
505
505
  const m = this.effectiveMode;
506
- if (["discovery", "code-review", "help"].includes(m)) return true;
506
+ if (["discovery", "help"].includes(m)) return true;
507
507
  return m === "auto" && !this._hasExitedPlanMode;
508
508
  }
509
509
  get isAutoPlanning() {
@@ -511,13 +511,13 @@ var ModeController = class {
511
511
  }
512
512
  get isBuildCapable() {
513
513
  const m = this.effectiveMode;
514
- return m === "building" || m === "auto" && this._hasExitedPlanMode;
514
+ return m === "building" || m === "review" || m === "auto" && this._hasExitedPlanMode;
515
515
  }
516
516
  // ── Mode resolution ────────────────────────────────────────────────
517
517
  /** Resolve the initial mode based on task context */
518
518
  resolveInitialMode(context) {
519
519
  if (this._runnerMode === "code-review") {
520
- this._mode = "code-review";
520
+ this._mode = "review";
521
521
  return this._mode;
522
522
  }
523
523
  if (this._mode === "auto" && this.canBypassPlanning(context)) {
@@ -536,8 +536,12 @@ var ModeController = class {
536
536
  // ── Mode transitions ───────────────────────────────────────────────
537
537
  /** Handle mode change from server */
538
538
  handleModeChange(newMode) {
539
- if (this._runnerMode !== "pm") return { type: "noop" };
540
539
  if (newMode === this._mode) return { type: "noop" };
540
+ if (this._runnerMode === "task" && newMode === "review") {
541
+ this._mode = newMode;
542
+ return { type: "restart_query", newMode: "review" };
543
+ }
544
+ if (this._runnerMode !== "pm") return { type: "noop" };
541
545
  this._mode = newMode;
542
546
  this.updateExitedPlanModeFlag(newMode);
543
547
  if (this.isBuildCapable) {
@@ -811,6 +815,28 @@ function updateRemoteToken(cwd, token) {
811
815
  } catch {
812
816
  }
813
817
  }
818
+ async function flushPendingChanges(cwd, opts) {
819
+ let committed = false;
820
+ let pushed = false;
821
+ let hadWork = false;
822
+ try {
823
+ if (hasUncommittedChanges(cwd)) {
824
+ hadWork = true;
825
+ const message = opts?.wipMessage ?? "WIP: auto-commit on conveyor-agent shutdown";
826
+ const hash = stageAndCommit(cwd, message);
827
+ committed = hash !== null;
828
+ }
829
+ } catch {
830
+ }
831
+ try {
832
+ if (hasUnpushedCommits(cwd)) {
833
+ hadWork = true;
834
+ pushed = await pushToOrigin(cwd, opts?.refreshToken);
835
+ }
836
+ } catch {
837
+ }
838
+ return { committed, pushed, hadWork };
839
+ }
814
840
  async function pushToOrigin(cwd, refreshToken) {
815
841
  try {
816
842
  const currentBranch = getCurrentBranch(cwd);
@@ -922,6 +948,8 @@ var PlanSync = class {
922
948
 
923
949
  // ../shared/dist/index.js
924
950
  import { z } from "zod";
951
+ import { z as z2 } from "zod";
952
+ import { z as z3 } from "zod";
925
953
  var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
926
954
  var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
927
955
  var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
@@ -1144,157 +1172,6 @@ var UpdateChildStatusRequestSchema = z.object({
1144
1172
  childTaskId: z.string(),
1145
1173
  status: z.string()
1146
1174
  });
1147
- var RegisterProjectAgentRequestSchema = z.object({
1148
- projectId: z.string(),
1149
- capabilities: z.array(z.string())
1150
- });
1151
- var ProjectRunnerHeartbeatRequestSchema = z.object({
1152
- projectId: z.string()
1153
- });
1154
- var ReportProjectAgentStatusRequestSchema = z.object({
1155
- projectId: z.string(),
1156
- status: z.enum(["busy", "idle"]),
1157
- activeChatId: z.string().nullish(),
1158
- activeTaskId: z.string().nullish(),
1159
- activeBranch: z.string().nullish()
1160
- });
1161
- var DisconnectProjectRunnerRequestSchema = z.object({
1162
- projectId: z.string()
1163
- });
1164
- var GetProjectAgentContextRequestSchema = z.object({
1165
- projectId: z.string()
1166
- });
1167
- var GetProjectChatHistoryRequestSchema = z.object({
1168
- projectId: z.string(),
1169
- limit: z.number().int().positive().optional().default(50),
1170
- chatId: z.string().optional()
1171
- });
1172
- var PostProjectAgentMessageRequestSchema = z.object({
1173
- projectId: z.string(),
1174
- content: z.string().min(1),
1175
- chatId: z.string().optional()
1176
- });
1177
- var ListProjectTasksRequestSchema = z.object({
1178
- projectId: z.string(),
1179
- status: z.string().optional(),
1180
- assigneeId: z.string().optional(),
1181
- limit: z.number().int().positive().optional().default(50)
1182
- });
1183
- var GetProjectTaskRequestSchema = z.object({
1184
- projectId: z.string(),
1185
- taskId: z.string()
1186
- });
1187
- var SearchProjectTasksRequestSchema = z.object({
1188
- projectId: z.string(),
1189
- tagNames: z.array(z.string()).optional(),
1190
- searchQuery: z.string().optional(),
1191
- statusFilters: z.array(z.string()).optional(),
1192
- limit: z.number().int().positive().optional().default(20)
1193
- });
1194
- var ListProjectTagsRequestSchema = z.object({
1195
- projectId: z.string()
1196
- });
1197
- var GetProjectSummaryRequestSchema = z.object({
1198
- projectId: z.string()
1199
- });
1200
- var CreateProjectTaskRequestSchema = z.object({
1201
- projectId: z.string(),
1202
- title: z.string().min(1),
1203
- description: z.string().optional(),
1204
- plan: z.string().optional(),
1205
- status: z.string().optional(),
1206
- isBug: z.boolean().optional()
1207
- });
1208
- var UpdateProjectTaskRequestSchema = z.object({
1209
- projectId: z.string(),
1210
- taskId: z.string(),
1211
- title: z.string().optional(),
1212
- description: z.string().optional(),
1213
- plan: z.string().optional(),
1214
- status: z.string().optional(),
1215
- assignedUserId: z.string().nullish()
1216
- });
1217
- var ReportProjectAgentEventRequestSchema = z.object({
1218
- projectId: z.string(),
1219
- event: z.record(z.string(), z.unknown())
1220
- });
1221
- var ReportTagAuditProgressRequestSchema = z.object({
1222
- projectId: z.string(),
1223
- requestId: z.string(),
1224
- activity: z.object({
1225
- tool: z.string(),
1226
- input: z.string().optional(),
1227
- timestamp: z.string()
1228
- })
1229
- });
1230
- var ReportTagAuditResultRequestSchema = z.object({
1231
- projectId: z.string(),
1232
- requestId: z.string(),
1233
- recommendations: z.array(z.record(z.string(), z.unknown())),
1234
- summary: z.string(),
1235
- complete: z.boolean()
1236
- });
1237
- var ReportNewCommitsDetectedRequestSchema = z.object({
1238
- projectId: z.string(),
1239
- commits: z.array(
1240
- z.object({
1241
- sha: z.string(),
1242
- message: z.string(),
1243
- author: z.string()
1244
- })
1245
- ),
1246
- branch: z.string()
1247
- });
1248
- var ReportEnvironmentReadyRequestSchema = z.object({
1249
- projectId: z.string(),
1250
- branch: z.string(),
1251
- setupComplete: z.boolean(),
1252
- startCommandRunning: z.boolean()
1253
- });
1254
- var ReportEnvSwitchProgressRequestSchema = z.object({
1255
- projectId: z.string(),
1256
- step: z.string(),
1257
- progress: z.number(),
1258
- message: z.string().optional()
1259
- });
1260
- var ForwardProjectChatMessageRequestSchema = z.object({
1261
- projectId: z.string(),
1262
- chatId: z.string(),
1263
- content: z.string().min(1),
1264
- targetUserId: z.string().optional()
1265
- });
1266
- var CancelQueuedProjectMessageRequestSchema = z.object({
1267
- projectId: z.string(),
1268
- index: z.number().int().nonnegative()
1269
- });
1270
- var GetProjectCliHistoryRequestSchema = z.object({
1271
- projectId: z.string(),
1272
- limit: z.number().int().positive().optional().default(50),
1273
- source: z.string().optional()
1274
- });
1275
- var PostToProjectTaskChatRequestSchema = z.object({
1276
- projectId: z.string(),
1277
- taskId: z.string(),
1278
- content: z.string()
1279
- });
1280
- var GetProjectTaskCliRequestSchema = z.object({
1281
- projectId: z.string(),
1282
- taskId: z.string(),
1283
- limit: z.number().int().positive().optional().default(50),
1284
- source: z.string().optional()
1285
- });
1286
- var StartProjectBuildRequestSchema = z.object({
1287
- projectId: z.string(),
1288
- taskId: z.string()
1289
- });
1290
- var StopProjectBuildRequestSchema = z.object({
1291
- projectId: z.string(),
1292
- taskId: z.string()
1293
- });
1294
- var ApproveProjectMergePRRequestSchema = z.object({
1295
- projectId: z.string(),
1296
- childTaskId: z.string()
1297
- });
1298
1175
  var GetAgentStatusRequestSchema = z.object({
1299
1176
  taskId: z.string()
1300
1177
  });
@@ -1390,7 +1267,200 @@ var RegisterProjectAgentResponseSchema = z.object({
1390
1267
  agentSettings: z.record(z.string(), z.unknown()).nullable(),
1391
1268
  branchSwitchCommand: z.string().nullable()
1392
1269
  });
1393
- var CRITICAL_AUTOMATED_SOURCES = /* @__PURE__ */ new Set(["ci_failure"]);
1270
+ var RegisterProjectAgentRequestSchema = z2.object({
1271
+ projectId: z2.string(),
1272
+ capabilities: z2.array(z2.string())
1273
+ });
1274
+ var ProjectRunnerHeartbeatRequestSchema = z2.object({
1275
+ projectId: z2.string()
1276
+ });
1277
+ var ReportProjectAgentStatusRequestSchema = z2.object({
1278
+ projectId: z2.string(),
1279
+ status: z2.enum(["busy", "idle"]),
1280
+ activeChatId: z2.string().nullish(),
1281
+ activeTaskId: z2.string().nullish(),
1282
+ activeBranch: z2.string().nullish()
1283
+ });
1284
+ var DisconnectProjectRunnerRequestSchema = z2.object({
1285
+ projectId: z2.string()
1286
+ });
1287
+ var GetProjectAgentContextRequestSchema = z2.object({
1288
+ projectId: z2.string()
1289
+ });
1290
+ var GetProjectChatHistoryRequestSchema = z2.object({
1291
+ projectId: z2.string(),
1292
+ limit: z2.number().int().positive().optional().default(50),
1293
+ chatId: z2.string().optional()
1294
+ });
1295
+ var PostProjectAgentMessageRequestSchema = z2.object({
1296
+ projectId: z2.string(),
1297
+ content: z2.string().min(1),
1298
+ chatId: z2.string().optional()
1299
+ });
1300
+ var ListProjectTasksRequestSchema = z2.object({
1301
+ projectId: z2.string(),
1302
+ status: z2.string().optional(),
1303
+ assigneeId: z2.string().optional(),
1304
+ limit: z2.number().int().positive().optional().default(50)
1305
+ });
1306
+ var GetProjectTaskRequestSchema = z2.object({
1307
+ projectId: z2.string(),
1308
+ taskId: z2.string()
1309
+ });
1310
+ var SearchProjectTasksRequestSchema = z2.object({
1311
+ projectId: z2.string(),
1312
+ tagNames: z2.array(z2.string()).optional(),
1313
+ searchQuery: z2.string().optional(),
1314
+ statusFilters: z2.array(z2.string()).optional(),
1315
+ limit: z2.number().int().positive().optional().default(20)
1316
+ });
1317
+ var ListProjectTagsRequestSchema = z2.object({
1318
+ projectId: z2.string()
1319
+ });
1320
+ var GetProjectSummaryRequestSchema = z2.object({
1321
+ projectId: z2.string()
1322
+ });
1323
+ var CreateProjectTaskRequestSchema = z2.object({
1324
+ projectId: z2.string(),
1325
+ title: z2.string().min(1),
1326
+ description: z2.string().optional(),
1327
+ plan: z2.string().optional(),
1328
+ status: z2.string().optional(),
1329
+ isBug: z2.boolean().optional()
1330
+ });
1331
+ var UpdateProjectTaskRequestSchema = z2.object({
1332
+ projectId: z2.string(),
1333
+ taskId: z2.string(),
1334
+ title: z2.string().optional(),
1335
+ description: z2.string().optional(),
1336
+ plan: z2.string().optional(),
1337
+ status: z2.string().optional(),
1338
+ assignedUserId: z2.string().nullish()
1339
+ });
1340
+ var ReportProjectAgentEventRequestSchema = z2.object({
1341
+ projectId: z2.string(),
1342
+ event: z2.record(z2.string(), z2.unknown())
1343
+ });
1344
+ var ReportTagAuditProgressRequestSchema = z2.object({
1345
+ projectId: z2.string(),
1346
+ requestId: z2.string(),
1347
+ activity: z2.object({
1348
+ tool: z2.string(),
1349
+ input: z2.string().optional(),
1350
+ timestamp: z2.string()
1351
+ })
1352
+ });
1353
+ var ReportTagAuditResultRequestSchema = z2.object({
1354
+ projectId: z2.string(),
1355
+ requestId: z2.string(),
1356
+ recommendations: z2.array(z2.record(z2.string(), z2.unknown())),
1357
+ summary: z2.string(),
1358
+ complete: z2.boolean()
1359
+ });
1360
+ var ReportNewCommitsDetectedRequestSchema = z2.object({
1361
+ projectId: z2.string(),
1362
+ commits: z2.array(
1363
+ z2.object({
1364
+ sha: z2.string(),
1365
+ message: z2.string(),
1366
+ author: z2.string()
1367
+ })
1368
+ ),
1369
+ branch: z2.string()
1370
+ });
1371
+ var ReportEnvironmentReadyRequestSchema = z2.object({
1372
+ projectId: z2.string(),
1373
+ branch: z2.string(),
1374
+ setupComplete: z2.boolean(),
1375
+ startCommandRunning: z2.boolean()
1376
+ });
1377
+ var ReportEnvSwitchProgressRequestSchema = z2.object({
1378
+ projectId: z2.string(),
1379
+ step: z2.string(),
1380
+ progress: z2.number(),
1381
+ message: z2.string().optional()
1382
+ });
1383
+ var ForwardProjectChatMessageRequestSchema = z2.object({
1384
+ projectId: z2.string(),
1385
+ chatId: z2.string(),
1386
+ content: z2.string().min(1),
1387
+ targetUserId: z2.string().optional()
1388
+ });
1389
+ var CancelQueuedProjectMessageRequestSchema = z2.object({
1390
+ projectId: z2.string(),
1391
+ index: z2.number().int().nonnegative()
1392
+ });
1393
+ var GetProjectCliHistoryRequestSchema = z2.object({
1394
+ projectId: z2.string(),
1395
+ limit: z2.number().int().positive().optional().default(50),
1396
+ source: z2.string().optional()
1397
+ });
1398
+ var PostToProjectTaskChatRequestSchema = z2.object({
1399
+ projectId: z2.string(),
1400
+ taskId: z2.string(),
1401
+ content: z2.string()
1402
+ });
1403
+ var GetProjectTaskCliRequestSchema = z2.object({
1404
+ projectId: z2.string(),
1405
+ taskId: z2.string(),
1406
+ limit: z2.number().int().positive().optional().default(50),
1407
+ source: z2.string().optional()
1408
+ });
1409
+ var StartProjectBuildRequestSchema = z2.object({
1410
+ projectId: z2.string(),
1411
+ taskId: z2.string()
1412
+ });
1413
+ var StopProjectBuildRequestSchema = z2.object({
1414
+ projectId: z2.string(),
1415
+ taskId: z2.string()
1416
+ });
1417
+ var ApproveProjectMergePRRequestSchema = z2.object({
1418
+ projectId: z2.string(),
1419
+ childTaskId: z2.string()
1420
+ });
1421
+ var CRITICAL_AUTOMATED_SOURCES = /* @__PURE__ */ new Set(["ci_failure", "review_trigger"]);
1422
+ var StartTaskAuditRequestSchema = z3.object({
1423
+ projectId: z3.string(),
1424
+ taskIds: z3.array(z3.string()).min(1)
1425
+ });
1426
+ var ReportTaskAuditProgressRequestSchema = z3.object({
1427
+ projectId: z3.string(),
1428
+ requestId: z3.string(),
1429
+ taskId: z3.string(),
1430
+ activity: z3.string()
1431
+ });
1432
+ var ReportTaskAuditResultRequestSchema = z3.object({
1433
+ projectId: z3.string(),
1434
+ requestId: z3.string(),
1435
+ taskId: z3.string(),
1436
+ summary: z3.string(),
1437
+ turnGrades: z3.array(
1438
+ z3.object({
1439
+ turnIndex: z3.number(),
1440
+ phase: z3.enum(["planning", "building", "human"]),
1441
+ grade: z3.enum(["correct", "neutral", "blunder"]),
1442
+ reasoning: z3.string(),
1443
+ eventType: z3.string(),
1444
+ eventSummary: z3.string()
1445
+ })
1446
+ ),
1447
+ planningAccuracy: z3.number().nullable(),
1448
+ buildingAccuracy: z3.number().nullable(),
1449
+ humanAccuracy: z3.number().nullable(),
1450
+ planningCorrect: z3.number(),
1451
+ planningNeutral: z3.number(),
1452
+ planningBlunder: z3.number(),
1453
+ buildingCorrect: z3.number(),
1454
+ buildingNeutral: z3.number(),
1455
+ buildingBlunder: z3.number(),
1456
+ humanCorrect: z3.number(),
1457
+ humanNeutral: z3.number(),
1458
+ humanBlunder: z3.number(),
1459
+ suggestionIds: z3.array(z3.string()),
1460
+ auditCostUsd: z3.number().nullable(),
1461
+ model: z3.string().nullable(),
1462
+ error: z3.string().optional()
1463
+ });
1394
1464
 
1395
1465
  // src/execution/pack-runner-prompt.ts
1396
1466
  function findLastAgentMessageIndex(history) {
@@ -1882,8 +1952,6 @@ function buildModePrompt(agentMode, context) {
1882
1952
  return buildReviewPrompt(context);
1883
1953
  case "auto":
1884
1954
  return buildAutoPrompt(context);
1885
- case "code-review":
1886
- return buildCodeReviewPrompt();
1887
1955
  default:
1888
1956
  return null;
1889
1957
  }
@@ -1892,8 +1960,9 @@ function buildReviewPrompt(context) {
1892
1960
  const parts = [
1893
1961
  `
1894
1962
  ## Mode: Review`,
1895
- `You are in Review mode \u2014 reviewing and coordinating.`,
1896
- `- You have read-only access plus light edit capability (can suggest fixes, run tests, check linting)`,
1963
+ `You are in Review mode \u2014 performing code review with fix capability.`,
1964
+ `- You have full write access \u2014 you can audit code, make fixes, push changes, and run tests`,
1965
+ `- Safety rules: no destructive operations, use --force-with-lease instead of --force`,
1897
1966
  ``
1898
1967
  ];
1899
1968
  if (context?.isParentTask) {
@@ -1915,80 +1984,62 @@ function buildReviewPrompt(context) {
1915
1984
  );
1916
1985
  } else {
1917
1986
  parts.push(
1918
- `### Leaf Task Review`,
1919
- `You are reviewing your own work before completion.`,
1920
- `- Run tests and check linting to verify the PR is ready.`,
1921
- `- If the PR is already open, review the diff for correctness.`,
1922
- `- You can get hands dirty \u2014 if a fix is small, make it directly.`,
1923
- `- If follow-up work is needed, use \`create_follow_up_task\`.`
1987
+ `### Code Review Process`,
1988
+ `1. Run \`git diff <baseBranch>..HEAD\` to see all changes in this PR`,
1989
+ `2. Read the task plan to understand the intended changes`,
1990
+ `3. Explore the surrounding codebase to verify pattern consistency`,
1991
+ `4. Review against the criteria below`,
1992
+ ``,
1993
+ `### Review Criteria`,
1994
+ `- **Correctness**: Does the code do what the plan says? Logic errors, off-by-one, race conditions?`,
1995
+ `- **Pattern Consistency**: Does the code follow existing patterns in the codebase? Check nearby files.`,
1996
+ `- **Security**: No hardcoded secrets, no injection vulnerabilities, proper input validation at boundaries.`,
1997
+ `- **Performance**: No unnecessary loops, no N+1 queries, no blocking in async contexts.`,
1998
+ `- **Error Handling**: Appropriate error handling at system boundaries. No swallowed errors.`,
1999
+ `- **Test Coverage**: Are new code paths tested? Edge cases covered?`,
2000
+ `- **TypeScript Best Practices**: Proper typing (no unnecessary \`any\`), correct React patterns, proper async/await.`,
2001
+ `- **Naming & Readability**: Clear names, no misleading comments, self-documenting code.`,
2002
+ ``,
2003
+ `### Fix Capability`,
2004
+ `You have full write access. If you find issues:`,
2005
+ `- **Small fixes**: Make the fix directly, commit, and push. Then re-review.`,
2006
+ `- **Larger issues**: Use \`request_code_changes\` to flag them for the team.`,
2007
+ `- After pushing fixes, wait for CI to pass before approving.`,
2008
+ ``,
2009
+ `### Output \u2014 You MUST do exactly ONE of:`,
2010
+ ``,
2011
+ `#### If code passes review (or after you've fixed all issues):`,
2012
+ `Use the \`approve_code_review\` tool with a brief summary of what looks good.`,
2013
+ ``,
2014
+ `#### If changes are needed that you cannot fix:`,
2015
+ `Use the \`request_code_changes\` tool with specific issues:`,
2016
+ `- Reference specific files and line numbers`,
2017
+ `- Explain what's wrong and suggest fixes`,
2018
+ `- Focus on substantive issues, not style nitpicks (linting handles that)`,
2019
+ ``,
2020
+ `### Previous Review Feedback`,
2021
+ `If previous review feedback is present in the chat history, verify those specific issues were addressed before raising new concerns.`,
2022
+ ``,
2023
+ `### Rules`,
2024
+ `- Do NOT re-review things CI already validates (formatting, lint rules).`,
2025
+ `- Be concise \u2014 actionable specifics over general observations.`,
2026
+ `- Max 5-7 issues per review. Prioritize the most important ones.`
1924
2027
  );
1925
2028
  }
1926
- parts.push(
1927
- ``,
1928
- `### General Review Guidelines`,
1929
- `- For larger issues, create a follow-up task rather than fixing directly.`,
1930
- `- Focus on correctness, pattern consistency, and test coverage.`,
1931
- `- Be concise in feedback \u2014 actionable specifics over general observations.`,
1932
- `- Goal: ensure quality, provide feedback, coordinate progression.`
1933
- );
1934
2029
  if (process.env.CLAUDESPACE_NAME) {
1935
2030
  parts.push(
1936
2031
  ``,
1937
2032
  `### Resource Management`,
1938
- `Your pod starts with minimal resources (0.25 CPU / 1 Gi). You MUST call \`scale_up_resources\``,
1939
- `BEFORE running any of these operations \u2014 they WILL fail or OOM at baseline resources:`,
1940
- `- **light** (1 CPU / 4 Gi) \u2014 bun/npm/yarn install, pip install, basic dev servers, light builds`,
1941
- `- **standard** (2 CPU / 8 Gi) \u2014 full dev servers, test suites, typecheck, lint`,
1942
- `- **heavy** (4 CPU / 16 Gi) \u2014 E2E/browser automation, large parallel builds`,
2033
+ `Your pod starts with minimal resources. You MUST call \`scale_up_resources\``,
2034
+ `BEFORE running any resource-intensive operations \u2014 they WILL fail or OOM at baseline resources:`,
2035
+ `- **setup** \u2014 package installs, basic dev servers, light builds`,
2036
+ `- **build** \u2014 full dev servers, test suites, typecheck, lint, E2E tests`,
1943
2037
  `Scaling is one-way (up only) and capped by project limits.`,
1944
- `CRITICAL: Always scale to at least "light" before running any package install command.`
2038
+ `CRITICAL: Always scale to at least "setup" before running any package install command.`
1945
2039
  );
1946
2040
  }
1947
2041
  return parts.join("\n");
1948
2042
  }
1949
- function buildCodeReviewPrompt() {
1950
- return [
1951
- `
1952
- ## Mode: Code Review`,
1953
- `You are an automated code reviewer. A PR has passed all CI checks and you are performing a final code quality review before merge.`,
1954
- ``,
1955
- `## Review Process`,
1956
- `1. Run \`git diff <devBranch>..HEAD\` to see all changes in this PR`,
1957
- `2. Read the task plan to understand the intended changes`,
1958
- `3. Explore the surrounding codebase to verify pattern consistency`,
1959
- `4. Review against the criteria below`,
1960
- ``,
1961
- `### Review Criteria`,
1962
- `- **Correctness**: Does the code do what the plan says? Logic errors, off-by-one, race conditions?`,
1963
- `- **Pattern Consistency**: Does the code follow existing patterns in the codebase? Check nearby files.`,
1964
- `- **Security**: No hardcoded secrets, no injection vulnerabilities, proper input validation at boundaries.`,
1965
- `- **Performance**: No unnecessary loops, no N+1 queries, no blocking in async contexts.`,
1966
- `- **Error Handling**: Appropriate error handling at system boundaries. No swallowed errors.`,
1967
- `- **Test Coverage**: Are new code paths tested? Edge cases covered?`,
1968
- `- **TypeScript Best Practices**: Proper typing (no unnecessary \`any\`), correct React patterns, proper async/await.`,
1969
- `- **Naming & Readability**: Clear names, no misleading comments, self-documenting code.`,
1970
- ``,
1971
- `## Output \u2014 You MUST do exactly ONE of:`,
1972
- ``,
1973
- `### If code passes review:`,
1974
- `Use the \`approve_code_review\` tool with a brief summary of what looks good.`,
1975
- ``,
1976
- `### If changes are needed:`,
1977
- `Use the \`request_code_changes\` tool with specific issues:`,
1978
- `- Reference specific files and line numbers`,
1979
- `- Explain what's wrong and suggest fixes`,
1980
- `- Focus on substantive issues, not style nitpicks (linting handles that)`,
1981
- ``,
1982
- `## Previous Review Feedback`,
1983
- `If previous review feedback is present in the chat history, verify those specific issues were addressed before raising new concerns. Focus on whether the requested changes were implemented correctly.`,
1984
- ``,
1985
- `## Rules`,
1986
- `- You are READ-ONLY. Do NOT modify any files.`,
1987
- `- Do NOT re-review things CI already validates (formatting, lint rules).`,
1988
- `- Be concise \u2014 the task agent needs actionable feedback, not essays.`,
1989
- `- Max 5-7 issues per review. Prioritize the most important ones.`
1990
- ].join("\n");
1991
- }
1992
2043
 
1993
2044
  // src/execution/system-prompt.ts
1994
2045
  function formatProjectAgentLine(pa) {
@@ -2415,18 +2466,6 @@ ${context.plan}`);
2415
2466
  }
2416
2467
  return parts;
2417
2468
  }
2418
- function buildCodeReviewInstructions(context) {
2419
- const parts = [
2420
- `You are performing an automated code review for this task.`,
2421
- `The PR branch is "${context.githubBranch}"${context.baseBranch ? ` based on "${context.baseBranch}"` : ""}.`,
2422
- `Begin your code review by running \`git diff ${context.baseBranch ?? "dev"}..HEAD\` to see all changes.`,
2423
- ``,
2424
- `CRITICAL: You are in Code Review mode. You are READ-ONLY \u2014 do NOT modify any files.`,
2425
- `After reviewing, you MUST call exactly one of: \`approve_code_review\` or \`request_code_changes\`.`,
2426
- `Do NOT go idle, ask for confirmation, or wait for instructions \u2014 complete the review and exit.`
2427
- ];
2428
- return parts;
2429
- }
2430
2469
  function buildFreshInstructions(isPm, isAutoMode, context, agentMode) {
2431
2470
  if (isPm && agentMode === "building") {
2432
2471
  return [
@@ -2577,10 +2616,6 @@ function buildIdleRelaunchInstructions(context, isPm, agentMode, isAuto) {
2577
2616
  function buildInstructions(mode, context, scenario, agentMode, isAuto) {
2578
2617
  const parts = [`
2579
2618
  ## Instructions`];
2580
- if (agentMode === "code-review") {
2581
- parts.push(...buildCodeReviewInstructions(context));
2582
- return parts;
2583
- }
2584
2619
  const isPm = mode === "pm";
2585
2620
  if (scenario === "fresh") {
2586
2621
  parts.push(...buildFreshInstructions(isPm, agentMode === "auto", context, agentMode));
@@ -2595,7 +2630,7 @@ function buildInstructions(mode, context, scenario, agentMode, isAuto) {
2595
2630
  }
2596
2631
  async function buildInitialPrompt(mode, context, isAuto, agentMode) {
2597
2632
  const isPackRunner = mode === "pm" && !!isAuto && !!context.isParentTask;
2598
- if (!isPackRunner && agentMode !== "code-review") {
2633
+ if (!isPackRunner) {
2599
2634
  const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);
2600
2635
  if (sessionRelaunch) return sessionRelaunch;
2601
2636
  }
@@ -2610,7 +2645,7 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
2610
2645
  }
2611
2646
 
2612
2647
  // src/tools/common-tools.ts
2613
- import { z as z2 } from "zod";
2648
+ import { z as z4 } from "zod";
2614
2649
 
2615
2650
  // src/tools/helpers.ts
2616
2651
  function textResult(text) {
@@ -2644,8 +2679,8 @@ function buildReadTaskChatTool(connection) {
2644
2679
  "read_task_chat",
2645
2680
  "Read recent messages from a task chat. Omit task_id to read the current task's chat, or provide a child task ID to read a child's chat.",
2646
2681
  {
2647
- limit: z2.number().optional().describe("Number of recent messages to fetch (default 20)"),
2648
- task_id: z2.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
2682
+ limit: z4.number().optional().describe("Number of recent messages to fetch (default 20)"),
2683
+ task_id: z4.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
2649
2684
  },
2650
2685
  async ({ limit, task_id }) => {
2651
2686
  try {
@@ -2689,7 +2724,7 @@ function buildGetTaskTool(connection) {
2689
2724
  "get_task",
2690
2725
  "Look up a task by slug or ID to get its title, description, plan, and status",
2691
2726
  {
2692
- slug_or_id: z2.string().describe("The task slug (e.g. 'my-task') or CUID")
2727
+ slug_or_id: z4.string().describe("The task slug (e.g. 'my-task') or CUID")
2693
2728
  },
2694
2729
  async ({ slug_or_id }) => {
2695
2730
  try {
@@ -2712,9 +2747,9 @@ function buildGetTaskCliTool(connection) {
2712
2747
  "get_task_cli",
2713
2748
  "Read CLI execution logs from a task. Returns agent reasoning, tool calls, setup output, and other execution events. Use 'source' to filter: 'agent' for agent reasoning/tool calls only, 'application' for setup/dev-server output only.",
2714
2749
  {
2715
- task_id: z2.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
2716
- source: z2.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
2717
- limit: z2.number().optional().describe("Max number of log entries to return (default 50, max 500).")
2750
+ task_id: z4.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
2751
+ source: z4.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
2752
+ limit: z4.number().optional().describe("Max number of log entries to return (default 50, max 500).")
2718
2753
  },
2719
2754
  async ({ task_id, source, limit }) => {
2720
2755
  try {
@@ -2774,7 +2809,7 @@ function buildGetTaskFileTool(connection) {
2774
2809
  return defineTool(
2775
2810
  "get_task_file",
2776
2811
  "Get a specific task file's content and download URL by file ID",
2777
- { fileId: z2.string().describe("The file ID to retrieve") },
2812
+ { fileId: z4.string().describe("The file ID to retrieve") },
2778
2813
  async ({ fileId }) => {
2779
2814
  try {
2780
2815
  const file = await connection.call("getTaskFile", {
@@ -2805,8 +2840,8 @@ function buildSearchIncidentsTool(connection) {
2805
2840
  "search_incidents",
2806
2841
  "Search incidents in the current project. Optionally filter by status (Open, Acknowledged, Investigating, Resolved, Closed) or source.",
2807
2842
  {
2808
- status: z2.string().optional().describe("Filter by incident status"),
2809
- source: z2.string().optional().describe("Filter by source (e.g., 'conveyor', 'agent', 'build')")
2843
+ status: z4.string().optional().describe("Filter by incident status"),
2844
+ source: z4.string().optional().describe("Filter by source (e.g., 'conveyor', 'agent', 'build')")
2810
2845
  },
2811
2846
  async ({ status, source }) => {
2812
2847
  try {
@@ -2830,7 +2865,7 @@ function buildGetTaskIncidentsTool(connection) {
2830
2865
  "get_task_incidents",
2831
2866
  "Get all incidents linked to the current task (or a specified task). Returns full incident details including title, description, severity, status, and source.",
2832
2867
  {
2833
- task_id: z2.string().optional().describe("Task ID (defaults to current task)")
2868
+ task_id: z4.string().optional().describe("Task ID (defaults to current task)")
2834
2869
  },
2835
2870
  async ({ task_id }) => {
2836
2871
  try {
@@ -2853,12 +2888,12 @@ function buildQueryGcpLogsTool(connection) {
2853
2888
  "query_gcp_logs",
2854
2889
  "Query GCP Cloud Logging for the current project. Returns log entries matching the given filters. Use severity to filter by minimum log level. The project's GCP credentials are used automatically.",
2855
2890
  {
2856
- filter: z2.string().optional().describe(
2891
+ filter: z4.string().optional().describe(
2857
2892
  `Cloud Logging filter expression (e.g., 'resource.type="gce_instance"'). Max 1000 chars.`
2858
2893
  ),
2859
- start_time: z2.string().optional().describe("Start time in ISO 8601 format (e.g., '2024-01-01T00:00:00Z')"),
2860
- end_time: z2.string().optional().describe("End time in ISO 8601 format (e.g., '2024-01-02T00:00:00Z')"),
2861
- severity: z2.enum([
2894
+ start_time: z4.string().optional().describe("Start time in ISO 8601 format (e.g., '2024-01-01T00:00:00Z')"),
2895
+ end_time: z4.string().optional().describe("End time in ISO 8601 format (e.g., '2024-01-02T00:00:00Z')"),
2896
+ severity: z4.enum([
2862
2897
  "DEFAULT",
2863
2898
  "DEBUG",
2864
2899
  "INFO",
@@ -2869,7 +2904,7 @@ function buildQueryGcpLogsTool(connection) {
2869
2904
  "ALERT",
2870
2905
  "EMERGENCY"
2871
2906
  ]).optional().describe("Minimum severity level to filter by (default: all levels)"),
2872
- page_size: z2.number().optional().describe("Number of log entries to return (default 100, max 500)")
2907
+ page_size: z4.number().optional().describe("Number of log entries to return (default 100, max 500)")
2873
2908
  },
2874
2909
  async ({ filter, start_time, end_time, severity, page_size }) => {
2875
2910
  try {
@@ -2923,8 +2958,8 @@ function buildGetSuggestionsTool(connection) {
2923
2958
  "get_suggestions",
2924
2959
  "List project suggestions sorted by vote score. Use this to see what the team thinks is important.",
2925
2960
  {
2926
- status: z2.string().optional().describe("Filter by status: Open, Accepted, Rejected, Implemented"),
2927
- limit: z2.number().optional().describe("Max results (default 20)")
2961
+ status: z4.string().optional().describe("Filter by status: Open, Accepted, Rejected, Implemented"),
2962
+ limit: z4.number().optional().describe("Max results (default 20)")
2928
2963
  },
2929
2964
  async ({ status: _status, limit: _limit }) => {
2930
2965
  try {
@@ -2949,8 +2984,8 @@ function buildPostToChatTool(connection) {
2949
2984
  "post_to_chat",
2950
2985
  "Post a message to a task chat. Your normal replies already appear in chat \u2014 only use this for explicit out-of-band updates or posting to a child task's chat.",
2951
2986
  {
2952
- message: z2.string().describe("The message to post to the team"),
2953
- task_id: z2.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
2987
+ message: z4.string().describe("The message to post to the team"),
2988
+ task_id: z4.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
2954
2989
  },
2955
2990
  async ({ message, task_id }) => {
2956
2991
  try {
@@ -2977,8 +3012,8 @@ function buildForceUpdateTaskStatusTool(connection) {
2977
3012
  "force_update_task_status",
2978
3013
  "EMERGENCY ONLY: Force-override a task's Kanban status. Status transitions happen automatically (building sets InProgress, PR creation sets ReviewPR, merge sets ReviewDev). Only use this if an automatic transition failed or a task is stuck in the wrong status. Omit task_id to update the current task, or provide a child task ID.",
2979
3014
  {
2980
- status: z2.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
2981
- task_id: z2.string().optional().describe("Child task ID to update. Omit to update the current task.")
3015
+ status: z4.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
3016
+ task_id: z4.string().optional().describe("Child task ID to update. Omit to update the current task.")
2982
3017
  },
2983
3018
  async ({ status, task_id }) => {
2984
3019
  try {
@@ -3009,15 +3044,15 @@ function buildCreatePullRequestTool(connection, config) {
3009
3044
  "create_pull_request",
3010
3045
  "Create a GitHub pull request for this task. Automatically stages uncommitted changes, commits them, and pushes before creating the PR. Use this instead of gh CLI or git commands to create PRs.",
3011
3046
  {
3012
- title: z2.string().describe("The PR title"),
3013
- body: z2.string().describe("The PR description/body in markdown"),
3014
- branch: z2.string().optional().describe(
3047
+ title: z4.string().describe("The PR title"),
3048
+ body: z4.string().describe("The PR description/body in markdown"),
3049
+ branch: z4.string().optional().describe(
3015
3050
  "The head branch name for the PR. If the task doesn't have a branch set, this will be used. Defaults to the task's existing branch."
3016
3051
  ),
3017
- baseBranch: z2.string().optional().describe(
3052
+ baseBranch: z4.string().optional().describe(
3018
3053
  "The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
3019
3054
  ),
3020
- commitMessage: z2.string().optional().describe(
3055
+ commitMessage: z4.string().optional().describe(
3021
3056
  "Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
3022
3057
  )
3023
3058
  },
@@ -3095,7 +3130,7 @@ function buildAddDependencyTool(connection) {
3095
3130
  "add_dependency",
3096
3131
  "Add a dependency \u2014 this task cannot start until the specified task is merged to dev",
3097
3132
  {
3098
- depends_on_slug_or_id: z2.string().describe("Slug or ID of the task this task depends on")
3133
+ depends_on_slug_or_id: z4.string().describe("Slug or ID of the task this task depends on")
3099
3134
  },
3100
3135
  async ({ depends_on_slug_or_id }) => {
3101
3136
  try {
@@ -3117,7 +3152,7 @@ function buildRemoveDependencyTool(connection) {
3117
3152
  "remove_dependency",
3118
3153
  "Remove a dependency from this task",
3119
3154
  {
3120
- depends_on_slug_or_id: z2.string().describe("Slug or ID of the task to remove as dependency")
3155
+ depends_on_slug_or_id: z4.string().describe("Slug or ID of the task to remove as dependency")
3121
3156
  },
3122
3157
  async ({ depends_on_slug_or_id }) => {
3123
3158
  try {
@@ -3139,10 +3174,10 @@ function buildCreateFollowUpTaskTool(connection) {
3139
3174
  "create_follow_up_task",
3140
3175
  "Create a follow-up task in this project that depends on the current task. Use for out-of-scope work, v1.1 features, or cleanup that should happen after this task merges.",
3141
3176
  {
3142
- title: z2.string().describe("Follow-up task title"),
3143
- description: z2.string().optional().describe("Brief description of the follow-up work"),
3144
- plan: z2.string().optional().describe("Implementation plan if known"),
3145
- story_point_value: z2.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
3177
+ title: z4.string().describe("Follow-up task title"),
3178
+ description: z4.string().optional().describe("Brief description of the follow-up work"),
3179
+ plan: z4.string().optional().describe("Implementation plan if known"),
3180
+ story_point_value: z4.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
3146
3181
  },
3147
3182
  async ({ title, description, plan, story_point_value }) => {
3148
3183
  try {
@@ -3169,9 +3204,9 @@ function buildCreateSuggestionTool(connection) {
3169
3204
  "create_suggestion",
3170
3205
  "Suggest a feature, improvement, or idea for the project. If you want to recommend something \u2014 a document, a rule, a feature, a task, an optimization \u2014 use this tool. If a similar suggestion already exists, your vote will be added to it instead of creating a duplicate.",
3171
3206
  {
3172
- title: z2.string().describe("Short title for the suggestion"),
3173
- description: z2.string().optional().describe("Details about the suggestion"),
3174
- tag_names: z2.array(z2.string()).optional().describe("Tag names to categorize the suggestion")
3207
+ title: z4.string().describe("Short title for the suggestion"),
3208
+ description: z4.string().optional().describe("Details about the suggestion"),
3209
+ tag_names: z4.array(z4.string()).optional().describe("Tag names to categorize the suggestion")
3175
3210
  },
3176
3211
  async ({ title, description, tag_names }) => {
3177
3212
  try {
@@ -3200,8 +3235,8 @@ function buildVoteSuggestionTool(connection) {
3200
3235
  "vote_suggestion",
3201
3236
  "Vote on a project suggestion. Use +1 to upvote or -1 to downvote.",
3202
3237
  {
3203
- suggestion_id: z2.string().describe("The suggestion ID to vote on"),
3204
- value: z2.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
3238
+ suggestion_id: z4.string().describe("The suggestion ID to vote on"),
3239
+ value: z4.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
3205
3240
  },
3206
3241
  async ({ suggestion_id, value }) => {
3207
3242
  try {
@@ -3224,8 +3259,8 @@ function buildScaleUpResourcesTool(connection) {
3224
3259
  "scale_up_resources",
3225
3260
  "Scale up the pod's CPU and memory resources to the 'build' tier. Use before running heavy operations like full test suites, integration tests, typechecks, or production builds. Pods start at the 'setup' tier by default \u2014 only call this when you actually need more. Scaling is one-way (up only).",
3226
3261
  {
3227
- tier: z2.literal("build").describe("The resource phase to scale up to"),
3228
- reason: z2.string().optional().describe("Brief reason for scaling (e.g., 'running test suite')")
3262
+ tier: z4.literal("build").describe("The resource phase to scale up to"),
3263
+ reason: z4.string().optional().describe("Brief reason for scaling (e.g., 'running test suite')")
3229
3264
  },
3230
3265
  async ({ tier, reason }) => {
3231
3266
  try {
@@ -3278,15 +3313,15 @@ function buildCommonTools(connection, config) {
3278
3313
  }
3279
3314
 
3280
3315
  // src/tools/pm-tools.ts
3281
- import { z as z3 } from "zod";
3316
+ import { z as z5 } from "zod";
3282
3317
  var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
3283
3318
  function buildUpdateTaskTool(connection) {
3284
3319
  return defineTool(
3285
3320
  "update_task",
3286
3321
  "Save the finalized task plan and/or description",
3287
3322
  {
3288
- plan: z3.string().optional().describe("The task plan in markdown"),
3289
- description: z3.string().optional().describe("Updated task description")
3323
+ plan: z5.string().optional().describe("The task plan in markdown"),
3324
+ description: z5.string().optional().describe("Updated task description")
3290
3325
  },
3291
3326
  async ({ plan, description }) => {
3292
3327
  try {
@@ -3307,11 +3342,11 @@ function buildCreateSubtaskTool(connection) {
3307
3342
  "create_subtask",
3308
3343
  "Create a subtask under the current parent task. Use for breaking complex tasks into smaller pieces.",
3309
3344
  {
3310
- title: z3.string().describe("Subtask title"),
3311
- description: z3.string().optional().describe("Brief description"),
3312
- plan: z3.string().optional().describe("Implementation plan in markdown"),
3313
- ordinal: z3.number().optional().describe("Step/order number (0-based)"),
3314
- storyPointValue: z3.number().optional().describe(SP_DESCRIPTION)
3345
+ title: z5.string().describe("Subtask title"),
3346
+ description: z5.string().optional().describe("Brief description"),
3347
+ plan: z5.string().optional().describe("Implementation plan in markdown"),
3348
+ ordinal: z5.number().optional().describe("Step/order number (0-based)"),
3349
+ storyPointValue: z5.number().optional().describe(SP_DESCRIPTION)
3315
3350
  },
3316
3351
  async ({ title, description, plan, ordinal, storyPointValue }) => {
3317
3352
  try {
@@ -3337,12 +3372,12 @@ function buildUpdateSubtaskTool(connection) {
3337
3372
  "update_subtask",
3338
3373
  "Update an existing subtask's fields",
3339
3374
  {
3340
- subtaskId: z3.string().describe("The subtask ID to update"),
3341
- title: z3.string().optional(),
3342
- description: z3.string().optional(),
3343
- plan: z3.string().optional(),
3344
- ordinal: z3.number().optional(),
3345
- storyPointValue: z3.number().optional().describe(SP_DESCRIPTION)
3375
+ subtaskId: z5.string().describe("The subtask ID to update"),
3376
+ title: z5.string().optional(),
3377
+ description: z5.string().optional(),
3378
+ plan: z5.string().optional(),
3379
+ ordinal: z5.number().optional(),
3380
+ storyPointValue: z5.number().optional().describe(SP_DESCRIPTION)
3346
3381
  },
3347
3382
  async ({ subtaskId, title, description, plan, storyPointValue }) => {
3348
3383
  try {
@@ -3365,7 +3400,7 @@ function buildDeleteSubtaskTool(connection) {
3365
3400
  return defineTool(
3366
3401
  "delete_subtask",
3367
3402
  "Delete a subtask",
3368
- { subtaskId: z3.string().describe("The subtask ID to delete") },
3403
+ { subtaskId: z5.string().describe("The subtask ID to delete") },
3369
3404
  async ({ subtaskId }) => {
3370
3405
  try {
3371
3406
  await connection.call("deleteSubtask", {
@@ -3403,7 +3438,7 @@ function buildPackTools(connection) {
3403
3438
  "start_child_cloud_build",
3404
3439
  "Start a cloud build for a child task. The child must be in Open status with story points and an agent assigned.",
3405
3440
  {
3406
- childTaskId: z3.string().describe("The child task ID to start a cloud build for")
3441
+ childTaskId: z5.string().describe("The child task ID to start a cloud build for")
3407
3442
  },
3408
3443
  async ({ childTaskId }) => {
3409
3444
  try {
@@ -3423,7 +3458,7 @@ function buildPackTools(connection) {
3423
3458
  "stop_child_build",
3424
3459
  "Stop a running cloud build for a child task. Sends a stop signal to the child agent.",
3425
3460
  {
3426
- childTaskId: z3.string().describe("The child task ID whose build should be stopped")
3461
+ childTaskId: z5.string().describe("The child task ID whose build should be stopped")
3427
3462
  },
3428
3463
  async ({ childTaskId }) => {
3429
3464
  try {
@@ -3443,7 +3478,7 @@ function buildPackTools(connection) {
3443
3478
  "approve_and_merge_pr",
3444
3479
  "Approve and merge a child task's pull request. Only succeeds if all CI/CD checks are passing. Returns an error if checks are pending (retry after waiting) or failed (investigate). The child task must be in ReviewPR status.",
3445
3480
  {
3446
- childTaskId: z3.string().describe("The child task ID whose PR should be approved and merged")
3481
+ childTaskId: z5.string().describe("The child task ID whose PR should be approved and merged")
3447
3482
  },
3448
3483
  async ({ childTaskId }) => {
3449
3484
  try {
@@ -3481,7 +3516,7 @@ function buildPmTools(connection, options) {
3481
3516
  }
3482
3517
 
3483
3518
  // src/tools/discovery-tools.ts
3484
- import { z as z4 } from "zod";
3519
+ import { z as z6 } from "zod";
3485
3520
  var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
3486
3521
  function buildDiscoveryTools(connection) {
3487
3522
  return [
@@ -3489,10 +3524,10 @@ function buildDiscoveryTools(connection) {
3489
3524
  "update_task_properties",
3490
3525
  "Set one or more task properties in a single call. All fields are optional \u2014 only include the fields you want to update.",
3491
3526
  {
3492
- title: z4.string().optional().describe("The new task title"),
3493
- storyPointValue: z4.number().optional().describe(SP_DESCRIPTION2),
3494
- tagIds: z4.array(z4.string()).optional().describe("Array of tag IDs to assign"),
3495
- githubPRUrl: z4.string().url().optional().describe("GitHub pull request URL to link to this task")
3527
+ title: z6.string().optional().describe("The new task title"),
3528
+ storyPointValue: z6.number().optional().describe(SP_DESCRIPTION2),
3529
+ tagIds: z6.array(z6.string()).optional().describe("Array of tag IDs to assign"),
3530
+ githubPRUrl: z6.string().url().optional().describe("GitHub pull request URL to link to this task")
3496
3531
  },
3497
3532
  async ({ title, storyPointValue, tagIds, githubPRUrl }) => {
3498
3533
  try {
@@ -3521,14 +3556,14 @@ function buildDiscoveryTools(connection) {
3521
3556
  }
3522
3557
 
3523
3558
  // src/tools/code-review-tools.ts
3524
- import { z as z5 } from "zod";
3559
+ import { z as z7 } from "zod";
3525
3560
  function buildCodeReviewTools(connection) {
3526
3561
  return [
3527
3562
  defineTool(
3528
3563
  "approve_code_review",
3529
3564
  "Approve the code review. Use this when the code passes all review criteria and is ready to merge.",
3530
3565
  {
3531
- summary: z5.string().describe("Brief summary of what was reviewed and why it looks good")
3566
+ summary: z7.string().describe("Brief summary of what was reviewed and why it looks good")
3532
3567
  },
3533
3568
  async ({ summary }) => {
3534
3569
  const content = `**Code Review: Approved** :white_check_mark:
@@ -3551,15 +3586,15 @@ ${summary}`;
3551
3586
  "request_code_changes",
3552
3587
  "Request changes during code review. Use this when substantive issues are found that need to be fixed before merge.",
3553
3588
  {
3554
- issues: z5.array(
3555
- z5.object({
3556
- file: z5.string().describe("File path where the issue was found"),
3557
- line: z5.number().optional().describe("Line number (if applicable)"),
3558
- severity: z5.enum(["critical", "major", "minor"]).describe("Issue severity"),
3559
- description: z5.string().describe("What is wrong and how to fix it")
3589
+ issues: z7.array(
3590
+ z7.object({
3591
+ file: z7.string().describe("File path where the issue was found"),
3592
+ line: z7.number().optional().describe("Line number (if applicable)"),
3593
+ severity: z7.enum(["critical", "major", "minor"]).describe("Issue severity"),
3594
+ description: z7.string().describe("What is wrong and how to fix it")
3560
3595
  })
3561
3596
  ).describe("List of issues found during review"),
3562
- summary: z5.string().describe("Brief overall summary of the review findings")
3597
+ summary: z7.string().describe("Brief overall summary of the review findings")
3563
3598
  },
3564
3599
  async ({ issues, summary }) => {
3565
3600
  const issueLines = issues.map((issue) => {
@@ -3589,10 +3624,10 @@ ${issueLines}`;
3589
3624
  }
3590
3625
 
3591
3626
  // src/tools/debug-tools.ts
3592
- import { z as z8 } from "zod";
3627
+ import { z as z10 } from "zod";
3593
3628
 
3594
3629
  // src/tools/telemetry-tools.ts
3595
- import { z as z6 } from "zod";
3630
+ import { z as z8 } from "zod";
3596
3631
 
3597
3632
  // src/debug/telemetry-injector.ts
3598
3633
  var BUFFER_SIZE = 200;
@@ -3987,12 +4022,12 @@ function buildGetTelemetryTool(manager) {
3987
4022
  "debug_get_telemetry",
3988
4023
  "Query structured telemetry events (HTTP requests, database queries, Socket.IO events, errors) captured from the running dev server. Returns filtered, structured data instead of raw logs.",
3989
4024
  {
3990
- type: z6.enum(["http", "db", "socket", "error"]).optional().describe("Filter by event type"),
3991
- urlPattern: z6.string().optional().describe("Regex pattern to filter HTTP events by URL"),
3992
- minDuration: z6.number().optional().describe("Minimum duration in ms \u2014 only return events slower than this"),
3993
- errorOnly: z6.boolean().optional().describe("Only return error events and HTTP 4xx/5xx responses"),
3994
- since: z6.number().optional().describe("Only return events after this timestamp (ms since epoch)"),
3995
- limit: z6.number().optional().describe("Max events to return (default: 20, from most recent)")
4025
+ type: z8.enum(["http", "db", "socket", "error"]).optional().describe("Filter by event type"),
4026
+ urlPattern: z8.string().optional().describe("Regex pattern to filter HTTP events by URL"),
4027
+ minDuration: z8.number().optional().describe("Minimum duration in ms \u2014 only return events slower than this"),
4028
+ errorOnly: z8.boolean().optional().describe("Only return error events and HTTP 4xx/5xx responses"),
4029
+ since: z8.number().optional().describe("Only return events after this timestamp (ms since epoch)"),
4030
+ limit: z8.number().optional().describe("Max events to return (default: 20, from most recent)")
3996
4031
  },
3997
4032
  async ({ type, urlPattern, minDuration, errorOnly, since, limit }) => {
3998
4033
  const clientOrErr = requireDebugClient(manager);
@@ -4062,7 +4097,7 @@ function buildTelemetryTools(manager) {
4062
4097
  }
4063
4098
 
4064
4099
  // src/tools/client-debug-tools.ts
4065
- import { z as z7 } from "zod";
4100
+ import { z as z9 } from "zod";
4066
4101
  function requirePlaywrightClient(manager) {
4067
4102
  if (!manager.isClientDebugMode()) {
4068
4103
  return "Client debug mode is not active. Use debug_enter_mode with clientSide: true first.";
@@ -4082,11 +4117,11 @@ function buildClientBreakpointTools(manager) {
4082
4117
  "debug_set_client_breakpoint",
4083
4118
  "Set a breakpoint in client-side code running in the headless Chromium browser. V8 resolves source maps automatically, so original .tsx/.ts file paths work. Use this for React components, client utilities, and browser-side code.",
4084
4119
  {
4085
- file: z7.string().describe(
4120
+ file: z9.string().describe(
4086
4121
  "Original source file path (e.g., src/components/App.tsx) \u2014 source maps resolve automatically"
4087
4122
  ),
4088
- line: z7.number().describe("Line number (1-based) in the original source file"),
4089
- condition: z7.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
4123
+ line: z9.number().describe("Line number (1-based) in the original source file"),
4124
+ condition: z9.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
4090
4125
  },
4091
4126
  async ({ file, line, condition }) => {
4092
4127
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4108,7 +4143,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
4108
4143
  "debug_remove_client_breakpoint",
4109
4144
  "Remove a previously set client-side breakpoint by its ID.",
4110
4145
  {
4111
- breakpointId: z7.string().describe("The breakpoint ID returned by debug_set_client_breakpoint")
4146
+ breakpointId: z9.string().describe("The breakpoint ID returned by debug_set_client_breakpoint")
4112
4147
  },
4113
4148
  async ({ breakpointId }) => {
4114
4149
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4188,8 +4223,8 @@ ${JSON.stringify(queuedHits, null, 2)}`
4188
4223
  "debug_evaluate_client",
4189
4224
  "Evaluate a JavaScript expression in the client-side browser context. When paused at a client breakpoint, evaluates in the paused scope. Can access DOM, window, React internals, etc.",
4190
4225
  {
4191
- expression: z7.string().describe("JavaScript expression to evaluate in the browser context"),
4192
- frameIndex: z7.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
4226
+ expression: z9.string().describe("JavaScript expression to evaluate in the browser context"),
4227
+ frameIndex: z9.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
4193
4228
  },
4194
4229
  async ({ expression, frameIndex }) => {
4195
4230
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4262,7 +4297,7 @@ function buildClientInteractionTools(manager) {
4262
4297
  "debug_navigate_client",
4263
4298
  "Navigate the headless browser to a specific URL. Use this to reproduce specific flows or visit different pages.",
4264
4299
  {
4265
- url: z7.string().describe("URL to navigate to (e.g., http://localhost:3000/dashboard)")
4300
+ url: z9.string().describe("URL to navigate to (e.g., http://localhost:3000/dashboard)")
4266
4301
  },
4267
4302
  async ({ url }) => {
4268
4303
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4279,7 +4314,7 @@ function buildClientInteractionTools(manager) {
4279
4314
  "debug_click_client",
4280
4315
  "Click an element on the page in the headless browser. Use CSS selectors to target elements. Useful for reproducing bugs by interacting with the UI programmatically.",
4281
4316
  {
4282
- selector: z7.string().describe(
4317
+ selector: z9.string().describe(
4283
4318
  "CSS selector of the element to click (e.g., 'button.submit', '#login-form input[type=submit]')"
4284
4319
  )
4285
4320
  },
@@ -4301,8 +4336,8 @@ function buildClientConsoleTool(manager) {
4301
4336
  "debug_get_client_console",
4302
4337
  "Get console messages captured from the headless browser. Includes console.log, warn, error, etc.",
4303
4338
  {
4304
- level: z7.string().optional().describe("Filter by console level: log, warn, error, info, debug"),
4305
- limit: z7.number().optional().describe("Maximum number of recent messages to return (default: all)")
4339
+ level: z9.string().optional().describe("Filter by console level: log, warn, error, info, debug"),
4340
+ limit: z9.number().optional().describe("Maximum number of recent messages to return (default: all)")
4306
4341
  },
4307
4342
  // oxlint-disable-next-line require-await
4308
4343
  async ({ level, limit }) => {
@@ -4329,8 +4364,8 @@ function buildClientNetworkTool(manager) {
4329
4364
  "debug_get_client_network",
4330
4365
  "Get network requests captured from the headless browser. Shows URLs, methods, status codes, and timing.",
4331
4366
  {
4332
- filter: z7.string().optional().describe("Regex pattern to filter requests by URL"),
4333
- limit: z7.number().optional().describe("Maximum number of recent requests to return (default: all)")
4367
+ filter: z9.string().optional().describe("Regex pattern to filter requests by URL"),
4368
+ limit: z9.number().optional().describe("Maximum number of recent requests to return (default: all)")
4334
4369
  },
4335
4370
  // oxlint-disable-next-line require-await
4336
4371
  async ({ filter, limit }) => {
@@ -4358,7 +4393,7 @@ function buildClientErrorsTool(manager) {
4358
4393
  "debug_get_client_errors",
4359
4394
  "Get uncaught errors captured from the headless browser. Includes error messages and source-mapped stack traces.",
4360
4395
  {
4361
- limit: z7.number().optional().describe("Maximum number of recent errors to return (default: all)")
4396
+ limit: z9.number().optional().describe("Maximum number of recent errors to return (default: all)")
4362
4397
  },
4363
4398
  // oxlint-disable-next-line require-await
4364
4399
  async ({ limit }) => {
@@ -4452,12 +4487,12 @@ function buildDebugLifecycleTools(manager) {
4452
4487
  "debug_enter_mode",
4453
4488
  "Activate debug mode: restarts the dev server with Node.js --inspect flag and connects the CDP debugger. Optionally launch a headless Chromium browser for client-side debugging. Use serverSide for backend breakpoints, clientSide for frontend breakpoints, or both for full-stack.",
4454
4489
  {
4455
- hypothesis: z8.string().optional().describe("Your hypothesis about the bug \u2014 helps track debugging intent"),
4456
- serverSide: z8.boolean().optional().describe(
4490
+ hypothesis: z10.string().optional().describe("Your hypothesis about the bug \u2014 helps track debugging intent"),
4491
+ serverSide: z10.boolean().optional().describe(
4457
4492
  "Enable server-side Node.js debugging (default: true if clientSide is not set)"
4458
4493
  ),
4459
- clientSide: z8.boolean().optional().describe("Enable client-side browser debugging via headless Chromium + Playwright"),
4460
- previewUrl: z8.string().optional().describe(
4494
+ clientSide: z10.boolean().optional().describe("Enable client-side browser debugging via headless Chromium + Playwright"),
4495
+ previewUrl: z10.string().optional().describe(
4461
4496
  "Preview URL for client-side debugging (e.g., http://localhost:3000). Required when clientSide is true."
4462
4497
  )
4463
4498
  },
@@ -4493,9 +4528,9 @@ function buildBreakpointTools(manager) {
4493
4528
  "debug_set_breakpoint",
4494
4529
  "Set a breakpoint at the specified file and line number. Optionally provide a condition expression that must evaluate to true for the breakpoint to pause execution.",
4495
4530
  {
4496
- file: z8.string().describe("Absolute or relative file path to set the breakpoint in"),
4497
- line: z8.number().describe("Line number (1-based) to set the breakpoint on"),
4498
- condition: z8.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
4531
+ file: z10.string().describe("Absolute or relative file path to set the breakpoint in"),
4532
+ line: z10.number().describe("Line number (1-based) to set the breakpoint on"),
4533
+ condition: z10.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
4499
4534
  },
4500
4535
  async ({ file, line, condition }) => {
4501
4536
  const clientOrErr = requireDebugClient2(manager);
@@ -4517,7 +4552,7 @@ Breakpoint ID: ${breakpointId}`
4517
4552
  "debug_remove_breakpoint",
4518
4553
  "Remove a previously set breakpoint by its ID.",
4519
4554
  {
4520
- breakpointId: z8.string().describe("The breakpoint ID returned by debug_set_breakpoint")
4555
+ breakpointId: z10.string().describe("The breakpoint ID returned by debug_set_breakpoint")
4521
4556
  },
4522
4557
  async ({ breakpointId }) => {
4523
4558
  const clientOrErr = requireDebugClient2(manager);
@@ -4598,8 +4633,8 @@ ${JSON.stringify(queuedHits, null, 2)}`
4598
4633
  "debug_evaluate",
4599
4634
  "Evaluate a JavaScript expression in the current paused scope (or globally if not paused). When paused, use frameIndex to evaluate in a specific call frame.",
4600
4635
  {
4601
- expression: z8.string().describe("The JavaScript expression to evaluate"),
4602
- frameIndex: z8.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
4636
+ expression: z10.string().describe("The JavaScript expression to evaluate"),
4637
+ frameIndex: z10.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
4603
4638
  },
4604
4639
  async ({ expression, frameIndex }) => {
4605
4640
  const clientOrErr = requireDebugClient2(manager);
@@ -4627,12 +4662,12 @@ function buildProbeManagementTools(manager) {
4627
4662
  "debug_add_probe",
4628
4663
  "Add a debug probe at a specific code location. Captures expression values each time the line executes \u2014 without pausing or modifying source files. Like console.log but better: structured, no diff pollution, auto-cleaned on debug exit.",
4629
4664
  {
4630
- file: z8.string().describe("File path to probe"),
4631
- line: z8.number().describe("Line number (1-based) to probe"),
4632
- expressions: z8.array(z8.string()).describe(
4665
+ file: z10.string().describe("File path to probe"),
4666
+ line: z10.number().describe("Line number (1-based) to probe"),
4667
+ expressions: z10.array(z10.string()).describe(
4633
4668
  'JavaScript expressions to capture when the line executes (e.g., ["req.params.id", "user.role"])'
4634
4669
  ),
4635
- label: z8.string().optional().describe("Optional label for this probe (defaults to file:line)")
4670
+ label: z10.string().optional().describe("Optional label for this probe (defaults to file:line)")
4636
4671
  },
4637
4672
  async ({ file, line, expressions, label }) => {
4638
4673
  const clientOrErr = requireDebugClient2(manager);
@@ -4657,7 +4692,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
4657
4692
  "debug_remove_probe",
4658
4693
  "Remove a previously set debug probe by its ID.",
4659
4694
  {
4660
- probeId: z8.string().describe("The probe ID returned by debug_add_probe")
4695
+ probeId: z10.string().describe("The probe ID returned by debug_add_probe")
4661
4696
  },
4662
4697
  async ({ probeId }) => {
4663
4698
  const clientOrErr = requireDebugClient2(manager);
@@ -4697,9 +4732,9 @@ function buildProbeResultTools(manager) {
4697
4732
  "debug_get_probe_results",
4698
4733
  "Fetch captured probe hit data. Returns expression values from each time a probed line executed.",
4699
4734
  {
4700
- probeId: z8.string().optional().describe("Filter results by probe ID (resolves to its label)"),
4701
- label: z8.string().optional().describe("Filter results by probe label"),
4702
- limit: z8.number().optional().describe("Maximum number of recent hits to return (default: all)")
4735
+ probeId: z10.string().optional().describe("Filter results by probe ID (resolves to its label)"),
4736
+ label: z10.string().optional().describe("Filter results by probe label"),
4737
+ limit: z10.number().optional().describe("Maximum number of recent hits to return (default: all)")
4703
4738
  },
4704
4739
  async ({ probeId, label, limit }) => {
4705
4740
  const clientOrErr = requireDebugClient2(manager);
@@ -4862,23 +4897,20 @@ function getModeTools(agentMode, connection, config, context) {
4862
4897
  }
4863
4898
  function buildConveyorTools(connection, config, context, agentMode, debugManager) {
4864
4899
  const effectiveMode = agentMode ?? context?.agentMode ?? void 0;
4865
- if (effectiveMode === "code-review") {
4866
- return [
4867
- buildReadTaskChatTool(connection),
4868
- buildGetTaskPlanTool(connection),
4869
- buildGetTaskTool(connection),
4870
- buildGetTaskCliTool(connection),
4871
- buildListTaskFilesTool(connection),
4872
- buildGetTaskFileTool(connection),
4873
- ...buildCodeReviewTools(connection)
4874
- ];
4875
- }
4876
4900
  const commonTools = buildCommonTools(connection, config);
4877
4901
  const modeTools = getModeTools(effectiveMode, connection, config, context);
4878
4902
  const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" ? buildDiscoveryTools(connection) : [];
4903
+ const codeReviewTools = effectiveMode === "review" ? buildCodeReviewTools(connection) : [];
4879
4904
  const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];
4880
4905
  const debugTools = debugManager && effectiveMode === "building" ? buildDebugTools(debugManager) : [];
4881
- return [...commonTools, ...modeTools, ...discoveryTools, ...emergencyTools, ...debugTools];
4906
+ return [
4907
+ ...commonTools,
4908
+ ...modeTools,
4909
+ ...discoveryTools,
4910
+ ...codeReviewTools,
4911
+ ...emergencyTools,
4912
+ ...debugTools
4913
+ ];
4882
4914
  }
4883
4915
  function createConveyorMcpServer(harness, connection, config, context, agentMode, debugManager) {
4884
4916
  return harness.createMcpServer({
@@ -5297,7 +5329,6 @@ function collectMissingProps(taskProps) {
5297
5329
  // src/execution/tool-access.ts
5298
5330
  var PM_PLAN_FILE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit"]);
5299
5331
  var DESTRUCTIVE_CMD_PATTERN = /git\s+push\s+--force(?!\s*-with-lease)|git\s+reset\s+--hard|rm\s+-rf\s+\//;
5300
- var CODE_REVIEW_WRITE_CMD_PATTERN = /git\s+push|git\s+commit|git\s+add|rm\s+|mv\s+|cp\s+|mkdir\s+|touch\s+|chmod\s+|chown\s+/;
5301
5332
  var RESOURCE_HEAVY_PATTERNS = [
5302
5333
  /\bbun\s+(install|i|add)\b/,
5303
5334
  /\bnpm\s+(install|ci|i)\b/,
@@ -5334,48 +5365,12 @@ function handleBuildingToolAccess(toolName, input) {
5334
5365
  }
5335
5366
  return { behavior: "allow", updatedInput: input };
5336
5367
  }
5337
- function handleReviewToolAccess(toolName, input, isParentTask) {
5338
- if (isParentTask) {
5339
- return handleBuildingToolAccess(toolName, input);
5340
- }
5341
- if (PM_PLAN_FILE_TOOLS.has(toolName)) {
5342
- if (isPlanFile(input)) {
5343
- return { behavior: "allow", updatedInput: input };
5344
- }
5345
- return {
5346
- behavior: "deny",
5347
- message: "Review mode restricts file writes. Use bash to run tests and linting instead."
5348
- };
5349
- }
5350
- if (toolName === "Bash") {
5351
- const cmd = String(input.command ?? "");
5352
- if (DESTRUCTIVE_CMD_PATTERN.test(cmd)) {
5353
- return { behavior: "deny", message: "Destructive operation blocked in review mode." };
5354
- }
5355
- }
5356
- return { behavior: "allow", updatedInput: input };
5357
- }
5358
- function handleCodeReviewToolAccess(toolName, input) {
5359
- if (PM_PLAN_FILE_TOOLS.has(toolName)) {
5360
- return {
5361
- behavior: "deny",
5362
- message: "Code review mode is fully read-only. File writes are not permitted."
5363
- };
5364
- }
5365
- if (toolName === "Bash") {
5366
- const cmd = String(input.command ?? "");
5367
- if (DESTRUCTIVE_CMD_PATTERN.test(cmd) || CODE_REVIEW_WRITE_CMD_PATTERN.test(cmd)) {
5368
- return {
5369
- behavior: "deny",
5370
- message: "Code review mode is read-only. Write operations and destructive commands are blocked."
5371
- };
5372
- }
5373
- }
5374
- return { behavior: "allow", updatedInput: input };
5368
+ function handleReviewToolAccess(toolName, input) {
5369
+ return handleBuildingToolAccess(toolName, input);
5375
5370
  }
5376
5371
  function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask) {
5377
5372
  if (hasExitedPlanMode) {
5378
- return isParentTask ? handleReviewToolAccess(toolName, input, true) : handleBuildingToolAccess(toolName, input);
5373
+ return isParentTask ? handleReviewToolAccess(toolName, input) : handleBuildingToolAccess(toolName, input);
5379
5374
  }
5380
5375
  return { behavior: "allow", updatedInput: input };
5381
5376
  }
@@ -5488,11 +5483,9 @@ function resolveToolAccess(host, toolName, input) {
5488
5483
  case "building":
5489
5484
  return handleBuildingToolAccess(toolName, input);
5490
5485
  case "review":
5491
- return handleReviewToolAccess(toolName, input, host.isParentTask);
5486
+ return handleReviewToolAccess(toolName, input);
5492
5487
  case "auto":
5493
5488
  return handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);
5494
- case "code-review":
5495
- return handleCodeReviewToolAccess(toolName, input);
5496
5489
  default:
5497
5490
  return { behavior: "allow", updatedInput: input };
5498
5491
  }
@@ -5571,13 +5564,10 @@ function buildHooks(host) {
5571
5564
  };
5572
5565
  }
5573
5566
  function isReadOnlyMode(mode, hasExitedPlanMode) {
5574
- return mode === "discovery" || mode === "help" || mode === "code-review" || mode === "auto" && !hasExitedPlanMode;
5567
+ return mode === "discovery" || mode === "help" || mode === "auto" && !hasExitedPlanMode;
5575
5568
  }
5576
5569
  function buildDisallowedTools(settings, mode, hasExitedPlanMode) {
5577
5570
  const modeDisallowed = isReadOnlyMode(mode, hasExitedPlanMode) ? ["TodoWrite", "TodoRead", "NotebookEdit"] : [];
5578
- if (mode === "code-review") {
5579
- modeDisallowed.push("ExitPlanMode", "EnterPlanMode");
5580
- }
5581
5571
  const configured = settings.disallowedTools ?? [];
5582
5572
  const combined = [...configured, ...modeDisallowed];
5583
5573
  return combined.length > 0 ? combined : void 0;
@@ -5613,11 +5603,11 @@ function buildQueryOptions(host, context) {
5613
5603
  },
5614
5604
  sandbox: context.useSandbox ? { enabled: true } : { enabled: false },
5615
5605
  hooks: buildHooks(host),
5616
- maxTurns: mode === "code-review" ? Math.min(settings.maxTurns ?? 15, 15) : settings.maxTurns,
5606
+ maxTurns: settings.maxTurns,
5617
5607
  effort: settings.effort,
5618
5608
  thinking: settings.thinking,
5619
5609
  betas: settings.betas,
5620
- maxBudgetUsd: mode === "code-review" ? Math.min(settings.maxBudgetUsd ?? 10, 10) : settings.maxBudgetUsd ?? 50,
5610
+ maxBudgetUsd: settings.maxBudgetUsd ?? 50,
5621
5611
  abortController: host.abortController ?? void 0,
5622
5612
  disallowedTools: buildDisallowedTools(settings, mode, host.hasExitedPlanMode),
5623
5613
  enableFileCheckpointing: settings.enableFileCheckpointing,
@@ -6126,6 +6116,7 @@ var SessionRunner = class _SessionRunner {
6126
6116
  stopped = false;
6127
6117
  hasCompleted = false;
6128
6118
  interrupted = false;
6119
+ _isReviewing = false;
6129
6120
  taskContext = null;
6130
6121
  fullContext = null;
6131
6122
  queryBridge = null;
@@ -6247,6 +6238,9 @@ var SessionRunner = class _SessionRunner {
6247
6238
  if (!this.stopped && this.pendingMessages.length === 0) {
6248
6239
  await this.maybeSendPRNudge();
6249
6240
  }
6241
+ if (!this.stopped && this.pendingMessages.length === 0) {
6242
+ await this.maybeTransitionToReview();
6243
+ }
6250
6244
  if (!this.stopped) {
6251
6245
  process.stderr.write(
6252
6246
  `[conveyor-agent] Listening for messages (mode: ${this.mode.effectiveMode})
@@ -6337,14 +6331,7 @@ var SessionRunner = class _SessionRunner {
6337
6331
  async executeInitialMode() {
6338
6332
  if (!this.taskContext || !this.fullContext) return false;
6339
6333
  const effectiveMode = this.mode.effectiveMode;
6340
- if (effectiveMode === "code-review") {
6341
- await this.setState("running");
6342
- await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode });
6343
- await this.executeQuery();
6344
- this.stopped = true;
6345
- return true;
6346
- }
6347
- const shouldRun = effectiveMode === "building" || effectiveMode === "auto" || effectiveMode === "review" && this.mode.isPackRunner(this.taskContext);
6334
+ const shouldRun = effectiveMode === "building" || effectiveMode === "auto" || effectiveMode === "review";
6348
6335
  if (shouldRun) {
6349
6336
  await this.setState("running");
6350
6337
  await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode });
@@ -6393,6 +6380,36 @@ var SessionRunner = class _SessionRunner {
6393
6380
  }
6394
6381
  }
6395
6382
  // ── Stop / soft-stop ───────────────────────────────────────────────
6383
+ /** Best-effort WIP commit + push on shutdown so in-flight work isn't lost
6384
+ * when a claudespace pod is killed. Must be called BEFORE stop() so the
6385
+ * connection is still alive for token refresh. Never throws. */
6386
+ async flushGitOnShutdown() {
6387
+ try {
6388
+ const result = await flushPendingChanges(this.config.workspaceDir, {
6389
+ wipMessage: "WIP: auto-commit on conveyor-agent shutdown",
6390
+ refreshToken: async () => {
6391
+ try {
6392
+ const res = await this.connection.call("refreshGithubToken", {
6393
+ sessionId: this.connection.sessionId
6394
+ });
6395
+ return res.token;
6396
+ } catch {
6397
+ return void 0;
6398
+ }
6399
+ }
6400
+ });
6401
+ if (result.hadWork) {
6402
+ process.stderr.write(
6403
+ `[conveyor-agent] Shutdown git flush: committed=${result.committed} pushed=${result.pushed}
6404
+ `
6405
+ );
6406
+ }
6407
+ } catch (err) {
6408
+ const msg = err instanceof Error ? err.message : String(err);
6409
+ process.stderr.write(`[conveyor-agent] Shutdown git flush failed: ${msg}
6410
+ `);
6411
+ }
6412
+ }
6396
6413
  stop() {
6397
6414
  this.stopped = true;
6398
6415
  this.queryBridge?.stop();
@@ -6468,6 +6485,37 @@ var SessionRunner = class _SessionRunner {
6468
6485
  await this.refreshTaskContext();
6469
6486
  }
6470
6487
  }
6488
+ // ── Same-box review transition ─────────────────────────────────
6489
+ async maybeTransitionToReview() {
6490
+ if (!this.config.isAuto || this._isReviewing) return;
6491
+ await this.refreshTaskContext();
6492
+ if (!this.taskContext?.githubPRUrl || this.taskContext.status !== "ReviewPR") return;
6493
+ this._isReviewing = true;
6494
+ try {
6495
+ this.mode.handleModeChange("review");
6496
+ process.stderr.write(
6497
+ `[conveyor-agent] Auto-transitioning to review mode (same-box code review)
6498
+ `
6499
+ );
6500
+ this.connection.sendEvent({
6501
+ type: "mode_transition",
6502
+ from: "building",
6503
+ to: "review"
6504
+ });
6505
+ this.connection.emitModeChanged("review");
6506
+ const reviewPrompt = [
6507
+ `You have just created a PR for this task. Now perform a self-review of your changes.`,
6508
+ `Run \`git diff ${this.fullContext?.baseBranch ?? "dev"}..HEAD\` to see all changes.`,
6509
+ `Review the changes according to the review criteria in your instructions.`,
6510
+ `If you find issues, fix them directly, commit, and push. Then approve the review.`,
6511
+ `If everything looks good, approve the review using \`approve_code_review\`.`
6512
+ ].join("\n");
6513
+ await this.setState("running");
6514
+ await this.executeQuery(reviewPrompt);
6515
+ } finally {
6516
+ this._isReviewing = false;
6517
+ }
6518
+ }
6471
6519
  // ── Context & bridge construction ────────────────────────────────
6472
6520
  buildFullContext(ctx) {
6473
6521
  const chatHistory = mapChatHistory(ctx.chatHistory);
@@ -6545,6 +6593,9 @@ var SessionRunner = class _SessionRunner {
6545
6593
  if (action.type === "start_auto") {
6546
6594
  this.connection.emitModeChanged(this.mode.effectiveMode);
6547
6595
  this.softStop();
6596
+ } else if (action.type === "restart_query") {
6597
+ this.connection.emitModeChanged(action.newMode);
6598
+ this.softStop();
6548
6599
  }
6549
6600
  });
6550
6601
  this.connection.onWake(() => this.lifecycle.wake());
@@ -7000,7 +7051,7 @@ import * as path from "path";
7000
7051
  import { fileURLToPath as fileURLToPath2 } from "url";
7001
7052
 
7002
7053
  // src/tools/project-tools.ts
7003
- import { z as z9 } from "zod";
7054
+ import { z as z11 } from "zod";
7004
7055
  function buildTaskListTools(connection) {
7005
7056
  const projectId = connection.projectId;
7006
7057
  return [
@@ -7008,9 +7059,9 @@ function buildTaskListTools(connection) {
7008
7059
  "list_tasks",
7009
7060
  "List tasks in the project. Optionally filter by status or assignee.",
7010
7061
  {
7011
- status: z9.string().optional().describe("Filter by task status"),
7012
- assigneeId: z9.string().optional().describe("Filter by assigned user ID"),
7013
- limit: z9.number().optional().describe("Max number of tasks to return (default 50)")
7062
+ status: z11.string().optional().describe("Filter by task status"),
7063
+ assigneeId: z11.string().optional().describe("Filter by assigned user ID"),
7064
+ limit: z11.number().optional().describe("Max number of tasks to return (default 50)")
7014
7065
  },
7015
7066
  async (params) => {
7016
7067
  try {
@@ -7027,7 +7078,7 @@ function buildTaskListTools(connection) {
7027
7078
  defineTool(
7028
7079
  "get_task",
7029
7080
  "Get detailed information about a task including chat messages, child tasks, and session.",
7030
- { task_id: z9.string().describe("The task ID to look up") },
7081
+ { task_id: z11.string().describe("The task ID to look up") },
7031
7082
  async ({ task_id }) => {
7032
7083
  try {
7033
7084
  const task = await connection.call("getProjectTask", { projectId, taskId: task_id });
@@ -7044,10 +7095,10 @@ function buildTaskListTools(connection) {
7044
7095
  "search_tasks",
7045
7096
  "Search tasks by tags, text query, or status filters.",
7046
7097
  {
7047
- tagNames: z9.array(z9.string()).optional().describe("Filter by tag names"),
7048
- searchQuery: z9.string().optional().describe("Text search in title/description"),
7049
- statusFilters: z9.array(z9.string()).optional().describe("Filter by statuses"),
7050
- limit: z9.number().optional().describe("Max results (default 20)")
7098
+ tagNames: z11.array(z11.string()).optional().describe("Filter by tag names"),
7099
+ searchQuery: z11.string().optional().describe("Text search in title/description"),
7100
+ statusFilters: z11.array(z11.string()).optional().describe("Filter by statuses"),
7101
+ limit: z11.number().optional().describe("Max results (default 20)")
7051
7102
  },
7052
7103
  async (params) => {
7053
7104
  try {
@@ -7107,11 +7158,11 @@ function buildMutationTools(connection) {
7107
7158
  "create_task",
7108
7159
  "Create a new task in the project.",
7109
7160
  {
7110
- title: z9.string().describe("Task title"),
7111
- description: z9.string().optional().describe("Task description"),
7112
- plan: z9.string().optional().describe("Implementation plan in markdown"),
7113
- status: z9.string().optional().describe("Initial status (default: Planning)"),
7114
- isBug: z9.boolean().optional().describe("Whether this is a bug report")
7161
+ title: z11.string().describe("Task title"),
7162
+ description: z11.string().optional().describe("Task description"),
7163
+ plan: z11.string().optional().describe("Implementation plan in markdown"),
7164
+ status: z11.string().optional().describe("Initial status (default: Planning)"),
7165
+ isBug: z11.boolean().optional().describe("Whether this is a bug report")
7115
7166
  },
7116
7167
  async (params) => {
7117
7168
  try {
@@ -7128,12 +7179,12 @@ function buildMutationTools(connection) {
7128
7179
  "update_task",
7129
7180
  "Update an existing task's title, description, plan, status, or assignee.",
7130
7181
  {
7131
- task_id: z9.string().describe("The task ID to update"),
7132
- title: z9.string().optional().describe("New title"),
7133
- description: z9.string().optional().describe("New description"),
7134
- plan: z9.string().optional().describe("New plan in markdown"),
7135
- status: z9.string().optional().describe("New status"),
7136
- assignedUserId: z9.string().nullable().optional().describe("Assign to user ID, or null to unassign")
7182
+ task_id: z11.string().describe("The task ID to update"),
7183
+ title: z11.string().optional().describe("New title"),
7184
+ description: z11.string().optional().describe("New description"),
7185
+ plan: z11.string().optional().describe("New plan in markdown"),
7186
+ status: z11.string().optional().describe("New status"),
7187
+ assignedUserId: z11.string().nullable().optional().describe("Assign to user ID, or null to unassign")
7137
7188
  },
7138
7189
  async ({ task_id, ...fields }) => {
7139
7190
  try {
@@ -7502,6 +7553,32 @@ var ProjectRunner = class {
7502
7553
  this.resolveLifecycle = resolve2;
7503
7554
  });
7504
7555
  }
7556
+ /** Best-effort WIP commit + push of every tracked working tree on shutdown.
7557
+ * Iterates the main project dir plus any active agent worktrees so nothing
7558
+ * pending is lost when the pod is killed. Never throws. */
7559
+ async flushGitOnShutdown() {
7560
+ const dirs = /* @__PURE__ */ new Set([this.projectDir]);
7561
+ for (const agent of this.activeAgents.values()) {
7562
+ if (agent.worktreePath) dirs.add(agent.worktreePath);
7563
+ }
7564
+ for (const dir of dirs) {
7565
+ try {
7566
+ const result = await flushPendingChanges(dir, {
7567
+ wipMessage: "WIP: auto-commit on conveyor-agent shutdown"
7568
+ });
7569
+ if (result.hadWork) {
7570
+ logger7.info("Shutdown git flush", {
7571
+ dir,
7572
+ committed: result.committed,
7573
+ pushed: result.pushed
7574
+ });
7575
+ }
7576
+ } catch (err) {
7577
+ const msg = err instanceof Error ? err.message : String(err);
7578
+ logger7.warn("Shutdown git flush failed", { dir, error: msg });
7579
+ }
7580
+ }
7581
+ }
7505
7582
  async stop() {
7506
7583
  if (this.stopping) return;
7507
7584
  this.stopping = true;
@@ -7529,6 +7606,7 @@ var ProjectRunner = class {
7529
7606
  setTimeout(resolve2, STOP_TIMEOUT_MS + 5e3);
7530
7607
  })
7531
7608
  ]);
7609
+ await this.flushGitOnShutdown();
7532
7610
  try {
7533
7611
  await this.connection.call("disconnectProjectRunner", {
7534
7612
  projectId: this.connection.projectId
@@ -7582,7 +7660,7 @@ var ProjectRunner = class {
7582
7660
  async handleAuditTags(request) {
7583
7661
  this.connection.emitStatus("busy");
7584
7662
  try {
7585
- const { handleTagAudit } = await import("./tag-audit-handler-L7YPDXTA.js");
7663
+ const { handleTagAudit } = await import("./tag-audit-handler-PACJJEDB.js");
7586
7664
  await handleTagAudit(request, this.connection, this.projectDir);
7587
7665
  } catch (error) {
7588
7666
  const msg = error instanceof Error ? error.message : String(error);
@@ -7987,6 +8065,7 @@ export {
7987
8065
  hasUnpushedCommits,
7988
8066
  stageAndCommit,
7989
8067
  updateRemoteToken,
8068
+ flushPendingChanges,
7990
8069
  pushToOrigin,
7991
8070
  injectTelemetry,
7992
8071
  PlanSync,
@@ -8003,4 +8082,4 @@ export {
8003
8082
  loadForwardPorts,
8004
8083
  loadConveyorConfig
8005
8084
  };
8006
- //# sourceMappingURL=chunk-QLY35BX7.js.map
8085
+ //# sourceMappingURL=chunk-23JCJ2GV.js.map