@visorcraft/idlehands 4.0.13 → 4.0.15

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 (167) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{agent-via-gateway-B7gDrTh2.js → agent-via-gateway-BFtbpQpT.js} +7 -7
  3. package/dist/{agent-via-gateway-C1akskt-.js → agent-via-gateway-BvXS1sXv.js} +1 -1
  4. package/dist/{agent-via-gateway-C9xTFnnb.js → agent-via-gateway-CIM26Dxl.js} +2 -2
  5. package/dist/{agent-via-gateway-Cq6YTkRw.js → agent-via-gateway-CcaPUQrc.js} +1 -1
  6. package/dist/{agents-BEWuTIwE.js → agents-DPlb4UQu.js} +4 -4
  7. package/dist/{agents.config-s_1D920P.js → agents.config-8pxRoZvL.js} +1 -1
  8. package/dist/{agents.config-cH3kcrKU.js → agents.config-BKoyeUnK.js} +1 -1
  9. package/dist/{anton-gFIz387q.js → anton-BTjKlGm7.js} +155 -12
  10. package/dist/{anton-DZGESeSl.js → anton-DKA8iAQE.js} +155 -12
  11. package/dist/{anton-bQ51g5Ec.js → anton-DhBvDNcB.js} +155 -12
  12. package/dist/{anton-Cs3aBMKq.js → anton-Dyhtv3C8.js} +155 -12
  13. package/dist/{audio-preflight-BSlR2jEq.js → audio-preflight-CW8IH1lU.js} +4 -4
  14. package/dist/{auth-choice-Dunr1I8A.js → auth-choice-CMUzxwaw.js} +1 -1
  15. package/dist/{auth-choice-CoDCd8IM.js → auth-choice-D-_AVWgJ.js} +1 -1
  16. package/dist/{banner-XXOWQkH8.js → banner-B6ih1A5q.js} +1 -1
  17. package/dist/build-info.json +3 -3
  18. package/dist/bundled/boot-md/handler.js +7 -7
  19. package/dist/bundled/session-memory/handler.js +7 -7
  20. package/dist/{channel-options-JZ8UUgne.js → channel-options-DdT_iiu2.js} +1 -1
  21. package/dist/{channel-options-DcbnvkV8.js → channel-options-DqOp64vm.js} +1 -1
  22. package/dist/{channel-web-Z-H-wjMO.js → channel-web-DjS8VQYO.js} +2 -2
  23. package/dist/{channel-web-Dz8l9j3Z.js → channel-web-PG7u76pG.js} +2 -2
  24. package/dist/{channels-cli-F1TB2Ms2.js → channels-cli-1tt6zmdw.js} +7 -7
  25. package/dist/{channels-cli-DVTF8msL.js → channels-cli-CWxVX3_x.js} +7 -7
  26. package/dist/{chrome-_2tzVjVl.js → chrome-BcJB6PcM.js} +9 -9
  27. package/dist/{cli-CLfBho_N.js → cli-CmOlEYcx.js} +2 -2
  28. package/dist/{cli-Cysh5mku.js → cli-D4FV736E.js} +2 -2
  29. package/dist/{command-registry-BzM89IOr.js → command-registry-CQ_cgvak.js} +10 -10
  30. package/dist/{completion-cli-CWl8tMGs.js → completion-cli-UytEAOmM.js} +2 -2
  31. package/dist/{completion-cli-C5Y0omSs.js → completion-cli-y9BFk5F6.js} +1 -1
  32. package/dist/{config-cli-DrupHrLQ.js → config-cli-5c6A3y5U.js} +1 -1
  33. package/dist/{config-cli-DY7H5mxq.js → config-cli-DUb0ZGdL.js} +1 -1
  34. package/dist/{configure-CEhvh4Tl.js → configure-AlSS40po.js} +3 -3
  35. package/dist/{configure-teHRuPU7.js → configure-BPwYKVb4.js} +3 -3
  36. package/dist/{deliver-CVTXl0Cv.js → deliver-BUiQ-9fE.js} +1 -1
  37. package/dist/{deps-DOKkEv5X.js → deps-BYfE_aIY.js} +1 -1
  38. package/dist/{deps-BuqRbUb-.js → deps-DxMLbT7t.js} +1 -1
  39. package/dist/{deps--Jd_1mvW.js → deps-KIFYHxig.js} +1 -1
  40. package/dist/{deps-CEc0DzO7.js → deps-TwKaIh1I.js} +1 -1
  41. package/dist/{doctor-completion-C47EWkPr.js → doctor-completion-HzTBPNbS.js} +1 -1
  42. package/dist/{doctor-completion-jhxR4t3O.js → doctor-completion-S-XHygGb.js} +1 -1
  43. package/dist/{emergency-stop-CC3HM3fX.js → emergency-stop--ScwariE.js} +7 -7
  44. package/dist/{emergency-stop-DeVGttt7.js → emergency-stop-BDwI4Cyl.js} +2 -2
  45. package/dist/{emergency-stop-BDOqqnou.js → emergency-stop-DOi-rKmj.js} +2 -2
  46. package/dist/{emergency-stop-C1Aq7hF2.js → emergency-stop-DpMAMIiz.js} +2 -2
  47. package/dist/entry.js +1 -1
  48. package/dist/extensionAPI.js +2 -2
  49. package/dist/{gateway-cli-Bg9EHlHZ.js → gateway-cli-B4T44JsM.js} +9 -9
  50. package/dist/{gateway-cli-CwuxFfnq.js → gateway-cli-DQcjWJr7.js} +9 -9
  51. package/dist/{health-B5FcoZjN.js → health--39yieH5.js} +1 -1
  52. package/dist/{health-D-LRUDN7.js → health-D7UCYzfy.js} +1 -1
  53. package/dist/{hooks-cli-hH93rV1P.js → hooks-cli-CGB7TcZZ.js} +3 -3
  54. package/dist/{hooks-cli-DrwJGeyQ.js → hooks-cli-Cko_uweG.js} +3 -3
  55. package/dist/{image-COw__ACq.js → image-D8b_rlQC.js} +1 -1
  56. package/dist/index.js +7 -7
  57. package/dist/llm-slug-generator.js +7 -7
  58. package/dist/{models-C7BxqYrW.js → models-CWfcMshO.js} +2 -2
  59. package/dist/{models-cli-CDDj0F5v.js → models-cli-NlT2N74B.js} +4 -4
  60. package/dist/{models-cli-CqjmKMK2.js → models-cli-d_ead6LU.js} +3 -3
  61. package/dist/{npm-resolution-BjPIvwHA.js → npm-resolution-DIJeEhoa.js} +1 -1
  62. package/dist/{npm-resolution-C_gT5wrI.js → npm-resolution-Dpn9DNPz.js} +1 -1
  63. package/dist/{onboard-DyZAtFGg.js → onboard-DFseyAG9.js} +2 -2
  64. package/dist/{onboard-CAifMogc.js → onboard-Raw5nkGc.js} +2 -2
  65. package/dist/{onboard-channels-Bk3dz_Jr.js → onboard-channels-CG1HcORq.js} +1 -1
  66. package/dist/{onboard-channels-DAk60Ns1.js → onboard-channels-mLWuxUlN.js} +1 -1
  67. package/dist/{onboarding-DxXFvGbr.js → onboarding-CzzjhwRf.js} +3 -3
  68. package/dist/{onboarding-kCJZ-hVf.js → onboarding-DYlNLV9R.js} +3 -3
  69. package/dist/{onboarding.finalize-Dl63X819.js → onboarding.finalize-BJYuOTPe.js} +6 -6
  70. package/dist/{onboarding.finalize-CLyBIGRt.js → onboarding.finalize-CIOBj6Jy.js} +7 -7
  71. package/dist/{pi-embedded-B4tp4aBd.js → pi-embedded-7XGjNojd.js} +26 -26
  72. package/dist/{pi-embedded-CNvCKXkm.js → pi-embedded-Swc7dke2.js} +11 -11
  73. package/dist/{pi-embedded-helpers-CyTpDKo5.js → pi-embedded-helpers-CghCLoPo.js} +4 -4
  74. package/dist/{plugin-registry-CVL1r-yd.js → plugin-registry-BAd0SoEv.js} +1 -1
  75. package/dist/{plugin-registry-n---u7EU.js → plugin-registry-D9Z1bMNt.js} +1 -1
  76. package/dist/plugin-sdk/{agent-via-gateway-nyxykUkn.js → agent-via-gateway-B3F-royZ.js} +2 -2
  77. package/dist/plugin-sdk/{anton-BdO0Oxvp.js → anton-DfpQdXJJ.js} +155 -12
  78. package/dist/plugin-sdk/{channel-web-CtnWXT6I.js → channel-web-BWE_kecR.js} +2 -2
  79. package/dist/plugin-sdk/{deps-Be1yXgl3.js → deps-B0MfJgDH.js} +1 -1
  80. package/dist/plugin-sdk/{emergency-stop-qkFklwE3.js → emergency-stop-rTRWpk26.js} +2 -2
  81. package/dist/plugin-sdk/index.js +3 -3
  82. package/dist/plugin-sdk/{reply-Csf1i8F8.js → reply-C2G4DKTN.js} +11 -11
  83. package/dist/plugin-sdk/{web-Cs2SXpS-.js → web-bxu2RRVS.js} +3 -3
  84. package/dist/{plugins-cli--xMWIg-4.js → plugins-cli-BYfDyWXn.js} +3 -3
  85. package/dist/{plugins-cli-D3VgmVpQ.js → plugins-cli-DP46ipIu.js} +3 -3
  86. package/dist/{program-C4UqPGzI.js → program-BlV0XOMu.js} +8 -8
  87. package/dist/{program-context-Dp52v2OQ.js → program-context-PC7Knx3s.js} +18 -18
  88. package/dist/{prompt-select-styled-CsGzk9Gq.js → prompt-select-styled-BEnn1bwr.js} +4 -4
  89. package/dist/{prompt-select-styled-DlX1LGGJ.js → prompt-select-styled-BgfuPDVv.js} +4 -4
  90. package/dist/{provider-auth-helpers-Czzq_QPi.js → provider-auth-helpers-CKIkgNDk.js} +1 -1
  91. package/dist/{provider-auth-helpers-DOkJeW-i.js → provider-auth-helpers-CrjXAqYu.js} +1 -1
  92. package/dist/{push-apns-BtFayED4.js → push-apns-B4sxQAG3.js} +1 -1
  93. package/dist/{push-apns-RknfH2wN.js → push-apns-BPmS_f8e.js} +1 -1
  94. package/dist/{pw-ai-CowTfhOG.js → pw-ai-CfYaR1K2.js} +1 -1
  95. package/dist/{register.agent-C35pTLnm.js → register.agent-DRcOj2U3.js} +9 -9
  96. package/dist/{register.agent-BiHrmIpA.js → register.agent-uaM-OgFM.js} +8 -8
  97. package/dist/{register.configure-DCf6SaYp.js → register.configure-B0i1vobR.js} +8 -8
  98. package/dist/{register.configure-BPdGcoT-.js → register.configure-BebpNVXc.js} +8 -8
  99. package/dist/{register.maintenance-DUdYmaQm.js → register.maintenance-CjWtRkPb.js} +9 -9
  100. package/dist/{register.maintenance-DujCPOfC.js → register.maintenance-Cr0SJRGa.js} +8 -8
  101. package/dist/{register.message-BhzLKaq7.js → register.message-BNqRwnPx.js} +3 -3
  102. package/dist/{register.message-BHLa16p6.js → register.message-DMAqqNBh.js} +3 -3
  103. package/dist/{register.onboard-hOo1cBls.js → register.onboard-9Z1ghVgM.js} +2 -2
  104. package/dist/{register.onboard-DqRuNACj.js → register.onboard-DDLj9mJ2.js} +2 -2
  105. package/dist/{register.orchestrator-anton-gJUfWbMJ.js → register.orchestrator-anton-9Al8Av8i.js} +2 -2
  106. package/dist/{register.orchestrator-anton-DDUP6r-1.js → register.orchestrator-anton-BybNaYi1.js} +2 -2
  107. package/dist/{register.setup-1kqsk9Nz.js → register.setup-Z1tBfa9d.js} +2 -2
  108. package/dist/{register.setup-Cg9pGGKa.js → register.setup-yqN0SXow.js} +2 -2
  109. package/dist/{register.status-health-sessions-DGVjxQ4x.js → register.status-health-sessions-Di92AnoH.js} +4 -4
  110. package/dist/{register.status-health-sessions-DWCD-xxm.js → register.status-health-sessions-r-mpQR1m.js} +4 -4
  111. package/dist/{register.subclis-C39R-X4d.js → register.subclis-DPQqxIZd.js} +9 -9
  112. package/dist/{reply-DuYN0-Pb.js → reply-ZWOav11z.js} +11 -11
  113. package/dist/{run-main-DhnKFvJ8.js → run-main-DDbBATo6.js} +15 -15
  114. package/dist/{runner-BzNdfqDz.js → runner-PgRFPYUj.js} +1 -1
  115. package/dist/{server-node-events-S-Ffj9aJ.js → server-node-events-BcZPS5tj.js} +3 -3
  116. package/dist/{server-node-events-CsvrVnbd.js → server-node-events-DNJLKEMT.js} +3 -3
  117. package/dist/{status-DtnoXYQp.js → status-BXSiFfmy.js} +2 -2
  118. package/dist/{status-OrfDNo6n.js → status-geIYZraQ.js} +2 -2
  119. package/dist/{subagent-registry-CV8jrQca.js → subagent-registry-C6uygQa1.js} +11 -11
  120. package/dist/{update-cli-DZfUy8hM.js → update-cli-BxVcRBy_.js} +9 -9
  121. package/dist/{update-cli-UpWfq3c5.js → update-cli-VlK55yII.js} +8 -8
  122. package/dist/{update-runner-DTzgmQYD.js → update-runner-Cw7BbjGv.js} +1 -1
  123. package/dist/{update-runner-GJO5-g7n.js → update-runner-bFqEARFN.js} +1 -1
  124. package/dist/{web-DpyY5rK8.js → web-BjMMu9l1.js} +3 -3
  125. package/dist/{web-CwYkIq_A.js → web-Bjj9WtlF.js} +3 -3
  126. package/dist/{web-y9QkD_tf.js → web-DptF9st7.js} +3 -3
  127. package/dist/{web-BC36pno5.js → web-TRTzT6rm.js} +8 -8
  128. package/extensions/acpx/package.json +1 -1
  129. package/extensions/bluebubbles/package.json +1 -1
  130. package/extensions/copilot-proxy/package.json +1 -1
  131. package/extensions/diagnostics-otel/package.json +1 -1
  132. package/extensions/discord/package.json +1 -1
  133. package/extensions/feishu/package.json +1 -1
  134. package/extensions/google-gemini-cli-auth/package.json +1 -1
  135. package/extensions/googlechat/package.json +1 -1
  136. package/extensions/hand/package.json +1 -1
  137. package/extensions/imessage/package.json +1 -1
  138. package/extensions/irc/package.json +1 -1
  139. package/extensions/line/package.json +1 -1
  140. package/extensions/llm-task/package.json +1 -1
  141. package/extensions/matrix/CHANGELOG.md +12 -0
  142. package/extensions/matrix/package.json +1 -1
  143. package/extensions/mattermost/package.json +1 -1
  144. package/extensions/memory-core/package.json +1 -1
  145. package/extensions/memory-lancedb/package.json +1 -1
  146. package/extensions/minimax-portal-auth/package.json +1 -1
  147. package/extensions/msteams/CHANGELOG.md +12 -0
  148. package/extensions/msteams/package.json +1 -1
  149. package/extensions/nextcloud-talk/package.json +1 -1
  150. package/extensions/nostr/CHANGELOG.md +12 -0
  151. package/extensions/nostr/package.json +1 -1
  152. package/extensions/open-prose/package.json +1 -1
  153. package/extensions/signal/package.json +1 -1
  154. package/extensions/slack/package.json +1 -1
  155. package/extensions/synology-chat/package.json +1 -1
  156. package/extensions/telegram/package.json +1 -1
  157. package/extensions/tlon/package.json +1 -1
  158. package/extensions/twitch/CHANGELOG.md +12 -0
  159. package/extensions/twitch/package.json +1 -1
  160. package/extensions/voice-call/CHANGELOG.md +12 -0
  161. package/extensions/voice-call/package.json +1 -1
  162. package/extensions/whatsapp/package.json +1 -1
  163. package/extensions/zalo/CHANGELOG.md +12 -0
  164. package/extensions/zalo/package.json +1 -1
  165. package/extensions/zalouser/CHANGELOG.md +12 -0
  166. package/extensions/zalouser/package.json +1 -1
  167. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  Docs: https://docs.idlehands.ai
4
4
 
5
+ ## 4.0.15
6
+
7
+ ### Fixes
8
+
9
+ - Anton preflight correctness: remove unsafe fallback that previously allowed direct implementation when discovery failed to produce a verified plan file.
10
+ - Anton completion integrity: in preflight mode, Anton now verifies repository change count before marking a task complete, preventing false positives when implementation returns success without making code changes.
11
+
12
+ ## 4.0.14
13
+
14
+ ### Fixes
15
+
16
+ - Anton preflight reliability: add multi-pass discovery with structured JSON extraction, repair-pass retries, and fallback plan persistence so discovery can recover when models return malformed output or claim success without writing the plan file.
17
+ - Anton preflight redundancy: when discovery reports `incomplete` but no plan file exists, Anton now validates declared paths, attempts deterministic plan recovery, and only advances when a non-empty plan file is verified.
18
+
5
19
  ## 4.0.13
6
20
 
7
21
  ### Fixes
@@ -12,14 +12,14 @@ import "./boolean-CE7i9tBR.js";
12
12
  import "./env-B5G1qwGc.js";
13
13
  import "./dock-BgOmHcbh.js";
14
14
  import "./tokens-BRLyURxW.js";
15
- import { H as randomIdempotencyKey, V as callGateway, a as agentCommand, o as resolveSessionKeyForRequest, v as withProgress } from "./pi-embedded-B4tp4aBd.js";
15
+ import { H as randomIdempotencyKey, V as callGateway, a as agentCommand, o as resolveSessionKeyForRequest, v as withProgress } from "./pi-embedded-7XGjNojd.js";
16
16
  import "./plugins-CRB60mCJ.js";
17
17
  import "./accounts-Dk8mJIrQ.js";
18
18
  import "./bindings-D3b5Fmc9.js";
19
19
  import "./auth-store-DXT-l7fO.js";
20
20
  import "./send-BeIZJuy4.js";
21
21
  import "./send-DmLC7aEF.js";
22
- import "./deliver-CVTXl0Cv.js";
22
+ import "./deliver-BUiQ-9fE.js";
23
23
  import "./diagnostic-4owMk4vH.js";
24
24
  import "./diagnostic-session-state-BGF2r-kt.js";
25
25
  import "./accounts-BDVs8LTu.js";
@@ -27,8 +27,8 @@ import "./send-Dfa3sn6r.js";
27
27
  import "./image-ops-D1KtygWz.js";
28
28
  import "./pi-model-discovery-Bb__OY-j.js";
29
29
  import { d as GATEWAY_CLIENT_MODES, f as GATEWAY_CLIENT_NAMES, s as normalizeMessageChannel } from "./message-channel-C8QtrwEU.js";
30
- import "./pi-embedded-helpers-CyTpDKo5.js";
31
- import "./chrome-_2tzVjVl.js";
30
+ import "./pi-embedded-helpers-CghCLoPo.js";
31
+ import "./chrome-BcJB6PcM.js";
32
32
  import "./ssrf-CZeHDwVZ.js";
33
33
  import "./frontmatter-BOudmHMS.js";
34
34
  import "./skills-CnAPWfca.js";
@@ -42,7 +42,7 @@ import "./accounts-CIvVRRHb.js";
42
42
  import "./paths-D_qUel1T.js";
43
43
  import "./tool-images-CcGZpzmq.js";
44
44
  import "./thinking-z4_linel.js";
45
- import "./image-COw__ACq.js";
45
+ import "./image-D8b_rlQC.js";
46
46
  import "./reply-prefix-BUgeSN2R.js";
47
47
  import "./manager-BE_76jWB.js";
48
48
  import "./gemini-auth-CIyaa44H.js";
@@ -57,7 +57,7 @@ import "./ir-B7IBoKLy.js";
57
57
  import "./render-MTSxc7LK.js";
58
58
  import "./commands-registry-j4vAzcF2.js";
59
59
  import "./skill-commands-Ck3flWX7.js";
60
- import "./runner-BzNdfqDz.js";
60
+ import "./runner-PgRFPYUj.js";
61
61
  import "./fetch-CsfR_943.js";
62
62
  import "./channel-activity-D_TMOGQ0.js";
63
63
  import "./tables-5k-zOZ-s.js";
@@ -67,7 +67,7 @@ import "./send-D4bMycQu.js";
67
67
  import "./resolve-route-DuttYY7A.js";
68
68
  import "./proxy-CRB9oCP5.js";
69
69
  import "./replies-6_GxvQYe.js";
70
- import "./deps--Jd_1mvW.js";
70
+ import "./deps-KIFYHxig.js";
71
71
 
72
72
  //#region src/commands/agent-via-gateway.ts
73
73
  const NO_GATEWAY_TIMEOUT_MS = 2147e6;
@@ -4,7 +4,7 @@ import { t as formatCliCommand } from "./command-format-CPa5ksO_.js";
4
4
  import { r as listAgentIds } from "./agent-scope-mLXQGQde.js";
5
5
  import { s as normalizeAgentId } from "./session-key-B9ePuoPx.js";
6
6
  import { h as GATEWAY_CLIENT_NAMES, l as normalizeMessageChannel, m as GATEWAY_CLIENT_MODES } from "./message-channel-Qpj4ExtQ.js";
7
- import { D as resolveSessionKeyForRequest, E as agentCommand } from "./subagent-registry-CV8jrQca.js";
7
+ import { D as resolveSessionKeyForRequest, E as agentCommand } from "./subagent-registry-C6uygQa1.js";
8
8
  import { a as randomIdempotencyKey, n as callGateway } from "./call-DuNslqj2.js";
9
9
  import { n as withProgress } from "./progress-B76RkFx7.js";
10
10
 
@@ -11,7 +11,7 @@ import { t as formatCliCommand } from "./command-format-BAxx4PW5.js";
11
11
  import "./env-BpvqFD5n.js";
12
12
  import "./dock-QcCdS4qA.js";
13
13
  import "./tokens-Cg4XNE3H.js";
14
- import { H as callGateway, U as randomIdempotencyKey, a as agentCommand, o as resolveSessionKeyForRequest, v as withProgress } from "./pi-embedded-CNvCKXkm.js";
14
+ import { H as callGateway, U as randomIdempotencyKey, a as agentCommand, o as resolveSessionKeyForRequest, v as withProgress } from "./pi-embedded-Swc7dke2.js";
15
15
  import "./plugins-D-_jp4FO.js";
16
16
  import "./accounts-BwrguHMw.js";
17
17
  import "./bindings-hT7SPhiA.js";
@@ -64,7 +64,7 @@ import "./send-Cn2wvd3W.js";
64
64
  import "./resolve-route-BI3VjtwE.js";
65
65
  import "./proxy-CNZpb4NE.js";
66
66
  import "./replies-CqYEEgmA.js";
67
- import "./deps-CEc0DzO7.js";
67
+ import "./deps-TwKaIh1I.js";
68
68
 
69
69
  //#region src/commands/agent-via-gateway.ts
70
70
  const NO_GATEWAY_TIMEOUT_MS = 2147e6;
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
- import { Mt as resolveSessionKeyForRequest, jt as agentCommand } from "./reply-DuYN0-Pb.js";
2
+ import { Mt as resolveSessionKeyForRequest, jt as agentCommand } from "./reply-ZWOav11z.js";
3
3
  import { r as listAgentIds } from "./agent-scope-RA0zXRpu.js";
4
4
  import { s as normalizeAgentId } from "./session-key-Cuihcz_O.js";
5
5
  import { It as loadConfig } from "./model-selection-0dGxYGp8.js";
@@ -6,18 +6,18 @@ import { t as formatCliCommand } from "./command-format-CPa5ksO_.js";
6
6
  import { a as resolveAgentDir, b as DEFAULT_IDENTITY_FILENAME, d as resolveDefaultAgentId, n as listAgentEntries, u as resolveAgentWorkspaceDir } from "./agent-scope-mLXQGQde.js";
7
7
  import { m as DEFAULT_ACCOUNT_ID, s as normalizeAgentId, t as DEFAULT_AGENT_ID } from "./session-key-B9ePuoPx.js";
8
8
  import { n as listChannelPlugins, r as normalizeChannelId, t as getChannelPlugin } from "./plugins-CCrfZ49T.js";
9
- import { M as identityHasValues, P as parseIdentityMarkdown } from "./subagent-registry-CV8jrQca.js";
9
+ import { M as identityHasValues, P as parseIdentityMarkdown } from "./subagent-registry-C6uygQa1.js";
10
10
  import { l as resolveSessionTranscriptsDirForAgent } from "./paths-CC17i2eK.js";
11
11
  import { a as ensureWorkspaceAndSessions, l as moveToTrash } from "./onboard-helpers-Dp6wXNs7.js";
12
12
  import { t as WizardCancelledError } from "./prompts-D3HHe1ZZ.js";
13
13
  import { t as createClackPrompter } from "./clack-prompter-Bo7vS5xP.js";
14
14
  import { t as resolveChannelDefaultAccountId } from "./helpers-CIyuenBU.js";
15
15
  import { a as parseBindingSpecs, i as describeBinding, n as applyAgentBindings, o as removeAgentBindings, r as buildChannelBindings, t as requireValidConfigSnapshot } from "./config-validation-BgKexeQb.js";
16
- import { a as pruneAgentConfig, i as loadAgentIdentity, n as buildAgentSummaries, r as findAgentEntryIndex, t as applyAgentConfig } from "./agents.config-s_1D920P.js";
17
- import { r as setupChannels } from "./onboard-channels-DAk60Ns1.js";
16
+ import { a as pruneAgentConfig, i as loadAgentIdentity, n as buildAgentSummaries, r as findAgentEntryIndex, t as applyAgentConfig } from "./agents.config-8pxRoZvL.js";
17
+ import { r as setupChannels } from "./onboard-channels-mLWuxUlN.js";
18
18
  import { n as logConfigUpdated } from "./logging-MF6Thoxk.js";
19
19
  import { n as promptAuthChoiceGrouped } from "./auth-choice-prompt-kycZqH8q.js";
20
- import { i as applyAuthChoice, r as warnIfModelConfigLooksOff } from "./auth-choice-CoDCd8IM.js";
20
+ import { i as applyAuthChoice, r as warnIfModelConfigLooksOff } from "./auth-choice-D-_AVWgJ.js";
21
21
  import path from "node:path";
22
22
  import fs from "node:fs/promises";
23
23
 
@@ -1,6 +1,6 @@
1
1
  import { a as resolveAgentDir, d as resolveDefaultAgentId, n as listAgentEntries, u as resolveAgentWorkspaceDir } from "./agent-scope-mLXQGQde.js";
2
2
  import { s as normalizeAgentId } from "./session-key-B9ePuoPx.js";
3
- import { M as identityHasValues, N as loadAgentIdentityFromWorkspace } from "./subagent-registry-CV8jrQca.js";
3
+ import { M as identityHasValues, N as loadAgentIdentityFromWorkspace } from "./subagent-registry-C6uygQa1.js";
4
4
 
5
5
  //#region src/commands/agents.config.ts
6
6
  function findAgentEntryIndex(list, agentId) {
@@ -1,4 +1,4 @@
1
- import { en as identityHasValues, tn as loadAgentIdentityFromWorkspace } from "./reply-DuYN0-Pb.js";
1
+ import { en as identityHasValues, tn as loadAgentIdentityFromWorkspace } from "./reply-ZWOav11z.js";
2
2
  import { a as resolveAgentDir, d as resolveDefaultAgentId, n as listAgentEntries, u as resolveAgentWorkspaceDir } from "./agent-scope-RA0zXRpu.js";
3
3
  import { s as normalizeAgentId } from "./session-key-Cuihcz_O.js";
4
4
 
@@ -1,11 +1,14 @@
1
1
  import "./paths-BQL7-SbN.js";
2
2
  import { t as CONFIG_DIR } from "./utils-DWJR1fcE.js";
3
3
  import path from "node:path";
4
+ import { promisify } from "node:util";
4
5
  import fs from "node:fs/promises";
6
+ import { execFile } from "node:child_process";
5
7
 
6
8
  //#region src/commands/anton.ts
7
9
  const ANTON_STATE_PATH = path.join(CONFIG_DIR, "anton.state.json");
8
10
  const ANTON_LOCK_PATH = path.join(CONFIG_DIR, "anton.lock");
11
+ const execFile$1 = promisify(execFile);
9
12
  async function ensureStateDir() {
10
13
  await fs.mkdir(CONFIG_DIR, { recursive: true });
11
14
  }
@@ -216,18 +219,19 @@ async function loadAntonConfig() {
216
219
  }
217
220
  }
218
221
  async function runAgentTask(args) {
219
- const { agentCliCommand } = await import("./agent-via-gateway-C9xTFnnb.js");
222
+ const { agentCliCommand } = await import("./agent-via-gateway-CIM26Dxl.js");
220
223
  const extraSystemPrompt = args.workspaceDir ? `Your working directory is: ${args.workspaceDir}\nAll file paths are relative to this directory. Use this as your cwd for all operations.` : void 0;
221
- await agentCliCommand({
224
+ const result = await agentCliCommand({
222
225
  message: args.message,
223
226
  agent: args.agent,
224
227
  to: args.to,
225
228
  sessionId: args.sessionId,
226
229
  timeout: args.timeout,
227
- json: false,
230
+ json: true,
228
231
  deliver: false,
229
232
  extraSystemPrompt
230
233
  }, args.runtime, args.deps);
234
+ return { text: (result && typeof result === "object" && "result" in result ? result.result?.payloads ?? [] : []).map((p) => typeof p?.text === "string" ? p.text.trim() : "").filter(Boolean).join("\n\n").trim() };
231
235
  }
232
236
  function makePlanFilePath(planDir, taskIndex) {
233
237
  return path.join(planDir, `task-${taskIndex}-${Date.now()}.md`);
@@ -243,6 +247,71 @@ async function isPlanFileValid(filePath) {
243
247
  return false;
244
248
  }
245
249
  }
250
+ async function getGitChangedFileCount(cwd) {
251
+ try {
252
+ const { stdout } = await execFile$1("git", ["status", "--porcelain"], { cwd });
253
+ return stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).length;
254
+ } catch {
255
+ return null;
256
+ }
257
+ }
258
+ function extractJsonObject(text) {
259
+ const trimmed = text.trim();
260
+ if (!trimmed) return null;
261
+ const tryParse = (candidate) => {
262
+ try {
263
+ const parsed = JSON.parse(candidate);
264
+ if (!parsed || typeof parsed !== "object") return null;
265
+ return parsed;
266
+ } catch {
267
+ return null;
268
+ }
269
+ };
270
+ const direct = tryParse(trimmed);
271
+ if (direct) return direct;
272
+ const fencedMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i);
273
+ if (fencedMatch?.[1]) {
274
+ const fenced = tryParse(fencedMatch[1].trim());
275
+ if (fenced) return fenced;
276
+ }
277
+ const first = trimmed.indexOf("{");
278
+ const last = trimmed.lastIndexOf("}");
279
+ if (first >= 0 && last > first) {
280
+ const sliced = tryParse(trimmed.slice(first, last + 1));
281
+ if (sliced) return sliced;
282
+ }
283
+ return null;
284
+ }
285
+ function extractPlanMarkdownFromText(text) {
286
+ const candidate = text.match(/```(?:markdown|md)?\s*([\s\S]*?)```/i)?.[1]?.trim() ?? text.trim();
287
+ if (candidate.length < 60) return;
288
+ return candidate;
289
+ }
290
+ function normalizeDiscoveryFilename(filename, expectedPlanFile) {
291
+ const trimmed = filename?.trim();
292
+ if (!trimmed) return expectedPlanFile;
293
+ return path.resolve(trimmed);
294
+ }
295
+ function buildDiscoveryRepairPrompt(task, taskFile, planFilePath) {
296
+ return `RETRY: your previous preflight response did not produce a valid plan file.
297
+
298
+ You MUST complete these steps exactly:
299
+ 1) Write the implementation plan to: ${planFilePath}
300
+ 2) Verify the file exists and is non-empty
301
+ 3) Return ONLY strict JSON: {"status":"incomplete","filename":"${planFilePath}"}
302
+
303
+ If task is already complete, return ONLY: {"status":"complete","filename":""}
304
+
305
+ Do not include THOUGHT, markdown fences, or extra commentary.
306
+ Task file: ${taskFile}
307
+ Task: ${task}`;
308
+ }
309
+ async function tryPersistPlanFallback(params) {
310
+ const planText = (((typeof params.parsed?.planMarkdown === "string" ? params.parsed.planMarkdown : void 0) ?? (typeof params.parsed?.plan === "string" ? params.parsed.plan : void 0))?.trim() || extractPlanMarkdownFromText(params.rawText) || "").trim();
311
+ if (planText.length < 60) return false;
312
+ await fs.writeFile(params.planFile, `${planText}\n`, "utf8");
313
+ return await isPlanFileValid(params.planFile);
314
+ }
246
315
  async function runDiscoveryPhase(args) {
247
316
  const planFile = makePlanFilePath(args.planDir, args.taskNum);
248
317
  await ensurePlanDir(args.planDir);
@@ -262,7 +331,7 @@ async function runDiscoveryPhase(args) {
262
331
  task: `Discovery (attempt ${attempt + 1})`,
263
332
  sessionId
264
333
  });
265
- await runAgentTask({
334
+ const firstPass = await runAgentTask({
266
335
  message: buildDiscoveryPrompt(args.task.text, args.taskFile, planFile),
267
336
  sessionId,
268
337
  timeout: args.timeout,
@@ -272,23 +341,91 @@ async function runDiscoveryPhase(args) {
272
341
  deps: args.deps,
273
342
  workspaceDir: args.workspaceDir
274
343
  });
275
- if (await isPlanFileValid(planFile)) {
344
+ const firstParsed = extractJsonObject(firstPass.text);
345
+ if ((firstParsed?.status ?? "").toLowerCase() === "complete") return { status: "complete" };
346
+ const declaredPlanFile = normalizeDiscoveryFilename(firstParsed?.filename, planFile);
347
+ if (await isPlanFileValid(declaredPlanFile)) {
276
348
  await args.notify({
277
349
  phase: "discovery_complete",
278
350
  index: args.taskNum,
279
351
  total: args.total,
280
352
  task: args.task.text,
281
- planFile
353
+ planFile: declaredPlanFile
282
354
  });
283
355
  return {
284
356
  status: "plan_ready",
285
- planFile
357
+ planFile: declaredPlanFile
358
+ };
359
+ }
360
+ if ((firstParsed?.status ?? "").toLowerCase() === "incomplete" && await tryPersistPlanFallback({
361
+ planFile: declaredPlanFile,
362
+ parsed: firstParsed,
363
+ rawText: firstPass.text
364
+ })) {
365
+ await args.notify({
366
+ phase: "discovery_complete",
367
+ index: args.taskNum,
368
+ total: args.total,
369
+ task: args.task.text,
370
+ planFile: declaredPlanFile
371
+ });
372
+ return {
373
+ status: "plan_ready",
374
+ planFile: declaredPlanFile
375
+ };
376
+ }
377
+ const repairSessionId = `anton-discovery-repair-${Date.now()}-${args.taskNum}-${attempt}`;
378
+ await args.notify({
379
+ phase: "task_agent_spawned",
380
+ index: args.taskNum,
381
+ total: args.total,
382
+ task: `Discovery repair (attempt ${attempt + 1})`,
383
+ sessionId: repairSessionId
384
+ });
385
+ const repairPass = await runAgentTask({
386
+ message: buildDiscoveryRepairPrompt(args.task.text, args.taskFile, declaredPlanFile),
387
+ sessionId: repairSessionId,
388
+ timeout: args.timeout,
389
+ agent: args.agent,
390
+ to: args.to,
391
+ runtime: args.runtime,
392
+ deps: args.deps,
393
+ workspaceDir: args.workspaceDir
394
+ });
395
+ const repairParsed = extractJsonObject(repairPass.text);
396
+ if ((repairParsed?.status ?? "").toLowerCase() === "complete") return { status: "complete" };
397
+ const repairPlanFile = normalizeDiscoveryFilename(repairParsed?.filename, declaredPlanFile);
398
+ if (await isPlanFileValid(repairPlanFile) || await tryPersistPlanFallback({
399
+ planFile: repairPlanFile,
400
+ parsed: repairParsed,
401
+ rawText: repairPass.text
402
+ })) {
403
+ await args.notify({
404
+ phase: "discovery_complete",
405
+ index: args.taskNum,
406
+ total: args.total,
407
+ task: args.task.text,
408
+ planFile: repairPlanFile
409
+ });
410
+ return {
411
+ status: "plan_ready",
412
+ planFile: repairPlanFile
413
+ };
414
+ }
415
+ if (attempt === args.maxRetries) {
416
+ const reason = "Discovery did not produce a valid plan file after primary + repair passes";
417
+ await args.notify({
418
+ phase: "discovery_failed",
419
+ index: args.taskNum,
420
+ total: args.total,
421
+ task: args.task.text,
422
+ error: reason
423
+ });
424
+ return {
425
+ status: "failed",
426
+ error: reason
286
427
  };
287
428
  }
288
- if (attempt === args.maxRetries) return {
289
- status: "failed",
290
- error: "Discovery did not produce a valid plan file"
291
- };
292
429
  } catch (err) {
293
430
  const errorMsg = err instanceof Error ? err.message : String(err);
294
431
  if (attempt === args.maxRetries) {
@@ -495,6 +632,7 @@ async function runAnton(args) {
495
632
  workspaceDir: args.workspaceDir
496
633
  });
497
634
  }
635
+ if (!planFile) throw new Error("Preflight discovery did not produce a verified plan file; refusing direct implementation fallback");
498
636
  }
499
637
  await notify({
500
638
  phase: "implementation_start",
@@ -511,8 +649,11 @@ async function runAnton(args) {
511
649
  task: task.text,
512
650
  sessionId: implSessionId
513
651
  });
652
+ const implPrompt = planFile ? buildImplementationPrompt(task.text, planFile) : buildDirectTaskPrompt(task.text);
653
+ const gitCwd = args.workspaceDir ? path.resolve(args.workspaceDir) : path.dirname(filePath);
654
+ const changedBefore = await getGitChangedFileCount(gitCwd);
514
655
  await runAgentTask({
515
- message: planFile ? buildImplementationPrompt(task.text, planFile) : buildDirectTaskPrompt(task.text),
656
+ message: implPrompt,
516
657
  sessionId: implSessionId,
517
658
  timeout: defaultTimeout,
518
659
  agent: args.agent,
@@ -521,6 +662,8 @@ async function runAnton(args) {
521
662
  deps: args.deps,
522
663
  workspaceDir: args.workspaceDir
523
664
  });
665
+ const changedAfter = await getGitChangedFileCount(gitCwd);
666
+ if (mode === "preflight" && changedBefore !== null && changedAfter !== null && changedAfter <= changedBefore) throw new Error("Implementation made no repository changes; refusing to mark task complete");
524
667
  const updated = markTaskDone(await fs.readFile(filePath, "utf8"), task.line);
525
668
  await fs.writeFile(filePath, updated, "utf8");
526
669
  completed += 1;
@@ -1,6 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
2
  import { R as CONFIG_DIR } from "./entry.js";
3
+ import { execFile } from "node:child_process";
3
4
  import path from "node:path";
5
+ import { promisify } from "node:util";
4
6
  import fs from "node:fs/promises";
5
7
 
6
8
  //#region src/commands/anton.ts
@@ -12,6 +14,7 @@ var anton_exports = /* @__PURE__ */ __exportAll({
12
14
  });
13
15
  const ANTON_STATE_PATH = path.join(CONFIG_DIR, "anton.state.json");
14
16
  const ANTON_LOCK_PATH = path.join(CONFIG_DIR, "anton.lock");
17
+ const execFile$1 = promisify(execFile);
15
18
  async function ensureStateDir() {
16
19
  await fs.mkdir(CONFIG_DIR, { recursive: true });
17
20
  }
@@ -222,18 +225,19 @@ async function loadAntonConfig() {
222
225
  }
223
226
  }
224
227
  async function runAgentTask(args) {
225
- const { agentCliCommand } = await import("./agent-via-gateway-C1akskt-.js").then((n) => n.n);
228
+ const { agentCliCommand } = await import("./agent-via-gateway-BvXS1sXv.js").then((n) => n.n);
226
229
  const extraSystemPrompt = args.workspaceDir ? `Your working directory is: ${args.workspaceDir}\nAll file paths are relative to this directory. Use this as your cwd for all operations.` : void 0;
227
- await agentCliCommand({
230
+ const result = await agentCliCommand({
228
231
  message: args.message,
229
232
  agent: args.agent,
230
233
  to: args.to,
231
234
  sessionId: args.sessionId,
232
235
  timeout: args.timeout,
233
- json: false,
236
+ json: true,
234
237
  deliver: false,
235
238
  extraSystemPrompt
236
239
  }, args.runtime, args.deps);
240
+ return { text: (result && typeof result === "object" && "result" in result ? result.result?.payloads ?? [] : []).map((p) => typeof p?.text === "string" ? p.text.trim() : "").filter(Boolean).join("\n\n").trim() };
237
241
  }
238
242
  function makePlanFilePath(planDir, taskIndex) {
239
243
  return path.join(planDir, `task-${taskIndex}-${Date.now()}.md`);
@@ -249,6 +253,71 @@ async function isPlanFileValid(filePath) {
249
253
  return false;
250
254
  }
251
255
  }
256
+ async function getGitChangedFileCount(cwd) {
257
+ try {
258
+ const { stdout } = await execFile$1("git", ["status", "--porcelain"], { cwd });
259
+ return stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).length;
260
+ } catch {
261
+ return null;
262
+ }
263
+ }
264
+ function extractJsonObject(text) {
265
+ const trimmed = text.trim();
266
+ if (!trimmed) return null;
267
+ const tryParse = (candidate) => {
268
+ try {
269
+ const parsed = JSON.parse(candidate);
270
+ if (!parsed || typeof parsed !== "object") return null;
271
+ return parsed;
272
+ } catch {
273
+ return null;
274
+ }
275
+ };
276
+ const direct = tryParse(trimmed);
277
+ if (direct) return direct;
278
+ const fencedMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i);
279
+ if (fencedMatch?.[1]) {
280
+ const fenced = tryParse(fencedMatch[1].trim());
281
+ if (fenced) return fenced;
282
+ }
283
+ const first = trimmed.indexOf("{");
284
+ const last = trimmed.lastIndexOf("}");
285
+ if (first >= 0 && last > first) {
286
+ const sliced = tryParse(trimmed.slice(first, last + 1));
287
+ if (sliced) return sliced;
288
+ }
289
+ return null;
290
+ }
291
+ function extractPlanMarkdownFromText(text) {
292
+ const candidate = text.match(/```(?:markdown|md)?\s*([\s\S]*?)```/i)?.[1]?.trim() ?? text.trim();
293
+ if (candidate.length < 60) return;
294
+ return candidate;
295
+ }
296
+ function normalizeDiscoveryFilename(filename, expectedPlanFile) {
297
+ const trimmed = filename?.trim();
298
+ if (!trimmed) return expectedPlanFile;
299
+ return path.resolve(trimmed);
300
+ }
301
+ function buildDiscoveryRepairPrompt(task, taskFile, planFilePath) {
302
+ return `RETRY: your previous preflight response did not produce a valid plan file.
303
+
304
+ You MUST complete these steps exactly:
305
+ 1) Write the implementation plan to: ${planFilePath}
306
+ 2) Verify the file exists and is non-empty
307
+ 3) Return ONLY strict JSON: {"status":"incomplete","filename":"${planFilePath}"}
308
+
309
+ If task is already complete, return ONLY: {"status":"complete","filename":""}
310
+
311
+ Do not include THOUGHT, markdown fences, or extra commentary.
312
+ Task file: ${taskFile}
313
+ Task: ${task}`;
314
+ }
315
+ async function tryPersistPlanFallback(params) {
316
+ const planText = (((typeof params.parsed?.planMarkdown === "string" ? params.parsed.planMarkdown : void 0) ?? (typeof params.parsed?.plan === "string" ? params.parsed.plan : void 0))?.trim() || extractPlanMarkdownFromText(params.rawText) || "").trim();
317
+ if (planText.length < 60) return false;
318
+ await fs.writeFile(params.planFile, `${planText}\n`, "utf8");
319
+ return await isPlanFileValid(params.planFile);
320
+ }
252
321
  async function runDiscoveryPhase(args) {
253
322
  const planFile = makePlanFilePath(args.planDir, args.taskNum);
254
323
  await ensurePlanDir(args.planDir);
@@ -268,7 +337,7 @@ async function runDiscoveryPhase(args) {
268
337
  task: `Discovery (attempt ${attempt + 1})`,
269
338
  sessionId
270
339
  });
271
- await runAgentTask({
340
+ const firstPass = await runAgentTask({
272
341
  message: buildDiscoveryPrompt(args.task.text, args.taskFile, planFile),
273
342
  sessionId,
274
343
  timeout: args.timeout,
@@ -278,23 +347,91 @@ async function runDiscoveryPhase(args) {
278
347
  deps: args.deps,
279
348
  workspaceDir: args.workspaceDir
280
349
  });
281
- if (await isPlanFileValid(planFile)) {
350
+ const firstParsed = extractJsonObject(firstPass.text);
351
+ if ((firstParsed?.status ?? "").toLowerCase() === "complete") return { status: "complete" };
352
+ const declaredPlanFile = normalizeDiscoveryFilename(firstParsed?.filename, planFile);
353
+ if (await isPlanFileValid(declaredPlanFile)) {
282
354
  await args.notify({
283
355
  phase: "discovery_complete",
284
356
  index: args.taskNum,
285
357
  total: args.total,
286
358
  task: args.task.text,
287
- planFile
359
+ planFile: declaredPlanFile
288
360
  });
289
361
  return {
290
362
  status: "plan_ready",
291
- planFile
363
+ planFile: declaredPlanFile
364
+ };
365
+ }
366
+ if ((firstParsed?.status ?? "").toLowerCase() === "incomplete" && await tryPersistPlanFallback({
367
+ planFile: declaredPlanFile,
368
+ parsed: firstParsed,
369
+ rawText: firstPass.text
370
+ })) {
371
+ await args.notify({
372
+ phase: "discovery_complete",
373
+ index: args.taskNum,
374
+ total: args.total,
375
+ task: args.task.text,
376
+ planFile: declaredPlanFile
377
+ });
378
+ return {
379
+ status: "plan_ready",
380
+ planFile: declaredPlanFile
381
+ };
382
+ }
383
+ const repairSessionId = `anton-discovery-repair-${Date.now()}-${args.taskNum}-${attempt}`;
384
+ await args.notify({
385
+ phase: "task_agent_spawned",
386
+ index: args.taskNum,
387
+ total: args.total,
388
+ task: `Discovery repair (attempt ${attempt + 1})`,
389
+ sessionId: repairSessionId
390
+ });
391
+ const repairPass = await runAgentTask({
392
+ message: buildDiscoveryRepairPrompt(args.task.text, args.taskFile, declaredPlanFile),
393
+ sessionId: repairSessionId,
394
+ timeout: args.timeout,
395
+ agent: args.agent,
396
+ to: args.to,
397
+ runtime: args.runtime,
398
+ deps: args.deps,
399
+ workspaceDir: args.workspaceDir
400
+ });
401
+ const repairParsed = extractJsonObject(repairPass.text);
402
+ if ((repairParsed?.status ?? "").toLowerCase() === "complete") return { status: "complete" };
403
+ const repairPlanFile = normalizeDiscoveryFilename(repairParsed?.filename, declaredPlanFile);
404
+ if (await isPlanFileValid(repairPlanFile) || await tryPersistPlanFallback({
405
+ planFile: repairPlanFile,
406
+ parsed: repairParsed,
407
+ rawText: repairPass.text
408
+ })) {
409
+ await args.notify({
410
+ phase: "discovery_complete",
411
+ index: args.taskNum,
412
+ total: args.total,
413
+ task: args.task.text,
414
+ planFile: repairPlanFile
415
+ });
416
+ return {
417
+ status: "plan_ready",
418
+ planFile: repairPlanFile
419
+ };
420
+ }
421
+ if (attempt === args.maxRetries) {
422
+ const reason = "Discovery did not produce a valid plan file after primary + repair passes";
423
+ await args.notify({
424
+ phase: "discovery_failed",
425
+ index: args.taskNum,
426
+ total: args.total,
427
+ task: args.task.text,
428
+ error: reason
429
+ });
430
+ return {
431
+ status: "failed",
432
+ error: reason
292
433
  };
293
434
  }
294
- if (attempt === args.maxRetries) return {
295
- status: "failed",
296
- error: "Discovery did not produce a valid plan file"
297
- };
298
435
  } catch (err) {
299
436
  const errorMsg = err instanceof Error ? err.message : String(err);
300
437
  if (attempt === args.maxRetries) {
@@ -501,6 +638,7 @@ async function runAnton(args) {
501
638
  workspaceDir: args.workspaceDir
502
639
  });
503
640
  }
641
+ if (!planFile) throw new Error("Preflight discovery did not produce a verified plan file; refusing direct implementation fallback");
504
642
  }
505
643
  await notify({
506
644
  phase: "implementation_start",
@@ -517,8 +655,11 @@ async function runAnton(args) {
517
655
  task: task.text,
518
656
  sessionId: implSessionId
519
657
  });
658
+ const implPrompt = planFile ? buildImplementationPrompt(task.text, planFile) : buildDirectTaskPrompt(task.text);
659
+ const gitCwd = args.workspaceDir ? path.resolve(args.workspaceDir) : path.dirname(filePath);
660
+ const changedBefore = await getGitChangedFileCount(gitCwd);
520
661
  await runAgentTask({
521
- message: planFile ? buildImplementationPrompt(task.text, planFile) : buildDirectTaskPrompt(task.text),
662
+ message: implPrompt,
522
663
  sessionId: implSessionId,
523
664
  timeout: defaultTimeout,
524
665
  agent: args.agent,
@@ -527,6 +668,8 @@ async function runAnton(args) {
527
668
  deps: args.deps,
528
669
  workspaceDir: args.workspaceDir
529
670
  });
671
+ const changedAfter = await getGitChangedFileCount(gitCwd);
672
+ if (mode === "preflight" && changedBefore !== null && changedAfter !== null && changedAfter <= changedBefore) throw new Error("Implementation made no repository changes; refusing to mark task complete");
530
673
  const updated = markTaskDone(await fs.readFile(filePath, "utf8"), task.line);
531
674
  await fs.writeFile(filePath, updated, "utf8");
532
675
  completed += 1;