@xdevops/issue-auto-finish 1.0.87 → 1.0.89

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 (134) hide show
  1. package/dist/{AIRunnerRegistry-II3WWSFN.js → AIRunnerRegistry-CFDNWSXC.js} +6 -3
  2. package/dist/{LockNote-Z2CLDZNN.js → LockNote-W2JNVMW7.js} +3 -3
  3. package/dist/PtyRunner-NYASBTRP.js +33 -0
  4. package/dist/SdkRunner-U2OTOMZU.js +9 -0
  5. package/dist/ai-runner/AIRunner.d.ts +19 -1
  6. package/dist/ai-runner/AIRunner.d.ts.map +1 -1
  7. package/dist/ai-runner/AIRunnerRegistry.d.ts +8 -0
  8. package/dist/ai-runner/AIRunnerRegistry.d.ts.map +1 -1
  9. package/dist/ai-runner/PlanFileResolver.d.ts +53 -0
  10. package/dist/ai-runner/PlanFileResolver.d.ts.map +1 -0
  11. package/dist/ai-runner/PtyRunner.d.ts +45 -4
  12. package/dist/ai-runner/PtyRunner.d.ts.map +1 -1
  13. package/dist/ai-runner/SdkRunner.d.ts +22 -0
  14. package/dist/ai-runner/SdkRunner.d.ts.map +1 -0
  15. package/dist/ai-runner/index.d.ts +5 -2
  16. package/dist/ai-runner/index.d.ts.map +1 -1
  17. package/dist/ai-runner/sdk/ClaudeCodeSDK.d.ts +37 -0
  18. package/dist/ai-runner/sdk/ClaudeCodeSDK.d.ts.map +1 -0
  19. package/dist/ai-runner/sdk/Stream.d.ts +22 -0
  20. package/dist/ai-runner/sdk/Stream.d.ts.map +1 -0
  21. package/dist/ai-runner/sdk/types.d.ts +146 -0
  22. package/dist/ai-runner/sdk/types.d.ts.map +1 -0
  23. package/dist/{ai-runner-HLA44WI6.js → ai-runner-TOHVJJ76.js} +14 -5
  24. package/dist/{analyze-ZIXNC5GN.js → analyze-DBH4K3J7.js} +8 -6
  25. package/dist/{analyze-ZIXNC5GN.js.map → analyze-DBH4K3J7.js.map} +1 -1
  26. package/dist/{braindump-56WAY2RD.js → braindump-RYI4BGMG.js} +11 -9
  27. package/dist/{braindump-56WAY2RD.js.map → braindump-RYI4BGMG.js.map} +1 -1
  28. package/dist/{chunk-AVGZH64A.js → chunk-2RWGZPNF.js} +4 -1
  29. package/dist/chunk-2RWGZPNF.js.map +1 -0
  30. package/dist/chunk-4XMYOXGZ.js +1153 -0
  31. package/dist/chunk-4XMYOXGZ.js.map +1 -0
  32. package/dist/{chunk-UBQLXQ7I.js → chunk-5JBADEKR.js} +7 -7
  33. package/dist/{chunk-M5C2WILQ.js → chunk-5M5SB6ZA.js} +7 -5
  34. package/dist/{chunk-M5C2WILQ.js.map → chunk-5M5SB6ZA.js.map} +1 -1
  35. package/dist/{chunk-HDFNMVRQ.js → chunk-DVNAH2GV.js} +2 -2
  36. package/dist/{chunk-GXFG4JU6.js → chunk-EU4XFZ2T.js} +2 -2
  37. package/dist/{chunk-NZHKAPU6.js → chunk-FJTZKAJA.js} +9 -3
  38. package/dist/chunk-FJTZKAJA.js.map +1 -0
  39. package/dist/chunk-G7QI5WDI.js +14 -0
  40. package/dist/chunk-G7QI5WDI.js.map +1 -0
  41. package/dist/{chunk-2YQHKXLL.js → chunk-GPZX4DSY.js} +22 -6
  42. package/dist/chunk-GPZX4DSY.js.map +1 -0
  43. package/dist/{chunk-IP3QTP5A.js → chunk-IWSMQXBL.js} +189 -48
  44. package/dist/chunk-IWSMQXBL.js.map +1 -0
  45. package/dist/{chunk-O3WEV5W3.js → chunk-JMACM7AJ.js} +47 -9
  46. package/dist/chunk-JMACM7AJ.js.map +1 -0
  47. package/dist/chunk-MSL7ROVK.js +1 -0
  48. package/dist/{chunk-YCYVNRLF.js → chunk-OBGEEGQ3.js} +61 -19
  49. package/dist/chunk-OBGEEGQ3.js.map +1 -0
  50. package/dist/chunk-R32Q3RGK.js +666 -0
  51. package/dist/chunk-R32Q3RGK.js.map +1 -0
  52. package/dist/{chunk-SAMTXC4A.js → chunk-TFEPHOVE.js} +12 -17
  53. package/dist/chunk-TFEPHOVE.js.map +1 -0
  54. package/dist/{chunk-QZZGIZWC.js → chunk-XSX3PGQW.js} +63 -20
  55. package/dist/chunk-XSX3PGQW.js.map +1 -0
  56. package/dist/{chunk-2MESXJEZ.js → chunk-YNRKPQLS.js} +3 -3
  57. package/dist/cli/setup/PreflightChecker.d.ts +1 -0
  58. package/dist/cli/setup/PreflightChecker.d.ts.map +1 -1
  59. package/dist/cli/setup/env-metadata.d.ts.map +1 -1
  60. package/dist/cli.js +10 -9
  61. package/dist/cli.js.map +1 -1
  62. package/dist/{config-WTRSZLOC.js → config-23TBYFP5.js} +5 -4
  63. package/dist/config-schema.d.ts +6 -0
  64. package/dist/config-schema.d.ts.map +1 -1
  65. package/dist/config.d.ts +6 -0
  66. package/dist/config.d.ts.map +1 -1
  67. package/dist/{doctor-37JNBGDN.js → doctor-ZG3DO7J5.js} +3 -3
  68. package/dist/errors/AIExecutionError.d.ts +3 -0
  69. package/dist/errors/AIExecutionError.d.ts.map +1 -1
  70. package/dist/{errors-S3BWYA4I.js → errors-J3ZRP66W.js} +2 -2
  71. package/dist/events/EventBus.d.ts +1 -1
  72. package/dist/events/EventBus.d.ts.map +1 -1
  73. package/dist/i18n/locales/en.d.ts.map +1 -1
  74. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +16 -14
  77. package/dist/{init-QQDXGTPB.js → init-37DLQ5AJ.js} +9 -8
  78. package/dist/{init-QQDXGTPB.js.map → init-37DLQ5AJ.js.map} +1 -1
  79. package/dist/lib.js +10 -8
  80. package/dist/lib.js.map +1 -1
  81. package/dist/orchestrator/PendingDialogStore.d.ts +12 -0
  82. package/dist/orchestrator/PendingDialogStore.d.ts.map +1 -0
  83. package/dist/orchestrator/steps/FailureHandler.d.ts.map +1 -1
  84. package/dist/orchestrator/steps/PhaseLoopStep.d.ts.map +1 -1
  85. package/dist/persistence/PlanPersistence.d.ts +5 -0
  86. package/dist/persistence/PlanPersistence.d.ts.map +1 -1
  87. package/dist/persistence/TodolistExtractor.d.ts +31 -0
  88. package/dist/persistence/TodolistExtractor.d.ts.map +1 -0
  89. package/dist/phases/BasePhase.d.ts.map +1 -1
  90. package/dist/phases/PhaseOutcome.d.ts +2 -0
  91. package/dist/phases/PhaseOutcome.d.ts.map +1 -1
  92. package/dist/phases/PlanPhase.d.ts.map +1 -1
  93. package/dist/prompts/templates.d.ts +2 -2
  94. package/dist/prompts/templates.d.ts.map +1 -1
  95. package/dist/{restart-BMILTP5X.js → restart-C7QBXT44.js} +9 -8
  96. package/dist/{restart-BMILTP5X.js.map → restart-C7QBXT44.js.map} +1 -1
  97. package/dist/run.js +16 -14
  98. package/dist/run.js.map +1 -1
  99. package/dist/start-66JO56AW.js +16 -0
  100. package/dist/start-66JO56AW.js.map +1 -0
  101. package/dist/tracker/IssueTracker.d.ts +6 -0
  102. package/dist/tracker/IssueTracker.d.ts.map +1 -1
  103. package/dist/web/routes/api.d.ts.map +1 -1
  104. package/package.json +5 -1
  105. package/src/web/frontend/dist/assets/index-DJzC2saL.css +1 -0
  106. package/src/web/frontend/dist/assets/{index-D_oTMuJU.js → index-Mnu8M3ww.js} +57 -57
  107. package/src/web/frontend/dist/index.html +2 -2
  108. package/dist/PtyRunner-6UGI5STW.js +0 -22
  109. package/dist/chunk-2YQHKXLL.js.map +0 -1
  110. package/dist/chunk-AVGZH64A.js.map +0 -1
  111. package/dist/chunk-IP3QTP5A.js.map +0 -1
  112. package/dist/chunk-NZHKAPU6.js.map +0 -1
  113. package/dist/chunk-O3WEV5W3.js.map +0 -1
  114. package/dist/chunk-QZZGIZWC.js.map +0 -1
  115. package/dist/chunk-SAMTXC4A.js.map +0 -1
  116. package/dist/chunk-U237JSLB.js +0 -1
  117. package/dist/chunk-U6GWFTKA.js +0 -657
  118. package/dist/chunk-U6GWFTKA.js.map +0 -1
  119. package/dist/chunk-YCYVNRLF.js.map +0 -1
  120. package/dist/start-6QRW6IJI.js +0 -15
  121. package/src/web/frontend/dist/assets/index-COYziOhv.css +0 -1
  122. /package/dist/{AIRunnerRegistry-II3WWSFN.js.map → AIRunnerRegistry-CFDNWSXC.js.map} +0 -0
  123. /package/dist/{LockNote-Z2CLDZNN.js.map → LockNote-W2JNVMW7.js.map} +0 -0
  124. /package/dist/{PtyRunner-6UGI5STW.js.map → PtyRunner-NYASBTRP.js.map} +0 -0
  125. /package/dist/{ai-runner-HLA44WI6.js.map → SdkRunner-U2OTOMZU.js.map} +0 -0
  126. /package/dist/{chunk-U237JSLB.js.map → ai-runner-TOHVJJ76.js.map} +0 -0
  127. /package/dist/{chunk-UBQLXQ7I.js.map → chunk-5JBADEKR.js.map} +0 -0
  128. /package/dist/{chunk-HDFNMVRQ.js.map → chunk-DVNAH2GV.js.map} +0 -0
  129. /package/dist/{chunk-GXFG4JU6.js.map → chunk-EU4XFZ2T.js.map} +0 -0
  130. /package/dist/{config-WTRSZLOC.js.map → chunk-MSL7ROVK.js.map} +0 -0
  131. /package/dist/{chunk-2MESXJEZ.js.map → chunk-YNRKPQLS.js.map} +0 -0
  132. /package/dist/{errors-S3BWYA4I.js.map → config-23TBYFP5.js.map} +0 -0
  133. /package/dist/{doctor-37JNBGDN.js.map → doctor-ZG3DO7J5.js.map} +0 -0
  134. /package/dist/{start-6QRW6IJI.js.map → errors-J3ZRP66W.js.map} +0 -0
@@ -17,7 +17,7 @@ import {
17
17
  planPrompt,
18
18
  rePlanPrompt,
19
19
  verifyPrompt
20
- } from "./chunk-2YQHKXLL.js";
20
+ } from "./chunk-GPZX4DSY.js";
21
21
  import {
22
22
  getProjectKnowledge
23
23
  } from "./chunk-ACVOOHAR.js";
@@ -26,7 +26,7 @@ import {
26
26
  } from "./chunk-B7TVVODN.js";
27
27
  import {
28
28
  t
29
- } from "./chunk-YCYVNRLF.js";
29
+ } from "./chunk-OBGEEGQ3.js";
30
30
  import {
31
31
  getLocalIP
32
32
  } from "./chunk-AKXDQH25.js";
@@ -36,8 +36,11 @@ import {
36
36
  import {
37
37
  createAIRunner,
38
38
  getRunnerCapabilities,
39
+ usesDeterministicPlanCopy
40
+ } from "./chunk-TFEPHOVE.js";
41
+ import {
39
42
  isShuttingDown
40
- } from "./chunk-SAMTXC4A.js";
43
+ } from "./chunk-G7QI5WDI.js";
41
44
  import {
42
45
  AIExecutionError,
43
46
  GongfengApiError,
@@ -51,7 +54,7 @@ import {
51
54
  PortExhaustionError,
52
55
  ServiceShutdownError,
53
56
  UnregisteredPhasesError
54
- } from "./chunk-AVGZH64A.js";
57
+ } from "./chunk-2RWGZPNF.js";
55
58
  import {
56
59
  logger,
57
60
  runWithIssueContext
@@ -1082,6 +1085,28 @@ var IssueTracker = class _IssueTracker extends BaseTracker {
1082
1085
  logger5.warn("Issue marked as failed", { issueIid, error, failedAtState, attempts: record.attempts, isRetryable });
1083
1086
  eventBus.emitTyped("issue:failed", { issueIid, error, failedAtState, record });
1084
1087
  }
1088
+ /**
1089
+ * Mark as failed WITHOUT incrementing attempts. Used when the agent was still
1090
+ * actively producing output at timeout — a slow-but-progressing run should not
1091
+ * consume the retry budget.
1092
+ */
1093
+ markFailedSoft(issueIid, error, failedAtState) {
1094
+ const record = this.collection[this.key(issueIid)];
1095
+ if (!record) return;
1096
+ record.state = "failed" /* Failed */;
1097
+ record.lastError = error;
1098
+ record.failedAtState = failedAtState;
1099
+ record.lastErrorRetryable = true;
1100
+ record.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1101
+ this.save();
1102
+ logger5.warn("Issue marked as failed (soft \u2014 no attempt increment)", {
1103
+ issueIid,
1104
+ error,
1105
+ failedAtState,
1106
+ attempts: record.attempts
1107
+ });
1108
+ eventBus.emitTyped("issue:failed", { issueIid, error, failedAtState, record });
1109
+ }
1085
1110
  pauseIssue(issueIid, currentPhase) {
1086
1111
  const record = this.collection[this.key(issueIid)];
1087
1112
  if (!record) return;
@@ -1593,6 +1618,31 @@ var PlanPersistence = class _PlanPersistence {
1593
1618
  this.ensureDir();
1594
1619
  fs2.writeFileSync(path2.join(this.planDir, filename), content, "utf-8");
1595
1620
  }
1621
+ /**
1622
+ * Copy a plan file from an external source (e.g. ~/.claude/plans/) into planDir.
1623
+ * Returns the destination path, or null if the source is empty/unreadable.
1624
+ */
1625
+ copyPlanFromExternal(sourcePath, targetFilename = "01-plan.md") {
1626
+ try {
1627
+ const content = fs2.readFileSync(sourcePath, "utf-8");
1628
+ if (content.trim().length === 0) {
1629
+ logger6.warn("External plan file is empty", { sourcePath });
1630
+ return null;
1631
+ }
1632
+ this.ensureDir();
1633
+ const destPath = path2.join(this.planDir, targetFilename);
1634
+ fs2.writeFileSync(destPath, content, "utf-8");
1635
+ logger6.info("Plan copied from external source", {
1636
+ source: sourcePath,
1637
+ dest: destPath,
1638
+ size: content.length
1639
+ });
1640
+ return destPath;
1641
+ } catch (err) {
1642
+ logger6.error("Failed to copy plan from external source", { sourcePath, err });
1643
+ return null;
1644
+ }
1645
+ }
1596
1646
  };
1597
1647
 
1598
1648
  // src/phases/BasePhase.ts
@@ -1776,7 +1826,8 @@ ${t("basePhase.rulesSection", { rules })}`;
1776
1826
  error: {
1777
1827
  message: (result.errorMessage || result.output).slice(0, 500),
1778
1828
  isRetryable: this.classifyRetryable(result),
1779
- rawOutput: result.output
1829
+ rawOutput: result.output,
1830
+ wasActiveAtTimeout: result.wasActiveAtTimeout
1780
1831
  }
1781
1832
  };
1782
1833
  }
@@ -1843,6 +1894,9 @@ ${t("basePhase.rulesSection", { rules })}`;
1843
1894
  workDir: this.resolveAIWorkDir(ctx),
1844
1895
  timeoutMs: this.config.ai.phaseTimeoutMs,
1845
1896
  idleTimeoutMs: this.config.ai.idleTimeoutMs,
1897
+ timeoutGraceMs: this.config.ai.timeoutGraceMs,
1898
+ timeoutExtensionMs: this.config.ai.timeoutExtensionMs,
1899
+ timeoutMaxExtensions: this.config.ai.timeoutMaxExtensions,
1846
1900
  mode: this.getRunMode(),
1847
1901
  phaseName: this.phaseName,
1848
1902
  artifactCheck,
@@ -2122,6 +2176,7 @@ var PlanPhase = class extends BasePhase {
2122
2176
  buildPrompt(ctx) {
2123
2177
  const pc = demandToPromptContext(ctx.demand);
2124
2178
  const history = this.plan.readReviewHistory();
2179
+ const detCopy = usesDeterministicPlanCopy(this.config.ai.mode);
2125
2180
  const promptCtx = {
2126
2181
  issueTitle: pc.title,
2127
2182
  issueDescription: pc.description,
@@ -2131,13 +2186,14 @@ var PlanPhase = class extends BasePhase {
2131
2186
  };
2132
2187
  let basePrompt;
2133
2188
  if (history.length > 0) {
2134
- basePrompt = rePlanPrompt(promptCtx, history);
2189
+ basePrompt = rePlanPrompt(promptCtx, history, detCopy);
2135
2190
  } else {
2136
- basePrompt = planPrompt(promptCtx);
2191
+ basePrompt = planPrompt(promptCtx, detCopy);
2137
2192
  }
2138
2193
  const caps = getRunnerCapabilities(this.config.ai.mode);
2139
2194
  if (!caps?.nativePlanMode) {
2140
- basePrompt = `${t("prompt.planModeFallback")}
2195
+ const preambleKey = detCopy ? "prompt.planModeNative" : "prompt.planModeFallback";
2196
+ basePrompt = `${t(preambleKey)}
2141
2197
 
2142
2198
  ${basePrompt}`;
2143
2199
  }
@@ -3804,6 +3860,18 @@ function buildNoteSyncComment(phaseName, phaseLabel, docUrl, dashboardUrl, summa
3804
3860
  ].join("\n");
3805
3861
  }
3806
3862
 
3863
+ // src/orchestrator/PendingDialogStore.ts
3864
+ var store = /* @__PURE__ */ new Map();
3865
+ function setPendingDialog(info) {
3866
+ store.set(info.issueIid, info);
3867
+ }
3868
+ function getPendingDialog(issueIid) {
3869
+ return store.get(issueIid);
3870
+ }
3871
+ function clearPendingDialog(issueIid) {
3872
+ store.delete(issueIid);
3873
+ }
3874
+
3807
3875
  // src/orchestrator/steps/PhaseLoopStep.ts
3808
3876
  var logger15 = logger.child("PhaseLoopStep");
3809
3877
  function resolveVerifyRunner(deps) {
@@ -3878,41 +3946,95 @@ async function syncResultToIssue(phase, ctx, displayId, phaseName, deps, issueId
3878
3946
  await safeComment(deps, issueId, issueProgressComment(phaseName, "completed"));
3879
3947
  }
3880
3948
  }
3881
- function buildAcpHandler(displayId, phaseName, deps) {
3882
- if (deps.config.ai.codebuddyAcpAutoApprove !== false) return void 0;
3949
+ function buildInputHandler(displayId, phaseName, deps) {
3950
+ const useAcpGate = deps.config.ai.codebuddyAcpAutoApprove === false;
3883
3951
  return (request) => {
3884
- if (request.type !== "plan-approval") {
3885
- return Promise.resolve("allow");
3952
+ if (request.type === "interactive-dialog") {
3953
+ return handleInteractiveDialog(displayId, phaseName, deps, request);
3886
3954
  }
3887
- logger15.info("ACP plan-approval requested, delegating to review gate", {
3888
- issueIid: displayId,
3889
- phase: phaseName
3890
- });
3891
- deps.eventBus.emitTyped("review:requested", { issueIid: displayId });
3892
- return new Promise((resolve) => {
3893
- const onApproved = (payload) => {
3894
- const data = payload.data;
3895
- if (data.issueIid !== displayId) return;
3896
- cleanup();
3897
- logger15.info("ACP plan-approval approved via review gate", { issueIid: displayId });
3898
- resolve("allow");
3899
- };
3900
- const onRejected = (payload) => {
3901
- const data = payload.data;
3902
- if (data.issueIid !== displayId) return;
3903
- cleanup();
3904
- logger15.info("ACP plan-approval rejected via review gate", { issueIid: displayId });
3905
- resolve("reject");
3906
- };
3907
- const cleanup = () => {
3908
- deps.eventBus.removeListener("review:approved", onApproved);
3909
- deps.eventBus.removeListener("review:rejected", onRejected);
3910
- };
3911
- deps.eventBus.on("review:approved", onApproved);
3912
- deps.eventBus.on("review:rejected", onRejected);
3913
- });
3955
+ if (request.type === "plan-approval" && useAcpGate) {
3956
+ return handlePlanApproval(displayId, phaseName, deps);
3957
+ }
3958
+ return Promise.resolve("allow");
3914
3959
  };
3915
3960
  }
3961
+ function handlePlanApproval(displayId, phaseName, deps) {
3962
+ logger15.info("ACP plan-approval requested, delegating to review gate", {
3963
+ issueIid: displayId,
3964
+ phase: phaseName
3965
+ });
3966
+ deps.eventBus.emitTyped("review:requested", { issueIid: displayId });
3967
+ return new Promise((resolve) => {
3968
+ const onApproved = (payload) => {
3969
+ const data = payload.data;
3970
+ if (data.issueIid !== displayId) return;
3971
+ cleanup();
3972
+ logger15.info("ACP plan-approval approved via review gate", { issueIid: displayId });
3973
+ resolve("allow");
3974
+ };
3975
+ const onRejected = (payload) => {
3976
+ const data = payload.data;
3977
+ if (data.issueIid !== displayId) return;
3978
+ cleanup();
3979
+ logger15.info("ACP plan-approval rejected via review gate", { issueIid: displayId });
3980
+ resolve("reject");
3981
+ };
3982
+ const cleanup = () => {
3983
+ deps.eventBus.removeListener("review:approved", onApproved);
3984
+ deps.eventBus.removeListener("review:rejected", onRejected);
3985
+ };
3986
+ deps.eventBus.on("review:approved", onApproved);
3987
+ deps.eventBus.on("review:rejected", onRejected);
3988
+ });
3989
+ }
3990
+ function handleInteractiveDialog(displayId, phaseName, deps, request) {
3991
+ logger15.info("Interactive dialog forwarded to frontend", {
3992
+ issueIid: displayId,
3993
+ phase: phaseName,
3994
+ question: request.content.slice(0, 80),
3995
+ optionCount: request.options?.length
3996
+ });
3997
+ const options = request.options ?? [];
3998
+ setPendingDialog({
3999
+ issueIid: displayId,
4000
+ question: request.content,
4001
+ options,
4002
+ phase: phaseName,
4003
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4004
+ });
4005
+ deps.eventBus.emitTyped("agent:inputRequired", {
4006
+ issueIid: displayId,
4007
+ phase: phaseName,
4008
+ question: request.content,
4009
+ options
4010
+ });
4011
+ return new Promise((resolve) => {
4012
+ const cleanup = () => {
4013
+ deps.eventBus.removeListener("agent:inputResponse", onResponse);
4014
+ deps.eventBus.removeListener("agent:dialogDismissed", onDismiss);
4015
+ };
4016
+ const onResponse = (payload) => {
4017
+ const data = payload.data;
4018
+ if (data.issueIid !== displayId) return;
4019
+ cleanup();
4020
+ clearPendingDialog(displayId);
4021
+ logger15.info("Interactive dialog response received from frontend", {
4022
+ issueIid: displayId,
4023
+ response: data.response
4024
+ });
4025
+ resolve(data.response ?? "1");
4026
+ };
4027
+ const onDismiss = (payload) => {
4028
+ const data = payload.data;
4029
+ if (data.issueIid !== displayId) return;
4030
+ cleanup();
4031
+ logger15.info("Interactive dialog dismissed by user (false positive)", { issueIid: displayId });
4032
+ resolve("");
4033
+ };
4034
+ deps.eventBus.on("agent:inputResponse", onResponse);
4035
+ deps.eventBus.on("agent:dialogDismissed", onDismiss);
4036
+ });
4037
+ }
3916
4038
  async function safeComment(deps, issueId, message) {
3917
4039
  try {
3918
4040
  await deps.gongfeng.createIssueNote(issueId, message);
@@ -3941,7 +4063,7 @@ async function runPhaseWithLifecycle(phase, phaseCtx, spec, ctx, deps, wtGit, wt
3941
4063
  phase: spec.name,
3942
4064
  event
3943
4065
  }),
3944
- onInputRequired: buildAcpHandler(displayId, spec.name, deps)
4066
+ onInputRequired: buildInputHandler(displayId, spec.name, deps)
3945
4067
  };
3946
4068
  const outcome = await phase.run(phaseCtx, callbacks);
3947
4069
  if (outcome.sessionId) wtPlan.updatePhaseSessionId(spec.name, outcome.sessionId);
@@ -3961,14 +4083,20 @@ async function runPhaseWithLifecycle(phase, phaseCtx, spec, ctx, deps, wtGit, wt
3961
4083
  }
3962
4084
  const errMsg = outcome.error?.message ?? "Unknown error";
3963
4085
  const shortErr = errMsg.slice(0, 200);
4086
+ const wasActive = outcome.error?.wasActiveAtTimeout ?? false;
3964
4087
  wtPlan.updatePhaseProgress(spec.name, "failed", errMsg);
3965
4088
  deps.tracker.updatePhaseProgress(displayId, spec.name, { status: "failed" });
3966
- deps.tracker.markFailed(displayId, errMsg, "phase_running" /* PhaseRunning */);
4089
+ if (wasActive) {
4090
+ deps.tracker.markFailedSoft(displayId, errMsg, "phase_running" /* PhaseRunning */);
4091
+ } else {
4092
+ deps.tracker.markFailed(displayId, errMsg, "phase_running" /* PhaseRunning */);
4093
+ }
3967
4094
  await safeComment(deps, issue.id, issueProgressComment(spec.name, "failed", shortErr));
3968
4095
  throw new AIExecutionError(spec.name, `Phase ${spec.name} failed: ${shortErr}`, {
3969
4096
  output: outcome.error?.rawOutput ?? outcome.output,
3970
4097
  exitCode: outcome.exitCode ?? 1,
3971
- isRetryable: outcome.error?.isRetryable
4098
+ isRetryable: outcome.error?.isRetryable,
4099
+ wasActiveAtTimeout: wasActive
3972
4100
  });
3973
4101
  }
3974
4102
  async function executePhaseLoop(ctx, deps, wtGit, wtPlan, wtGitMap) {
@@ -4185,14 +4313,20 @@ async function awaitAsyncPhase(outcome, spec, ctx, deps, wtGit, wtPlan, wtGitMap
4185
4313
  }
4186
4314
  const errMsg = finalOutcome.error?.message ?? "Unknown error";
4187
4315
  const shortErr = errMsg.slice(0, 200);
4316
+ const wasActive = finalOutcome.error?.wasActiveAtTimeout ?? false;
4188
4317
  wtPlan.updatePhaseProgress(spec.name, "failed", errMsg);
4189
4318
  deps.tracker.updatePhaseProgress(displayId, spec.name, { status: "failed" });
4190
- deps.tracker.markFailed(displayId, errMsg, "phase_running" /* PhaseRunning */);
4319
+ if (wasActive) {
4320
+ deps.tracker.markFailedSoft(displayId, errMsg, "phase_running" /* PhaseRunning */);
4321
+ } else {
4322
+ deps.tracker.markFailed(displayId, errMsg, "phase_running" /* PhaseRunning */);
4323
+ }
4191
4324
  await safeComment(deps, issue.id, issueProgressComment(spec.name, "failed", shortErr));
4192
4325
  throw new AIExecutionError(spec.name, `Phase ${spec.name} failed: ${shortErr}`, {
4193
4326
  output: finalOutcome.error?.rawOutput ?? finalOutcome.output,
4194
4327
  exitCode: finalOutcome.exitCode ?? 1,
4195
- isRetryable: finalOutcome.error?.isRetryable
4328
+ isRetryable: finalOutcome.error?.isRetryable,
4329
+ wasActiveAtTimeout: wasActive
4196
4330
  });
4197
4331
  }
4198
4332
  function findPreviousAiPhaseIndex(phases, currentIdx) {
@@ -4417,13 +4551,18 @@ var logger17 = logger.child("FailureHandler");
4417
4551
  async function handleFailure(err, issue, wtCtx, deps) {
4418
4552
  const errorMsg = err.message;
4419
4553
  const isRetryable = err instanceof AIExecutionError ? err.isRetryable : true;
4420
- logger17.error("Issue processing failed", { iid: issue.iid, error: errorMsg, isRetryable });
4554
+ const wasActiveAtTimeout = err instanceof AIExecutionError && err.wasActiveAtTimeout;
4555
+ logger17.error("Issue processing failed", { iid: issue.iid, error: errorMsg, isRetryable, wasActiveAtTimeout });
4421
4556
  metrics.incCounter("iaf_issues_failed_total");
4422
4557
  const currentRecord = deps.tracker.get(issue.iid);
4423
4558
  const failedAtState = currentRecord?.state || "pending" /* Pending */;
4424
4559
  const wasReset = failedAtState === "pending" /* Pending */ && currentRecord?.attempts === 0;
4425
4560
  if (failedAtState !== "failed" /* Failed */ && !wasReset) {
4426
- deps.tracker.markFailed(issue.iid, errorMsg.slice(0, 500), failedAtState, isRetryable);
4561
+ if (wasActiveAtTimeout) {
4562
+ deps.tracker.markFailedSoft(issue.iid, errorMsg.slice(0, 500), failedAtState);
4563
+ } else {
4564
+ deps.tracker.markFailed(issue.iid, errorMsg.slice(0, 500), failedAtState, isRetryable);
4565
+ }
4427
4566
  }
4428
4567
  if (wasReset) {
4429
4568
  logger17.info("Issue was reset during processing, skipping failure marking", { iid: issue.iid });
@@ -5363,7 +5502,7 @@ E2E \u6D4B\u8BD5\u5C06\u5C1D\u8BD5\u4F7F\u7528 config.json \u4E2D\u7684\u9ED8\u8
5363
5502
  const verifyOutcome = await verifyPhase.run(verifyCtx);
5364
5503
  if (verifyOutcome.status === "failed") {
5365
5504
  const errMsg = verifyOutcome.error?.message ?? "Verification failed after conflict resolution";
5366
- throw new (await import("./errors-S3BWYA4I.js")).AIExecutionError("verify", errMsg, {
5505
+ throw new (await import("./errors-J3ZRP66W.js")).AIExecutionError("verify", errMsg, {
5367
5506
  output: verifyOutcome.error?.rawOutput ?? verifyOutcome.output,
5368
5507
  exitCode: verifyOutcome.exitCode ?? 1
5369
5508
  });
@@ -5674,7 +5813,9 @@ export {
5674
5813
  getNoteSyncEnabled,
5675
5814
  setNoteSyncOverride,
5676
5815
  isNoteSyncEnabledForIssue,
5816
+ getPendingDialog,
5817
+ clearPendingDialog,
5677
5818
  PipelineOrchestrator,
5678
5819
  BrainstormService
5679
5820
  };
5680
- //# sourceMappingURL=chunk-IP3QTP5A.js.map
5821
+ //# sourceMappingURL=chunk-IWSMQXBL.js.map