@caupulican/pi-adaptative 0.81.39 → 0.81.40

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 (667) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +2 -0
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +2 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +2 -0
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +3 -0
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +9 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +290 -107
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
  12. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +357 -122
  13. package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +2 -2
  14. package/dist/cli/args.d.ts +2 -0
  15. package/dist/cli/args.d.ts.map +1 -1
  16. package/dist/cli/args.js +9 -0
  17. package/dist/cli/args.js.map +1 -1
  18. package/dist/core/agent-directory-layout.d.ts +15 -0
  19. package/dist/core/agent-directory-layout.d.ts.map +1 -0
  20. package/dist/core/agent-directory-layout.js +72 -0
  21. package/dist/core/agent-directory-layout.js.map +1 -0
  22. package/dist/core/agent-paths.d.ts +19 -2
  23. package/dist/core/agent-paths.d.ts.map +1 -1
  24. package/dist/core/agent-paths.js +67 -4
  25. package/dist/core/agent-paths.js.map +1 -1
  26. package/dist/core/agent-session-runtime.d.ts +52 -8
  27. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  28. package/dist/core/agent-session-runtime.js +397 -79
  29. package/dist/core/agent-session-runtime.js.map +1 -1
  30. package/dist/core/agent-session-services.d.ts +1 -0
  31. package/dist/core/agent-session-services.d.ts.map +1 -1
  32. package/dist/core/agent-session-services.js +1 -0
  33. package/dist/core/agent-session-services.js.map +1 -1
  34. package/dist/core/agent-session.d.ts +71 -136
  35. package/dist/core/agent-session.d.ts.map +1 -1
  36. package/dist/core/agent-session.js +477 -1318
  37. package/dist/core/agent-session.js.map +1 -1
  38. package/dist/core/autonomy/approval-gate.d.ts +3 -2
  39. package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
  40. package/dist/core/autonomy/approval-gate.js +6 -28
  41. package/dist/core/autonomy/approval-gate.js.map +1 -1
  42. package/dist/core/autonomy/bounded-completion.d.ts +1 -1
  43. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  44. package/dist/core/autonomy/bounded-completion.js +1 -1
  45. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  46. package/dist/core/autonomy/contracts.d.ts +20 -12
  47. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  48. package/dist/core/autonomy/contracts.js.map +1 -1
  49. package/dist/core/autonomy/foreground-envelope.d.ts +8 -2
  50. package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -1
  51. package/dist/core/autonomy/foreground-envelope.js +8 -25
  52. package/dist/core/autonomy/foreground-envelope.js.map +1 -1
  53. package/dist/core/autonomy/gates.d.ts.map +1 -1
  54. package/dist/core/autonomy/gates.js +8 -10
  55. package/dist/core/autonomy/gates.js.map +1 -1
  56. package/dist/core/autonomy/lane-private-paths.d.ts +2 -0
  57. package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -0
  58. package/dist/core/autonomy/lane-private-paths.js +16 -0
  59. package/dist/core/autonomy/lane-private-paths.js.map +1 -0
  60. package/dist/core/autonomy/lane-tool-surface.d.ts +10 -0
  61. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  62. package/dist/core/autonomy/lane-tool-surface.js +46 -8
  63. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  64. package/dist/core/autonomy/lane-tracker.d.ts +14 -0
  65. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  66. package/dist/core/autonomy/lane-tracker.js +38 -0
  67. package/dist/core/autonomy/lane-tracker.js.map +1 -1
  68. package/dist/core/autonomy/risk-assessment.d.ts +1 -2
  69. package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
  70. package/dist/core/autonomy/risk-assessment.js +1 -123
  71. package/dist/core/autonomy/risk-assessment.js.map +1 -1
  72. package/dist/core/autonomy/session-lane-record.d.ts +4 -4
  73. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
  74. package/dist/core/autonomy/session-lane-record.js +16 -29
  75. package/dist/core/autonomy/session-lane-record.js.map +1 -1
  76. package/dist/core/autonomy/telemetry-events.d.ts +1 -1
  77. package/dist/core/autonomy/telemetry-events.d.ts.map +1 -1
  78. package/dist/core/autonomy/telemetry-events.js +1 -1
  79. package/dist/core/autonomy/telemetry-events.js.map +1 -1
  80. package/dist/core/autonomy-telemetry.d.ts +7 -7
  81. package/dist/core/autonomy-telemetry.d.ts.map +1 -1
  82. package/dist/core/autonomy-telemetry.js +9 -9
  83. package/dist/core/autonomy-telemetry.js.map +1 -1
  84. package/dist/core/background-lane-controller.d.ts +54 -236
  85. package/dist/core/background-lane-controller.d.ts.map +1 -1
  86. package/dist/core/background-lane-controller.js +140 -1273
  87. package/dist/core/background-lane-controller.js.map +1 -1
  88. package/dist/core/capability-contract.d.ts +4 -0
  89. package/dist/core/capability-contract.d.ts.map +1 -0
  90. package/dist/core/capability-contract.js +28 -0
  91. package/dist/core/capability-contract.js.map +1 -0
  92. package/dist/core/compaction-controller.d.ts +90 -0
  93. package/dist/core/compaction-controller.d.ts.map +1 -0
  94. package/dist/core/compaction-controller.js +452 -0
  95. package/dist/core/compaction-controller.js.map +1 -0
  96. package/dist/core/compaction-support.d.ts +12 -11
  97. package/dist/core/compaction-support.d.ts.map +1 -1
  98. package/dist/core/compaction-support.js.map +1 -1
  99. package/dist/core/context/context-artifacts.d.ts +6 -2
  100. package/dist/core/context/context-artifacts.d.ts.map +1 -1
  101. package/dist/core/context/context-artifacts.js +34 -2
  102. package/dist/core/context/context-artifacts.js.map +1 -1
  103. package/dist/core/context/context-store-retention.d.ts +8 -2
  104. package/dist/core/context/context-store-retention.d.ts.map +1 -1
  105. package/dist/core/context/context-store-retention.js +158 -35
  106. package/dist/core/context/context-store-retention.js.map +1 -1
  107. package/dist/core/context/okf-memory.d.ts.map +1 -1
  108. package/dist/core/context/okf-memory.js +9 -11
  109. package/dist/core/context/okf-memory.js.map +1 -1
  110. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
  111. package/dist/core/context/sqlite-runtime-index.js +6 -8
  112. package/dist/core/context/sqlite-runtime-index.js.map +1 -1
  113. package/dist/core/context-gc.d.ts +3 -0
  114. package/dist/core/context-gc.d.ts.map +1 -1
  115. package/dist/core/context-gc.js +10 -5
  116. package/dist/core/context-gc.js.map +1 -1
  117. package/dist/core/context-pipeline.d.ts.map +1 -1
  118. package/dist/core/context-pipeline.js +9 -4
  119. package/dist/core/context-pipeline.js.map +1 -1
  120. package/dist/core/default-tool-surface.d.ts.map +1 -1
  121. package/dist/core/default-tool-surface.js +1 -0
  122. package/dist/core/default-tool-surface.js.map +1 -1
  123. package/dist/core/delegation/managed-lane-controller.d.ts +34 -0
  124. package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -0
  125. package/dist/core/delegation/managed-lane-controller.js +217 -0
  126. package/dist/core/delegation/managed-lane-controller.js.map +1 -0
  127. package/dist/core/delegation/session-worker-claim.d.ts +44 -0
  128. package/dist/core/delegation/session-worker-claim.d.ts.map +1 -0
  129. package/dist/core/delegation/session-worker-claim.js +98 -0
  130. package/dist/core/delegation/session-worker-claim.js.map +1 -0
  131. package/dist/core/delegation/worker-actions.d.ts +7 -5
  132. package/dist/core/delegation/worker-actions.d.ts.map +1 -1
  133. package/dist/core/delegation/worker-actions.js +20 -4
  134. package/dist/core/delegation/worker-actions.js.map +1 -1
  135. package/dist/core/delegation/{worker-result.d.ts → worker-claim.d.ts} +13 -13
  136. package/dist/core/delegation/worker-claim.d.ts.map +1 -0
  137. package/dist/core/delegation/{worker-result.js → worker-claim.js} +61 -51
  138. package/dist/core/delegation/worker-claim.js.map +1 -0
  139. package/dist/core/delegation/worker-delegation-controller.d.ts +110 -0
  140. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -0
  141. package/dist/core/delegation/worker-delegation-controller.js +861 -0
  142. package/dist/core/delegation/worker-delegation-controller.js.map +1 -0
  143. package/dist/core/delegation/worker-delegation-request.d.ts +11 -0
  144. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -0
  145. package/dist/core/delegation/worker-delegation-request.js +2 -0
  146. package/dist/core/delegation/worker-delegation-request.js.map +1 -0
  147. package/dist/core/delegation/worker-dispatch-scheduler.d.ts +40 -0
  148. package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -0
  149. package/dist/core/delegation/worker-dispatch-scheduler.js +93 -0
  150. package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -0
  151. package/dist/core/delegation/worker-execution-policy.d.ts +62 -0
  152. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -0
  153. package/dist/core/delegation/worker-execution-policy.js +160 -0
  154. package/dist/core/delegation/worker-execution-policy.js.map +1 -0
  155. package/dist/core/delegation/worker-lane-projection.d.ts +14 -0
  156. package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -0
  157. package/dist/core/delegation/worker-lane-projection.js +100 -0
  158. package/dist/core/delegation/worker-lane-projection.js.map +1 -0
  159. package/dist/core/delegation/worker-lifecycle.d.ts +97 -0
  160. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -0
  161. package/dist/core/delegation/worker-lifecycle.js +339 -0
  162. package/dist/core/delegation/worker-lifecycle.js.map +1 -0
  163. package/dist/core/delegation/worker-notification-coordinator.d.ts +36 -0
  164. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -0
  165. package/dist/core/delegation/worker-notification-coordinator.js +90 -0
  166. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -0
  167. package/dist/core/delegation/worker-profile-resolver.d.ts +55 -0
  168. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -0
  169. package/dist/core/delegation/worker-profile-resolver.js +113 -0
  170. package/dist/core/delegation/worker-profile-resolver.js.map +1 -0
  171. package/dist/core/delegation/worker-runner.d.ts +25 -14
  172. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  173. package/dist/core/delegation/worker-runner.js +122 -53
  174. package/dist/core/delegation/worker-runner.js.map +1 -1
  175. package/dist/core/delegation/worker-task-label.d.ts +3 -0
  176. package/dist/core/delegation/worker-task-label.d.ts.map +1 -0
  177. package/dist/core/delegation/worker-task-label.js +11 -0
  178. package/dist/core/delegation/worker-task-label.js.map +1 -0
  179. package/dist/core/doctor.d.ts +8 -0
  180. package/dist/core/doctor.d.ts.map +1 -1
  181. package/dist/core/doctor.js +32 -1
  182. package/dist/core/doctor.js.map +1 -1
  183. package/dist/core/extensions/index.d.ts +1 -1
  184. package/dist/core/extensions/index.d.ts.map +1 -1
  185. package/dist/core/extensions/index.js.map +1 -1
  186. package/dist/core/extensions/loader.d.ts +5 -1
  187. package/dist/core/extensions/loader.d.ts.map +1 -1
  188. package/dist/core/extensions/loader.js +50 -15
  189. package/dist/core/extensions/loader.js.map +1 -1
  190. package/dist/core/extensions/runner.d.ts.map +1 -1
  191. package/dist/core/extensions/runner.js +6 -0
  192. package/dist/core/extensions/runner.js.map +1 -1
  193. package/dist/core/extensions/storage.d.ts +8 -0
  194. package/dist/core/extensions/storage.d.ts.map +1 -0
  195. package/dist/core/extensions/storage.js +28 -0
  196. package/dist/core/extensions/storage.js.map +1 -0
  197. package/dist/core/extensions/types.d.ts +70 -21
  198. package/dist/core/extensions/types.d.ts.map +1 -1
  199. package/dist/core/extensions/types.js.map +1 -1
  200. package/dist/core/failure-corpus.d.ts +1 -15
  201. package/dist/core/failure-corpus.d.ts.map +1 -1
  202. package/dist/core/failure-corpus.js +9 -37
  203. package/dist/core/failure-corpus.js.map +1 -1
  204. package/dist/core/foreground-recovery-controller.d.ts +52 -0
  205. package/dist/core/foreground-recovery-controller.d.ts.map +1 -0
  206. package/dist/core/foreground-recovery-controller.js +111 -0
  207. package/dist/core/foreground-recovery-controller.js.map +1 -0
  208. package/dist/core/gateways/channel-provider.d.ts +3 -0
  209. package/dist/core/gateways/channel-provider.d.ts.map +1 -1
  210. package/dist/core/gateways/channel-provider.js +31 -6
  211. package/dist/core/gateways/channel-provider.js.map +1 -1
  212. package/dist/core/goals/goal-acceptance.d.ts +11 -0
  213. package/dist/core/goals/goal-acceptance.d.ts.map +1 -0
  214. package/dist/core/goals/goal-acceptance.js +25 -0
  215. package/dist/core/goals/goal-acceptance.js.map +1 -0
  216. package/dist/core/goals/goal-auto-continue-controller.d.ts +27 -0
  217. package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -0
  218. package/dist/core/goals/goal-auto-continue-controller.js +93 -0
  219. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -0
  220. package/dist/core/goals/goal-continuation-controller.d.ts +1 -1
  221. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  222. package/dist/core/goals/goal-continuation-controller.js +10 -0
  223. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  224. package/dist/core/goals/goal-continuation-prompt.d.ts +1 -1
  225. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  226. package/dist/core/goals/goal-continuation-prompt.js +6 -6
  227. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  228. package/dist/core/goals/goal-lifecycle.d.ts +20 -0
  229. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -0
  230. package/dist/core/goals/goal-lifecycle.js +17 -0
  231. package/dist/core/goals/goal-lifecycle.js.map +1 -0
  232. package/dist/core/goals/goal-runtime-snapshot.d.ts +11 -9
  233. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
  234. package/dist/core/goals/goal-runtime-snapshot.js +10 -8
  235. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
  236. package/dist/core/goals/goal-state.d.ts +1 -0
  237. package/dist/core/goals/goal-state.d.ts.map +1 -1
  238. package/dist/core/goals/goal-state.js +7 -10
  239. package/dist/core/goals/goal-state.js.map +1 -1
  240. package/dist/core/goals/goal-tool-core.d.ts +8 -6
  241. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  242. package/dist/core/goals/goal-tool-core.js +11 -41
  243. package/dist/core/goals/goal-tool-core.js.map +1 -1
  244. package/dist/core/goals/session-goal-state.d.ts +2 -4
  245. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  246. package/dist/core/goals/session-goal-state.js +10 -33
  247. package/dist/core/goals/session-goal-state.js.map +1 -1
  248. package/dist/core/human-input.d.ts +100 -0
  249. package/dist/core/human-input.d.ts.map +1 -0
  250. package/dist/core/human-input.js +362 -0
  251. package/dist/core/human-input.js.map +1 -0
  252. package/dist/core/index.d.ts +9 -1
  253. package/dist/core/index.d.ts.map +1 -1
  254. package/dist/core/index.js +9 -1
  255. package/dist/core/index.js.map +1 -1
  256. package/dist/core/{telemetry.d.ts → install-telemetry.d.ts} +1 -1
  257. package/dist/core/install-telemetry.d.ts.map +1 -0
  258. package/dist/core/{telemetry.js → install-telemetry.js} +1 -1
  259. package/dist/core/install-telemetry.js.map +1 -0
  260. package/dist/core/keybindings.d.ts +17 -1
  261. package/dist/core/keybindings.d.ts.map +1 -1
  262. package/dist/core/keybindings.js +24 -6
  263. package/dist/core/keybindings.js.map +1 -1
  264. package/dist/core/learning/learning-audit.d.ts +2 -4
  265. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  266. package/dist/core/learning/learning-audit.js +9 -29
  267. package/dist/core/learning/learning-audit.js.map +1 -1
  268. package/dist/core/learning/learning-gate.d.ts.map +1 -1
  269. package/dist/core/learning/learning-gate.js +1 -6
  270. package/dist/core/learning/learning-gate.js.map +1 -1
  271. package/dist/core/learning/session-learning-decision.d.ts +2 -4
  272. package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
  273. package/dist/core/learning/session-learning-decision.js +9 -29
  274. package/dist/core/learning/session-learning-decision.js.map +1 -1
  275. package/dist/core/memory-controller.d.ts.map +1 -1
  276. package/dist/core/memory-controller.js +4 -4
  277. package/dist/core/memory-controller.js.map +1 -1
  278. package/dist/core/model-capability.d.ts.map +1 -1
  279. package/dist/core/model-capability.js +1 -0
  280. package/dist/core/model-capability.js.map +1 -1
  281. package/dist/core/model-resolver.d.ts +1 -1
  282. package/dist/core/model-resolver.d.ts.map +1 -1
  283. package/dist/core/model-resolver.js +6 -9
  284. package/dist/core/model-resolver.js.map +1 -1
  285. package/dist/core/model-router/intent-classifier.d.ts +1 -4
  286. package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
  287. package/dist/core/model-router/intent-classifier.js +1 -156
  288. package/dist/core/model-router/intent-classifier.js.map +1 -1
  289. package/dist/core/model-router-controller.d.ts.map +1 -1
  290. package/dist/core/model-router-controller.js +2 -2
  291. package/dist/core/model-router-controller.js.map +1 -1
  292. package/dist/core/model-selection-controller.d.ts +4 -4
  293. package/dist/core/model-selection-controller.d.ts.map +1 -1
  294. package/dist/core/model-selection-controller.js.map +1 -1
  295. package/dist/core/model-tool-protocol.d.ts +23 -0
  296. package/dist/core/model-tool-protocol.d.ts.map +1 -0
  297. package/dist/core/model-tool-protocol.js +43 -0
  298. package/dist/core/model-tool-protocol.js.map +1 -0
  299. package/dist/core/models/adaptation-store.d.ts +4 -6
  300. package/dist/core/models/adaptation-store.d.ts.map +1 -1
  301. package/dist/core/models/adaptation-store.js +95 -83
  302. package/dist/core/models/adaptation-store.js.map +1 -1
  303. package/dist/core/models/fitness-store.d.ts +2 -12
  304. package/dist/core/models/fitness-store.d.ts.map +1 -1
  305. package/dist/core/models/fitness-store.js +84 -57
  306. package/dist/core/models/fitness-store.js.map +1 -1
  307. package/dist/core/models/host-state-store.d.ts +34 -0
  308. package/dist/core/models/host-state-store.d.ts.map +1 -0
  309. package/dist/core/models/host-state-store.js +86 -0
  310. package/dist/core/models/host-state-store.js.map +1 -0
  311. package/dist/core/orchestration/agent-resume.d.ts +24 -0
  312. package/dist/core/orchestration/agent-resume.d.ts.map +1 -0
  313. package/dist/core/orchestration/agent-resume.js +90 -0
  314. package/dist/core/orchestration/agent-resume.js.map +1 -0
  315. package/dist/core/orchestration/capability-gateway.d.ts +61 -0
  316. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -0
  317. package/dist/core/orchestration/capability-gateway.js +152 -0
  318. package/dist/core/orchestration/capability-gateway.js.map +1 -0
  319. package/dist/core/orchestration/contracts.d.ts +343 -0
  320. package/dist/core/orchestration/contracts.d.ts.map +1 -0
  321. package/dist/core/orchestration/contracts.js +135 -0
  322. package/dist/core/orchestration/contracts.js.map +1 -0
  323. package/dist/core/orchestration/delegation-ledger.d.ts +56 -0
  324. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -0
  325. package/dist/core/orchestration/delegation-ledger.js +197 -0
  326. package/dist/core/orchestration/delegation-ledger.js.map +1 -0
  327. package/dist/core/orchestration/event-store.d.ts +83 -0
  328. package/dist/core/orchestration/event-store.d.ts.map +1 -0
  329. package/dist/core/orchestration/event-store.js +560 -0
  330. package/dist/core/orchestration/event-store.js.map +1 -0
  331. package/dist/core/orchestration/lane-tool-manifests.d.ts +9 -0
  332. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -0
  333. package/dist/core/orchestration/lane-tool-manifests.js +37 -0
  334. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -0
  335. package/dist/core/orchestration/model-binding.d.ts +15 -0
  336. package/dist/core/orchestration/model-binding.d.ts.map +1 -0
  337. package/dist/core/orchestration/model-binding.js +29 -0
  338. package/dist/core/orchestration/model-binding.js.map +1 -0
  339. package/dist/core/orchestration/policy-compiler.d.ts +49 -0
  340. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -0
  341. package/dist/core/orchestration/policy-compiler.js +191 -0
  342. package/dist/core/orchestration/policy-compiler.js.map +1 -0
  343. package/dist/core/orchestration/policy-gate.d.ts +18 -0
  344. package/dist/core/orchestration/policy-gate.d.ts.map +1 -0
  345. package/dist/core/orchestration/policy-gate.js +24 -0
  346. package/dist/core/orchestration/policy-gate.js.map +1 -0
  347. package/dist/core/orchestration/profile-registry.d.ts +51 -0
  348. package/dist/core/orchestration/profile-registry.d.ts.map +1 -0
  349. package/dist/core/orchestration/profile-registry.js +393 -0
  350. package/dist/core/orchestration/profile-registry.js.map +1 -0
  351. package/dist/core/orchestration/profile-store.d.ts +31 -0
  352. package/dist/core/orchestration/profile-store.d.ts.map +1 -0
  353. package/dist/core/orchestration/profile-store.js +136 -0
  354. package/dist/core/orchestration/profile-store.js.map +1 -0
  355. package/dist/core/orchestration/risk-budget.d.ts +9 -0
  356. package/dist/core/orchestration/risk-budget.d.ts.map +1 -0
  357. package/dist/core/orchestration/risk-budget.js +48 -0
  358. package/dist/core/orchestration/risk-budget.js.map +1 -0
  359. package/dist/core/orchestration/task-runtime.d.ts +168 -0
  360. package/dist/core/orchestration/task-runtime.d.ts.map +1 -0
  361. package/dist/core/orchestration/task-runtime.js +1600 -0
  362. package/dist/core/orchestration/task-runtime.js.map +1 -0
  363. package/dist/core/orchestration/work-state-projection.d.ts +32 -0
  364. package/dist/core/orchestration/work-state-projection.d.ts.map +1 -0
  365. package/dist/core/orchestration/work-state-projection.js +116 -0
  366. package/dist/core/orchestration/work-state-projection.js.map +1 -0
  367. package/dist/core/orchestration/worker-execution-contract.d.ts +21 -0
  368. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -0
  369. package/dist/core/orchestration/worker-execution-contract.js +179 -0
  370. package/dist/core/orchestration/worker-execution-contract.js.map +1 -0
  371. package/dist/core/orchestration/worker-result-adapter.d.ts +21 -0
  372. package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -0
  373. package/dist/core/orchestration/worker-result-adapter.js +109 -0
  374. package/dist/core/orchestration/worker-result-adapter.js.map +1 -0
  375. package/dist/core/process-identity.d.ts +11 -0
  376. package/dist/core/process-identity.d.ts.map +1 -0
  377. package/dist/core/process-identity.js +26 -0
  378. package/dist/core/process-identity.js.map +1 -0
  379. package/dist/core/process-matrix/codes.d.ts +14 -3
  380. package/dist/core/process-matrix/codes.d.ts.map +1 -1
  381. package/dist/core/process-matrix/codes.js.map +1 -1
  382. package/dist/core/process-matrix/resume-launcher.d.ts +26 -0
  383. package/dist/core/process-matrix/resume-launcher.d.ts.map +1 -0
  384. package/dist/core/process-matrix/resume-launcher.js +62 -0
  385. package/dist/core/process-matrix/resume-launcher.js.map +1 -0
  386. package/dist/core/process-matrix/runtime.d.ts +37 -22
  387. package/dist/core/process-matrix/runtime.d.ts.map +1 -1
  388. package/dist/core/process-matrix/runtime.js +399 -76
  389. package/dist/core/process-matrix/runtime.js.map +1 -1
  390. package/dist/core/process-matrix/store.d.ts +5 -2
  391. package/dist/core/process-matrix/store.d.ts.map +1 -1
  392. package/dist/core/process-matrix/store.js +123 -14
  393. package/dist/core/process-matrix/store.js.map +1 -1
  394. package/dist/core/process-matrix/supervisor.d.ts +10 -7
  395. package/dist/core/process-matrix/supervisor.d.ts.map +1 -1
  396. package/dist/core/process-matrix/supervisor.js +45 -14
  397. package/dist/core/process-matrix/supervisor.js.map +1 -1
  398. package/dist/core/profile-registry.d.ts.map +1 -1
  399. package/dist/core/profile-registry.js +6 -8
  400. package/dist/core/profile-registry.js.map +1 -1
  401. package/dist/core/reflection-controller.d.ts +4 -4
  402. package/dist/core/reflection-controller.d.ts.map +1 -1
  403. package/dist/core/reflection-controller.js +2 -1
  404. package/dist/core/reflection-controller.js.map +1 -1
  405. package/dist/core/reload-blockers.d.ts.map +1 -1
  406. package/dist/core/reload-blockers.js +6 -8
  407. package/dist/core/reload-blockers.js.map +1 -1
  408. package/dist/core/research/evidence-bundle.d.ts.map +1 -1
  409. package/dist/core/research/evidence-bundle.js +1 -6
  410. package/dist/core/research/evidence-bundle.js.map +1 -1
  411. package/dist/core/research/lane-model-resolver.d.ts +33 -0
  412. package/dist/core/research/lane-model-resolver.d.ts.map +1 -0
  413. package/dist/core/research/lane-model-resolver.js +65 -0
  414. package/dist/core/research/lane-model-resolver.js.map +1 -0
  415. package/dist/core/research/model-fitness-controller.d.ts +38 -0
  416. package/dist/core/research/model-fitness-controller.d.ts.map +1 -0
  417. package/dist/core/research/model-fitness-controller.js +106 -0
  418. package/dist/core/research/model-fitness-controller.js.map +1 -0
  419. package/dist/core/research/model-fitness.d.ts +1 -1
  420. package/dist/core/research/model-fitness.d.ts.map +1 -1
  421. package/dist/core/research/model-fitness.js +4 -4
  422. package/dist/core/research/model-fitness.js.map +1 -1
  423. package/dist/core/research/research-gate.d.ts.map +1 -1
  424. package/dist/core/research/research-gate.js +7 -7
  425. package/dist/core/research/research-gate.js.map +1 -1
  426. package/dist/core/research/research-lane-controller.d.ts +62 -0
  427. package/dist/core/research/research-lane-controller.d.ts.map +1 -0
  428. package/dist/core/research/research-lane-controller.js +292 -0
  429. package/dist/core/research/research-lane-controller.js.map +1 -0
  430. package/dist/core/research/session-evidence-bundle.d.ts +2 -4
  431. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
  432. package/dist/core/research/session-evidence-bundle.js +10 -46
  433. package/dist/core/research/session-evidence-bundle.js.map +1 -1
  434. package/dist/core/resource-loader.d.ts.map +1 -1
  435. package/dist/core/resource-loader.js +7 -2
  436. package/dist/core/resource-loader.js.map +1 -1
  437. package/dist/core/risk-classifier.d.ts +6 -0
  438. package/dist/core/risk-classifier.d.ts.map +1 -0
  439. package/dist/core/risk-classifier.js +225 -0
  440. package/dist/core/risk-classifier.js.map +1 -0
  441. package/dist/core/runtime-builder.d.ts +26 -20
  442. package/dist/core/runtime-builder.d.ts.map +1 -1
  443. package/dist/core/runtime-builder.js +237 -178
  444. package/dist/core/runtime-builder.js.map +1 -1
  445. package/dist/core/sdk.d.ts +6 -3
  446. package/dist/core/sdk.d.ts.map +1 -1
  447. package/dist/core/sdk.js +61 -24
  448. package/dist/core/sdk.js.map +1 -1
  449. package/dist/core/session-analytics.d.ts.map +1 -1
  450. package/dist/core/session-analytics.js +28 -1
  451. package/dist/core/session-analytics.js.map +1 -1
  452. package/dist/core/session-image-store.d.ts +33 -0
  453. package/dist/core/session-image-store.d.ts.map +1 -0
  454. package/dist/core/session-image-store.js +283 -0
  455. package/dist/core/session-image-store.js.map +1 -0
  456. package/dist/core/session-role.d.ts +6 -4
  457. package/dist/core/session-role.d.ts.map +1 -1
  458. package/dist/core/session-role.js +10 -4
  459. package/dist/core/session-role.js.map +1 -1
  460. package/dist/core/session-snapshot.d.ts +34 -0
  461. package/dist/core/session-snapshot.d.ts.map +1 -0
  462. package/dist/core/session-snapshot.js +68 -0
  463. package/dist/core/session-snapshot.js.map +1 -0
  464. package/dist/core/session-supervision-runtime.d.ts +31 -0
  465. package/dist/core/session-supervision-runtime.d.ts.map +1 -0
  466. package/dist/core/session-supervision-runtime.js +97 -0
  467. package/dist/core/session-supervision-runtime.js.map +1 -0
  468. package/dist/core/settings-manager.d.ts +9 -4
  469. package/dist/core/settings-manager.d.ts.map +1 -1
  470. package/dist/core/settings-manager.js +80 -28
  471. package/dist/core/settings-manager.js.map +1 -1
  472. package/dist/core/tasks/session-task-state.d.ts +2 -4
  473. package/dist/core/tasks/session-task-state.d.ts.map +1 -1
  474. package/dist/core/tasks/session-task-state.js +10 -28
  475. package/dist/core/tasks/session-task-state.js.map +1 -1
  476. package/dist/core/tasks/task-projection.d.ts +20 -0
  477. package/dist/core/tasks/task-projection.d.ts.map +1 -0
  478. package/dist/core/tasks/task-projection.js +47 -0
  479. package/dist/core/tasks/task-projection.js.map +1 -0
  480. package/dist/core/tasks/task-state.d.ts +4 -0
  481. package/dist/core/tasks/task-state.d.ts.map +1 -1
  482. package/dist/core/tasks/task-state.js +28 -11
  483. package/dist/core/tasks/task-state.js.map +1 -1
  484. package/dist/core/tool-capability-policy.d.ts +13 -0
  485. package/dist/core/tool-capability-policy.d.ts.map +1 -0
  486. package/dist/core/tool-capability-policy.js +85 -0
  487. package/dist/core/tool-capability-policy.js.map +1 -0
  488. package/dist/core/tool-protocol-controller.d.ts +91 -0
  489. package/dist/core/tool-protocol-controller.d.ts.map +1 -0
  490. package/dist/core/tool-protocol-controller.js +512 -0
  491. package/dist/core/tool-protocol-controller.js.map +1 -0
  492. package/dist/core/tool-recovery-log-records.d.ts +2 -3
  493. package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
  494. package/dist/core/tool-recovery-log-records.js +9 -35
  495. package/dist/core/tool-recovery-log-records.js.map +1 -1
  496. package/dist/core/tool-selection/tool-performance-store.d.ts +3 -7
  497. package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
  498. package/dist/core/tool-selection/tool-performance-store.js +97 -138
  499. package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
  500. package/dist/core/tools/ask-question.d.ts +124 -0
  501. package/dist/core/tools/ask-question.d.ts.map +1 -0
  502. package/dist/core/tools/ask-question.js +693 -0
  503. package/dist/core/tools/ask-question.js.map +1 -0
  504. package/dist/core/tools/delegate-status.d.ts +31 -3
  505. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  506. package/dist/core/tools/delegate-status.js +149 -29
  507. package/dist/core/tools/delegate-status.js.map +1 -1
  508. package/dist/core/tools/delegate.d.ts +15 -13
  509. package/dist/core/tools/delegate.d.ts.map +1 -1
  510. package/dist/core/tools/delegate.js +108 -23
  511. package/dist/core/tools/delegate.js.map +1 -1
  512. package/dist/core/tools/extensionify.d.ts.map +1 -1
  513. package/dist/core/tools/extensionify.js +1 -0
  514. package/dist/core/tools/extensionify.js.map +1 -1
  515. package/dist/core/tools/goal.d.ts +5 -5
  516. package/dist/core/tools/goal.d.ts.map +1 -1
  517. package/dist/core/tools/goal.js +10 -10
  518. package/dist/core/tools/goal.js.map +1 -1
  519. package/dist/core/tools/model-fitness.d.ts.map +1 -1
  520. package/dist/core/tools/model-fitness.js +2 -2
  521. package/dist/core/tools/model-fitness.js.map +1 -1
  522. package/dist/core/tools/orchestration-panel.d.ts +43 -0
  523. package/dist/core/tools/orchestration-panel.d.ts.map +1 -0
  524. package/dist/core/tools/orchestration-panel.js +168 -0
  525. package/dist/core/tools/orchestration-panel.js.map +1 -0
  526. package/dist/core/tools/run-process.d.ts +26 -0
  527. package/dist/core/tools/run-process.d.ts.map +1 -0
  528. package/dist/core/tools/run-process.js +138 -0
  529. package/dist/core/tools/run-process.js.map +1 -0
  530. package/dist/core/tools/task-steps.d.ts +2 -0
  531. package/dist/core/tools/task-steps.d.ts.map +1 -1
  532. package/dist/core/tools/task-steps.js +102 -0
  533. package/dist/core/tools/task-steps.js.map +1 -1
  534. package/dist/core/tools/tmux-dispatch.d.ts +3 -5
  535. package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
  536. package/dist/core/tools/tmux-dispatch.js +4 -4
  537. package/dist/core/tools/tmux-dispatch.js.map +1 -1
  538. package/dist/core/tools/windows-shell-engine.d.ts.map +1 -1
  539. package/dist/core/tools/windows-shell-engine.js +4 -6
  540. package/dist/core/tools/windows-shell-engine.js.map +1 -1
  541. package/dist/core/util/bounded-jsonl.d.ts +10 -0
  542. package/dist/core/util/bounded-jsonl.d.ts.map +1 -0
  543. package/dist/core/util/bounded-jsonl.js +75 -0
  544. package/dist/core/util/bounded-jsonl.js.map +1 -0
  545. package/dist/core/util/value-guards.d.ts +5 -0
  546. package/dist/core/util/value-guards.d.ts.map +1 -0
  547. package/dist/core/util/value-guards.js +12 -0
  548. package/dist/core/util/value-guards.js.map +1 -0
  549. package/dist/core/worktree-sync/store.d.ts +3 -3
  550. package/dist/core/worktree-sync/store.d.ts.map +1 -1
  551. package/dist/core/worktree-sync/store.js +10 -5
  552. package/dist/core/worktree-sync/store.js.map +1 -1
  553. package/dist/index.d.ts +13 -3
  554. package/dist/index.d.ts.map +1 -1
  555. package/dist/index.js +12 -2
  556. package/dist/index.js.map +1 -1
  557. package/dist/main.d.ts.map +1 -1
  558. package/dist/main.js +128 -44
  559. package/dist/main.js.map +1 -1
  560. package/dist/migrations.d.ts +4 -6
  561. package/dist/migrations.d.ts.map +1 -1
  562. package/dist/migrations.js +186 -28
  563. package/dist/migrations.js.map +1 -1
  564. package/dist/modes/interactive/clipboard-input.d.ts +7 -1
  565. package/dist/modes/interactive/clipboard-input.d.ts.map +1 -1
  566. package/dist/modes/interactive/clipboard-input.js +44 -6
  567. package/dist/modes/interactive/clipboard-input.js.map +1 -1
  568. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  569. package/dist/modes/interactive/components/settings-selector.js +2 -2
  570. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  571. package/dist/modes/interactive/config-backup.d.ts.map +1 -1
  572. package/dist/modes/interactive/config-backup.js +5 -4
  573. package/dist/modes/interactive/config-backup.js.map +1 -1
  574. package/dist/modes/interactive/extension-ui-host.d.ts +14 -0
  575. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  576. package/dist/modes/interactive/extension-ui-host.js +76 -15
  577. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  578. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  579. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  580. package/dist/modes/interactive/interactive-mode.js +63 -1
  581. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  582. package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
  583. package/dist/modes/interactive/key-handlers.js +1 -1
  584. package/dist/modes/interactive/key-handlers.js.map +1 -1
  585. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
  586. package/dist/modes/interactive/profile-menu-controller.js +7 -7
  587. package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
  588. package/dist/modes/interactive/report-commands.d.ts.map +1 -1
  589. package/dist/modes/interactive/report-commands.js +21 -0
  590. package/dist/modes/interactive/report-commands.js.map +1 -1
  591. package/dist/modes/interactive/session-flow-commands.d.ts +17 -2
  592. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  593. package/dist/modes/interactive/session-flow-commands.js +50 -17
  594. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  595. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
  596. package/dist/modes/interactive/session-io-commands.js +16 -6
  597. package/dist/modes/interactive/session-io-commands.js.map +1 -1
  598. package/dist/modes/interactive/session-replacement-errors.d.ts +7 -0
  599. package/dist/modes/interactive/session-replacement-errors.d.ts.map +1 -0
  600. package/dist/modes/interactive/session-replacement-errors.js +15 -0
  601. package/dist/modes/interactive/session-replacement-errors.js.map +1 -0
  602. package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
  603. package/dist/modes/interactive/startup-checks.js +1 -1
  604. package/dist/modes/interactive/startup-checks.js.map +1 -1
  605. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  606. package/dist/modes/rpc/rpc-mode.js +82 -23
  607. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  608. package/dist/modes/rpc/rpc-types.d.ts +15 -0
  609. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  610. package/dist/modes/rpc/rpc-types.js +138 -1
  611. package/dist/modes/rpc/rpc-types.js.map +1 -1
  612. package/dist/utils/clipboard-image.d.ts.map +1 -1
  613. package/dist/utils/clipboard-image.js +2 -13
  614. package/dist/utils/clipboard-image.js.map +1 -1
  615. package/dist/utils/clipboard-native.d.ts +1 -0
  616. package/dist/utils/clipboard-native.d.ts.map +1 -1
  617. package/dist/utils/clipboard-native.js.map +1 -1
  618. package/dist/utils/clipboard.d.ts +1 -0
  619. package/dist/utils/clipboard.d.ts.map +1 -1
  620. package/dist/utils/clipboard.js +52 -1
  621. package/dist/utils/clipboard.js.map +1 -1
  622. package/dist/utils/platform.d.ts +3 -0
  623. package/dist/utils/platform.d.ts.map +1 -0
  624. package/dist/utils/platform.js +8 -0
  625. package/dist/utils/platform.js.map +1 -0
  626. package/dist/utils/work-directory.d.ts +11 -0
  627. package/dist/utils/work-directory.d.ts.map +1 -1
  628. package/dist/utils/work-directory.js +30 -9
  629. package/dist/utils/work-directory.js.map +1 -1
  630. package/docs/UI_POLISH_ORCHESTRATION.md +44 -0
  631. package/docs/UI_QUALITY_ORCHESTRATION.md +30 -0
  632. package/docs/docs.json +4 -0
  633. package/docs/extensions.md +62 -2
  634. package/docs/harness-architecture.md +156 -0
  635. package/docs/keybindings.md +11 -1
  636. package/docs/process-matrix.md +59 -26
  637. package/docs/rpc.md +45 -2
  638. package/docs/sessions.md +15 -0
  639. package/docs/settings.md +125 -11
  640. package/docs/task-steps.md +8 -0
  641. package/docs/telemetry.md +19 -0
  642. package/docs/tmux-agent-manager.md +10 -3
  643. package/docs/ui-reference/README.md +9 -0
  644. package/docs/ui-reference/orchestration-after.txt +7 -0
  645. package/docs/ui-reference/orchestration-before.txt +7 -0
  646. package/docs/ui-reference/orchestration-reference.txt +6 -0
  647. package/docs/usage.md +14 -2
  648. package/docs/work-directory.md +19 -8
  649. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  650. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  651. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  652. package/examples/extensions/question.ts +34 -245
  653. package/examples/extensions/questionnaire.ts +41 -407
  654. package/examples/extensions/sandbox/package-lock.json +2 -2
  655. package/examples/extensions/sandbox/package.json +1 -1
  656. package/examples/extensions/with-deps/package-lock.json +2 -2
  657. package/examples/extensions/with-deps/package.json +1 -1
  658. package/npm-shrinkwrap.json +12 -12
  659. package/package.json +4 -4
  660. package/dist/core/delegation/session-worker-result.d.ts +0 -46
  661. package/dist/core/delegation/session-worker-result.d.ts.map +0 -1
  662. package/dist/core/delegation/session-worker-result.js +0 -113
  663. package/dist/core/delegation/session-worker-result.js.map +0 -1
  664. package/dist/core/delegation/worker-result.d.ts.map +0 -1
  665. package/dist/core/delegation/worker-result.js.map +0 -1
  666. package/dist/core/telemetry.d.ts.map +0 -1
  667. package/dist/core/telemetry.js.map +0 -1
@@ -152,6 +152,7 @@ export type GoalEvent = {
152
152
  now: string;
153
153
  } | {
154
154
  type: "complete_goal";
155
+ acceptanceOverride?: boolean;
155
156
  now: string;
156
157
  } | {
157
158
  type: "complete_goal_manually";
@@ -1 +1 @@
1
- {"version":3,"file":"goal-state.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"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","sourcesContent":["export type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\" | \"worker\";\n\nexport interface GoalState {\n\tgoalId: string;\n\tuserGoal: string;\n\tstatus: GoalStatus;\n\trequirements: readonly Requirement[];\n\tevidence: readonly GoalEvidenceRef[];\n\tevents: readonly GoalEvent[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlastProgressAt: string;\n\tstallTurns: number;\n\tblockedReason?: string;\n\t/**\n\t * Cumulative continuation turns submitted for this goal across EVERY `continueGoalLoop`\n\t * invocation for its lifetime (idle-driven auto-continues and manual continues alike) —\n\t * durable via goal-state persistence, so it survives process restarts and idle cycles.\n\t * Optional because snapshots persisted before this field existed carry no value; treat\n\t * `undefined` as `0` everywhere it is read (see `applyGoalEvent`'s `record_continuation_budget`\n\t * case and `goal-loop-controller.ts`'s budget check).\n\t */\n\tcontinuationTurnsUsed?: number;\n\t/**\n\t * Cumulative ACTIVE wall-clock milliseconds spent running continuation passes for this goal —\n\t * the sum of each individual pass's own await duration, NOT wall-clock time elapsed between\n\t * passes or during idle gaps. Same backward-compat/undefined-as-0 note as `continuationTurnsUsed`.\n\t */\n\tcontinuationWallClockMs?: number;\n\t/**\n\t * Cumulative USD attributed to this goal's own continuation passes, derived from the session's\n\t * own model spend (`getCostSummary().ownCost` at the persistence dep) — deliberately excludes\n\t * worker/subagent spend, which is tracked and budgeted separately. Same backward-compat note.\n\t */\n\tcontinuationSpendUsd?: number;\n\t/**\n\t * Bookkeeping only: the session's own cumulative cost reading as of the last recorded pass,\n\t * used to derive the NEXT pass's spend delta (`event.sessionCostUsd - continuationSpendCheckpointUsd`)\n\t * while keeping `applyGoalEvent` pure (it consumes one externally-observed absolute reading per\n\t * call rather than reaching for session state itself). Not meaningful read in isolation; `undefined`\n\t * means no pass has been recorded yet, so the first recorded pass establishes the checkpoint with a\n\t * zero delta rather than mis-attributing all pre-goal-loop session spend to that one pass.\n\t */\n\tcontinuationSpendCheckpointUsd?: number;\n\t/**\n\t * Cumulative USD attributed to WORKER/SUBAGENT spend for this goal's lanes (in-process worker\n\t * usage via `addSpawnedUsage`, out-of-process tmux-worker usage via the advisory\n\t * `reportSpawnedUsage` claim) — the counterpart this goal's OWN model spend excludes (see\n\t * {@link continuationSpendUsd}). Populated by the runtime that sums lane spend by goalId; this\n\t * field is only the durable slot. Same backward-compat/undefined-as-0 note as the other\n\t * continuation budget fields. Advisory for out-of-process (tmux) workers — never a hard cap\n\t * across the process boundary.\n\t */\n\tcontinuationWorkerSpendUsd?: number;\n}\n\nexport interface Requirement {\n\tid: string;\n\ttext: string;\n\tstatus: RequirementStatus;\n\tevidenceIds: readonly string[];\n\tblockedReason?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\t/**\n\t * LaneId of a worker dispatched against this requirement (set by the `dispatch_worker` event).\n\t * Recording a binding never satisfies the requirement by itself -- the worker's own completion\n\t * later populates `\"worker\"`-kind evidence and prompts an explicit `satisfy_requirement` pass.\n\t */\n\tboundLaneId?: string;\n\t/**\n\t * ISO timestamp of the moment `boundLaneId` was most recently bound to a REAL lane -- the clock\n\t * the never-hang wait-timeout (`evaluateGoalContinuation`'s `worker_wait_timeout` reasonCode)\n\t * reads to detect a worker that has hung past `maxWorkerWaitMs`. Stamped ONLY when a\n\t * `dispatch_worker` event carries a lane id; a declined dispatch (no lane) leaves this field\n\t * untouched, so no clock starts for a worker that never actually launched.\n\t */\n\tboundAt?: string;\n}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\n\t/**\n\t * Whether `uri` was checked against session records (\"tool\" evidence, a toolCallId) or the\n\t * filesystem (\"file\" evidence, a path) at add_evidence time. `true`/`false` only when the\n\t * ref was checkable; `undefined` when the evidence kind carries no checkable ref (e.g.\n\t * \"user\"/\"finding\"/\"test\", or a \"tool\"/\"file\" entry with no `uri`).\n\t */\n\tverified?: boolean;\n\tcreatedAt: string;\n}\n\nexport type GoalEvent =\n\t| { type: \"add_requirement\"; id: string; text: string; now: string }\n\t| { type: \"satisfy_requirement\"; id: string; evidenceIds: readonly string[]; now: string }\n\t| { type: \"block_requirement\"; id: string; blockedReason: string; now: string }\n\t| { type: \"reopen_requirement\"; id: string; now: string }\n\t| {\n\t\t\ttype: \"dispatch_worker\";\n\t\t\t/** Requirement id the worker is bound to. */\n\t\t\tid: string;\n\t\t\t/** Instructions the worker was (or will be) dispatched with. */\n\t\t\tinstructions: string;\n\t\t\t/**\n\t\t\t * LaneId returned by the tool-layer dispatch side effect. Undefined when that side effect\n\t\t\t * is unwired/stubbed -- the binding is then recorded with no lane target yet.\n\t\t\t */\n\t\t\tlaneId?: string;\n\t\t\tnow: string;\n\t }\n\t| {\n\t\t\ttype: \"add_evidence\";\n\t\t\tid: string;\n\t\t\tkind: GoalEvidenceKind;\n\t\t\tsummary: string;\n\t\t\turi?: string;\n\t\t\t/** See {@link GoalEvidenceRef.verified}; computed by the tool layer before the event is applied. */\n\t\t\tverified?: boolean;\n\t\t\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| {\n\t\t\ttype: \"record_continuation_budget\";\n\t\t\t/** Turns submitted in this pass (currently always 1 — the loop calls once per submitted pass). */\n\t\t\tturns: number;\n\t\t\t/** This pass's own active wall-clock duration, in milliseconds. */\n\t\t\twallClockMs: number;\n\t\t\t/**\n\t\t\t * The session's own cumulative model spend (`getCostSummary().ownCost`) AT THE TIME this pass\n\t\t\t * was recorded — an absolute reading, not a pre-computed delta. See\n\t\t\t * `GoalState.continuationSpendCheckpointUsd` for how the reducer derives the delta.\n\t\t\t */\n\t\t\tsessionCostUsd: number;\n\t\t\tnow: string;\n\t }\n\t| { type: \"complete_goal\"; now: string }\n\t| { type: \"complete_goal_manually\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn (\n\t\tvalue === \"file\" ||\n\t\tvalue === \"test\" ||\n\t\tvalue === \"tool\" ||\n\t\tvalue === \"user\" ||\n\t\tvalue === \"finding\" ||\n\t\tvalue === \"worker\"\n\t);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction hasOptionalBoolean(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"boolean\";\n}\n\nfunction hasOptionalFiniteNumber(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || (typeof record[key] === \"number\" && Number.isFinite(record[key]));\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalString(value, \"boundLaneId\") &&\n\t\thasOptionalString(value, \"boundAt\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\") &&\n\t\thasOptionalBoolean(value, \"verified\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"reopen_requirement\":\n\t\t\treturn typeof value.id === \"string\";\n\t\tcase \"dispatch_worker\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" && typeof value.instructions === \"string\" && hasOptionalString(value, \"laneId\")\n\t\t\t);\n\t\tcase \"add_evidence\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" &&\n\t\t\t\tisGoalEvidenceKind(value.kind) &&\n\t\t\t\ttypeof value.summary === \"string\" &&\n\t\t\t\thasOptionalString(value, \"uri\") &&\n\t\t\t\thasOptionalBoolean(value, \"verified\")\n\t\t\t);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\tcase \"complete_goal\":\n\t\tcase \"complete_goal_manually\":\n\t\tcase \"resume_goal\":\n\t\tcase \"cancel_goal\":\n\t\t\treturn true;\n\t\tcase \"block_goal\":\n\t\t\treturn typeof value.reason === \"string\";\n\t\tcase \"record_continuation_budget\":\n\t\t\treturn (\n\t\t\t\ttypeof value.turns === \"number\" &&\n\t\t\t\tNumber.isFinite(value.turns) &&\n\t\t\t\ttypeof value.wallClockMs === \"number\" &&\n\t\t\t\tNumber.isFinite(value.wallClockMs) &&\n\t\t\t\ttypeof value.sessionCostUsd === \"number\" &&\n\t\t\t\tNumber.isFinite(value.sessionCostUsd)\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationTurnsUsed\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWallClockMs\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendCheckpointUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWorkerSpendUsd\")\n\t);\n}\n\nfunction cloneRequirement(requirement: Requirement): Requirement {\n\treturn {\n\t\t...requirement,\n\t\tevidenceIds: [...requirement.evidenceIds],\n\t};\n}\n\nfunction cloneGoalEvidenceRef(evidence: GoalEvidenceRef): GoalEvidenceRef {\n\treturn { ...evidence };\n}\n\nfunction cloneGoalEvent(event: GoalEvent): GoalEvent {\n\tif (event.type === \"satisfy_requirement\") {\n\t\treturn { ...event, evidenceIds: [...event.evidenceIds] };\n\t}\n\treturn { ...event };\n}\n\nfunction cloneGoalState(state: GoalState): GoalState {\n\treturn {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: state.events.map(cloneGoalEvent),\n\t};\n}\n\nexport function cloneGoalStateForStorage(state: GoalState): GoalState {\n\treturn cloneGoalState(state);\n}\n\nexport function createGoalState(args: { goalId: string; userGoal: string; now: string }): GoalState {\n\treturn {\n\t\tgoalId: args.goalId,\n\t\tuserGoal: args.userGoal,\n\t\tstatus: \"active\",\n\t\trequirements: [],\n\t\tevidence: [],\n\t\tevents: [],\n\t\tcreatedAt: args.now,\n\t\tupdatedAt: args.now,\n\t\tlastProgressAt: args.now,\n\t\tstallTurns: 0,\n\t\tcontinuationTurnsUsed: 0,\n\t\tcontinuationWallClockMs: 0,\n\t\tcontinuationSpendUsd: 0,\n\t\tcontinuationWorkerSpendUsd: 0,\n\t};\n}\n\nexport function applyGoalEvent(state: GoalState, event: GoalEvent): GoalState {\n\tconst newState: GoalState = {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)],\n\t\tupdatedAt: event.now,\n\t};\n\n\tswitch (event.type) {\n\t\tcase \"add_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tconst newRequirement: Requirement = {\n\t\t\t\tid: event.id,\n\t\t\t\ttext: event.text,\n\t\t\t\tstatus: \"open\",\n\t\t\t\tevidenceIds: [],\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.requirements[existingIndex].createdAt : event.now,\n\t\t\t\tupdatedAt: event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = newRequirement;\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t} else {\n\t\t\t\tnewState.requirements = [...newState.requirements, newRequirement];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"satisfy_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"satisfied\",\n\t\t\t\t\tevidenceIds: [...event.evidenceIds],\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\tblockedReason: event.blockedReason,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"reopen_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"open\",\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"dispatch_worker\": {\n\t\t\t// Records the requirement<->lane binding ONLY -- never satisfies the requirement and never\n\t\t\t// touches lastProgressAt/stallTurns. The worker's own completion later populates \"worker\"\n\t\t\t// evidence and prompts an explicit satisfy_requirement pass through the existing gate.\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tboundLaneId: event.laneId,\n\t\t\t\t\t// Start (or keep) the wait-timeout clock ONLY when this dispatch actually bound a real\n\t\t\t\t\t// lane -- a declined dispatch (no laneId) preserves whatever boundAt was already there.\n\t\t\t\t\tboundAt: event.laneId ? event.now : requirement.boundAt,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"add_evidence\": {\n\t\t\tconst existingIndex = newState.evidence.findIndex((evidence) => evidence.id === event.id);\n\t\t\tconst newEvidence: GoalEvidenceRef = {\n\t\t\t\tid: event.id,\n\t\t\t\tkind: event.kind,\n\t\t\t\tsummary: event.summary,\n\t\t\t\turi: event.uri,\n\t\t\t\tverified: event.verified,\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.evidence[existingIndex].createdAt : event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedEvidence = [...newState.evidence];\n\t\t\t\tupdatedEvidence[existingIndex] = newEvidence;\n\t\t\t\tnewState.evidence = updatedEvidence;\n\t\t\t} else {\n\t\t\t\tnewState.evidence = [...newState.evidence, newEvidence];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"progress\": {\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"no_progress\": {\n\t\t\tnewState.stallTurns = state.stallTurns + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"record_continuation_budget\": {\n\t\t\tconst previousCheckpoint = state.continuationSpendCheckpointUsd;\n\t\t\t// No prior checkpoint (first pass ever recorded for this goal): there is no valid \"before\"\n\t\t\t// reading to diff against, so attribute a zero delta for this one pass rather than mis-count\n\t\t\t// all pre-goal-loop session spend into it. Every subsequent pass gets an accurate delta.\n\t\t\tconst spendDelta =\n\t\t\t\tpreviousCheckpoint === undefined ? 0 : Math.max(0, event.sessionCostUsd - previousCheckpoint);\n\t\t\tnewState.continuationTurnsUsed = (state.continuationTurnsUsed ?? 0) + event.turns;\n\t\t\tnewState.continuationWallClockMs = (state.continuationWallClockMs ?? 0) + event.wallClockMs;\n\t\t\tnewState.continuationSpendUsd = (state.continuationSpendUsd ?? 0) + spendDelta;\n\t\t\tnewState.continuationSpendCheckpointUsd = event.sessionCostUsd;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal\": {\n\t\t\tconst hasUnsatisfied = newState.requirements.some((requirement) => requirement.status !== \"satisfied\");\n\t\t\tif (!hasUnsatisfied) {\n\t\t\t\tnewState.status = \"completed\";\n\t\t\t\tnewState.blockedReason = undefined;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal_manually\": {\n\t\t\tnewState.status = \"completed\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_goal\": {\n\t\t\tnewState.status = \"blocked\";\n\t\t\tnewState.blockedReason = event.reason;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"resume_goal\": {\n\t\t\tnewState.status = \"active\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"cancel_goal\": {\n\t\t\tnewState.status = \"cancelled\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn newState;\n}\n\nexport function shouldContinueGoalLoop(args: { state: GoalState; maxStallTurns: number; now: string }): boolean {\n\tif (args.state.status !== \"active\") {\n\t\treturn false;\n\t}\n\tif (args.state.stallTurns >= args.maxStallTurns) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function serializeGoalState(state: GoalState): string {\n\treturn JSON.stringify(cloneGoalState(state), null, 2);\n}\n\nexport function parseGoalState(text: string): GoalState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\tif (!isGoalState(parsed)) return undefined;\n\t\treturn cloneGoalState(parsed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"goal-state.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPlainRecord } from \"../util/value-guards.ts\";\n\nexport type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\" | \"worker\";\n\nexport interface GoalState {\n\tgoalId: string;\n\tuserGoal: string;\n\tstatus: GoalStatus;\n\trequirements: readonly Requirement[];\n\tevidence: readonly GoalEvidenceRef[];\n\tevents: readonly GoalEvent[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlastProgressAt: string;\n\tstallTurns: number;\n\tblockedReason?: string;\n\t/**\n\t * Cumulative continuation turns submitted for this goal across EVERY `continueGoalLoop`\n\t * invocation for its lifetime (idle-driven auto-continues and manual continues alike) —\n\t * durable via goal-state persistence, so it survives process restarts and idle cycles.\n\t * Optional because snapshots persisted before this field existed carry no value; treat\n\t * `undefined` as `0` everywhere it is read (see `applyGoalEvent`'s `record_continuation_budget`\n\t * case and `goal-loop-controller.ts`'s budget check).\n\t */\n\tcontinuationTurnsUsed?: number;\n\t/**\n\t * Cumulative ACTIVE wall-clock milliseconds spent running continuation passes for this goal —\n\t * the sum of each individual pass's own await duration, NOT wall-clock time elapsed between\n\t * passes or during idle gaps. Same backward-compat/undefined-as-0 note as `continuationTurnsUsed`.\n\t */\n\tcontinuationWallClockMs?: number;\n\t/**\n\t * Cumulative USD attributed to this goal's own continuation passes, derived from the session's\n\t * own model spend (`getCostSummary().ownCost` at the persistence dep) — deliberately excludes\n\t * worker/subagent spend, which is tracked and budgeted separately. Same backward-compat note.\n\t */\n\tcontinuationSpendUsd?: number;\n\t/**\n\t * Bookkeeping only: the session's own cumulative cost reading as of the last recorded pass,\n\t * used to derive the NEXT pass's spend delta (`event.sessionCostUsd - continuationSpendCheckpointUsd`)\n\t * while keeping `applyGoalEvent` pure (it consumes one externally-observed absolute reading per\n\t * call rather than reaching for session state itself). Not meaningful read in isolation; `undefined`\n\t * means no pass has been recorded yet, so the first recorded pass establishes the checkpoint with a\n\t * zero delta rather than mis-attributing all pre-goal-loop session spend to that one pass.\n\t */\n\tcontinuationSpendCheckpointUsd?: number;\n\t/**\n\t * Cumulative USD attributed to WORKER/SUBAGENT spend for this goal's lanes (in-process worker\n\t * usage via `addSpawnedUsage`, out-of-process tmux-worker usage via the advisory\n\t * `reportSpawnedUsage` claim) — the counterpart this goal's OWN model spend excludes (see\n\t * {@link continuationSpendUsd}). Populated by the runtime that sums lane spend by goalId; this\n\t * field is only the durable slot. Same backward-compat/undefined-as-0 note as the other\n\t * continuation budget fields. Advisory for out-of-process (tmux) workers — never a hard cap\n\t * across the process boundary.\n\t */\n\tcontinuationWorkerSpendUsd?: number;\n}\n\nexport interface Requirement {\n\tid: string;\n\ttext: string;\n\tstatus: RequirementStatus;\n\tevidenceIds: readonly string[];\n\tblockedReason?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\t/**\n\t * LaneId of a worker dispatched against this requirement (set by the `dispatch_worker` event).\n\t * Recording a binding never satisfies the requirement by itself -- the worker's own completion\n\t * later populates `\"worker\"`-kind evidence and prompts an explicit `satisfy_requirement` pass.\n\t */\n\tboundLaneId?: string;\n\t/**\n\t * ISO timestamp of the moment `boundLaneId` was most recently bound to a REAL lane -- the clock\n\t * the never-hang wait-timeout (`evaluateGoalContinuation`'s `worker_wait_timeout` reasonCode)\n\t * reads to detect a worker that has hung past `maxWorkerWaitMs`. Stamped ONLY when a\n\t * `dispatch_worker` event carries a lane id; a declined dispatch (no lane) leaves this field\n\t * untouched, so no clock starts for a worker that never actually launched.\n\t */\n\tboundAt?: string;\n}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\n\t/**\n\t * Whether `uri` was checked against session records (\"tool\" evidence, a toolCallId) or the\n\t * filesystem (\"file\" evidence, a path) at add_evidence time. `true`/`false` only when the\n\t * ref was checkable; `undefined` when the evidence kind carries no checkable ref (e.g.\n\t * \"user\"/\"finding\"/\"test\", or a \"tool\"/\"file\" entry with no `uri`).\n\t */\n\tverified?: boolean;\n\tcreatedAt: string;\n}\n\nexport type GoalEvent =\n\t| { type: \"add_requirement\"; id: string; text: string; now: string }\n\t| { type: \"satisfy_requirement\"; id: string; evidenceIds: readonly string[]; now: string }\n\t| { type: \"block_requirement\"; id: string; blockedReason: string; now: string }\n\t| { type: \"reopen_requirement\"; id: string; now: string }\n\t| {\n\t\t\ttype: \"dispatch_worker\";\n\t\t\t/** Requirement id the worker is bound to. */\n\t\t\tid: string;\n\t\t\t/** Instructions the worker was (or will be) dispatched with. */\n\t\t\tinstructions: string;\n\t\t\t/**\n\t\t\t * LaneId returned by the tool-layer dispatch side effect. Undefined when that side effect\n\t\t\t * is unwired/stubbed -- the binding is then recorded with no lane target yet.\n\t\t\t */\n\t\t\tlaneId?: string;\n\t\t\tnow: string;\n\t }\n\t| {\n\t\t\ttype: \"add_evidence\";\n\t\t\tid: string;\n\t\t\tkind: GoalEvidenceKind;\n\t\t\tsummary: string;\n\t\t\turi?: string;\n\t\t\t/** See {@link GoalEvidenceRef.verified}; computed by the tool layer before the event is applied. */\n\t\t\tverified?: boolean;\n\t\t\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| {\n\t\t\ttype: \"record_continuation_budget\";\n\t\t\t/** Turns submitted in this pass (currently always 1 — the loop calls once per submitted pass). */\n\t\t\tturns: number;\n\t\t\t/** This pass's own active wall-clock duration, in milliseconds. */\n\t\t\twallClockMs: number;\n\t\t\t/**\n\t\t\t * The session's own cumulative model spend (`getCostSummary().ownCost`) AT THE TIME this pass\n\t\t\t * was recorded — an absolute reading, not a pre-computed delta. See\n\t\t\t * `GoalState.continuationSpendCheckpointUsd` for how the reducer derives the delta.\n\t\t\t */\n\t\t\tsessionCostUsd: number;\n\t\t\tnow: string;\n\t }\n\t| { type: \"complete_goal\"; acceptanceOverride?: boolean; now: string }\n\t| { type: \"complete_goal_manually\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn (\n\t\tvalue === \"file\" ||\n\t\tvalue === \"test\" ||\n\t\tvalue === \"tool\" ||\n\t\tvalue === \"user\" ||\n\t\tvalue === \"finding\" ||\n\t\tvalue === \"worker\"\n\t);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction hasOptionalBoolean(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"boolean\";\n}\n\nfunction hasOptionalFiniteNumber(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || (typeof record[key] === \"number\" && Number.isFinite(record[key]));\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isPlainRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalString(value, \"boundLaneId\") &&\n\t\thasOptionalString(value, \"boundAt\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isPlainRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\") &&\n\t\thasOptionalBoolean(value, \"verified\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isPlainRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"reopen_requirement\":\n\t\t\treturn typeof value.id === \"string\";\n\t\tcase \"dispatch_worker\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" && typeof value.instructions === \"string\" && hasOptionalString(value, \"laneId\")\n\t\t\t);\n\t\tcase \"add_evidence\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" &&\n\t\t\t\tisGoalEvidenceKind(value.kind) &&\n\t\t\t\ttypeof value.summary === \"string\" &&\n\t\t\t\thasOptionalString(value, \"uri\") &&\n\t\t\t\thasOptionalBoolean(value, \"verified\")\n\t\t\t);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\t\treturn true;\n\t\tcase \"complete_goal\":\n\t\t\treturn hasOptionalBoolean(value, \"acceptanceOverride\");\n\t\tcase \"complete_goal_manually\":\n\t\tcase \"resume_goal\":\n\t\tcase \"cancel_goal\":\n\t\t\treturn true;\n\t\tcase \"block_goal\":\n\t\t\treturn typeof value.reason === \"string\";\n\t\tcase \"record_continuation_budget\":\n\t\t\treturn (\n\t\t\t\ttypeof value.turns === \"number\" &&\n\t\t\t\tNumber.isFinite(value.turns) &&\n\t\t\t\ttypeof value.wallClockMs === \"number\" &&\n\t\t\t\tNumber.isFinite(value.wallClockMs) &&\n\t\t\t\ttypeof value.sessionCostUsd === \"number\" &&\n\t\t\t\tNumber.isFinite(value.sessionCostUsd)\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isPlainRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationTurnsUsed\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWallClockMs\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendCheckpointUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWorkerSpendUsd\")\n\t);\n}\n\nfunction cloneRequirement(requirement: Requirement): Requirement {\n\treturn {\n\t\t...requirement,\n\t\tevidenceIds: [...requirement.evidenceIds],\n\t};\n}\n\nfunction cloneGoalEvidenceRef(evidence: GoalEvidenceRef): GoalEvidenceRef {\n\treturn { ...evidence };\n}\n\nfunction cloneGoalEvent(event: GoalEvent): GoalEvent {\n\tif (event.type === \"satisfy_requirement\") {\n\t\treturn { ...event, evidenceIds: [...event.evidenceIds] };\n\t}\n\treturn { ...event };\n}\n\nfunction cloneGoalState(state: GoalState): GoalState {\n\treturn {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: state.events.map(cloneGoalEvent),\n\t};\n}\n\nexport function cloneGoalStateForStorage(state: GoalState): GoalState {\n\treturn cloneGoalState(state);\n}\n\nexport function createGoalState(args: { goalId: string; userGoal: string; now: string }): GoalState {\n\treturn {\n\t\tgoalId: args.goalId,\n\t\tuserGoal: args.userGoal,\n\t\tstatus: \"active\",\n\t\trequirements: [],\n\t\tevidence: [],\n\t\tevents: [],\n\t\tcreatedAt: args.now,\n\t\tupdatedAt: args.now,\n\t\tlastProgressAt: args.now,\n\t\tstallTurns: 0,\n\t\tcontinuationTurnsUsed: 0,\n\t\tcontinuationWallClockMs: 0,\n\t\tcontinuationSpendUsd: 0,\n\t\tcontinuationWorkerSpendUsd: 0,\n\t};\n}\n\nexport function applyGoalEvent(state: GoalState, event: GoalEvent): GoalState {\n\tconst newState: GoalState = {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)],\n\t\tupdatedAt: event.now,\n\t};\n\n\tswitch (event.type) {\n\t\tcase \"add_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tconst newRequirement: Requirement = {\n\t\t\t\tid: event.id,\n\t\t\t\ttext: event.text,\n\t\t\t\tstatus: \"open\",\n\t\t\t\tevidenceIds: [],\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.requirements[existingIndex].createdAt : event.now,\n\t\t\t\tupdatedAt: event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = newRequirement;\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t} else {\n\t\t\t\tnewState.requirements = [...newState.requirements, newRequirement];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"satisfy_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"satisfied\",\n\t\t\t\t\tevidenceIds: [...event.evidenceIds],\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\tblockedReason: event.blockedReason,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"reopen_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"open\",\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"dispatch_worker\": {\n\t\t\t// Records the requirement<->lane binding ONLY -- never satisfies the requirement and never\n\t\t\t// touches lastProgressAt/stallTurns. The worker's own completion later populates \"worker\"\n\t\t\t// evidence and prompts an explicit satisfy_requirement pass through the existing gate.\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tboundLaneId: event.laneId,\n\t\t\t\t\t// Start (or keep) the wait-timeout clock ONLY when this dispatch actually bound a real\n\t\t\t\t\t// lane -- a declined dispatch (no laneId) preserves whatever boundAt was already there.\n\t\t\t\t\tboundAt: event.laneId ? event.now : requirement.boundAt,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"add_evidence\": {\n\t\t\tconst existingIndex = newState.evidence.findIndex((evidence) => evidence.id === event.id);\n\t\t\tconst newEvidence: GoalEvidenceRef = {\n\t\t\t\tid: event.id,\n\t\t\t\tkind: event.kind,\n\t\t\t\tsummary: event.summary,\n\t\t\t\turi: event.uri,\n\t\t\t\tverified: event.verified,\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.evidence[existingIndex].createdAt : event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedEvidence = [...newState.evidence];\n\t\t\t\tupdatedEvidence[existingIndex] = newEvidence;\n\t\t\t\tnewState.evidence = updatedEvidence;\n\t\t\t} else {\n\t\t\t\tnewState.evidence = [...newState.evidence, newEvidence];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"progress\": {\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"no_progress\": {\n\t\t\tnewState.stallTurns = state.stallTurns + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"record_continuation_budget\": {\n\t\t\tconst previousCheckpoint = state.continuationSpendCheckpointUsd;\n\t\t\t// No prior checkpoint (first pass ever recorded for this goal): there is no valid \"before\"\n\t\t\t// reading to diff against, so attribute a zero delta for this one pass rather than mis-count\n\t\t\t// all pre-goal-loop session spend into it. Every subsequent pass gets an accurate delta.\n\t\t\tconst spendDelta =\n\t\t\t\tpreviousCheckpoint === undefined ? 0 : Math.max(0, event.sessionCostUsd - previousCheckpoint);\n\t\t\tnewState.continuationTurnsUsed = (state.continuationTurnsUsed ?? 0) + event.turns;\n\t\t\tnewState.continuationWallClockMs = (state.continuationWallClockMs ?? 0) + event.wallClockMs;\n\t\t\tnewState.continuationSpendUsd = (state.continuationSpendUsd ?? 0) + spendDelta;\n\t\t\tnewState.continuationSpendCheckpointUsd = event.sessionCostUsd;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal\": {\n\t\t\tconst hasUnsatisfied = newState.requirements.some((requirement) => requirement.status !== \"satisfied\");\n\t\t\tif (!hasUnsatisfied) {\n\t\t\t\tnewState.status = \"completed\";\n\t\t\t\tnewState.blockedReason = undefined;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal_manually\": {\n\t\t\tnewState.status = \"completed\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_goal\": {\n\t\t\tnewState.status = \"blocked\";\n\t\t\tnewState.blockedReason = event.reason;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"resume_goal\": {\n\t\t\tnewState.status = \"active\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"cancel_goal\": {\n\t\t\tnewState.status = \"cancelled\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn newState;\n}\n\nexport function shouldContinueGoalLoop(args: { state: GoalState; maxStallTurns: number; now: string }): boolean {\n\tif (args.state.status !== \"active\") {\n\t\treturn false;\n\t}\n\tif (args.state.stallTurns >= args.maxStallTurns) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function serializeGoalState(state: GoalState): string {\n\treturn JSON.stringify(cloneGoalState(state), null, 2);\n}\n\nexport function parseGoalState(text: string): GoalState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\tif (!isGoalState(parsed)) return undefined;\n\t\treturn cloneGoalState(parsed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -1,9 +1,4 @@
1
- function isRecord(value) {
2
- if (!value || typeof value !== "object" || Array.isArray(value))
3
- return false;
4
- const prototype = Object.getPrototypeOf(value);
5
- return prototype === Object.prototype || prototype === null;
6
- }
1
+ import { isPlainRecord } from "../util/value-guards.js";
7
2
  function isStringArray(value) {
8
3
  return Array.isArray(value) && value.every((item) => typeof item === "string");
9
4
  }
@@ -31,7 +26,7 @@ function hasOptionalFiniteNumber(record, key) {
31
26
  return record[key] === undefined || (typeof record[key] === "number" && Number.isFinite(record[key]));
32
27
  }
33
28
  function isRequirement(value) {
34
- if (!isRecord(value))
29
+ if (!isPlainRecord(value))
35
30
  return false;
36
31
  return (typeof value.id === "string" &&
37
32
  typeof value.text === "string" &&
@@ -44,7 +39,7 @@ function isRequirement(value) {
44
39
  hasOptionalString(value, "boundAt"));
45
40
  }
46
41
  function isGoalEvidenceRef(value) {
47
- if (!isRecord(value))
42
+ if (!isPlainRecord(value))
48
43
  return false;
49
44
  return (typeof value.id === "string" &&
50
45
  isGoalEvidenceKind(value.kind) &&
@@ -54,7 +49,7 @@ function isGoalEvidenceRef(value) {
54
49
  hasOptionalBoolean(value, "verified"));
55
50
  }
56
51
  function isGoalEvent(value) {
57
- if (!isRecord(value) || typeof value.type !== "string" || typeof value.now !== "string")
52
+ if (!isPlainRecord(value) || typeof value.type !== "string" || typeof value.now !== "string")
58
53
  return false;
59
54
  switch (value.type) {
60
55
  case "add_requirement":
@@ -75,7 +70,9 @@ function isGoalEvent(value) {
75
70
  hasOptionalBoolean(value, "verified"));
76
71
  case "progress":
77
72
  case "no_progress":
73
+ return true;
78
74
  case "complete_goal":
75
+ return hasOptionalBoolean(value, "acceptanceOverride");
79
76
  case "complete_goal_manually":
80
77
  case "resume_goal":
81
78
  case "cancel_goal":
@@ -94,7 +91,7 @@ function isGoalEvent(value) {
94
91
  }
95
92
  }
96
93
  export function isGoalState(value) {
97
- if (!isRecord(value))
94
+ if (!isPlainRecord(value))
98
95
  return false;
99
96
  return (typeof value.goalId === "string" &&
100
97
  typeof value.userGoal === "string" &&
@@ -1 +1 @@
1
- {"version":3,"file":"goal-state.js","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"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","sourcesContent":["export type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\" | \"worker\";\n\nexport interface GoalState {\n\tgoalId: string;\n\tuserGoal: string;\n\tstatus: GoalStatus;\n\trequirements: readonly Requirement[];\n\tevidence: readonly GoalEvidenceRef[];\n\tevents: readonly GoalEvent[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlastProgressAt: string;\n\tstallTurns: number;\n\tblockedReason?: string;\n\t/**\n\t * Cumulative continuation turns submitted for this goal across EVERY `continueGoalLoop`\n\t * invocation for its lifetime (idle-driven auto-continues and manual continues alike) —\n\t * durable via goal-state persistence, so it survives process restarts and idle cycles.\n\t * Optional because snapshots persisted before this field existed carry no value; treat\n\t * `undefined` as `0` everywhere it is read (see `applyGoalEvent`'s `record_continuation_budget`\n\t * case and `goal-loop-controller.ts`'s budget check).\n\t */\n\tcontinuationTurnsUsed?: number;\n\t/**\n\t * Cumulative ACTIVE wall-clock milliseconds spent running continuation passes for this goal —\n\t * the sum of each individual pass's own await duration, NOT wall-clock time elapsed between\n\t * passes or during idle gaps. Same backward-compat/undefined-as-0 note as `continuationTurnsUsed`.\n\t */\n\tcontinuationWallClockMs?: number;\n\t/**\n\t * Cumulative USD attributed to this goal's own continuation passes, derived from the session's\n\t * own model spend (`getCostSummary().ownCost` at the persistence dep) — deliberately excludes\n\t * worker/subagent spend, which is tracked and budgeted separately. Same backward-compat note.\n\t */\n\tcontinuationSpendUsd?: number;\n\t/**\n\t * Bookkeeping only: the session's own cumulative cost reading as of the last recorded pass,\n\t * used to derive the NEXT pass's spend delta (`event.sessionCostUsd - continuationSpendCheckpointUsd`)\n\t * while keeping `applyGoalEvent` pure (it consumes one externally-observed absolute reading per\n\t * call rather than reaching for session state itself). Not meaningful read in isolation; `undefined`\n\t * means no pass has been recorded yet, so the first recorded pass establishes the checkpoint with a\n\t * zero delta rather than mis-attributing all pre-goal-loop session spend to that one pass.\n\t */\n\tcontinuationSpendCheckpointUsd?: number;\n\t/**\n\t * Cumulative USD attributed to WORKER/SUBAGENT spend for this goal's lanes (in-process worker\n\t * usage via `addSpawnedUsage`, out-of-process tmux-worker usage via the advisory\n\t * `reportSpawnedUsage` claim) — the counterpart this goal's OWN model spend excludes (see\n\t * {@link continuationSpendUsd}). Populated by the runtime that sums lane spend by goalId; this\n\t * field is only the durable slot. Same backward-compat/undefined-as-0 note as the other\n\t * continuation budget fields. Advisory for out-of-process (tmux) workers — never a hard cap\n\t * across the process boundary.\n\t */\n\tcontinuationWorkerSpendUsd?: number;\n}\n\nexport interface Requirement {\n\tid: string;\n\ttext: string;\n\tstatus: RequirementStatus;\n\tevidenceIds: readonly string[];\n\tblockedReason?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\t/**\n\t * LaneId of a worker dispatched against this requirement (set by the `dispatch_worker` event).\n\t * Recording a binding never satisfies the requirement by itself -- the worker's own completion\n\t * later populates `\"worker\"`-kind evidence and prompts an explicit `satisfy_requirement` pass.\n\t */\n\tboundLaneId?: string;\n\t/**\n\t * ISO timestamp of the moment `boundLaneId` was most recently bound to a REAL lane -- the clock\n\t * the never-hang wait-timeout (`evaluateGoalContinuation`'s `worker_wait_timeout` reasonCode)\n\t * reads to detect a worker that has hung past `maxWorkerWaitMs`. Stamped ONLY when a\n\t * `dispatch_worker` event carries a lane id; a declined dispatch (no lane) leaves this field\n\t * untouched, so no clock starts for a worker that never actually launched.\n\t */\n\tboundAt?: string;\n}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\n\t/**\n\t * Whether `uri` was checked against session records (\"tool\" evidence, a toolCallId) or the\n\t * filesystem (\"file\" evidence, a path) at add_evidence time. `true`/`false` only when the\n\t * ref was checkable; `undefined` when the evidence kind carries no checkable ref (e.g.\n\t * \"user\"/\"finding\"/\"test\", or a \"tool\"/\"file\" entry with no `uri`).\n\t */\n\tverified?: boolean;\n\tcreatedAt: string;\n}\n\nexport type GoalEvent =\n\t| { type: \"add_requirement\"; id: string; text: string; now: string }\n\t| { type: \"satisfy_requirement\"; id: string; evidenceIds: readonly string[]; now: string }\n\t| { type: \"block_requirement\"; id: string; blockedReason: string; now: string }\n\t| { type: \"reopen_requirement\"; id: string; now: string }\n\t| {\n\t\t\ttype: \"dispatch_worker\";\n\t\t\t/** Requirement id the worker is bound to. */\n\t\t\tid: string;\n\t\t\t/** Instructions the worker was (or will be) dispatched with. */\n\t\t\tinstructions: string;\n\t\t\t/**\n\t\t\t * LaneId returned by the tool-layer dispatch side effect. Undefined when that side effect\n\t\t\t * is unwired/stubbed -- the binding is then recorded with no lane target yet.\n\t\t\t */\n\t\t\tlaneId?: string;\n\t\t\tnow: string;\n\t }\n\t| {\n\t\t\ttype: \"add_evidence\";\n\t\t\tid: string;\n\t\t\tkind: GoalEvidenceKind;\n\t\t\tsummary: string;\n\t\t\turi?: string;\n\t\t\t/** See {@link GoalEvidenceRef.verified}; computed by the tool layer before the event is applied. */\n\t\t\tverified?: boolean;\n\t\t\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| {\n\t\t\ttype: \"record_continuation_budget\";\n\t\t\t/** Turns submitted in this pass (currently always 1 — the loop calls once per submitted pass). */\n\t\t\tturns: number;\n\t\t\t/** This pass's own active wall-clock duration, in milliseconds. */\n\t\t\twallClockMs: number;\n\t\t\t/**\n\t\t\t * The session's own cumulative model spend (`getCostSummary().ownCost`) AT THE TIME this pass\n\t\t\t * was recorded — an absolute reading, not a pre-computed delta. See\n\t\t\t * `GoalState.continuationSpendCheckpointUsd` for how the reducer derives the delta.\n\t\t\t */\n\t\t\tsessionCostUsd: number;\n\t\t\tnow: string;\n\t }\n\t| { type: \"complete_goal\"; now: string }\n\t| { type: \"complete_goal_manually\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn (\n\t\tvalue === \"file\" ||\n\t\tvalue === \"test\" ||\n\t\tvalue === \"tool\" ||\n\t\tvalue === \"user\" ||\n\t\tvalue === \"finding\" ||\n\t\tvalue === \"worker\"\n\t);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction hasOptionalBoolean(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"boolean\";\n}\n\nfunction hasOptionalFiniteNumber(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || (typeof record[key] === \"number\" && Number.isFinite(record[key]));\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalString(value, \"boundLaneId\") &&\n\t\thasOptionalString(value, \"boundAt\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\") &&\n\t\thasOptionalBoolean(value, \"verified\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"reopen_requirement\":\n\t\t\treturn typeof value.id === \"string\";\n\t\tcase \"dispatch_worker\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" && typeof value.instructions === \"string\" && hasOptionalString(value, \"laneId\")\n\t\t\t);\n\t\tcase \"add_evidence\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" &&\n\t\t\t\tisGoalEvidenceKind(value.kind) &&\n\t\t\t\ttypeof value.summary === \"string\" &&\n\t\t\t\thasOptionalString(value, \"uri\") &&\n\t\t\t\thasOptionalBoolean(value, \"verified\")\n\t\t\t);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\tcase \"complete_goal\":\n\t\tcase \"complete_goal_manually\":\n\t\tcase \"resume_goal\":\n\t\tcase \"cancel_goal\":\n\t\t\treturn true;\n\t\tcase \"block_goal\":\n\t\t\treturn typeof value.reason === \"string\";\n\t\tcase \"record_continuation_budget\":\n\t\t\treturn (\n\t\t\t\ttypeof value.turns === \"number\" &&\n\t\t\t\tNumber.isFinite(value.turns) &&\n\t\t\t\ttypeof value.wallClockMs === \"number\" &&\n\t\t\t\tNumber.isFinite(value.wallClockMs) &&\n\t\t\t\ttypeof value.sessionCostUsd === \"number\" &&\n\t\t\t\tNumber.isFinite(value.sessionCostUsd)\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationTurnsUsed\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWallClockMs\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendCheckpointUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWorkerSpendUsd\")\n\t);\n}\n\nfunction cloneRequirement(requirement: Requirement): Requirement {\n\treturn {\n\t\t...requirement,\n\t\tevidenceIds: [...requirement.evidenceIds],\n\t};\n}\n\nfunction cloneGoalEvidenceRef(evidence: GoalEvidenceRef): GoalEvidenceRef {\n\treturn { ...evidence };\n}\n\nfunction cloneGoalEvent(event: GoalEvent): GoalEvent {\n\tif (event.type === \"satisfy_requirement\") {\n\t\treturn { ...event, evidenceIds: [...event.evidenceIds] };\n\t}\n\treturn { ...event };\n}\n\nfunction cloneGoalState(state: GoalState): GoalState {\n\treturn {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: state.events.map(cloneGoalEvent),\n\t};\n}\n\nexport function cloneGoalStateForStorage(state: GoalState): GoalState {\n\treturn cloneGoalState(state);\n}\n\nexport function createGoalState(args: { goalId: string; userGoal: string; now: string }): GoalState {\n\treturn {\n\t\tgoalId: args.goalId,\n\t\tuserGoal: args.userGoal,\n\t\tstatus: \"active\",\n\t\trequirements: [],\n\t\tevidence: [],\n\t\tevents: [],\n\t\tcreatedAt: args.now,\n\t\tupdatedAt: args.now,\n\t\tlastProgressAt: args.now,\n\t\tstallTurns: 0,\n\t\tcontinuationTurnsUsed: 0,\n\t\tcontinuationWallClockMs: 0,\n\t\tcontinuationSpendUsd: 0,\n\t\tcontinuationWorkerSpendUsd: 0,\n\t};\n}\n\nexport function applyGoalEvent(state: GoalState, event: GoalEvent): GoalState {\n\tconst newState: GoalState = {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)],\n\t\tupdatedAt: event.now,\n\t};\n\n\tswitch (event.type) {\n\t\tcase \"add_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tconst newRequirement: Requirement = {\n\t\t\t\tid: event.id,\n\t\t\t\ttext: event.text,\n\t\t\t\tstatus: \"open\",\n\t\t\t\tevidenceIds: [],\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.requirements[existingIndex].createdAt : event.now,\n\t\t\t\tupdatedAt: event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = newRequirement;\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t} else {\n\t\t\t\tnewState.requirements = [...newState.requirements, newRequirement];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"satisfy_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"satisfied\",\n\t\t\t\t\tevidenceIds: [...event.evidenceIds],\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\tblockedReason: event.blockedReason,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"reopen_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"open\",\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"dispatch_worker\": {\n\t\t\t// Records the requirement<->lane binding ONLY -- never satisfies the requirement and never\n\t\t\t// touches lastProgressAt/stallTurns. The worker's own completion later populates \"worker\"\n\t\t\t// evidence and prompts an explicit satisfy_requirement pass through the existing gate.\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tboundLaneId: event.laneId,\n\t\t\t\t\t// Start (or keep) the wait-timeout clock ONLY when this dispatch actually bound a real\n\t\t\t\t\t// lane -- a declined dispatch (no laneId) preserves whatever boundAt was already there.\n\t\t\t\t\tboundAt: event.laneId ? event.now : requirement.boundAt,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"add_evidence\": {\n\t\t\tconst existingIndex = newState.evidence.findIndex((evidence) => evidence.id === event.id);\n\t\t\tconst newEvidence: GoalEvidenceRef = {\n\t\t\t\tid: event.id,\n\t\t\t\tkind: event.kind,\n\t\t\t\tsummary: event.summary,\n\t\t\t\turi: event.uri,\n\t\t\t\tverified: event.verified,\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.evidence[existingIndex].createdAt : event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedEvidence = [...newState.evidence];\n\t\t\t\tupdatedEvidence[existingIndex] = newEvidence;\n\t\t\t\tnewState.evidence = updatedEvidence;\n\t\t\t} else {\n\t\t\t\tnewState.evidence = [...newState.evidence, newEvidence];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"progress\": {\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"no_progress\": {\n\t\t\tnewState.stallTurns = state.stallTurns + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"record_continuation_budget\": {\n\t\t\tconst previousCheckpoint = state.continuationSpendCheckpointUsd;\n\t\t\t// No prior checkpoint (first pass ever recorded for this goal): there is no valid \"before\"\n\t\t\t// reading to diff against, so attribute a zero delta for this one pass rather than mis-count\n\t\t\t// all pre-goal-loop session spend into it. Every subsequent pass gets an accurate delta.\n\t\t\tconst spendDelta =\n\t\t\t\tpreviousCheckpoint === undefined ? 0 : Math.max(0, event.sessionCostUsd - previousCheckpoint);\n\t\t\tnewState.continuationTurnsUsed = (state.continuationTurnsUsed ?? 0) + event.turns;\n\t\t\tnewState.continuationWallClockMs = (state.continuationWallClockMs ?? 0) + event.wallClockMs;\n\t\t\tnewState.continuationSpendUsd = (state.continuationSpendUsd ?? 0) + spendDelta;\n\t\t\tnewState.continuationSpendCheckpointUsd = event.sessionCostUsd;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal\": {\n\t\t\tconst hasUnsatisfied = newState.requirements.some((requirement) => requirement.status !== \"satisfied\");\n\t\t\tif (!hasUnsatisfied) {\n\t\t\t\tnewState.status = \"completed\";\n\t\t\t\tnewState.blockedReason = undefined;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal_manually\": {\n\t\t\tnewState.status = \"completed\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_goal\": {\n\t\t\tnewState.status = \"blocked\";\n\t\t\tnewState.blockedReason = event.reason;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"resume_goal\": {\n\t\t\tnewState.status = \"active\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"cancel_goal\": {\n\t\t\tnewState.status = \"cancelled\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn newState;\n}\n\nexport function shouldContinueGoalLoop(args: { state: GoalState; maxStallTurns: number; now: string }): boolean {\n\tif (args.state.status !== \"active\") {\n\t\treturn false;\n\t}\n\tif (args.state.stallTurns >= args.maxStallTurns) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function serializeGoalState(state: GoalState): string {\n\treturn JSON.stringify(cloneGoalState(state), null, 2);\n}\n\nexport function parseGoalState(text: string): GoalState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\tif (!isGoalState(parsed)) return undefined;\n\t\treturn cloneGoalState(parsed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"goal-state.js","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPlainRecord } from \"../util/value-guards.ts\";\n\nexport type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\" | \"worker\";\n\nexport interface GoalState {\n\tgoalId: string;\n\tuserGoal: string;\n\tstatus: GoalStatus;\n\trequirements: readonly Requirement[];\n\tevidence: readonly GoalEvidenceRef[];\n\tevents: readonly GoalEvent[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlastProgressAt: string;\n\tstallTurns: number;\n\tblockedReason?: string;\n\t/**\n\t * Cumulative continuation turns submitted for this goal across EVERY `continueGoalLoop`\n\t * invocation for its lifetime (idle-driven auto-continues and manual continues alike) —\n\t * durable via goal-state persistence, so it survives process restarts and idle cycles.\n\t * Optional because snapshots persisted before this field existed carry no value; treat\n\t * `undefined` as `0` everywhere it is read (see `applyGoalEvent`'s `record_continuation_budget`\n\t * case and `goal-loop-controller.ts`'s budget check).\n\t */\n\tcontinuationTurnsUsed?: number;\n\t/**\n\t * Cumulative ACTIVE wall-clock milliseconds spent running continuation passes for this goal —\n\t * the sum of each individual pass's own await duration, NOT wall-clock time elapsed between\n\t * passes or during idle gaps. Same backward-compat/undefined-as-0 note as `continuationTurnsUsed`.\n\t */\n\tcontinuationWallClockMs?: number;\n\t/**\n\t * Cumulative USD attributed to this goal's own continuation passes, derived from the session's\n\t * own model spend (`getCostSummary().ownCost` at the persistence dep) — deliberately excludes\n\t * worker/subagent spend, which is tracked and budgeted separately. Same backward-compat note.\n\t */\n\tcontinuationSpendUsd?: number;\n\t/**\n\t * Bookkeeping only: the session's own cumulative cost reading as of the last recorded pass,\n\t * used to derive the NEXT pass's spend delta (`event.sessionCostUsd - continuationSpendCheckpointUsd`)\n\t * while keeping `applyGoalEvent` pure (it consumes one externally-observed absolute reading per\n\t * call rather than reaching for session state itself). Not meaningful read in isolation; `undefined`\n\t * means no pass has been recorded yet, so the first recorded pass establishes the checkpoint with a\n\t * zero delta rather than mis-attributing all pre-goal-loop session spend to that one pass.\n\t */\n\tcontinuationSpendCheckpointUsd?: number;\n\t/**\n\t * Cumulative USD attributed to WORKER/SUBAGENT spend for this goal's lanes (in-process worker\n\t * usage via `addSpawnedUsage`, out-of-process tmux-worker usage via the advisory\n\t * `reportSpawnedUsage` claim) — the counterpart this goal's OWN model spend excludes (see\n\t * {@link continuationSpendUsd}). Populated by the runtime that sums lane spend by goalId; this\n\t * field is only the durable slot. Same backward-compat/undefined-as-0 note as the other\n\t * continuation budget fields. Advisory for out-of-process (tmux) workers — never a hard cap\n\t * across the process boundary.\n\t */\n\tcontinuationWorkerSpendUsd?: number;\n}\n\nexport interface Requirement {\n\tid: string;\n\ttext: string;\n\tstatus: RequirementStatus;\n\tevidenceIds: readonly string[];\n\tblockedReason?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\t/**\n\t * LaneId of a worker dispatched against this requirement (set by the `dispatch_worker` event).\n\t * Recording a binding never satisfies the requirement by itself -- the worker's own completion\n\t * later populates `\"worker\"`-kind evidence and prompts an explicit `satisfy_requirement` pass.\n\t */\n\tboundLaneId?: string;\n\t/**\n\t * ISO timestamp of the moment `boundLaneId` was most recently bound to a REAL lane -- the clock\n\t * the never-hang wait-timeout (`evaluateGoalContinuation`'s `worker_wait_timeout` reasonCode)\n\t * reads to detect a worker that has hung past `maxWorkerWaitMs`. Stamped ONLY when a\n\t * `dispatch_worker` event carries a lane id; a declined dispatch (no lane) leaves this field\n\t * untouched, so no clock starts for a worker that never actually launched.\n\t */\n\tboundAt?: string;\n}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\n\t/**\n\t * Whether `uri` was checked against session records (\"tool\" evidence, a toolCallId) or the\n\t * filesystem (\"file\" evidence, a path) at add_evidence time. `true`/`false` only when the\n\t * ref was checkable; `undefined` when the evidence kind carries no checkable ref (e.g.\n\t * \"user\"/\"finding\"/\"test\", or a \"tool\"/\"file\" entry with no `uri`).\n\t */\n\tverified?: boolean;\n\tcreatedAt: string;\n}\n\nexport type GoalEvent =\n\t| { type: \"add_requirement\"; id: string; text: string; now: string }\n\t| { type: \"satisfy_requirement\"; id: string; evidenceIds: readonly string[]; now: string }\n\t| { type: \"block_requirement\"; id: string; blockedReason: string; now: string }\n\t| { type: \"reopen_requirement\"; id: string; now: string }\n\t| {\n\t\t\ttype: \"dispatch_worker\";\n\t\t\t/** Requirement id the worker is bound to. */\n\t\t\tid: string;\n\t\t\t/** Instructions the worker was (or will be) dispatched with. */\n\t\t\tinstructions: string;\n\t\t\t/**\n\t\t\t * LaneId returned by the tool-layer dispatch side effect. Undefined when that side effect\n\t\t\t * is unwired/stubbed -- the binding is then recorded with no lane target yet.\n\t\t\t */\n\t\t\tlaneId?: string;\n\t\t\tnow: string;\n\t }\n\t| {\n\t\t\ttype: \"add_evidence\";\n\t\t\tid: string;\n\t\t\tkind: GoalEvidenceKind;\n\t\t\tsummary: string;\n\t\t\turi?: string;\n\t\t\t/** See {@link GoalEvidenceRef.verified}; computed by the tool layer before the event is applied. */\n\t\t\tverified?: boolean;\n\t\t\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| {\n\t\t\ttype: \"record_continuation_budget\";\n\t\t\t/** Turns submitted in this pass (currently always 1 — the loop calls once per submitted pass). */\n\t\t\tturns: number;\n\t\t\t/** This pass's own active wall-clock duration, in milliseconds. */\n\t\t\twallClockMs: number;\n\t\t\t/**\n\t\t\t * The session's own cumulative model spend (`getCostSummary().ownCost`) AT THE TIME this pass\n\t\t\t * was recorded — an absolute reading, not a pre-computed delta. See\n\t\t\t * `GoalState.continuationSpendCheckpointUsd` for how the reducer derives the delta.\n\t\t\t */\n\t\t\tsessionCostUsd: number;\n\t\t\tnow: string;\n\t }\n\t| { type: \"complete_goal\"; acceptanceOverride?: boolean; now: string }\n\t| { type: \"complete_goal_manually\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn (\n\t\tvalue === \"file\" ||\n\t\tvalue === \"test\" ||\n\t\tvalue === \"tool\" ||\n\t\tvalue === \"user\" ||\n\t\tvalue === \"finding\" ||\n\t\tvalue === \"worker\"\n\t);\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction hasOptionalBoolean(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"boolean\";\n}\n\nfunction hasOptionalFiniteNumber(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || (typeof record[key] === \"number\" && Number.isFinite(record[key]));\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isPlainRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalString(value, \"boundLaneId\") &&\n\t\thasOptionalString(value, \"boundAt\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isPlainRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\") &&\n\t\thasOptionalBoolean(value, \"verified\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isPlainRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"reopen_requirement\":\n\t\t\treturn typeof value.id === \"string\";\n\t\tcase \"dispatch_worker\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" && typeof value.instructions === \"string\" && hasOptionalString(value, \"laneId\")\n\t\t\t);\n\t\tcase \"add_evidence\":\n\t\t\treturn (\n\t\t\t\ttypeof value.id === \"string\" &&\n\t\t\t\tisGoalEvidenceKind(value.kind) &&\n\t\t\t\ttypeof value.summary === \"string\" &&\n\t\t\t\thasOptionalString(value, \"uri\") &&\n\t\t\t\thasOptionalBoolean(value, \"verified\")\n\t\t\t);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\t\treturn true;\n\t\tcase \"complete_goal\":\n\t\t\treturn hasOptionalBoolean(value, \"acceptanceOverride\");\n\t\tcase \"complete_goal_manually\":\n\t\tcase \"resume_goal\":\n\t\tcase \"cancel_goal\":\n\t\t\treturn true;\n\t\tcase \"block_goal\":\n\t\t\treturn typeof value.reason === \"string\";\n\t\tcase \"record_continuation_budget\":\n\t\t\treturn (\n\t\t\t\ttypeof value.turns === \"number\" &&\n\t\t\t\tNumber.isFinite(value.turns) &&\n\t\t\t\ttypeof value.wallClockMs === \"number\" &&\n\t\t\t\tNumber.isFinite(value.wallClockMs) &&\n\t\t\t\ttypeof value.sessionCostUsd === \"number\" &&\n\t\t\t\tNumber.isFinite(value.sessionCostUsd)\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isPlainRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationTurnsUsed\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWallClockMs\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationSpendCheckpointUsd\") &&\n\t\thasOptionalFiniteNumber(value, \"continuationWorkerSpendUsd\")\n\t);\n}\n\nfunction cloneRequirement(requirement: Requirement): Requirement {\n\treturn {\n\t\t...requirement,\n\t\tevidenceIds: [...requirement.evidenceIds],\n\t};\n}\n\nfunction cloneGoalEvidenceRef(evidence: GoalEvidenceRef): GoalEvidenceRef {\n\treturn { ...evidence };\n}\n\nfunction cloneGoalEvent(event: GoalEvent): GoalEvent {\n\tif (event.type === \"satisfy_requirement\") {\n\t\treturn { ...event, evidenceIds: [...event.evidenceIds] };\n\t}\n\treturn { ...event };\n}\n\nfunction cloneGoalState(state: GoalState): GoalState {\n\treturn {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: state.events.map(cloneGoalEvent),\n\t};\n}\n\nexport function cloneGoalStateForStorage(state: GoalState): GoalState {\n\treturn cloneGoalState(state);\n}\n\nexport function createGoalState(args: { goalId: string; userGoal: string; now: string }): GoalState {\n\treturn {\n\t\tgoalId: args.goalId,\n\t\tuserGoal: args.userGoal,\n\t\tstatus: \"active\",\n\t\trequirements: [],\n\t\tevidence: [],\n\t\tevents: [],\n\t\tcreatedAt: args.now,\n\t\tupdatedAt: args.now,\n\t\tlastProgressAt: args.now,\n\t\tstallTurns: 0,\n\t\tcontinuationTurnsUsed: 0,\n\t\tcontinuationWallClockMs: 0,\n\t\tcontinuationSpendUsd: 0,\n\t\tcontinuationWorkerSpendUsd: 0,\n\t};\n}\n\nexport function applyGoalEvent(state: GoalState, event: GoalEvent): GoalState {\n\tconst newState: GoalState = {\n\t\t...state,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)],\n\t\tupdatedAt: event.now,\n\t};\n\n\tswitch (event.type) {\n\t\tcase \"add_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tconst newRequirement: Requirement = {\n\t\t\t\tid: event.id,\n\t\t\t\ttext: event.text,\n\t\t\t\tstatus: \"open\",\n\t\t\t\tevidenceIds: [],\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.requirements[existingIndex].createdAt : event.now,\n\t\t\t\tupdatedAt: event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = newRequirement;\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t} else {\n\t\t\t\tnewState.requirements = [...newState.requirements, newRequirement];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"satisfy_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"satisfied\",\n\t\t\t\t\tevidenceIds: [...event.evidenceIds],\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"blocked\",\n\t\t\t\t\tblockedReason: event.blockedReason,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"reopen_requirement\": {\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tstatus: \"open\",\n\t\t\t\t\tblockedReason: undefined,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"dispatch_worker\": {\n\t\t\t// Records the requirement<->lane binding ONLY -- never satisfies the requirement and never\n\t\t\t// touches lastProgressAt/stallTurns. The worker's own completion later populates \"worker\"\n\t\t\t// evidence and prompts an explicit satisfy_requirement pass through the existing gate.\n\t\t\tconst existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst requirement = newState.requirements[existingIndex];\n\t\t\t\tconst updatedRequirements = [...newState.requirements];\n\t\t\t\tupdatedRequirements[existingIndex] = {\n\t\t\t\t\t...requirement,\n\t\t\t\t\tboundLaneId: event.laneId,\n\t\t\t\t\t// Start (or keep) the wait-timeout clock ONLY when this dispatch actually bound a real\n\t\t\t\t\t// lane -- a declined dispatch (no laneId) preserves whatever boundAt was already there.\n\t\t\t\t\tboundAt: event.laneId ? event.now : requirement.boundAt,\n\t\t\t\t\tupdatedAt: event.now,\n\t\t\t\t};\n\t\t\t\tnewState.requirements = updatedRequirements;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"add_evidence\": {\n\t\t\tconst existingIndex = newState.evidence.findIndex((evidence) => evidence.id === event.id);\n\t\t\tconst newEvidence: GoalEvidenceRef = {\n\t\t\t\tid: event.id,\n\t\t\t\tkind: event.kind,\n\t\t\t\tsummary: event.summary,\n\t\t\t\turi: event.uri,\n\t\t\t\tverified: event.verified,\n\t\t\t\tcreatedAt: existingIndex >= 0 ? newState.evidence[existingIndex].createdAt : event.now,\n\t\t\t};\n\t\t\tif (existingIndex >= 0) {\n\t\t\t\tconst updatedEvidence = [...newState.evidence];\n\t\t\t\tupdatedEvidence[existingIndex] = newEvidence;\n\t\t\t\tnewState.evidence = updatedEvidence;\n\t\t\t} else {\n\t\t\t\tnewState.evidence = [...newState.evidence, newEvidence];\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"progress\": {\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"no_progress\": {\n\t\t\tnewState.stallTurns = state.stallTurns + 1;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"record_continuation_budget\": {\n\t\t\tconst previousCheckpoint = state.continuationSpendCheckpointUsd;\n\t\t\t// No prior checkpoint (first pass ever recorded for this goal): there is no valid \"before\"\n\t\t\t// reading to diff against, so attribute a zero delta for this one pass rather than mis-count\n\t\t\t// all pre-goal-loop session spend into it. Every subsequent pass gets an accurate delta.\n\t\t\tconst spendDelta =\n\t\t\t\tpreviousCheckpoint === undefined ? 0 : Math.max(0, event.sessionCostUsd - previousCheckpoint);\n\t\t\tnewState.continuationTurnsUsed = (state.continuationTurnsUsed ?? 0) + event.turns;\n\t\t\tnewState.continuationWallClockMs = (state.continuationWallClockMs ?? 0) + event.wallClockMs;\n\t\t\tnewState.continuationSpendUsd = (state.continuationSpendUsd ?? 0) + spendDelta;\n\t\t\tnewState.continuationSpendCheckpointUsd = event.sessionCostUsd;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal\": {\n\t\t\tconst hasUnsatisfied = newState.requirements.some((requirement) => requirement.status !== \"satisfied\");\n\t\t\tif (!hasUnsatisfied) {\n\t\t\t\tnewState.status = \"completed\";\n\t\t\t\tnewState.blockedReason = undefined;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"complete_goal_manually\": {\n\t\t\tnewState.status = \"completed\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"block_goal\": {\n\t\t\tnewState.status = \"blocked\";\n\t\t\tnewState.blockedReason = event.reason;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"resume_goal\": {\n\t\t\tnewState.status = \"active\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tnewState.lastProgressAt = event.now;\n\t\t\tnewState.stallTurns = 0;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase \"cancel_goal\": {\n\t\t\tnewState.status = \"cancelled\";\n\t\t\tnewState.blockedReason = undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn newState;\n}\n\nexport function shouldContinueGoalLoop(args: { state: GoalState; maxStallTurns: number; now: string }): boolean {\n\tif (args.state.status !== \"active\") {\n\t\treturn false;\n\t}\n\tif (args.state.stallTurns >= args.maxStallTurns) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function serializeGoalState(state: GoalState): string {\n\treturn JSON.stringify(cloneGoalState(state), null, 2);\n}\n\nexport function parseGoalState(text: string): GoalState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\tif (!isGoalState(parsed)) return undefined;\n\t\treturn cloneGoalState(parsed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -77,7 +77,7 @@ export interface GoalActionFailure {
77
77
  export type GoalActionResult = GoalActionSuccess | GoalActionFailure;
78
78
  export interface ApplyGoalActionOptions {
79
79
  /**
80
- * Gate agent-facing 'complete' on at least one satisfied requirement being backed by
80
+ * Gate agent-facing 'complete' on every satisfied requirement being backed by
81
81
  * verified-ref evidence (kind 'tool'/'file' with `verified === true`) or kind 'user'
82
82
  * evidence. Defaults to `true` (on) when omitted — the conservative default. Manual
83
83
  * completion ({@link completeGoalManually}) is never subject to this gate.
@@ -108,13 +108,15 @@ export declare function summarizeGoalState(state: GoalState, options?: {
108
108
  *
109
109
  * `goal-tool-core` never reads or mutates task state itself (it stays pure); callers that DO
110
110
  * have access to the branch-scoped open task steps (e.g. via `buildGoalRuntimeSnapshot`) may
111
- * pass them through here to surface a nudge in the tool response when an open task_steps step
112
- * appears to reference a requirement the agent just satisfied or completed. Task state is never
113
- * written from goal code — this only reads an already-resolved, caller-supplied summary.
111
+ * pass them through here to surface a nudge in the tool response when an open task_steps step is
112
+ * explicitly linked to, or conservatively appears to reference, a requirement the agent just
113
+ * satisfied or completed. Task state is never written from goal code — this only reads an
114
+ * already-resolved, caller-supplied summary.
114
115
  */
115
116
  export interface OpenTaskStepRef {
116
117
  id: string;
117
118
  content: string;
119
+ requirementIds?: readonly string[];
118
120
  }
119
121
  /**
120
122
  * Nudge lines for open task steps that reference any of `requirementIds` (deduped per
@@ -122,8 +124,8 @@ export interface OpenTaskStepRef {
122
124
  */
123
125
  export declare function findRequirementCrossReferenceNudges(state: GoalState, requirementIds: readonly string[], openTaskSteps: readonly OpenTaskStepRef[]): string[];
124
126
  /**
125
- * After 'satisfy_requirement' or 'complete', nudge lines for open task steps whose content
126
- * references a just-satisfied requirement. Returns `[]` for every other action, or when
127
+ * After 'satisfy_requirement' or 'complete', nudge lines for linked open task steps. Returns `[]`
128
+ * for every other action, or when
127
129
  * `openTaskSteps` was not supplied (the default -- backward compatible, no behavior change for
128
130
  * callers that do not pass task-step context).
129
131
  */
@@ -1 +1 @@
1
- {"version":3,"file":"goal-tool-core.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-tool-core.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n} from \"./goal-state.ts\";\n\n/**\n * Agent-facing goal ledger actions.\n *\n * This is the producer half of the goal continuation pipeline: the agent records\n * what it is trying to achieve and how far it has gotten, and those records become\n * the {@link GoalState} snapshots that the runtime continuation consumer reads.\n *\n * Each action maps onto either {@link createGoalState} or a single\n * {@link GoalEvent}, so the durable state model stays the single source of truth.\n */\nexport type GoalAction =\n\t| { action: \"start\"; goalId: string; userGoal: string }\n\t| { action: \"add_requirement\"; requirementId: string; text: string }\n\t| { action: \"satisfy_requirement\"; requirementId: string; evidenceIds?: readonly string[] }\n\t| { action: \"block_requirement\"; requirementId: string; reason: string }\n\t| { action: \"reopen_requirement\"; requirementId: string }\n\t| {\n\t\t\taction: \"dispatch_worker\";\n\t\t\trequirementId: string;\n\t\t\tinstructions: string;\n\t\t\t/**\n\t\t\t * LaneId returned by the tool layer's dispatch side effect (calling the real worker/tmux\n\t\t\t * dispatch). Computed by the tool layer -- which has session/runtime access -- and merged\n\t\t\t * onto the action before it reaches this pure reducer, exactly like `add_evidence`'s\n\t\t\t * `verified` field. Undefined when the dispatch side effect is unwired/stubbed.\n\t\t\t */\n\t\t\tlaneId?: string;\n\t }\n\t| {\n\t\t\taction: \"add_evidence\";\n\t\t\tevidenceId: string;\n\t\t\tkind: GoalEvidenceKind;\n\t\t\tsummary: string;\n\t\t\turi?: string;\n\t\t\t/**\n\t\t\t * Whether `uri` was checked against session records/the filesystem. Computed by the\n\t\t\t * tool layer (which has session/filesystem access); `applyGoalAction` stays pure and\n\t\t\t * only carries this value through into the recorded {@link GoalEvidenceRef}.\n\t\t\t */\n\t\t\tverified?: boolean;\n\t }\n\t| { action: \"progress\" }\n\t| { action: \"no_progress\" }\n\t| { action: \"complete\" }\n\t| { action: \"block_goal\"; reason: string }\n\t| { action: \"resume_goal\" }\n\t| { action: \"cancel\" };\n\nexport type GoalActionName = GoalAction[\"action\"];\n\nexport interface GoalActionSuccess {\n\tok: true;\n\tstate: GoalState;\n}\n\nexport interface GoalActionFailure {\n\tok: false;\n\terror: string;\n}\n\nexport type GoalActionResult = GoalActionSuccess | GoalActionFailure;\n\nexport interface ApplyGoalActionOptions {\n\t/**\n\t * Gate agent-facing 'complete' on at least one satisfied requirement being backed by\n\t * verified-ref evidence (kind 'tool'/'file' with `verified === true`) or kind 'user'\n\t * evidence. Defaults to `true` (on) when omitted — the conservative default. Manual\n\t * completion ({@link completeGoalManually}) is never subject to this gate.\n\t */\n\trequireVerifiedEvidenceForCompletion?: boolean;\n}\n\nfunction requirementExists(state: GoalState, requirementId: string): boolean {\n\treturn state.requirements.some((requirement) => requirement.id === requirementId);\n}\n\nfunction evidenceExists(state: GoalState, evidenceId: string): boolean {\n\treturn state.evidence.some((evidence) => evidence.id === evidenceId);\n}\n\nfunction isVerifiedOrUserEvidence(evidence: GoalState[\"evidence\"][number]): boolean {\n\treturn evidence.kind === \"user\" || evidence.verified === true;\n}\n\n/** Does at least one SATISFIED requirement cite evidence that is verified-ref or kind:'user'? */\nfunction hasEvidenceBackedSatisfaction(state: GoalState): boolean {\n\treturn state.requirements.some((requirement) => {\n\t\tif (requirement.status !== \"satisfied\") return false;\n\t\treturn requirement.evidenceIds.some((evidenceId) => {\n\t\t\tconst evidence = state.evidence.find((candidate) => candidate.id === evidenceId);\n\t\t\treturn evidence !== undefined && isVerifiedOrUserEvidence(evidence);\n\t\t});\n\t});\n}\n\n/**\n * Apply one agent-facing goal action to the current ledger state.\n *\n * Pure: takes the current state (or `undefined` when no goal exists yet) and the\n * action, and returns either the next state or a validation error. Performs no\n * I/O and never mutates its inputs.\n */\nexport function applyGoalAction(\n\tcurrent: GoalState | undefined,\n\taction: GoalAction,\n\tnow: string,\n\toptions?: ApplyGoalActionOptions,\n): GoalActionResult {\n\tif (action.action === \"start\") {\n\t\tconst goalId = action.goalId.trim();\n\t\tconst userGoal = action.userGoal.trim();\n\t\tif (!goalId) return { ok: false, error: \"start requires a non-empty goalId.\" };\n\t\tif (!userGoal) return { ok: false, error: \"start requires a non-empty userGoal.\" };\n\t\tif (current && current.status === \"active\" && current.goalId !== goalId) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `An active goal '${current.goalId}' already exists. Complete, block, or cancel it before starting '${goalId}'.`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, state: createGoalState({ goalId, userGoal, now }) };\n\t}\n\n\tif (!current) {\n\t\treturn { ok: false, error: \"No active goal. Use action 'start' before recording goal updates.\" };\n\t}\n\n\tif (action.action === \"resume_goal\") {\n\t\tif (current.status !== \"blocked\") {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `Goal '${current.goalId}' is ${current.status}; only blocked goals can be resumed.`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, state: applyGoalEvent(current, { type: \"resume_goal\", now }) };\n\t}\n\n\tif (current.status !== \"active\") {\n\t\tif (current.status === \"blocked\" && action.action === \"cancel\") {\n\t\t\treturn { ok: true, state: applyGoalEvent(current, { type: \"cancel_goal\", now }) };\n\t\t}\n\t\tconst recovery =\n\t\t\tcurrent.status === \"blocked\"\n\t\t\t\t? \"Resume it with action 'resume_goal', cancel it, or start a replacement goal.\"\n\t\t\t\t: \"Start a new goal before recording updates.\";\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: `Goal '${current.goalId}' is ${current.status}. ${recovery}`,\n\t\t};\n\t}\n\n\tconst event = toGoalEvent(current, action, now, options);\n\tif (!event.ok) return event;\n\treturn { ok: true, state: applyGoalEvent(current, event.event) };\n}\n\ntype ToGoalEventResult = { ok: true; event: GoalEvent } | GoalActionFailure;\n\nfunction toGoalEvent(\n\tstate: GoalState,\n\taction: GoalAction,\n\tnow: string,\n\toptions: ApplyGoalActionOptions | undefined,\n): ToGoalEventResult {\n\tswitch (action.action) {\n\t\tcase \"add_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tconst text = action.text.trim();\n\t\t\tif (!id) return { ok: false, error: \"add_requirement requires a non-empty requirementId.\" };\n\t\t\tif (!text) return { ok: false, error: \"add_requirement requires non-empty text.\" };\n\t\t\tif (requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Requirement '${id}' already exists.` };\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"add_requirement\", id, text, now } };\n\t\t}\n\t\tcase \"satisfy_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tif (!id) return { ok: false, error: \"satisfy_requirement requires a non-empty requirementId.\" };\n\t\t\tif (!requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\tconst evidenceIds = action.evidenceIds ?? [];\n\t\t\tfor (const evidenceId of evidenceIds) {\n\t\t\t\tif (!evidenceExists(state, evidenceId)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\terror: `Unknown evidence '${evidenceId}'. Record it with action 'add_evidence' first.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"satisfy_requirement\", id, evidenceIds: [...evidenceIds], now } };\n\t\t}\n\t\tcase \"block_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!id) return { ok: false, error: \"block_requirement requires a non-empty requirementId.\" };\n\t\t\tif (!reason) return { ok: false, error: \"block_requirement requires a non-empty reason.\" };\n\t\t\tif (!requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"block_requirement\", id, blockedReason: reason, now } };\n\t\t}\n\t\tcase \"reopen_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tif (!id) return { ok: false, error: \"reopen_requirement requires a non-empty requirementId.\" };\n\t\t\tconst requirement = state.requirements.find((candidate) => candidate.id === id);\n\t\t\tif (!requirement) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\tif (requirement.status !== \"blocked\") {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `Requirement '${id}' is ${requirement.status}; only blocked requirements can be reopened.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"reopen_requirement\", id, now } };\n\t\t}\n\t\tcase \"dispatch_worker\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tconst instructions = action.instructions.trim();\n\t\t\tif (!id) return { ok: false, error: \"dispatch_worker requires a non-empty requirementId.\" };\n\t\t\tif (!instructions) return { ok: false, error: \"dispatch_worker requires non-empty instructions.\" };\n\t\t\tif (!requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"dispatch_worker\", id, instructions, laneId: action.laneId, now } };\n\t\t}\n\t\tcase \"add_evidence\": {\n\t\t\tconst id = action.evidenceId.trim();\n\t\t\tconst summary = action.summary.trim();\n\t\t\tif (!id) return { ok: false, error: \"add_evidence requires a non-empty evidenceId.\" };\n\t\t\tif (!summary) return { ok: false, error: \"add_evidence requires a non-empty summary.\" };\n\t\t\tif (evidenceExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Evidence '${id}' already exists.` };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tevent: {\n\t\t\t\t\ttype: \"add_evidence\",\n\t\t\t\t\tid,\n\t\t\t\t\tkind: action.kind,\n\t\t\t\t\tsummary,\n\t\t\t\t\turi: action.uri?.trim() || undefined,\n\t\t\t\t\tverified: action.verified,\n\t\t\t\t\tnow,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { ok: true, event: { type: \"progress\", now } };\n\t\tcase \"no_progress\":\n\t\t\treturn { ok: true, event: { type: \"no_progress\", now } };\n\t\tcase \"complete\": {\n\t\t\tconst unsatisfied = state.requirements.filter((requirement) => requirement.status !== \"satisfied\");\n\t\t\tif (unsatisfied.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `Cannot complete goal: ${unsatisfied.length} requirement(s) not satisfied (${unsatisfied\n\t\t\t\t\t\t.map((requirement) => requirement.id)\n\t\t\t\t\t\t.join(\", \")}).`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst requireVerifiedEvidence = options?.requireVerifiedEvidenceForCompletion ?? true;\n\t\t\tif (requireVerifiedEvidence && !hasEvidenceBackedSatisfaction(state)) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: \"Cannot complete goal: no satisfied requirement is backed by verified evidence (kind 'tool'/'file' with a validated ref) or kind 'user' evidence. Record such evidence with 'add_evidence' and cite it in 'satisfy_requirement'.\",\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"complete_goal\", now } };\n\t\t}\n\t\tcase \"block_goal\": {\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!reason) return { ok: false, error: \"block_goal requires a non-empty reason.\" };\n\t\t\treturn { ok: true, event: { type: \"block_goal\", reason, now } };\n\t\t}\n\t\tcase \"resume_goal\":\n\t\t\treturn { ok: true, event: { type: \"resume_goal\", now } };\n\t\tcase \"cancel\":\n\t\t\treturn { ok: true, event: { type: \"cancel_goal\", now } };\n\t\tdefault:\n\t\t\treturn { ok: false, error: \"Unknown goal action.\" };\n\t}\n}\n\n/**\n * Complete a goal on explicit user authority, even when requirements remain open or\n * blocked. Agent-facing `complete` stays evidence-gated; this path is reserved for\n * direct user lifecycle controls.\n */\nexport function completeGoalManually(current: GoalState | undefined, now: string): GoalActionResult {\n\tif (!current) {\n\t\treturn { ok: false, error: \"No goal exists to complete.\" };\n\t}\n\tif (current.status === \"completed\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is already completed.` };\n\t}\n\tif (current.status === \"cancelled\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is cancelled; start or override with a new goal.` };\n\t}\n\treturn { ok: true, state: applyGoalEvent(current, { type: \"complete_goal_manually\", now }) };\n}\n\n/** Render a compact human-readable summary of the ledger after an action. */\nexport function summarizeGoalState(\n\tstate: GoalState,\n\toptions?: { action?: GoalAction; openTaskSteps?: readonly OpenTaskStepRef[] },\n): string {\n\tconst open = state.requirements.filter((requirement) => requirement.status === \"open\").length;\n\tconst satisfied = state.requirements.filter((requirement) => requirement.status === \"satisfied\").length;\n\tconst blocked = state.requirements.filter((requirement) => requirement.status === \"blocked\").length;\n\tconst lines = [\n\t\t`Goal '${state.goalId}' (${state.status}): ${state.userGoal}`,\n\t\t`Requirements: ${state.requirements.length} total — ${open} open, ${satisfied} satisfied, ${blocked} blocked.`,\n\t\t`Evidence: ${state.evidence.length}. Stall turns: ${state.stallTurns}.`,\n\t];\n\tif (state.blockedReason) lines.push(`Blocked reason: ${state.blockedReason}`);\n\tif (options?.action) {\n\t\tlines.push(...buildGoalTaskCrossVisibilityNudges(options.action, state, options.openTaskSteps));\n\t}\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Read-only goal⇄task cross-visibility (bounded slice — no shared state machine).\n *\n * `goal-tool-core` never reads or mutates task state itself (it stays pure); callers that DO\n * have access to the branch-scoped open task steps (e.g. via `buildGoalRuntimeSnapshot`) may\n * pass them through here to surface a nudge in the tool response when an open task_steps step\n * appears to reference a requirement the agent just satisfied or completed. Task state is never\n * written from goal code — this only reads an already-resolved, caller-supplied summary.\n */\nexport interface OpenTaskStepRef {\n\tid: string;\n\tcontent: string;\n}\n\nfunction escapeRegExp(text: string): string {\n\treturn text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Cheap, conservative cross-reference: an open task step \"references\" a requirement when its\n * content contains the requirement id as a whole token (not a substring of a longer token), or\n * contains the requirement's full text verbatim (case-insensitive). Both conditions are chosen\n * to avoid noisy partial-word matches -- a short common id or a coincidental few-word overlap\n * does not qualify.\n */\nfunction taskStepReferencesRequirement(step: OpenTaskStepRef, requirement: { id: string; text: string }): boolean {\n\tconst idToken = requirement.id.trim();\n\tif (idToken.length >= 2) {\n\t\tconst idPattern = new RegExp(`(^|[^a-z0-9])${escapeRegExp(idToken.toLocaleLowerCase())}([^a-z0-9]|$)`, \"i\");\n\t\tif (idPattern.test(step.content)) return true;\n\t}\n\tconst text = requirement.text.trim();\n\tif (text.length >= 8 && step.content.toLocaleLowerCase().includes(text.toLocaleLowerCase())) return true;\n\treturn false;\n}\n\n/**\n * Nudge lines for open task steps that reference any of `requirementIds` (deduped per\n * requirement, one line naming every referencing step). Empty when there is nothing to say.\n */\nexport function findRequirementCrossReferenceNudges(\n\tstate: GoalState,\n\trequirementIds: readonly string[],\n\topenTaskSteps: readonly OpenTaskStepRef[],\n): string[] {\n\tif (openTaskSteps.length === 0 || requirementIds.length === 0) return [];\n\tconst nudges: string[] = [];\n\tfor (const requirementId of requirementIds) {\n\t\tconst requirement = state.requirements.find((candidate) => candidate.id === requirementId);\n\t\tif (!requirement) continue;\n\t\tconst referencing = openTaskSteps.filter((step) => taskStepReferencesRequirement(step, requirement));\n\t\tif (referencing.length === 0) continue;\n\t\tconst stepList = referencing.map((step) => step.id).join(\", \");\n\t\tnudges.push(\n\t\t\t`Note: open task step(s) ${stepList} appear to reference satisfied requirement '${requirement.id}' -- consider updating them via task_steps once covered.`,\n\t\t);\n\t}\n\treturn nudges;\n}\n\n/**\n * After 'satisfy_requirement' or 'complete', nudge lines for open task steps whose content\n * references a just-satisfied requirement. Returns `[]` for every other action, or when\n * `openTaskSteps` was not supplied (the default -- backward compatible, no behavior change for\n * callers that do not pass task-step context).\n */\nexport function buildGoalTaskCrossVisibilityNudges(\n\taction: GoalAction,\n\tstate: GoalState,\n\topenTaskSteps: readonly OpenTaskStepRef[] | undefined,\n): string[] {\n\tif (!openTaskSteps || openTaskSteps.length === 0) return [];\n\tif (action.action === \"satisfy_requirement\") {\n\t\treturn findRequirementCrossReferenceNudges(state, [action.requirementId.trim()], openTaskSteps);\n\t}\n\tif (action.action === \"complete\") {\n\t\tconst satisfiedIds = state.requirements\n\t\t\t.filter((requirement) => requirement.status === \"satisfied\")\n\t\t\t.map((requirement) => requirement.id);\n\t\treturn findRequirementCrossReferenceNudges(state, satisfiedIds, openTaskSteps);\n\t}\n\treturn [];\n}\n"]}
1
+ {"version":3,"file":"goal-tool-core.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-tool-core.ts"],"names":[],"mappings":"AAEA,OAAO,EAIN,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GACnB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,MAAM,EAAE,qBAAqB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACzF;IAAE,MAAM,EAAE,mBAAmB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACvD;IACA,MAAM,EAAE,iBAAiB,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACf,GACD;IACA,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CAClB,GACD;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExB,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AAElD,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACtC;;;;;OAKG;IACH,oCAAoC,CAAC,EAAE,OAAO,CAAC;CAC/C;AAUD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,SAAS,GAAG,SAAS,EAC9B,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,sBAAsB,GAC9B,gBAAgB,CA8ClB;AAuID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAWlG;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,GAC3E,MAAM,CAcR;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAClD,KAAK,EAAE,SAAS,EAChB,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,aAAa,EAAE,SAAS,eAAe,EAAE,GACvC,MAAM,EAAE,CAcV;AAED;;;;;GAKG;AACH,wBAAgB,kCAAkC,CACjD,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,SAAS,EAChB,aAAa,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,GACnD,MAAM,EAAE,CAYV","sourcesContent":["import { taskStepReferencesRequirement } from \"../tasks/task-projection.ts\";\nimport { getUnprovenGoalRequirementIds } from \"./goal-acceptance.ts\";\nimport {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n} from \"./goal-state.ts\";\n\n/**\n * Agent-facing goal ledger actions.\n *\n * This is the producer half of the goal continuation pipeline: the agent records\n * what it is trying to achieve and how far it has gotten, and those records become\n * the {@link GoalState} snapshots that the runtime continuation consumer reads.\n *\n * Each action maps onto either {@link createGoalState} or a single\n * {@link GoalEvent}, so the durable state model stays the single source of truth.\n */\nexport type GoalAction =\n\t| { action: \"start\"; goalId: string; userGoal: string }\n\t| { action: \"add_requirement\"; requirementId: string; text: string }\n\t| { action: \"satisfy_requirement\"; requirementId: string; evidenceIds?: readonly string[] }\n\t| { action: \"block_requirement\"; requirementId: string; reason: string }\n\t| { action: \"reopen_requirement\"; requirementId: string }\n\t| {\n\t\t\taction: \"dispatch_worker\";\n\t\t\trequirementId: string;\n\t\t\tinstructions: string;\n\t\t\t/**\n\t\t\t * LaneId returned by the tool layer's dispatch side effect (calling the real worker/tmux\n\t\t\t * dispatch). Computed by the tool layer -- which has session/runtime access -- and merged\n\t\t\t * onto the action before it reaches this pure reducer, exactly like `add_evidence`'s\n\t\t\t * `verified` field. Undefined when the dispatch side effect is unwired/stubbed.\n\t\t\t */\n\t\t\tlaneId?: string;\n\t }\n\t| {\n\t\t\taction: \"add_evidence\";\n\t\t\tevidenceId: string;\n\t\t\tkind: GoalEvidenceKind;\n\t\t\tsummary: string;\n\t\t\turi?: string;\n\t\t\t/**\n\t\t\t * Whether `uri` was checked against session records/the filesystem. Computed by the\n\t\t\t * tool layer (which has session/filesystem access); `applyGoalAction` stays pure and\n\t\t\t * only carries this value through into the recorded {@link GoalEvidenceRef}.\n\t\t\t */\n\t\t\tverified?: boolean;\n\t }\n\t| { action: \"progress\" }\n\t| { action: \"no_progress\" }\n\t| { action: \"complete\" }\n\t| { action: \"block_goal\"; reason: string }\n\t| { action: \"resume_goal\" }\n\t| { action: \"cancel\" };\n\nexport type GoalActionName = GoalAction[\"action\"];\n\nexport interface GoalActionSuccess {\n\tok: true;\n\tstate: GoalState;\n}\n\nexport interface GoalActionFailure {\n\tok: false;\n\terror: string;\n}\n\nexport type GoalActionResult = GoalActionSuccess | GoalActionFailure;\n\nexport interface ApplyGoalActionOptions {\n\t/**\n\t * Gate agent-facing 'complete' on every satisfied requirement being backed by\n\t * verified-ref evidence (kind 'tool'/'file' with `verified === true`) or kind 'user'\n\t * evidence. Defaults to `true` (on) when omitted — the conservative default. Manual\n\t * completion ({@link completeGoalManually}) is never subject to this gate.\n\t */\n\trequireVerifiedEvidenceForCompletion?: boolean;\n}\n\nfunction requirementExists(state: GoalState, requirementId: string): boolean {\n\treturn state.requirements.some((requirement) => requirement.id === requirementId);\n}\n\nfunction evidenceExists(state: GoalState, evidenceId: string): boolean {\n\treturn state.evidence.some((evidence) => evidence.id === evidenceId);\n}\n\n/**\n * Apply one agent-facing goal action to the current ledger state.\n *\n * Pure: takes the current state (or `undefined` when no goal exists yet) and the\n * action, and returns either the next state or a validation error. Performs no\n * I/O and never mutates its inputs.\n */\nexport function applyGoalAction(\n\tcurrent: GoalState | undefined,\n\taction: GoalAction,\n\tnow: string,\n\toptions?: ApplyGoalActionOptions,\n): GoalActionResult {\n\tif (action.action === \"start\") {\n\t\tconst goalId = action.goalId.trim();\n\t\tconst userGoal = action.userGoal.trim();\n\t\tif (!goalId) return { ok: false, error: \"start requires a non-empty goalId.\" };\n\t\tif (!userGoal) return { ok: false, error: \"start requires a non-empty userGoal.\" };\n\t\tif (current && current.status === \"active\" && current.goalId !== goalId) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `An active goal '${current.goalId}' already exists. Complete, block, or cancel it before starting '${goalId}'.`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, state: createGoalState({ goalId, userGoal, now }) };\n\t}\n\n\tif (!current) {\n\t\treturn { ok: false, error: \"No active goal. Use action 'start' before recording goal updates.\" };\n\t}\n\n\tif (action.action === \"resume_goal\") {\n\t\tif (current.status !== \"blocked\") {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `Goal '${current.goalId}' is ${current.status}; only blocked goals can be resumed.`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, state: applyGoalEvent(current, { type: \"resume_goal\", now }) };\n\t}\n\n\tif (current.status !== \"active\") {\n\t\tif (current.status === \"blocked\" && action.action === \"cancel\") {\n\t\t\treturn { ok: true, state: applyGoalEvent(current, { type: \"cancel_goal\", now }) };\n\t\t}\n\t\tconst recovery =\n\t\t\tcurrent.status === \"blocked\"\n\t\t\t\t? \"Resume it with action 'resume_goal', cancel it, or start a replacement goal.\"\n\t\t\t\t: \"Start a new goal before recording updates.\";\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: `Goal '${current.goalId}' is ${current.status}. ${recovery}`,\n\t\t};\n\t}\n\n\tconst event = toGoalEvent(current, action, now, options);\n\tif (!event.ok) return event;\n\treturn { ok: true, state: applyGoalEvent(current, event.event) };\n}\n\ntype ToGoalEventResult = { ok: true; event: GoalEvent } | GoalActionFailure;\n\nfunction toGoalEvent(\n\tstate: GoalState,\n\taction: GoalAction,\n\tnow: string,\n\toptions: ApplyGoalActionOptions | undefined,\n): ToGoalEventResult {\n\tswitch (action.action) {\n\t\tcase \"add_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tconst text = action.text.trim();\n\t\t\tif (!id) return { ok: false, error: \"add_requirement requires a non-empty requirementId.\" };\n\t\t\tif (!text) return { ok: false, error: \"add_requirement requires non-empty text.\" };\n\t\t\tif (requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Requirement '${id}' already exists.` };\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"add_requirement\", id, text, now } };\n\t\t}\n\t\tcase \"satisfy_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tif (!id) return { ok: false, error: \"satisfy_requirement requires a non-empty requirementId.\" };\n\t\t\tif (!requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\tconst evidenceIds = action.evidenceIds ?? [];\n\t\t\tfor (const evidenceId of evidenceIds) {\n\t\t\t\tif (!evidenceExists(state, evidenceId)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: false,\n\t\t\t\t\t\terror: `Unknown evidence '${evidenceId}'. Record it with action 'add_evidence' first.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"satisfy_requirement\", id, evidenceIds: [...evidenceIds], now } };\n\t\t}\n\t\tcase \"block_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!id) return { ok: false, error: \"block_requirement requires a non-empty requirementId.\" };\n\t\t\tif (!reason) return { ok: false, error: \"block_requirement requires a non-empty reason.\" };\n\t\t\tif (!requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"block_requirement\", id, blockedReason: reason, now } };\n\t\t}\n\t\tcase \"reopen_requirement\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tif (!id) return { ok: false, error: \"reopen_requirement requires a non-empty requirementId.\" };\n\t\t\tconst requirement = state.requirements.find((candidate) => candidate.id === id);\n\t\t\tif (!requirement) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\tif (requirement.status !== \"blocked\") {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `Requirement '${id}' is ${requirement.status}; only blocked requirements can be reopened.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"reopen_requirement\", id, now } };\n\t\t}\n\t\tcase \"dispatch_worker\": {\n\t\t\tconst id = action.requirementId.trim();\n\t\t\tconst instructions = action.instructions.trim();\n\t\t\tif (!id) return { ok: false, error: \"dispatch_worker requires a non-empty requirementId.\" };\n\t\t\tif (!instructions) return { ok: false, error: \"dispatch_worker requires non-empty instructions.\" };\n\t\t\tif (!requirementExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Unknown requirement '${id}'.` };\n\t\t\t}\n\t\t\treturn { ok: true, event: { type: \"dispatch_worker\", id, instructions, laneId: action.laneId, now } };\n\t\t}\n\t\tcase \"add_evidence\": {\n\t\t\tconst id = action.evidenceId.trim();\n\t\t\tconst summary = action.summary.trim();\n\t\t\tif (!id) return { ok: false, error: \"add_evidence requires a non-empty evidenceId.\" };\n\t\t\tif (!summary) return { ok: false, error: \"add_evidence requires a non-empty summary.\" };\n\t\t\tif (evidenceExists(state, id)) {\n\t\t\t\treturn { ok: false, error: `Evidence '${id}' already exists.` };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tevent: {\n\t\t\t\t\ttype: \"add_evidence\",\n\t\t\t\t\tid,\n\t\t\t\t\tkind: action.kind,\n\t\t\t\t\tsummary,\n\t\t\t\t\turi: action.uri?.trim() || undefined,\n\t\t\t\t\tverified: action.verified,\n\t\t\t\t\tnow,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tcase \"progress\":\n\t\t\treturn { ok: true, event: { type: \"progress\", now } };\n\t\tcase \"no_progress\":\n\t\t\treturn { ok: true, event: { type: \"no_progress\", now } };\n\t\tcase \"complete\": {\n\t\t\tconst unsatisfied = state.requirements.filter((requirement) => requirement.status !== \"satisfied\");\n\t\t\tif (unsatisfied.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `Cannot complete goal: ${unsatisfied.length} requirement(s) not satisfied (${unsatisfied\n\t\t\t\t\t\t.map((requirement) => requirement.id)\n\t\t\t\t\t\t.join(\", \")}).`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst requireVerifiedEvidence = options?.requireVerifiedEvidenceForCompletion ?? true;\n\t\t\tconst unprovenRequirementIds = getUnprovenGoalRequirementIds(state);\n\t\t\tif (requireVerifiedEvidence && unprovenRequirementIds.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: `Cannot complete goal: requirement(s) lack verified evidence (${unprovenRequirementIds.join(\", \")}). Record verified or user-confirmed evidence and cite it in satisfy_requirement.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tevent: { type: \"complete_goal\", acceptanceOverride: !requireVerifiedEvidence, now },\n\t\t\t};\n\t\t}\n\t\tcase \"block_goal\": {\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!reason) return { ok: false, error: \"block_goal requires a non-empty reason.\" };\n\t\t\treturn { ok: true, event: { type: \"block_goal\", reason, now } };\n\t\t}\n\t\tcase \"resume_goal\":\n\t\t\treturn { ok: true, event: { type: \"resume_goal\", now } };\n\t\tcase \"cancel\":\n\t\t\treturn { ok: true, event: { type: \"cancel_goal\", now } };\n\t\tdefault:\n\t\t\treturn { ok: false, error: \"Unknown goal action.\" };\n\t}\n}\n\n/**\n * Complete a goal on explicit user authority, even when requirements remain open or\n * blocked. Agent-facing `complete` stays evidence-gated; this path is reserved for\n * direct user lifecycle controls.\n */\nexport function completeGoalManually(current: GoalState | undefined, now: string): GoalActionResult {\n\tif (!current) {\n\t\treturn { ok: false, error: \"No goal exists to complete.\" };\n\t}\n\tif (current.status === \"completed\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is already completed.` };\n\t}\n\tif (current.status === \"cancelled\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is cancelled; start or override with a new goal.` };\n\t}\n\treturn { ok: true, state: applyGoalEvent(current, { type: \"complete_goal_manually\", now }) };\n}\n\n/** Render a compact human-readable summary of the ledger after an action. */\nexport function summarizeGoalState(\n\tstate: GoalState,\n\toptions?: { action?: GoalAction; openTaskSteps?: readonly OpenTaskStepRef[] },\n): string {\n\tconst open = state.requirements.filter((requirement) => requirement.status === \"open\").length;\n\tconst satisfied = state.requirements.filter((requirement) => requirement.status === \"satisfied\").length;\n\tconst blocked = state.requirements.filter((requirement) => requirement.status === \"blocked\").length;\n\tconst lines = [\n\t\t`Goal '${state.goalId}' (${state.status}): ${state.userGoal}`,\n\t\t`Requirements: ${state.requirements.length} total — ${open} open, ${satisfied} satisfied, ${blocked} blocked.`,\n\t\t`Evidence: ${state.evidence.length}. Stall turns: ${state.stallTurns}.`,\n\t];\n\tif (state.blockedReason) lines.push(`Blocked reason: ${state.blockedReason}`);\n\tif (options?.action) {\n\t\tlines.push(...buildGoalTaskCrossVisibilityNudges(options.action, state, options.openTaskSteps));\n\t}\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Read-only goal⇄task cross-visibility (bounded slice — no shared state machine).\n *\n * `goal-tool-core` never reads or mutates task state itself (it stays pure); callers that DO\n * have access to the branch-scoped open task steps (e.g. via `buildGoalRuntimeSnapshot`) may\n * pass them through here to surface a nudge in the tool response when an open task_steps step is\n * explicitly linked to, or conservatively appears to reference, a requirement the agent just\n * satisfied or completed. Task state is never written from goal code — this only reads an\n * already-resolved, caller-supplied summary.\n */\nexport interface OpenTaskStepRef {\n\tid: string;\n\tcontent: string;\n\trequirementIds?: readonly string[];\n}\n\n/**\n * Nudge lines for open task steps that reference any of `requirementIds` (deduped per\n * requirement, one line naming every referencing step). Empty when there is nothing to say.\n */\nexport function findRequirementCrossReferenceNudges(\n\tstate: GoalState,\n\trequirementIds: readonly string[],\n\topenTaskSteps: readonly OpenTaskStepRef[],\n): string[] {\n\tif (openTaskSteps.length === 0 || requirementIds.length === 0) return [];\n\tconst nudges: string[] = [];\n\tfor (const requirementId of requirementIds) {\n\t\tconst requirement = state.requirements.find((candidate) => candidate.id === requirementId);\n\t\tif (!requirement) continue;\n\t\tconst referencing = openTaskSteps.filter((step) => taskStepReferencesRequirement(step, requirement));\n\t\tif (referencing.length === 0) continue;\n\t\tconst stepList = referencing.map((step) => step.id).join(\", \");\n\t\tnudges.push(\n\t\t\t`Note: open task step(s) ${stepList} appear to reference satisfied requirement '${requirement.id}' -- consider updating them via task_steps once covered.`,\n\t\t);\n\t}\n\treturn nudges;\n}\n\n/**\n * After 'satisfy_requirement' or 'complete', nudge lines for linked open task steps. Returns `[]`\n * for every other action, or when\n * `openTaskSteps` was not supplied (the default -- backward compatible, no behavior change for\n * callers that do not pass task-step context).\n */\nexport function buildGoalTaskCrossVisibilityNudges(\n\taction: GoalAction,\n\tstate: GoalState,\n\topenTaskSteps: readonly OpenTaskStepRef[] | undefined,\n): string[] {\n\tif (!openTaskSteps || openTaskSteps.length === 0) return [];\n\tif (action.action === \"satisfy_requirement\") {\n\t\treturn findRequirementCrossReferenceNudges(state, [action.requirementId.trim()], openTaskSteps);\n\t}\n\tif (action.action === \"complete\") {\n\t\tconst satisfiedIds = state.requirements\n\t\t\t.filter((requirement) => requirement.status === \"satisfied\")\n\t\t\t.map((requirement) => requirement.id);\n\t\treturn findRequirementCrossReferenceNudges(state, satisfiedIds, openTaskSteps);\n\t}\n\treturn [];\n}\n"]}
@@ -1,3 +1,5 @@
1
+ import { taskStepReferencesRequirement } from "../tasks/task-projection.js";
2
+ import { getUnprovenGoalRequirementIds } from "./goal-acceptance.js";
1
3
  import { applyGoalEvent, createGoalState, } from "./goal-state.js";
2
4
  function requirementExists(state, requirementId) {
3
5
  return state.requirements.some((requirement) => requirement.id === requirementId);
@@ -5,20 +7,6 @@ function requirementExists(state, requirementId) {
5
7
  function evidenceExists(state, evidenceId) {
6
8
  return state.evidence.some((evidence) => evidence.id === evidenceId);
7
9
  }
8
- function isVerifiedOrUserEvidence(evidence) {
9
- return evidence.kind === "user" || evidence.verified === true;
10
- }
11
- /** Does at least one SATISFIED requirement cite evidence that is verified-ref or kind:'user'? */
12
- function hasEvidenceBackedSatisfaction(state) {
13
- return state.requirements.some((requirement) => {
14
- if (requirement.status !== "satisfied")
15
- return false;
16
- return requirement.evidenceIds.some((evidenceId) => {
17
- const evidence = state.evidence.find((candidate) => candidate.id === evidenceId);
18
- return evidence !== undefined && isVerifiedOrUserEvidence(evidence);
19
- });
20
- });
21
- }
22
10
  /**
23
11
  * Apply one agent-facing goal action to the current ledger state.
24
12
  *
@@ -181,13 +169,17 @@ function toGoalEvent(state, action, now, options) {
181
169
  };
182
170
  }
183
171
  const requireVerifiedEvidence = options?.requireVerifiedEvidenceForCompletion ?? true;
184
- if (requireVerifiedEvidence && !hasEvidenceBackedSatisfaction(state)) {
172
+ const unprovenRequirementIds = getUnprovenGoalRequirementIds(state);
173
+ if (requireVerifiedEvidence && unprovenRequirementIds.length > 0) {
185
174
  return {
186
175
  ok: false,
187
- error: "Cannot complete goal: no satisfied requirement is backed by verified evidence (kind 'tool'/'file' with a validated ref) or kind 'user' evidence. Record such evidence with 'add_evidence' and cite it in 'satisfy_requirement'.",
176
+ error: `Cannot complete goal: requirement(s) lack verified evidence (${unprovenRequirementIds.join(", ")}). Record verified or user-confirmed evidence and cite it in satisfy_requirement.`,
188
177
  };
189
178
  }
190
- return { ok: true, event: { type: "complete_goal", now } };
179
+ return {
180
+ ok: true,
181
+ event: { type: "complete_goal", acceptanceOverride: !requireVerifiedEvidence, now },
182
+ };
191
183
  }
192
184
  case "block_goal": {
193
185
  const reason = action.reason.trim();
@@ -237,28 +229,6 @@ export function summarizeGoalState(state, options) {
237
229
  }
238
230
  return lines.join("\n");
239
231
  }
240
- function escapeRegExp(text) {
241
- return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
242
- }
243
- /**
244
- * Cheap, conservative cross-reference: an open task step "references" a requirement when its
245
- * content contains the requirement id as a whole token (not a substring of a longer token), or
246
- * contains the requirement's full text verbatim (case-insensitive). Both conditions are chosen
247
- * to avoid noisy partial-word matches -- a short common id or a coincidental few-word overlap
248
- * does not qualify.
249
- */
250
- function taskStepReferencesRequirement(step, requirement) {
251
- const idToken = requirement.id.trim();
252
- if (idToken.length >= 2) {
253
- const idPattern = new RegExp(`(^|[^a-z0-9])${escapeRegExp(idToken.toLocaleLowerCase())}([^a-z0-9]|$)`, "i");
254
- if (idPattern.test(step.content))
255
- return true;
256
- }
257
- const text = requirement.text.trim();
258
- if (text.length >= 8 && step.content.toLocaleLowerCase().includes(text.toLocaleLowerCase()))
259
- return true;
260
- return false;
261
- }
262
232
  /**
263
233
  * Nudge lines for open task steps that reference any of `requirementIds` (deduped per
264
234
  * requirement, one line naming every referencing step). Empty when there is nothing to say.
@@ -280,8 +250,8 @@ export function findRequirementCrossReferenceNudges(state, requirementIds, openT
280
250
  return nudges;
281
251
  }
282
252
  /**
283
- * After 'satisfy_requirement' or 'complete', nudge lines for open task steps whose content
284
- * references a just-satisfied requirement. Returns `[]` for every other action, or when
253
+ * After 'satisfy_requirement' or 'complete', nudge lines for linked open task steps. Returns `[]`
254
+ * for every other action, or when
285
255
  * `openTaskSteps` was not supplied (the default -- backward compatible, no behavior change for
286
256
  * callers that do not pass task-step context).
287
257
  */