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
@@ -6,10 +6,11 @@
6
6
 
7
7
  import * as fs from "node:fs";
8
8
 
9
- import { getProjectRoot } from "./constants.js";
10
- import { logDebug, logWarn, hookLog, setSessionId, getContextPath as _getContextPath } from "./logger.js";
11
- import { getContextBySessionId } from "../context/context-store.js";
12
- import type { HookInput, HookOutput, PermissionRequestOutput } from "../types.js";
9
+ import { getContextBySessionId, maybeActivate } from "../context/context-store.js";
10
+ import { getProjectRoot } from "../runtime/constants.js";
11
+ import { logDebug, logWarn, hookLog, setSessionId, getContextPath as _getContextPath } from "../runtime/logger.js";
12
+ import { HookInputSchema } from "../schemas.js";
13
+ import type { ContextState, HookInput, HookOutput, PermissionRequestOutput } from "../types.js";
13
14
 
14
15
  // Re-export logger functions for convenience (matches Python hook_utils re-exports)
15
16
 
@@ -24,7 +25,120 @@ let _lastToolName: string | null = null;
24
25
  let _cachedHookName: string | null = null;
25
26
 
26
27
  // Pre-fetched input stash
27
- let _prefetchedInput: Record<string, any> | null = null;
28
+ let _prefetchedInput: Record<string, unknown> | null = null;
29
+
30
+ function readStringField(value: Record<string, unknown>, key: string): null | string {
31
+ const field = value[key];
32
+ return typeof field === "string" ? field : null;
33
+ }
34
+
35
+ export interface BoundSessionContext {
36
+ payload: HookInput;
37
+ projectRoot: string;
38
+ sessionId: string;
39
+ state: ContextState;
40
+ }
41
+
42
+ export interface PersistenceContext extends BoundSessionContext {
43
+ toolInput: Record<string, unknown>;
44
+ }
45
+
46
+ export interface ToolInputContext {
47
+ payload: HookInput;
48
+ toolInput: Record<string, unknown>;
49
+ }
50
+
51
+ /**
52
+ * Load the current payload, resolve its project root, and require an already-bound session.
53
+ * Returns null when the hook should quietly no-op.
54
+ */
55
+ export function requireBoundSession(
56
+ hookName: string,
57
+ prefetchedPayload?: HookInput | null,
58
+ ): BoundSessionContext | null {
59
+ const payload = prefetchedPayload ?? loadHookInput();
60
+ if (!payload) return null;
61
+
62
+ const sessionId = payload.session_id;
63
+ if (!sessionId) {
64
+ logDebug(hookName, "No session_id available");
65
+ return null;
66
+ }
67
+
68
+ const projectRoot = getProjectRoot(payload.cwd);
69
+ const state = getContextBySessionId(sessionId, projectRoot);
70
+ if (!state) {
71
+ logDebug(hookName, `No bound context for session ${sessionId.slice(0, 8)}`);
72
+ return null;
73
+ }
74
+
75
+ return { payload, projectRoot, sessionId, state };
76
+ }
77
+
78
+ /**
79
+ * Require a bound session plus tool_input for PostToolUse task persistence hooks.
80
+ */
81
+ export function requirePersistenceContext(
82
+ expectedTool: string,
83
+ hookName: string,
84
+ ): PersistenceContext | null {
85
+ const bound = requireBoundSession(hookName);
86
+ if (!bound) return null;
87
+
88
+ const { payload } = bound;
89
+ if (payload.hook_event_name !== "PostToolUse") {
90
+ return null;
91
+ }
92
+ if (payload.tool_name !== expectedTool) {
93
+ return null;
94
+ }
95
+ if (checkSkipPersistence(payload, hookName)) {
96
+ return null;
97
+ }
98
+
99
+ const toolInput = getToolInput(payload);
100
+ if (!toolInput) {
101
+ logWarn(hookName, `${expectedTool} missing tool_input payload`);
102
+ return null;
103
+ }
104
+
105
+ return { ...bound, toolInput };
106
+ }
107
+
108
+ /**
109
+ * Require a tool_input payload for tool-oriented hooks without needing a bound session.
110
+ */
111
+ export function requireToolInput(
112
+ hookName: string,
113
+ ): ToolInputContext | null {
114
+ const payload = loadHookInput();
115
+ if (!payload) return null;
116
+
117
+ const toolInput = getToolInput(payload);
118
+ if (!toolInput) {
119
+ logDebug(hookName, "No tool_input payload");
120
+ return null;
121
+ }
122
+
123
+ return { payload, toolInput };
124
+ }
125
+
126
+ /**
127
+ * Best-effort wrapper around maybeActivate. Hooks should never fail closed on activation.
128
+ */
129
+ export function safeMaybeActivate(
130
+ contextId: string,
131
+ permissionMode: string,
132
+ projectRoot?: string,
133
+ hookName = "hook",
134
+ ): boolean {
135
+ try {
136
+ return maybeActivate(contextId, permissionMode, projectRoot, hookName);
137
+ } catch (error) {
138
+ logWarn(hookName, `maybeActivate failed for ${contextId}: ${error}`);
139
+ return false;
140
+ }
141
+ }
28
142
 
29
143
  /**
30
144
  * Load and parse JSON from stdin (or return prefetched input if set).
@@ -36,23 +150,28 @@ export function loadHookInput(): HookInput | null {
36
150
  const result = _prefetchedInput;
37
151
  _prefetchedInput = null; // consume once
38
152
  if (result && typeof result === "object") {
39
- _lastHookEvent = result.hook_event_name ?? null;
40
- _lastToolName = result.tool_name ?? null;
153
+ _lastHookEvent = readStringField(result, "hook_event_name");
154
+ _lastToolName = readStringField(result, "tool_name");
41
155
  }
42
- return result as HookInput;
156
+ return result as unknown as HookInput;
43
157
  }
44
158
 
45
159
  try {
46
160
  // Read entire stdin using fd 0 (cross-platform, works on Windows)
47
- const inputData = fs.readFileSync(0, "utf-8").trim();
161
+ const inputData = fs.readFileSync(0, "utf8").trim();
48
162
  if (!inputData) return null;
49
163
 
50
- const result = JSON.parse(inputData);
164
+ const result = JSON.parse(inputData) as Record<string, unknown>;
165
+ const validated = HookInputSchema.safeParse(result);
166
+ if (!validated.success) {
167
+ logWarn("hook_utils", `Hook input schema validation failed: ${validated.error.message}`);
168
+ return null;
169
+ }
51
170
  if (result && typeof result === "object") {
52
- _lastHookEvent = result.hook_event_name ?? null;
53
- _lastToolName = result.tool_name ?? null;
171
+ _lastHookEvent = readStringField(result, "hook_event_name");
172
+ _lastToolName = readStringField(result, "tool_name");
54
173
  }
55
- return result as HookInput;
174
+ return result as unknown as HookInput;
56
175
  } catch {
57
176
  return null;
58
177
  }
@@ -78,7 +197,7 @@ export function validateHookEvent(
78
197
  */
79
198
  export function getToolInput(
80
199
  payload: HookInput,
81
- ): Record<string, any> | null {
200
+ ): Record<string, unknown> | null {
82
201
  const toolInput = payload.tool_input;
83
202
  return toolInput && typeof toolInput === "object" ? toolInput : null;
84
203
  }
@@ -95,7 +214,11 @@ export function checkSkipPersistence(
95
214
  if (!toolInput) return false;
96
215
 
97
216
  const {metadata} = toolInput;
98
- if (metadata && typeof metadata === "object" && metadata.skip_persistence) {
217
+ if (
218
+ metadata &&
219
+ typeof metadata === "object" &&
220
+ Boolean((metadata as Record<string, unknown>).skip_persistence)
221
+ ) {
99
222
  logDebug(hookName, "Skipping persistence (skip_persistence flag set)");
100
223
  return true;
101
224
  }
@@ -167,12 +290,12 @@ export function emitContextAndBlock(
167
290
  }
168
291
 
169
292
  /** Log hook output (context, systemMessage, or block) to hook-log.jsonl for visibility. */
170
- function _logEmit(type: "context" | "systemMessage" | "block", chars: number, payload: Record<string, any>): void {
293
+ function _logEmit(type: "context" | "systemMessage" | "block", chars: number, payload: Record<string, unknown>): void {
171
294
  const hook = _cachedHookName ?? "unknown";
172
295
  const event = payload.event ?? "unknown";
173
296
  const mechanism = payload.mechanism ? ` via ${payload.mechanism}` : "";
174
297
  const msg = type === "block"
175
- ? `HOOK_OUTPUT [${type}] ${event} ${chars} chars${mechanism}, reason="${(payload.blockReason ?? "").slice(0, 80)}"`
298
+ ? `HOOK_OUTPUT [${type}] ${event} ${chars} chars${mechanism}, reason="${String(payload.blockReason ?? "").slice(0, 80)}"`
176
299
  : `HOOK_OUTPUT [${type}] ${event} ${chars} chars`;
177
300
  hookLog("info", hook, msg, { data: payload });
178
301
  }
@@ -316,8 +439,13 @@ export function emitBlock(reason: string, context?: string): void {
316
439
  */
317
440
  function detectTemplate(scriptPath = ""): string {
318
441
  const p = (scriptPath || (process.argv[1] ?? "")).replaceAll('\\', "/");
319
- if (p.includes("/_shared/hooks/") || p.startsWith("_shared/hooks/")) {
320
- return "shared";
442
+ if (
443
+ p.includes("/_core/hooks-ts/") ||
444
+ p.startsWith("_core/hooks-ts/") ||
445
+ p.includes("/core/hooks-ts/") ||
446
+ p.startsWith("core/hooks-ts/")
447
+ ) {
448
+ return "core";
321
449
  }
322
450
  const match = p.match(/_([a-z][a-z0-9-]*)\/hooks\//);
323
451
  if (match?.[1]) return match[1]; // e.g., "cc-native"
@@ -390,32 +518,39 @@ export function getContextPercentRemaining(
390
518
  * Read stdin early and extract session_id + event metadata.
391
519
  * Stashes parsed input for loadHookInput() to consume later.
392
520
  */
393
- function _earlyReadInput(prefetchedInput?: Record<string, any>): void {
521
+ function _earlyReadInput(prefetchedInput?: Record<string, unknown>): void {
394
522
  if (prefetchedInput !== undefined) {
395
523
  _prefetchedInput = prefetchedInput;
396
524
  }
397
525
 
398
526
  // If we already have prefetched input, extract metadata from it
399
527
  if (_prefetchedInput && typeof _prefetchedInput === "object") {
400
- _lastHookEvent = _prefetchedInput.hook_event_name ?? null;
401
- _lastToolName = _prefetchedInput.tool_name ?? null;
402
- if (_prefetchedInput.session_id) {
403
- setSessionId(_prefetchedInput.session_id);
528
+ _lastHookEvent = readStringField(_prefetchedInput, "hook_event_name");
529
+ _lastToolName = readStringField(_prefetchedInput, "tool_name");
530
+ const sessionId = readStringField(_prefetchedInput, "session_id");
531
+ if (sessionId) {
532
+ setSessionId(sessionId);
404
533
  }
405
534
  return;
406
535
  }
407
536
 
408
537
  // Read stdin now so HOOK_START can include sid
409
538
  try {
410
- const inputData = fs.readFileSync(0, "utf-8").trim();
539
+ const inputData = fs.readFileSync(0, "utf8").trim();
411
540
  if (inputData) {
412
- const parsed = JSON.parse(inputData);
541
+ const parsed = JSON.parse(inputData) as Record<string, unknown>;
542
+ const validated = HookInputSchema.safeParse(parsed);
543
+ if (!validated.success) {
544
+ logWarn("hook_utils", `Early input schema validation failed: ${validated.error.message}`);
545
+ return;
546
+ }
413
547
  if (parsed && typeof parsed === "object") {
414
548
  _prefetchedInput = parsed;
415
- _lastHookEvent = parsed.hook_event_name ?? null;
416
- _lastToolName = parsed.tool_name ?? null;
417
- if (parsed.session_id) {
418
- setSessionId(parsed.session_id);
549
+ _lastHookEvent = readStringField(parsed, "hook_event_name");
550
+ _lastToolName = readStringField(parsed, "tool_name");
551
+ const sessionId = readStringField(parsed, "session_id");
552
+ if (sessionId) {
553
+ setSessionId(sessionId);
419
554
  }
420
555
  }
421
556
  }
@@ -431,7 +566,7 @@ function _earlyReadInput(prefetchedInput?: Record<string, any>): void {
431
566
  export function runHook(
432
567
  mainFunc: () => number | void,
433
568
  hookName = "unknown",
434
- prefetchedInput?: Record<string, any>,
569
+ prefetchedInput?: Record<string, unknown>,
435
570
  ): never {
436
571
  _earlyReadInput(prefetchedInput);
437
572
  _cachedHookName = hookName;
@@ -439,7 +574,8 @@ export function runHook(
439
574
  // Ensure cwd is project root so relative paths in hooks resolve correctly,
440
575
  // even when cwd has drifted via `cd` in a Bash tool call.
441
576
  try {
442
- const projectRoot = getProjectRoot(_prefetchedInput?.cwd);
577
+ const cwd = _prefetchedInput ? readStringField(_prefetchedInput, "cwd") ?? undefined : undefined;
578
+ const projectRoot = getProjectRoot(cwd);
443
579
  if (process.cwd() !== projectRoot) process.chdir(projectRoot);
444
580
  } catch { /* non-fatal — proceed with current cwd */ }
445
581
 
@@ -448,7 +584,7 @@ export function runHook(
448
584
  const event = _lastHookEvent ?? "unknown";
449
585
  const tool = _lastToolName;
450
586
 
451
- const startData: Record<string, any> = {
587
+ const startData: Record<string, unknown> = {
452
588
  lifecycle: "start",
453
589
  template,
454
590
  event,
@@ -464,7 +600,7 @@ export function runHook(
464
600
  const result = mainFunc();
465
601
  exitCode = typeof result === "number" ? result : 0;
466
602
  status = exitCode !== 0 ? "blocked" : "success";
467
- } catch (error: any) {
603
+ } catch (error: unknown) {
468
604
  if (error instanceof Error && error.message.startsWith("SystemExit:")) {
469
605
  const code = parseInt(error.message.slice(11), 10);
470
606
  exitCode = isNaN(code) ? (error.message.slice(11) ? 1 : 0) : code;
@@ -489,7 +625,7 @@ export function runHook(
489
625
  export function runHookAsync(
490
626
  mainFunc: () => Promise<number | void>,
491
627
  hookName = "unknown",
492
- prefetchedInput?: Record<string, any>,
628
+ prefetchedInput?: Record<string, unknown>,
493
629
  ): void {
494
630
  _earlyReadInput(prefetchedInput);
495
631
  _cachedHookName = hookName;
@@ -497,7 +633,8 @@ export function runHookAsync(
497
633
  // Ensure cwd is project root so relative paths in hooks resolve correctly,
498
634
  // even when cwd has drifted via `cd` in a Bash tool call.
499
635
  try {
500
- const projectRoot = getProjectRoot(_prefetchedInput?.cwd);
636
+ const cwd = _prefetchedInput ? readStringField(_prefetchedInput, "cwd") ?? undefined : undefined;
637
+ const projectRoot = getProjectRoot(cwd);
501
638
  if (process.cwd() !== projectRoot) process.chdir(projectRoot);
502
639
  } catch { /* non-fatal — proceed with current cwd */ }
503
640
 
@@ -506,7 +643,7 @@ export function runHookAsync(
506
643
  const event = _lastHookEvent ?? "unknown";
507
644
  const tool = _lastToolName;
508
645
 
509
- const startData: Record<string, any> = {
646
+ const startData: Record<string, unknown> = {
510
647
  lifecycle: "start",
511
648
  template,
512
649
  event,
@@ -520,7 +657,7 @@ export function runHookAsync(
520
657
  _emitHookEnd(hookName, startTime, exitCode, exitCode !== 0 ? "blocked" : "success", null, startData, event, tool, template);
521
658
  _drainAndExit(exitCode);
522
659
  })
523
- .catch((error: any) => {
660
+ .catch((error: unknown) => {
524
661
  let exitCode = 0;
525
662
  let status = "error";
526
663
  let errorInfo: [Error, string] | null = null;
@@ -547,7 +684,7 @@ function _emitHookEnd(
547
684
  exitCode: number,
548
685
  status: string,
549
686
  errorInfo: [Error, string] | null,
550
- startData: Record<string, any>,
687
+ startData: Record<string, unknown>,
551
688
  event: string,
552
689
  tool: string | null,
553
690
  template: string,
@@ -561,7 +698,7 @@ function _emitHookEnd(
561
698
  const durationMs = Math.round((performance.now() - startTime) * 10) / 10;
562
699
  const endEvent = _lastHookEvent ?? event;
563
700
  const endTool = _lastToolName ?? tool;
564
- const endData: Record<string, any> = {
701
+ const endData: Record<string, unknown> = {
565
702
  lifecycle: "end",
566
703
  status,
567
704
  duration_ms: durationMs,
@@ -602,4 +739,5 @@ function _drainAndExit(code: number): void {
602
739
  });
603
740
  }
604
741
 
605
- export {hookLog, logBlocking, logDebug, logDiagnostic, logError, logHookError, logInfo, logWarn, setContextPath, setSessionId} from "./logger.js";
742
+ export {hookLog, logBlocking, logDebug, logDiagnostic, logError, logHookError, logInfo, logWarn, setContextPath, setSessionId} from "../runtime/logger.js";
743
+
@@ -0,0 +1,80 @@
1
+ import { safeMaybeActivate, logInfo, logWarn } from "./hook-utils.js";
2
+ import { buildContextInventory } from "../context/context-formatter.js";
3
+ import { BlockRequest, determineContext } from "../context/context-selector.js";
4
+ import {
5
+ bindSession,
6
+ getContextBySessionId,
7
+ saveState,
8
+ } from "../context/context-store.js";
9
+ import type { ContextState } from "../types.js";
10
+
11
+ export interface PromptBindingResult {
12
+ outputs: string[];
13
+ blockedReason?: string;
14
+ }
15
+
16
+ export function shouldClearHandoff(state: ContextState): boolean {
17
+ return Boolean(state.handoff_path);
18
+ }
19
+
20
+ export async function executePromptBinding(
21
+ prompt: string | undefined,
22
+ sessionId: string,
23
+ permissionMode: string,
24
+ projectRoot: string,
25
+ ): Promise<PromptBindingResult> {
26
+ const outputs: string[] = [];
27
+ const existingCtx = getContextBySessionId(sessionId, projectRoot);
28
+
29
+ if (existingCtx) {
30
+ safeMaybeActivate(
31
+ existingCtx.id,
32
+ permissionMode,
33
+ projectRoot,
34
+ "user_prompt_submit",
35
+ );
36
+ return { outputs };
37
+ }
38
+
39
+ if (!prompt) return { outputs };
40
+
41
+ try {
42
+ const [contextId, method, outputText] = await determineContext(
43
+ prompt,
44
+ sessionId,
45
+ projectRoot,
46
+ );
47
+
48
+ if (contextId) {
49
+ bindSession(contextId, sessionId, projectRoot);
50
+ safeMaybeActivate(contextId, permissionMode, projectRoot, "user_prompt_submit");
51
+
52
+ const state = getContextBySessionId(sessionId, projectRoot);
53
+ if (state && shouldClearHandoff(state)) {
54
+ state.handoff_path = null;
55
+ saveState(state.id, state, projectRoot);
56
+ }
57
+
58
+ logInfo("user_prompt_submit", `Context ${contextId} via ${method}`);
59
+ }
60
+
61
+ if (outputText) outputs.push(outputText);
62
+
63
+ try {
64
+ const boundState = getContextBySessionId(sessionId, projectRoot);
65
+ if (boundState) {
66
+ const inventory = buildContextInventory(boundState, projectRoot);
67
+ if (inventory) outputs.push(inventory);
68
+ }
69
+ } catch (error) {
70
+ logWarn("user_prompt_submit", `Inventory failed (non-critical): ${error}`);
71
+ }
72
+ } catch (error) {
73
+ if (error instanceof BlockRequest) {
74
+ return { outputs, blockedReason: (error as Error).message };
75
+ }
76
+ throw error;
77
+ }
78
+
79
+ return { outputs };
80
+ }
@@ -0,0 +1,82 @@
1
+ import * as crypto from "node:crypto";
2
+
3
+ import { determineArtifactType } from "../context/context-store.js";
4
+ import {
5
+ extractPlanAnchors,
6
+ generatePlanId,
7
+ normalizePlanContent,
8
+ } from "../context/plan-manager.js";
9
+ import { nowIso } from "../runtime/utils.js";
10
+ import type { ContextState, GitState, LastSession } from "../types.js";
11
+
12
+ function formatArchiveTimestamp(date: Date): string {
13
+ return (
14
+ `${date.getFullYear()}-` +
15
+ `${String(date.getMonth() + 1).padStart(2, "0")}-` +
16
+ `${String(date.getDate()).padStart(2, "0")}-` +
17
+ `${String(date.getHours()).padStart(2, "0")}` +
18
+ `${String(date.getMinutes()).padStart(2, "0")}`
19
+ );
20
+ }
21
+
22
+ export function computePlanFallback(
23
+ state: ContextState,
24
+ planContent: string,
25
+ ): Partial<ContextState> {
26
+ const normalized = normalizePlanContent(planContent);
27
+ const planHash = crypto
28
+ .createHash("sha256")
29
+ .update(normalized, "utf8")
30
+ .digest("hex")
31
+ .slice(0, 12);
32
+
33
+ return {
34
+ plan_hash: planHash,
35
+ plan_signature: planContent.slice(0, 200),
36
+ plan_id: generatePlanId(),
37
+ plan_anchors: extractPlanAnchors(planContent),
38
+ work_consumed: state.work_consumed ?? false,
39
+ };
40
+ }
41
+
42
+ export function shouldStage(
43
+ state: ContextState,
44
+ permissionMode: string,
45
+ ): boolean {
46
+ const artifactType = determineArtifactType(state);
47
+ const canStage = state.mode === "active" || permissionMode === "plan";
48
+ return Boolean(artifactType && canStage && !state.work_consumed);
49
+ }
50
+
51
+ export function buildSessionMetadata(
52
+ sessionId: string,
53
+ source: string,
54
+ transcriptPath: string | undefined,
55
+ gitState?: GitState,
56
+ ): LastSession {
57
+ return {
58
+ session_id: sessionId,
59
+ save_reason: source,
60
+ saved_at: nowIso(),
61
+ ...(transcriptPath ? { transcript_path: transcriptPath } : {}),
62
+ git_state: gitState ?? {},
63
+ };
64
+ }
65
+
66
+ export function generateArchiveFilename(
67
+ sessionId: string,
68
+ date: Date,
69
+ existingNames: Iterable<string>,
70
+ ): string {
71
+ const existing = new Set(existingNames);
72
+ const timestamp = formatArchiveTimestamp(date);
73
+
74
+ let archiveName = `${timestamp}-${sessionId}.jsonl`;
75
+ let counter = 2;
76
+ while (existing.has(archiveName)) {
77
+ archiveName = `${timestamp}-${sessionId}-${counter}.jsonl`;
78
+ counter += 1;
79
+ }
80
+
81
+ return archiveName;
82
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "lib-ts-tests",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "test": "vitest run",
7
+ "test:unit": "vitest run '__tests__/runtime/**/*.test.ts' '__tests__/templates/**/*.test.ts'",
8
+ "test:contract": "vitest run '__tests__/context/**/*.test.ts' '__tests__/handoff/**/*.test.ts'",
9
+ "test:integration": "vitest run '__tests__/integration/**/*.test.ts'",
10
+ "test:parity": "vitest run '__tests__/integration/python-parity.test.ts'"
11
+ },
12
+ "devDependencies": {
13
+ "chai": "^5.0.0",
14
+ "@types/sinon": "^17.0.0",
15
+ "sinon": "^17.0.0",
16
+ "typescript": "^5.0.0",
17
+ "vitest": "^3.2.4"
18
+ }
19
+ }