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,620 @@
1
+ /**
2
+ * Common utilities for hook scripts.
3
+ * Standardized boilerplate for JSON parsing, validation, error handling.
4
+ * See SPEC.md §5
5
+ */
6
+ import * as fs from "node:fs";
7
+ import { getContextBySessionId, maybeActivate } from "../context/context-store.js";
8
+ import { getProjectRoot } from "../runtime/constants.js";
9
+ import { logDebug, logWarn, hookLog, setSessionId, getContextPath as _getContextPath } from "../runtime/logger.js";
10
+ import { HookInputSchema } from "../schemas.js";
11
+ // Re-export logger functions for convenience (matches Python hook_utils re-exports)
12
+ // Context window baseline: tokens not visible in hook data §5.9
13
+ export const CONTEXT_BASELINE_TOKENS = 22_600;
14
+ export const DEFAULT_CONTEXT_WINDOW_SIZE = 200_000;
15
+ // Event metadata stash — populated by loadHookInput(), read by runHook()
16
+ let _lastHookEvent = null;
17
+ let _lastToolName = null;
18
+ let _cachedHookName = null;
19
+ // Pre-fetched input stash
20
+ let _prefetchedInput = null;
21
+ function readStringField(value, key) {
22
+ const field = value[key];
23
+ return typeof field === "string" ? field : null;
24
+ }
25
+ /**
26
+ * Load the current payload, resolve its project root, and require an already-bound session.
27
+ * Returns null when the hook should quietly no-op.
28
+ */
29
+ export function requireBoundSession(hookName, prefetchedPayload) {
30
+ const payload = prefetchedPayload ?? loadHookInput();
31
+ if (!payload)
32
+ return null;
33
+ const sessionId = payload.session_id;
34
+ if (!sessionId) {
35
+ logDebug(hookName, "No session_id available");
36
+ return null;
37
+ }
38
+ const projectRoot = getProjectRoot(payload.cwd);
39
+ const state = getContextBySessionId(sessionId, projectRoot);
40
+ if (!state) {
41
+ logDebug(hookName, `No bound context for session ${sessionId.slice(0, 8)}`);
42
+ return null;
43
+ }
44
+ return { payload, projectRoot, sessionId, state };
45
+ }
46
+ /**
47
+ * Require a bound session plus tool_input for PostToolUse task persistence hooks.
48
+ */
49
+ export function requirePersistenceContext(expectedTool, hookName) {
50
+ const bound = requireBoundSession(hookName);
51
+ if (!bound)
52
+ return null;
53
+ const { payload } = bound;
54
+ if (payload.hook_event_name !== "PostToolUse") {
55
+ return null;
56
+ }
57
+ if (payload.tool_name !== expectedTool) {
58
+ return null;
59
+ }
60
+ if (checkSkipPersistence(payload, hookName)) {
61
+ return null;
62
+ }
63
+ const toolInput = getToolInput(payload);
64
+ if (!toolInput) {
65
+ logWarn(hookName, `${expectedTool} missing tool_input payload`);
66
+ return null;
67
+ }
68
+ return { ...bound, toolInput };
69
+ }
70
+ /**
71
+ * Require a tool_input payload for tool-oriented hooks without needing a bound session.
72
+ */
73
+ export function requireToolInput(hookName) {
74
+ const payload = loadHookInput();
75
+ if (!payload)
76
+ return null;
77
+ const toolInput = getToolInput(payload);
78
+ if (!toolInput) {
79
+ logDebug(hookName, "No tool_input payload");
80
+ return null;
81
+ }
82
+ return { payload, toolInput };
83
+ }
84
+ /**
85
+ * Best-effort wrapper around maybeActivate. Hooks should never fail closed on activation.
86
+ */
87
+ export function safeMaybeActivate(contextId, permissionMode, projectRoot, hookName = "hook") {
88
+ try {
89
+ return maybeActivate(contextId, permissionMode, projectRoot, hookName);
90
+ }
91
+ catch (error) {
92
+ logWarn(hookName, `maybeActivate failed for ${contextId}: ${error}`);
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Load and parse JSON from stdin (or return prefetched input if set).
98
+ * Returns null if stdin is empty or invalid JSON.
99
+ * See SPEC.md §5.1
100
+ */
101
+ export function loadHookInput() {
102
+ if (_prefetchedInput !== null) {
103
+ const result = _prefetchedInput;
104
+ _prefetchedInput = null; // consume once
105
+ if (result && typeof result === "object") {
106
+ _lastHookEvent = readStringField(result, "hook_event_name");
107
+ _lastToolName = readStringField(result, "tool_name");
108
+ }
109
+ return result;
110
+ }
111
+ try {
112
+ // Read entire stdin using fd 0 (cross-platform, works on Windows)
113
+ const inputData = fs.readFileSync(0, "utf8").trim();
114
+ if (!inputData)
115
+ return null;
116
+ const result = JSON.parse(inputData);
117
+ const validated = HookInputSchema.safeParse(result);
118
+ if (!validated.success) {
119
+ logWarn("hook_utils", `Hook input schema validation failed: ${validated.error.message}`);
120
+ return null;
121
+ }
122
+ if (result && typeof result === "object") {
123
+ _lastHookEvent = readStringField(result, "hook_event_name");
124
+ _lastToolName = readStringField(result, "tool_name");
125
+ }
126
+ return result;
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ /**
133
+ * Validate hook event type and optional tool name.
134
+ * See SPEC.md §5.2
135
+ */
136
+ export function validateHookEvent(payload, expectedEvent, expectedTool) {
137
+ if (payload.hook_event_name !== expectedEvent)
138
+ return false;
139
+ if (expectedTool && payload.tool_name !== expectedTool)
140
+ return false;
141
+ return true;
142
+ }
143
+ /**
144
+ * Extract and validate tool_input from payload.
145
+ * See SPEC.md §5.3
146
+ */
147
+ export function getToolInput(payload) {
148
+ const toolInput = payload.tool_input;
149
+ return toolInput && typeof toolInput === "object" ? toolInput : null;
150
+ }
151
+ /**
152
+ * Check if persistence should be skipped based on metadata flags.
153
+ * See SPEC.md §5.4
154
+ */
155
+ export function checkSkipPersistence(payload, hookName = "hook") {
156
+ const toolInput = getToolInput(payload);
157
+ if (!toolInput)
158
+ return false;
159
+ const { metadata } = toolInput;
160
+ if (metadata &&
161
+ typeof metadata === "object" &&
162
+ Boolean(metadata.skip_persistence)) {
163
+ logDebug(hookName, "Skipping persistence (skip_persistence flag set)");
164
+ return true;
165
+ }
166
+ return false;
167
+ }
168
+ /**
169
+ * Emit hookSpecificOutput with additionalContext to stdout.
170
+ * hookEventName is required by Claude Code's Zod validator (discriminated union).
171
+ * Auto-detected from stdin payload (set by loadHookInput/runHook).
172
+ *
173
+ * SubagentStop and Stop events use top-level systemMessage field instead of hookSpecificOutput.
174
+ * See SPEC.md §5.5
175
+ */
176
+ export function emitContext(additionalContext) {
177
+ const eventName = _lastHookEvent ?? undefined;
178
+ const tool = _lastToolName;
179
+ // SubagentStop and Stop use top-level systemMessage field
180
+ if (eventName === "SubagentStop" || eventName === "Stop") {
181
+ const out = { systemMessage: additionalContext };
182
+ process.stdout.write(JSON.stringify(out) + "\n");
183
+ _logEmit("systemMessage", additionalContext.length, { event: eventName ?? "unknown", systemMessage: additionalContext });
184
+ return;
185
+ }
186
+ // All other events use hookSpecificOutput
187
+ const out = {
188
+ hookSpecificOutput: {
189
+ ...(eventName ? { hookEventName: eventName } : {}),
190
+ additionalContext,
191
+ },
192
+ };
193
+ const json = JSON.stringify(out);
194
+ const eventDesc = tool ? `${eventName}:${tool}` : eventName ?? "unknown";
195
+ _logEmit("context", additionalContext.length, { event: eventDesc, additionalContext });
196
+ process.stdout.write(json + "\n");
197
+ }
198
+ /**
199
+ * Emit hookSpecificOutput that denies the tool call with context and reason.
200
+ * hookEventName is required by Claude Code's Zod validator (discriminated union).
201
+ * Auto-detected from stdin payload (set by loadHookInput/runHook).
202
+ * See SPEC.md §5.6
203
+ */
204
+ export function emitContextAndBlock(additionalContext, reason) {
205
+ const eventName = _lastHookEvent ?? undefined;
206
+ if (eventName && eventName !== "PreToolUse") {
207
+ logWarn(_cachedHookName ?? "unknown", `emitContextAndBlock() called from ${eventName} — permissionDecision only works for PreToolUse. ` +
208
+ `Use emitBlock() or the event-specific function instead.`);
209
+ }
210
+ const tool = _lastToolName;
211
+ const out = {
212
+ hookSpecificOutput: {
213
+ ...(eventName ? { hookEventName: eventName } : {}),
214
+ additionalContext,
215
+ permissionDecision: "deny",
216
+ permissionDecisionReason: reason,
217
+ },
218
+ };
219
+ const json = JSON.stringify(out);
220
+ const eventDesc = tool ? `${eventName}:${tool}` : eventName ?? "unknown";
221
+ _logEmit("block", additionalContext.length, { event: eventDesc, additionalContext, blockReason: reason });
222
+ process.stdout.write(json + "\n");
223
+ }
224
+ /** Log hook output (context, systemMessage, or block) to hook-log.jsonl for visibility. */
225
+ function _logEmit(type, chars, payload) {
226
+ const hook = _cachedHookName ?? "unknown";
227
+ const event = payload.event ?? "unknown";
228
+ const mechanism = payload.mechanism ? ` via ${payload.mechanism}` : "";
229
+ const msg = type === "block"
230
+ ? `HOOK_OUTPUT [${type}] ${event} ${chars} chars${mechanism}, reason="${String(payload.blockReason ?? "").slice(0, 80)}"`
231
+ : `HOOK_OUTPUT [${type}] ${event} ${chars} chars`;
232
+ hookLog("info", hook, msg, { data: payload });
233
+ }
234
+ /**
235
+ * Block a user prompt submission with a reason.
236
+ * Only works for UserPromptSubmit hooks.
237
+ * Output: top-level { decision: "block", reason } + optional hookSpecificOutput.additionalContext
238
+ */
239
+ export function emitBlockPrompt(reason, context) {
240
+ const eventName = _lastHookEvent ?? undefined;
241
+ if (eventName && eventName !== "UserPromptSubmit") {
242
+ logWarn(_cachedHookName ?? "unknown", `emitBlockPrompt() called from ${eventName} — only works for UserPromptSubmit`);
243
+ }
244
+ const out = {
245
+ decision: "block",
246
+ reason,
247
+ ...(context ? {
248
+ hookSpecificOutput: {
249
+ ...(eventName ? { hookEventName: eventName } : {}),
250
+ additionalContext: context,
251
+ }
252
+ } : {}),
253
+ };
254
+ _logEmit("block", context?.length ?? 0, { event: eventName ?? "unknown", additionalContext: context, blockReason: reason });
255
+ process.stdout.write(JSON.stringify(out) + "\n");
256
+ }
257
+ /**
258
+ * Block via exit code 2 + stderr feedback.
259
+ * Works for PostToolUse, PostToolUseFailure.
260
+ * The reason becomes the stderr message (fed to Claude as system-reminder).
261
+ * If context is provided, it's prepended to the stderr message for richer feedback.
262
+ * NOTE: Exit 2 causes Claude Code to ignore all JSON stdout — only stderr matters.
263
+ */
264
+ export function emitBlockViaExit(reason, context) {
265
+ const stderrMessage = context ? `${context}\n\n${reason}` : reason;
266
+ _logEmit("block", stderrMessage.length, {
267
+ event: _lastHookEvent ?? "unknown",
268
+ blockReason: reason,
269
+ mechanism: "exit2",
270
+ });
271
+ process.stderr.write(stderrMessage + "\n");
272
+ throw new Error("SystemExit:2");
273
+ }
274
+ /**
275
+ * Block via top-level { decision: "block", reason }.
276
+ * Works for Stop and SubagentStop events.
277
+ * These events do NOT support additionalContext — only reason is available.
278
+ */
279
+ export function emitBlockTopLevel(reason) {
280
+ const eventName = _lastHookEvent ?? undefined;
281
+ if (eventName && eventName !== "Stop" && eventName !== "SubagentStop") {
282
+ logWarn(_cachedHookName ?? "unknown", `emitBlockTopLevel() called from ${eventName} — only works for Stop/SubagentStop`);
283
+ }
284
+ const out = { decision: "block", reason };
285
+ _logEmit("block", reason.length, {
286
+ event: eventName ?? "unknown",
287
+ blockReason: reason,
288
+ mechanism: "topLevelDecision",
289
+ });
290
+ process.stdout.write(JSON.stringify(out) + "\n");
291
+ }
292
+ /**
293
+ * Respond to a PermissionRequest with allow/deny.
294
+ * Only works for PermissionRequest hooks.
295
+ */
296
+ export function emitPermissionDecision(behavior, opts) {
297
+ const out = {
298
+ decision: {
299
+ behavior,
300
+ ...(opts?.message ? { message: opts.message } : {}),
301
+ ...(opts?.updatedInput ? { updatedInput: opts.updatedInput } : {}),
302
+ ...(opts?.updatedPermissions ? { updatedPermissions: opts.updatedPermissions } : {}),
303
+ },
304
+ };
305
+ _logEmit("block", 0, {
306
+ event: _lastHookEvent ?? "unknown",
307
+ blockReason: `permission:${behavior}`,
308
+ mechanism: "permissionRequest",
309
+ });
310
+ process.stdout.write(JSON.stringify(out) + "\n");
311
+ }
312
+ /**
313
+ * Unified block dispatcher — auto-detects the correct blocking mechanism
314
+ * based on the current hook event type.
315
+ *
316
+ * PreToolUse → permissionDecision: "deny" (via emitContextAndBlock)
317
+ * UserPromptSubmit → top-level decision: "block" (via emitBlockPrompt)
318
+ * PostToolUse/PostToolUseFailure → exit(2) + stderr (via emitBlockViaExit)
319
+ * Stop/SubagentStop → top-level { decision: "block", reason } (via emitBlockTopLevel)
320
+ * PermissionRequest → decision: { behavior: "deny" } (via emitPermissionDecision)
321
+ * SessionStart/Notification/SubagentStart/SessionEnd/etc. → warn and no-op
322
+ *
323
+ * This is the RECOMMENDED universal blocking API. Hook authors should use
324
+ * emitBlock() and let the library handle event-specific dispatch.
325
+ */
326
+ export function emitBlock(reason, context) {
327
+ const event = _lastHookEvent;
328
+ switch (event) {
329
+ case "PermissionRequest": {
330
+ emitPermissionDecision("deny", { message: reason });
331
+ break;
332
+ }
333
+ case "PostToolUse":
334
+ case "PostToolUseFailure": {
335
+ emitBlockViaExit(reason, context);
336
+ break;
337
+ }
338
+ case "PreToolUse": {
339
+ emitContextAndBlock(context ?? reason, reason);
340
+ break;
341
+ }
342
+ case "Stop":
343
+ case "SubagentStop": {
344
+ emitBlockTopLevel(reason);
345
+ break;
346
+ }
347
+ case "UserPromptSubmit": {
348
+ emitBlockPrompt(reason, context);
349
+ break;
350
+ }
351
+ default: {
352
+ logWarn(_cachedHookName ?? "unknown", `emitBlock() called from ${event ?? "unknown"} — no blocking mechanism exists for this event type, ignoring`);
353
+ break;
354
+ }
355
+ }
356
+ }
357
+ /**
358
+ * Auto-detect template origin from the hook script path.
359
+ */
360
+ function detectTemplate(scriptPath = "") {
361
+ const p = (scriptPath || (process.argv[1] ?? "")).replaceAll('\\', "/");
362
+ if (p.includes("/_core/hooks-ts/") ||
363
+ p.startsWith("_core/hooks-ts/") ||
364
+ p.includes("/core/hooks-ts/") ||
365
+ p.startsWith("core/hooks-ts/")) {
366
+ return "core";
367
+ }
368
+ const match = p.match(/_([a-z][a-z0-9-]*)\/hooks\//);
369
+ if (match?.[1])
370
+ return match[1]; // e.g., "cc-native"
371
+ return "unknown";
372
+ }
373
+ /**
374
+ * Parse context window from hook input.
375
+ * Returns [tokensUsed, maxTokens] or [null, null].
376
+ * See SPEC.md §5.9
377
+ */
378
+ export function parseContextWindow(hookInput) {
379
+ const contextWindow = hookInput.context_window;
380
+ if (!contextWindow)
381
+ return [null, null];
382
+ const currentUsage = contextWindow.current_usage;
383
+ if (!currentUsage)
384
+ return [null, null];
385
+ const cacheRead = currentUsage.cache_read_input_tokens ?? 0;
386
+ const inputTokens = currentUsage.input_tokens ?? 0;
387
+ const cacheCreation = currentUsage.cache_creation_input_tokens ?? 0;
388
+ const outputTokens = currentUsage.output_tokens ?? 0;
389
+ const contentTokens = cacheRead + inputTokens + cacheCreation + outputTokens;
390
+ const tokensUsed = contentTokens + CONTEXT_BASELINE_TOKENS;
391
+ const maxTokens = contextWindow.context_window_size ?? DEFAULT_CONTEXT_WINDOW_SIZE;
392
+ return [tokensUsed, maxTokens];
393
+ }
394
+ /**
395
+ * Get context percentage remaining with fallback.
396
+ * Returns [percentRemaining, tokensUsed, maxTokens] or [null, null, null].
397
+ * See SPEC.md §5.9
398
+ */
399
+ export function getContextPercentRemaining(hookInput) {
400
+ const [tokensUsed, maxTokens] = parseContextWindow(hookInput);
401
+ if (tokensUsed !== null && maxTokens !== null && maxTokens > 0) {
402
+ const remaining = maxTokens - tokensUsed;
403
+ const percentRemaining = Math.max(0, Math.min(100, Math.round((remaining / maxTokens) * 100)));
404
+ return [percentRemaining, tokensUsed, maxTokens];
405
+ }
406
+ // Source 2: context.json fallback (written by status_line.py)
407
+ try {
408
+ const sessionId = hookInput.session_id;
409
+ if (sessionId) {
410
+ const projectRoot = getProjectRoot(hookInput.cwd);
411
+ const context = getContextBySessionId(sessionId, projectRoot);
412
+ if (context?.last_session?.context_remaining_pct !== undefined) {
413
+ return [context.last_session.context_remaining_pct, null, null];
414
+ }
415
+ }
416
+ }
417
+ catch {
418
+ // Fallback failed — degrade gracefully
419
+ }
420
+ return [null, null, null];
421
+ }
422
+ /**
423
+ * Read stdin early and extract session_id + event metadata.
424
+ * Stashes parsed input for loadHookInput() to consume later.
425
+ */
426
+ function _earlyReadInput(prefetchedInput) {
427
+ if (prefetchedInput !== undefined) {
428
+ _prefetchedInput = prefetchedInput;
429
+ }
430
+ // If we already have prefetched input, extract metadata from it
431
+ if (_prefetchedInput && typeof _prefetchedInput === "object") {
432
+ _lastHookEvent = readStringField(_prefetchedInput, "hook_event_name");
433
+ _lastToolName = readStringField(_prefetchedInput, "tool_name");
434
+ const sessionId = readStringField(_prefetchedInput, "session_id");
435
+ if (sessionId) {
436
+ setSessionId(sessionId);
437
+ }
438
+ return;
439
+ }
440
+ // Read stdin now so HOOK_START can include sid
441
+ try {
442
+ const inputData = fs.readFileSync(0, "utf8").trim();
443
+ if (inputData) {
444
+ const parsed = JSON.parse(inputData);
445
+ const validated = HookInputSchema.safeParse(parsed);
446
+ if (!validated.success) {
447
+ logWarn("hook_utils", `Early input schema validation failed: ${validated.error.message}`);
448
+ return;
449
+ }
450
+ if (parsed && typeof parsed === "object") {
451
+ _prefetchedInput = parsed;
452
+ _lastHookEvent = readStringField(parsed, "hook_event_name");
453
+ _lastToolName = readStringField(parsed, "tool_name");
454
+ const sessionId = readStringField(parsed, "session_id");
455
+ if (sessionId) {
456
+ setSessionId(sessionId);
457
+ }
458
+ }
459
+ }
460
+ }
461
+ catch {
462
+ // Non-fatal — loadHookInput will return null
463
+ }
464
+ }
465
+ /**
466
+ * Standard hook entry point with lifecycle logging.
467
+ * See SPEC.md §5.7
468
+ */
469
+ export function runHook(mainFunc, hookName = "unknown", prefetchedInput) {
470
+ _earlyReadInput(prefetchedInput);
471
+ _cachedHookName = hookName;
472
+ // Ensure cwd is project root so relative paths in hooks resolve correctly,
473
+ // even when cwd has drifted via `cd` in a Bash tool call.
474
+ try {
475
+ const cwd = _prefetchedInput ? readStringField(_prefetchedInput, "cwd") ?? undefined : undefined;
476
+ const projectRoot = getProjectRoot(cwd);
477
+ if (process.cwd() !== projectRoot)
478
+ process.chdir(projectRoot);
479
+ }
480
+ catch { /* non-fatal — proceed with current cwd */ }
481
+ const startTime = performance.now();
482
+ const template = detectTemplate();
483
+ const event = _lastHookEvent ?? "unknown";
484
+ const tool = _lastToolName;
485
+ const startData = {
486
+ lifecycle: "start",
487
+ template,
488
+ event,
489
+ };
490
+ if (tool)
491
+ startData.tool = tool;
492
+ hookLog("info", hookName, "HOOK_START", { data: startData });
493
+ let exitCode = 0;
494
+ let status = "success";
495
+ let errorInfo = null;
496
+ try {
497
+ const result = mainFunc();
498
+ exitCode = typeof result === "number" ? result : 0;
499
+ status = exitCode !== 0 ? "blocked" : "success";
500
+ }
501
+ catch (error) {
502
+ if (error instanceof Error && error.message.startsWith("SystemExit:")) {
503
+ const code = parseInt(error.message.slice(11), 10);
504
+ exitCode = isNaN(code) ? (error.message.slice(11) ? 1 : 0) : code;
505
+ status = exitCode !== 0 ? "blocked" : "success";
506
+ }
507
+ else {
508
+ exitCode = 0; // Non-blocking
509
+ status = "error";
510
+ const stack = error instanceof Error ? error.stack ?? "" : "";
511
+ errorInfo = [error instanceof Error ? error : new Error(String(error)), stack];
512
+ }
513
+ }
514
+ _emitHookEnd(hookName, startTime, exitCode, status, errorInfo, startData, event, tool, template);
515
+ process.exit(exitCode);
516
+ }
517
+ /**
518
+ * Async variant of runHook for hooks that need await (e.g., AI inference).
519
+ * Provides identical structured JSONL lifecycle logging as runHook.
520
+ * See SPEC.md §5.7
521
+ */
522
+ export function runHookAsync(mainFunc, hookName = "unknown", prefetchedInput) {
523
+ _earlyReadInput(prefetchedInput);
524
+ _cachedHookName = hookName;
525
+ // Ensure cwd is project root so relative paths in hooks resolve correctly,
526
+ // even when cwd has drifted via `cd` in a Bash tool call.
527
+ try {
528
+ const cwd = _prefetchedInput ? readStringField(_prefetchedInput, "cwd") ?? undefined : undefined;
529
+ const projectRoot = getProjectRoot(cwd);
530
+ if (process.cwd() !== projectRoot)
531
+ process.chdir(projectRoot);
532
+ }
533
+ catch { /* non-fatal — proceed with current cwd */ }
534
+ const startTime = performance.now();
535
+ const template = detectTemplate();
536
+ const event = _lastHookEvent ?? "unknown";
537
+ const tool = _lastToolName;
538
+ const startData = {
539
+ lifecycle: "start",
540
+ template,
541
+ event,
542
+ };
543
+ if (tool)
544
+ startData.tool = tool;
545
+ hookLog("info", hookName, "HOOK_START", { data: startData });
546
+ mainFunc()
547
+ .then((result) => {
548
+ const exitCode = typeof result === "number" ? result : 0;
549
+ _emitHookEnd(hookName, startTime, exitCode, exitCode !== 0 ? "blocked" : "success", null, startData, event, tool, template);
550
+ _drainAndExit(exitCode);
551
+ })
552
+ .catch((error) => {
553
+ let exitCode = 0;
554
+ let status = "error";
555
+ let errorInfo = null;
556
+ if (error instanceof Error && error.message.startsWith("SystemExit:")) {
557
+ const code = parseInt(error.message.slice(11), 10);
558
+ exitCode = isNaN(code) ? (error.message.slice(11) ? 1 : 0) : code;
559
+ status = exitCode !== 0 ? "blocked" : "success";
560
+ }
561
+ else {
562
+ exitCode = 0; // Non-blocking (fail open)
563
+ const stack = error instanceof Error ? error.stack ?? "" : "";
564
+ errorInfo = [error instanceof Error ? error : new Error(String(error)), stack];
565
+ }
566
+ _emitHookEnd(hookName, startTime, exitCode, status, errorInfo, startData, event, tool, template);
567
+ _drainAndExit(exitCode);
568
+ });
569
+ }
570
+ /** Shared HOOK_END logic for runHook and runHookAsync */
571
+ function _emitHookEnd(hookName, startTime, exitCode, status, errorInfo, startData, event, tool, template) {
572
+ // Retroactive HOOK_START to per-context log (context_path resolved after main runs)
573
+ const resolvedAfter = _getContextPath();
574
+ if (resolvedAfter && fs.existsSync(resolvedAfter)) {
575
+ hookLog("info", hookName, "HOOK_START", { data: startData });
576
+ }
577
+ const durationMs = Math.round((performance.now() - startTime) * 10) / 10;
578
+ const endEvent = _lastHookEvent ?? event;
579
+ const endTool = _lastToolName ?? tool;
580
+ const endData = {
581
+ lifecycle: "end",
582
+ status,
583
+ duration_ms: durationMs,
584
+ exit_code: exitCode,
585
+ template,
586
+ event: endEvent,
587
+ };
588
+ if (endTool)
589
+ endData.tool = endTool;
590
+ if (errorInfo) {
591
+ const [err, tb] = errorInfo;
592
+ endData.error_type = err.constructor.name;
593
+ hookLog("error", hookName, `[${endEvent}] ${err.constructor.name}: ${String(err).replaceAll(/[\n\r]/g, " ").slice(0, 200)}`, { traceback_str: tb });
594
+ hookLog("error", hookName, `HOOK_END: ${err}`, { data: endData, traceback_str: tb });
595
+ }
596
+ else if (status === "blocked") {
597
+ hookLog("warn", hookName, "HOOK_END", { data: endData });
598
+ }
599
+ else {
600
+ hookLog("info", hookName, "HOOK_END", { data: endData });
601
+ }
602
+ }
603
+ /**
604
+ * Drain stdout before exiting to ensure pipe consumers receive all data.
605
+ * On Windows, stdout to a pipe is fully buffered — process.exit() can
606
+ * discard unflushed data. This waits for the write buffer to drain.
607
+ */
608
+ function _drainAndExit(code) {
609
+ // If stdout is already finished or not writable, exit immediately
610
+ if (!process.stdout.writable || process.stdout.writableFinished) {
611
+ process.exit(code);
612
+ }
613
+ // Attempt to end stdout and wait for drain
614
+ const timeout = setTimeout(() => process.exit(code), 1000); // safety fallback
615
+ process.stdout.end(() => {
616
+ clearTimeout(timeout);
617
+ process.exit(code);
618
+ });
619
+ }
620
+ export { hookLog, logBlocking, logDebug, logDiagnostic, logError, logHookError, logInfo, logWarn, setContextPath, setSessionId } from "../runtime/logger.js";
@@ -0,0 +1,7 @@
1
+ import type { ContextState } from "../types.js";
2
+ export interface PromptBindingResult {
3
+ outputs: string[];
4
+ blockedReason?: string;
5
+ }
6
+ export declare function shouldClearHandoff(state: ContextState): boolean;
7
+ export declare function executePromptBinding(prompt: string | undefined, sessionId: string, permissionMode: string, projectRoot: string): Promise<PromptBindingResult>;
@@ -0,0 +1,50 @@
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 { bindSession, getContextBySessionId, saveState, } from "../context/context-store.js";
5
+ export function shouldClearHandoff(state) {
6
+ return Boolean(state.handoff_path);
7
+ }
8
+ export async function executePromptBinding(prompt, sessionId, permissionMode, projectRoot) {
9
+ const outputs = [];
10
+ const existingCtx = getContextBySessionId(sessionId, projectRoot);
11
+ if (existingCtx) {
12
+ safeMaybeActivate(existingCtx.id, permissionMode, projectRoot, "user_prompt_submit");
13
+ return { outputs };
14
+ }
15
+ if (!prompt)
16
+ return { outputs };
17
+ try {
18
+ const [contextId, method, outputText] = await determineContext(prompt, sessionId, projectRoot);
19
+ if (contextId) {
20
+ bindSession(contextId, sessionId, projectRoot);
21
+ safeMaybeActivate(contextId, permissionMode, projectRoot, "user_prompt_submit");
22
+ const state = getContextBySessionId(sessionId, projectRoot);
23
+ if (state && shouldClearHandoff(state)) {
24
+ state.handoff_path = null;
25
+ saveState(state.id, state, projectRoot);
26
+ }
27
+ logInfo("user_prompt_submit", `Context ${contextId} via ${method}`);
28
+ }
29
+ if (outputText)
30
+ outputs.push(outputText);
31
+ try {
32
+ const boundState = getContextBySessionId(sessionId, projectRoot);
33
+ if (boundState) {
34
+ const inventory = buildContextInventory(boundState, projectRoot);
35
+ if (inventory)
36
+ outputs.push(inventory);
37
+ }
38
+ }
39
+ catch (error) {
40
+ logWarn("user_prompt_submit", `Inventory failed (non-critical): ${error}`);
41
+ }
42
+ }
43
+ catch (error) {
44
+ if (error instanceof BlockRequest) {
45
+ return { outputs, blockedReason: error.message };
46
+ }
47
+ throw error;
48
+ }
49
+ return { outputs };
50
+ }
@@ -0,0 +1,5 @@
1
+ import type { ContextState, GitState, LastSession } from "../types.js";
2
+ export declare function computePlanFallback(state: ContextState, planContent: string): Partial<ContextState>;
3
+ export declare function shouldStage(state: ContextState, permissionMode: string): boolean;
4
+ export declare function buildSessionMetadata(sessionId: string, source: string, transcriptPath: string | undefined, gitState?: GitState): LastSession;
5
+ export declare function generateArchiveFilename(sessionId: string, date: Date, existingNames: Iterable<string>): string;