aiwcli 0.15.5 → 0.17.0

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 (435) hide show
  1. package/README.md +108 -1124
  2. package/bin/run.js +0 -4
  3. package/dist/capabilities/branch/adapters.d.ts +2 -0
  4. package/dist/capabilities/branch/adapters.js +21 -0
  5. package/dist/capabilities/branch/contracts.d.ts +57 -0
  6. package/dist/capabilities/branch/contracts.js +1 -0
  7. package/dist/capabilities/branch/control-plane.d.ts +2 -0
  8. package/dist/capabilities/branch/control-plane.js +343 -0
  9. package/dist/capabilities/branch/runtime-core.d.ts +5 -0
  10. package/dist/capabilities/branch/runtime-core.js +36 -0
  11. package/dist/capabilities/installation/control-plane/clean-command.d.ts +41 -0
  12. package/dist/capabilities/installation/control-plane/clean-command.js +196 -0
  13. package/dist/capabilities/installation/control-plane/clear-command.d.ts +162 -0
  14. package/dist/capabilities/installation/control-plane/clear-command.js +1249 -0
  15. package/dist/capabilities/installation/control-plane/init-command.d.ts +81 -0
  16. package/dist/capabilities/installation/control-plane/init-command.js +449 -0
  17. package/dist/capabilities/launch/contracts.d.ts +86 -0
  18. package/dist/capabilities/launch/contracts.js +1 -0
  19. package/dist/capabilities/launch/control-plane/execute-launch.d.ts +2 -0
  20. package/dist/capabilities/launch/control-plane/execute-launch.js +261 -0
  21. package/dist/capabilities/launch/runtime-core/launch-decisions.d.ts +82 -0
  22. package/dist/capabilities/launch/runtime-core/launch-decisions.js +202 -0
  23. package/dist/capabilities/launch/runtime-core/launch-options.d.ts +14 -0
  24. package/dist/capabilities/launch/runtime-core/launch-options.js +69 -0
  25. package/dist/cli/base-command.d.ts +18 -0
  26. package/dist/cli/base-command.js +55 -0
  27. package/dist/commands/branch.d.ts +1 -21
  28. package/dist/commands/branch.js +25 -417
  29. package/dist/commands/clean.d.ts +1 -41
  30. package/dist/commands/clean.js +1 -196
  31. package/dist/commands/clear.d.ts +1 -161
  32. package/dist/commands/clear.js +1 -1121
  33. package/dist/commands/init/index.d.ts +1 -98
  34. package/dist/commands/init/index.js +4 -478
  35. package/dist/commands/launch.d.ts +32 -12
  36. package/dist/commands/launch.js +107 -166
  37. package/dist/lib/claude-settings-types.d.ts +31 -19
  38. package/dist/lib/config.js +1 -2
  39. package/dist/lib/context/context-formatter.d.ts +74 -0
  40. package/dist/lib/context/context-formatter.js +493 -0
  41. package/dist/lib/context/context-selector.d.ts +42 -0
  42. package/dist/lib/context/context-selector.js +451 -0
  43. package/dist/lib/context/context-store.d.ts +100 -0
  44. package/dist/lib/context/context-store.js +644 -0
  45. package/dist/lib/context/plan-manager.d.ts +54 -0
  46. package/dist/lib/context/plan-manager.js +282 -0
  47. package/dist/lib/context/task-tracker.d.ts +44 -0
  48. package/dist/lib/context/task-tracker.js +146 -0
  49. package/dist/lib/core-ide-base.d.ts +4 -0
  50. package/dist/lib/core-ide-base.js +77 -0
  51. package/dist/lib/core-installer.d.ts +5 -0
  52. package/dist/lib/core-installer.js +33 -0
  53. package/dist/lib/debug.d.ts +0 -10
  54. package/dist/lib/debug.js +0 -10
  55. package/dist/lib/env-sanitizer.d.ts +25 -0
  56. package/dist/lib/env-sanitizer.js +46 -0
  57. package/dist/lib/errors.d.ts +0 -13
  58. package/dist/lib/errors.js +0 -15
  59. package/dist/lib/git-exclude-manager.d.ts +2 -2
  60. package/dist/lib/git-exclude-manager.js +3 -3
  61. package/dist/lib/hooks/context-monitor-logic.d.ts +6 -0
  62. package/dist/lib/hooks/context-monitor-logic.js +25 -0
  63. package/dist/lib/hooks/hook-utils.d.ts +143 -0
  64. package/dist/lib/hooks/hook-utils.js +620 -0
  65. package/dist/lib/hooks/prompt-binding-logic.d.ts +7 -0
  66. package/dist/lib/hooks/prompt-binding-logic.js +50 -0
  67. package/dist/lib/hooks/session-end-logic.d.ts +5 -0
  68. package/dist/lib/hooks/session-end-logic.js +51 -0
  69. package/dist/lib/hooks-merger.js +25 -19
  70. package/dist/lib/ide-path-resolver.d.ts +19 -7
  71. package/dist/lib/ide-path-resolver.js +25 -9
  72. package/dist/lib/install-state.d.ts +34 -0
  73. package/dist/lib/install-state.js +154 -0
  74. package/dist/lib/json-io.d.ts +12 -0
  75. package/dist/lib/json-io.js +30 -0
  76. package/dist/lib/lsp-patch.d.ts +12 -0
  77. package/dist/lib/lsp-patch.js +156 -0
  78. package/dist/lib/multiplexer.d.ts +65 -0
  79. package/dist/lib/multiplexer.js +38 -0
  80. package/dist/lib/multiplexers/psmux.d.ts +55 -0
  81. package/dist/lib/multiplexers/psmux.js +324 -0
  82. package/dist/lib/multiplexers/tmux.d.ts +36 -0
  83. package/dist/lib/multiplexers/tmux.js +221 -0
  84. package/dist/lib/multiplexers/wezterm.d.ts +38 -0
  85. package/dist/lib/multiplexers/wezterm.js +225 -0
  86. package/dist/lib/mux-utils.d.ts +6 -0
  87. package/dist/lib/mux-utils.js +36 -0
  88. package/dist/lib/paths.d.ts +2 -2
  89. package/dist/lib/paths.js +2 -2
  90. package/dist/lib/platform-commands.d.ts +27 -0
  91. package/dist/lib/platform-commands.js +49 -0
  92. package/dist/lib/prompt-file-manager.d.ts +23 -0
  93. package/dist/lib/prompt-file-manager.js +41 -0
  94. package/dist/lib/runtime/agent-launcher.d.ts +67 -0
  95. package/dist/lib/runtime/agent-launcher.js +262 -0
  96. package/dist/lib/runtime/aiw-cli.d.ts +39 -0
  97. package/dist/lib/runtime/aiw-cli.js +76 -0
  98. package/dist/lib/runtime/atomic-write.d.ts +19 -0
  99. package/dist/lib/runtime/atomic-write.js +121 -0
  100. package/dist/lib/runtime/cli-args.d.ts +58 -0
  101. package/dist/lib/runtime/cli-args.js +200 -0
  102. package/dist/lib/runtime/constants.d.ts +56 -0
  103. package/dist/lib/runtime/constants.js +230 -0
  104. package/dist/lib/runtime/executable-policy.d.ts +16 -0
  105. package/dist/lib/runtime/executable-policy.js +57 -0
  106. package/dist/lib/runtime/git-state.d.ts +9 -0
  107. package/dist/lib/runtime/git-state.js +59 -0
  108. package/dist/lib/runtime/inference.d.ts +37 -0
  109. package/dist/lib/runtime/inference.js +251 -0
  110. package/dist/lib/runtime/lint-dispatch.d.ts +40 -0
  111. package/dist/lib/runtime/lint-dispatch.js +285 -0
  112. package/dist/lib/runtime/logger.d.ts +66 -0
  113. package/dist/lib/runtime/logger.js +201 -0
  114. package/dist/lib/runtime/models.d.ts +20 -0
  115. package/dist/lib/runtime/models.js +20 -0
  116. package/dist/lib/runtime/platform-adapter.d.ts +7 -0
  117. package/dist/lib/runtime/platform-adapter.js +21 -0
  118. package/dist/lib/runtime/preflight.d.ts +24 -0
  119. package/dist/lib/runtime/preflight.js +65 -0
  120. package/dist/lib/runtime/sentinel-ipc.d.ts +14 -0
  121. package/dist/lib/runtime/sentinel-ipc.js +67 -0
  122. package/dist/lib/runtime/state-io.d.ts +31 -0
  123. package/dist/lib/runtime/state-io.js +179 -0
  124. package/dist/lib/runtime/stop-words.d.ts +20 -0
  125. package/dist/lib/runtime/stop-words.js +150 -0
  126. package/dist/lib/runtime/subprocess-utils.d.ts +29 -0
  127. package/dist/lib/runtime/subprocess-utils.js +96 -0
  128. package/dist/lib/runtime/tmux-preflight.d.ts +13 -0
  129. package/dist/lib/runtime/tmux-preflight.js +78 -0
  130. package/dist/lib/runtime/utils.d.ts +62 -0
  131. package/dist/lib/runtime/utils.js +192 -0
  132. package/dist/lib/schemas.d.ts +250 -0
  133. package/dist/lib/schemas.js +216 -0
  134. package/dist/lib/sentinel-manager.d.ts +32 -0
  135. package/dist/lib/sentinel-manager.js +62 -0
  136. package/dist/lib/sentinel-wrapper.d.ts +10 -0
  137. package/dist/lib/sentinel-wrapper.js +29 -0
  138. package/dist/lib/settings-hierarchy.js +3 -20
  139. package/dist/lib/shell-adapters/bash-adapter.d.ts +18 -0
  140. package/dist/lib/shell-adapters/bash-adapter.js +69 -0
  141. package/dist/lib/shell-adapters/index.d.ts +5 -0
  142. package/dist/lib/shell-adapters/index.js +7 -0
  143. package/dist/lib/shell-adapters/powershell-adapter.d.ts +18 -0
  144. package/dist/lib/shell-adapters/powershell-adapter.js +62 -0
  145. package/dist/lib/shell-adapters/shell-adapter.d.ts +45 -0
  146. package/dist/lib/shell-adapters/shell-adapter.js +5 -0
  147. package/dist/lib/shell-quoting.d.ts +5 -0
  148. package/dist/lib/shell-quoting.js +17 -0
  149. package/dist/lib/spawn-errors.d.ts +9 -0
  150. package/dist/lib/spawn-errors.js +29 -0
  151. package/dist/lib/spawn.js +5 -11
  152. package/dist/lib/spinner.d.ts +0 -5
  153. package/dist/lib/spinner.js +0 -16
  154. package/dist/lib/template-installer.d.ts +14 -5
  155. package/dist/lib/template-installer.js +40 -38
  156. package/dist/lib/template-resolver.d.ts +6 -7
  157. package/dist/lib/template-resolver.js +26 -21
  158. package/dist/lib/template-settings-reconstructor.d.ts +7 -2
  159. package/dist/lib/template-settings-reconstructor.js +76 -45
  160. package/dist/lib/terminal-strategy.d.ts +12 -0
  161. package/dist/lib/terminal-strategy.js +55 -0
  162. package/dist/lib/terminal.d.ts +34 -4
  163. package/dist/lib/terminal.js +192 -119
  164. package/dist/lib/tmux-pane-placement.d.ts +17 -0
  165. package/dist/lib/tmux-pane-placement.js +58 -0
  166. package/dist/lib/tmux-primitives.d.ts +3 -0
  167. package/dist/lib/tmux-primitives.js +11 -0
  168. package/dist/lib/tmux-session.d.ts +32 -0
  169. package/dist/lib/tmux-session.js +87 -0
  170. package/dist/lib/tty-detection.js +1 -1
  171. package/dist/lib/types.d.ts +168 -0
  172. package/dist/lib/types.js +6 -0
  173. package/dist/lib/version.d.ts +1 -1
  174. package/dist/lib/version.js +1 -1
  175. package/dist/lib/windsurf-hooks-hierarchy.js +6 -23
  176. package/dist/platform/launch.d.ts +11 -0
  177. package/dist/platform/launch.js +11 -0
  178. package/dist/templates/CLAUDE.md +30 -40
  179. package/dist/templates/cc-native/.claude/settings.json +26 -36
  180. package/dist/templates/cc-native/CC-NATIVE-README.md +1 -1
  181. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +20 -12
  182. package/dist/templates/cc-native/_cc-native/cc-native.config.json +2 -6
  183. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +39 -59
  184. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +9 -11
  185. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +2 -2
  186. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +4 -5
  187. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +4 -4
  188. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +2 -27
  189. package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +7 -7
  190. package/dist/templates/cc-native/_cc-native/lib-ts/.mocharc.json +9 -0
  191. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/aggregate-agents.test.ts +118 -0
  192. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/artifacts.test.ts +234 -0
  193. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cc-native-state.test.ts +170 -0
  194. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cli-output-parser.test.ts +73 -0
  195. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/config.test.ts +64 -0
  196. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/constants.test.ts +40 -0
  197. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/debug.test.ts +42 -0
  198. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/exports.test.ts +58 -0
  199. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/helpers.ts +107 -0
  200. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/add-plan-context.hook.test.ts +97 -0
  201. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-questions.hook.test.ts +81 -0
  202. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-review.hook.test.ts +71 -0
  203. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/json-parser.test.ts +99 -0
  204. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator-agent.test.ts +288 -0
  205. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator.test.ts +48 -0
  206. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/reviewers.test.ts +32 -0
  207. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/state.test.ts +124 -0
  208. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/verdict.test.ts +93 -0
  209. package/dist/templates/cc-native/_cc-native/lib-ts/agent-selection.ts +163 -0
  210. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +6 -14
  211. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/format.ts +597 -599
  212. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/index.ts +26 -26
  213. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/tracker.ts +106 -107
  214. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/write.ts +118 -119
  215. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +21 -0
  216. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +17 -16
  217. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +132 -10
  218. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +1 -1
  219. package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +6 -6
  220. package/dist/templates/cc-native/_cc-native/lib-ts/corroboration.ts +119 -0
  221. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +2 -3
  222. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/graduation.ts +132 -132
  223. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +88 -86
  224. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +5 -6
  225. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/orchestrator.ts +70 -70
  226. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/output-builder.ts +130 -121
  227. package/dist/templates/cc-native/_cc-native/lib-ts/package-lock.json +1679 -0
  228. package/dist/templates/cc-native/_cc-native/lib-ts/package.json +24 -0
  229. package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +5 -5
  230. package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +1 -6
  231. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/plan-questions.ts +101 -101
  232. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/review-pipeline.ts +511 -543
  233. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/__tests__/agent-providers.test.ts +262 -0
  234. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/agent.ts +71 -85
  235. package/dist/templates/{_shared/lib-ts/agent-exec → cc-native/_cc-native/lib-ts/reviewers/base}/base-agent.ts +138 -150
  236. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/index.ts +12 -12
  237. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/claude-agent.ts +66 -57
  238. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/codex-agent.ts +185 -200
  239. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/gemini-agent.ts +39 -40
  240. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/orchestrator-claude-agent.ts +196 -225
  241. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/schemas.ts +201 -201
  242. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/types.ts +21 -23
  243. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/hyde.test.ts +365 -0
  244. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/ollama-client.test.ts +223 -0
  245. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +12 -16
  246. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +3 -2
  247. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +31 -31
  248. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +7 -8
  249. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +7 -9
  250. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +16 -19
  251. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +37 -41
  252. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +33 -43
  253. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +20 -20
  254. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +9 -10
  255. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +3 -4
  256. package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +50 -126
  257. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +20 -22
  258. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +2 -2
  259. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +14 -89
  260. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/verdict.ts +72 -72
  261. package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +38 -1
  262. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/agent-selection.test.ts +345 -0
  263. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/preflight.test.ts +344 -0
  264. package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +38 -16
  265. package/dist/templates/cc-native/_cc-native/plan-review/lib/preflight.ts +56 -26
  266. package/dist/templates/cc-native/_cc-native/scripts/council_debate.ts +242 -0
  267. package/dist/templates/cc-native/_cc-native/scripts/council_debate_simple.ts +294 -0
  268. package/dist/templates/cc-native/_cc-native/{plan-review/workflows → workflows}/specdev.md +9 -9
  269. package/dist/templates/core/.claude/skills/codex/SKILL.md +25 -0
  270. package/dist/templates/core/.claude/skills/devin/SKILL.md +25 -0
  271. package/dist/templates/core/.claude/skills/handoff/SKILL.md +11 -0
  272. package/dist/templates/core/.claude/skills/handoff-resume/SKILL.md +11 -0
  273. package/dist/templates/core/.claude/skills/meta-plan/SKILL.md +13 -0
  274. package/dist/templates/core/.codex/skills/codex/SKILL.md +13 -0
  275. package/dist/templates/core/.codex/skills/devin/SKILL.md +19 -0
  276. package/dist/templates/core/.codex/skills/handoff/SKILL.md +11 -0
  277. package/dist/templates/core/.codex/skills/handoff-resume/SKILL.md +11 -0
  278. package/dist/templates/core/.codex/skills/meta-plan/SKILL.md +13 -0
  279. package/dist/templates/core/.devin/AGENTS.md +5 -0
  280. package/dist/templates/core/.devin/config.json +12 -0
  281. package/dist/templates/core/.devin/skills/codex/SKILL.md +19 -0
  282. package/dist/templates/core/.devin/skills/devin/SKILL.md +13 -0
  283. package/dist/templates/core/.devin/skills/handoff/SKILL.md +11 -0
  284. package/dist/templates/core/.devin/skills/handoff-resume/SKILL.md +11 -0
  285. package/dist/templates/core/.devin/skills/meta-plan/SKILL.md +13 -0
  286. package/dist/templates/core/.windsurf/workflows/handoff-resume.md +9 -0
  287. package/dist/templates/{_shared → core}/.windsurf/workflows/handoff.md +1 -1
  288. package/dist/templates/{_shared → core}/.windsurf/workflows/meta-plan.md +1 -1
  289. package/dist/templates/core/hooks-ts/_utils/git-state.ts +2 -0
  290. package/dist/templates/{_shared → core}/hooks-ts/archive_plan.ts +15 -44
  291. package/dist/templates/core/hooks-ts/codex_explorer.ts +160 -0
  292. package/dist/templates/{_shared → core}/hooks-ts/context_monitor.ts +23 -55
  293. package/dist/templates/{_shared → core}/hooks-ts/file-suggestion.ts +5 -22
  294. package/dist/templates/{_shared → core}/hooks-ts/lint_after_edit.ts +7 -9
  295. package/dist/templates/core/hooks-ts/pre_compact.ts +36 -0
  296. package/dist/templates/{_shared → core}/hooks-ts/session_end.ts +38 -78
  297. package/dist/templates/{_shared → core}/hooks-ts/session_start.ts +5 -5
  298. package/dist/templates/core/hooks-ts/task_create_capture.ts +32 -0
  299. package/dist/templates/{_shared → core}/hooks-ts/task_update_capture.ts +9 -24
  300. package/dist/templates/core/hooks-ts/user_prompt_submit.ts +46 -0
  301. package/dist/templates/{_shared → core}/lib-ts/CLAUDE.md +27 -16
  302. package/dist/templates/{_shared → core}/lib-ts/context/CLAUDE.md +9 -6
  303. package/dist/templates/{_shared → core}/lib-ts/context/context-formatter.ts +16 -21
  304. package/dist/templates/{_shared → core}/lib-ts/context/context-selector.ts +8 -6
  305. package/dist/templates/{_shared → core}/lib-ts/context/context-store.ts +59 -20
  306. package/dist/templates/{_shared → core}/lib-ts/context/plan-manager.ts +19 -15
  307. package/dist/templates/{_shared → core}/lib-ts/context/task-tracker.ts +3 -3
  308. package/dist/templates/core/lib-ts/hooks/context-monitor-logic.ts +32 -0
  309. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/hooks}/hook-utils.ts +179 -41
  310. package/dist/templates/core/lib-ts/hooks/prompt-binding-logic.ts +80 -0
  311. package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +82 -0
  312. package/dist/templates/core/lib-ts/package.json +19 -0
  313. package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +369 -0
  314. package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +108 -0
  315. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/atomic-write.ts +12 -7
  316. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/cli-args.ts +24 -8
  317. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/constants.ts +326 -324
  318. package/dist/templates/core/lib-ts/runtime/executable-policy.ts +89 -0
  319. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/git-state.ts +6 -4
  320. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/inference.ts +60 -23
  321. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/lint-dispatch.ts +25 -23
  322. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/logger.ts +32 -29
  323. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/models.ts +9 -2
  324. package/dist/templates/core/lib-ts/runtime/platform-adapter.ts +33 -0
  325. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/preflight.ts +4 -3
  326. package/dist/templates/core/lib-ts/runtime/sentinel-ipc.ts +91 -0
  327. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/state-io.ts +20 -11
  328. package/dist/templates/core/lib-ts/runtime/stop-words.ts +185 -0
  329. package/dist/templates/core/lib-ts/runtime/subprocess-utils.ts +147 -0
  330. package/dist/templates/core/lib-ts/runtime/tmux-preflight.ts +93 -0
  331. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/utils.ts +34 -4
  332. package/dist/templates/core/lib-ts/schemas.ts +233 -0
  333. package/dist/templates/{_shared → core}/lib-ts/templates/formatters.ts +7 -5
  334. package/dist/templates/{_shared → core}/lib-ts/templates/plan-context.ts +2 -1
  335. package/dist/templates/{_shared → core}/lib-ts/tsconfig.json +3 -1
  336. package/dist/templates/{_shared → core}/lib-ts/types.ts +78 -77
  337. package/dist/templates/core/scripts/resolve-run.ts +93 -0
  338. package/dist/templates/{_shared → core}/scripts/resolve_context.ts +3 -3
  339. package/dist/templates/{_shared → core}/scripts/status_line.ts +26 -21
  340. package/dist/templates/core/skills/codex/CLAUDE.md +83 -0
  341. package/dist/templates/{_shared → core}/skills/codex/SKILL.md +27 -18
  342. package/dist/templates/{_shared → core}/skills/codex/lib/codex-watcher.ts +79 -113
  343. package/dist/templates/{_shared → core}/skills/codex/scripts/launch-codex.ts +134 -148
  344. package/dist/templates/{_shared → core}/skills/codex/scripts/watch-codex.ts +6 -4
  345. package/dist/templates/core/skills/devin/CLAUDE.md +122 -0
  346. package/dist/templates/core/skills/devin/SKILL.md +73 -0
  347. package/dist/templates/core/skills/devin/lib/devin-watcher.ts +300 -0
  348. package/dist/templates/core/skills/devin/scripts/launch-devin.ts +258 -0
  349. package/dist/templates/{_shared → core}/skills/handoff-system/CLAUDE.md +436 -433
  350. package/dist/templates/{_shared → core}/skills/handoff-system/lib/document-generator.ts +9 -7
  351. package/dist/templates/{_shared → core}/skills/handoff-system/lib/handoff-reader.ts +6 -4
  352. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/resume_handoff.ts +10 -8
  353. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/save_handoff.ts +12 -10
  354. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff-resume.md +2 -2
  355. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff.md +6 -5
  356. package/dist/templates/{_shared → core}/skills/meta-plan/CLAUDE.md +2 -1
  357. package/dist/templates/{_shared → core}/skills/meta-plan/workflows/meta-plan.md +8 -7
  358. package/oclif.manifest.json +89 -13
  359. package/package.json +13 -12
  360. package/dist/lib/base-command.d.ts +0 -114
  361. package/dist/lib/base-command.js +0 -153
  362. package/dist/lib/env-compat.d.ts +0 -18
  363. package/dist/lib/env-compat.js +0 -23
  364. package/dist/lib/stdin.d.ts +0 -48
  365. package/dist/lib/stdin.js +0 -60
  366. package/dist/templates/_shared/.claude/settings.json +0 -120
  367. package/dist/templates/_shared/.claude/skills/codex/SKILL.md +0 -35
  368. package/dist/templates/_shared/.claude/skills/handoff/SKILL.md +0 -13
  369. package/dist/templates/_shared/.claude/skills/handoff-resume/SKILL.md +0 -13
  370. package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +0 -43
  371. package/dist/templates/_shared/.codex/workflows/codex.md +0 -11
  372. package/dist/templates/_shared/.codex/workflows/handoff.md +0 -226
  373. package/dist/templates/_shared/.codex/workflows/meta-plan.md +0 -347
  374. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +0 -2
  375. package/dist/templates/_shared/hooks-ts/pre_compact.ts +0 -49
  376. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +0 -48
  377. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +0 -93
  378. package/dist/templates/_shared/lib-ts/agent-exec/backends/headless.ts +0 -33
  379. package/dist/templates/_shared/lib-ts/agent-exec/backends/index.ts +0 -6
  380. package/dist/templates/_shared/lib-ts/agent-exec/backends/tmux.ts +0 -119
  381. package/dist/templates/_shared/lib-ts/agent-exec/execution-backend.ts +0 -50
  382. package/dist/templates/_shared/lib-ts/agent-exec/index.ts +0 -6
  383. package/dist/templates/_shared/lib-ts/agent-exec/structured-output.ts +0 -166
  384. package/dist/templates/_shared/lib-ts/base/launchers/tmux-launcher.ts +0 -173
  385. package/dist/templates/_shared/lib-ts/base/launchers/window-launcher.ts +0 -93
  386. package/dist/templates/_shared/lib-ts/base/launchers/wt-launcher.ts +0 -64
  387. package/dist/templates/_shared/lib-ts/base/pane-launcher.ts +0 -55
  388. package/dist/templates/_shared/lib-ts/base/sentinel-ipc.ts +0 -87
  389. package/dist/templates/_shared/lib-ts/base/stop-words.ts +0 -184
  390. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +0 -249
  391. package/dist/templates/_shared/lib-ts/base/tmux-driver.ts +0 -341
  392. package/dist/templates/_shared/lib-ts/base/tmux-pane-placement.ts +0 -78
  393. package/dist/templates/_shared/lib-ts/package.json +0 -20
  394. package/dist/templates/_shared/scripts/resolve-run.ts +0 -62
  395. package/dist/templates/_shared/skills/codex/CLAUDE.md +0 -70
  396. package/dist/templates/cc-native/_cc-native/CLAUDE.md +0 -73
  397. package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +0 -64
  398. package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +0 -70
  399. package/dist/templates/cc-native/_cc-native/plan-review/CODING-STANDARDS-CHECKLIST.md +0 -75
  400. package/dist/templates/cc-native/_cc-native/plan-review/agents/CLAUDE.md +0 -143
  401. package/dist/templates/cc-native/_cc-native/plan-review/agents/PLAN-ORCHESTRATOR.md +0 -213
  402. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-questions/PLAN-QUESTIONER.md +0 -70
  403. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-EVOLUTION.md +0 -62
  404. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-PATTERNS.md +0 -61
  405. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-STRUCTURE.md +0 -62
  406. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ASSUMPTION-TRACER.md +0 -56
  407. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CLARITY-AUDITOR.md +0 -53
  408. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-FEASIBILITY.md +0 -66
  409. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-GAPS.md +0 -70
  410. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-ORDERING.md +0 -62
  411. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CONSTRAINT-VALIDATOR.md +0 -72
  412. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-ADR-VALIDATOR.md +0 -61
  413. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-SCALE-MATCHER.md +0 -64
  414. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DEVILS-ADVOCATE.md +0 -56
  415. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DOCUMENTATION-PHILOSOPHY.md +0 -86
  416. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HANDOFF-READINESS.md +0 -59
  417. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HIDDEN-COMPLEXITY.md +0 -58
  418. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/INCREMENTAL-DELIVERY.md +0 -66
  419. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-DEPENDENCY.md +0 -62
  420. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-FMEA.md +0 -66
  421. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-PREMORTEM.md +0 -71
  422. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-REVERSIBILITY.md +0 -74
  423. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SCOPE-BOUNDARY.md +0 -77
  424. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SIMPLICITY-GUARDIAN.md +0 -62
  425. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SKEPTIC.md +0 -68
  426. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md +0 -61
  427. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-CHARACTERIZATION.md +0 -71
  428. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-FIRST-VALIDATOR.md +0 -61
  429. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md +0 -61
  430. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-COSTS.md +0 -67
  431. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-STAKEHOLDERS.md +0 -65
  432. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-COVERAGE.md +0 -74
  433. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-STRENGTH.md +0 -69
  434. package/dist/templates/cc-native/_cc-native/plan-review/lib/corroboration.ts +0 -172
  435. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +0 -7
@@ -0,0 +1,644 @@
1
+ /**
2
+ * Context store — 2-layer CRUD for context state management.
3
+ * See SPEC.md §7
4
+ *
5
+ * Replaces context_manager's 3-layer approach with a simpler 2-layer model:
6
+ * state.json (per context folder — SOURCE OF TRUTH)
7
+ * index.json (at _output/ root — fast session→context lookup)
8
+ */
9
+ import * as fs from "node:fs";
10
+ import path from "node:path";
11
+ import { atomicWrite } from "../runtime/atomic-write.js";
12
+ import { getContextDir, getContextsDir, getIndexPath, getArchiveDir, getArchiveContextDir, getArchiveIndexPath, validateContextId, } from "../runtime/constants.js";
13
+ import { logInfo, logWarn, logError, setContextPath } from "../runtime/logger.js";
14
+ import { readStateJson, writeStateJson } from "../runtime/state-io.js";
15
+ import { nowIso, generateContextId } from "../runtime/utils.js";
16
+ import { IndexFileSchema } from "../schemas.js";
17
+ const INDEX_VERSION = "3.0";
18
+ // Module-level index cache — safe because each hook is a separate bun process
19
+ let _indexCache = null;
20
+ // ---------------------------------------------------------------------------
21
+ // Public utilities
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * Determine artifact type from context state.
25
+ * Checks explicit next_artifact_type field first, falls back to field detection.
26
+ *
27
+ * Edge cases:
28
+ * - Both artifacts exist: Log warning, return "plan" (deterministic fallback for corrupted state)
29
+ * - No artifacts: Return null (caller handles gracefully)
30
+ */
31
+ export function determineArtifactType(state) {
32
+ // Explicit field takes precedence
33
+ if (state.next_artifact_type) {
34
+ return state.next_artifact_type;
35
+ }
36
+ // Implicit detection
37
+ const hasPlan = Boolean(state.plan_path && state.plan_hash);
38
+ const hasHandoff = Boolean(state.handoff_path);
39
+ // Edge case: Both exist (shouldn't happen - indicates bug in replacement logic)
40
+ // Fallback: Pick plan (deterministic, no filesystem I/O)
41
+ if (hasPlan && hasHandoff) {
42
+ logWarn("context_store", `Context ${state.id} has both plan and handoff - indicates bug in replacement logic`);
43
+ return "plan";
44
+ }
45
+ if (hasPlan)
46
+ return "plan";
47
+ if (hasHandoff)
48
+ return "handoff";
49
+ // No artifacts present - return null (caller logs warning and skips)
50
+ return null;
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Internal helpers
54
+ // ---------------------------------------------------------------------------
55
+ function loadIndex(projectRoot) {
56
+ if (_indexCache)
57
+ return _indexCache;
58
+ const indexPath = getIndexPath(projectRoot);
59
+ if (fs.existsSync(indexPath)) {
60
+ try {
61
+ const raw = fs.readFileSync(indexPath, "utf8");
62
+ const data = JSON.parse(raw);
63
+ const validated = IndexFileSchema.safeParse(data);
64
+ if (!validated.success) {
65
+ logWarn("context_store", `Index schema validation failed, recreating: ${validated.error.message}`);
66
+ }
67
+ else {
68
+ _indexCache = data;
69
+ return _indexCache;
70
+ }
71
+ }
72
+ catch (error) {
73
+ logWarn("context_store", `Failed to read index, recreating: ${error}`);
74
+ }
75
+ }
76
+ const fresh = { version: INDEX_VERSION, updated_at: nowIso(), sessions: {}, contexts: {} };
77
+ _indexCache = fresh;
78
+ return fresh;
79
+ }
80
+ function saveIndex(index, projectRoot) {
81
+ index.updated_at = nowIso();
82
+ const content = JSON.stringify(index, null, 2);
83
+ // fsync: false — index.json is reconstructable by scanning _output/contexts/
84
+ const [success, error] = atomicWrite(getIndexPath(projectRoot), content, 2, [500, 1000], false);
85
+ if (!success) {
86
+ logWarn("context_store", `Failed to write index: ${error}`);
87
+ }
88
+ _indexCache = index;
89
+ return success;
90
+ }
91
+ function toIndexEntry(state) {
92
+ return {
93
+ summary: state.summary,
94
+ mode: state.mode,
95
+ last_active: state.last_active,
96
+ };
97
+ }
98
+ /**
99
+ * Backward compat: read legacy context.json and convert to ContextState.
100
+ */
101
+ function migrateContextJson(contextId, projectRoot) {
102
+ const legacyPath = path.join(getContextDir(contextId, projectRoot), "context.json");
103
+ if (!fs.existsSync(legacyPath))
104
+ return null;
105
+ try {
106
+ const data = JSON.parse(fs.readFileSync(legacyPath, "utf8"));
107
+ const inFlight = data.in_flight ?? {};
108
+ const oldMode = inFlight.mode ?? "none";
109
+ const MODE_MIGRATION = {
110
+ none: "idle",
111
+ planning: "idle",
112
+ pending_implementation: "has_plan",
113
+ implementing: "active",
114
+ };
115
+ const mode = (MODE_MIGRATION[oldMode] ?? "idle");
116
+ const sessionIds = inFlight.session_ids ??
117
+ (inFlight.session_id ? [inFlight.session_id] : []);
118
+ return {
119
+ id: data.id ?? contextId,
120
+ status: data.status ?? "active",
121
+ summary: data.summary ?? "",
122
+ method: data.method ?? "",
123
+ tags: data.tags ?? [],
124
+ created_at: data.created_at ?? "",
125
+ last_active: data.last_active ?? "",
126
+ mode,
127
+ plan_path: inFlight.artifact_path ?? null,
128
+ plan_hash: inFlight.artifact_hash ?? null,
129
+ plan_signature: null,
130
+ plan_id: null,
131
+ plan_anchors: [],
132
+ plan_hash_consumed: null,
133
+ plan_consumed: false,
134
+ handoff_path: inFlight.handoff_path ?? null,
135
+ handoff_consumed: false,
136
+ work_consumed: false,
137
+ next_artifact_type: null,
138
+ session_ids: sessionIds,
139
+ last_session: null,
140
+ tasks: [],
141
+ };
142
+ }
143
+ catch (error) {
144
+ logWarn("context_store", `Failed to migrate context.json for '${contextId}': ${error}`);
145
+ return null;
146
+ }
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // Core CRUD
150
+ // ---------------------------------------------------------------------------
151
+ /**
152
+ * Read state.json for a context. Falls back to context.json for migration.
153
+ * See SPEC.md §7.2
154
+ */
155
+ export function loadState(contextId, projectRoot) {
156
+ const state = readStateJson(contextId, projectRoot);
157
+ if (state)
158
+ return state;
159
+ // Backward compat: migrate from legacy context.json
160
+ return migrateContextJson(contextId, projectRoot);
161
+ }
162
+ /**
163
+ * Atomically write state.json AND update index.json.
164
+ * See SPEC.md §7.3
165
+ */
166
+ export function saveState(contextId, state, projectRoot) {
167
+ // Ensure the state ID matches
168
+ state.id = contextId;
169
+ const [success, error] = writeStateJson(contextId, state, projectRoot);
170
+ if (!success) {
171
+ logWarn("context_store", `Failed to write state.json for '${contextId}': ${error}`);
172
+ return [false, error];
173
+ }
174
+ // Update index.json
175
+ const index = loadIndex(projectRoot);
176
+ index.contexts[contextId] = toIndexEntry(state);
177
+ // Keep session mappings in sync
178
+ for (const sid of state.session_ids) {
179
+ if (!index.sessions)
180
+ index.sessions = {};
181
+ index.sessions[sid] = contextId;
182
+ }
183
+ const indexOk = saveIndex(index, projectRoot);
184
+ if (!indexOk) {
185
+ return [true, "state.json saved but index.json update failed"];
186
+ }
187
+ return [true, null];
188
+ }
189
+ /**
190
+ * Create a new context folder + state.json + index entry.
191
+ * Throws ValueError-equivalent if context already exists.
192
+ * See SPEC.md §7.4
193
+ */
194
+ export function createContext(contextId, summary, method = "", projectRoot, tags) {
195
+ // Generate ID if needed
196
+ if (!contextId) {
197
+ const existingIds = new Set();
198
+ const contextsDir = getContextsDir(projectRoot);
199
+ if (fs.existsSync(contextsDir)) {
200
+ for (const entry of fs.readdirSync(contextsDir)) {
201
+ const fullPath = path.join(contextsDir, entry);
202
+ try {
203
+ if (fs.statSync(fullPath).isDirectory()) {
204
+ existingIds.add(entry);
205
+ }
206
+ }
207
+ catch { /* ignore */ }
208
+ }
209
+ }
210
+ contextId = generateContextId(summary, existingIds);
211
+ }
212
+ contextId = validateContextId(contextId);
213
+ const contextDir = getContextDir(contextId, projectRoot);
214
+ if (fs.existsSync(contextDir)) {
215
+ throw new Error(`Context '${contextId}' already exists`);
216
+ }
217
+ fs.mkdirSync(contextDir, { recursive: true });
218
+ fs.mkdirSync(path.join(contextDir, "notes"), { recursive: true });
219
+ const now = nowIso();
220
+ const state = {
221
+ id: contextId,
222
+ status: "active",
223
+ summary,
224
+ method,
225
+ tags: tags ?? [],
226
+ created_at: now,
227
+ last_active: now,
228
+ mode: "idle",
229
+ plan_path: null,
230
+ plan_hash: null,
231
+ plan_signature: null,
232
+ plan_id: null,
233
+ plan_anchors: [],
234
+ plan_hash_consumed: null,
235
+ handoff_path: null,
236
+ work_consumed: false, // CHANGED: unified flag
237
+ next_artifact_type: null,
238
+ session_ids: [],
239
+ last_session: null,
240
+ tasks: [],
241
+ };
242
+ saveState(contextId, state, projectRoot);
243
+ logInfo("context_store", `Created context: ${contextId}`);
244
+ return state;
245
+ }
246
+ /**
247
+ * Load a single context by ID.
248
+ * See SPEC.md §7.5
249
+ */
250
+ export function getContext(contextId, projectRoot) {
251
+ try {
252
+ contextId = validateContextId(contextId);
253
+ }
254
+ catch {
255
+ return null;
256
+ }
257
+ return loadState(contextId, projectRoot);
258
+ }
259
+ /**
260
+ * List contexts from index.json, loading each state.json.
261
+ * Falls back to scanning context folders if index is missing.
262
+ * Results sorted by last_active descending.
263
+ * See SPEC.md §7.6
264
+ */
265
+ export function getAllContexts(status, projectRoot) {
266
+ const results = [];
267
+ const contextsDir = getContextsDir(projectRoot);
268
+ if (!fs.existsSync(contextsDir))
269
+ return [];
270
+ // Try index-driven path first
271
+ const index = loadIndex(projectRoot);
272
+ const ctxMap = index.contexts;
273
+ if (ctxMap && typeof ctxMap === "object" && Object.keys(ctxMap).length > 0) {
274
+ const orphanIds = [];
275
+ for (const cid of Object.keys(ctxMap)) {
276
+ const state = loadState(cid, projectRoot);
277
+ if (state && (!status || state.status === status)) {
278
+ results.push(state);
279
+ }
280
+ else if (!state) {
281
+ orphanIds.push(cid);
282
+ }
283
+ }
284
+ if (orphanIds.length > 0) {
285
+ logWarn("context_store", `Index references ${orphanIds.length} missing context(s): ${orphanIds.join(", ")}. Auto-repairing index.`);
286
+ const idx = loadIndex(projectRoot);
287
+ for (const cid of orphanIds) {
288
+ delete idx.contexts[cid];
289
+ if (idx.sessions) {
290
+ for (const [sid, target] of Object.entries(idx.sessions)) {
291
+ if (target === cid)
292
+ delete idx.sessions[sid];
293
+ }
294
+ }
295
+ }
296
+ saveIndex(idx, projectRoot);
297
+ }
298
+ }
299
+ else {
300
+ // Fallback: scan folders
301
+ try {
302
+ for (const entry of fs.readdirSync(contextsDir)) {
303
+ if (entry.startsWith("_"))
304
+ continue;
305
+ const fullPath = path.join(contextsDir, entry);
306
+ try {
307
+ if (!fs.statSync(fullPath).isDirectory())
308
+ continue;
309
+ }
310
+ catch {
311
+ continue;
312
+ }
313
+ const state = loadState(entry, projectRoot);
314
+ if (state && (!status || state.status === status)) {
315
+ results.push(state);
316
+ }
317
+ }
318
+ }
319
+ catch { /* empty dir */ }
320
+ }
321
+ results.sort((a, b) => (b.last_active || "").localeCompare(a.last_active || ""));
322
+ return results;
323
+ }
324
+ /**
325
+ * Update allowed metadata fields (summary, tags, method) on a context.
326
+ * See SPEC.md §7.7
327
+ */
328
+ export function updateContext(contextId, updates, projectRoot) {
329
+ const state = getContext(contextId, projectRoot);
330
+ if (!state)
331
+ return null;
332
+ let changed = false;
333
+ if (updates.summary !== undefined) {
334
+ state.summary = updates.summary;
335
+ changed = true;
336
+ }
337
+ if (updates.tags !== undefined) {
338
+ state.tags = updates.tags;
339
+ changed = true;
340
+ }
341
+ if (updates.method !== undefined) {
342
+ state.method = updates.method;
343
+ changed = true;
344
+ }
345
+ if (!changed)
346
+ return state;
347
+ state.last_active = nowIso();
348
+ saveState(contextId, state, projectRoot);
349
+ return state;
350
+ }
351
+ // ---------------------------------------------------------------------------
352
+ // Session binding & mode updates
353
+ // ---------------------------------------------------------------------------
354
+ /**
355
+ * O(1) lookup: check index.json sessions map first.
356
+ * Side effect: sets logger context path for per-context log routing.
357
+ * See SPEC.md §7.8
358
+ */
359
+ export function getContextBySessionId(sessionId, projectRoot) {
360
+ if (!sessionId || sessionId === "unknown")
361
+ return null;
362
+ const index = loadIndex(projectRoot);
363
+ const cid = index.sessions?.[sessionId];
364
+ if (cid) {
365
+ const state = loadState(cid, projectRoot);
366
+ if (state) {
367
+ setLoggerContext(state.id, projectRoot);
368
+ return state;
369
+ }
370
+ }
371
+ // Fallback: scan all contexts
372
+ for (const state of getAllContexts("active", projectRoot)) {
373
+ if (state.session_ids.includes(sessionId)) {
374
+ setLoggerContext(state.id, projectRoot);
375
+ return state;
376
+ }
377
+ }
378
+ return null;
379
+ }
380
+ function setLoggerContext(contextId, projectRoot) {
381
+ try {
382
+ const ctxDir = getContextDir(contextId, projectRoot);
383
+ if (fs.existsSync(ctxDir)) {
384
+ setContextPath(ctxDir);
385
+ }
386
+ }
387
+ catch {
388
+ // Never crash on logging setup
389
+ }
390
+ }
391
+ /**
392
+ * Add session_id to both index.json sessions map and state.json session_ids.
393
+ * See SPEC.md §7.9
394
+ */
395
+ export function bindSession(contextId, sessionId, projectRoot) {
396
+ if (!sessionId || sessionId === "unknown")
397
+ return false;
398
+ const state = getContext(contextId, projectRoot);
399
+ if (!state)
400
+ return false;
401
+ if (!state.session_ids.includes(sessionId)) {
402
+ state.session_ids.push(sessionId);
403
+ }
404
+ state.last_active = nowIso();
405
+ const [success] = saveState(contextId, state, projectRoot);
406
+ return success;
407
+ }
408
+ /**
409
+ * Change the mode field, optionally setting plan/handoff fields.
410
+ * See SPEC.md §7.10
411
+ */
412
+ export function updateMode(contextId, mode, projectRoot, opts) {
413
+ const state = getContext(contextId, projectRoot);
414
+ if (!state)
415
+ return null;
416
+ state.mode = mode;
417
+ state.last_active = nowIso();
418
+ if (opts) {
419
+ if (opts.plan_path !== undefined)
420
+ state.plan_path = opts.plan_path;
421
+ if (opts.plan_hash !== undefined)
422
+ state.plan_hash = opts.plan_hash;
423
+ if (opts.plan_signature !== undefined)
424
+ state.plan_signature = opts.plan_signature;
425
+ if (opts.plan_id !== undefined)
426
+ state.plan_id = opts.plan_id;
427
+ if (opts.plan_anchors !== undefined)
428
+ state.plan_anchors = opts.plan_anchors;
429
+ if (opts.work_consumed !== undefined)
430
+ state.work_consumed = opts.work_consumed; // CHANGED: unified flag
431
+ if (opts.plan_hash_consumed !== undefined)
432
+ state.plan_hash_consumed = opts.plan_hash_consumed;
433
+ }
434
+ // Clear plan/handoff fields when returning to idle
435
+ if (mode === "idle") {
436
+ state.plan_path = null;
437
+ state.plan_hash = null;
438
+ state.plan_signature = null;
439
+ state.plan_id = null;
440
+ state.plan_anchors = [];
441
+ state.plan_hash_consumed = null;
442
+ state.handoff_path = null;
443
+ state.work_consumed = false; // CHANGED: unified flag
444
+ state.next_artifact_type = null;
445
+ }
446
+ saveState(contextId, state, projectRoot);
447
+ return state;
448
+ }
449
+ /**
450
+ * Transition idle/has_staged_work → active, unless in plan mode.
451
+ * See SPEC.md §7.11
452
+ */
453
+ export function maybeActivate(contextId, permissionMode, projectRoot, caller = "") {
454
+ if (permissionMode === "plan")
455
+ return false;
456
+ const state = getContext(contextId, projectRoot);
457
+ if (!state)
458
+ return false;
459
+ if (state.mode === "idle" || state.mode === "has_staged_work") {
460
+ const oldMode = state.mode;
461
+ const opts = {};
462
+ if (oldMode === "has_staged_work")
463
+ opts.work_consumed = true; // CHANGED: unified flag
464
+ updateMode(contextId, "active", projectRoot, opts);
465
+ logInfo("context_store", `maybe_activate (${caller}): ${contextId} ${oldMode} -> active`);
466
+ return true;
467
+ }
468
+ return false;
469
+ }
470
+ // ---------------------------------------------------------------------------
471
+ // Lifecycle
472
+ // ---------------------------------------------------------------------------
473
+ /**
474
+ * Mark context completed and archive it.
475
+ * See SPEC.md §7.12
476
+ */
477
+ export function completeContext(contextId, projectRoot) {
478
+ const state = getContext(contextId, projectRoot);
479
+ if (!state)
480
+ return null;
481
+ if (state.status === "completed") {
482
+ logInfo("context_store", `Context '${contextId}' already completed`);
483
+ return state;
484
+ }
485
+ state.status = "completed";
486
+ state.last_active = nowIso();
487
+ saveState(contextId, state, projectRoot);
488
+ logInfo("context_store", `Completed context: ${contextId}`);
489
+ const archived = archiveContext(contextId, projectRoot);
490
+ return archived ?? state;
491
+ }
492
+ /**
493
+ * Move completed context folder to _archive/, update indices.
494
+ * See SPEC.md §7.13
495
+ */
496
+ export function archiveContext(contextId, projectRoot) {
497
+ const state = getContext(contextId, projectRoot);
498
+ if (!state) {
499
+ logWarn("context_store", `Cannot archive: context '${contextId}' not found`);
500
+ return null;
501
+ }
502
+ if (state.status !== "completed") {
503
+ logWarn("context_store", `Cannot archive: context '${contextId}' not completed`);
504
+ return null;
505
+ }
506
+ const sourceDir = getContextDir(contextId, projectRoot);
507
+ const archiveDest = getArchiveContextDir(contextId, projectRoot);
508
+ if (fs.existsSync(archiveDest)) {
509
+ logWarn("context_store", `Cannot archive: archive folder already exists for '${contextId}'`);
510
+ return null;
511
+ }
512
+ const archiveParent = path.dirname(archiveDest);
513
+ fs.mkdirSync(archiveParent, { recursive: true });
514
+ try {
515
+ fs.renameSync(sourceDir, archiveDest);
516
+ }
517
+ catch (error) {
518
+ logError("context_store", `Failed to move context to archive: ${error}`);
519
+ return null;
520
+ }
521
+ // Remove from main index
522
+ const index = loadIndex(projectRoot);
523
+ delete index.contexts[contextId];
524
+ const sessions = index.sessions ?? {};
525
+ for (const [sid, cid] of Object.entries(sessions)) {
526
+ if (cid === contextId)
527
+ delete sessions[sid];
528
+ }
529
+ saveIndex(index, projectRoot);
530
+ // Add to archive index
531
+ updateArchiveIndex(state, projectRoot);
532
+ logInfo("context_store", `Archived context: ${contextId}`);
533
+ return state;
534
+ }
535
+ /**
536
+ * Reopen a completed/archived context.
537
+ * See SPEC.md §7.14
538
+ */
539
+ export function reopenContext(contextId, projectRoot) {
540
+ let state = getContext(contextId, projectRoot);
541
+ if (!state) {
542
+ state = restoreFromArchive(contextId, projectRoot);
543
+ }
544
+ if (!state)
545
+ return null;
546
+ if (state.status === "active") {
547
+ logInfo("context_store", `Context '${contextId}' already active`);
548
+ return state;
549
+ }
550
+ state.status = "active";
551
+ state.last_active = nowIso();
552
+ saveState(contextId, state, projectRoot);
553
+ logInfo("context_store", `Reopened context: ${contextId}`);
554
+ return state;
555
+ }
556
+ // ---------------------------------------------------------------------------
557
+ // Auto-creation from prompt
558
+ // ---------------------------------------------------------------------------
559
+ /**
560
+ * Auto-create a context from the user's prompt.
561
+ * See SPEC.md §7.15
562
+ */
563
+ export function createContextFromPrompt(userPrompt, projectRoot) {
564
+ let summary = userPrompt.trim().slice(0, 2000);
565
+ if (userPrompt.trim().length > 2000) {
566
+ summary += "...";
567
+ }
568
+ return createContext(null, summary, "auto-created", projectRoot, ["auto-created"]);
569
+ }
570
+ // ---------------------------------------------------------------------------
571
+ // Archive helpers
572
+ // ---------------------------------------------------------------------------
573
+ function updateArchiveIndex(state, projectRoot) {
574
+ const archiveDir = getArchiveDir(projectRoot);
575
+ const archiveIndexPath = getArchiveIndexPath(projectRoot);
576
+ fs.mkdirSync(archiveDir, { recursive: true });
577
+ let archiveIndex = {
578
+ version: INDEX_VERSION,
579
+ updated_at: nowIso(),
580
+ sessions: {},
581
+ contexts: {},
582
+ };
583
+ if (fs.existsSync(archiveIndexPath)) {
584
+ try {
585
+ archiveIndex = JSON.parse(fs.readFileSync(archiveIndexPath, "utf8"));
586
+ }
587
+ catch (error_) {
588
+ logWarn("context_store", `Failed to read archive index, recreating: ${error_}`);
589
+ }
590
+ }
591
+ archiveIndex.contexts[state.id] = toIndexEntry(state);
592
+ archiveIndex.updated_at = nowIso();
593
+ const content = JSON.stringify(archiveIndex, null, 2);
594
+ const [success, error] = atomicWrite(archiveIndexPath, content);
595
+ if (!success) {
596
+ logWarn("context_store", `Failed to write archive index: ${error}`);
597
+ }
598
+ return success;
599
+ }
600
+ function restoreFromArchive(contextId, projectRoot) {
601
+ const archiveDir = getArchiveContextDir(contextId, projectRoot);
602
+ const activeDir = getContextDir(contextId, projectRoot);
603
+ if (!fs.existsSync(archiveDir))
604
+ return null;
605
+ if (fs.existsSync(activeDir)) {
606
+ logWarn("context_store", `Cannot restore: active folder already exists for '${contextId}'`);
607
+ return null;
608
+ }
609
+ try {
610
+ fs.renameSync(archiveDir, activeDir);
611
+ }
612
+ catch (error) {
613
+ logError("context_store", `Failed to restore context from archive: ${error}`);
614
+ return null;
615
+ }
616
+ // Remove from archive index
617
+ removeFromArchiveIndex(contextId, projectRoot);
618
+ const state = loadState(contextId, projectRoot);
619
+ logInfo("context_store", `Restored context from archive: ${contextId}`);
620
+ return state;
621
+ }
622
+ function removeFromArchiveIndex(contextId, projectRoot) {
623
+ const archiveIndexPath = getArchiveIndexPath(projectRoot);
624
+ if (!fs.existsSync(archiveIndexPath))
625
+ return true;
626
+ try {
627
+ const archiveIndex = JSON.parse(fs.readFileSync(archiveIndexPath, "utf8"));
628
+ if (archiveIndex.contexts[contextId]) {
629
+ delete archiveIndex.contexts[contextId];
630
+ archiveIndex.updated_at = nowIso();
631
+ const content = JSON.stringify(archiveIndex, null, 2);
632
+ const [success, error] = atomicWrite(archiveIndexPath, content);
633
+ if (!success) {
634
+ logWarn("context_store", `Failed to write archive index: ${error}`);
635
+ return false;
636
+ }
637
+ }
638
+ return true;
639
+ }
640
+ catch (error) {
641
+ logWarn("context_store", `Failed to read archive index: ${error}`);
642
+ return false;
643
+ }
644
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Plan lifecycle management — archival, lookup, and path extraction.
3
+ * See SPEC.md §9
4
+ *
5
+ * Provides pure-data operations on plan files:
6
+ * - archivePlan: copy plan to context plans/ folder, compute hash + signature
7
+ * - findLatestPlan: locate the most relevant plan for a context
8
+ * - extractPlanPathFromResult: parse plan path from ExitPlanMode output
9
+ */
10
+ /**
11
+ * Archive a plan file to the context's plans/ folder.
12
+ * Computes a content hash and signature.
13
+ * Does NOT modify state.json or mode.
14
+ * See SPEC.md §9.2
15
+ *
16
+ * Returns [archivedPath, planHash, planSignature] on success,
17
+ * or [null, null, null] on error.
18
+ */
19
+ export declare function archivePlan(planPath: string, contextId: string, projectRoot?: string): [string | null, string | null, string | null];
20
+ /**
21
+ * Find the most relevant plan file for a context.
22
+ * Priority: state.json plan_path > most recent .md in plans/ dir.
23
+ * See SPEC.md §9.3
24
+ */
25
+ export declare function findLatestPlan(contextId: string, projectRoot?: string): string | null;
26
+ /**
27
+ * Generate a short unique plan identifier (8 hex chars).
28
+ * See SPEC.md §9.4
29
+ */
30
+ export declare function generatePlanId(): string;
31
+ /**
32
+ * Aggressively normalize plan content for hashing.
33
+ * Strips all XML/HTML tags and collapses whitespace.
34
+ * See SPEC.md §9.5
35
+ */
36
+ export declare function normalizePlanContent(text: string): string;
37
+ /**
38
+ * Extract structural anchors from plan content.
39
+ * Returns markdown headings + first substantial paragraph as short strings.
40
+ * See SPEC.md §9.6
41
+ */
42
+ export declare function extractPlanAnchors(content: string, maxAnchors?: number): string[];
43
+ /**
44
+ * Find the plan file path by parsing the session transcript JSONL.
45
+ * Searches in reverse for the most recent Write tool call targeting .claude/plans/.
46
+ * See SPEC.md §9.7
47
+ */
48
+ export declare function findPlanPathInTranscript(transcriptPath: string): string | null;
49
+ /**
50
+ * Extract plan file path from ExitPlanMode tool result.
51
+ * Parses the pattern: "Your plan has been saved to: <path>"
52
+ * See SPEC.md §9.8
53
+ */
54
+ export declare function extractPlanPathFromResult(toolResult: string): string | null;