@kenkaiiii/ggcoder 4.3.211 → 4.3.213

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 (314) hide show
  1. package/README.md +5 -8
  2. package/dist/cli.d.ts +3 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +112 -61
  5. package/dist/cli.js.map +1 -1
  6. package/dist/core/continue-replay-inventory.test.d.ts +2 -0
  7. package/dist/core/continue-replay-inventory.test.d.ts.map +1 -0
  8. package/dist/core/continue-replay-inventory.test.js +42 -0
  9. package/dist/core/continue-replay-inventory.test.js.map +1 -0
  10. package/dist/core/goal-controller.d.ts +2 -0
  11. package/dist/core/goal-controller.d.ts.map +1 -1
  12. package/dist/core/goal-controller.js +283 -24
  13. package/dist/core/goal-controller.js.map +1 -1
  14. package/dist/core/goal-controller.test.js +413 -16
  15. package/dist/core/goal-controller.test.js.map +1 -1
  16. package/dist/core/goal-lifecycle-smoke.test.js +48 -6
  17. package/dist/core/goal-lifecycle-smoke.test.js.map +1 -1
  18. package/dist/core/goal-prerequisites.d.ts +23 -0
  19. package/dist/core/goal-prerequisites.d.ts.map +1 -0
  20. package/dist/core/goal-prerequisites.js +114 -0
  21. package/dist/core/goal-prerequisites.js.map +1 -0
  22. package/dist/core/goal-prerequisites.test.d.ts +2 -0
  23. package/dist/core/goal-prerequisites.test.d.ts.map +1 -0
  24. package/dist/core/goal-prerequisites.test.js +118 -0
  25. package/dist/core/goal-prerequisites.test.js.map +1 -0
  26. package/dist/core/goal-references.d.ts +14 -0
  27. package/dist/core/goal-references.d.ts.map +1 -0
  28. package/dist/core/goal-references.js +153 -0
  29. package/dist/core/goal-references.js.map +1 -0
  30. package/dist/core/goal-references.test.d.ts +2 -0
  31. package/dist/core/goal-references.test.d.ts.map +1 -0
  32. package/dist/core/goal-references.test.js +77 -0
  33. package/dist/core/goal-references.test.js.map +1 -0
  34. package/dist/core/goal-store.d.ts +25 -0
  35. package/dist/core/goal-store.d.ts.map +1 -1
  36. package/dist/core/goal-store.js +161 -38
  37. package/dist/core/goal-store.js.map +1 -1
  38. package/dist/core/goal-store.test.js +33 -8
  39. package/dist/core/goal-store.test.js.map +1 -1
  40. package/dist/core/goal-verifier.d.ts.map +1 -1
  41. package/dist/core/goal-verifier.js +4 -1
  42. package/dist/core/goal-verifier.js.map +1 -1
  43. package/dist/core/goal-verifier.test.js +43 -0
  44. package/dist/core/goal-verifier.test.js.map +1 -1
  45. package/dist/core/goal-worker.d.ts +2 -0
  46. package/dist/core/goal-worker.d.ts.map +1 -1
  47. package/dist/core/goal-worker.js +33 -9
  48. package/dist/core/goal-worker.js.map +1 -1
  49. package/dist/core/goal-worker.test.js +49 -1
  50. package/dist/core/goal-worker.test.js.map +1 -1
  51. package/dist/core/prompt-commands.d.ts.map +1 -1
  52. package/dist/core/prompt-commands.js +28 -845
  53. package/dist/core/prompt-commands.js.map +1 -1
  54. package/dist/core/prompt-commands.test.js +40 -74
  55. package/dist/core/prompt-commands.test.js.map +1 -1
  56. package/dist/core/runtime-mode.d.ts +14 -0
  57. package/dist/core/runtime-mode.d.ts.map +1 -0
  58. package/dist/core/runtime-mode.js +10 -0
  59. package/dist/core/runtime-mode.js.map +1 -0
  60. package/dist/core/session-restore-display.test.d.ts +2 -0
  61. package/dist/core/session-restore-display.test.d.ts.map +1 -0
  62. package/dist/core/session-restore-display.test.js +100 -0
  63. package/dist/core/session-restore-display.test.js.map +1 -0
  64. package/dist/core/verify-commands.js +4 -4
  65. package/dist/core/verify-commands.js.map +1 -1
  66. package/dist/system-prompt.d.ts +2 -1
  67. package/dist/system-prompt.d.ts.map +1 -1
  68. package/dist/system-prompt.js +51 -37
  69. package/dist/system-prompt.js.map +1 -1
  70. package/dist/system-prompt.test.js +147 -40
  71. package/dist/system-prompt.test.js.map +1 -1
  72. package/dist/tools/bash.d.ts +3 -2
  73. package/dist/tools/bash.d.ts.map +1 -1
  74. package/dist/tools/bash.js +11 -4
  75. package/dist/tools/bash.js.map +1 -1
  76. package/dist/tools/edit.d.ts +5 -3
  77. package/dist/tools/edit.d.ts.map +1 -1
  78. package/dist/tools/edit.js +14 -4
  79. package/dist/tools/edit.js.map +1 -1
  80. package/dist/tools/edit.test.js +0 -10
  81. package/dist/tools/edit.test.js.map +1 -1
  82. package/dist/tools/goal-mode.test.d.ts +2 -0
  83. package/dist/tools/goal-mode.test.d.ts.map +1 -0
  84. package/dist/tools/goal-mode.test.js +121 -0
  85. package/dist/tools/goal-mode.test.js.map +1 -0
  86. package/dist/tools/goals.d.ts +15 -3
  87. package/dist/tools/goals.d.ts.map +1 -1
  88. package/dist/tools/goals.js +385 -35
  89. package/dist/tools/goals.js.map +1 -1
  90. package/dist/tools/goals.test.js +389 -6
  91. package/dist/tools/goals.test.js.map +1 -1
  92. package/dist/tools/index.d.ts +7 -10
  93. package/dist/tools/index.d.ts.map +1 -1
  94. package/dist/tools/index.js +6 -19
  95. package/dist/tools/index.js.map +1 -1
  96. package/dist/tools/plan-mode.test.js +34 -224
  97. package/dist/tools/plan-mode.test.js.map +1 -1
  98. package/dist/tools/prompt-hints.d.ts.map +1 -1
  99. package/dist/tools/prompt-hints.js +2 -6
  100. package/dist/tools/prompt-hints.js.map +1 -1
  101. package/dist/tools/subagent.d.ts +3 -2
  102. package/dist/tools/subagent.d.ts.map +1 -1
  103. package/dist/tools/subagent.js +4 -9
  104. package/dist/tools/subagent.js.map +1 -1
  105. package/dist/tools/write.d.ts +5 -3
  106. package/dist/tools/write.d.ts.map +1 -1
  107. package/dist/tools/write.js +14 -13
  108. package/dist/tools/write.js.map +1 -1
  109. package/dist/tools/write.test.js +0 -16
  110. package/dist/tools/write.test.js.map +1 -1
  111. package/dist/ui/App.d.ts +146 -30
  112. package/dist/ui/App.d.ts.map +1 -1
  113. package/dist/ui/App.js +1202 -910
  114. package/dist/ui/App.js.map +1 -1
  115. package/dist/ui/activity-phrases.d.ts.map +1 -1
  116. package/dist/ui/activity-phrases.js +0 -2
  117. package/dist/ui/activity-phrases.js.map +1 -1
  118. package/dist/ui/app-state-persistence.test.js +181 -13
  119. package/dist/ui/app-state-persistence.test.js.map +1 -1
  120. package/dist/ui/chat-layout-pinning.test.d.ts +2 -0
  121. package/dist/ui/chat-layout-pinning.test.d.ts.map +1 -0
  122. package/dist/ui/chat-layout-pinning.test.js +407 -0
  123. package/dist/ui/chat-layout-pinning.test.js.map +1 -0
  124. package/dist/ui/components/ActivityIndicator.d.ts +1 -2
  125. package/dist/ui/components/ActivityIndicator.d.ts.map +1 -1
  126. package/dist/ui/components/ActivityIndicator.js +63 -94
  127. package/dist/ui/components/ActivityIndicator.js.map +1 -1
  128. package/dist/ui/components/AssistantMessage.d.ts +6 -2
  129. package/dist/ui/components/AssistantMessage.d.ts.map +1 -1
  130. package/dist/ui/components/AssistantMessage.js +9 -4
  131. package/dist/ui/components/AssistantMessage.js.map +1 -1
  132. package/dist/ui/components/AssistantMessage.test.d.ts +2 -0
  133. package/dist/ui/components/AssistantMessage.test.d.ts.map +1 -0
  134. package/dist/ui/components/AssistantMessage.test.js +369 -0
  135. package/dist/ui/components/AssistantMessage.test.js.map +1 -0
  136. package/dist/ui/components/BackgroundTasksBar.d.ts +1 -3
  137. package/dist/ui/components/BackgroundTasksBar.d.ts.map +1 -1
  138. package/dist/ui/components/BackgroundTasksBar.js +2 -4
  139. package/dist/ui/components/BackgroundTasksBar.js.map +1 -1
  140. package/dist/ui/components/Banner.d.ts +1 -3
  141. package/dist/ui/components/Banner.d.ts.map +1 -1
  142. package/dist/ui/components/Banner.js +7 -3
  143. package/dist/ui/components/Banner.js.map +1 -1
  144. package/dist/ui/components/Footer.d.ts +26 -4
  145. package/dist/ui/components/Footer.d.ts.map +1 -1
  146. package/dist/ui/components/Footer.js +73 -21
  147. package/dist/ui/components/Footer.js.map +1 -1
  148. package/dist/ui/components/GoalOverlay.d.ts +28 -20
  149. package/dist/ui/components/GoalOverlay.d.ts.map +1 -1
  150. package/dist/ui/components/GoalOverlay.js +283 -253
  151. package/dist/ui/components/GoalOverlay.js.map +1 -1
  152. package/dist/ui/components/InputArea.d.ts +2 -6
  153. package/dist/ui/components/InputArea.d.ts.map +1 -1
  154. package/dist/ui/components/InputArea.js +40 -32
  155. package/dist/ui/components/InputArea.js.map +1 -1
  156. package/dist/ui/components/InputArea.test.js +11 -1
  157. package/dist/ui/components/InputArea.test.js.map +1 -1
  158. package/dist/ui/components/Markdown.d.ts +11 -11
  159. package/dist/ui/components/Markdown.d.ts.map +1 -1
  160. package/dist/ui/components/Markdown.js +25 -198
  161. package/dist/ui/components/Markdown.js.map +1 -1
  162. package/dist/ui/components/PlanOverlay.d.ts.map +1 -1
  163. package/dist/ui/components/PlanOverlay.js +1 -1
  164. package/dist/ui/components/PlanOverlay.js.map +1 -1
  165. package/dist/ui/components/ServerToolExecution.d.ts.map +1 -1
  166. package/dist/ui/components/ServerToolExecution.js +3 -2
  167. package/dist/ui/components/ServerToolExecution.js.map +1 -1
  168. package/dist/ui/components/SlashCommandMenu.d.ts +4 -3
  169. package/dist/ui/components/SlashCommandMenu.d.ts.map +1 -1
  170. package/dist/ui/components/SlashCommandMenu.js +38 -26
  171. package/dist/ui/components/SlashCommandMenu.js.map +1 -1
  172. package/dist/ui/components/StreamingArea.d.ts +11 -2
  173. package/dist/ui/components/StreamingArea.d.ts.map +1 -1
  174. package/dist/ui/components/StreamingArea.js +20 -23
  175. package/dist/ui/components/StreamingArea.js.map +1 -1
  176. package/dist/ui/components/StreamingArea.test.d.ts +2 -0
  177. package/dist/ui/components/StreamingArea.test.d.ts.map +1 -0
  178. package/dist/ui/components/StreamingArea.test.js +18 -0
  179. package/dist/ui/components/StreamingArea.test.js.map +1 -0
  180. package/dist/ui/components/ToolExecution.d.ts.map +1 -1
  181. package/dist/ui/components/ToolExecution.js +11 -27
  182. package/dist/ui/components/ToolExecution.js.map +1 -1
  183. package/dist/ui/components/ToolGroupExecution.d.ts.map +1 -1
  184. package/dist/ui/components/ToolGroupExecution.js +9 -124
  185. package/dist/ui/components/ToolGroupExecution.js.map +1 -1
  186. package/dist/ui/components/UserMessage.d.ts.map +1 -1
  187. package/dist/ui/components/UserMessage.js +15 -10
  188. package/dist/ui/components/UserMessage.js.map +1 -1
  189. package/dist/ui/components/UserMessage.test.d.ts +2 -0
  190. package/dist/ui/components/UserMessage.test.d.ts.map +1 -0
  191. package/dist/ui/components/UserMessage.test.js +39 -0
  192. package/dist/ui/components/UserMessage.test.js.map +1 -0
  193. package/dist/ui/footer-status-layout.test.js +21 -7
  194. package/dist/ui/footer-status-layout.test.js.map +1 -1
  195. package/dist/ui/goal-events.d.ts +8 -0
  196. package/dist/ui/goal-events.d.ts.map +1 -1
  197. package/dist/ui/goal-events.js +28 -8
  198. package/dist/ui/goal-events.js.map +1 -1
  199. package/dist/ui/goal-events.test.js +40 -2
  200. package/dist/ui/goal-events.test.js.map +1 -1
  201. package/dist/ui/goal-lifecycle-orchestration.test.js +127 -34
  202. package/dist/ui/goal-lifecycle-orchestration.test.js.map +1 -1
  203. package/dist/ui/goal-overlay.test.js +122 -44
  204. package/dist/ui/goal-overlay.test.js.map +1 -1
  205. package/dist/ui/goal-summary.d.ts +14 -0
  206. package/dist/ui/goal-summary.d.ts.map +1 -0
  207. package/dist/ui/goal-summary.js +194 -0
  208. package/dist/ui/goal-summary.js.map +1 -0
  209. package/dist/ui/hooks/useAgentLoop.d.ts +8 -2
  210. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  211. package/dist/ui/hooks/useAgentLoop.js +20 -9
  212. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  213. package/dist/ui/hooks/useAgentLoop.test.d.ts +2 -0
  214. package/dist/ui/hooks/useAgentLoop.test.d.ts.map +1 -0
  215. package/dist/ui/hooks/useAgentLoop.test.js +8 -0
  216. package/dist/ui/hooks/useAgentLoop.test.js.map +1 -0
  217. package/dist/ui/hooks/useTerminalSize.d.ts +5 -9
  218. package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
  219. package/dist/ui/hooks/useTerminalSize.js +9 -14
  220. package/dist/ui/hooks/useTerminalSize.js.map +1 -1
  221. package/dist/ui/live-item-flush.d.ts +2 -2
  222. package/dist/ui/live-item-flush.d.ts.map +1 -1
  223. package/dist/ui/live-item-flush.js +8 -4
  224. package/dist/ui/live-item-flush.js.map +1 -1
  225. package/dist/ui/long-prompt-regression-harness.test.d.ts +2 -0
  226. package/dist/ui/long-prompt-regression-harness.test.d.ts.map +1 -0
  227. package/dist/ui/long-prompt-regression-harness.test.js +195 -0
  228. package/dist/ui/long-prompt-regression-harness.test.js.map +1 -0
  229. package/dist/ui/plan-overlay.test.js +7 -29
  230. package/dist/ui/plan-overlay.test.js.map +1 -1
  231. package/dist/ui/queued-message.test.d.ts.map +1 -1
  232. package/dist/ui/queued-message.test.js +76 -14
  233. package/dist/ui/queued-message.test.js.map +1 -1
  234. package/dist/ui/render.d.ts +21 -24
  235. package/dist/ui/render.d.ts.map +1 -1
  236. package/dist/ui/render.js +46 -28
  237. package/dist/ui/render.js.map +1 -1
  238. package/dist/ui/render.test.d.ts +2 -0
  239. package/dist/ui/render.test.d.ts.map +1 -0
  240. package/dist/ui/render.test.js +16 -0
  241. package/dist/ui/render.test.js.map +1 -0
  242. package/dist/ui/scroll-stabilization.test.js +1 -1
  243. package/dist/ui/scroll-stabilization.test.js.map +1 -1
  244. package/dist/ui/slash-command-images.test.js +79 -4
  245. package/dist/ui/slash-command-images.test.js.map +1 -1
  246. package/dist/ui/terminal-history.d.ts +26 -0
  247. package/dist/ui/terminal-history.d.ts.map +1 -0
  248. package/dist/ui/terminal-history.js +910 -0
  249. package/dist/ui/terminal-history.js.map +1 -0
  250. package/dist/ui/terminal-history.test.d.ts +2 -0
  251. package/dist/ui/terminal-history.test.d.ts.map +1 -0
  252. package/dist/ui/terminal-history.test.js +314 -0
  253. package/dist/ui/terminal-history.test.js.map +1 -0
  254. package/dist/ui/tool-group-summary.d.ts +16 -0
  255. package/dist/ui/tool-group-summary.d.ts.map +1 -0
  256. package/dist/ui/tool-group-summary.js +123 -0
  257. package/dist/ui/tool-group-summary.js.map +1 -0
  258. package/dist/ui/tui-history-parity.test.d.ts +2 -0
  259. package/dist/ui/tui-history-parity.test.d.ts.map +1 -0
  260. package/dist/ui/tui-history-parity.test.js +243 -0
  261. package/dist/ui/tui-history-parity.test.js.map +1 -0
  262. package/dist/ui/utils/assistant-stream-split.d.ts +6 -0
  263. package/dist/ui/utils/assistant-stream-split.d.ts.map +1 -0
  264. package/dist/ui/utils/assistant-stream-split.js +37 -0
  265. package/dist/ui/utils/assistant-stream-split.js.map +1 -0
  266. package/dist/ui/utils/assistant-stream-split.test.d.ts +2 -0
  267. package/dist/ui/utils/assistant-stream-split.test.d.ts.map +1 -0
  268. package/dist/ui/utils/assistant-stream-split.test.js +58 -0
  269. package/dist/ui/utils/assistant-stream-split.test.js.map +1 -0
  270. package/dist/ui/utils/latex-to-unicode.d.ts +22 -0
  271. package/dist/ui/utils/latex-to-unicode.d.ts.map +1 -0
  272. package/dist/ui/utils/latex-to-unicode.js +538 -0
  273. package/dist/ui/utils/latex-to-unicode.js.map +1 -0
  274. package/dist/ui/utils/markdown-renderer.d.ts +20 -0
  275. package/dist/ui/utils/markdown-renderer.d.ts.map +1 -0
  276. package/dist/ui/utils/markdown-renderer.js +327 -0
  277. package/dist/ui/utils/markdown-renderer.js.map +1 -0
  278. package/dist/ui/utils/markdown-table.d.ts +9 -0
  279. package/dist/ui/utils/markdown-table.d.ts.map +1 -0
  280. package/dist/ui/utils/markdown-table.js +95 -0
  281. package/dist/ui/utils/markdown-table.js.map +1 -0
  282. package/dist/ui/utils/text-utils.d.ts +8 -0
  283. package/dist/ui/utils/text-utils.d.ts.map +1 -0
  284. package/dist/ui/utils/text-utils.js +16 -0
  285. package/dist/ui/utils/text-utils.js.map +1 -0
  286. package/dist/ui/utils/token-to-ansi.js +19 -9
  287. package/dist/ui/utils/token-to-ansi.js.map +1 -1
  288. package/dist/ui/utils/user-message-display.d.ts +7 -0
  289. package/dist/ui/utils/user-message-display.d.ts.map +1 -0
  290. package/dist/ui/utils/user-message-display.js +26 -0
  291. package/dist/ui/utils/user-message-display.js.map +1 -0
  292. package/dist/utils/format.js +0 -9
  293. package/dist/utils/format.js.map +1 -1
  294. package/package.json +9 -5
  295. package/dist/tools/enter-plan.d.ts +0 -8
  296. package/dist/tools/enter-plan.d.ts.map +0 -1
  297. package/dist/tools/enter-plan.js +0 -30
  298. package/dist/tools/enter-plan.js.map +0 -1
  299. package/dist/tools/exit-plan.d.ts +0 -8
  300. package/dist/tools/exit-plan.d.ts.map +0 -1
  301. package/dist/tools/exit-plan.js +0 -36
  302. package/dist/tools/exit-plan.js.map +0 -1
  303. package/dist/tools/tasks.d.ts +0 -16
  304. package/dist/tools/tasks.d.ts.map +0 -1
  305. package/dist/tools/tasks.js +0 -133
  306. package/dist/tools/tasks.js.map +0 -1
  307. package/dist/ui/components/EyesOverlay.d.ts +0 -10
  308. package/dist/ui/components/EyesOverlay.d.ts.map +0 -1
  309. package/dist/ui/components/EyesOverlay.js +0 -220
  310. package/dist/ui/components/EyesOverlay.js.map +0 -1
  311. package/dist/ui/components/TaskOverlay.d.ts +0 -10
  312. package/dist/ui/components/TaskOverlay.d.ts.map +0 -1
  313. package/dist/ui/components/TaskOverlay.js +0 -267
  314. package/dist/ui/components/TaskOverlay.js.map +0 -1
@@ -1,8 +1,11 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { z } from "zod";
3
3
  import { log } from "../core/logger.js";
4
- import { canCompleteGoalRun, decideGoalNextAction } from "../core/goal-controller.js";
5
- import { appendGoalDecision, appendGoalEvidence, createGoalEvidence, formatGoalBlockingPrerequisiteList, formatGoalBlockingPrerequisites, getActiveGoalRun, getGoalRun, goalHasBlockingPrerequisites, loadGoalRuns, upsertGoalRun, updateGoalTask, } from "../core/goal-store.js";
4
+ import { canCompleteGoalRun, decideGoalNextAction, hasFreshGoalCompletionAudit, } from "../core/goal-controller.js";
5
+ import { runGoalPrerequisiteCheckCommand } from "../core/goal-prerequisites.js";
6
+ import { appendGoalBlockers, appendGoalDecision, appendGoalEvidence, createGoalEvidence, formatGoalBlockingPrerequisiteList, formatGoalBlockingPrerequisites, getActiveGoalRun, getGoalRun, goalHasBlockingPrerequisites, loadGoalRuns, upsertGoalRun, updateGoalTask, } from "../core/goal-store.js";
7
+ import { referencesRequiringAcknowledgement } from "../core/goal-references.js";
8
+ import { getActiveGoalMode } from "../core/runtime-mode.js";
6
9
  const PrerequisiteInput = z.object({
7
10
  id: z.string().optional().describe("Stable prerequisite id"),
8
11
  label: z.string().describe("Human-readable prerequisite label"),
@@ -51,7 +54,9 @@ const GoalsParams = z.object({
51
54
  "prerequisite",
52
55
  "task",
53
56
  "evidence",
57
+ "evidence_plan",
54
58
  "verify",
59
+ "audit",
55
60
  "status",
56
61
  "pause",
57
62
  "resume",
@@ -81,6 +86,11 @@ const GoalsParams = z.object({
81
86
  .array(EvidencePlanInput)
82
87
  .optional()
83
88
  .describe("Planned proof paths for end-to-end verification"),
89
+ evidence_plan_item_id: z.string().optional().describe("Evidence-plan item id to update"),
90
+ evidence_plan_status: z
91
+ .enum(["planned", "ready", "blocked"])
92
+ .optional()
93
+ .describe("Updated evidence-plan item status"),
84
94
  verifier_command: z.string().optional().describe("Command that verifies the goal end-to-end"),
85
95
  verifier_description: z.string().optional().describe("Natural-language verifier description"),
86
96
  task_id: z.string().optional().describe("Goal task id to update"),
@@ -116,6 +126,40 @@ function asPrerequisiteStatus(value) {
116
126
  return value;
117
127
  return "unknown";
118
128
  }
129
+ function requiresPrerequisiteCheck(status, evidence) {
130
+ return status === "unknown" || (status === "met" && !evidence?.trim());
131
+ }
132
+ function uncheckedPrerequisiteInstructions(label) {
133
+ return `Check ${label} locally and record non-secret evidence before workers can start.`;
134
+ }
135
+ async function normalizePrerequisiteInput(cwd, item) {
136
+ const requestedStatus = asPrerequisiteStatus(item.status);
137
+ const id = item.id ?? randomUUID();
138
+ if (item.check_command && requiresPrerequisiteCheck(requestedStatus, item.evidence)) {
139
+ const result = await runGoalPrerequisiteCheckCommand({ cwd, command: item.check_command });
140
+ return {
141
+ id,
142
+ label: item.label,
143
+ status: result.status,
144
+ checkCommand: item.check_command,
145
+ evidence: result.evidence,
146
+ ...(result.status === "missing" || item.instructions
147
+ ? { instructions: item.instructions ?? `Make \`${item.check_command}\` pass locally.` }
148
+ : {}),
149
+ };
150
+ }
151
+ return {
152
+ id,
153
+ label: item.label,
154
+ status: requestedStatus,
155
+ ...(item.check_command ? { checkCommand: item.check_command } : {}),
156
+ ...(item.instructions ? { instructions: item.instructions } : {}),
157
+ ...(item.evidence ? { evidence: item.evidence } : {}),
158
+ ...(requiresPrerequisiteCheck(requestedStatus, item.evidence) && !item.instructions
159
+ ? { instructions: uncheckedPrerequisiteInstructions(item.label) }
160
+ : {}),
161
+ };
162
+ }
119
163
  function asTaskStatus(value) {
120
164
  if (value === "pending" ||
121
165
  value === "running" ||
@@ -137,6 +181,11 @@ function asEvidenceKind(value) {
137
181
  }
138
182
  return "summary";
139
183
  }
184
+ function asEvidencePlanStatus(value) {
185
+ if (value === "ready" || value === "blocked" || value === "planned")
186
+ return value;
187
+ return "planned";
188
+ }
140
189
  function asEvidenceMechanism(value) {
141
190
  if (value === "command" ||
142
191
  value === "test" ||
@@ -159,6 +208,12 @@ function asVerificationStatus(value) {
159
208
  return value;
160
209
  return "unknown";
161
210
  }
211
+ function formatRunReferences(run) {
212
+ if (!run.references?.length)
213
+ return "";
214
+ const lines = run.references.map((reference) => `- ${reference.id}: ${reference.kind}; ${reference.label}${reference.value ? `; value=${reference.value}` : ""}${reference.path ? `; path=${reference.path}` : ""}`);
215
+ return `\nReferences:\n${lines.join("\n")}`;
216
+ }
162
217
  function formatRun(run) {
163
218
  const prereqs = run.prerequisites.length
164
219
  ? `${run.prerequisites.filter((item) => item.status === "met").length}/${run.prerequisites.length} prereqs met`
@@ -171,31 +226,144 @@ function formatRun(run) {
171
226
  : run.verifier?.command
172
227
  ? "verifier configured"
173
228
  : "no verifier";
229
+ const refs = run.references?.length ? `, ${run.references.length} reference(s)` : "";
230
+ const audit = run.completionAudit
231
+ ? `, final audit ${run.completionAudit.status}`
232
+ : run.verifier?.lastResult?.status === "pass"
233
+ ? ", final audit missing"
234
+ : "";
174
235
  const blocker = goalHasBlockingPrerequisites(run)
175
236
  ? `\nUser prerequisites: ${formatGoalBlockingPrerequisites(run)}`
176
237
  : "";
177
- return `[${run.status}] ${run.title} (id: ${run.id.slice(0, 8)}) — ${prereqs}, ${tasks}, ${verifier}${blocker}`;
238
+ return `[${run.status}] ${run.title} (id: ${run.id.slice(0, 8)}) — ${prereqs}, ${tasks}, ${verifier}${refs}${audit}${blocker}${formatRunReferences(run)}`;
178
239
  }
179
240
  function recoverableTaskStatus(status) {
180
241
  return status === "pending" || status === "failed";
181
242
  }
182
243
  function statusAfterTaskPatch(run, status) {
183
- if (run.status !== "failed" || !recoverableTaskStatus(status))
244
+ if ((run.status !== "failed" && run.status !== "passed") || !recoverableTaskStatus(status)) {
184
245
  return run.status;
246
+ }
185
247
  return goalHasBlockingPrerequisites(run) ? "blocked" : "ready";
186
248
  }
249
+ const SETUP_BLOCKER_PREFIX = "Goal setup incomplete:";
250
+ function referencesAcknowledged(references, fields) {
251
+ const required = referencesRequiringAcknowledgement(references ?? []);
252
+ if (required.length === 0)
253
+ return true;
254
+ const haystack = fields.join("\n").toLowerCase();
255
+ return required.every((reference) => {
256
+ const tokens = [reference.id, reference.label, reference.value, reference.path]
257
+ .filter((token) => !!token?.trim())
258
+ .map((token) => token.toLowerCase());
259
+ return tokens.some((token) => haystack.includes(token));
260
+ });
261
+ }
262
+ function hasOriginalGoalPromptReference(references) {
263
+ return (references ?? []).some((reference) => reference.id === "original-goal-prompt" &&
264
+ reference.kind === "prompt" &&
265
+ reference.content?.trim());
266
+ }
267
+ function setupBlockersForRun(run) {
268
+ const blockers = [];
269
+ const contractFields = [
270
+ run.goal ?? "",
271
+ ...run.successCriteria,
272
+ ...(run.references ?? []).map((reference) => `${reference.id} ${reference.label} ${reference.content ?? ""}`),
273
+ ...(run.evidence ?? []).map((item) => `${item.label}\n${item.path ?? ""}\n${item.content ?? ""}`),
274
+ ].join("\n");
275
+ const requiresReliabilityContract = /GOAL_PLAN/.test(contractFields);
276
+ if (requiresReliabilityContract && !hasOriginalGoalPromptReference(run.references)) {
277
+ blockers.push(`${SETUP_BLOCKER_PREFIX} durable [original-goal-prompt] reference is required.`);
278
+ }
279
+ const plannerFields = [
280
+ run.goal ?? "",
281
+ ...(run.evidence ?? []).map((item) => `${item.label}\n${item.path ?? ""}\n${item.content ?? ""}`),
282
+ ].join("\n");
283
+ if (requiresReliabilityContract &&
284
+ (!/GOAL_PLAN/.test(plannerFields) ||
285
+ !/research=/.test(plannerFields) ||
286
+ !/success=/.test(plannerFields))) {
287
+ blockers.push(`${SETUP_BLOCKER_PREFIX} durable planner GOAL_PLAN evidence/state is required.`);
288
+ }
289
+ if (run.successCriteria.length === 0)
290
+ blockers.push(`${SETUP_BLOCKER_PREFIX} success criteria are required.`);
291
+ if (run.evidencePlan.length === 0)
292
+ blockers.push(`${SETUP_BLOCKER_PREFIX} evidence_plan is required.`);
293
+ if (!run.verifier?.command)
294
+ blockers.push(`${SETUP_BLOCKER_PREFIX} verifier_command is required.`);
295
+ const referenceFields = [
296
+ ...run.successCriteria,
297
+ ...run.evidencePlan.map((item) => `${item.id} ${item.label} ${item.description} ${item.command ?? ""} ${item.path ?? ""} ${item.evidence ?? ""}`),
298
+ ...run.tasks.map((task) => `${task.title} ${task.prompt}`),
299
+ run.verifier?.description ?? "",
300
+ run.verifier?.command ?? "",
301
+ ];
302
+ if (!referencesAcknowledged(run.references, referenceFields)) {
303
+ blockers.push(`${SETUP_BLOCKER_PREFIX} every non-prompt Goal reference must be named in success criteria, task prompts, evidence_plan, or verifier metadata.`);
304
+ }
305
+ return blockers;
306
+ }
307
+ function blockersAfterSetupCheck(run, setupBlockers) {
308
+ if (run.status !== "draft")
309
+ return run.blockers;
310
+ return Array.from(new Set([
311
+ ...run.blockers.filter((blocker) => !blocker.startsWith(SETUP_BLOCKER_PREFIX)),
312
+ ...setupBlockers,
313
+ ]));
314
+ }
315
+ function statusAfterSetupCheck(run, setupBlockers) {
316
+ if (run.status !== "draft")
317
+ return run.status;
318
+ if (setupBlockers.length > 0)
319
+ return "draft";
320
+ return goalHasBlockingPrerequisites(run) ? "blocked" : "ready";
321
+ }
322
+ function validatePassAuditContract(run, summary, outputPath) {
323
+ const verifier = run.verifier?.lastResult;
324
+ if (!verifier)
325
+ return "cannot audit completion before a verifier result exists.";
326
+ if (!summary.startsWith("FINAL_AUDIT_PASS"))
327
+ return "pass audit summary must start with FINAL_AUDIT_PASS.";
328
+ if (!summary.includes(`verifier_checked_at=${verifier.checkedAt}`)) {
329
+ return `pass audit summary must include verifier_checked_at=${verifier.checkedAt}.`;
330
+ }
331
+ if (!outputPath && !summary.match(/(?:output|artifact|log|path)=\S+/)) {
332
+ return "pass audit must include output_path or an output/artifact/log/path reference in the summary.";
333
+ }
334
+ const contractFields = [
335
+ run.goal,
336
+ ...run.successCriteria,
337
+ ...(run.references ?? []).map((reference) => `${reference.id} ${reference.label} ${reference.content ?? ""}`),
338
+ ...run.evidence.map((item) => `${item.label}\n${item.path ?? ""}\n${item.content ?? ""}`),
339
+ ].join("\n");
340
+ const requiresReliabilityContract = /GOAL_PLAN/.test(contractFields);
341
+ if (requiresReliabilityContract && !summary.includes("original-goal-prompt")) {
342
+ return "pass audit summary must explicitly reference original-goal-prompt.";
343
+ }
344
+ if (requiresReliabilityContract && !summary.includes("GOAL_PLAN")) {
345
+ return "pass audit summary must explicitly reference durable GOAL_PLAN evidence.";
346
+ }
347
+ if (!referencesAcknowledged(run.references, [summary, outputPath ?? ""])) {
348
+ return "pass audit summary or output_path must explicitly reference every non-prompt Goal reference id, label, URL, or path.";
349
+ }
350
+ return undefined;
351
+ }
187
352
  async function resolveRun(cwd, id) {
188
353
  if (id)
189
354
  return getGoalRun(cwd, id);
190
355
  return getActiveGoalRun(cwd);
191
356
  }
192
- export function createGoalsTool(cwd) {
357
+ export function createGoalsTool(cwd, goalModeRef, getGoalReferences) {
193
358
  return {
194
359
  name: "goals",
195
- description: "Manage durable Goal runs for /goal and Ctrl+G workflows. Use this instead of tasks when the user wants a programmatic goal loop: define success criteria first, check prerequisites before launching workers, persist harness/diagnostics/evidence, add standalone worker tasks, and only mark the goal complete when verifier evidence proves the original objective. Do not require paid services or signups without recording a blocker and asking the user for the missing prerequisite.",
360
+ description: "Manage durable Goal runs for /goal and Ctrl+G workflows. Use this instead of tasks when the user wants a programmatic goal loop: define success criteria first, check prerequisites before launching workers, persist harness/diagnostics/evidence, add standalone worker tasks, record final completion audits, and only mark the goal complete when verifier plus final-audit evidence proves the original objective. Do not require paid services or signups without recording a blocker and asking the user for the missing prerequisite.",
196
361
  parameters: GoalsParams,
197
362
  executionMode: "sequential",
198
363
  async execute(args) {
364
+ if (getActiveGoalMode(goalModeRef) === "planner") {
365
+ return "Error: goals is restricted in Goal planner mode. Emit a compact GOAL_PLAN block only; setup creates durable Goal state.";
366
+ }
199
367
  switch (args.action) {
200
368
  case "create": {
201
369
  if (!args.title)
@@ -203,14 +371,9 @@ export function createGoalsTool(cwd) {
203
371
  if (!args.goal)
204
372
  return "Error: goal is required for create.";
205
373
  const existing = args.run_id ? await getGoalRun(cwd, args.run_id) : null;
206
- const prerequisites = args.prerequisites?.map((item) => ({
207
- id: item.id ?? randomUUID(),
208
- label: item.label,
209
- status: asPrerequisiteStatus(item.status),
210
- ...(item.check_command ? { checkCommand: item.check_command } : {}),
211
- ...(item.instructions ? { instructions: item.instructions } : {}),
212
- ...(item.evidence ? { evidence: item.evidence } : {}),
213
- }));
374
+ const prerequisites = args.prerequisites
375
+ ? await Promise.all(args.prerequisites.map((item) => normalizePrerequisiteInput(cwd, item)))
376
+ : undefined;
214
377
  const harness = args.harness?.map((item) => ({
215
378
  id: item.id ?? randomUUID(),
216
379
  label: item.label,
@@ -243,28 +406,58 @@ export function createGoalsTool(cwd) {
243
406
  const nextPrerequisites = prerequisites ?? existing?.prerequisites ?? [];
244
407
  const missingPrerequisites = formatGoalBlockingPrerequisiteList(nextPrerequisites);
245
408
  const hasBlockingPrerequisites = missingPrerequisites !== "Goal has no missing user prerequisites.";
409
+ const references = [...(getGoalReferences?.() ?? existing?.references ?? [])];
410
+ const plannerEvidence = args.summary?.includes("GOAL_PLAN")
411
+ ? [
412
+ createGoalEvidence({
413
+ kind: "summary",
414
+ label: "Planner GOAL_PLAN",
415
+ content: args.summary,
416
+ }),
417
+ ]
418
+ : undefined;
419
+ const draftProbe = {
420
+ goal: args.goal,
421
+ successCriteria: args.success_criteria ?? existing?.successCriteria ?? [],
422
+ evidencePlan: evidencePlan ?? existing?.evidencePlan ?? [],
423
+ references,
424
+ tasks: existing?.tasks ?? [],
425
+ evidence: plannerEvidence ?? existing?.evidence ?? [],
426
+ verifier,
427
+ };
428
+ const setupBlockers = setupBlockersForRun(draftProbe);
429
+ const blockers = Array.from(new Set([
430
+ ...(args.blockers ?? existing?.blockers ?? []),
431
+ ...(hasBlockingPrerequisites ? [missingPrerequisites] : []),
432
+ ...setupBlockers,
433
+ ]));
246
434
  const run = await upsertGoalRun(cwd, {
247
435
  ...(args.run_id ? { id: args.run_id } : {}),
248
436
  title: args.title,
249
437
  goal: args.goal,
250
- status: hasBlockingPrerequisites ? "blocked" : (existing?.status ?? "ready"),
251
- successCriteria: args.success_criteria ?? existing?.successCriteria ?? [],
438
+ status: setupBlockers.length > 0
439
+ ? "draft"
440
+ : hasBlockingPrerequisites
441
+ ? "blocked"
442
+ : (existing?.status ?? "ready"),
443
+ successCriteria: draftProbe.successCriteria,
252
444
  prerequisites: nextPrerequisites,
253
445
  harness: harness ?? existing?.harness ?? [],
254
- evidencePlan: evidencePlan ?? existing?.evidencePlan ?? [],
446
+ evidencePlan: draftProbe.evidencePlan,
447
+ references: draftProbe.references,
448
+ ...(plannerEvidence ? { evidence: plannerEvidence } : {}),
255
449
  ...(verifier ? { verifier } : {}),
256
- blockers: hasBlockingPrerequisites
257
- ? Array.from(new Set([...(args.blockers ?? existing?.blockers ?? []), missingPrerequisites]))
258
- : (args.blockers ?? []),
450
+ blockers,
259
451
  });
260
452
  await appendGoalDecision(cwd, run.id, {
261
453
  kind: args.run_id ? "update" : "create",
262
- reason: `criteria=${run.successCriteria.length}; prerequisites=${run.prerequisites.length}; harness=${run.harness.length}; evidence_plan=${run.evidencePlan.length}; verifier=${run.verifier?.command ? "configured" : "missing"}`,
454
+ reason: `criteria=${run.successCriteria.length}; prerequisites=${run.prerequisites.length}; harness=${run.harness.length}; evidence_plan=${run.evidencePlan.length}; references=${run.references?.length ?? 0}; verifier=${run.verifier?.command ? "configured" : "missing"}`,
263
455
  });
264
456
  log("INFO", "goals", `Goal created: ${run.title}`, { id: run.id, status: run.status });
457
+ const setupMessage = setupBlockers.length > 0 ? ` Setup blockers: ${setupBlockers.join(" ")}` : "";
265
458
  return goalHasBlockingPrerequisites(run)
266
- ? `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status}). User prerequisites: ${formatGoalBlockingPrerequisites(run)}`
267
- : `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status})`;
459
+ ? `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status}). User prerequisites: ${formatGoalBlockingPrerequisites(run)}${setupMessage}`
460
+ : `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status}).${setupMessage}`;
268
461
  }
269
462
  case "status": {
270
463
  if (args.run_id) {
@@ -288,12 +481,22 @@ export function createGoalsTool(cwd) {
288
481
  const index = prereqId
289
482
  ? prerequisites.findIndex((item) => item.id === prereqId || item.id.startsWith(prereqId))
290
483
  : -1;
484
+ const existingPrerequisite = index >= 0 ? prerequisites[index] : undefined;
291
485
  const patch = {
292
486
  id: prereqId ?? randomUUID(),
293
- label: args.prerequisite_label ?? prereqId ?? "Prerequisite",
487
+ label: args.prerequisite_label ?? existingPrerequisite?.label ?? prereqId ?? "Prerequisite",
294
488
  status: asPrerequisiteStatus(args.prerequisite_status),
295
489
  ...(args.instructions ? { instructions: args.instructions } : {}),
296
490
  ...(args.summary ? { evidence: args.summary } : {}),
491
+ ...(asPrerequisiteStatus(args.prerequisite_status) === "met" && !args.summary
492
+ ? {
493
+ instructions: args.instructions ??
494
+ uncheckedPrerequisiteInstructions(args.prerequisite_label ??
495
+ existingPrerequisite?.label ??
496
+ prereqId ??
497
+ "Prerequisite"),
498
+ }
499
+ : {}),
297
500
  };
298
501
  if (index >= 0) {
299
502
  prerequisites[index] = {
@@ -305,12 +508,17 @@ export function createGoalsTool(cwd) {
305
508
  else {
306
509
  prerequisites.push(patch);
307
510
  }
308
- const stillBlocked = goalHasBlockingPrerequisites({ ...run, prerequisites });
309
- const updated = await upsertGoalRun(cwd, {
511
+ const prerequisiteRun = {
310
512
  ...run,
311
513
  prerequisites,
312
- status: stillBlocked ? "blocked" : "ready",
313
- blockers: stillBlocked ? run.blockers : [],
514
+ status: goalHasBlockingPrerequisites({ ...run, prerequisites }) ? "blocked" : "ready",
515
+ blockers: goalHasBlockingPrerequisites({ ...run, prerequisites }) ? run.blockers : [],
516
+ };
517
+ const setupBlockers = setupBlockersForRun(prerequisiteRun);
518
+ const updated = await upsertGoalRun(cwd, {
519
+ ...prerequisiteRun,
520
+ status: statusAfterSetupCheck(prerequisiteRun, setupBlockers),
521
+ blockers: blockersAfterSetupCheck(prerequisiteRun, setupBlockers),
314
522
  });
315
523
  await appendGoalDecision(cwd, updated.id, {
316
524
  kind: "prerequisites",
@@ -333,6 +541,10 @@ export function createGoalsTool(cwd) {
333
541
  if (!taskExisted && (!args.task_title || !args.task_prompt)) {
334
542
  return "Error: task_title and task_prompt are required when adding a task.";
335
543
  }
544
+ if (!taskExisted &&
545
+ !referencesAcknowledged(run.references, [args.task_title ?? "", args.task_prompt ?? ""])) {
546
+ return "Error: task_prompt must explicitly include each non-prompt Goal reference id, label, URL, or path so workers cannot silently ignore the user's references.";
547
+ }
336
548
  const taskStatus = asTaskStatus(args.task_status);
337
549
  const updated = await updateGoalTask(cwd, run.id, taskId, {
338
550
  id: taskId,
@@ -344,10 +556,18 @@ export function createGoalsTool(cwd) {
344
556
  ...(args.summary ? { lastSummary: args.summary } : {}),
345
557
  });
346
558
  const recovered = updated
347
- ? await upsertGoalRun(updated.projectPath, {
348
- ...updated,
349
- status: statusAfterTaskPatch(updated, taskStatus),
350
- })
559
+ ? await (async () => {
560
+ const taskPatchedRun = {
561
+ ...updated,
562
+ status: statusAfterTaskPatch(updated, taskStatus),
563
+ };
564
+ const setupBlockers = setupBlockersForRun(taskPatchedRun);
565
+ return upsertGoalRun(updated.projectPath, {
566
+ ...taskPatchedRun,
567
+ status: statusAfterSetupCheck(taskPatchedRun, setupBlockers),
568
+ blockers: blockersAfterSetupCheck(taskPatchedRun, setupBlockers),
569
+ });
570
+ })()
351
571
  : null;
352
572
  if (!recovered)
353
573
  return `Error: no task found matching id "${taskId}".`;
@@ -372,6 +592,48 @@ export function createGoalsTool(cwd) {
372
592
  return "Error: failed to append evidence.";
373
593
  return `Evidence added to "${updated.title}".`;
374
594
  }
595
+ case "evidence_plan": {
596
+ const run = await resolveRun(cwd, args.run_id);
597
+ if (!run)
598
+ return "Error: no active goal run found.";
599
+ const evidencePlanItemId = args.evidence_plan_item_id;
600
+ if (!evidencePlanItemId)
601
+ return "Error: evidence_plan_item_id is required.";
602
+ const evidencePlan = [...run.evidencePlan];
603
+ const index = evidencePlan.findIndex((item) => item.id === evidencePlanItemId || item.id.startsWith(evidencePlanItemId));
604
+ if (index < 0) {
605
+ return `Error: no evidence-plan item found matching id "${args.evidence_plan_item_id}".`;
606
+ }
607
+ const existing = evidencePlan[index];
608
+ const status = asEvidencePlanStatus(args.evidence_plan_status);
609
+ evidencePlan[index] = {
610
+ ...existing,
611
+ status,
612
+ ...(args.instructions ? { instructions: args.instructions } : {}),
613
+ ...(args.evidence_content || args.summary
614
+ ? { evidence: args.evidence_content ?? args.summary }
615
+ : {}),
616
+ ...(args.evidence_path ? { path: args.evidence_path } : {}),
617
+ };
618
+ const canRecoverBlockedRun = run.status === "blocked" && status === "ready" && !goalHasBlockingPrerequisites(run);
619
+ const evidencePlanRun = {
620
+ ...run,
621
+ evidencePlan,
622
+ status: canRecoverBlockedRun ? "ready" : run.status,
623
+ blockers: canRecoverBlockedRun ? [] : run.blockers,
624
+ };
625
+ const setupBlockers = setupBlockersForRun(evidencePlanRun);
626
+ const updated = await upsertGoalRun(cwd, {
627
+ ...evidencePlanRun,
628
+ status: statusAfterSetupCheck(evidencePlanRun, setupBlockers),
629
+ blockers: blockersAfterSetupCheck(evidencePlanRun, setupBlockers),
630
+ });
631
+ await appendGoalDecision(cwd, updated.id, {
632
+ kind: "evidence_plan",
633
+ reason: `Evidence-plan item ${existing.label} is ${status}.`,
634
+ });
635
+ return `Evidence-plan item updated for "${updated.title}": "${existing.label}" is ${status}.`;
636
+ }
375
637
  case "verify": {
376
638
  const run = await resolveRun(cwd, args.run_id);
377
639
  if (!run)
@@ -395,6 +657,17 @@ export function createGoalsTool(cwd) {
395
657
  : {}),
396
658
  lastResult: result,
397
659
  },
660
+ ...(result.status === "pass"
661
+ ? {
662
+ completionAudit: {
663
+ status: "unknown",
664
+ summary: "Final completion audit pending for latest verifier result.",
665
+ checkedAt: result.checkedAt,
666
+ verifierCheckedAt: result.checkedAt,
667
+ ...(result.outputPath ? { outputPath: result.outputPath } : {}),
668
+ },
669
+ }
670
+ : {}),
398
671
  evidence: [
399
672
  ...run.evidence,
400
673
  createGoalEvidence({
@@ -424,6 +697,61 @@ export function createGoalsTool(cwd) {
424
697
  });
425
698
  return `Verifier recorded for "${updated.title}": ${result.status}.`;
426
699
  }
700
+ case "audit": {
701
+ const run = await resolveRun(cwd, args.run_id);
702
+ if (!run)
703
+ return "Error: no active goal run found.";
704
+ const verifierResult = run.verifier?.lastResult;
705
+ if (!verifierResult || verifierResult.status !== "pass") {
706
+ return "Error: cannot audit completion before a passing verifier result exists.";
707
+ }
708
+ const auditStatus = asVerificationStatus(args.verification_status);
709
+ const auditSummary = args.summary ?? "Final completion audit recorded.";
710
+ const auditOutputPath = args.output_path ?? verifierResult.outputPath;
711
+ if (auditStatus === "pass") {
712
+ const contractError = validatePassAuditContract(run, auditSummary, auditOutputPath);
713
+ if (contractError)
714
+ return `Error: invalid final completion audit pass contract: ${contractError}`;
715
+ }
716
+ const completionAudit = {
717
+ status: auditStatus,
718
+ summary: auditSummary,
719
+ checkedAt: new Date().toISOString(),
720
+ verifierCheckedAt: verifierResult.checkedAt,
721
+ ...(auditOutputPath ? { outputPath: auditOutputPath } : {}),
722
+ };
723
+ const runWithAudit = {
724
+ ...run,
725
+ completionAudit,
726
+ evidence: [
727
+ ...run.evidence,
728
+ createGoalEvidence({
729
+ kind: "summary",
730
+ label: `Final completion audit ${completionAudit.status}`,
731
+ content: completionAudit.summary,
732
+ ...(completionAudit.outputPath ? { path: completionAudit.outputPath } : {}),
733
+ }),
734
+ ],
735
+ };
736
+ const auditCheck = hasFreshGoalCompletionAudit(runWithAudit);
737
+ const completion = canCompleteGoalRun(runWithAudit);
738
+ const updated = await upsertGoalRun(cwd, {
739
+ ...runWithAudit,
740
+ status: completionAudit.status === "pass" && auditCheck.ok && completion.ok
741
+ ? "passed"
742
+ : goalHasBlockingPrerequisites(runWithAudit)
743
+ ? "blocked"
744
+ : "ready",
745
+ blockers: completionAudit.status === "pass" && auditCheck.ok ? [] : run.blockers,
746
+ activeWorkerId: undefined,
747
+ });
748
+ await appendGoalDecision(cwd, updated.id, {
749
+ kind: "completion_audit",
750
+ reason: auditCheck.reason,
751
+ content: `status=${completionAudit.status}; verifierCheckedAt=${completionAudit.verifierCheckedAt ?? ""}; outputPath=${completionAudit.outputPath ?? ""}`,
752
+ });
753
+ return `Completion audit recorded for "${updated.title}": ${completionAudit.status}.`;
754
+ }
427
755
  case "pause":
428
756
  case "resume":
429
757
  case "complete": {
@@ -431,8 +759,12 @@ export function createGoalsTool(cwd) {
431
759
  if (!run)
432
760
  return "Error: no active goal run found.";
433
761
  let status;
434
- if (args.action === "pause")
762
+ if (args.action === "pause") {
763
+ if (run.activeWorkerId || run.tasks.some((task) => task.status === "running")) {
764
+ return `Error: cannot pause goal while worker ${run.activeWorkerId ?? "task"} is active. Stop the worker first or wait for it to finish.`;
765
+ }
435
766
  status = "paused";
767
+ }
436
768
  else if (args.action === "resume") {
437
769
  const missing = goalHasBlockingPrerequisites(run)
438
770
  ? formatGoalBlockingPrerequisites(run)
@@ -441,7 +773,7 @@ export function createGoalsTool(cwd) {
441
773
  const updated = await upsertGoalRun(cwd, {
442
774
  ...run,
443
775
  status: "blocked",
444
- blockers: Array.from(new Set([...run.blockers, missing])),
776
+ blockers: appendGoalBlockers(run.blockers, missing),
445
777
  evidence: [
446
778
  ...run.evidence,
447
779
  createGoalEvidence({
@@ -469,7 +801,25 @@ export function createGoalsTool(cwd) {
469
801
  ],
470
802
  };
471
803
  const decision = decideGoalNextAction(resumed);
472
- const updated = await upsertGoalRun(cwd, resumed);
804
+ const blockedReason = decision.kind === "blocked" ? decision.reason : undefined;
805
+ const updated = await upsertGoalRun(cwd, {
806
+ ...resumed,
807
+ ...(blockedReason
808
+ ? {
809
+ status: "blocked",
810
+ continueRequestedAt: undefined,
811
+ blockers: appendGoalBlockers(run.blockers, blockedReason),
812
+ evidence: [
813
+ ...resumed.evidence,
814
+ createGoalEvidence({
815
+ kind: "summary",
816
+ label: "Goal resume blocked",
817
+ content: blockedReason,
818
+ }),
819
+ ],
820
+ }
821
+ : {}),
822
+ });
473
823
  await appendGoalDecision(cwd, updated.id, {
474
824
  kind: "resume",
475
825
  reason: decision.kind === "wait" ||