baxian 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/agent/manager.d.ts +10 -9
  2. package/dist/agent/manager.d.ts.map +1 -1
  3. package/dist/agent/manager.js +181 -413
  4. package/dist/agent/manager.js.map +1 -1
  5. package/dist/agent/phase-signal-watcher.d.ts +1 -4
  6. package/dist/agent/phase-signal-watcher.d.ts.map +1 -1
  7. package/dist/agent/phase-signal-watcher.js +3 -22
  8. package/dist/agent/phase-signal-watcher.js.map +1 -1
  9. package/dist/agent/phase-signal.d.ts +1 -10
  10. package/dist/agent/phase-signal.d.ts.map +1 -1
  11. package/dist/agent/phase-signal.js +5 -8
  12. package/dist/agent/phase-signal.js.map +1 -1
  13. package/dist/agent/prompt.d.ts +1 -2
  14. package/dist/agent/prompt.d.ts.map +1 -1
  15. package/dist/agent/prompt.js +32 -63
  16. package/dist/agent/prompt.js.map +1 -1
  17. package/dist/agent/repo-store.d.ts +0 -1
  18. package/dist/agent/repo-store.d.ts.map +1 -1
  19. package/dist/agent/repo-store.js +0 -25
  20. package/dist/agent/repo-store.js.map +1 -1
  21. package/dist/agent/worktree.d.ts +1 -0
  22. package/dist/agent/worktree.d.ts.map +1 -1
  23. package/dist/agent/worktree.js +14 -0
  24. package/dist/agent/worktree.js.map +1 -1
  25. package/dist/api/agents.d.ts.map +1 -1
  26. package/dist/api/agents.js +4 -0
  27. package/dist/api/agents.js.map +1 -1
  28. package/dist/api/tasks.js +1 -1
  29. package/dist/api/tasks.js.map +1 -1
  30. package/dist/cli.d.ts.map +1 -1
  31. package/dist/cli.js +8 -1
  32. package/dist/cli.js.map +1 -1
  33. package/dist/event/handlers.d.ts.map +1 -1
  34. package/dist/event/handlers.js +10 -430
  35. package/dist/event/handlers.js.map +1 -1
  36. package/dist/event/server-handlers.d.ts.map +1 -1
  37. package/dist/event/server-handlers.js +21 -14
  38. package/dist/event/server-handlers.js.map +1 -1
  39. package/dist/shared/constants.d.ts +1 -1
  40. package/dist/shared/constants.d.ts.map +1 -1
  41. package/dist/shared/constants.js +0 -6
  42. package/dist/shared/constants.js.map +1 -1
  43. package/dist/shared/types.d.ts +1 -1
  44. package/dist/shared/types.d.ts.map +1 -1
  45. package/dist/skills/server-feedback/SKILL.md +4 -2
  46. package/dist/terminal/attach.d.ts.map +1 -1
  47. package/dist/terminal/attach.js +8 -2
  48. package/dist/terminal/attach.js.map +1 -1
  49. package/dist/web/assets/index-OtgjyQI1.js +4 -0
  50. package/dist/web/index.html +1 -1
  51. package/package.json +1 -1
  52. package/dist/web/assets/index-DE_xpPQe.js +0 -4
@@ -8,7 +8,7 @@ function validHeadSha(value) {
8
8
  // Re-establish the develop-phase watcher after a handler-side rejection so the same
9
9
  // task can consume a corrected emit (same token) without a server restart.
10
10
  async function reArmDevelopWatcher(manager, task, agentId) {
11
- const kinds = task.phase === 'code' ? ['pr-created'] : ['spec-created', 'pr-created'];
11
+ const kinds = task.phase === 'code' ? ['pr-created'] : ['spec-done', 'pr-created'];
12
12
  await manager.setupPhaseSignal(task.id, agentId, kinds);
13
13
  }
14
14
  async function emitIntervention(bus, projectId, agentId, taskId, data) {
@@ -157,10 +157,8 @@ export function registerEventHandlers(bus, manager) {
157
157
  // transition only needs prNumber to wire task→PR; prUrl is derivable from
158
158
  // repo+number; headSha lands via the next pr.updated push event.
159
159
  //
160
- // spec phase 完全由 signal 协议(spec.ready / spec.review.submitted / spec.fix.submitted)
161
- // 驱动;spec doc PR push 也会触发 pr.created/updated,poller 不应越过 signal 协议派
162
- // QA review。否则 QA 在 spec-review 槽位上跑 pr-review 流程,再 gh pr review --approve
163
- // → review.submitted → post-approve dispatch,实际代码还没写。
160
+ // spec phase server 评审链(server.spec.* handlers)驱动;poller 不应越过它派 QA review,
161
+ // 否则 QA spec-review 槽位上跑 pr-review 流程,gh pr review --approve 会误触 post-approve。
164
162
  {
165
163
  const taskNow = await manager.getTask(event.taskId);
166
164
  if (taskNow?.phase === 'spec') {
@@ -341,9 +339,9 @@ export function registerEventHandlers(bus, manager) {
341
339
  const eventPrNumber = event.data.prNumber;
342
340
  const eventPrUrl = event.data.prUrl;
343
341
  const eventKind = event.data.kind;
344
- // spec phase 由 signal 协议驱动;spec doc 的 push / spec-review 留下的 PR comment 都不应
345
- // 进入 code-review 流程(避免派 QA recheck → gh pr review --approve → 误派 post-approve)。
346
- // pr-merge-ready 是 dev 自己内部状态推进,不受 phase gate 限制。
342
+ // spec phase 由 server 评审链驱动;spec doc 的 push/comment 不应进入 code-review 流程
343
+ // (避免 QA recheck → gh pr review --approve → 误派 post-approve)。
344
+ // pr-merge-ready 是 dev 内部状态推进,不受 phase gate 限制。
347
345
  if (eventKind !== 'pr-merge-ready') {
348
346
  const taskNow = await manager.getTask(event.taskId);
349
347
  if (taskNow?.phase === 'spec') {
@@ -577,7 +575,7 @@ export function registerEventHandlers(bus, manager) {
577
575
  // No armed watcher → a same-identity verdict would have no consumer.
578
576
  console.warn(`[EventHandler] pr.updated verdict watcher failed to arm for task=${transitioned.id} (${qaPhase}); rolling back recheck dispatch`);
579
577
  if (previousStatus === 'in_progress' || previousStatus === 'fixing') {
580
- // Full rollback: the dev's prior-phase prompt (spec-created/pr-created or pr-fixed) used the
578
+ // Full rollback: the dev's prior-phase prompt (spec-done/pr-created or pr-fixed) used the
581
579
  // pre-rotation token; restore status+token+anchor and re-arm so its already-emitted signal
582
580
  // isn't stranded by the token rotation.
583
581
  await manager.rollbackVerdictArmFailure(transitioned.id, {
@@ -746,10 +744,9 @@ export function registerEventHandlers(bus, manager) {
746
744
  }
747
745
  }
748
746
  }
749
- // spec phase(非 terminal)由 signal 协议(spec.review.submitted)驱动 verdict;GitHub
750
- // PR review 不应改 task.status。QA spec-review 槽位上若错走 gh pr review --approve
751
- // 这里早退避免把 status 推到 approved + 派 dev post-approve。terminal 状态已在前面兜底
752
- // 释放,此处只屏蔽 active spec 路径。
747
+ // spec phase(非 terminal)由 server 评审链(server.spec.review.submitted)驱动 verdict;
748
+ // GitHub PR review 不应改 task.status,早退避免误推 approved + dev post-approve
749
+ // terminal 状态已在前面兜底释放,此处只屏蔽 active spec 路径。
753
750
  if (task.phase === 'spec') {
754
751
  console.warn(`[EventHandler] review.submitted (action=${action}) ignored for task ${task.id}: task in spec phase`);
755
752
  return;
@@ -1085,222 +1082,6 @@ export function registerEventHandlers(bus, manager) {
1085
1082
  }
1086
1083
  }
1087
1084
  });
1088
- bus.on('spec.ready', async (event) => {
1089
- if (!event.taskId)
1090
- return;
1091
- const task = await manager.getTask(event.taskId);
1092
- if (!task)
1093
- return;
1094
- // Freshness gate: 拒迟到 / scrollback 复活的 stale spec-created signal。
1095
- // 期望 task 仍在 pre-spec 阶段 (phase undefined, status in_progress) 且 token 匹配。
1096
- const eventToken = event.data?.token;
1097
- const stale = task.phase !== undefined
1098
- || task.status !== 'in_progress'
1099
- || !eventToken
1100
- || eventToken !== task.signalToken;
1101
- if (stale) {
1102
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1103
- phase: 'spec-created-event-stale',
1104
- taskPhase: task.phase ?? null,
1105
- taskStatus: task.status,
1106
- });
1107
- return;
1108
- }
1109
- try {
1110
- await manager.dispatchSpecReviewToQa(event.taskId);
1111
- }
1112
- catch (err) {
1113
- console.error(`[EventHandler] spec.ready dispatchSpecReviewToQa(${event.taskId}) failed:`, err);
1114
- await emitIntervention(bus, event.projectId, event.agentId ?? '', event.taskId, {
1115
- phase: 'spec-created-dispatch-failed',
1116
- error: err instanceof Error ? err.message : String(err),
1117
- });
1118
- }
1119
- });
1120
- bus.on('spec.review.submitted', async (event) => {
1121
- if (!event.taskId)
1122
- return;
1123
- const task = await manager.getTask(event.taskId);
1124
- if (!task)
1125
- return;
1126
- // Freshness gate: stale signal would inject old findings into a code-phase session.
1127
- const eventToken = event.data?.token;
1128
- const stale = task.phase !== 'spec'
1129
- || task.status !== 'review'
1130
- || !eventToken
1131
- || eventToken !== task.signalToken;
1132
- if (stale) {
1133
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1134
- phase: 'spec-review-event-stale',
1135
- taskPhase: task.phase ?? null,
1136
- taskStatus: task.status,
1137
- });
1138
- return;
1139
- }
1140
- const round = task.specReviewRound ?? 1;
1141
- // Verdict comes from the signal kind directly — no findings.json read for
1142
- // the verdict bit. findings.json is still read later (during spec-fix
1143
- // dispatch) for the issue list, but its schema no longer carries a verdict.
1144
- const signalKind = event.data?.kind;
1145
- if (signalKind === 'spec-approved') {
1146
- try {
1147
- await manager.transitionToCodePhase(task.id);
1148
- }
1149
- catch (err) {
1150
- console.error(`[EventHandler] spec.review approve transitionToCodePhase(${task.id}) failed:`, err);
1151
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1152
- phase: 'spec-review-approve-transition-failed',
1153
- error: err instanceof Error ? err.message : String(err),
1154
- });
1155
- }
1156
- return;
1157
- }
1158
- if (signalKind !== 'spec-changes-requested') {
1159
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1160
- phase: 'spec-review-unknown-verdict-signal',
1161
- round,
1162
- signalKind: signalKind ?? null,
1163
- });
1164
- return;
1165
- }
1166
- // changes-requested path: load findings.json for the issue list (verdict
1167
- // already known from the signal kind above).
1168
- const fileName = `round-${round}-findings.json`;
1169
- let raw = null;
1170
- try {
1171
- raw = await manager.readSpecReviewFile(event.taskId, fileName);
1172
- }
1173
- catch (err) {
1174
- console.error(`[EventHandler] spec.review.submitted readSpecReviewFile(${event.taskId}) failed:`, err);
1175
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1176
- phase: 'spec-review-findings-read-failed',
1177
- round,
1178
- error: err instanceof Error ? err.message : String(err),
1179
- });
1180
- return;
1181
- }
1182
- if (raw === null) {
1183
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1184
- phase: 'spec-review-findings-missing',
1185
- round,
1186
- fileName,
1187
- });
1188
- return;
1189
- }
1190
- let parsed;
1191
- try {
1192
- parsed = JSON.parse(raw);
1193
- }
1194
- catch (err) {
1195
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1196
- phase: 'spec-review-findings-invalid-json',
1197
- round,
1198
- error: err instanceof Error ? err.message : String(err),
1199
- });
1200
- return;
1201
- }
1202
- // Round mismatch ⇒ QA wrote wrong-round content into current findings file.
1203
- if (typeof parsed.round !== 'number' || parsed.round !== round) {
1204
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1205
- phase: 'spec-review-findings-round-mismatch',
1206
- round,
1207
- parsedRound: parsed.round ?? null,
1208
- });
1209
- return;
1210
- }
1211
- const cap = manager.getConfig().review.rounds;
1212
- if (round >= cap) {
1213
- const result = await manager.transitionTaskStatus(event.taskId, 'max_rounds', { fromStatus: ['review'] });
1214
- if (!result)
1215
- return;
1216
- const { task: transitioned } = result;
1217
- manager.stopSpecSignalWatcher(transitioned.id);
1218
- // release 失败时 binding 残留 → 后续 acquire 会拒;emit intervention 让 stale binding 可见。
1219
- // spec max_rounds 同样暂停为 active 态:清掉已成功释放(解绑)的 agent 引用,否则该已释放
1220
- // agent 之后因 tmux/recovery 失败会经 failTasksForAgent 把这个暂停 task 误标 failed。仅当释放
1221
- // 成功(确已解绑)才清——若仍 held/bound 则保留引用,让其故障正常归因到本 task。
1222
- const clearIds = {};
1223
- if (transitioned.qaAgentId) {
1224
- const qaReleased = await manager
1225
- .releaseAgentForTask(transitioned.qaAgentId, transitioned.id, 'idle')
1226
- .catch(() => false);
1227
- if (qaReleased) {
1228
- clearIds.qaAgentId = undefined;
1229
- }
1230
- else {
1231
- await emitIntervention(bus, transitioned.projectId, transitioned.qaAgentId, transitioned.id, {
1232
- phase: 'spec-review-max-rounds-qa-release-failed',
1233
- qaAgentId: transitioned.qaAgentId,
1234
- });
1235
- }
1236
- }
1237
- if (transitioned.agentId) {
1238
- const devReleased = await manager
1239
- .releaseAgentForTask(transitioned.agentId, transitioned.id, 'idle')
1240
- .catch(() => false);
1241
- if (devReleased) {
1242
- clearIds.agentId = undefined;
1243
- }
1244
- else {
1245
- await emitIntervention(bus, transitioned.projectId, transitioned.agentId, transitioned.id, {
1246
- phase: 'spec-review-max-rounds-dev-release-failed',
1247
- devAgentId: transitioned.agentId,
1248
- });
1249
- }
1250
- }
1251
- if ('qaAgentId' in clearIds || 'agentId' in clearIds) {
1252
- await manager.updateTask(transitioned.id, clearIds)
1253
- .catch(err => console.error(`[EventHandler] spec max_rounds clear agent ids(${transitioned.id}) failed:`, err));
1254
- }
1255
- await emitIntervention(bus, transitioned.projectId, transitioned.agentId, transitioned.id, {
1256
- phase: 'spec-review-max-rounds',
1257
- round,
1258
- cap,
1259
- });
1260
- return;
1261
- }
1262
- // changes-requested 必须有非空 findings — 提前 fail-loud。
1263
- if (!Array.isArray(parsed.findings) || parsed.findings.length === 0) {
1264
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1265
- phase: 'spec-review-findings-invalid-shape',
1266
- round,
1267
- findingsType: Array.isArray(parsed.findings) ? 'empty-array' : typeof parsed.findings,
1268
- });
1269
- return;
1270
- }
1271
- // 每条 finding 必须有唯一非空 id — coverage 校验依赖它。fail-closed。
1272
- const findingsArr = parsed.findings;
1273
- const idSet = new Set();
1274
- for (const f of findingsArr) {
1275
- const id = f?.id;
1276
- if (typeof id !== 'string' || id.length === 0) {
1277
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1278
- phase: 'spec-review-findings-missing-id',
1279
- round,
1280
- });
1281
- return;
1282
- }
1283
- if (idSet.has(id)) {
1284
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1285
- phase: 'spec-review-findings-duplicate-id',
1286
- round,
1287
- duplicateId: id,
1288
- });
1289
- return;
1290
- }
1291
- idSet.add(id);
1292
- }
1293
- try {
1294
- await manager.dispatchSpecFixToDev(task.id, raw);
1295
- }
1296
- catch (err) {
1297
- console.error(`[EventHandler] spec.review dispatchSpecFixToDev(${task.id}) failed:`, err);
1298
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1299
- phase: 'spec-fix-dispatch-failed',
1300
- error: err instanceof Error ? err.message : String(err),
1301
- });
1302
- }
1303
- });
1304
1085
  // Dev emitted pr-fixed: it claims the fixing round is done. Verify on GitHub
1305
1086
  // before advancing (option C) — a new commit OR a reply to the findings means
1306
1087
  // real work; neither means a no-op claim (the task-060 lie). Every GitHub read
@@ -1407,206 +1188,5 @@ export function registerEventHandlers(bus, manager) {
1407
1188
  });
1408
1189
  }
1409
1190
  });
1410
- bus.on('spec.fix.submitted', async (event) => {
1411
- if (!event.taskId)
1412
- return;
1413
- const task = await manager.getTask(event.taskId);
1414
- if (!task)
1415
- return;
1416
- // Freshness gate: stale signal may re-trigger dispatch after spec phase exit.
1417
- const eventToken = event.data?.token;
1418
- const stale = task.phase !== 'spec'
1419
- || task.status !== 'fixing'
1420
- || !eventToken
1421
- || eventToken !== task.signalToken;
1422
- if (stale) {
1423
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1424
- phase: 'spec-fix-event-stale',
1425
- taskPhase: task.phase ?? null,
1426
- taskStatus: task.status,
1427
- });
1428
- return;
1429
- }
1430
- const round = task.specReviewRound ?? 1;
1431
- const fileName = `round-${round}-response.json`;
1432
- let raw = null;
1433
- try {
1434
- raw = await manager.readSpecReviewFile(event.taskId, fileName);
1435
- }
1436
- catch (err) {
1437
- console.error(`[EventHandler] spec.fix.submitted readSpecReviewFile(${event.taskId}) failed:`, err);
1438
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1439
- phase: 'spec-fix-response-read-failed',
1440
- round,
1441
- error: err instanceof Error ? err.message : String(err),
1442
- });
1443
- return;
1444
- }
1445
- if (raw === null) {
1446
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1447
- phase: 'spec-fix-response-missing',
1448
- round,
1449
- fileName,
1450
- });
1451
- return;
1452
- }
1453
- let parsed;
1454
- try {
1455
- parsed = JSON.parse(raw);
1456
- }
1457
- catch (err) {
1458
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1459
- phase: 'spec-fix-response-invalid-json',
1460
- round,
1461
- error: err instanceof Error ? err.message : String(err),
1462
- });
1463
- return;
1464
- }
1465
- if (typeof parsed.round !== 'number' || parsed.round !== round) {
1466
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1467
- phase: 'spec-fix-response-round-mismatch',
1468
- round,
1469
- parsedRound: parsed.round ?? null,
1470
- });
1471
- return;
1472
- }
1473
- if (!Array.isArray(parsed.responses)) {
1474
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1475
- phase: 'spec-fix-response-invalid-shape',
1476
- round,
1477
- });
1478
- return;
1479
- }
1480
- const responses = parsed.responses;
1481
- if (responses.length === 0) {
1482
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1483
- phase: 'spec-fix-response-empty',
1484
- round,
1485
- });
1486
- return;
1487
- }
1488
- for (const r of responses) {
1489
- if (r?.action !== 'fix' && r?.action !== 'reject') {
1490
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1491
- phase: 'spec-fix-response-invalid-action',
1492
- round,
1493
- action: r?.action ?? null,
1494
- });
1495
- return;
1496
- }
1497
- }
1498
- // Coverage check: response must cover every finding.id; all branches fail-closed
1499
- // (read/parse/round-mismatch all emit + return — fail-open would let all-reject sneak into code phase).
1500
- let findingsRaw;
1501
- try {
1502
- findingsRaw = await manager.readSpecReviewFile(event.taskId, `round-${round}-findings.json`);
1503
- }
1504
- catch (err) {
1505
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1506
- phase: 'spec-fix-coverage-findings-read-failed',
1507
- round,
1508
- error: err instanceof Error ? err.message : String(err),
1509
- });
1510
- return;
1511
- }
1512
- if (findingsRaw === null) {
1513
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1514
- phase: 'spec-fix-coverage-findings-missing',
1515
- round,
1516
- });
1517
- return;
1518
- }
1519
- let findingsParsed;
1520
- try {
1521
- findingsParsed = JSON.parse(findingsRaw);
1522
- }
1523
- catch (err) {
1524
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1525
- phase: 'spec-fix-coverage-findings-invalid-json',
1526
- round,
1527
- error: err instanceof Error ? err.message : String(err),
1528
- });
1529
- return;
1530
- }
1531
- if (typeof findingsParsed.round !== 'number' || findingsParsed.round !== round) {
1532
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1533
- phase: 'spec-fix-coverage-findings-round-mismatch',
1534
- round,
1535
- parsedRound: findingsParsed.round ?? null,
1536
- });
1537
- return;
1538
- }
1539
- // 独立 fail-closed schema 校验 — 上一阶段的校验对本 handler 不可信。
1540
- if (!Array.isArray(findingsParsed.findings) || findingsParsed.findings.length === 0) {
1541
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1542
- phase: 'spec-fix-coverage-findings-invalid-shape',
1543
- round,
1544
- findingsType: Array.isArray(findingsParsed.findings)
1545
- ? 'empty-array'
1546
- : typeof findingsParsed.findings,
1547
- });
1548
- return;
1549
- }
1550
- const findingIdsList = [];
1551
- for (const f of findingsParsed.findings) {
1552
- const id = f?.id;
1553
- if (typeof id !== 'string' || id.length === 0) {
1554
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1555
- phase: 'spec-fix-coverage-findings-missing-id',
1556
- round,
1557
- });
1558
- return;
1559
- }
1560
- if (findingIdsList.includes(id)) {
1561
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1562
- phase: 'spec-fix-coverage-findings-duplicate-id',
1563
- round,
1564
- duplicateId: id,
1565
- });
1566
- return;
1567
- }
1568
- findingIdsList.push(id);
1569
- }
1570
- const findingIds = new Set(findingIdsList);
1571
- const responseIds = new Set(responses
1572
- .map(r => r?.findingId)
1573
- .filter((id) => typeof id === 'string'));
1574
- const missing = [...findingIds].filter(id => !responseIds.has(id));
1575
- const unknown = [...responseIds].filter(id => !findingIds.has(id));
1576
- if (missing.length > 0 || unknown.length > 0) {
1577
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1578
- phase: 'spec-fix-response-coverage-mismatch',
1579
- round,
1580
- missingFindingIds: missing,
1581
- unknownFindingIds: unknown,
1582
- });
1583
- return;
1584
- }
1585
- const hasAnyFix = responses.some(r => r.action === 'fix');
1586
- if (!hasAnyFix) {
1587
- // 全 reject → dev 直接进 code phase;不再 qa review。
1588
- try {
1589
- await manager.transitionToCodePhase(task.id);
1590
- }
1591
- catch (err) {
1592
- console.error(`[EventHandler] spec.fix all-reject transitionToCodePhase(${task.id}) failed:`, err);
1593
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1594
- phase: 'spec-fix-all-reject-transition-failed',
1595
- error: err instanceof Error ? err.message : String(err),
1596
- });
1597
- }
1598
- return;
1599
- }
1600
- try {
1601
- await manager.dispatchSpecReviewToQa(task.id);
1602
- }
1603
- catch (err) {
1604
- console.error(`[EventHandler] spec.fix dispatchSpecReviewToQa(${task.id}) failed:`, err);
1605
- await emitIntervention(bus, task.projectId, task.agentId, task.id, {
1606
- phase: 'spec-fix-redispatch-failed',
1607
- error: err instanceof Error ? err.message : String(err),
1608
- });
1609
- }
1610
- });
1611
1191
  }
1612
1192
  //# sourceMappingURL=handlers.js.map