@rallycry/conveyor-agent 7.1.0 → 7.1.3

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.
@@ -1,10 +1,8 @@
1
1
  import {
2
2
  createHarness,
3
+ createServiceLogger,
3
4
  defineTool
4
- } from "./chunk-KNBG2634.js";
5
- import {
6
- createServiceLogger
7
- } from "./chunk-CYZPFJGN.js";
5
+ } from "./chunk-U6AYNVS7.js";
8
6
 
9
7
  // src/connection/agent-connection.ts
10
8
  import { io } from "socket.io-client";
@@ -503,7 +501,7 @@ var ModeController = class {
503
501
  }
504
502
  get isReadOnly() {
505
503
  const m = this.effectiveMode;
506
- if (["discovery", "code-review", "help"].includes(m)) return true;
504
+ if (["discovery", "help"].includes(m)) return true;
507
505
  return m === "auto" && !this._hasExitedPlanMode;
508
506
  }
509
507
  get isAutoPlanning() {
@@ -511,13 +509,13 @@ var ModeController = class {
511
509
  }
512
510
  get isBuildCapable() {
513
511
  const m = this.effectiveMode;
514
- return m === "building" || m === "auto" && this._hasExitedPlanMode;
512
+ return m === "building" || m === "review" || m === "auto" && this._hasExitedPlanMode;
515
513
  }
516
514
  // ── Mode resolution ────────────────────────────────────────────────
517
515
  /** Resolve the initial mode based on task context */
518
516
  resolveInitialMode(context) {
519
517
  if (this._runnerMode === "code-review") {
520
- this._mode = "code-review";
518
+ this._mode = "review";
521
519
  return this._mode;
522
520
  }
523
521
  if (this._mode === "auto" && this.canBypassPlanning(context)) {
@@ -536,8 +534,12 @@ var ModeController = class {
536
534
  // ── Mode transitions ───────────────────────────────────────────────
537
535
  /** Handle mode change from server */
538
536
  handleModeChange(newMode) {
539
- if (this._runnerMode !== "pm") return { type: "noop" };
540
537
  if (newMode === this._mode) return { type: "noop" };
538
+ if (this._runnerMode === "task" && newMode === "review") {
539
+ this._mode = newMode;
540
+ return { type: "restart_query", newMode: "review" };
541
+ }
542
+ if (this._runnerMode !== "pm") return { type: "noop" };
541
543
  this._mode = newMode;
542
544
  this.updateExitedPlanModeFlag(newMode);
543
545
  if (this.isBuildCapable) {
@@ -811,6 +813,28 @@ function updateRemoteToken(cwd, token) {
811
813
  } catch {
812
814
  }
813
815
  }
816
+ async function flushPendingChanges(cwd, opts) {
817
+ let committed = false;
818
+ let pushed = false;
819
+ let hadWork = false;
820
+ try {
821
+ if (hasUncommittedChanges(cwd)) {
822
+ hadWork = true;
823
+ const message = opts?.wipMessage ?? "WIP: auto-commit on conveyor-agent shutdown";
824
+ const hash = stageAndCommit(cwd, message);
825
+ committed = hash !== null;
826
+ }
827
+ } catch {
828
+ }
829
+ try {
830
+ if (hasUnpushedCommits(cwd)) {
831
+ hadWork = true;
832
+ pushed = await pushToOrigin(cwd, opts?.refreshToken);
833
+ }
834
+ } catch {
835
+ }
836
+ return { committed, pushed, hadWork };
837
+ }
814
838
  async function pushToOrigin(cwd, refreshToken) {
815
839
  try {
816
840
  const currentBranch = getCurrentBranch(cwd);
@@ -922,6 +946,8 @@ var PlanSync = class {
922
946
 
923
947
  // ../shared/dist/index.js
924
948
  import { z } from "zod";
949
+ import { z as z2 } from "zod";
950
+ import { z as z3 } from "zod";
925
951
  var MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;
926
952
  var EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;
927
953
  var EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;
@@ -1144,157 +1170,6 @@ var UpdateChildStatusRequestSchema = z.object({
1144
1170
  childTaskId: z.string(),
1145
1171
  status: z.string()
1146
1172
  });
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
1173
  var GetAgentStatusRequestSchema = z.object({
1299
1174
  taskId: z.string()
1300
1175
  });
@@ -1390,7 +1265,200 @@ var RegisterProjectAgentResponseSchema = z.object({
1390
1265
  agentSettings: z.record(z.string(), z.unknown()).nullable(),
1391
1266
  branchSwitchCommand: z.string().nullable()
1392
1267
  });
1393
- var CRITICAL_AUTOMATED_SOURCES = /* @__PURE__ */ new Set(["ci_failure"]);
1268
+ var RegisterProjectAgentRequestSchema = z2.object({
1269
+ projectId: z2.string(),
1270
+ capabilities: z2.array(z2.string())
1271
+ });
1272
+ var ProjectRunnerHeartbeatRequestSchema = z2.object({
1273
+ projectId: z2.string()
1274
+ });
1275
+ var ReportProjectAgentStatusRequestSchema = z2.object({
1276
+ projectId: z2.string(),
1277
+ status: z2.enum(["busy", "idle"]),
1278
+ activeChatId: z2.string().nullish(),
1279
+ activeTaskId: z2.string().nullish(),
1280
+ activeBranch: z2.string().nullish()
1281
+ });
1282
+ var DisconnectProjectRunnerRequestSchema = z2.object({
1283
+ projectId: z2.string()
1284
+ });
1285
+ var GetProjectAgentContextRequestSchema = z2.object({
1286
+ projectId: z2.string()
1287
+ });
1288
+ var GetProjectChatHistoryRequestSchema = z2.object({
1289
+ projectId: z2.string(),
1290
+ limit: z2.number().int().positive().optional().default(50),
1291
+ chatId: z2.string().optional()
1292
+ });
1293
+ var PostProjectAgentMessageRequestSchema = z2.object({
1294
+ projectId: z2.string(),
1295
+ content: z2.string().min(1),
1296
+ chatId: z2.string().optional()
1297
+ });
1298
+ var ListProjectTasksRequestSchema = z2.object({
1299
+ projectId: z2.string(),
1300
+ status: z2.string().optional(),
1301
+ assigneeId: z2.string().optional(),
1302
+ limit: z2.number().int().positive().optional().default(50)
1303
+ });
1304
+ var GetProjectTaskRequestSchema = z2.object({
1305
+ projectId: z2.string(),
1306
+ taskId: z2.string()
1307
+ });
1308
+ var SearchProjectTasksRequestSchema = z2.object({
1309
+ projectId: z2.string(),
1310
+ tagNames: z2.array(z2.string()).optional(),
1311
+ searchQuery: z2.string().optional(),
1312
+ statusFilters: z2.array(z2.string()).optional(),
1313
+ limit: z2.number().int().positive().optional().default(20)
1314
+ });
1315
+ var ListProjectTagsRequestSchema = z2.object({
1316
+ projectId: z2.string()
1317
+ });
1318
+ var GetProjectSummaryRequestSchema = z2.object({
1319
+ projectId: z2.string()
1320
+ });
1321
+ var CreateProjectTaskRequestSchema = z2.object({
1322
+ projectId: z2.string(),
1323
+ title: z2.string().min(1),
1324
+ description: z2.string().optional(),
1325
+ plan: z2.string().optional(),
1326
+ status: z2.string().optional(),
1327
+ isBug: z2.boolean().optional()
1328
+ });
1329
+ var UpdateProjectTaskRequestSchema = z2.object({
1330
+ projectId: z2.string(),
1331
+ taskId: z2.string(),
1332
+ title: z2.string().optional(),
1333
+ description: z2.string().optional(),
1334
+ plan: z2.string().optional(),
1335
+ status: z2.string().optional(),
1336
+ assignedUserId: z2.string().nullish()
1337
+ });
1338
+ var ReportProjectAgentEventRequestSchema = z2.object({
1339
+ projectId: z2.string(),
1340
+ event: z2.record(z2.string(), z2.unknown())
1341
+ });
1342
+ var ReportTagAuditProgressRequestSchema = z2.object({
1343
+ projectId: z2.string(),
1344
+ requestId: z2.string(),
1345
+ activity: z2.object({
1346
+ tool: z2.string(),
1347
+ input: z2.string().optional(),
1348
+ timestamp: z2.string()
1349
+ })
1350
+ });
1351
+ var ReportTagAuditResultRequestSchema = z2.object({
1352
+ projectId: z2.string(),
1353
+ requestId: z2.string(),
1354
+ recommendations: z2.array(z2.record(z2.string(), z2.unknown())),
1355
+ summary: z2.string(),
1356
+ complete: z2.boolean()
1357
+ });
1358
+ var ReportNewCommitsDetectedRequestSchema = z2.object({
1359
+ projectId: z2.string(),
1360
+ commits: z2.array(
1361
+ z2.object({
1362
+ sha: z2.string(),
1363
+ message: z2.string(),
1364
+ author: z2.string()
1365
+ })
1366
+ ),
1367
+ branch: z2.string()
1368
+ });
1369
+ var ReportEnvironmentReadyRequestSchema = z2.object({
1370
+ projectId: z2.string(),
1371
+ branch: z2.string(),
1372
+ setupComplete: z2.boolean(),
1373
+ startCommandRunning: z2.boolean()
1374
+ });
1375
+ var ReportEnvSwitchProgressRequestSchema = z2.object({
1376
+ projectId: z2.string(),
1377
+ step: z2.string(),
1378
+ progress: z2.number(),
1379
+ message: z2.string().optional()
1380
+ });
1381
+ var ForwardProjectChatMessageRequestSchema = z2.object({
1382
+ projectId: z2.string(),
1383
+ chatId: z2.string(),
1384
+ content: z2.string().min(1),
1385
+ targetUserId: z2.string().optional()
1386
+ });
1387
+ var CancelQueuedProjectMessageRequestSchema = z2.object({
1388
+ projectId: z2.string(),
1389
+ index: z2.number().int().nonnegative()
1390
+ });
1391
+ var GetProjectCliHistoryRequestSchema = z2.object({
1392
+ projectId: z2.string(),
1393
+ limit: z2.number().int().positive().optional().default(50),
1394
+ source: z2.string().optional()
1395
+ });
1396
+ var PostToProjectTaskChatRequestSchema = z2.object({
1397
+ projectId: z2.string(),
1398
+ taskId: z2.string(),
1399
+ content: z2.string()
1400
+ });
1401
+ var GetProjectTaskCliRequestSchema = z2.object({
1402
+ projectId: z2.string(),
1403
+ taskId: z2.string(),
1404
+ limit: z2.number().int().positive().optional().default(50),
1405
+ source: z2.string().optional()
1406
+ });
1407
+ var StartProjectBuildRequestSchema = z2.object({
1408
+ projectId: z2.string(),
1409
+ taskId: z2.string()
1410
+ });
1411
+ var StopProjectBuildRequestSchema = z2.object({
1412
+ projectId: z2.string(),
1413
+ taskId: z2.string()
1414
+ });
1415
+ var ApproveProjectMergePRRequestSchema = z2.object({
1416
+ projectId: z2.string(),
1417
+ childTaskId: z2.string()
1418
+ });
1419
+ var CRITICAL_AUTOMATED_SOURCES = /* @__PURE__ */ new Set(["ci_failure", "review_trigger"]);
1420
+ var StartTaskAuditRequestSchema = z3.object({
1421
+ projectId: z3.string(),
1422
+ taskIds: z3.array(z3.string()).min(1)
1423
+ });
1424
+ var ReportTaskAuditProgressRequestSchema = z3.object({
1425
+ projectId: z3.string(),
1426
+ requestId: z3.string(),
1427
+ taskId: z3.string(),
1428
+ activity: z3.string()
1429
+ });
1430
+ var ReportTaskAuditResultRequestSchema = z3.object({
1431
+ projectId: z3.string(),
1432
+ requestId: z3.string(),
1433
+ taskId: z3.string(),
1434
+ summary: z3.string(),
1435
+ turnGrades: z3.array(
1436
+ z3.object({
1437
+ turnIndex: z3.number(),
1438
+ phase: z3.enum(["planning", "building", "human"]),
1439
+ grade: z3.enum(["correct", "neutral", "blunder"]),
1440
+ reasoning: z3.string(),
1441
+ eventType: z3.string(),
1442
+ eventSummary: z3.string()
1443
+ })
1444
+ ),
1445
+ planningAccuracy: z3.number().nullable(),
1446
+ buildingAccuracy: z3.number().nullable(),
1447
+ humanAccuracy: z3.number().nullable(),
1448
+ planningCorrect: z3.number(),
1449
+ planningNeutral: z3.number(),
1450
+ planningBlunder: z3.number(),
1451
+ buildingCorrect: z3.number(),
1452
+ buildingNeutral: z3.number(),
1453
+ buildingBlunder: z3.number(),
1454
+ humanCorrect: z3.number(),
1455
+ humanNeutral: z3.number(),
1456
+ humanBlunder: z3.number(),
1457
+ suggestionIds: z3.array(z3.string()),
1458
+ auditCostUsd: z3.number().nullable(),
1459
+ model: z3.string().nullable(),
1460
+ error: z3.string().optional()
1461
+ });
1394
1462
 
1395
1463
  // src/execution/pack-runner-prompt.ts
1396
1464
  function findLastAgentMessageIndex(history) {
@@ -1882,8 +1950,6 @@ function buildModePrompt(agentMode, context) {
1882
1950
  return buildReviewPrompt(context);
1883
1951
  case "auto":
1884
1952
  return buildAutoPrompt(context);
1885
- case "code-review":
1886
- return buildCodeReviewPrompt();
1887
1953
  default:
1888
1954
  return null;
1889
1955
  }
@@ -1892,8 +1958,9 @@ function buildReviewPrompt(context) {
1892
1958
  const parts = [
1893
1959
  `
1894
1960
  ## 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)`,
1961
+ `You are in Review mode \u2014 performing code review with fix capability.`,
1962
+ `- You have full write access \u2014 you can audit code, make fixes, push changes, and run tests`,
1963
+ `- Safety rules: no destructive operations, use --force-with-lease instead of --force`,
1897
1964
  ``
1898
1965
  ];
1899
1966
  if (context?.isParentTask) {
@@ -1915,80 +1982,62 @@ function buildReviewPrompt(context) {
1915
1982
  );
1916
1983
  } else {
1917
1984
  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\`.`
1985
+ `### Code Review Process`,
1986
+ `1. Run \`git diff ${context?.baseBranch ?? "dev"}..HEAD\` to see all changes in this PR`,
1987
+ `2. Read the task plan to understand the intended changes`,
1988
+ `3. Explore the surrounding codebase to verify pattern consistency`,
1989
+ `4. Review against the criteria below`,
1990
+ ``,
1991
+ `### Review Criteria`,
1992
+ `- **Correctness**: Does the code do what the plan says? Logic errors, off-by-one, race conditions?`,
1993
+ `- **Pattern Consistency**: Does the code follow existing patterns in the codebase? Check nearby files.`,
1994
+ `- **Security**: No hardcoded secrets, no injection vulnerabilities, proper input validation at boundaries.`,
1995
+ `- **Performance**: No unnecessary loops, no N+1 queries, no blocking in async contexts.`,
1996
+ `- **Error Handling**: Appropriate error handling at system boundaries. No swallowed errors.`,
1997
+ `- **Test Coverage**: Are new code paths tested? Edge cases covered?`,
1998
+ `- **TypeScript Best Practices**: Proper typing (no unnecessary \`any\`), correct React patterns, proper async/await.`,
1999
+ `- **Naming & Readability**: Clear names, no misleading comments, self-documenting code.`,
2000
+ ``,
2001
+ `### Fix Capability`,
2002
+ `You have full write access. If you find issues:`,
2003
+ `- **Small fixes**: Make the fix directly, commit, and push. Then re-review.`,
2004
+ `- **Larger issues**: Use \`request_code_changes\` to flag them for the team.`,
2005
+ `- After pushing fixes, wait for CI to pass before approving.`,
2006
+ ``,
2007
+ `### Output \u2014 You MUST do exactly ONE of:`,
2008
+ ``,
2009
+ `#### If code passes review (or after you've fixed all issues):`,
2010
+ `Use the \`approve_code_review\` tool with a brief summary of what looks good.`,
2011
+ ``,
2012
+ `#### If changes are needed that you cannot fix:`,
2013
+ `Use the \`request_code_changes\` tool with specific issues:`,
2014
+ `- Reference specific files and line numbers`,
2015
+ `- Explain what's wrong and suggest fixes`,
2016
+ `- Focus on substantive issues, not style nitpicks (linting handles that)`,
2017
+ ``,
2018
+ `### Previous Review Feedback`,
2019
+ `If previous review feedback is present in the chat history, verify those specific issues were addressed before raising new concerns.`,
2020
+ ``,
2021
+ `### Rules`,
2022
+ `- Do NOT re-review things CI already validates (formatting, lint rules).`,
2023
+ `- Be concise \u2014 actionable specifics over general observations.`,
2024
+ `- Max 5-7 issues per review. Prioritize the most important ones.`
1924
2025
  );
1925
2026
  }
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
2027
  if (process.env.CLAUDESPACE_NAME) {
1935
2028
  parts.push(
1936
2029
  ``,
1937
2030
  `### 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`,
2031
+ `Your pod starts with minimal resources. You MUST call \`scale_up_resources\``,
2032
+ `BEFORE running any resource-intensive operations \u2014 they WILL fail or OOM at baseline resources:`,
2033
+ `- **setup** \u2014 package installs, basic dev servers, light builds`,
2034
+ `- **build** \u2014 full dev servers, test suites, typecheck, lint, E2E tests`,
1943
2035
  `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.`
2036
+ `CRITICAL: Always scale to at least "setup" before running any package install command.`
1945
2037
  );
1946
2038
  }
1947
2039
  return parts.join("\n");
1948
2040
  }
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
2041
 
1993
2042
  // src/execution/system-prompt.ts
1994
2043
  function formatProjectAgentLine(pa) {
@@ -2415,18 +2464,6 @@ ${context.plan}`);
2415
2464
  }
2416
2465
  return parts;
2417
2466
  }
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
2467
  function buildFreshInstructions(isPm, isAutoMode, context, agentMode) {
2431
2468
  if (isPm && agentMode === "building") {
2432
2469
  return [
@@ -2463,16 +2500,16 @@ CRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or g
2463
2500
  return [
2464
2501
  `You are the project manager for this task and its subtasks.`,
2465
2502
  `Review existing subtasks via \`list_subtasks\` and the chat history before taking action.`,
2466
- `Read the task description and chat history carefully \u2014 the team may have already provided context and requirements. Respond to what's been discussed rather than starting from scratch.`,
2467
- `The task details are provided above. Wait for the team to provide instructions before taking action.`,
2503
+ `Read the task description and chat history carefully \u2014 the team has provided the initial context below. Acknowledge what they've asked for and respond in chat before taking silent tool actions.`,
2504
+ `Start planning now \u2014 explore the codebase, ask clarifying questions if needed, and propose a subtask breakdown. Do not wait for additional team input before engaging.`,
2468
2505
  `When you finish planning, save the plan with update_task and end your turn. Your reply will be visible to the team in chat.`
2469
2506
  ];
2470
2507
  }
2471
2508
  if (isPm) {
2472
2509
  return [
2473
2510
  `You are the project manager for this task.`,
2474
- `Read the task description and chat history carefully \u2014 the team may have already provided context and requirements. Respond to what's been discussed rather than starting from scratch.`,
2475
- `The task details are provided above. Wait for the team to ask questions or provide additional requirements before starting to plan.`,
2511
+ `Read the task description and chat history carefully \u2014 the team has provided the initial context below. Acknowledge what they've asked for and respond in chat before taking silent tool actions.`,
2512
+ `Start planning now \u2014 explore the codebase, ask clarifying questions if needed, and draft a plan. Do not wait for additional team input before engaging; the initial message IS the team engaging.`,
2476
2513
  `When you finish planning, save the plan with update_task and end your turn. Your reply summarizing the plan will be visible in chat. A separate task agent will execute the plan after review.`
2477
2514
  ];
2478
2515
  }
@@ -2577,10 +2614,6 @@ function buildIdleRelaunchInstructions(context, isPm, agentMode, isAuto) {
2577
2614
  function buildInstructions(mode, context, scenario, agentMode, isAuto) {
2578
2615
  const parts = [`
2579
2616
  ## Instructions`];
2580
- if (agentMode === "code-review") {
2581
- parts.push(...buildCodeReviewInstructions(context));
2582
- return parts;
2583
- }
2584
2617
  const isPm = mode === "pm";
2585
2618
  if (scenario === "fresh") {
2586
2619
  parts.push(...buildFreshInstructions(isPm, agentMode === "auto", context, agentMode));
@@ -2595,7 +2628,7 @@ function buildInstructions(mode, context, scenario, agentMode, isAuto) {
2595
2628
  }
2596
2629
  async function buildInitialPrompt(mode, context, isAuto, agentMode) {
2597
2630
  const isPackRunner = mode === "pm" && !!isAuto && !!context.isParentTask;
2598
- if (!isPackRunner && agentMode !== "code-review") {
2631
+ if (!isPackRunner) {
2599
2632
  const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);
2600
2633
  if (sessionRelaunch) return sessionRelaunch;
2601
2634
  }
@@ -2610,7 +2643,7 @@ async function buildInitialPrompt(mode, context, isAuto, agentMode) {
2610
2643
  }
2611
2644
 
2612
2645
  // src/tools/common-tools.ts
2613
- import { z as z2 } from "zod";
2646
+ import { z as z4 } from "zod";
2614
2647
 
2615
2648
  // src/tools/helpers.ts
2616
2649
  function textResult(text) {
@@ -2644,8 +2677,8 @@ function buildReadTaskChatTool(connection) {
2644
2677
  "read_task_chat",
2645
2678
  "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
2679
  {
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.")
2680
+ limit: z4.number().optional().describe("Number of recent messages to fetch (default 20)"),
2681
+ task_id: z4.string().optional().describe("Child task ID to read chat from. Omit to read the current task's chat.")
2649
2682
  },
2650
2683
  async ({ limit, task_id }) => {
2651
2684
  try {
@@ -2689,7 +2722,7 @@ function buildGetTaskTool(connection) {
2689
2722
  "get_task",
2690
2723
  "Look up a task by slug or ID to get its title, description, plan, and status",
2691
2724
  {
2692
- slug_or_id: z2.string().describe("The task slug (e.g. 'my-task') or CUID")
2725
+ slug_or_id: z4.string().describe("The task slug (e.g. 'my-task') or CUID")
2693
2726
  },
2694
2727
  async ({ slug_or_id }) => {
2695
2728
  try {
@@ -2712,9 +2745,9 @@ function buildGetTaskCliTool(connection) {
2712
2745
  "get_task_cli",
2713
2746
  "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
2747
  {
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).")
2748
+ task_id: z4.string().optional().describe("Task ID or slug. Omit to read logs from the current task."),
2749
+ source: z4.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
2750
+ limit: z4.number().optional().describe("Max number of log entries to return (default 50, max 500).")
2718
2751
  },
2719
2752
  async ({ task_id, source, limit }) => {
2720
2753
  try {
@@ -2774,7 +2807,7 @@ function buildGetTaskFileTool(connection) {
2774
2807
  return defineTool(
2775
2808
  "get_task_file",
2776
2809
  "Get a specific task file's content and download URL by file ID",
2777
- { fileId: z2.string().describe("The file ID to retrieve") },
2810
+ { fileId: z4.string().describe("The file ID to retrieve") },
2778
2811
  async ({ fileId }) => {
2779
2812
  try {
2780
2813
  const file = await connection.call("getTaskFile", {
@@ -2805,8 +2838,8 @@ function buildSearchIncidentsTool(connection) {
2805
2838
  "search_incidents",
2806
2839
  "Search incidents in the current project. Optionally filter by status (Open, Acknowledged, Investigating, Resolved, Closed) or source.",
2807
2840
  {
2808
- status: z2.string().optional().describe("Filter by incident status"),
2809
- source: z2.string().optional().describe("Filter by source (e.g., 'conveyor', 'agent', 'build')")
2841
+ status: z4.string().optional().describe("Filter by incident status"),
2842
+ source: z4.string().optional().describe("Filter by source (e.g., 'conveyor', 'agent', 'build')")
2810
2843
  },
2811
2844
  async ({ status, source }) => {
2812
2845
  try {
@@ -2830,7 +2863,7 @@ function buildGetTaskIncidentsTool(connection) {
2830
2863
  "get_task_incidents",
2831
2864
  "Get all incidents linked to the current task (or a specified task). Returns full incident details including title, description, severity, status, and source.",
2832
2865
  {
2833
- task_id: z2.string().optional().describe("Task ID (defaults to current task)")
2866
+ task_id: z4.string().optional().describe("Task ID (defaults to current task)")
2834
2867
  },
2835
2868
  async ({ task_id }) => {
2836
2869
  try {
@@ -2853,12 +2886,12 @@ function buildQueryGcpLogsTool(connection) {
2853
2886
  "query_gcp_logs",
2854
2887
  "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
2888
  {
2856
- filter: z2.string().optional().describe(
2889
+ filter: z4.string().optional().describe(
2857
2890
  `Cloud Logging filter expression (e.g., 'resource.type="gce_instance"'). Max 1000 chars.`
2858
2891
  ),
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([
2892
+ start_time: z4.string().optional().describe("Start time in ISO 8601 format (e.g., '2024-01-01T00:00:00Z')"),
2893
+ end_time: z4.string().optional().describe("End time in ISO 8601 format (e.g., '2024-01-02T00:00:00Z')"),
2894
+ severity: z4.enum([
2862
2895
  "DEFAULT",
2863
2896
  "DEBUG",
2864
2897
  "INFO",
@@ -2869,7 +2902,7 @@ function buildQueryGcpLogsTool(connection) {
2869
2902
  "ALERT",
2870
2903
  "EMERGENCY"
2871
2904
  ]).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)")
2905
+ page_size: z4.number().optional().describe("Number of log entries to return (default 100, max 500)")
2873
2906
  },
2874
2907
  async ({ filter, start_time, end_time, severity, page_size }) => {
2875
2908
  try {
@@ -2923,8 +2956,8 @@ function buildGetSuggestionsTool(connection) {
2923
2956
  "get_suggestions",
2924
2957
  "List project suggestions sorted by vote score. Use this to see what the team thinks is important.",
2925
2958
  {
2926
- status: z2.string().optional().describe("Filter by status: Open, Accepted, Rejected, Implemented"),
2927
- limit: z2.number().optional().describe("Max results (default 20)")
2959
+ status: z4.string().optional().describe("Filter by status: Open, Accepted, Rejected, Implemented"),
2960
+ limit: z4.number().optional().describe("Max results (default 20)")
2928
2961
  },
2929
2962
  async ({ status: _status, limit: _limit }) => {
2930
2963
  try {
@@ -2949,8 +2982,8 @@ function buildPostToChatTool(connection) {
2949
2982
  "post_to_chat",
2950
2983
  "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
2984
  {
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.")
2985
+ message: z4.string().describe("The message to post to the team"),
2986
+ task_id: z4.string().optional().describe("Child task ID to post to. Omit to post to the current task's chat.")
2954
2987
  },
2955
2988
  async ({ message, task_id }) => {
2956
2989
  try {
@@ -2977,8 +3010,8 @@ function buildForceUpdateTaskStatusTool(connection) {
2977
3010
  "force_update_task_status",
2978
3011
  "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
3012
  {
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.")
3013
+ status: z4.enum(["InProgress", "ReviewPR", "ReviewDev", "Complete"]).describe("The new status for the task"),
3014
+ task_id: z4.string().optional().describe("Child task ID to update. Omit to update the current task.")
2982
3015
  },
2983
3016
  async ({ status, task_id }) => {
2984
3017
  try {
@@ -3009,15 +3042,15 @@ function buildCreatePullRequestTool(connection, config) {
3009
3042
  "create_pull_request",
3010
3043
  "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
3044
  {
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(
3045
+ title: z4.string().describe("The PR title"),
3046
+ body: z4.string().describe("The PR description/body in markdown"),
3047
+ branch: z4.string().optional().describe(
3015
3048
  "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
3049
  ),
3017
- baseBranch: z2.string().optional().describe(
3050
+ baseBranch: z4.string().optional().describe(
3018
3051
  "The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch."
3019
3052
  ),
3020
- commitMessage: z2.string().optional().describe(
3053
+ commitMessage: z4.string().optional().describe(
3021
3054
  "Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used."
3022
3055
  )
3023
3056
  },
@@ -3095,7 +3128,7 @@ function buildAddDependencyTool(connection) {
3095
3128
  "add_dependency",
3096
3129
  "Add a dependency \u2014 this task cannot start until the specified task is merged to dev",
3097
3130
  {
3098
- depends_on_slug_or_id: z2.string().describe("Slug or ID of the task this task depends on")
3131
+ depends_on_slug_or_id: z4.string().describe("Slug or ID of the task this task depends on")
3099
3132
  },
3100
3133
  async ({ depends_on_slug_or_id }) => {
3101
3134
  try {
@@ -3117,7 +3150,7 @@ function buildRemoveDependencyTool(connection) {
3117
3150
  "remove_dependency",
3118
3151
  "Remove a dependency from this task",
3119
3152
  {
3120
- depends_on_slug_or_id: z2.string().describe("Slug or ID of the task to remove as dependency")
3153
+ depends_on_slug_or_id: z4.string().describe("Slug or ID of the task to remove as dependency")
3121
3154
  },
3122
3155
  async ({ depends_on_slug_or_id }) => {
3123
3156
  try {
@@ -3139,10 +3172,10 @@ function buildCreateFollowUpTaskTool(connection) {
3139
3172
  "create_follow_up_task",
3140
3173
  "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
3174
  {
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)")
3175
+ title: z4.string().describe("Follow-up task title"),
3176
+ description: z4.string().optional().describe("Brief description of the follow-up work"),
3177
+ plan: z4.string().optional().describe("Implementation plan if known"),
3178
+ story_point_value: z4.number().optional().describe("Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)")
3146
3179
  },
3147
3180
  async ({ title, description, plan, story_point_value }) => {
3148
3181
  try {
@@ -3169,9 +3202,9 @@ function buildCreateSuggestionTool(connection) {
3169
3202
  "create_suggestion",
3170
3203
  "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
3204
  {
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")
3205
+ title: z4.string().describe("Short title for the suggestion"),
3206
+ description: z4.string().optional().describe("Details about the suggestion"),
3207
+ tag_names: z4.array(z4.string()).optional().describe("Tag names to categorize the suggestion")
3175
3208
  },
3176
3209
  async ({ title, description, tag_names }) => {
3177
3210
  try {
@@ -3200,8 +3233,8 @@ function buildVoteSuggestionTool(connection) {
3200
3233
  "vote_suggestion",
3201
3234
  "Vote on a project suggestion. Use +1 to upvote or -1 to downvote.",
3202
3235
  {
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")
3236
+ suggestion_id: z4.string().describe("The suggestion ID to vote on"),
3237
+ value: z4.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
3205
3238
  },
3206
3239
  async ({ suggestion_id, value }) => {
3207
3240
  try {
@@ -3224,8 +3257,8 @@ function buildScaleUpResourcesTool(connection) {
3224
3257
  "scale_up_resources",
3225
3258
  "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
3259
  {
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')")
3260
+ tier: z4.literal("build").describe("The resource phase to scale up to"),
3261
+ reason: z4.string().optional().describe("Brief reason for scaling (e.g., 'running test suite')")
3229
3262
  },
3230
3263
  async ({ tier, reason }) => {
3231
3264
  try {
@@ -3278,15 +3311,15 @@ function buildCommonTools(connection, config) {
3278
3311
  }
3279
3312
 
3280
3313
  // src/tools/pm-tools.ts
3281
- import { z as z3 } from "zod";
3314
+ import { z as z5 } from "zod";
3282
3315
  var SP_DESCRIPTION = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
3283
3316
  function buildUpdateTaskTool(connection) {
3284
3317
  return defineTool(
3285
3318
  "update_task",
3286
3319
  "Save the finalized task plan and/or description",
3287
3320
  {
3288
- plan: z3.string().optional().describe("The task plan in markdown"),
3289
- description: z3.string().optional().describe("Updated task description")
3321
+ plan: z5.string().optional().describe("The task plan in markdown"),
3322
+ description: z5.string().optional().describe("Updated task description")
3290
3323
  },
3291
3324
  async ({ plan, description }) => {
3292
3325
  try {
@@ -3307,11 +3340,11 @@ function buildCreateSubtaskTool(connection) {
3307
3340
  "create_subtask",
3308
3341
  "Create a subtask under the current parent task. Use for breaking complex tasks into smaller pieces.",
3309
3342
  {
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)
3343
+ title: z5.string().describe("Subtask title"),
3344
+ description: z5.string().optional().describe("Brief description"),
3345
+ plan: z5.string().optional().describe("Implementation plan in markdown"),
3346
+ ordinal: z5.number().optional().describe("Step/order number (0-based)"),
3347
+ storyPointValue: z5.number().optional().describe(SP_DESCRIPTION)
3315
3348
  },
3316
3349
  async ({ title, description, plan, ordinal, storyPointValue }) => {
3317
3350
  try {
@@ -3337,12 +3370,12 @@ function buildUpdateSubtaskTool(connection) {
3337
3370
  "update_subtask",
3338
3371
  "Update an existing subtask's fields",
3339
3372
  {
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)
3373
+ subtaskId: z5.string().describe("The subtask ID to update"),
3374
+ title: z5.string().optional(),
3375
+ description: z5.string().optional(),
3376
+ plan: z5.string().optional(),
3377
+ ordinal: z5.number().optional(),
3378
+ storyPointValue: z5.number().optional().describe(SP_DESCRIPTION)
3346
3379
  },
3347
3380
  async ({ subtaskId, title, description, plan, storyPointValue }) => {
3348
3381
  try {
@@ -3365,7 +3398,7 @@ function buildDeleteSubtaskTool(connection) {
3365
3398
  return defineTool(
3366
3399
  "delete_subtask",
3367
3400
  "Delete a subtask",
3368
- { subtaskId: z3.string().describe("The subtask ID to delete") },
3401
+ { subtaskId: z5.string().describe("The subtask ID to delete") },
3369
3402
  async ({ subtaskId }) => {
3370
3403
  try {
3371
3404
  await connection.call("deleteSubtask", {
@@ -3403,7 +3436,7 @@ function buildPackTools(connection) {
3403
3436
  "start_child_cloud_build",
3404
3437
  "Start a cloud build for a child task. The child must be in Open status with story points and an agent assigned.",
3405
3438
  {
3406
- childTaskId: z3.string().describe("The child task ID to start a cloud build for")
3439
+ childTaskId: z5.string().describe("The child task ID to start a cloud build for")
3407
3440
  },
3408
3441
  async ({ childTaskId }) => {
3409
3442
  try {
@@ -3423,7 +3456,7 @@ function buildPackTools(connection) {
3423
3456
  "stop_child_build",
3424
3457
  "Stop a running cloud build for a child task. Sends a stop signal to the child agent.",
3425
3458
  {
3426
- childTaskId: z3.string().describe("The child task ID whose build should be stopped")
3459
+ childTaskId: z5.string().describe("The child task ID whose build should be stopped")
3427
3460
  },
3428
3461
  async ({ childTaskId }) => {
3429
3462
  try {
@@ -3443,7 +3476,7 @@ function buildPackTools(connection) {
3443
3476
  "approve_and_merge_pr",
3444
3477
  "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
3478
  {
3446
- childTaskId: z3.string().describe("The child task ID whose PR should be approved and merged")
3479
+ childTaskId: z5.string().describe("The child task ID whose PR should be approved and merged")
3447
3480
  },
3448
3481
  async ({ childTaskId }) => {
3449
3482
  try {
@@ -3481,7 +3514,7 @@ function buildPmTools(connection, options) {
3481
3514
  }
3482
3515
 
3483
3516
  // src/tools/discovery-tools.ts
3484
- import { z as z4 } from "zod";
3517
+ import { z as z6 } from "zod";
3485
3518
  var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
3486
3519
  function buildDiscoveryTools(connection) {
3487
3520
  return [
@@ -3489,10 +3522,10 @@ function buildDiscoveryTools(connection) {
3489
3522
  "update_task_properties",
3490
3523
  "Set one or more task properties in a single call. All fields are optional \u2014 only include the fields you want to update.",
3491
3524
  {
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")
3525
+ title: z6.string().optional().describe("The new task title"),
3526
+ storyPointValue: z6.number().optional().describe(SP_DESCRIPTION2),
3527
+ tagIds: z6.array(z6.string()).optional().describe("Array of tag IDs to assign"),
3528
+ githubPRUrl: z6.string().url().optional().describe("GitHub pull request URL to link to this task")
3496
3529
  },
3497
3530
  async ({ title, storyPointValue, tagIds, githubPRUrl }) => {
3498
3531
  try {
@@ -3521,14 +3554,14 @@ function buildDiscoveryTools(connection) {
3521
3554
  }
3522
3555
 
3523
3556
  // src/tools/code-review-tools.ts
3524
- import { z as z5 } from "zod";
3557
+ import { z as z7 } from "zod";
3525
3558
  function buildCodeReviewTools(connection) {
3526
3559
  return [
3527
3560
  defineTool(
3528
3561
  "approve_code_review",
3529
3562
  "Approve the code review. Use this when the code passes all review criteria and is ready to merge.",
3530
3563
  {
3531
- summary: z5.string().describe("Brief summary of what was reviewed and why it looks good")
3564
+ summary: z7.string().describe("Brief summary of what was reviewed and why it looks good")
3532
3565
  },
3533
3566
  async ({ summary }) => {
3534
3567
  const content = `**Code Review: Approved** :white_check_mark:
@@ -3551,15 +3584,15 @@ ${summary}`;
3551
3584
  "request_code_changes",
3552
3585
  "Request changes during code review. Use this when substantive issues are found that need to be fixed before merge.",
3553
3586
  {
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")
3587
+ issues: z7.array(
3588
+ z7.object({
3589
+ file: z7.string().describe("File path where the issue was found"),
3590
+ line: z7.number().optional().describe("Line number (if applicable)"),
3591
+ severity: z7.enum(["critical", "major", "minor"]).describe("Issue severity"),
3592
+ description: z7.string().describe("What is wrong and how to fix it")
3560
3593
  })
3561
3594
  ).describe("List of issues found during review"),
3562
- summary: z5.string().describe("Brief overall summary of the review findings")
3595
+ summary: z7.string().describe("Brief overall summary of the review findings")
3563
3596
  },
3564
3597
  async ({ issues, summary }) => {
3565
3598
  const issueLines = issues.map((issue) => {
@@ -3589,10 +3622,10 @@ ${issueLines}`;
3589
3622
  }
3590
3623
 
3591
3624
  // src/tools/debug-tools.ts
3592
- import { z as z8 } from "zod";
3625
+ import { z as z10 } from "zod";
3593
3626
 
3594
3627
  // src/tools/telemetry-tools.ts
3595
- import { z as z6 } from "zod";
3628
+ import { z as z8 } from "zod";
3596
3629
 
3597
3630
  // src/debug/telemetry-injector.ts
3598
3631
  var BUFFER_SIZE = 200;
@@ -3987,12 +4020,12 @@ function buildGetTelemetryTool(manager) {
3987
4020
  "debug_get_telemetry",
3988
4021
  "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
4022
  {
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)")
4023
+ type: z8.enum(["http", "db", "socket", "error"]).optional().describe("Filter by event type"),
4024
+ urlPattern: z8.string().optional().describe("Regex pattern to filter HTTP events by URL"),
4025
+ minDuration: z8.number().optional().describe("Minimum duration in ms \u2014 only return events slower than this"),
4026
+ errorOnly: z8.boolean().optional().describe("Only return error events and HTTP 4xx/5xx responses"),
4027
+ since: z8.number().optional().describe("Only return events after this timestamp (ms since epoch)"),
4028
+ limit: z8.number().optional().describe("Max events to return (default: 20, from most recent)")
3996
4029
  },
3997
4030
  async ({ type, urlPattern, minDuration, errorOnly, since, limit }) => {
3998
4031
  const clientOrErr = requireDebugClient(manager);
@@ -4062,7 +4095,7 @@ function buildTelemetryTools(manager) {
4062
4095
  }
4063
4096
 
4064
4097
  // src/tools/client-debug-tools.ts
4065
- import { z as z7 } from "zod";
4098
+ import { z as z9 } from "zod";
4066
4099
  function requirePlaywrightClient(manager) {
4067
4100
  if (!manager.isClientDebugMode()) {
4068
4101
  return "Client debug mode is not active. Use debug_enter_mode with clientSide: true first.";
@@ -4082,11 +4115,11 @@ function buildClientBreakpointTools(manager) {
4082
4115
  "debug_set_client_breakpoint",
4083
4116
  "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
4117
  {
4085
- file: z7.string().describe(
4118
+ file: z9.string().describe(
4086
4119
  "Original source file path (e.g., src/components/App.tsx) \u2014 source maps resolve automatically"
4087
4120
  ),
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")
4121
+ line: z9.number().describe("Line number (1-based) in the original source file"),
4122
+ condition: z9.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
4090
4123
  },
4091
4124
  async ({ file, line, condition }) => {
4092
4125
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4108,7 +4141,7 @@ Breakpoint ID: ${breakpointId}${sourceMapNote}`
4108
4141
  "debug_remove_client_breakpoint",
4109
4142
  "Remove a previously set client-side breakpoint by its ID.",
4110
4143
  {
4111
- breakpointId: z7.string().describe("The breakpoint ID returned by debug_set_client_breakpoint")
4144
+ breakpointId: z9.string().describe("The breakpoint ID returned by debug_set_client_breakpoint")
4112
4145
  },
4113
4146
  async ({ breakpointId }) => {
4114
4147
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4188,8 +4221,8 @@ ${JSON.stringify(queuedHits, null, 2)}`
4188
4221
  "debug_evaluate_client",
4189
4222
  "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
4223
  {
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.")
4224
+ expression: z9.string().describe("JavaScript expression to evaluate in the browser context"),
4225
+ frameIndex: z9.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
4193
4226
  },
4194
4227
  async ({ expression, frameIndex }) => {
4195
4228
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4262,7 +4295,7 @@ function buildClientInteractionTools(manager) {
4262
4295
  "debug_navigate_client",
4263
4296
  "Navigate the headless browser to a specific URL. Use this to reproduce specific flows or visit different pages.",
4264
4297
  {
4265
- url: z7.string().describe("URL to navigate to (e.g., http://localhost:3000/dashboard)")
4298
+ url: z9.string().describe("URL to navigate to (e.g., http://localhost:3000/dashboard)")
4266
4299
  },
4267
4300
  async ({ url }) => {
4268
4301
  const clientOrErr = requirePlaywrightClient(manager);
@@ -4279,7 +4312,7 @@ function buildClientInteractionTools(manager) {
4279
4312
  "debug_click_client",
4280
4313
  "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
4314
  {
4282
- selector: z7.string().describe(
4315
+ selector: z9.string().describe(
4283
4316
  "CSS selector of the element to click (e.g., 'button.submit', '#login-form input[type=submit]')"
4284
4317
  )
4285
4318
  },
@@ -4301,8 +4334,8 @@ function buildClientConsoleTool(manager) {
4301
4334
  "debug_get_client_console",
4302
4335
  "Get console messages captured from the headless browser. Includes console.log, warn, error, etc.",
4303
4336
  {
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)")
4337
+ level: z9.string().optional().describe("Filter by console level: log, warn, error, info, debug"),
4338
+ limit: z9.number().optional().describe("Maximum number of recent messages to return (default: all)")
4306
4339
  },
4307
4340
  // oxlint-disable-next-line require-await
4308
4341
  async ({ level, limit }) => {
@@ -4329,8 +4362,8 @@ function buildClientNetworkTool(manager) {
4329
4362
  "debug_get_client_network",
4330
4363
  "Get network requests captured from the headless browser. Shows URLs, methods, status codes, and timing.",
4331
4364
  {
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)")
4365
+ filter: z9.string().optional().describe("Regex pattern to filter requests by URL"),
4366
+ limit: z9.number().optional().describe("Maximum number of recent requests to return (default: all)")
4334
4367
  },
4335
4368
  // oxlint-disable-next-line require-await
4336
4369
  async ({ filter, limit }) => {
@@ -4358,7 +4391,7 @@ function buildClientErrorsTool(manager) {
4358
4391
  "debug_get_client_errors",
4359
4392
  "Get uncaught errors captured from the headless browser. Includes error messages and source-mapped stack traces.",
4360
4393
  {
4361
- limit: z7.number().optional().describe("Maximum number of recent errors to return (default: all)")
4394
+ limit: z9.number().optional().describe("Maximum number of recent errors to return (default: all)")
4362
4395
  },
4363
4396
  // oxlint-disable-next-line require-await
4364
4397
  async ({ limit }) => {
@@ -4452,12 +4485,12 @@ function buildDebugLifecycleTools(manager) {
4452
4485
  "debug_enter_mode",
4453
4486
  "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
4487
  {
4455
- hypothesis: z8.string().optional().describe("Your hypothesis about the bug \u2014 helps track debugging intent"),
4456
- serverSide: z8.boolean().optional().describe(
4488
+ hypothesis: z10.string().optional().describe("Your hypothesis about the bug \u2014 helps track debugging intent"),
4489
+ serverSide: z10.boolean().optional().describe(
4457
4490
  "Enable server-side Node.js debugging (default: true if clientSide is not set)"
4458
4491
  ),
4459
- clientSide: z8.boolean().optional().describe("Enable client-side browser debugging via headless Chromium + Playwright"),
4460
- previewUrl: z8.string().optional().describe(
4492
+ clientSide: z10.boolean().optional().describe("Enable client-side browser debugging via headless Chromium + Playwright"),
4493
+ previewUrl: z10.string().optional().describe(
4461
4494
  "Preview URL for client-side debugging (e.g., http://localhost:3000). Required when clientSide is true."
4462
4495
  )
4463
4496
  },
@@ -4493,9 +4526,9 @@ function buildBreakpointTools(manager) {
4493
4526
  "debug_set_breakpoint",
4494
4527
  "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
4528
  {
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")
4529
+ file: z10.string().describe("Absolute or relative file path to set the breakpoint in"),
4530
+ line: z10.number().describe("Line number (1-based) to set the breakpoint on"),
4531
+ condition: z10.string().optional().describe("JavaScript condition expression \u2014 breakpoint only triggers when truthy")
4499
4532
  },
4500
4533
  async ({ file, line, condition }) => {
4501
4534
  const clientOrErr = requireDebugClient2(manager);
@@ -4517,7 +4550,7 @@ Breakpoint ID: ${breakpointId}`
4517
4550
  "debug_remove_breakpoint",
4518
4551
  "Remove a previously set breakpoint by its ID.",
4519
4552
  {
4520
- breakpointId: z8.string().describe("The breakpoint ID returned by debug_set_breakpoint")
4553
+ breakpointId: z10.string().describe("The breakpoint ID returned by debug_set_breakpoint")
4521
4554
  },
4522
4555
  async ({ breakpointId }) => {
4523
4556
  const clientOrErr = requireDebugClient2(manager);
@@ -4598,8 +4631,8 @@ ${JSON.stringify(queuedHits, null, 2)}`
4598
4631
  "debug_evaluate",
4599
4632
  "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
4633
  {
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.")
4634
+ expression: z10.string().describe("The JavaScript expression to evaluate"),
4635
+ frameIndex: z10.number().optional().describe("Call stack frame index (0 = top frame). Defaults to the top frame.")
4603
4636
  },
4604
4637
  async ({ expression, frameIndex }) => {
4605
4638
  const clientOrErr = requireDebugClient2(manager);
@@ -4627,12 +4660,12 @@ function buildProbeManagementTools(manager) {
4627
4660
  "debug_add_probe",
4628
4661
  "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
4662
  {
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(
4663
+ file: z10.string().describe("File path to probe"),
4664
+ line: z10.number().describe("Line number (1-based) to probe"),
4665
+ expressions: z10.array(z10.string()).describe(
4633
4666
  'JavaScript expressions to capture when the line executes (e.g., ["req.params.id", "user.role"])'
4634
4667
  ),
4635
- label: z8.string().optional().describe("Optional label for this probe (defaults to file:line)")
4668
+ label: z10.string().optional().describe("Optional label for this probe (defaults to file:line)")
4636
4669
  },
4637
4670
  async ({ file, line, expressions, label }) => {
4638
4671
  const clientOrErr = requireDebugClient2(manager);
@@ -4657,7 +4690,7 @@ Trigger the code path, then use debug_get_probe_results to see captured values.`
4657
4690
  "debug_remove_probe",
4658
4691
  "Remove a previously set debug probe by its ID.",
4659
4692
  {
4660
- probeId: z8.string().describe("The probe ID returned by debug_add_probe")
4693
+ probeId: z10.string().describe("The probe ID returned by debug_add_probe")
4661
4694
  },
4662
4695
  async ({ probeId }) => {
4663
4696
  const clientOrErr = requireDebugClient2(manager);
@@ -4697,9 +4730,9 @@ function buildProbeResultTools(manager) {
4697
4730
  "debug_get_probe_results",
4698
4731
  "Fetch captured probe hit data. Returns expression values from each time a probed line executed.",
4699
4732
  {
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)")
4733
+ probeId: z10.string().optional().describe("Filter results by probe ID (resolves to its label)"),
4734
+ label: z10.string().optional().describe("Filter results by probe label"),
4735
+ limit: z10.number().optional().describe("Maximum number of recent hits to return (default: all)")
4703
4736
  },
4704
4737
  async ({ probeId, label, limit }) => {
4705
4738
  const clientOrErr = requireDebugClient2(manager);
@@ -4862,23 +4895,20 @@ function getModeTools(agentMode, connection, config, context) {
4862
4895
  }
4863
4896
  function buildConveyorTools(connection, config, context, agentMode, debugManager) {
4864
4897
  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
4898
  const commonTools = buildCommonTools(connection, config);
4877
4899
  const modeTools = getModeTools(effectiveMode, connection, config, context);
4878
4900
  const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" ? buildDiscoveryTools(connection) : [];
4901
+ const codeReviewTools = effectiveMode === "review" ? buildCodeReviewTools(connection) : [];
4879
4902
  const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];
4880
4903
  const debugTools = debugManager && effectiveMode === "building" ? buildDebugTools(debugManager) : [];
4881
- return [...commonTools, ...modeTools, ...discoveryTools, ...emergencyTools, ...debugTools];
4904
+ return [
4905
+ ...commonTools,
4906
+ ...modeTools,
4907
+ ...discoveryTools,
4908
+ ...codeReviewTools,
4909
+ ...emergencyTools,
4910
+ ...debugTools
4911
+ ];
4882
4912
  }
4883
4913
  function createConveyorMcpServer(harness, connection, config, context, agentMode, debugManager) {
4884
4914
  return harness.createMcpServer({
@@ -5297,7 +5327,6 @@ function collectMissingProps(taskProps) {
5297
5327
  // src/execution/tool-access.ts
5298
5328
  var PM_PLAN_FILE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit"]);
5299
5329
  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
5330
  var RESOURCE_HEAVY_PATTERNS = [
5302
5331
  /\bbun\s+(install|i|add)\b/,
5303
5332
  /\bnpm\s+(install|ci|i)\b/,
@@ -5334,48 +5363,12 @@ function handleBuildingToolAccess(toolName, input) {
5334
5363
  }
5335
5364
  return { behavior: "allow", updatedInput: input };
5336
5365
  }
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 };
5366
+ function handleReviewToolAccess(toolName, input) {
5367
+ return handleBuildingToolAccess(toolName, input);
5375
5368
  }
5376
5369
  function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask) {
5377
5370
  if (hasExitedPlanMode) {
5378
- return isParentTask ? handleReviewToolAccess(toolName, input, true) : handleBuildingToolAccess(toolName, input);
5371
+ return isParentTask ? handleReviewToolAccess(toolName, input) : handleBuildingToolAccess(toolName, input);
5379
5372
  }
5380
5373
  return { behavior: "allow", updatedInput: input };
5381
5374
  }
@@ -5423,6 +5416,7 @@ async function handleExitPlanMode(host, input) {
5423
5416
  }
5424
5417
  if (host.agentMode === "discovery") {
5425
5418
  host.hasExitedPlanMode = true;
5419
+ host.pendingModeRestart = true;
5426
5420
  void host.connection.triggerIdentification();
5427
5421
  host.connection.postChatMessage(
5428
5422
  "Plan complete. Running identification \u2014 icon and agent assignment will be set automatically."
@@ -5488,11 +5482,9 @@ function resolveToolAccess(host, toolName, input) {
5488
5482
  case "building":
5489
5483
  return handleBuildingToolAccess(toolName, input);
5490
5484
  case "review":
5491
- return handleReviewToolAccess(toolName, input, host.isParentTask);
5485
+ return handleReviewToolAccess(toolName, input);
5492
5486
  case "auto":
5493
5487
  return handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);
5494
- case "code-review":
5495
- return handleCodeReviewToolAccess(toolName, input);
5496
5488
  default:
5497
5489
  return { behavior: "allow", updatedInput: input };
5498
5490
  }
@@ -5571,13 +5563,10 @@ function buildHooks(host) {
5571
5563
  };
5572
5564
  }
5573
5565
  function isReadOnlyMode(mode, hasExitedPlanMode) {
5574
- return mode === "discovery" || mode === "help" || mode === "code-review" || mode === "auto" && !hasExitedPlanMode;
5566
+ return mode === "discovery" || mode === "help" || mode === "auto" && !hasExitedPlanMode;
5575
5567
  }
5576
5568
  function buildDisallowedTools(settings, mode, hasExitedPlanMode) {
5577
5569
  const modeDisallowed = isReadOnlyMode(mode, hasExitedPlanMode) ? ["TodoWrite", "TodoRead", "NotebookEdit"] : [];
5578
- if (mode === "code-review") {
5579
- modeDisallowed.push("ExitPlanMode", "EnterPlanMode");
5580
- }
5581
5570
  const configured = settings.disallowedTools ?? [];
5582
5571
  const combined = [...configured, ...modeDisallowed];
5583
5572
  return combined.length > 0 ? combined : void 0;
@@ -5613,11 +5602,11 @@ function buildQueryOptions(host, context) {
5613
5602
  },
5614
5603
  sandbox: context.useSandbox ? { enabled: true } : { enabled: false },
5615
5604
  hooks: buildHooks(host),
5616
- maxTurns: mode === "code-review" ? Math.min(settings.maxTurns ?? 15, 15) : settings.maxTurns,
5605
+ maxTurns: settings.maxTurns,
5617
5606
  effort: settings.effort,
5618
5607
  thinking: settings.thinking,
5619
5608
  betas: settings.betas,
5620
- maxBudgetUsd: mode === "code-review" ? Math.min(settings.maxBudgetUsd ?? 10, 10) : settings.maxBudgetUsd ?? 50,
5609
+ maxBudgetUsd: settings.maxBudgetUsd ?? 50,
5621
5610
  abortController: host.abortController ?? void 0,
5622
5611
  disallowedTools: buildDisallowedTools(settings, mode, host.hasExitedPlanMode),
5623
5612
  enableFileCheckpointing: settings.enableFileCheckpointing,
@@ -6337,14 +6326,7 @@ var SessionRunner = class _SessionRunner {
6337
6326
  async executeInitialMode() {
6338
6327
  if (!this.taskContext || !this.fullContext) return false;
6339
6328
  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);
6329
+ const shouldRun = effectiveMode === "building" || effectiveMode === "auto" || effectiveMode === "review";
6348
6330
  if (shouldRun) {
6349
6331
  await this.setState("running");
6350
6332
  await this.callbacks.onEvent({ type: "execute_mode", mode: effectiveMode });
@@ -6393,6 +6375,36 @@ var SessionRunner = class _SessionRunner {
6393
6375
  }
6394
6376
  }
6395
6377
  // ── Stop / soft-stop ───────────────────────────────────────────────
6378
+ /** Best-effort WIP commit + push on shutdown so in-flight work isn't lost
6379
+ * when a claudespace pod is killed. Must be called BEFORE stop() so the
6380
+ * connection is still alive for token refresh. Never throws. */
6381
+ async flushGitOnShutdown() {
6382
+ try {
6383
+ const result = await flushPendingChanges(this.config.workspaceDir, {
6384
+ wipMessage: "WIP: auto-commit on conveyor-agent shutdown",
6385
+ refreshToken: async () => {
6386
+ try {
6387
+ const res = await this.connection.call("refreshGithubToken", {
6388
+ sessionId: this.connection.sessionId
6389
+ });
6390
+ return res.token;
6391
+ } catch {
6392
+ return void 0;
6393
+ }
6394
+ }
6395
+ });
6396
+ if (result.hadWork) {
6397
+ process.stderr.write(
6398
+ `[conveyor-agent] Shutdown git flush: committed=${result.committed} pushed=${result.pushed}
6399
+ `
6400
+ );
6401
+ }
6402
+ } catch (err) {
6403
+ const msg = err instanceof Error ? err.message : String(err);
6404
+ process.stderr.write(`[conveyor-agent] Shutdown git flush failed: ${msg}
6405
+ `);
6406
+ }
6407
+ }
6396
6408
  stop() {
6397
6409
  this.stopped = true;
6398
6410
  this.queryBridge?.stop();
@@ -6469,6 +6481,7 @@ var SessionRunner = class _SessionRunner {
6469
6481
  }
6470
6482
  }
6471
6483
  // ── Context & bridge construction ────────────────────────────────
6484
+ // oxlint-disable-next-line complexity
6472
6485
  buildFullContext(ctx) {
6473
6486
  const chatHistory = mapChatHistory(ctx.chatHistory);
6474
6487
  return {
@@ -6495,7 +6508,8 @@ var SessionRunner = class _SessionRunner {
6495
6508
  projectTags: ctx.projectTags ?? void 0,
6496
6509
  taskTagIds: ctx.taskTagIds ?? void 0,
6497
6510
  projectObjectives: ctx.projectObjectives ?? void 0,
6498
- incidents: ctx.incidents ?? void 0
6511
+ incidents: ctx.incidents ?? void 0,
6512
+ agentSettings: ctx.agentSettings ?? null
6499
6513
  };
6500
6514
  }
6501
6515
  createQueryBridge() {
@@ -6545,6 +6559,12 @@ var SessionRunner = class _SessionRunner {
6545
6559
  if (action.type === "start_auto") {
6546
6560
  this.connection.emitModeChanged(this.mode.effectiveMode);
6547
6561
  this.softStop();
6562
+ } else if (action.type === "restart_query") {
6563
+ if (this.fullContext && action.newMode === "review") {
6564
+ this.fullContext.claudeSessionId = null;
6565
+ }
6566
+ this.connection.emitModeChanged(action.newMode);
6567
+ this.softStop();
6548
6568
  }
6549
6569
  });
6550
6570
  this.connection.onWake(() => this.lifecycle.wake());
@@ -7000,7 +7020,7 @@ import * as path from "path";
7000
7020
  import { fileURLToPath as fileURLToPath2 } from "url";
7001
7021
 
7002
7022
  // src/tools/project-tools.ts
7003
- import { z as z9 } from "zod";
7023
+ import { z as z11 } from "zod";
7004
7024
  function buildTaskListTools(connection) {
7005
7025
  const projectId = connection.projectId;
7006
7026
  return [
@@ -7008,9 +7028,9 @@ function buildTaskListTools(connection) {
7008
7028
  "list_tasks",
7009
7029
  "List tasks in the project. Optionally filter by status or assignee.",
7010
7030
  {
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)")
7031
+ status: z11.string().optional().describe("Filter by task status"),
7032
+ assigneeId: z11.string().optional().describe("Filter by assigned user ID"),
7033
+ limit: z11.number().optional().describe("Max number of tasks to return (default 50)")
7014
7034
  },
7015
7035
  async (params) => {
7016
7036
  try {
@@ -7027,7 +7047,7 @@ function buildTaskListTools(connection) {
7027
7047
  defineTool(
7028
7048
  "get_task",
7029
7049
  "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") },
7050
+ { task_id: z11.string().describe("The task ID to look up") },
7031
7051
  async ({ task_id }) => {
7032
7052
  try {
7033
7053
  const task = await connection.call("getProjectTask", { projectId, taskId: task_id });
@@ -7044,10 +7064,10 @@ function buildTaskListTools(connection) {
7044
7064
  "search_tasks",
7045
7065
  "Search tasks by tags, text query, or status filters.",
7046
7066
  {
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)")
7067
+ tagNames: z11.array(z11.string()).optional().describe("Filter by tag names"),
7068
+ searchQuery: z11.string().optional().describe("Text search in title/description"),
7069
+ statusFilters: z11.array(z11.string()).optional().describe("Filter by statuses"),
7070
+ limit: z11.number().optional().describe("Max results (default 20)")
7051
7071
  },
7052
7072
  async (params) => {
7053
7073
  try {
@@ -7107,11 +7127,11 @@ function buildMutationTools(connection) {
7107
7127
  "create_task",
7108
7128
  "Create a new task in the project.",
7109
7129
  {
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")
7130
+ title: z11.string().describe("Task title"),
7131
+ description: z11.string().optional().describe("Task description"),
7132
+ plan: z11.string().optional().describe("Implementation plan in markdown"),
7133
+ status: z11.string().optional().describe("Initial status (default: Planning)"),
7134
+ isBug: z11.boolean().optional().describe("Whether this is a bug report")
7115
7135
  },
7116
7136
  async (params) => {
7117
7137
  try {
@@ -7128,12 +7148,12 @@ function buildMutationTools(connection) {
7128
7148
  "update_task",
7129
7149
  "Update an existing task's title, description, plan, status, or assignee.",
7130
7150
  {
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")
7151
+ task_id: z11.string().describe("The task ID to update"),
7152
+ title: z11.string().optional().describe("New title"),
7153
+ description: z11.string().optional().describe("New description"),
7154
+ plan: z11.string().optional().describe("New plan in markdown"),
7155
+ status: z11.string().optional().describe("New status"),
7156
+ assignedUserId: z11.string().nullable().optional().describe("Assign to user ID, or null to unassign")
7137
7157
  },
7138
7158
  async ({ task_id, ...fields }) => {
7139
7159
  try {
@@ -7502,6 +7522,32 @@ var ProjectRunner = class {
7502
7522
  this.resolveLifecycle = resolve2;
7503
7523
  });
7504
7524
  }
7525
+ /** Best-effort WIP commit + push of every tracked working tree on shutdown.
7526
+ * Iterates the main project dir plus any active agent worktrees so nothing
7527
+ * pending is lost when the pod is killed. Never throws. */
7528
+ async flushGitOnShutdown() {
7529
+ const dirs = /* @__PURE__ */ new Set([this.projectDir]);
7530
+ for (const agent of this.activeAgents.values()) {
7531
+ if (agent.worktreePath) dirs.add(agent.worktreePath);
7532
+ }
7533
+ for (const dir of dirs) {
7534
+ try {
7535
+ const result = await flushPendingChanges(dir, {
7536
+ wipMessage: "WIP: auto-commit on conveyor-agent shutdown"
7537
+ });
7538
+ if (result.hadWork) {
7539
+ logger7.info("Shutdown git flush", {
7540
+ dir,
7541
+ committed: result.committed,
7542
+ pushed: result.pushed
7543
+ });
7544
+ }
7545
+ } catch (err) {
7546
+ const msg = err instanceof Error ? err.message : String(err);
7547
+ logger7.warn("Shutdown git flush failed", { dir, error: msg });
7548
+ }
7549
+ }
7550
+ }
7505
7551
  async stop() {
7506
7552
  if (this.stopping) return;
7507
7553
  this.stopping = true;
@@ -7529,6 +7575,7 @@ var ProjectRunner = class {
7529
7575
  setTimeout(resolve2, STOP_TIMEOUT_MS + 5e3);
7530
7576
  })
7531
7577
  ]);
7578
+ await this.flushGitOnShutdown();
7532
7579
  try {
7533
7580
  await this.connection.call("disconnectProjectRunner", {
7534
7581
  projectId: this.connection.projectId
@@ -7582,7 +7629,7 @@ var ProjectRunner = class {
7582
7629
  async handleAuditTags(request) {
7583
7630
  this.connection.emitStatus("busy");
7584
7631
  try {
7585
- const { handleTagAudit } = await import("./tag-audit-handler-L7YPDXTA.js");
7632
+ const { handleTagAudit } = await import("./tag-audit-handler-BM6MMS5T.js");
7586
7633
  await handleTagAudit(request, this.connection, this.projectDir);
7587
7634
  } catch (error) {
7588
7635
  const msg = error instanceof Error ? error.message : String(error);
@@ -7987,6 +8034,7 @@ export {
7987
8034
  hasUnpushedCommits,
7988
8035
  stageAndCommit,
7989
8036
  updateRemoteToken,
8037
+ flushPendingChanges,
7990
8038
  pushToOrigin,
7991
8039
  injectTelemetry,
7992
8040
  PlanSync,
@@ -8003,4 +8051,4 @@ export {
8003
8051
  loadForwardPorts,
8004
8052
  loadConveyorConfig
8005
8053
  };
8006
- //# sourceMappingURL=chunk-QLY35BX7.js.map
8054
+ //# sourceMappingURL=chunk-AZ6CRVYN.js.map