@caupulican/pi-adaptative 0.81.40 → 0.81.42

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 (599) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +1 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +1 -0
  6. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +5 -1
  7. package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +3 -3
  8. package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +8 -0
  9. package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +26 -3
  10. package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +3 -0
  11. package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +4 -1
  12. package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +2 -1
  13. package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +2 -0
  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 +22 -1
  17. package/dist/cli/args.js.map +1 -1
  18. package/dist/core/agent-paths.d.ts +38 -0
  19. package/dist/core/agent-paths.d.ts.map +1 -1
  20. package/dist/core/agent-paths.js +77 -0
  21. package/dist/core/agent-paths.js.map +1 -1
  22. package/dist/core/agent-session-contracts.d.ts +311 -0
  23. package/dist/core/agent-session-contracts.d.ts.map +1 -0
  24. package/dist/core/agent-session-contracts.js +26 -0
  25. package/dist/core/agent-session-contracts.js.map +1 -0
  26. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  27. package/dist/core/agent-session-runtime.js +3 -0
  28. package/dist/core/agent-session-runtime.js.map +1 -1
  29. package/dist/core/agent-session.d.ts +26 -405
  30. package/dist/core/agent-session.d.ts.map +1 -1
  31. package/dist/core/agent-session.js +90 -316
  32. package/dist/core/agent-session.js.map +1 -1
  33. package/dist/core/auth-storage.d.ts.map +1 -1
  34. package/dist/core/auth-storage.js +3 -1
  35. package/dist/core/auth-storage.js.map +1 -1
  36. package/dist/core/autonomy/contracts.d.ts +2 -0
  37. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  38. package/dist/core/autonomy/contracts.js.map +1 -1
  39. package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
  40. package/dist/core/autonomy/envelope-enforcement.js +4 -9
  41. package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
  42. package/dist/core/autonomy/lane-tool-surface.d.ts +3 -1
  43. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  44. package/dist/core/autonomy/lane-tool-surface.js +19 -5
  45. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  46. package/dist/core/autonomy/path-scope.d.ts +14 -0
  47. package/dist/core/autonomy/path-scope.d.ts.map +1 -1
  48. package/dist/core/autonomy/path-scope.js +37 -6
  49. package/dist/core/autonomy/path-scope.js.map +1 -1
  50. package/dist/core/background-lane-controller.d.ts +30 -2
  51. package/dist/core/background-lane-controller.d.ts.map +1 -1
  52. package/dist/core/background-lane-controller.js +33 -1
  53. package/dist/core/background-lane-controller.js.map +1 -1
  54. package/dist/core/bedrock-sso-login.d.ts +16 -0
  55. package/dist/core/bedrock-sso-login.d.ts.map +1 -0
  56. package/dist/core/bedrock-sso-login.js +98 -0
  57. package/dist/core/bedrock-sso-login.js.map +1 -0
  58. package/dist/core/compaction-controller.d.ts.map +1 -1
  59. package/dist/core/compaction-controller.js +1 -1
  60. package/dist/core/compaction-controller.js.map +1 -1
  61. package/dist/core/compaction-support.d.ts +3 -8
  62. package/dist/core/compaction-support.d.ts.map +1 -1
  63. package/dist/core/compaction-support.js +3 -3
  64. package/dist/core/compaction-support.js.map +1 -1
  65. package/dist/core/context-pipeline.d.ts +1 -1
  66. package/dist/core/context-pipeline.d.ts.map +1 -1
  67. package/dist/core/context-pipeline.js +7 -33
  68. package/dist/core/context-pipeline.js.map +1 -1
  69. package/dist/core/cost/cost-summary.d.ts.map +1 -1
  70. package/dist/core/cost/cost-summary.js +5 -3
  71. package/dist/core/cost/cost-summary.js.map +1 -1
  72. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  73. package/dist/core/cost/daily-usage.js +4 -5
  74. package/dist/core/cost/daily-usage.js.map +1 -1
  75. package/dist/core/default-tool-surface.d.ts.map +1 -1
  76. package/dist/core/default-tool-surface.js +1 -0
  77. package/dist/core/default-tool-surface.js.map +1 -1
  78. package/dist/core/delegation/managed-lane-controller.d.ts +11 -1
  79. package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -1
  80. package/dist/core/delegation/managed-lane-controller.js +84 -41
  81. package/dist/core/delegation/managed-lane-controller.js.map +1 -1
  82. package/dist/core/delegation/session-worker-claim.d.ts.map +1 -1
  83. package/dist/core/delegation/session-worker-claim.js +4 -3
  84. package/dist/core/delegation/session-worker-claim.js.map +1 -1
  85. package/dist/core/delegation/worker-action-journal.d.ts +73 -0
  86. package/dist/core/delegation/worker-action-journal.d.ts.map +1 -0
  87. package/dist/core/delegation/worker-action-journal.js +297 -0
  88. package/dist/core/delegation/worker-action-journal.js.map +1 -0
  89. package/dist/core/delegation/worker-actions.d.ts +36 -1
  90. package/dist/core/delegation/worker-actions.d.ts.map +1 -1
  91. package/dist/core/delegation/worker-actions.js +171 -46
  92. package/dist/core/delegation/worker-actions.js.map +1 -1
  93. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +75 -0
  94. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -0
  95. package/dist/core/delegation/worker-agent-control-coordinator.js +218 -0
  96. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -0
  97. package/dist/core/delegation/worker-agent-control.d.ts +66 -0
  98. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -0
  99. package/dist/core/delegation/worker-agent-control.js +163 -0
  100. package/dist/core/delegation/worker-agent-control.js.map +1 -0
  101. package/dist/core/delegation/worker-attempt-executor.d.ts +80 -0
  102. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -0
  103. package/dist/core/delegation/worker-attempt-executor.js +343 -0
  104. package/dist/core/delegation/worker-attempt-executor.js.map +1 -0
  105. package/dist/core/delegation/worker-claim.d.ts +30 -0
  106. package/dist/core/delegation/worker-claim.d.ts.map +1 -1
  107. package/dist/core/delegation/worker-claim.js +205 -53
  108. package/dist/core/delegation/worker-claim.js.map +1 -1
  109. package/dist/core/delegation/worker-conversation-store.d.ts +116 -0
  110. package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -0
  111. package/dist/core/delegation/worker-conversation-store.js +442 -0
  112. package/dist/core/delegation/worker-conversation-store.js.map +1 -0
  113. package/dist/core/delegation/worker-delegation-controller.d.ts +21 -5
  114. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  115. package/dist/core/delegation/worker-delegation-controller.js +386 -251
  116. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  117. package/dist/core/delegation/worker-delegation-request.d.ts +14 -0
  118. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
  119. package/dist/core/delegation/worker-delegation-request.js.map +1 -1
  120. package/dist/core/delegation/worker-dispatch-scheduler.d.ts +4 -2
  121. package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -1
  122. package/dist/core/delegation/worker-dispatch-scheduler.js +16 -6
  123. package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -1
  124. package/dist/core/delegation/worker-execution-policy.d.ts +2 -1
  125. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  126. package/dist/core/delegation/worker-execution-policy.js +5 -7
  127. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  128. package/dist/core/delegation/worker-lifecycle.d.ts +44 -1
  129. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  130. package/dist/core/delegation/worker-lifecycle.js +120 -0
  131. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  132. package/dist/core/delegation/worker-process-owner.d.ts +18 -0
  133. package/dist/core/delegation/worker-process-owner.d.ts.map +1 -0
  134. package/dist/core/delegation/worker-process-owner.js +54 -0
  135. package/dist/core/delegation/worker-process-owner.js.map +1 -0
  136. package/dist/core/delegation/worker-profile-resolver.d.ts +5 -1
  137. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
  138. package/dist/core/delegation/worker-profile-resolver.js +8 -0
  139. package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
  140. package/dist/core/delegation/worker-recovery-coordinator.d.ts +54 -0
  141. package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -0
  142. package/dist/core/delegation/worker-recovery-coordinator.js +181 -0
  143. package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -0
  144. package/dist/core/delegation/worker-resource-catalog.d.ts +32 -0
  145. package/dist/core/delegation/worker-resource-catalog.d.ts.map +1 -0
  146. package/dist/core/delegation/worker-resource-catalog.js +116 -0
  147. package/dist/core/delegation/worker-resource-catalog.js.map +1 -0
  148. package/dist/core/delegation/worker-resource-materializer.d.ts +47 -0
  149. package/dist/core/delegation/worker-resource-materializer.d.ts.map +1 -0
  150. package/dist/core/delegation/worker-resource-materializer.js +137 -0
  151. package/dist/core/delegation/worker-resource-materializer.js.map +1 -0
  152. package/dist/core/delegation/worker-runner.d.ts +3 -1
  153. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  154. package/dist/core/delegation/worker-runner.js +189 -54
  155. package/dist/core/delegation/worker-runner.js.map +1 -1
  156. package/dist/core/delegation/worker-terminal-finalizer.d.ts +23 -0
  157. package/dist/core/delegation/worker-terminal-finalizer.d.ts.map +1 -0
  158. package/dist/core/delegation/worker-terminal-finalizer.js +12 -0
  159. package/dist/core/delegation/worker-terminal-finalizer.js.map +1 -0
  160. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +38 -0
  161. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -0
  162. package/dist/core/delegation/worker-write-reservation-coordinator.js +107 -0
  163. package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -0
  164. package/dist/core/delegation/worker-write-reservation.d.ts +90 -0
  165. package/dist/core/delegation/worker-write-reservation.d.ts.map +1 -0
  166. package/dist/core/delegation/worker-write-reservation.js +348 -0
  167. package/dist/core/delegation/worker-write-reservation.js.map +1 -0
  168. package/dist/core/extension-import-authority.d.ts +6 -0
  169. package/dist/core/extension-import-authority.d.ts.map +1 -0
  170. package/dist/core/extension-import-authority.js +10 -0
  171. package/dist/core/extension-import-authority.js.map +1 -0
  172. package/dist/core/extensions/loader.d.ts.map +1 -1
  173. package/dist/core/extensions/loader.js +2 -3
  174. package/dist/core/extensions/loader.js.map +1 -1
  175. package/dist/core/extensions/runner.d.ts +3 -0
  176. package/dist/core/extensions/runner.d.ts.map +1 -1
  177. package/dist/core/extensions/runner.js +14 -5
  178. package/dist/core/extensions/runner.js.map +1 -1
  179. package/dist/core/extensions/stale-context.d.ts +2 -0
  180. package/dist/core/extensions/stale-context.d.ts.map +1 -0
  181. package/dist/core/extensions/stale-context.js +2 -0
  182. package/dist/core/extensions/stale-context.js.map +1 -0
  183. package/dist/core/extensions/types.d.ts +8 -0
  184. package/dist/core/extensions/types.d.ts.map +1 -1
  185. package/dist/core/extensions/types.js.map +1 -1
  186. package/dist/core/foreground-recovery-controller.d.ts +1 -0
  187. package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
  188. package/dist/core/foreground-recovery-controller.js +13 -13
  189. package/dist/core/foreground-recovery-controller.js.map +1 -1
  190. package/dist/core/goal-loop-controller.d.ts +14 -9
  191. package/dist/core/goal-loop-controller.d.ts.map +1 -1
  192. package/dist/core/goal-loop-controller.js +47 -75
  193. package/dist/core/goal-loop-controller.js.map +1 -1
  194. package/dist/core/goals/compact-goal-context.d.ts +11 -0
  195. package/dist/core/goals/compact-goal-context.d.ts.map +1 -0
  196. package/dist/core/goals/compact-goal-context.js +59 -0
  197. package/dist/core/goals/compact-goal-context.js.map +1 -0
  198. package/dist/core/goals/goal-acceptance.d.ts.map +1 -1
  199. package/dist/core/goals/goal-acceptance.js +2 -0
  200. package/dist/core/goals/goal-acceptance.js.map +1 -1
  201. package/dist/core/goals/goal-auto-continue-controller.d.ts +2 -1
  202. package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
  203. package/dist/core/goals/goal-auto-continue-controller.js +5 -8
  204. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
  205. package/dist/core/goals/goal-continuation-controller.d.ts +2 -2
  206. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  207. package/dist/core/goals/goal-continuation-controller.js +42 -11
  208. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  209. package/dist/core/goals/goal-continuation-defaults.d.ts +4 -29
  210. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
  211. package/dist/core/goals/goal-continuation-defaults.js +4 -32
  212. package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
  213. package/dist/core/goals/goal-continuation-prompt.d.ts +8 -18
  214. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  215. package/dist/core/goals/goal-continuation-prompt.js +9 -179
  216. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  217. package/dist/core/goals/goal-lifecycle.d.ts +35 -12
  218. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
  219. package/dist/core/goals/goal-lifecycle.js +98 -13
  220. package/dist/core/goals/goal-lifecycle.js.map +1 -1
  221. package/dist/core/goals/goal-record.d.ts +17 -0
  222. package/dist/core/goals/goal-record.d.ts.map +1 -0
  223. package/dist/core/goals/goal-record.js +31 -0
  224. package/dist/core/goals/goal-record.js.map +1 -0
  225. package/dist/core/goals/goal-session-controller.d.ts +42 -0
  226. package/dist/core/goals/goal-session-controller.d.ts.map +1 -0
  227. package/dist/core/goals/goal-session-controller.js +128 -0
  228. package/dist/core/goals/goal-session-controller.js.map +1 -0
  229. package/dist/core/goals/goal-state.d.ts +45 -25
  230. package/dist/core/goals/goal-state.d.ts.map +1 -1
  231. package/dist/core/goals/goal-state.js +85 -15
  232. package/dist/core/goals/goal-state.js.map +1 -1
  233. package/dist/core/goals/goal-tool-core.d.ts +1 -4
  234. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  235. package/dist/core/goals/goal-tool-core.js +49 -34
  236. package/dist/core/goals/goal-tool-core.js.map +1 -1
  237. package/dist/core/goals/session-goal-state.d.ts +18 -8
  238. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  239. package/dist/core/goals/session-goal-state.js +134 -11
  240. package/dist/core/goals/session-goal-state.js.map +1 -1
  241. package/dist/core/human-input-controller.d.ts +47 -0
  242. package/dist/core/human-input-controller.d.ts.map +1 -0
  243. package/dist/core/human-input-controller.js +181 -0
  244. package/dist/core/human-input-controller.js.map +1 -0
  245. package/dist/core/local-runtime-controller.d.ts +1 -1
  246. package/dist/core/local-runtime-controller.d.ts.map +1 -1
  247. package/dist/core/local-runtime-controller.js.map +1 -1
  248. package/dist/core/model-capability.d.ts +0 -19
  249. package/dist/core/model-capability.d.ts.map +1 -1
  250. package/dist/core/model-capability.js +0 -19
  251. package/dist/core/model-capability.js.map +1 -1
  252. package/dist/core/model-registry.d.ts +6 -1
  253. package/dist/core/model-registry.d.ts.map +1 -1
  254. package/dist/core/model-registry.js +13 -5
  255. package/dist/core/model-registry.js.map +1 -1
  256. package/dist/core/model-resolver.d.ts +16 -1
  257. package/dist/core/model-resolver.d.ts.map +1 -1
  258. package/dist/core/model-resolver.js +32 -16
  259. package/dist/core/model-resolver.js.map +1 -1
  260. package/dist/core/model-router-controller.d.ts +1 -1
  261. package/dist/core/model-router-controller.d.ts.map +1 -1
  262. package/dist/core/model-router-controller.js.map +1 -1
  263. package/dist/core/model-selection-controller.d.ts +1 -1
  264. package/dist/core/model-selection-controller.d.ts.map +1 -1
  265. package/dist/core/model-selection-controller.js.map +1 -1
  266. package/dist/core/models/model-endpoint.d.ts +3 -0
  267. package/dist/core/models/model-endpoint.d.ts.map +1 -0
  268. package/dist/core/models/model-endpoint.js +11 -0
  269. package/dist/core/models/model-endpoint.js.map +1 -0
  270. package/dist/core/orchestration/agent-resume.d.ts +2 -0
  271. package/dist/core/orchestration/agent-resume.d.ts.map +1 -1
  272. package/dist/core/orchestration/agent-resume.js +7 -0
  273. package/dist/core/orchestration/agent-resume.js.map +1 -1
  274. package/dist/core/orchestration/attempt-usage.d.ts +28 -0
  275. package/dist/core/orchestration/attempt-usage.d.ts.map +1 -0
  276. package/dist/core/orchestration/attempt-usage.js +168 -0
  277. package/dist/core/orchestration/attempt-usage.js.map +1 -0
  278. package/dist/core/orchestration/capability-gateway.d.ts +19 -1
  279. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  280. package/dist/core/orchestration/capability-gateway.js +128 -28
  281. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  282. package/dist/core/orchestration/contracts.d.ts +35 -0
  283. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  284. package/dist/core/orchestration/contracts.js +17 -0
  285. package/dist/core/orchestration/contracts.js.map +1 -1
  286. package/dist/core/orchestration/delegation-ledger.d.ts +17 -2
  287. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  288. package/dist/core/orchestration/delegation-ledger.js +81 -3
  289. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  290. package/dist/core/orchestration/event-store.d.ts +1 -0
  291. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  292. package/dist/core/orchestration/event-store.js +78 -38
  293. package/dist/core/orchestration/event-store.js.map +1 -1
  294. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  295. package/dist/core/orchestration/profile-registry.js +81 -41
  296. package/dist/core/orchestration/profile-registry.js.map +1 -1
  297. package/dist/core/orchestration/profile-store.d.ts.map +1 -1
  298. package/dist/core/orchestration/profile-store.js +18 -4
  299. package/dist/core/orchestration/profile-store.js.map +1 -1
  300. package/dist/core/orchestration/risk-budget.d.ts +2 -0
  301. package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
  302. package/dist/core/orchestration/risk-budget.js +26 -0
  303. package/dist/core/orchestration/risk-budget.js.map +1 -1
  304. package/dist/core/orchestration/task-runtime.d.ts +13 -1
  305. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  306. package/dist/core/orchestration/task-runtime.js +127 -16
  307. package/dist/core/orchestration/task-runtime.js.map +1 -1
  308. package/dist/core/orchestration/work-state-projection.d.ts.map +1 -1
  309. package/dist/core/orchestration/work-state-projection.js +1 -1
  310. package/dist/core/orchestration/work-state-projection.js.map +1 -1
  311. package/dist/core/orchestration/worker-execution-contract.d.ts +3 -1
  312. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  313. package/dist/core/orchestration/worker-execution-contract.js +75 -23
  314. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  315. package/dist/core/orchestration/worker-result-adapter.d.ts +9 -3
  316. package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -1
  317. package/dist/core/orchestration/worker-result-adapter.js +167 -14
  318. package/dist/core/orchestration/worker-result-adapter.js.map +1 -1
  319. package/dist/core/package-manager.d.ts.map +1 -1
  320. package/dist/core/package-manager.js +20 -3
  321. package/dist/core/package-manager.js.map +1 -1
  322. package/dist/core/profile-filter-controller.d.ts +8 -1
  323. package/dist/core/profile-filter-controller.d.ts.map +1 -1
  324. package/dist/core/profile-filter-controller.js +23 -5
  325. package/dist/core/profile-filter-controller.js.map +1 -1
  326. package/dist/core/prompt-templates.d.ts +1 -0
  327. package/dist/core/prompt-templates.d.ts.map +1 -1
  328. package/dist/core/prompt-templates.js +18 -29
  329. package/dist/core/prompt-templates.js.map +1 -1
  330. package/dist/core/reflection-controller.d.ts +2 -2
  331. package/dist/core/reflection-controller.d.ts.map +1 -1
  332. package/dist/core/reflection-controller.js +92 -54
  333. package/dist/core/reflection-controller.js.map +1 -1
  334. package/dist/core/request-auth.d.ts +7 -0
  335. package/dist/core/request-auth.d.ts.map +1 -0
  336. package/dist/core/request-auth.js +8 -0
  337. package/dist/core/request-auth.js.map +1 -0
  338. package/dist/core/research/evidence-bundle.d.ts +20 -0
  339. package/dist/core/research/evidence-bundle.d.ts.map +1 -1
  340. package/dist/core/research/evidence-bundle.js +173 -69
  341. package/dist/core/research/evidence-bundle.js.map +1 -1
  342. package/dist/core/resource-loader.d.ts.map +1 -1
  343. package/dist/core/resource-loader.js +16 -6
  344. package/dist/core/resource-loader.js.map +1 -1
  345. package/dist/core/risk-classifier.d.ts.map +1 -1
  346. package/dist/core/risk-classifier.js +8 -0
  347. package/dist/core/risk-classifier.js.map +1 -1
  348. package/dist/core/runtime-builder.d.ts +22 -3
  349. package/dist/core/runtime-builder.d.ts.map +1 -1
  350. package/dist/core/runtime-builder.js +147 -80
  351. package/dist/core/runtime-builder.js.map +1 -1
  352. package/dist/core/sdk.d.ts.map +1 -1
  353. package/dist/core/sdk.js +7 -1
  354. package/dist/core/sdk.js.map +1 -1
  355. package/dist/core/secrets/credential-exposure-guard.d.ts +9 -0
  356. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -0
  357. package/dist/core/secrets/credential-exposure-guard.js +241 -0
  358. package/dist/core/secrets/credential-exposure-guard.js.map +1 -0
  359. package/dist/core/secrets/secret-dotenv.d.ts +27 -0
  360. package/dist/core/secrets/secret-dotenv.d.ts.map +1 -0
  361. package/dist/core/secrets/secret-dotenv.js +183 -0
  362. package/dist/core/secrets/secret-dotenv.js.map +1 -0
  363. package/dist/core/secrets/secret-vault-format.d.ts +112 -0
  364. package/dist/core/secrets/secret-vault-format.d.ts.map +1 -0
  365. package/dist/core/secrets/secret-vault-format.js +397 -0
  366. package/dist/core/secrets/secret-vault-format.js.map +1 -0
  367. package/dist/core/secrets/secret-vault.d.ts +72 -0
  368. package/dist/core/secrets/secret-vault.d.ts.map +1 -0
  369. package/dist/core/secrets/secret-vault.js +671 -0
  370. package/dist/core/secrets/secret-vault.js.map +1 -0
  371. package/dist/core/session-analytics.d.ts +4 -23
  372. package/dist/core/session-analytics.d.ts.map +1 -1
  373. package/dist/core/session-analytics.js +39 -69
  374. package/dist/core/session-analytics.js.map +1 -1
  375. package/dist/core/session-artifact-bundle.d.ts +35 -0
  376. package/dist/core/session-artifact-bundle.d.ts.map +1 -0
  377. package/dist/core/session-artifact-bundle.js +61 -0
  378. package/dist/core/session-artifact-bundle.js.map +1 -0
  379. package/dist/core/session-role.d.ts +5 -0
  380. package/dist/core/session-role.d.ts.map +1 -1
  381. package/dist/core/session-role.js +14 -1
  382. package/dist/core/session-role.js.map +1 -1
  383. package/dist/core/session-tree-navigator.d.ts +4 -6
  384. package/dist/core/session-tree-navigator.d.ts.map +1 -1
  385. package/dist/core/session-tree-navigator.js +4 -1
  386. package/dist/core/session-tree-navigator.js.map +1 -1
  387. package/dist/core/settings-manager.d.ts +1 -1
  388. package/dist/core/settings-manager.d.ts.map +1 -1
  389. package/dist/core/settings-manager.js +1 -1
  390. package/dist/core/settings-manager.js.map +1 -1
  391. package/dist/core/slash-commands.d.ts.map +1 -1
  392. package/dist/core/slash-commands.js +2 -2
  393. package/dist/core/slash-commands.js.map +1 -1
  394. package/dist/core/tool-capability-policy.d.ts.map +1 -1
  395. package/dist/core/tool-capability-policy.js +1 -0
  396. package/dist/core/tool-capability-policy.js.map +1 -1
  397. package/dist/core/tool-gate-controller.d.ts.map +1 -1
  398. package/dist/core/tool-gate-controller.js +8 -2
  399. package/dist/core/tool-gate-controller.js.map +1 -1
  400. package/dist/core/tool-protocol-controller.d.ts +2 -4
  401. package/dist/core/tool-protocol-controller.d.ts.map +1 -1
  402. package/dist/core/tool-protocol-controller.js.map +1 -1
  403. package/dist/core/tool-recovery-stats.d.ts +21 -1
  404. package/dist/core/tool-recovery-stats.d.ts.map +1 -1
  405. package/dist/core/tool-recovery-stats.js.map +1 -1
  406. package/dist/core/tools/bash.d.ts +5 -0
  407. package/dist/core/tools/bash.d.ts.map +1 -1
  408. package/dist/core/tools/bash.js +59 -5
  409. package/dist/core/tools/bash.js.map +1 -1
  410. package/dist/core/tools/delegate-status.d.ts +6 -1
  411. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  412. package/dist/core/tools/delegate-status.js +106 -25
  413. package/dist/core/tools/delegate-status.js.map +1 -1
  414. package/dist/core/tools/delegate.d.ts +9 -1
  415. package/dist/core/tools/delegate.d.ts.map +1 -1
  416. package/dist/core/tools/delegate.js +329 -69
  417. package/dist/core/tools/delegate.js.map +1 -1
  418. package/dist/core/tools/git-filter.d.ts +1 -8
  419. package/dist/core/tools/git-filter.d.ts.map +1 -1
  420. package/dist/core/tools/git-filter.js +2 -63
  421. package/dist/core/tools/git-filter.js.map +1 -1
  422. package/dist/core/tools/goal.d.ts +5 -3
  423. package/dist/core/tools/goal.d.ts.map +1 -1
  424. package/dist/core/tools/goal.js +97 -19
  425. package/dist/core/tools/goal.js.map +1 -1
  426. package/dist/core/tools/index.d.ts +1 -0
  427. package/dist/core/tools/index.d.ts.map +1 -1
  428. package/dist/core/tools/index.js +1 -0
  429. package/dist/core/tools/index.js.map +1 -1
  430. package/dist/core/tools/orchestration-panel.d.ts +1 -4
  431. package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
  432. package/dist/core/tools/orchestration-panel.js +0 -44
  433. package/dist/core/tools/orchestration-panel.js.map +1 -1
  434. package/dist/core/tools/output-accumulator.d.ts +11 -0
  435. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  436. package/dist/core/tools/output-accumulator.js +36 -3
  437. package/dist/core/tools/output-accumulator.js.map +1 -1
  438. package/dist/core/tools/python.d.ts +2 -0
  439. package/dist/core/tools/python.d.ts.map +1 -1
  440. package/dist/core/tools/python.js +3 -1
  441. package/dist/core/tools/python.js.map +1 -1
  442. package/dist/core/tools/read.d.ts.map +1 -1
  443. package/dist/core/tools/read.js +1 -1
  444. package/dist/core/tools/read.js.map +1 -1
  445. package/dist/core/tools/run-process.d.ts +1 -1
  446. package/dist/core/tools/run-process.d.ts.map +1 -1
  447. package/dist/core/tools/run-process.js +69 -9
  448. package/dist/core/tools/run-process.js.map +1 -1
  449. package/dist/core/tools/search-command-guard.d.ts +14 -0
  450. package/dist/core/tools/search-command-guard.d.ts.map +1 -0
  451. package/dist/core/tools/search-command-guard.js +333 -0
  452. package/dist/core/tools/search-command-guard.js.map +1 -0
  453. package/dist/core/tools/secret-store.d.ts +38 -0
  454. package/dist/core/tools/secret-store.d.ts.map +1 -0
  455. package/dist/core/tools/secret-store.js +412 -0
  456. package/dist/core/tools/secret-store.js.map +1 -0
  457. package/dist/core/tools/shell-command-parser.d.ts +16 -0
  458. package/dist/core/tools/shell-command-parser.d.ts.map +1 -0
  459. package/dist/core/tools/shell-command-parser.js +113 -0
  460. package/dist/core/tools/shell-command-parser.js.map +1 -0
  461. package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
  462. package/dist/core/tools/shell-contract-router.js +12 -5
  463. package/dist/core/tools/shell-contract-router.js.map +1 -1
  464. package/dist/core/tools/task-steps.d.ts.map +1 -1
  465. package/dist/core/tools/task-steps.js +4 -7
  466. package/dist/core/tools/task-steps.js.map +1 -1
  467. package/dist/core/util/atomic-file.d.ts +6 -2
  468. package/dist/core/util/atomic-file.d.ts.map +1 -1
  469. package/dist/core/util/atomic-file.js +4 -4
  470. package/dist/core/util/atomic-file.js.map +1 -1
  471. package/dist/core/util/bounded-file.d.ts +15 -0
  472. package/dist/core/util/bounded-file.d.ts.map +1 -0
  473. package/dist/core/util/bounded-file.js +120 -0
  474. package/dist/core/util/bounded-file.js.map +1 -0
  475. package/dist/core/util/bounded-jsonl.d.ts.map +1 -1
  476. package/dist/core/util/bounded-jsonl.js +119 -9
  477. package/dist/core/util/bounded-jsonl.js.map +1 -1
  478. package/dist/core/util/bounded-value.d.ts +3 -0
  479. package/dist/core/util/bounded-value.d.ts.map +1 -0
  480. package/dist/core/util/bounded-value.js +12 -0
  481. package/dist/core/util/bounded-value.js.map +1 -0
  482. package/dist/core/util/value-guards.d.ts +2 -0
  483. package/dist/core/util/value-guards.d.ts.map +1 -1
  484. package/dist/core/util/value-guards.js +5 -0
  485. package/dist/core/util/value-guards.js.map +1 -1
  486. package/dist/index.d.ts +3 -2
  487. package/dist/index.d.ts.map +1 -1
  488. package/dist/index.js +2 -1
  489. package/dist/index.js.map +1 -1
  490. package/dist/main.d.ts.map +1 -1
  491. package/dist/main.js +25 -11
  492. package/dist/main.js.map +1 -1
  493. package/dist/modes/interactive/auth-dialogs-controller.d.ts +4 -0
  494. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  495. package/dist/modes/interactive/auth-dialogs-controller.js +60 -1
  496. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  497. package/dist/modes/interactive/components/activity-lane.d.ts +55 -0
  498. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -0
  499. package/dist/modes/interactive/components/activity-lane.js +304 -0
  500. package/dist/modes/interactive/components/activity-lane.js.map +1 -0
  501. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  502. package/dist/modes/interactive/components/assistant-message.js +19 -10
  503. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  504. package/dist/modes/interactive/components/expandable-text.d.ts +12 -0
  505. package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -0
  506. package/dist/modes/interactive/components/expandable-text.js +17 -0
  507. package/dist/modes/interactive/components/expandable-text.js.map +1 -0
  508. package/dist/modes/interactive/components/extension-editor.d.ts +15 -1
  509. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/extension-editor.js +30 -21
  511. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  512. package/dist/modes/interactive/components/extension-input.d.ts +1 -0
  513. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  514. package/dist/modes/interactive/components/extension-input.js +6 -1
  515. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  516. package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
  517. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  518. package/dist/modes/interactive/components/scoped-models-selector.js +23 -14
  519. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  520. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  521. package/dist/modes/interactive/components/session-selector.js +27 -44
  522. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  523. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  524. package/dist/modes/interactive/components/settings-selector.js +4 -4
  525. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  526. package/dist/modes/interactive/components/tool-execution.d.ts +19 -11
  527. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  528. package/dist/modes/interactive/components/tool-execution.js +53 -20
  529. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  530. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  531. package/dist/modes/interactive/components/tool-group.js +3 -0
  532. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  533. package/dist/modes/interactive/components/usage-action-selector.d.ts +16 -0
  534. package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -0
  535. package/dist/modes/interactive/components/usage-action-selector.js +46 -0
  536. package/dist/modes/interactive/components/usage-action-selector.js.map +1 -0
  537. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  538. package/dist/modes/interactive/extension-ui-host.js +1 -0
  539. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  540. package/dist/modes/interactive/external-editor.d.ts +15 -0
  541. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  542. package/dist/modes/interactive/external-editor.js +27 -19
  543. package/dist/modes/interactive/external-editor.js.map +1 -1
  544. package/dist/modes/interactive/history-reload-math.d.ts +6 -2
  545. package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
  546. package/dist/modes/interactive/history-reload-math.js +10 -5
  547. package/dist/modes/interactive/history-reload-math.js.map +1 -1
  548. package/dist/modes/interactive/interactive-event-controller.d.ts +74 -0
  549. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -0
  550. package/dist/modes/interactive/interactive-event-controller.js +328 -0
  551. package/dist/modes/interactive/interactive-event-controller.js.map +1 -0
  552. package/dist/modes/interactive/interactive-mode.d.ts +20 -25
  553. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  554. package/dist/modes/interactive/interactive-mode.js +196 -608
  555. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  556. package/dist/modes/interactive/loaded-resources-view.d.ts +20 -0
  557. package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -0
  558. package/dist/modes/interactive/loaded-resources-view.js +147 -0
  559. package/dist/modes/interactive/loaded-resources-view.js.map +1 -0
  560. package/dist/modes/interactive/resource-display.d.ts.map +1 -1
  561. package/dist/modes/interactive/resource-display.js +8 -2
  562. package/dist/modes/interactive/resource-display.js.map +1 -1
  563. package/dist/modes/interactive/resource-shell-commands.d.ts +1 -5
  564. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
  565. package/dist/modes/interactive/resource-shell-commands.js +0 -5
  566. package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
  567. package/dist/modes/interactive/session-flow-commands.d.ts +10 -6
  568. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  569. package/dist/modes/interactive/session-flow-commands.js +123 -70
  570. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  571. package/dist/modes/interactive/usage-commands.d.ts +34 -0
  572. package/dist/modes/interactive/usage-commands.d.ts.map +1 -0
  573. package/dist/modes/interactive/usage-commands.js +225 -0
  574. package/dist/modes/interactive/usage-commands.js.map +1 -0
  575. package/dist/utils/shell.d.ts.map +1 -1
  576. package/dist/utils/shell.js +5 -3
  577. package/dist/utils/shell.js.map +1 -1
  578. package/dist/utils/version-check.d.ts.map +1 -1
  579. package/dist/utils/version-check.js +3 -1
  580. package/dist/utils/version-check.js.map +1 -1
  581. package/docs/UI_POLISH_ORCHESTRATION.md +25 -31
  582. package/docs/UI_QUALITY_ORCHESTRATION.md +22 -24
  583. package/docs/providers.md +9 -1
  584. package/docs/tool-repair.md +3 -0
  585. package/docs/ui-reference/README.md +6 -6
  586. package/docs/ui-reference/orchestration-after.txt +14 -7
  587. package/docs/ui-reference/orchestration-before.txt +12 -6
  588. package/docs/ui-reference/orchestration-reference.txt +15 -5
  589. package/docs/usage.md +9 -1
  590. package/docs/windows.md +4 -2
  591. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  592. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  593. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  594. package/examples/extensions/sandbox/package-lock.json +2 -2
  595. package/examples/extensions/sandbox/package.json +1 -1
  596. package/examples/extensions/with-deps/package-lock.json +2 -2
  597. package/examples/extensions/with-deps/package.json +1 -1
  598. package/npm-shrinkwrap.json +13 -13
  599. package/package.json +4 -4
@@ -1,9 +1,30 @@
1
1
  import { isPlainRecord } from "../util/value-guards.js";
2
+ export const MAX_GOAL_OBJECTIVE_LENGTH = 4_000;
3
+ export const MAX_GOAL_EVENT_HISTORY = 128;
4
+ /** One shared lifecycle classification for tools, runtime, persistence, and UI. */
5
+ export function isGoalExecutionActive(status) {
6
+ return status === "active";
7
+ }
8
+ export function isGoalResumableStatus(status) {
9
+ return status === "paused" || status === "blocked" || status === "usage_limited";
10
+ }
11
+ export function isGoalTerminalStatus(status) {
12
+ return status === "completed" || status === "cancelled" || status === "budget_limited";
13
+ }
14
+ export function isGoalUnfinishedStatus(status) {
15
+ return status !== "completed" && status !== "cancelled";
16
+ }
2
17
  function isStringArray(value) {
3
18
  return Array.isArray(value) && value.every((item) => typeof item === "string");
4
19
  }
5
20
  function isGoalStatus(value) {
6
- return value === "active" || value === "completed" || value === "blocked" || value === "cancelled";
21
+ return (value === "active" ||
22
+ value === "paused" ||
23
+ value === "blocked" ||
24
+ value === "usage_limited" ||
25
+ value === "budget_limited" ||
26
+ value === "completed" ||
27
+ value === "cancelled");
7
28
  }
8
29
  function isRequirementStatus(value) {
9
30
  return value === "open" || value === "satisfied" || value === "blocked";
@@ -48,10 +69,12 @@ function isGoalEvidenceRef(value) {
48
69
  hasOptionalString(value, "uri") &&
49
70
  hasOptionalBoolean(value, "verified"));
50
71
  }
51
- function isGoalEvent(value) {
72
+ export function isGoalEvent(value) {
52
73
  if (!isPlainRecord(value) || typeof value.type !== "string" || typeof value.now !== "string")
53
74
  return false;
54
75
  switch (value.type) {
76
+ case "edit_goal":
77
+ return typeof value.userGoal === "string" && hasOptionalFiniteNumber(value, "tokenBudget");
55
78
  case "add_requirement":
56
79
  return typeof value.id === "string" && typeof value.text === "string";
57
80
  case "satisfy_requirement":
@@ -74,18 +97,24 @@ function isGoalEvent(value) {
74
97
  case "complete_goal":
75
98
  return hasOptionalBoolean(value, "acceptanceOverride");
76
99
  case "complete_goal_manually":
100
+ case "pause_goal":
77
101
  case "resume_goal":
78
102
  case "cancel_goal":
79
103
  return true;
80
104
  case "block_goal":
81
105
  return typeof value.reason === "string";
106
+ case "system_stop_goal":
107
+ return ((value.status === "blocked" || value.status === "usage_limited" || value.status === "budget_limited") &&
108
+ typeof value.reason === "string");
82
109
  case "record_continuation_budget":
83
110
  return (typeof value.turns === "number" &&
84
111
  Number.isFinite(value.turns) &&
85
112
  typeof value.wallClockMs === "number" &&
86
113
  Number.isFinite(value.wallClockMs) &&
87
- typeof value.sessionCostUsd === "number" &&
88
- Number.isFinite(value.sessionCostUsd));
114
+ typeof value.tokens === "number" &&
115
+ Number.isFinite(value.tokens) &&
116
+ typeof value.spendUsd === "number" &&
117
+ Number.isFinite(value.spendUsd));
89
118
  default:
90
119
  return false;
91
120
  }
@@ -96,6 +125,10 @@ export function isGoalState(value) {
96
125
  return (typeof value.goalId === "string" &&
97
126
  typeof value.userGoal === "string" &&
98
127
  isGoalStatus(value.status) &&
128
+ hasOptionalFiniteNumber(value, "revision") &&
129
+ hasOptionalFiniteNumber(value, "progressRevision") &&
130
+ hasOptionalFiniteNumber(value, "tokenBudget") &&
131
+ hasOptionalFiniteNumber(value, "tokensUsed") &&
99
132
  Array.isArray(value.requirements) &&
100
133
  value.requirements.every(isRequirement) &&
101
134
  Array.isArray(value.evidence) &&
@@ -111,8 +144,8 @@ export function isGoalState(value) {
111
144
  hasOptionalFiniteNumber(value, "continuationTurnsUsed") &&
112
145
  hasOptionalFiniteNumber(value, "continuationWallClockMs") &&
113
146
  hasOptionalFiniteNumber(value, "continuationSpendUsd") &&
114
- hasOptionalFiniteNumber(value, "continuationSpendCheckpointUsd") &&
115
- hasOptionalFiniteNumber(value, "continuationWorkerSpendUsd"));
147
+ hasOptionalFiniteNumber(value, "continuationWorkerSpendUsd") &&
148
+ hasOptionalBoolean(value, "acceptanceOverride"));
116
149
  }
117
150
  function cloneRequirement(requirement) {
118
151
  return {
@@ -129,6 +162,9 @@ function cloneGoalEvent(event) {
129
162
  }
130
163
  return { ...event };
131
164
  }
165
+ export function cloneGoalEventForStorage(event) {
166
+ return cloneGoalEvent(event);
167
+ }
132
168
  function cloneGoalState(state) {
133
169
  return {
134
170
  ...state,
@@ -145,6 +181,10 @@ export function createGoalState(args) {
145
181
  goalId: args.goalId,
146
182
  userGoal: args.userGoal,
147
183
  status: "active",
184
+ revision: 0,
185
+ progressRevision: 0,
186
+ tokensUsed: 0,
187
+ ...(args.tokenBudget !== undefined ? { tokenBudget: args.tokenBudget } : {}),
148
188
  requirements: [],
149
189
  evidence: [],
150
190
  events: [],
@@ -161,12 +201,29 @@ export function createGoalState(args) {
161
201
  export function applyGoalEvent(state, event) {
162
202
  const newState = {
163
203
  ...state,
204
+ revision: (state.revision ?? 0) + 1,
164
205
  requirements: state.requirements.map(cloneRequirement),
165
206
  evidence: state.evidence.map(cloneGoalEvidenceRef),
166
- events: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)],
207
+ events: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)].slice(-MAX_GOAL_EVENT_HISTORY),
167
208
  updatedAt: event.now,
168
209
  };
169
210
  switch (event.type) {
211
+ case "edit_goal": {
212
+ newState.userGoal = event.userGoal;
213
+ if (event.tokenBudget !== undefined)
214
+ newState.tokenBudget = event.tokenBudget;
215
+ if (state.status === "completed")
216
+ newState.status = "active";
217
+ if (state.status === "budget_limited" &&
218
+ event.tokenBudget !== undefined &&
219
+ event.tokenBudget > (state.tokensUsed ?? 0)) {
220
+ newState.status = "active";
221
+ }
222
+ if (newState.status === "active")
223
+ newState.blockedReason = undefined;
224
+ newState.progressRevision = (state.progressRevision ?? 0) + 1;
225
+ break;
226
+ }
170
227
  case "add_requirement": {
171
228
  const existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);
172
229
  const newRequirement = {
@@ -185,6 +242,7 @@ export function applyGoalEvent(state, event) {
185
242
  else {
186
243
  newState.requirements = [...newState.requirements, newRequirement];
187
244
  }
245
+ newState.progressRevision = (state.progressRevision ?? 0) + 1;
188
246
  break;
189
247
  }
190
248
  case "satisfy_requirement": {
@@ -203,6 +261,7 @@ export function applyGoalEvent(state, event) {
203
261
  }
204
262
  newState.lastProgressAt = event.now;
205
263
  newState.stallTurns = 0;
264
+ newState.progressRevision = (state.progressRevision ?? 0) + 1;
206
265
  break;
207
266
  }
208
267
  case "block_requirement": {
@@ -275,11 +334,15 @@ export function applyGoalEvent(state, event) {
275
334
  else {
276
335
  newState.evidence = [...newState.evidence, newEvidence];
277
336
  }
337
+ if (event.kind === "user" || event.verified === true) {
338
+ newState.progressRevision = (state.progressRevision ?? 0) + 1;
339
+ }
278
340
  break;
279
341
  }
280
342
  case "progress": {
281
343
  newState.lastProgressAt = event.now;
282
344
  newState.stallTurns = 0;
345
+ newState.progressRevision = (state.progressRevision ?? 0) + 1;
283
346
  break;
284
347
  }
285
348
  case "no_progress": {
@@ -287,15 +350,10 @@ export function applyGoalEvent(state, event) {
287
350
  break;
288
351
  }
289
352
  case "record_continuation_budget": {
290
- const previousCheckpoint = state.continuationSpendCheckpointUsd;
291
- // No prior checkpoint (first pass ever recorded for this goal): there is no valid "before"
292
- // reading to diff against, so attribute a zero delta for this one pass rather than mis-count
293
- // all pre-goal-loop session spend into it. Every subsequent pass gets an accurate delta.
294
- const spendDelta = previousCheckpoint === undefined ? 0 : Math.max(0, event.sessionCostUsd - previousCheckpoint);
295
353
  newState.continuationTurnsUsed = (state.continuationTurnsUsed ?? 0) + event.turns;
296
354
  newState.continuationWallClockMs = (state.continuationWallClockMs ?? 0) + event.wallClockMs;
297
- newState.continuationSpendUsd = (state.continuationSpendUsd ?? 0) + spendDelta;
298
- newState.continuationSpendCheckpointUsd = event.sessionCostUsd;
355
+ newState.continuationSpendUsd = (state.continuationSpendUsd ?? 0) + Math.max(0, event.spendUsd);
356
+ newState.tokensUsed = (state.tokensUsed ?? 0) + Math.max(0, event.tokens);
299
357
  break;
300
358
  }
301
359
  case "complete_goal": {
@@ -303,6 +361,7 @@ export function applyGoalEvent(state, event) {
303
361
  if (!hasUnsatisfied) {
304
362
  newState.status = "completed";
305
363
  newState.blockedReason = undefined;
364
+ newState.acceptanceOverride = event.acceptanceOverride;
306
365
  }
307
366
  break;
308
367
  }
@@ -311,6 +370,7 @@ export function applyGoalEvent(state, event) {
311
370
  newState.blockedReason = undefined;
312
371
  newState.lastProgressAt = event.now;
313
372
  newState.stallTurns = 0;
373
+ newState.acceptanceOverride = true;
314
374
  break;
315
375
  }
316
376
  case "block_goal": {
@@ -318,6 +378,11 @@ export function applyGoalEvent(state, event) {
318
378
  newState.blockedReason = event.reason;
319
379
  break;
320
380
  }
381
+ case "pause_goal": {
382
+ newState.status = "paused";
383
+ newState.blockedReason = undefined;
384
+ break;
385
+ }
321
386
  case "resume_goal": {
322
387
  newState.status = "active";
323
388
  newState.blockedReason = undefined;
@@ -325,6 +390,11 @@ export function applyGoalEvent(state, event) {
325
390
  newState.stallTurns = 0;
326
391
  break;
327
392
  }
393
+ case "system_stop_goal": {
394
+ newState.status = event.status;
395
+ newState.blockedReason = event.reason;
396
+ break;
397
+ }
328
398
  case "cancel_goal": {
329
399
  newState.status = "cancelled";
330
400
  newState.blockedReason = undefined;
@@ -334,7 +404,7 @@ export function applyGoalEvent(state, event) {
334
404
  return newState;
335
405
  }
336
406
  export function shouldContinueGoalLoop(args) {
337
- if (args.state.status !== "active") {
407
+ if (!isGoalExecutionActive(args.state.status)) {
338
408
  return false;
339
409
  }
340
410
  if (args.state.stallTurns >= args.maxStallTurns) {
@@ -1 +1 @@
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"]}
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 =\n\t| \"active\"\n\t| \"paused\"\n\t| \"blocked\"\n\t| \"usage_limited\"\n\t| \"budget_limited\"\n\t| \"completed\"\n\t| \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\" | \"worker\";\n\nexport const MAX_GOAL_OBJECTIVE_LENGTH = 4_000;\nexport const MAX_GOAL_EVENT_HISTORY = 128;\n\n/** One shared lifecycle classification for tools, runtime, persistence, and UI. */\nexport function isGoalExecutionActive(status: GoalStatus): boolean {\n\treturn status === \"active\";\n}\n\nexport function isGoalResumableStatus(status: GoalStatus): boolean {\n\treturn status === \"paused\" || status === \"blocked\" || status === \"usage_limited\";\n}\n\nexport function isGoalTerminalStatus(status: GoalStatus): boolean {\n\treturn status === \"completed\" || status === \"cancelled\" || status === \"budget_limited\";\n}\n\nexport function isGoalUnfinishedStatus(status: GoalStatus): boolean {\n\treturn status !== \"completed\" && status !== \"cancelled\";\n}\n\nexport interface GoalState {\n\tgoalId: string;\n\tuserGoal: string;\n\tstatus: GoalStatus;\n\t/** Monotonic state revision used by compare-and-append persistence. Legacy snapshots start at 0. */\n\trevision?: number;\n\t/** Monotonic meaningful-progress revision used by the continuation stall gate. */\n\tprogressRevision?: number;\n\t/** Optional owner-requested token ceiling. Charged usage is uncached input plus output. */\n\ttokenBudget?: number;\n\t/** Exact usage attributed to submitted goal-continuation turns. */\n\ttokensUsed?: number;\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.\n\t */\n\tcontinuationTurnsUsed?: number;\n\t/**\n\t * Observed 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 * Observed cumulative USD attributed to this goal's own continuation passes from assistant messages\n\t * appended within each pass's captured branch interval. Deliberately excludes worker/subagent spend,\n\t * which is reported separately. Same backward-compat note.\n\t */\n\tcontinuationSpendUsd?: number;\n\t/**\n\t * Observed 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 accounting fields. This is advisory telemetry, not an implicit execution limit.\n\t */\n\tcontinuationWorkerSpendUsd?: number;\n\t/** Durable acceptance override; avoids depending on an unbounded historical event scan. */\n\tacceptanceOverride?: boolean;\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: \"edit_goal\"; userGoal: string; tokenBudget?: number; now: string }\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/** Exact uncached input + output tokens produced after this pass's session-entry cursor. */\n\t\t\ttokens: number;\n\t\t\t/** Exact model spend produced after this pass's session-entry cursor. */\n\t\t\tspendUsd: 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: \"pause_goal\"; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"system_stop_goal\"; status: \"blocked\" | \"usage_limited\" | \"budget_limited\"; reason: string; 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 (\n\t\tvalue === \"active\" ||\n\t\tvalue === \"paused\" ||\n\t\tvalue === \"blocked\" ||\n\t\tvalue === \"usage_limited\" ||\n\t\tvalue === \"budget_limited\" ||\n\t\tvalue === \"completed\" ||\n\t\tvalue === \"cancelled\"\n\t);\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\nexport function 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 \"edit_goal\":\n\t\t\treturn typeof value.userGoal === \"string\" && hasOptionalFiniteNumber(value, \"tokenBudget\");\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 \"pause_goal\":\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 \"system_stop_goal\":\n\t\t\treturn (\n\t\t\t\t(value.status === \"blocked\" || value.status === \"usage_limited\" || value.status === \"budget_limited\") &&\n\t\t\t\ttypeof value.reason === \"string\"\n\t\t\t);\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.tokens === \"number\" &&\n\t\t\t\tNumber.isFinite(value.tokens) &&\n\t\t\t\ttypeof value.spendUsd === \"number\" &&\n\t\t\t\tNumber.isFinite(value.spendUsd)\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\thasOptionalFiniteNumber(value, \"revision\") &&\n\t\thasOptionalFiniteNumber(value, \"progressRevision\") &&\n\t\thasOptionalFiniteNumber(value, \"tokenBudget\") &&\n\t\thasOptionalFiniteNumber(value, \"tokensUsed\") &&\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, \"continuationWorkerSpendUsd\") &&\n\t\thasOptionalBoolean(value, \"acceptanceOverride\")\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\nexport function cloneGoalEventForStorage(event: GoalEvent): GoalEvent {\n\treturn cloneGoalEvent(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: {\n\tgoalId: string;\n\tuserGoal: string;\n\tnow: string;\n\ttokenBudget?: number;\n}): GoalState {\n\treturn {\n\t\tgoalId: args.goalId,\n\t\tuserGoal: args.userGoal,\n\t\tstatus: \"active\",\n\t\trevision: 0,\n\t\tprogressRevision: 0,\n\t\ttokensUsed: 0,\n\t\t...(args.tokenBudget !== undefined ? { tokenBudget: args.tokenBudget } : {}),\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\trevision: (state.revision ?? 0) + 1,\n\t\trequirements: state.requirements.map(cloneRequirement),\n\t\tevidence: state.evidence.map(cloneGoalEvidenceRef),\n\t\tevents: [...state.events.map(cloneGoalEvent), cloneGoalEvent(event)].slice(-MAX_GOAL_EVENT_HISTORY),\n\t\tupdatedAt: event.now,\n\t};\n\n\tswitch (event.type) {\n\t\tcase \"edit_goal\": {\n\t\t\tnewState.userGoal = event.userGoal;\n\t\t\tif (event.tokenBudget !== undefined) newState.tokenBudget = event.tokenBudget;\n\t\t\tif (state.status === \"completed\") newState.status = \"active\";\n\t\t\tif (\n\t\t\t\tstate.status === \"budget_limited\" &&\n\t\t\t\tevent.tokenBudget !== undefined &&\n\t\t\t\tevent.tokenBudget > (state.tokensUsed ?? 0)\n\t\t\t) {\n\t\t\t\tnewState.status = \"active\";\n\t\t\t}\n\t\t\tif (newState.status === \"active\") newState.blockedReason = undefined;\n\t\t\tnewState.progressRevision = (state.progressRevision ?? 0) + 1;\n\t\t\tbreak;\n\t\t}\n\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\tnewState.progressRevision = (state.progressRevision ?? 0) + 1;\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\tnewState.progressRevision = (state.progressRevision ?? 0) + 1;\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\tif (event.kind === \"user\" || event.verified === true) {\n\t\t\t\tnewState.progressRevision = (state.progressRevision ?? 0) + 1;\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\tnewState.progressRevision = (state.progressRevision ?? 0) + 1;\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\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) + Math.max(0, event.spendUsd);\n\t\t\tnewState.tokensUsed = (state.tokensUsed ?? 0) + Math.max(0, event.tokens);\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\tnewState.acceptanceOverride = event.acceptanceOverride;\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\tnewState.acceptanceOverride = true;\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 \"pause_goal\": {\n\t\t\tnewState.status = \"paused\";\n\t\t\tnewState.blockedReason = undefined;\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 \"system_stop_goal\": {\n\t\t\tnewState.status = event.status;\n\t\t\tnewState.blockedReason = event.reason;\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 (!isGoalExecutionActive(args.state.status)) {\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"]}
@@ -13,6 +13,7 @@ export type GoalAction = {
13
13
  action: "start";
14
14
  goalId: string;
15
15
  userGoal: string;
16
+ tokenBudget?: number;
16
17
  } | {
17
18
  action: "add_requirement";
18
19
  requirementId: string;
@@ -60,10 +61,6 @@ export type GoalAction = {
60
61
  } | {
61
62
  action: "block_goal";
62
63
  reason: string;
63
- } | {
64
- action: "resume_goal";
65
- } | {
66
- action: "cancel";
67
64
  };
68
65
  export type GoalActionName = GoalAction["action"];
69
66
  export interface GoalActionSuccess {
@@ -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 { 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
+ {"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 { taskStepReferencesRequirement } from \"../tasks/task-projection.ts\";\nimport { getUnprovenGoalRequirementIds } from \"./goal-acceptance.ts\";\nimport { formatGoalRecord, projectGoalRecord } from \"./goal-record.ts\";\nimport {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n\tisGoalUnfinishedStatus,\n\tMAX_GOAL_OBJECTIVE_LENGTH,\n} from \"./goal-state.ts\";\n\nconst MAX_GOAL_ID_LENGTH = 128;\nconst MAX_GOAL_REQUIREMENTS = 256;\nconst MAX_GOAL_EVIDENCE = 512;\nconst MAX_GOAL_LEDGER_TEXT_LENGTH = 4_000;\nconst MAX_GOAL_URI_LENGTH = 4_096;\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; tokenBudget?: number }\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\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 (goalId.length > MAX_GOAL_ID_LENGTH) {\n\t\t\treturn { ok: false, error: `start goalId must be at most ${MAX_GOAL_ID_LENGTH} characters.` };\n\t\t}\n\t\tif (userGoal.length > MAX_GOAL_OBJECTIVE_LENGTH) {\n\t\t\treturn { ok: false, error: `start userGoal must be at most ${MAX_GOAL_OBJECTIVE_LENGTH} characters.` };\n\t\t}\n\t\tif (action.tokenBudget !== undefined && (!Number.isSafeInteger(action.tokenBudget) || action.tokenBudget <= 0)) {\n\t\t\treturn { ok: false, error: \"start tokenBudget must be a positive integer when provided.\" };\n\t\t}\n\t\tif (current && isGoalUnfinishedStatus(current.status)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `An unfinished goal '${current.goalId}' already exists (${current.status}). Complete, clear, or explicitly replace it before starting '${goalId}'.`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, state: createGoalState({ goalId, userGoal, tokenBudget: action.tokenBudget, 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 (current.status !== \"active\") {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: `Goal '${current.goalId}' is ${current.status}. Lifecycle changes are owner/system controlled; use the /goal controls.`,\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 (id.length > MAX_GOAL_ID_LENGTH) {\n\t\t\t\treturn { ok: false, error: `requirementId must be at most ${MAX_GOAL_ID_LENGTH} characters.` };\n\t\t\t}\n\t\t\tif (text.length > MAX_GOAL_LEDGER_TEXT_LENGTH) {\n\t\t\t\treturn { ok: false, error: `requirement text must be at most ${MAX_GOAL_LEDGER_TEXT_LENGTH} characters.` };\n\t\t\t}\n\t\t\tif (state.requirements.length >= MAX_GOAL_REQUIREMENTS) {\n\t\t\t\treturn { ok: false, error: `Goal already has the maximum ${MAX_GOAL_REQUIREMENTS} requirements.` };\n\t\t\t}\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 (id.length > MAX_GOAL_ID_LENGTH) {\n\t\t\t\treturn { ok: false, error: `evidenceId must be at most ${MAX_GOAL_ID_LENGTH} characters.` };\n\t\t\t}\n\t\t\tif (summary.length > MAX_GOAL_LEDGER_TEXT_LENGTH) {\n\t\t\t\treturn { ok: false, error: `evidence summary must be at most ${MAX_GOAL_LEDGER_TEXT_LENGTH} characters.` };\n\t\t\t}\n\t\t\tif ((action.uri?.trim().length ?? 0) > MAX_GOAL_URI_LENGTH) {\n\t\t\t\treturn { ok: false, error: `evidence uri must be at most ${MAX_GOAL_URI_LENGTH} characters.` };\n\t\t\t}\n\t\t\tif (state.evidence.length >= MAX_GOAL_EVIDENCE) {\n\t\t\t\treturn { ok: false, error: `Goal already has the maximum ${MAX_GOAL_EVIDENCE} evidence entries.` };\n\t\t\t}\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\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 lines = [formatGoalRecord(projectGoalRecord(state))];\n\tif (state.requirements.length > 0) {\n\t\tconst openIds = state.requirements\n\t\t\t.filter((requirement) => requirement.status === \"open\")\n\t\t\t.slice(0, 20)\n\t\t\t.map((requirement) => requirement.id);\n\t\tlines.push(\n\t\t\t`Legacy ledger: ${state.requirements.length} requirements, ${state.evidence.length} evidence${openIds.length > 0 ? `; open: ${openIds.join(\", \")}` : \"\"}.`,\n\t\t);\n\t}\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"]}