@caupulican/pi-adaptative 0.81.31 → 0.81.35

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 (237) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +69 -0
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +53 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -0
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +1282 -0
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -0
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +1453 -0
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/builder-validator.json +14 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/claude-trio.json +32 -0
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/full-provider-review.json +15 -0
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/provider-prompt-smoke.json +14 -0
  12. package/dist/bundled-resources/prompts/extensionify.md +5 -4
  13. package/dist/bundled-resources/prompts/skillify.md +5 -5
  14. package/dist/bundled-resources/skills/pi-harness-learning/SKILL.md +6 -3
  15. package/dist/config.d.ts +5 -1
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/config.js +10 -2
  18. package/dist/config.js.map +1 -1
  19. package/dist/core/agent-session.d.ts +7 -0
  20. package/dist/core/agent-session.d.ts.map +1 -1
  21. package/dist/core/agent-session.js +25 -2
  22. package/dist/core/agent-session.js.map +1 -1
  23. package/dist/core/background-lane-controller.d.ts +12 -3
  24. package/dist/core/background-lane-controller.d.ts.map +1 -1
  25. package/dist/core/background-lane-controller.js +67 -26
  26. package/dist/core/background-lane-controller.js.map +1 -1
  27. package/dist/core/bash-executor.d.ts.map +1 -1
  28. package/dist/core/bash-executor.js +7 -3
  29. package/dist/core/bash-executor.js.map +1 -1
  30. package/dist/core/context/context-store-retention.d.ts +4 -1
  31. package/dist/core/context/context-store-retention.d.ts.map +1 -1
  32. package/dist/core/context/context-store-retention.js +42 -151
  33. package/dist/core/context/context-store-retention.js.map +1 -1
  34. package/dist/core/context-pipeline.d.ts.map +1 -1
  35. package/dist/core/context-pipeline.js +6 -6
  36. package/dist/core/context-pipeline.js.map +1 -1
  37. package/dist/core/exec.d.ts.map +1 -1
  38. package/dist/core/exec.js +25 -39
  39. package/dist/core/exec.js.map +1 -1
  40. package/dist/core/extensions/loader.d.ts +9 -2
  41. package/dist/core/extensions/loader.d.ts.map +1 -1
  42. package/dist/core/extensions/loader.js +105 -21
  43. package/dist/core/extensions/loader.js.map +1 -1
  44. package/dist/core/footer-data-provider.d.ts.map +1 -1
  45. package/dist/core/footer-data-provider.js +2 -0
  46. package/dist/core/footer-data-provider.js.map +1 -1
  47. package/dist/core/goals/goal-state.d.ts +10 -0
  48. package/dist/core/goals/goal-state.d.ts.map +1 -1
  49. package/dist/core/goals/goal-state.js +37 -0
  50. package/dist/core/goals/goal-state.js.map +1 -1
  51. package/dist/core/goals/goal-tool-core.d.ts +11 -0
  52. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  53. package/dist/core/goals/goal-tool-core.js +51 -1
  54. package/dist/core/goals/goal-tool-core.js.map +1 -1
  55. package/dist/core/improvement-loop.d.ts.map +1 -1
  56. package/dist/core/improvement-loop.js +26 -5
  57. package/dist/core/improvement-loop.js.map +1 -1
  58. package/dist/core/models/fitness-store.d.ts.map +1 -1
  59. package/dist/core/models/fitness-store.js +1 -1
  60. package/dist/core/models/fitness-store.js.map +1 -1
  61. package/dist/core/models/local-runtime.d.ts +6 -4
  62. package/dist/core/models/local-runtime.d.ts.map +1 -1
  63. package/dist/core/models/local-runtime.js +108 -36
  64. package/dist/core/models/local-runtime.js.map +1 -1
  65. package/dist/core/output-guard.d.ts.map +1 -1
  66. package/dist/core/output-guard.js +23 -8
  67. package/dist/core/output-guard.js.map +1 -1
  68. package/dist/core/package-manager.d.ts.map +1 -1
  69. package/dist/core/package-manager.js +44 -59
  70. package/dist/core/package-manager.js.map +1 -1
  71. package/dist/core/profile-resource-selection.d.ts +16 -0
  72. package/dist/core/profile-resource-selection.d.ts.map +1 -1
  73. package/dist/core/profile-resource-selection.js +41 -0
  74. package/dist/core/profile-resource-selection.js.map +1 -1
  75. package/dist/core/reflection-controller.d.ts.map +1 -1
  76. package/dist/core/reflection-controller.js +18 -1
  77. package/dist/core/reflection-controller.js.map +1 -1
  78. package/dist/core/reload-blockers.d.ts +1 -0
  79. package/dist/core/reload-blockers.d.ts.map +1 -1
  80. package/dist/core/reload-blockers.js +6 -2
  81. package/dist/core/reload-blockers.js.map +1 -1
  82. package/dist/core/resource-loader.d.ts +2 -0
  83. package/dist/core/resource-loader.d.ts.map +1 -1
  84. package/dist/core/resource-loader.js +50 -28
  85. package/dist/core/resource-loader.js.map +1 -1
  86. package/dist/core/settings-manager.d.ts.map +1 -1
  87. package/dist/core/settings-manager.js +1 -1
  88. package/dist/core/settings-manager.js.map +1 -1
  89. package/dist/core/slash-commands.d.ts.map +1 -1
  90. package/dist/core/slash-commands.js +1 -1
  91. package/dist/core/slash-commands.js.map +1 -1
  92. package/dist/core/toolkit/script-runner.d.ts.map +1 -1
  93. package/dist/core/toolkit/script-runner.js +58 -24
  94. package/dist/core/toolkit/script-runner.js.map +1 -1
  95. package/dist/core/tools/bash.d.ts.map +1 -1
  96. package/dist/core/tools/bash.js +13 -26
  97. package/dist/core/tools/bash.js.map +1 -1
  98. package/dist/core/tools/extensionify.d.ts +2 -1
  99. package/dist/core/tools/extensionify.d.ts.map +1 -1
  100. package/dist/core/tools/extensionify.js +11 -8
  101. package/dist/core/tools/extensionify.js.map +1 -1
  102. package/dist/core/tools/find.d.ts.map +1 -1
  103. package/dist/core/tools/find.js +54 -48
  104. package/dist/core/tools/find.js.map +1 -1
  105. package/dist/core/tools/git-filter.d.ts.map +1 -1
  106. package/dist/core/tools/git-filter.js +20 -32
  107. package/dist/core/tools/git-filter.js.map +1 -1
  108. package/dist/core/tools/goal.d.ts +1 -1
  109. package/dist/core/tools/goal.d.ts.map +1 -1
  110. package/dist/core/tools/goal.js +10 -3
  111. package/dist/core/tools/goal.js.map +1 -1
  112. package/dist/core/tools/grep.d.ts.map +1 -1
  113. package/dist/core/tools/grep.js +89 -80
  114. package/dist/core/tools/grep.js.map +1 -1
  115. package/dist/core/tools/output-accumulator.d.ts +2 -0
  116. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  117. package/dist/core/tools/output-accumulator.js +7 -4
  118. package/dist/core/tools/output-accumulator.js.map +1 -1
  119. package/dist/core/tools/read.d.ts.map +1 -1
  120. package/dist/core/tools/read.js +4 -3
  121. package/dist/core/tools/read.js.map +1 -1
  122. package/dist/index.d.ts +2 -1
  123. package/dist/index.d.ts.map +1 -1
  124. package/dist/index.js +2 -1
  125. package/dist/index.js.map +1 -1
  126. package/dist/main.d.ts +2 -0
  127. package/dist/main.d.ts.map +1 -1
  128. package/dist/main.js +23 -4
  129. package/dist/main.js.map +1 -1
  130. package/dist/migrations.d.ts.map +1 -1
  131. package/dist/migrations.js +18 -4
  132. package/dist/migrations.js.map +1 -1
  133. package/dist/modes/interactive/auth-dialogs-controller.d.ts +10 -0
  134. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  135. package/dist/modes/interactive/auth-dialogs-controller.js +94 -27
  136. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  137. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
  138. package/dist/modes/interactive/auto-learn-controller.js +2 -1
  139. package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
  140. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -0
  141. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  142. package/dist/modes/interactive/components/bordered-loader.js +8 -0
  143. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  144. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/extension-editor.js +6 -15
  146. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  147. package/dist/modes/interactive/components/login-dialog.d.ts +3 -1
  148. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  149. package/dist/modes/interactive/components/login-dialog.js +20 -8
  150. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  151. package/dist/modes/interactive/components/profile-resource-editor.d.ts +4 -1
  152. package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
  153. package/dist/modes/interactive/components/profile-resource-editor.js +22 -39
  154. package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
  155. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  156. package/dist/modes/interactive/components/session-selector.js +1 -1
  157. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  158. package/dist/modes/interactive/config-backup.d.ts +1 -0
  159. package/dist/modes/interactive/config-backup.d.ts.map +1 -1
  160. package/dist/modes/interactive/config-backup.js +14 -3
  161. package/dist/modes/interactive/config-backup.js.map +1 -1
  162. package/dist/modes/interactive/editor-overlay-host.d.ts +12 -0
  163. package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -1
  164. package/dist/modes/interactive/editor-overlay-host.js +55 -0
  165. package/dist/modes/interactive/editor-overlay-host.js.map +1 -1
  166. package/dist/modes/interactive/extension-ui-host.d.ts +2 -1
  167. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  168. package/dist/modes/interactive/extension-ui-host.js +161 -96
  169. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  170. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  171. package/dist/modes/interactive/external-editor.js +23 -28
  172. package/dist/modes/interactive/external-editor.js.map +1 -1
  173. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  174. package/dist/modes/interactive/interactive-mode.js +14 -8
  175. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  176. package/dist/modes/interactive/profile-menu-controller.d.ts +5 -1
  177. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
  178. package/dist/modes/interactive/profile-menu-controller.js +118 -24
  179. package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
  180. package/dist/modes/interactive/resource-shell-commands.d.ts +1 -0
  181. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
  182. package/dist/modes/interactive/resource-shell-commands.js +5 -1
  183. package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
  184. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  185. package/dist/modes/interactive/session-flow-commands.js +100 -7
  186. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  187. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
  188. package/dist/modes/interactive/session-io-commands.js +80 -50
  189. package/dist/modes/interactive/session-io-commands.js.map +1 -1
  190. package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
  191. package/dist/modes/interactive/startup-checks.js +14 -17
  192. package/dist/modes/interactive/startup-checks.js.map +1 -1
  193. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  194. package/dist/modes/rpc/rpc-client.js +20 -19
  195. package/dist/modes/rpc/rpc-client.js.map +1 -1
  196. package/dist/package-manager-cli.d.ts.map +1 -1
  197. package/dist/package-manager-cli.js +10 -19
  198. package/dist/package-manager-cli.js.map +1 -1
  199. package/dist/utils/child-process.d.ts +13 -7
  200. package/dist/utils/child-process.d.ts.map +1 -1
  201. package/dist/utils/child-process.js +56 -3
  202. package/dist/utils/child-process.js.map +1 -1
  203. package/dist/utils/clipboard-image.d.ts.map +1 -1
  204. package/dist/utils/clipboard-image.js +3 -2
  205. package/dist/utils/clipboard-image.js.map +1 -1
  206. package/dist/utils/clipboard.d.ts.map +1 -1
  207. package/dist/utils/clipboard.js +17 -10
  208. package/dist/utils/clipboard.js.map +1 -1
  209. package/dist/utils/external-editor-command.d.ts +8 -0
  210. package/dist/utils/external-editor-command.d.ts.map +1 -0
  211. package/dist/utils/external-editor-command.js +60 -0
  212. package/dist/utils/external-editor-command.js.map +1 -0
  213. package/dist/utils/paths.d.ts.map +1 -1
  214. package/dist/utils/paths.js +10 -2
  215. package/dist/utils/paths.js.map +1 -1
  216. package/dist/utils/tools-manager.d.ts.map +1 -1
  217. package/dist/utils/tools-manager.js +23 -10
  218. package/dist/utils/tools-manager.js.map +1 -1
  219. package/dist/utils/work-directory.d.ts +36 -0
  220. package/dist/utils/work-directory.d.ts.map +1 -0
  221. package/dist/utils/work-directory.js +462 -0
  222. package/dist/utils/work-directory.js.map +1 -0
  223. package/docs/index.md +2 -0
  224. package/docs/resources.md +2 -2
  225. package/docs/rpc.md +1 -1
  226. package/docs/tmux-agent-manager.md +48 -0
  227. package/docs/windows.md +100 -7
  228. package/docs/work-directory.md +41 -0
  229. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  230. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  231. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  232. package/examples/extensions/sandbox/package-lock.json +2 -2
  233. package/examples/extensions/sandbox/package.json +1 -1
  234. package/examples/extensions/with-deps/package-lock.json +2 -2
  235. package/examples/extensions/with-deps/package.json +1 -1
  236. package/npm-shrinkwrap.json +42 -42
  237. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"goal-state.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC;AAC1E,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;AACjE,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IACrC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,GAClB;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,qBAAqB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC7E;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACX,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAgFxC,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAmB9D;AA6BD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAEpE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAalG;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,CAoH5E;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAQ9G;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAE3D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAQlE","sourcesContent":["export type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\";\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}\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}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\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| {\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\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| { type: \"complete_goal\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn value === \"file\" || value === \"test\" || value === \"tool\" || value === \"user\" || value === \"finding\";\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"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);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\tcase \"complete_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\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\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};\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 \"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\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 \"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}\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 \"cancel_goal\": {\n\t\t\tnewState.status = \"cancelled\";\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn newState;\n}\n\nexport function shouldContinueGoalLoop(args: { state: GoalState; maxStallTurns: number; now: string }): boolean {\n\tif (args.state.status !== \"active\") {\n\t\treturn false;\n\t}\n\tif (args.state.stallTurns >= args.maxStallTurns) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function serializeGoalState(state: GoalState): string {\n\treturn JSON.stringify(cloneGoalState(state), null, 2);\n}\n\nexport function parseGoalState(text: string): GoalState | undefined {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(text);\n\t\tif (!isGoalState(parsed)) return undefined;\n\t\treturn cloneGoalState(parsed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"goal-state.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"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","sourcesContent":["export type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\";\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}\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}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\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: \"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\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| { type: \"complete_goal\"; now: string }\n\t| { type: \"complete_goal_manually\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn value === \"file\" || value === \"test\" || value === \"tool\" || value === \"user\" || value === \"finding\";\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"reopen_requirement\":\n\t\t\treturn typeof value.id === \"string\";\n\t\tcase \"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);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\tcase \"complete_goal\":\n\t\tcase \"complete_goal_manually\":\n\t\tcase \"resume_goal\":\n\t\tcase \"cancel_goal\":\n\t\t\treturn true;\n\t\tcase \"block_goal\":\n\t\t\treturn typeof value.reason === \"string\";\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\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};\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 \"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\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 \"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"]}
@@ -49,6 +49,8 @@ function isGoalEvent(value) {
49
49
  return typeof value.id === "string" && isStringArray(value.evidenceIds);
50
50
  case "block_requirement":
51
51
  return typeof value.id === "string" && typeof value.blockedReason === "string";
52
+ case "reopen_requirement":
53
+ return typeof value.id === "string";
52
54
  case "add_evidence":
53
55
  return (typeof value.id === "string" &&
54
56
  isGoalEvidenceKind(value.kind) &&
@@ -57,6 +59,8 @@ function isGoalEvent(value) {
57
59
  case "progress":
58
60
  case "no_progress":
59
61
  case "complete_goal":
62
+ case "complete_goal_manually":
63
+ case "resume_goal":
60
64
  case "cancel_goal":
61
65
  return true;
62
66
  case "block_goal":
@@ -186,6 +190,23 @@ export function applyGoalEvent(state, event) {
186
190
  }
187
191
  break;
188
192
  }
193
+ case "reopen_requirement": {
194
+ const existingIndex = newState.requirements.findIndex((requirement) => requirement.id === event.id);
195
+ if (existingIndex >= 0) {
196
+ const requirement = newState.requirements[existingIndex];
197
+ const updatedRequirements = [...newState.requirements];
198
+ updatedRequirements[existingIndex] = {
199
+ ...requirement,
200
+ status: "open",
201
+ blockedReason: undefined,
202
+ updatedAt: event.now,
203
+ };
204
+ newState.requirements = updatedRequirements;
205
+ }
206
+ newState.lastProgressAt = event.now;
207
+ newState.stallTurns = 0;
208
+ break;
209
+ }
189
210
  case "add_evidence": {
190
211
  const existingIndex = newState.evidence.findIndex((evidence) => evidence.id === event.id);
191
212
  const newEvidence = {
@@ -218,16 +239,32 @@ export function applyGoalEvent(state, event) {
218
239
  const hasUnsatisfied = newState.requirements.some((requirement) => requirement.status !== "satisfied");
219
240
  if (!hasUnsatisfied) {
220
241
  newState.status = "completed";
242
+ newState.blockedReason = undefined;
221
243
  }
222
244
  break;
223
245
  }
246
+ case "complete_goal_manually": {
247
+ newState.status = "completed";
248
+ newState.blockedReason = undefined;
249
+ newState.lastProgressAt = event.now;
250
+ newState.stallTurns = 0;
251
+ break;
252
+ }
224
253
  case "block_goal": {
225
254
  newState.status = "blocked";
226
255
  newState.blockedReason = event.reason;
227
256
  break;
228
257
  }
258
+ case "resume_goal": {
259
+ newState.status = "active";
260
+ newState.blockedReason = undefined;
261
+ newState.lastProgressAt = event.now;
262
+ newState.stallTurns = 0;
263
+ break;
264
+ }
229
265
  case "cancel_goal": {
230
266
  newState.status = "cancelled";
267
+ newState.blockedReason = undefined;
231
268
  break;
232
269
  }
233
270
  }
@@ -1 +1 @@
1
- {"version":3,"file":"goal-state.js","sourceRoot":"","sources":["../../../src/core/goals/goal-state.ts"],"names":[],"mappings":"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","sourcesContent":["export type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\";\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}\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}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\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| {\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\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| { type: \"complete_goal\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn value === \"file\" || value === \"test\" || value === \"tool\" || value === \"user\" || value === \"finding\";\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"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);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\tcase \"complete_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\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\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};\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 \"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\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 \"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}\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 \"cancel_goal\": {\n\t\t\tnewState.status = \"cancelled\";\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":["export type GoalStatus = \"active\" | \"completed\" | \"blocked\" | \"cancelled\";\nexport type RequirementStatus = \"open\" | \"satisfied\" | \"blocked\";\nexport type GoalEvidenceKind = \"file\" | \"test\" | \"tool\" | \"user\" | \"finding\";\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}\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}\n\nexport interface GoalEvidenceRef {\n\tid: string;\n\tkind: GoalEvidenceKind;\n\tsummary: string;\n\turi?: string;\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: \"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\tnow: string;\n\t }\n\t| { type: \"progress\"; now: string }\n\t| { type: \"no_progress\"; now: string }\n\t| { type: \"complete_goal\"; now: string }\n\t| { type: \"complete_goal_manually\"; now: string }\n\t| { type: \"block_goal\"; reason: string; now: string }\n\t| { type: \"resume_goal\"; now: string }\n\t| { type: \"cancel_goal\"; now: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nfunction isStringArray(value: unknown): value is readonly string[] {\n\treturn Array.isArray(value) && value.every((item) => typeof item === \"string\");\n}\n\nfunction isGoalStatus(value: unknown): value is GoalStatus {\n\treturn value === \"active\" || value === \"completed\" || value === \"blocked\" || value === \"cancelled\";\n}\n\nfunction isRequirementStatus(value: unknown): value is RequirementStatus {\n\treturn value === \"open\" || value === \"satisfied\" || value === \"blocked\";\n}\n\nfunction isGoalEvidenceKind(value: unknown): value is GoalEvidenceKind {\n\treturn value === \"file\" || value === \"test\" || value === \"tool\" || value === \"user\" || value === \"finding\";\n}\n\nfunction hasOptionalString(record: Record<string, unknown>, key: string): boolean {\n\treturn record[key] === undefined || typeof record[key] === \"string\";\n}\n\nfunction isRequirement(value: unknown): value is Requirement {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\ttypeof value.text === \"string\" &&\n\t\tisRequirementStatus(value.status) &&\n\t\tisStringArray(value.evidenceIds) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\n}\n\nfunction isGoalEvidenceRef(value: unknown): value is GoalEvidenceRef {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.id === \"string\" &&\n\t\tisGoalEvidenceKind(value.kind) &&\n\t\ttypeof value.summary === \"string\" &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\thasOptionalString(value, \"uri\")\n\t);\n}\n\nfunction isGoalEvent(value: unknown): value is GoalEvent {\n\tif (!isRecord(value) || typeof value.type !== \"string\" || typeof value.now !== \"string\") return false;\n\tswitch (value.type) {\n\t\tcase \"add_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.text === \"string\";\n\t\tcase \"satisfy_requirement\":\n\t\t\treturn typeof value.id === \"string\" && isStringArray(value.evidenceIds);\n\t\tcase \"block_requirement\":\n\t\t\treturn typeof value.id === \"string\" && typeof value.blockedReason === \"string\";\n\t\tcase \"reopen_requirement\":\n\t\t\treturn typeof value.id === \"string\";\n\t\tcase \"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);\n\t\tcase \"progress\":\n\t\tcase \"no_progress\":\n\t\tcase \"complete_goal\":\n\t\tcase \"complete_goal_manually\":\n\t\tcase \"resume_goal\":\n\t\tcase \"cancel_goal\":\n\t\t\treturn true;\n\t\tcase \"block_goal\":\n\t\t\treturn typeof value.reason === \"string\";\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function isGoalState(value: unknown): value is GoalState {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\ttypeof value.goalId === \"string\" &&\n\t\ttypeof value.userGoal === \"string\" &&\n\t\tisGoalStatus(value.status) &&\n\t\tArray.isArray(value.requirements) &&\n\t\tvalue.requirements.every(isRequirement) &&\n\t\tArray.isArray(value.evidence) &&\n\t\tvalue.evidence.every(isGoalEvidenceRef) &&\n\t\tArray.isArray(value.events) &&\n\t\tvalue.events.every(isGoalEvent) &&\n\t\ttypeof value.createdAt === \"string\" &&\n\t\ttypeof value.updatedAt === \"string\" &&\n\t\ttypeof value.lastProgressAt === \"string\" &&\n\t\ttypeof value.stallTurns === \"number\" &&\n\t\tNumber.isFinite(value.stallTurns) &&\n\t\thasOptionalString(value, \"blockedReason\")\n\t);\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};\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 \"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\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 \"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"]}
@@ -25,6 +25,9 @@ export type GoalAction = {
25
25
  action: "block_requirement";
26
26
  requirementId: string;
27
27
  reason: string;
28
+ } | {
29
+ action: "reopen_requirement";
30
+ requirementId: string;
28
31
  } | {
29
32
  action: "add_evidence";
30
33
  evidenceId: string;
@@ -40,6 +43,8 @@ export type GoalAction = {
40
43
  } | {
41
44
  action: "block_goal";
42
45
  reason: string;
46
+ } | {
47
+ action: "resume_goal";
43
48
  } | {
44
49
  action: "cancel";
45
50
  };
@@ -61,6 +66,12 @@ export type GoalActionResult = GoalActionSuccess | GoalActionFailure;
61
66
  * I/O and never mutates its inputs.
62
67
  */
63
68
  export declare function applyGoalAction(current: GoalState | undefined, action: GoalAction, now: string): GoalActionResult;
69
+ /**
70
+ * Complete a goal on explicit user authority, even when requirements remain open or
71
+ * blocked. Agent-facing `complete` stays evidence-gated; this path is reserved for
72
+ * direct user lifecycle controls.
73
+ */
74
+ export declare function completeGoalManually(current: GoalState | undefined, now: string): GoalActionResult;
64
75
  /** Render a compact human-readable summary of the ledger after an action. */
65
76
  export declare function summarizeGoalState(state: GoalState): string;
66
77
  //# sourceMappingURL=goal-tool-core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"goal-tool-core.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-tool-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GACnB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,MAAM,EAAE,qBAAqB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACzF;IAAE,MAAM,EAAE,mBAAmB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACrG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExB,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AAElD,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAUrE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CA6BjH;AAoFD,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAW3D","sourcesContent":["import {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n} from \"./goal-state.ts\";\n\n/**\n * Agent-facing goal ledger actions.\n *\n * This is the producer half of the goal continuation pipeline: the agent records\n * what it is trying to achieve and how far it has gotten, and those records become\n * the {@link GoalState} snapshots that the runtime continuation consumer reads.\n *\n * Each action maps onto either {@link createGoalState} or a single\n * {@link GoalEvent}, so the durable state model stays the single source of truth.\n */\nexport type GoalAction =\n\t| { action: \"start\"; goalId: string; userGoal: string }\n\t| { action: \"add_requirement\"; requirementId: string; text: string }\n\t| { action: \"satisfy_requirement\"; requirementId: string; evidenceIds?: readonly string[] }\n\t| { action: \"block_requirement\"; requirementId: string; reason: string }\n\t| { action: \"add_evidence\"; evidenceId: string; kind: GoalEvidenceKind; summary: string; uri?: string }\n\t| { action: \"progress\" }\n\t| { action: \"no_progress\" }\n\t| { action: \"complete\" }\n\t| { action: \"block_goal\"; reason: string }\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\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(current: GoalState | undefined, action: GoalAction, now: string): 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 (current.status !== \"active\") {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: `Goal '${current.goalId}' is ${current.status}; start a new goal before recording updates.`,\n\t\t};\n\t}\n\n\tconst event = toGoalEvent(current, action, now);\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(state: GoalState, action: GoalAction, now: string): 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 \"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: { type: \"add_evidence\", id, kind: action.kind, summary, uri: action.uri?.trim() || undefined, now },\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\treturn { ok: true, event: { type: \"complete_goal\", now } };\n\t\t}\n\t\tcase \"block_goal\": {\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!reason) return { ok: false, error: \"block_goal requires a non-empty reason.\" };\n\t\t\treturn { ok: true, event: { type: \"block_goal\", reason, now } };\n\t\t}\n\t\tcase \"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/** Render a compact human-readable summary of the ledger after an action. */\nexport function summarizeGoalState(state: GoalState): 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\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"goal-tool-core.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-tool-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GACnB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,MAAM,EAAE,qBAAqB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACzF;IAAE,MAAM,EAAE,mBAAmB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACrG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExB,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AAElD,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAUrE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CA8CjH;AAqGD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAWlG;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAW3D","sourcesContent":["import {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n} from \"./goal-state.ts\";\n\n/**\n * Agent-facing goal ledger actions.\n *\n * This is the producer half of the goal continuation pipeline: the agent records\n * what it is trying to achieve and how far it has gotten, and those records become\n * the {@link GoalState} snapshots that the runtime continuation consumer reads.\n *\n * Each action maps onto either {@link createGoalState} or a single\n * {@link GoalEvent}, so the durable state model stays the single source of truth.\n */\nexport type GoalAction =\n\t| { action: \"start\"; goalId: string; userGoal: string }\n\t| { action: \"add_requirement\"; requirementId: string; text: string }\n\t| { action: \"satisfy_requirement\"; requirementId: string; evidenceIds?: readonly string[] }\n\t| { action: \"block_requirement\"; requirementId: string; reason: string }\n\t| { action: \"reopen_requirement\"; requirementId: string }\n\t| { action: \"add_evidence\"; evidenceId: string; kind: GoalEvidenceKind; summary: string; uri?: string }\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\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(current: GoalState | undefined, action: GoalAction, now: string): 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);\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(state: GoalState, action: GoalAction, now: string): 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 \"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: { type: \"add_evidence\", id, kind: action.kind, summary, uri: action.uri?.trim() || undefined, now },\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\treturn { ok: true, event: { type: \"complete_goal\", now } };\n\t\t}\n\t\tcase \"block_goal\": {\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!reason) return { ok: false, error: \"block_goal requires a non-empty reason.\" };\n\t\t\treturn { ok: true, event: { type: \"block_goal\", reason, now } };\n\t\t}\n\t\tcase \"resume_goal\":\n\t\t\treturn { ok: true, event: { type: \"resume_goal\", now } };\n\t\tcase \"cancel\":\n\t\t\treturn { ok: true, event: { type: \"cancel_goal\", now } };\n\t\tdefault:\n\t\t\treturn { ok: false, error: \"Unknown goal action.\" };\n\t}\n}\n\n/**\n * Complete a goal on explicit user authority, even when requirements remain open or\n * blocked. Agent-facing `complete` stays evidence-gated; this path is reserved for\n * direct user lifecycle controls.\n */\nexport function completeGoalManually(current: GoalState | undefined, now: string): GoalActionResult {\n\tif (!current) {\n\t\treturn { ok: false, error: \"No goal exists to complete.\" };\n\t}\n\tif (current.status === \"completed\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is already completed.` };\n\t}\n\tif (current.status === \"cancelled\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is cancelled; start or override with a new goal.` };\n\t}\n\treturn { ok: true, state: applyGoalEvent(current, { type: \"complete_goal_manually\", now }) };\n}\n\n/** Render a compact human-readable summary of the ledger after an action. */\nexport function summarizeGoalState(state: GoalState): 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\treturn lines.join(\"\\n\");\n}\n"]}
@@ -31,10 +31,25 @@ export function applyGoalAction(current, action, now) {
31
31
  if (!current) {
32
32
  return { ok: false, error: "No active goal. Use action 'start' before recording goal updates." };
33
33
  }
34
+ if (action.action === "resume_goal") {
35
+ if (current.status !== "blocked") {
36
+ return {
37
+ ok: false,
38
+ error: `Goal '${current.goalId}' is ${current.status}; only blocked goals can be resumed.`,
39
+ };
40
+ }
41
+ return { ok: true, state: applyGoalEvent(current, { type: "resume_goal", now }) };
42
+ }
34
43
  if (current.status !== "active") {
44
+ if (current.status === "blocked" && action.action === "cancel") {
45
+ return { ok: true, state: applyGoalEvent(current, { type: "cancel_goal", now }) };
46
+ }
47
+ const recovery = current.status === "blocked"
48
+ ? "Resume it with action 'resume_goal', cancel it, or start a replacement goal."
49
+ : "Start a new goal before recording updates.";
35
50
  return {
36
51
  ok: false,
37
- error: `Goal '${current.goalId}' is ${current.status}; start a new goal before recording updates.`,
52
+ error: `Goal '${current.goalId}' is ${current.status}. ${recovery}`,
38
53
  };
39
54
  }
40
55
  const event = toGoalEvent(current, action, now);
@@ -86,6 +101,22 @@ function toGoalEvent(state, action, now) {
86
101
  }
87
102
  return { ok: true, event: { type: "block_requirement", id, blockedReason: reason, now } };
88
103
  }
104
+ case "reopen_requirement": {
105
+ const id = action.requirementId.trim();
106
+ if (!id)
107
+ return { ok: false, error: "reopen_requirement requires a non-empty requirementId." };
108
+ const requirement = state.requirements.find((candidate) => candidate.id === id);
109
+ if (!requirement) {
110
+ return { ok: false, error: `Unknown requirement '${id}'.` };
111
+ }
112
+ if (requirement.status !== "blocked") {
113
+ return {
114
+ ok: false,
115
+ error: `Requirement '${id}' is ${requirement.status}; only blocked requirements can be reopened.`,
116
+ };
117
+ }
118
+ return { ok: true, event: { type: "reopen_requirement", id, now } };
119
+ }
89
120
  case "add_evidence": {
90
121
  const id = action.evidenceId.trim();
91
122
  const summary = action.summary.trim();
@@ -123,12 +154,31 @@ function toGoalEvent(state, action, now) {
123
154
  return { ok: false, error: "block_goal requires a non-empty reason." };
124
155
  return { ok: true, event: { type: "block_goal", reason, now } };
125
156
  }
157
+ case "resume_goal":
158
+ return { ok: true, event: { type: "resume_goal", now } };
126
159
  case "cancel":
127
160
  return { ok: true, event: { type: "cancel_goal", now } };
128
161
  default:
129
162
  return { ok: false, error: "Unknown goal action." };
130
163
  }
131
164
  }
165
+ /**
166
+ * Complete a goal on explicit user authority, even when requirements remain open or
167
+ * blocked. Agent-facing `complete` stays evidence-gated; this path is reserved for
168
+ * direct user lifecycle controls.
169
+ */
170
+ export function completeGoalManually(current, now) {
171
+ if (!current) {
172
+ return { ok: false, error: "No goal exists to complete." };
173
+ }
174
+ if (current.status === "completed") {
175
+ return { ok: false, error: `Goal '${current.goalId}' is already completed.` };
176
+ }
177
+ if (current.status === "cancelled") {
178
+ return { ok: false, error: `Goal '${current.goalId}' is cancelled; start or override with a new goal.` };
179
+ }
180
+ return { ok: true, state: applyGoalEvent(current, { type: "complete_goal_manually", now }) };
181
+ }
132
182
  /** Render a compact human-readable summary of the ledger after an action. */
133
183
  export function summarizeGoalState(state) {
134
184
  const open = state.requirements.filter((requirement) => requirement.status === "open").length;
@@ -1 +1 @@
1
- {"version":3,"file":"goal-tool-core.js","sourceRoot":"","sources":["../../../src/core/goals/goal-tool-core.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n} from \"./goal-state.ts\";\n\n/**\n * Agent-facing goal ledger actions.\n *\n * This is the producer half of the goal continuation pipeline: the agent records\n * what it is trying to achieve and how far it has gotten, and those records become\n * the {@link GoalState} snapshots that the runtime continuation consumer reads.\n *\n * Each action maps onto either {@link createGoalState} or a single\n * {@link GoalEvent}, so the durable state model stays the single source of truth.\n */\nexport type GoalAction =\n\t| { action: \"start\"; goalId: string; userGoal: string }\n\t| { action: \"add_requirement\"; requirementId: string; text: string }\n\t| { action: \"satisfy_requirement\"; requirementId: string; evidenceIds?: readonly string[] }\n\t| { action: \"block_requirement\"; requirementId: string; reason: string }\n\t| { action: \"add_evidence\"; evidenceId: string; kind: GoalEvidenceKind; summary: string; uri?: string }\n\t| { action: \"progress\" }\n\t| { action: \"no_progress\" }\n\t| { action: \"complete\" }\n\t| { action: \"block_goal\"; reason: string }\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\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(current: GoalState | undefined, action: GoalAction, now: string): 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 (current.status !== \"active\") {\n\t\treturn {\n\t\t\tok: false,\n\t\t\terror: `Goal '${current.goalId}' is ${current.status}; start a new goal before recording updates.`,\n\t\t};\n\t}\n\n\tconst event = toGoalEvent(current, action, now);\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(state: GoalState, action: GoalAction, now: string): 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 \"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: { type: \"add_evidence\", id, kind: action.kind, summary, uri: action.uri?.trim() || undefined, now },\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\treturn { ok: true, event: { type: \"complete_goal\", now } };\n\t\t}\n\t\tcase \"block_goal\": {\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!reason) return { ok: false, error: \"block_goal requires a non-empty reason.\" };\n\t\t\treturn { ok: true, event: { type: \"block_goal\", reason, now } };\n\t\t}\n\t\tcase \"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/** Render a compact human-readable summary of the ledger after an action. */\nexport function summarizeGoalState(state: GoalState): 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\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"goal-tool-core.js","sourceRoot":"","sources":["../../../src/core/goals/goal-tool-core.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tapplyGoalEvent,\n\tcreateGoalState,\n\ttype GoalEvent,\n\ttype GoalEvidenceKind,\n\ttype GoalState,\n} from \"./goal-state.ts\";\n\n/**\n * Agent-facing goal ledger actions.\n *\n * This is the producer half of the goal continuation pipeline: the agent records\n * what it is trying to achieve and how far it has gotten, and those records become\n * the {@link GoalState} snapshots that the runtime continuation consumer reads.\n *\n * Each action maps onto either {@link createGoalState} or a single\n * {@link GoalEvent}, so the durable state model stays the single source of truth.\n */\nexport type GoalAction =\n\t| { action: \"start\"; goalId: string; userGoal: string }\n\t| { action: \"add_requirement\"; requirementId: string; text: string }\n\t| { action: \"satisfy_requirement\"; requirementId: string; evidenceIds?: readonly string[] }\n\t| { action: \"block_requirement\"; requirementId: string; reason: string }\n\t| { action: \"reopen_requirement\"; requirementId: string }\n\t| { action: \"add_evidence\"; evidenceId: string; kind: GoalEvidenceKind; summary: string; uri?: string }\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\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(current: GoalState | undefined, action: GoalAction, now: string): 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);\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(state: GoalState, action: GoalAction, now: string): 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 \"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: { type: \"add_evidence\", id, kind: action.kind, summary, uri: action.uri?.trim() || undefined, now },\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\treturn { ok: true, event: { type: \"complete_goal\", now } };\n\t\t}\n\t\tcase \"block_goal\": {\n\t\t\tconst reason = action.reason.trim();\n\t\t\tif (!reason) return { ok: false, error: \"block_goal requires a non-empty reason.\" };\n\t\t\treturn { ok: true, event: { type: \"block_goal\", reason, now } };\n\t\t}\n\t\tcase \"resume_goal\":\n\t\t\treturn { ok: true, event: { type: \"resume_goal\", now } };\n\t\tcase \"cancel\":\n\t\t\treturn { ok: true, event: { type: \"cancel_goal\", now } };\n\t\tdefault:\n\t\t\treturn { ok: false, error: \"Unknown goal action.\" };\n\t}\n}\n\n/**\n * Complete a goal on explicit user authority, even when requirements remain open or\n * blocked. Agent-facing `complete` stays evidence-gated; this path is reserved for\n * direct user lifecycle controls.\n */\nexport function completeGoalManually(current: GoalState | undefined, now: string): GoalActionResult {\n\tif (!current) {\n\t\treturn { ok: false, error: \"No goal exists to complete.\" };\n\t}\n\tif (current.status === \"completed\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is already completed.` };\n\t}\n\tif (current.status === \"cancelled\") {\n\t\treturn { ok: false, error: `Goal '${current.goalId}' is cancelled; start or override with a new goal.` };\n\t}\n\treturn { ok: true, state: applyGoalEvent(current, { type: \"complete_goal_manually\", now }) };\n}\n\n/** Render a compact human-readable summary of the ledger after an action. */\nexport function summarizeGoalState(state: GoalState): 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\treturn lines.join(\"\\n\");\n}\n"]}