aiwcli 0.15.4 → 0.15.7

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 (299) hide show
  1. package/README.md +6 -3
  2. package/dist/capabilities/branch/adapters.d.ts +2 -0
  3. package/dist/capabilities/branch/adapters.js +21 -0
  4. package/dist/capabilities/branch/contracts.d.ts +57 -0
  5. package/dist/capabilities/branch/contracts.js +1 -0
  6. package/dist/capabilities/branch/control-plane.d.ts +2 -0
  7. package/dist/capabilities/branch/control-plane.js +343 -0
  8. package/dist/capabilities/branch/runtime-core.d.ts +5 -0
  9. package/dist/capabilities/branch/runtime-core.js +36 -0
  10. package/dist/capabilities/installation/control-plane/clean-command.d.ts +41 -0
  11. package/dist/capabilities/installation/control-plane/clean-command.js +196 -0
  12. package/dist/capabilities/installation/control-plane/clear-command.d.ts +160 -0
  13. package/dist/capabilities/installation/control-plane/clear-command.js +1220 -0
  14. package/dist/capabilities/installation/control-plane/init-command.d.ts +81 -0
  15. package/dist/capabilities/installation/control-plane/init-command.js +449 -0
  16. package/dist/capabilities/launch/contracts.d.ts +51 -0
  17. package/dist/capabilities/launch/contracts.js +1 -0
  18. package/dist/capabilities/launch/control-plane/execute-launch.d.ts +2 -0
  19. package/dist/capabilities/launch/control-plane/execute-launch.js +222 -0
  20. package/dist/capabilities/launch/runtime-core/launch-options.d.ts +14 -0
  21. package/dist/capabilities/launch/runtime-core/launch-options.js +69 -0
  22. package/dist/cli/base-command.d.ts +18 -0
  23. package/dist/cli/base-command.js +55 -0
  24. package/dist/commands/branch.d.ts +0 -20
  25. package/dist/commands/branch.js +24 -416
  26. package/dist/commands/clean.d.ts +1 -41
  27. package/dist/commands/clean.js +1 -196
  28. package/dist/commands/clear.d.ts +1 -161
  29. package/dist/commands/clear.js +1 -1121
  30. package/dist/commands/init/index.d.ts +1 -98
  31. package/dist/commands/init/index.js +4 -478
  32. package/dist/commands/launch.d.ts +36 -11
  33. package/dist/commands/launch.js +135 -159
  34. package/dist/lib/base-command.d.ts +1 -114
  35. package/dist/lib/base-command.js +1 -153
  36. package/dist/lib/claude-settings-types.d.ts +31 -19
  37. package/dist/lib/context/context-formatter.d.ts +74 -0
  38. package/dist/lib/context/context-formatter.js +493 -0
  39. package/dist/lib/context/context-selector.d.ts +42 -0
  40. package/dist/lib/context/context-selector.js +451 -0
  41. package/dist/lib/context/context-store.d.ts +100 -0
  42. package/dist/lib/context/context-store.js +618 -0
  43. package/dist/lib/context/plan-manager.d.ts +54 -0
  44. package/dist/lib/context/plan-manager.js +282 -0
  45. package/dist/lib/context/task-tracker.d.ts +44 -0
  46. package/dist/lib/context/task-tracker.js +146 -0
  47. package/dist/lib/core-ide-base.d.ts +4 -0
  48. package/dist/lib/core-ide-base.js +77 -0
  49. package/dist/lib/core-installer.d.ts +5 -0
  50. package/dist/lib/core-installer.js +54 -0
  51. package/dist/lib/git-exclude-manager.d.ts +2 -2
  52. package/dist/lib/git-exclude-manager.js +3 -3
  53. package/dist/lib/hooks/hook-utils.d.ts +143 -0
  54. package/dist/lib/hooks/hook-utils.js +609 -0
  55. package/dist/lib/hooks/session-end-logic.d.ts +5 -0
  56. package/dist/lib/hooks/session-end-logic.js +63 -0
  57. package/dist/lib/hooks-merger.js +25 -19
  58. package/dist/lib/ide-path-resolver.d.ts +19 -7
  59. package/dist/lib/ide-path-resolver.js +25 -9
  60. package/dist/lib/install-state.d.ts +34 -0
  61. package/dist/lib/install-state.js +161 -0
  62. package/dist/lib/launch-options.d.ts +1 -0
  63. package/dist/lib/launch-options.js +1 -0
  64. package/dist/lib/lsp-patch.d.ts +12 -0
  65. package/dist/lib/lsp-patch.js +156 -0
  66. package/dist/lib/multiplexer.d.ts +57 -0
  67. package/dist/lib/multiplexer.js +19 -0
  68. package/dist/lib/multiplexers/psmux.d.ts +75 -0
  69. package/dist/lib/multiplexers/psmux.js +384 -0
  70. package/dist/lib/multiplexers/tmux.d.ts +44 -0
  71. package/dist/lib/multiplexers/tmux.js +262 -0
  72. package/dist/lib/mux-utils.d.ts +5 -0
  73. package/dist/lib/mux-utils.js +42 -0
  74. package/dist/lib/paths.d.ts +2 -2
  75. package/dist/lib/paths.js +2 -2
  76. package/dist/lib/platform-commands.d.ts +27 -0
  77. package/dist/lib/platform-commands.js +49 -0
  78. package/dist/lib/runtime/aiw-cli.d.ts +37 -0
  79. package/dist/lib/runtime/aiw-cli.js +74 -0
  80. package/dist/lib/runtime/atomic-write.d.ts +19 -0
  81. package/dist/lib/runtime/atomic-write.js +121 -0
  82. package/dist/lib/runtime/cli-args.d.ts +55 -0
  83. package/dist/lib/runtime/cli-args.js +185 -0
  84. package/dist/lib/runtime/constants.d.ts +56 -0
  85. package/dist/lib/runtime/constants.js +230 -0
  86. package/dist/lib/runtime/executable-policy.d.ts +16 -0
  87. package/dist/lib/runtime/executable-policy.js +57 -0
  88. package/dist/lib/runtime/git-state.d.ts +9 -0
  89. package/dist/lib/runtime/git-state.js +59 -0
  90. package/dist/lib/runtime/inference.d.ts +37 -0
  91. package/dist/lib/runtime/inference.js +262 -0
  92. package/dist/lib/runtime/lint-dispatch.d.ts +40 -0
  93. package/dist/lib/runtime/lint-dispatch.js +285 -0
  94. package/dist/lib/runtime/logger.d.ts +66 -0
  95. package/dist/lib/runtime/logger.js +201 -0
  96. package/dist/lib/runtime/models.d.ts +14 -0
  97. package/dist/lib/runtime/models.js +14 -0
  98. package/dist/lib/runtime/platform-adapter.d.ts +7 -0
  99. package/dist/lib/runtime/platform-adapter.js +21 -0
  100. package/dist/lib/runtime/preflight.d.ts +24 -0
  101. package/dist/lib/runtime/preflight.js +65 -0
  102. package/dist/lib/runtime/sentinel-ipc.d.ts +14 -0
  103. package/dist/lib/runtime/sentinel-ipc.js +67 -0
  104. package/dist/lib/runtime/state-io.d.ts +30 -0
  105. package/dist/lib/runtime/state-io.js +174 -0
  106. package/dist/lib/runtime/stop-words.d.ts +20 -0
  107. package/dist/lib/runtime/stop-words.js +150 -0
  108. package/dist/lib/runtime/subprocess-utils.d.ts +29 -0
  109. package/dist/lib/runtime/subprocess-utils.js +96 -0
  110. package/dist/lib/runtime/tmux-preflight.d.ts +13 -0
  111. package/dist/lib/runtime/tmux-preflight.js +78 -0
  112. package/dist/lib/runtime/utils.d.ts +54 -0
  113. package/dist/lib/runtime/utils.js +162 -0
  114. package/dist/lib/sentinel-wrapper.d.ts +9 -0
  115. package/dist/lib/sentinel-wrapper.js +20 -0
  116. package/dist/lib/shell-quoting.d.ts +5 -0
  117. package/dist/lib/shell-quoting.js +17 -0
  118. package/dist/lib/spawn-errors.d.ts +6 -0
  119. package/dist/lib/spawn-errors.js +15 -0
  120. package/dist/lib/spawn.js +5 -11
  121. package/dist/lib/template-installer.d.ts +4 -5
  122. package/dist/lib/template-installer.js +36 -34
  123. package/dist/lib/template-resolver.d.ts +6 -7
  124. package/dist/lib/template-resolver.js +26 -21
  125. package/dist/lib/template-settings-reconstructor.d.ts +7 -2
  126. package/dist/lib/template-settings-reconstructor.js +76 -45
  127. package/dist/lib/terminal-strategy.d.ts +11 -0
  128. package/dist/lib/terminal-strategy.js +49 -0
  129. package/dist/lib/terminal.d.ts +28 -0
  130. package/dist/lib/terminal.js +162 -112
  131. package/dist/lib/tmux-pane-placement.d.ts +17 -0
  132. package/dist/lib/tmux-pane-placement.js +58 -0
  133. package/dist/lib/tmux-primitives.d.ts +5 -0
  134. package/dist/lib/tmux-primitives.js +15 -0
  135. package/dist/lib/tmux-session.d.ts +32 -0
  136. package/dist/lib/tmux-session.js +86 -0
  137. package/dist/lib/tty-detection.js +1 -1
  138. package/dist/lib/types.d.ts +168 -0
  139. package/dist/lib/types.js +6 -0
  140. package/dist/lib/version.d.ts +1 -1
  141. package/dist/lib/version.js +1 -1
  142. package/dist/platform/launch.d.ts +10 -0
  143. package/dist/platform/launch.js +10 -0
  144. package/dist/templates/CLAUDE.md +31 -40
  145. package/dist/templates/cc-native/.claude/settings.json +27 -27
  146. package/dist/templates/cc-native/CC-NATIVE-README.md +1 -1
  147. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +10 -9
  148. package/dist/templates/cc-native/_cc-native/CLAUDE.md +18 -18
  149. package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +3 -3
  150. package/dist/templates/cc-native/_cc-native/artifacts/lib/format.ts +14 -14
  151. package/dist/templates/cc-native/_cc-native/artifacts/lib/tracker.ts +1 -1
  152. package/dist/templates/cc-native/_cc-native/artifacts/lib/write.ts +3 -3
  153. package/dist/templates/cc-native/_cc-native/cc-native.config.json +3 -3
  154. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +16 -15
  155. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +3 -3
  156. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_subagent.ts +2 -2
  157. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +2 -2
  158. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +3 -3
  159. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +2 -2
  160. package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +3 -3
  161. package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +8 -8
  162. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +1 -1
  163. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +4 -4
  164. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +1 -1
  165. package/dist/templates/cc-native/_cc-native/lib-ts/config.ts +1 -1
  166. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +1 -1
  167. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +1 -1
  168. package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +2 -2
  169. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +1 -1
  170. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +2 -2
  171. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +1 -1
  172. package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +8 -8
  173. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +3 -3
  174. package/dist/templates/cc-native/_cc-native/lib-ts/tsconfig.json +2 -2
  175. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +3 -3
  176. package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +3 -1
  177. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/agent-selection.test.ts +345 -0
  178. package/dist/templates/cc-native/_cc-native/plan-review/lib/__tests__/preflight.test.ts +344 -0
  179. package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +37 -15
  180. package/dist/templates/cc-native/_cc-native/plan-review/lib/corroboration.ts +16 -69
  181. package/dist/templates/cc-native/_cc-native/plan-review/lib/orchestrator.ts +1 -1
  182. package/dist/templates/cc-native/_cc-native/plan-review/lib/output-builder.ts +1 -1
  183. package/dist/templates/cc-native/_cc-native/plan-review/lib/plan-questions.ts +2 -2
  184. package/dist/templates/cc-native/_cc-native/plan-review/lib/preflight.ts +56 -26
  185. package/dist/templates/cc-native/_cc-native/plan-review/lib/review-pipeline.ts +7 -7
  186. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/agent.ts +4 -4
  187. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +3 -3
  188. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/index.ts +1 -1
  189. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/claude-agent.ts +2 -2
  190. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/codex-agent.ts +4 -4
  191. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/gemini-agent.ts +1 -1
  192. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/providers/orchestrator-claude-agent.ts +5 -6
  193. package/dist/templates/core/.codex/workflows/codex.md +17 -0
  194. package/dist/templates/core/.codex/workflows/handoff.md +5 -0
  195. package/dist/templates/core/.codex/workflows/meta-plan.md +7 -0
  196. package/dist/templates/core/.cognition/AGENTS.md +5 -0
  197. package/dist/templates/core/.cognition/config.json +12 -0
  198. package/dist/templates/{_shared → core}/.windsurf/workflows/handoff.md +1 -1
  199. package/dist/templates/{_shared → core}/.windsurf/workflows/meta-plan.md +1 -1
  200. package/dist/templates/core/hooks-ts/_utils/git-state.ts +2 -0
  201. package/dist/templates/{_shared → core}/hooks-ts/archive_plan.ts +14 -23
  202. package/dist/templates/core/hooks-ts/codex_explorer.ts +160 -0
  203. package/dist/templates/{_shared → core}/hooks-ts/context_monitor.ts +23 -55
  204. package/dist/templates/{_shared → core}/hooks-ts/file-suggestion.ts +4 -3
  205. package/dist/templates/{_shared → core}/hooks-ts/lint_after_edit.ts +7 -9
  206. package/dist/templates/{_shared → core}/hooks-ts/pre_compact.ts +5 -5
  207. package/dist/templates/{_shared → core}/hooks-ts/session_end.ts +38 -78
  208. package/dist/templates/{_shared → core}/hooks-ts/session_start.ts +5 -5
  209. package/dist/templates/core/hooks-ts/task_create_capture.ts +32 -0
  210. package/dist/templates/{_shared → core}/hooks-ts/task_update_capture.ts +9 -24
  211. package/dist/templates/core/hooks-ts/user_prompt_submit.ts +46 -0
  212. package/dist/templates/{_shared → core}/lib-ts/CLAUDE.md +27 -16
  213. package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/headless.ts +3 -2
  214. package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/tmux.ts +44 -15
  215. package/dist/templates/{_shared → core}/lib-ts/agent-exec/base-agent.ts +6 -4
  216. package/dist/templates/{_shared → core}/lib-ts/agent-exec/execution-backend.ts +1 -1
  217. package/dist/templates/{_shared → core}/lib-ts/agent-exec/index.ts +2 -2
  218. package/dist/templates/{_shared → core}/lib-ts/agent-exec/structured-output.ts +4 -5
  219. package/dist/templates/{_shared → core}/lib-ts/context/CLAUDE.md +9 -6
  220. package/dist/templates/{_shared → core}/lib-ts/context/context-formatter.ts +16 -21
  221. package/dist/templates/{_shared → core}/lib-ts/context/context-selector.ts +8 -6
  222. package/dist/templates/{_shared → core}/lib-ts/context/context-store.ts +32 -20
  223. package/dist/templates/{_shared → core}/lib-ts/context/plan-manager.ts +19 -15
  224. package/dist/templates/{_shared → core}/lib-ts/context/task-tracker.ts +3 -3
  225. package/dist/templates/core/lib-ts/hooks/context-monitor-logic.ts +32 -0
  226. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/hooks}/hook-utils.ts +168 -41
  227. package/dist/templates/core/lib-ts/hooks/prompt-binding-logic.ts +80 -0
  228. package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +93 -0
  229. package/dist/templates/core/lib-ts/package.json +19 -0
  230. package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +295 -0
  231. package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +106 -0
  232. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/atomic-write.ts +12 -7
  233. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/cli-args.ts +8 -6
  234. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/constants.ts +326 -324
  235. package/dist/templates/core/lib-ts/runtime/executable-policy.ts +89 -0
  236. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/git-state.ts +6 -4
  237. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/inference.ts +59 -10
  238. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/lint-dispatch.ts +25 -23
  239. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/logger.ts +32 -29
  240. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/models.ts +2 -2
  241. package/dist/templates/core/lib-ts/runtime/platform-adapter.ts +33 -0
  242. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/preflight.ts +4 -3
  243. package/dist/templates/core/lib-ts/runtime/sentinel-ipc.ts +91 -0
  244. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/state-io.ts +11 -7
  245. package/dist/templates/core/lib-ts/runtime/stop-words.ts +185 -0
  246. package/dist/templates/core/lib-ts/runtime/subprocess-utils.ts +147 -0
  247. package/dist/templates/core/lib-ts/runtime/tmux-preflight.ts +93 -0
  248. package/dist/templates/{_shared/lib-ts/base → core/lib-ts/runtime}/utils.ts +4 -3
  249. package/dist/templates/{_shared → core}/lib-ts/templates/formatters.ts +7 -5
  250. package/dist/templates/{_shared → core}/lib-ts/templates/plan-context.ts +2 -1
  251. package/dist/templates/{_shared → core}/lib-ts/tsconfig.json +3 -1
  252. package/dist/templates/{_shared → core}/lib-ts/types.ts +78 -77
  253. package/dist/templates/core/scripts/resolve-run.ts +61 -0
  254. package/dist/templates/{_shared → core}/scripts/resolve_context.ts +3 -3
  255. package/dist/templates/{_shared → core}/scripts/status_line.ts +25 -20
  256. package/dist/templates/core/skills/codex/CLAUDE.md +78 -0
  257. package/dist/templates/{_shared → core}/skills/codex/SKILL.md +21 -18
  258. package/dist/templates/{_shared → core}/skills/codex/lib/codex-watcher.ts +76 -103
  259. package/dist/templates/{_shared → core}/skills/codex/scripts/launch-codex.ts +119 -133
  260. package/dist/templates/{_shared → core}/skills/codex/scripts/watch-codex.ts +6 -4
  261. package/dist/templates/core/skills/devin/CLAUDE.md +65 -0
  262. package/dist/templates/core/skills/devin/SKILL.md +73 -0
  263. package/dist/templates/core/skills/devin/lib/devin-watcher.ts +280 -0
  264. package/dist/templates/core/skills/devin/scripts/launch-devin.ts +257 -0
  265. package/dist/templates/{_shared → core}/skills/handoff-system/CLAUDE.md +436 -433
  266. package/dist/templates/{_shared → core}/skills/handoff-system/lib/document-generator.ts +9 -7
  267. package/dist/templates/{_shared → core}/skills/handoff-system/lib/handoff-reader.ts +6 -4
  268. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/resume_handoff.ts +10 -8
  269. package/dist/templates/{_shared → core}/skills/handoff-system/scripts/save_handoff.ts +12 -10
  270. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff-resume.md +2 -2
  271. package/dist/templates/{_shared → core}/skills/handoff-system/workflows/handoff.md +6 -5
  272. package/dist/templates/{_shared → core}/skills/meta-plan/CLAUDE.md +2 -1
  273. package/dist/templates/{_shared → core}/skills/meta-plan/workflows/meta-plan.md +8 -7
  274. package/oclif.manifest.json +89 -13
  275. package/package.json +13 -12
  276. package/dist/templates/_shared/.claude/settings.json +0 -120
  277. package/dist/templates/_shared/.claude/skills/codex/SKILL.md +0 -35
  278. package/dist/templates/_shared/.claude/skills/handoff/SKILL.md +0 -13
  279. package/dist/templates/_shared/.claude/skills/handoff-resume/SKILL.md +0 -13
  280. package/dist/templates/_shared/.claude/skills/meta-plan/SKILL.md +0 -43
  281. package/dist/templates/_shared/.codex/workflows/codex.md +0 -11
  282. package/dist/templates/_shared/.codex/workflows/handoff.md +0 -226
  283. package/dist/templates/_shared/.codex/workflows/meta-plan.md +0 -347
  284. package/dist/templates/_shared/hooks-ts/_utils/git-state.ts +0 -2
  285. package/dist/templates/_shared/hooks-ts/task_create_capture.ts +0 -48
  286. package/dist/templates/_shared/hooks-ts/user_prompt_submit.ts +0 -93
  287. package/dist/templates/_shared/lib-ts/base/launchers/tmux-launcher.ts +0 -173
  288. package/dist/templates/_shared/lib-ts/base/launchers/window-launcher.ts +0 -93
  289. package/dist/templates/_shared/lib-ts/base/launchers/wt-launcher.ts +0 -64
  290. package/dist/templates/_shared/lib-ts/base/pane-launcher.ts +0 -55
  291. package/dist/templates/_shared/lib-ts/base/sentinel-ipc.ts +0 -87
  292. package/dist/templates/_shared/lib-ts/base/stop-words.ts +0 -184
  293. package/dist/templates/_shared/lib-ts/base/subprocess-utils.ts +0 -249
  294. package/dist/templates/_shared/lib-ts/base/tmux-driver.ts +0 -341
  295. package/dist/templates/_shared/lib-ts/base/tmux-pane-placement.ts +0 -78
  296. package/dist/templates/_shared/lib-ts/package.json +0 -20
  297. package/dist/templates/_shared/scripts/resolve-run.ts +0 -62
  298. package/dist/templates/_shared/skills/codex/CLAUDE.md +0 -70
  299. /package/dist/templates/{_shared → core}/lib-ts/agent-exec/backends/index.ts +0 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Stop words for context ID generation.
3
+ *
4
+ * Generated from analysis of 1,424 prompts, context summaries, and plan files.
5
+ * Words that appear frequently but don't help identify the specific task.
6
+ *
7
+ * ACTION VERBS ARE INTENTIONALLY EXCLUDED:
8
+ * add, fix, update, create, implement, refactor, migrate, debug, remove, change,
9
+ * move, rename, delete, build, test, deploy, verify, analyze, modify, write, run,
10
+ * check, replace, save, sync, load, extract, install, clean, merge, etc.
11
+ *
12
+ * See SPEC.md §14.1
13
+ */
14
+ export const STOP_WORDS = new Set([
15
+ // ARTICLES
16
+ "a", "about", "above",
17
+ "absolutely", "accordingly", "across", "active", "actually", "after", "afterwards", "against", "ago", "ah",
18
+ "aiw", "all", "allow", "almost", "along", "already", "alright", "also",
19
+ "alternatively", "although", "always", // AUXILIARY/MODAL VERBS
20
+ "am", "among", "an", // CONJUNCTIONS
21
+ "and", "another",
22
+ "anybody", "anyone", "anything", "anyway", "anyways", "apparently", "appear", "are",
23
+ "aren", "arent", "args", "around", "as", "ask", "assert",
24
+ "async", "at", "b", // SINGLE LETTERS
25
+ "based",
26
+ "basic", "basically", "bat", "be", "because", "become", "been",
27
+ "before", "begin", "behind", "being", "below",
28
+ "below", "beside", "besides", "between", "beyond", "block", "both",
29
+ "but", "by", "c", "can", "cant", "case", "cases",
30
+ "cause", "cc", "certainly", "chunk", "clarification",
31
+ "class", "clearly", "come", "complete",
32
+ "completely", "consequently", "consider", "const",
33
+ "contain", "contains", "continue", "conversely", "correct", "correctly",
34
+ "could", "couldn", "couldnt", "critical", "current", "currently",
35
+ "d", "def",
36
+ "definitely", "dict", "did", "didn", "didnt", "different", "directory", "do",
37
+ "does", "doesn", "doesn", "doesnt",
38
+ "doing", "don", "done", "dont", "down",
39
+ "during", "e", "each", "eh", "eight", "either", "elif", "else", "empty",
40
+ "end", "enough", "entirely", "eprint", "er", "essentially", // SHORT NOISE
41
+ "etc",
42
+ "eventually", "every", "everybody", "everyone", "everything", "exactly",
43
+ "example", "examples", "except", "exe", "existing",
44
+ "expect", "expected", "f", "false", "feature",
45
+ "features", "feel", "few", "finally", "find", "first", "five",
46
+ "folder", "follow", "following", "footer", "for", "format", "four",
47
+ "from", "full", "furthermore", "g", "general",
48
+ "get", "getting", "give", // COMMON NON-ACTION VERBS
49
+ "go",
50
+ "going", "gonna", "gotta", "group",
51
+ "h", "had", "hadn", "hadnt", "has", "hasn", "hasnt",
52
+ "have", "haven", "havent", "having", "he", "header", "hello",
53
+ "help", "hence", "her", "her", "here", // ADVERBS OF PLACE/TIME
54
+ "heres", "hers", "herself", "hes",
55
+ "hey", "hi", "high", // GENERIC ADJECTIVES
56
+ "him", "himself", "his", "hm", "hmm",
57
+ "how", // LINKING/TRANSITION WORDS
58
+ "however",
59
+ "huh", "i", // PRONOUNS - Personal
60
+ "id", "if", "ill", "im", // CONTRACTED FORMS
61
+ "immediately",
62
+ "import", "important", "in", "include", "index", "information", // GENERIC TECHNICAL NOUNS
63
+ "inside",
64
+ "instead", "into", "is", "isn", "isnt",
65
+ "issue", "it", "item", "items", "its", "itself",
66
+ "ive", "j", "js", "json", // FILLER/HEDGE WORDS
67
+ "just",
68
+ "k", "keep", "kind", "kinda", "know", "l", "lambda", "last", "later",
69
+ "least", "len", "less", "let", "lets", "level", "like", "likewise",
70
+ "line", "lines", "list", "literally", "ll",
71
+ "look", "looking", "low", "m", "main", "make",
72
+ "making", "manual", "many", "may", "maybe", "md", "me",
73
+ "mean", "meanwhile", "method", "might", "mine", "mode", "more",
74
+ "moreover", "most", "much", "multiple", "must", // PRONOUNS - Possessive
75
+ "my",
76
+ "myself", "n", "nah", "near", "nearly", "need", "needed", "neither",
77
+ "never", "nevertheless", "new", "next", "nine", "no", // NEGATION
78
+ "nobody", "none",
79
+ "none", "nonetheless", "no one", "nope", "nor", "not",
80
+ "nothing", "now", "o", "obviously", "of", "off",
81
+ "often", "oh",
82
+ "ok", "okay", "on", "one", "ones", "only",
83
+ "onto", "option", "optional", "options", "or",
84
+ "other", "otherwise", "our", "ours", "ourselves",
85
+ "out", "outside", "over", "overall", "p", "part", "parts", "pass", "per",
86
+ "perhaps", "phase", "pl",
87
+ "please", "point",
88
+ "points", "possibly", "pretty", "previously", "primary", "probably", "process",
89
+ "proper", "provide", "provided", "purpose", "put", // FILE EXTENSIONS
90
+ "py",
91
+ "q", "question", "questions", // QUERY LANGUAGE
92
+ "quite",
93
+ "r", "rather", // FRAGMENT WORDS
94
+ "re",
95
+ "real", "really", "recently", "region",
96
+ "remain", "require", "required",
97
+ "result", "return", "right", "s", "same", "say", "secondary", // DOCUMENT/CODE STRUCTURE
98
+ "section",
99
+ "see", "seem", // PROGRAMMING KEYWORDS
100
+ "self",
101
+ "set", "seven", "several", "shall",
102
+ "she", "shes", "should", "shouldn",
103
+ "shouldnt", "show", "similarly", "simple", "simply",
104
+ "since", "single", "six", "so", "some", // QUANTIFIERS
105
+ "somebody", "someone", // PRONOUNS - Indefinite
106
+ "something",
107
+ "sometimes", "somewhat", "soon", "sorta", "source", "specific", "stable", "start",
108
+ "state", "status", "stay", "step", // STRUCTURAL WORDS
109
+ "steps", "still",
110
+ "str", "stuff", "such", "sys", "t", "take",
111
+ "tell", "ten", "that", "thats", "the", "their",
112
+ "theirs", "them", "themselves", "then", "there", "therefore",
113
+ "theres", "these", "they", "theyre", "theyve", // OVERLY GENERIC TERMS
114
+ "thing",
115
+ "things", "think", "this", // PRONOUNS - Demonstrative
116
+ "those", "though", "three", "through",
117
+ "thus", "time", "times", // PREPOSITIONS
118
+ "to",
119
+ "today", "toml", "tomorrow", "too", // SHORT FILLER
120
+ "totally", "toward",
121
+ "towards", "true", "try", "trying", "ts", // NUMBER WORDS
122
+ "two",
123
+ "type", "types", "u", "uh", "um", // SPEECH-TO-TEXT FILLERS (STT artifacts from voice input)
124
+ "under", "unknown", "unless",
125
+ "until", "up", "upon", "us", "used", "uses", // COMMON CODING TERMS
126
+ "using",
127
+ "v", "value", "ve", "version", "very", "via", "w",
128
+ "wanna", // COMMON REQUEST PHRASES
129
+ "want", "was", "wasn", "wasnt", "way", "ways",
130
+ "we", "well", "were", "weren", "werent", "weve", // QUESTION WORDS
131
+ "what",
132
+ "whats", "when", "whenever", "where", "whereas",
133
+ "wherever", "whether", "which", "while",
134
+ // PRONOUNS - Relative
135
+ "who", "whom", "whos", "whose", "why", "will", "with", "within", "without",
136
+ "won", "wont", "work", "working", "works", "would", "wouldn", "wouldnt", "x", "y", "yaml", "yeah", "yep", "yes",
137
+ "yesterday", "yet", "yield", "you", "youll", "your", "youre", "yours",
138
+ "yourself", "youve", "yup", "z",
139
+ ]);
140
+ /**
141
+ * Filter stop words from text.
142
+ * Splits on whitespace, removes words in STOP_WORDS set and single-char words.
143
+ * See SPEC.md §6.4
144
+ */
145
+ export function filterStopWords(text) {
146
+ return text
147
+ .split(/\s+/)
148
+ .filter((word) => word.length > 1 && !STOP_WORDS.has(word.toLowerCase()))
149
+ .join(" ");
150
+ }
@@ -0,0 +1,29 @@
1
+ export declare function isInternalCall(): boolean;
2
+ export declare function getInternalSubprocessEnv(): Record<string, string | undefined>;
3
+ export declare function findExecutable(name: string): string | null;
4
+ export interface ExecSyncError {
5
+ killed: boolean;
6
+ signal: string | null;
7
+ stdout: Buffer | string;
8
+ stderr: Buffer | string;
9
+ status: number | null;
10
+ message: string;
11
+ }
12
+ export declare function isExecSyncError(error: unknown): error is ExecSyncError;
13
+ export declare function normalizePathForCli(pathValue: string): string;
14
+ export declare function shellQuoteWin(arg: string): string;
15
+ export interface ExecResult {
16
+ stdout: string;
17
+ stderr: string;
18
+ exitCode: number;
19
+ killed: boolean;
20
+ signal: string | null;
21
+ }
22
+ export interface ExecAsyncOptions {
23
+ input?: string | undefined;
24
+ timeout?: number | undefined;
25
+ env?: Record<string, string | undefined> | undefined;
26
+ maxBuffer?: number | undefined;
27
+ shell?: boolean | undefined;
28
+ }
29
+ export declare function execFileAsync(file: string, args: string[], options?: ExecAsyncOptions): Promise<ExecResult>;
@@ -0,0 +1,96 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { resolveExecutable } from './executable-policy.js';
3
+ const childProcesses = new Set();
4
+ function cleanupChildren() {
5
+ for (const child of childProcesses) {
6
+ try {
7
+ child.kill('SIGKILL');
8
+ }
9
+ catch {
10
+ // Child may have already exited.
11
+ }
12
+ }
13
+ childProcesses.clear();
14
+ }
15
+ process.on('exit', () => {
16
+ cleanupChildren();
17
+ });
18
+ process.on('SIGINT', () => {
19
+ cleanupChildren();
20
+ process.exit(130);
21
+ });
22
+ process.on('SIGTERM', () => {
23
+ cleanupChildren();
24
+ process.exit(143);
25
+ });
26
+ export function isInternalCall() {
27
+ return process.env.AIWCLI_INTERNAL_CALL === 'true';
28
+ }
29
+ export function getInternalSubprocessEnv() {
30
+ const env = {
31
+ ...process.env,
32
+ AIWCLI_INTERNAL_CALL: 'true',
33
+ };
34
+ delete env.CLAUDECODE;
35
+ delete env.CLAUDE_CODE_ENTRYPOINT;
36
+ return env;
37
+ }
38
+ export function findExecutable(name) {
39
+ return resolveExecutable(name, { windowsProfile: 'cmdOrExeFirst' });
40
+ }
41
+ export function isExecSyncError(error) {
42
+ return typeof error === 'object' && error !== null && 'killed' in error && 'signal' in error;
43
+ }
44
+ export function normalizePathForCli(pathValue) {
45
+ if (process.platform !== 'win32')
46
+ return pathValue;
47
+ return pathValue.replaceAll('\\', '/');
48
+ }
49
+ export function shellQuoteWin(arg) {
50
+ if (process.platform !== 'win32')
51
+ return arg;
52
+ return '"' + arg.replaceAll('"', '""') + '"';
53
+ }
54
+ export function execFileAsync(file, args, options) {
55
+ return new Promise((resolve) => {
56
+ const child = execFile(file, args, {
57
+ encoding: 'utf8',
58
+ timeout: options?.timeout ?? 0,
59
+ env: options?.env,
60
+ maxBuffer: options?.maxBuffer ?? 10 * 1024 * 1024,
61
+ shell: options?.shell,
62
+ }, (error, stdout, stderr) => {
63
+ if (error) {
64
+ const errObj = error;
65
+ resolve({
66
+ stdout: String(stdout ?? ''),
67
+ stderr: String(stderr ?? ''),
68
+ exitCode: typeof errObj.code === 'number'
69
+ ? errObj.code
70
+ : typeof errObj.status === 'number'
71
+ ? errObj.status
72
+ : 1,
73
+ killed: Boolean(errObj.killed),
74
+ signal: typeof errObj.signal === 'string' ? errObj.signal : null,
75
+ });
76
+ }
77
+ else {
78
+ resolve({
79
+ stdout: String(stdout ?? ''),
80
+ stderr: String(stderr ?? ''),
81
+ exitCode: 0,
82
+ killed: false,
83
+ signal: null,
84
+ });
85
+ }
86
+ });
87
+ childProcesses.add(child);
88
+ child.on('exit', () => {
89
+ childProcesses.delete(child);
90
+ });
91
+ if (options?.input !== null && options?.input !== undefined && child.stdin) {
92
+ child.stdin.write(options.input);
93
+ child.stdin.end();
94
+ }
95
+ });
96
+ }
@@ -0,0 +1,13 @@
1
+ export declare function selectMsysBashFromLookupPaths(paths: string[]): null | string;
2
+ export declare function deriveMsysBashFromGitPath(gitPath: string): null | string;
3
+ export declare function findMsysBash(): null | string;
4
+ export declare function isTmuxReachableViaBash(bashPath: string): boolean;
5
+ export declare function isNativeTmuxAvailable(platform?: NodeJS.Platform): boolean;
6
+ /** Find psmux (native Windows terminal multiplexer) on PATH. */
7
+ export declare function findPsmux(): null | string;
8
+ export interface WindowsTmuxPreflight {
9
+ available: boolean;
10
+ bashPath?: string;
11
+ reason?: string;
12
+ }
13
+ export declare function preflightWindowsTmux(): WindowsTmuxPreflight;
@@ -0,0 +1,78 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { isCommandAvailable, lookupExecutables } from './executable-policy.js';
4
+ import { isWindowsPlatform } from './platform-adapter.js';
5
+ export function selectMsysBashFromLookupPaths(paths) {
6
+ for (const candidate of paths) {
7
+ const trimmed = candidate.trim();
8
+ if (trimmed && /git|msys|mingw/iu.test(trimmed))
9
+ return trimmed;
10
+ }
11
+ return null;
12
+ }
13
+ export function deriveMsysBashFromGitPath(gitPath) {
14
+ const trimmed = gitPath.trim();
15
+ if (!trimmed)
16
+ return null;
17
+ const gitMatch = trimmed.match(/^(.+[/\\]Git)[/\\]cmd[/\\]git\.exe$/iu);
18
+ if (!gitMatch?.[1])
19
+ return null;
20
+ return `${gitMatch[1]}\\usr\\bin\\bash.exe`;
21
+ }
22
+ export function findMsysBash() {
23
+ const directBash = selectMsysBashFromLookupPaths(lookupExecutables('bash', { platform: 'win32' }));
24
+ if (directBash)
25
+ return directBash;
26
+ const gitCandidates = lookupExecutables('git', { platform: 'win32' });
27
+ for (const candidate of gitCandidates) {
28
+ const derived = deriveMsysBashFromGitPath(candidate);
29
+ if (derived && existsSync(derived))
30
+ return derived;
31
+ }
32
+ const knownPaths = [
33
+ String.raw `C:\Program Files\Git\usr\bin\bash.exe`,
34
+ String.raw `C:\Program Files (x86)\Git\usr\bin\bash.exe`,
35
+ ];
36
+ for (const knownPath of knownPaths) {
37
+ if (existsSync(knownPath))
38
+ return knownPath;
39
+ }
40
+ return null;
41
+ }
42
+ export function isTmuxReachableViaBash(bashPath) {
43
+ try {
44
+ execFileSync(bashPath, ['-lc', 'tmux -V'], {
45
+ timeout: 3000,
46
+ stdio: 'ignore',
47
+ env: { ...process.env, MSYS_NO_PATHCONV: '1' },
48
+ windowsHide: true,
49
+ });
50
+ return true;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ export function isNativeTmuxAvailable(platform = process.platform) {
57
+ return isCommandAvailable('tmux', platform);
58
+ }
59
+ /** Find psmux (native Windows terminal multiplexer) on PATH. */
60
+ export function findPsmux() {
61
+ if (!isWindowsPlatform())
62
+ return null;
63
+ const candidates = lookupExecutables('psmux', { platform: 'win32' });
64
+ return candidates[0]?.trim() || null;
65
+ }
66
+ export function preflightWindowsTmux() {
67
+ if (!isWindowsPlatform()) {
68
+ return { available: false, reason: 'not running on Windows' };
69
+ }
70
+ const bashPath = findMsysBash();
71
+ if (!bashPath) {
72
+ return { available: false, reason: 'Git Bash not found' };
73
+ }
74
+ if (!isTmuxReachableViaBash(bashPath)) {
75
+ return { available: false, bashPath, reason: 'tmux not available in Git Bash' };
76
+ }
77
+ return { available: true, bashPath };
78
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Core utilities for shared context management.
3
+ * See SPEC.md §14.2, §14.3
4
+ */
5
+ /**
6
+ * Print to stderr. For terminal-only UX messages, not diagnostics.
7
+ */
8
+ export declare function eprint(...args: unknown[]): void;
9
+ /**
10
+ * Get current local datetime as Date.
11
+ */
12
+ export declare function nowLocal(): Date;
13
+ /**
14
+ * Get current time as ISO 8601 string (local time, no timezone suffix).
15
+ * Matches Python datetime.now().isoformat() behavior.
16
+ */
17
+ export declare function nowIso(): string;
18
+ /**
19
+ * Format datetime for display.
20
+ * Returns "YYYY-MM-DD HH:MM:SS"
21
+ * See SPEC.md §14.3
22
+ */
23
+ export declare function formatTimestamp(dt?: Date): string;
24
+ /**
25
+ * Parse ISO 8601 timestamp string.
26
+ * Returns null if parsing fails.
27
+ * See SPEC.md §14.3
28
+ */
29
+ export declare function parseIsoTimestamp(isoStr: string): Date | null;
30
+ /**
31
+ * Normalize a filesystem path for display — always uses forward slashes.
32
+ * No-op on Unix; converts backslashes on Windows.
33
+ */
34
+ export declare function displayPath(p: string): string;
35
+ /**
36
+ * Clean text for stop-word matching in slug generation.
37
+ * Strips apostrophes (i'm -> im), removes punctuation, normalizes whitespace.
38
+ * See SPEC.md §14.2
39
+ */
40
+ export declare function cleanTextForSlug(text: string): string;
41
+ /**
42
+ * Generate a slug from text using AI inference with stop-word fallbacks.
43
+ * Pipeline: AI inference → stop-word post-filter → stop-word fallback → word-length fallback.
44
+ * Reusable by both context ID generation and plan archival.
45
+ * See SPEC.md §14.2
46
+ */
47
+ export declare function generateSlug(text: string, maxLen?: number, fallbackSlug?: string): string;
48
+ /**
49
+ * Generate a context ID from a summary string.
50
+ * Format: YYMMDD-HHMM-slug
51
+ * Delegates slug generation to generateSlug().
52
+ * See SPEC.md §14.2
53
+ */
54
+ export declare function generateContextId(summary: string, existingIds?: Set<string>): string;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Core utilities for shared context management.
3
+ * See SPEC.md §14.2, §14.3
4
+ */
5
+ import { sanitizeTitle } from "./constants.js";
6
+ import { logDebug, logError, logWarn } from "./logger.js";
7
+ import { STOP_WORDS } from "./stop-words.js";
8
+ /**
9
+ * Print to stderr. For terminal-only UX messages, not diagnostics.
10
+ */
11
+ export function eprint(...args) {
12
+ process.stderr.write(args.map(String).join(" ") + "\n");
13
+ }
14
+ /**
15
+ * Get current local datetime as Date.
16
+ */
17
+ export function nowLocal() {
18
+ return new Date();
19
+ }
20
+ /**
21
+ * Get current time as ISO 8601 string (local time, no timezone suffix).
22
+ * Matches Python datetime.now().isoformat() behavior.
23
+ */
24
+ export function nowIso() {
25
+ const d = new Date();
26
+ const year = d.getFullYear();
27
+ const month = String(d.getMonth() + 1).padStart(2, "0");
28
+ const day = String(d.getDate()).padStart(2, "0");
29
+ const hours = String(d.getHours()).padStart(2, "0");
30
+ const minutes = String(d.getMinutes()).padStart(2, "0");
31
+ const seconds = String(d.getSeconds()).padStart(2, "0");
32
+ const ms = String(d.getMilliseconds()).padStart(3, "0");
33
+ return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${ms}`;
34
+ }
35
+ /**
36
+ * Format datetime for display.
37
+ * Returns "YYYY-MM-DD HH:MM:SS"
38
+ * See SPEC.md §14.3
39
+ */
40
+ export function formatTimestamp(dt) {
41
+ const d = dt ?? nowLocal();
42
+ const year = d.getFullYear();
43
+ const month = String(d.getMonth() + 1).padStart(2, "0");
44
+ const day = String(d.getDate()).padStart(2, "0");
45
+ const hours = String(d.getHours()).padStart(2, "0");
46
+ const minutes = String(d.getMinutes()).padStart(2, "0");
47
+ const seconds = String(d.getSeconds()).padStart(2, "0");
48
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
49
+ }
50
+ /**
51
+ * Parse ISO 8601 timestamp string.
52
+ * Returns null if parsing fails.
53
+ * See SPEC.md §14.3
54
+ */
55
+ export function parseIsoTimestamp(isoStr) {
56
+ try {
57
+ const normalized = isoStr.replace("Z", "+00:00");
58
+ const d = new Date(normalized);
59
+ if (isNaN(d.getTime()))
60
+ return null;
61
+ return d;
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ }
67
+ /**
68
+ * Normalize a filesystem path for display — always uses forward slashes.
69
+ * No-op on Unix; converts backslashes on Windows.
70
+ */
71
+ export function displayPath(p) {
72
+ return p.replaceAll("\\", "/");
73
+ }
74
+ /**
75
+ * Clean text for stop-word matching in slug generation.
76
+ * Strips apostrophes (i'm -> im), removes punctuation, normalizes whitespace.
77
+ * See SPEC.md §14.2
78
+ */
79
+ export function cleanTextForSlug(text) {
80
+ if (!text)
81
+ return "";
82
+ let result = text.toLowerCase();
83
+ result = result.replaceAll('\'', ""); // i'm -> im, you're -> youre
84
+ result = result.replaceAll(/[^a-z0-9\s]/g, " "); // punctuation -> spaces
85
+ result = result.replaceAll(/\s+/g, " ").trim();
86
+ return result;
87
+ }
88
+ /**
89
+ * Generate a slug from text using AI inference with stop-word fallbacks.
90
+ * Pipeline: AI inference → stop-word post-filter → stop-word fallback → word-length fallback.
91
+ * Reusable by both context ID generation and plan archival.
92
+ * See SPEC.md §14.2
93
+ */
94
+ export function generateSlug(text, maxLen = 150, fallbackSlug = "context") {
95
+ if (!text || !text.trim())
96
+ return fallbackSlug;
97
+ let slug = null;
98
+ const cleanedText = cleanTextForSlug(text);
99
+ // Tier 1: AI inference via generateContextIdSlug (sync — uses execFileSync)
100
+ try {
101
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef
102
+ const { generateContextIdSlug } = require("./inference.js");
103
+ const aiSlug = generateContextIdSlug(text);
104
+ if (aiSlug) {
105
+ const filteredWords = aiSlug
106
+ .split(/\s+/)
107
+ .filter((w) => !STOP_WORDS.has(w.toLowerCase()) && w.length > 1);
108
+ if (filteredWords.length >= 5) {
109
+ slug = sanitizeTitle(filteredWords.join(" "), maxLen);
110
+ }
111
+ else {
112
+ logDebug("utils", `AI slug too generic after stop-word filter (${filteredWords.length} words remain), using fallback`);
113
+ }
114
+ }
115
+ }
116
+ catch (error) {
117
+ logWarn("utils", `AI slug generation failed, using fallback: ${error}`);
118
+ }
119
+ // Tier 2: Stop-word filtering on cleaned text
120
+ if (!slug) {
121
+ const words = cleanedText
122
+ .split(/\s+/)
123
+ .filter((w) => !STOP_WORDS.has(w) && w.length > 1)
124
+ .slice(0, 12);
125
+ slug = words.length >= 3
126
+ ? sanitizeTitle(words.join(" "), maxLen)
127
+ : sanitizeTitle(cleanedText.split(/\s+/).filter((w) => w.length > 2).slice(0, 6).join(" "), maxLen) || fallbackSlug;
128
+ }
129
+ return slug;
130
+ }
131
+ /**
132
+ * Generate a context ID from a summary string.
133
+ * Format: YYMMDD-HHMM-slug
134
+ * Delegates slug generation to generateSlug().
135
+ * See SPEC.md §14.2
136
+ */
137
+ export function generateContextId(summary, existingIds) {
138
+ const now = new Date();
139
+ const yy = String(now.getFullYear()).slice(2);
140
+ const mm = String(now.getMonth() + 1).padStart(2, "0");
141
+ const dd = String(now.getDate()).padStart(2, "0");
142
+ const hh = String(now.getHours()).padStart(2, "0");
143
+ const min = String(now.getMinutes()).padStart(2, "0");
144
+ const timestamp = `${yy}${mm}${dd}-${hh}${min}`;
145
+ let baseId;
146
+ try {
147
+ const slug = generateSlug(summary);
148
+ baseId = `${timestamp}-${slug}`;
149
+ }
150
+ catch (error) {
151
+ logError("utils", `Context ID generation failed entirely, using timestamp: ${error}`);
152
+ baseId = `${timestamp}-context`;
153
+ }
154
+ if (!existingIds || !existingIds.has(baseId)) {
155
+ return baseId;
156
+ }
157
+ let counter = 2;
158
+ while (existingIds.has(`${baseId}-${counter}`)) {
159
+ counter++;
160
+ }
161
+ return `${baseId}-${counter}`;
162
+ }
@@ -0,0 +1,9 @@
1
+ export interface SentinelWrapParams {
2
+ autoClose: boolean;
3
+ command: string;
4
+ holdMessage: string;
5
+ holdPane: boolean;
6
+ sentinelPath: string;
7
+ }
8
+ export declare function wrapSentinelSh(params: SentinelWrapParams): string;
9
+ export declare function wrapSentinelPowerShell(params: SentinelWrapParams): string;
@@ -0,0 +1,20 @@
1
+ import { quoteForPowerShell, quoteForSh } from './shell-quoting.js';
2
+ export function wrapSentinelSh(params) {
3
+ const { command, sentinelPath, autoClose, holdPane, holdMessage } = params;
4
+ const base = `${command}; code=$?; printf '%s' "$code" > ${quoteForSh(sentinelPath)}`;
5
+ if (autoClose) {
6
+ return `${base}; tmux kill-pane -t "$TMUX_PANE" >/dev/null 2>&1 || true; exit $code`;
7
+ }
8
+ if (holdPane) {
9
+ return `${base}; echo; echo ${quoteForSh(holdMessage)}; exec bash`;
10
+ }
11
+ return `${base}; exit $code`;
12
+ }
13
+ export function wrapSentinelPowerShell(params) {
14
+ const { command, sentinelPath, autoClose, holdPane, holdMessage } = params;
15
+ const base = `${command}; $code = $LASTEXITCODE; Set-Content -Path ${quoteForPowerShell(sentinelPath)} -Value $code -NoNewline`;
16
+ if (holdPane && !autoClose) {
17
+ return `${base}; Write-Host ''; Write-Host ${quoteForPowerShell(holdMessage)}; Read-Host -Prompt 'Press Enter to close' | Out-Null`;
18
+ }
19
+ return `${base}; exit $code`;
20
+ }
@@ -0,0 +1,5 @@
1
+ export declare function quoteForSh(input: string): string;
2
+ export declare function quoteForPowerShell(input: string): string;
3
+ /** Wrap a PowerShell command using -EncodedCommand to avoid all quoting issues. */
4
+ export declare function toEncodedPowerShell(command: string): string;
5
+ export declare function escapeSingleQuotedPath(path: string, dialect: 'bash' | 'powershell'): string;
@@ -0,0 +1,17 @@
1
+ export function quoteForSh(input) {
2
+ return `'${input.replaceAll("'", "'\"'\"'")}'`;
3
+ }
4
+ export function quoteForPowerShell(input) {
5
+ return `'${input.replaceAll("'", "''")}'`;
6
+ }
7
+ /** Wrap a PowerShell command using -EncodedCommand to avoid all quoting issues. */
8
+ export function toEncodedPowerShell(command) {
9
+ const encoded = Buffer.from(command, 'utf16le').toString('base64');
10
+ return `powershell.exe -NoProfile -EncodedCommand ${encoded}`;
11
+ }
12
+ export function escapeSingleQuotedPath(path, dialect) {
13
+ if (dialect === 'powershell') {
14
+ return path.replaceAll("'", "''");
15
+ }
16
+ return path.replaceAll("'", String.raw `'\''`);
17
+ }
@@ -0,0 +1,6 @@
1
+ import { ProcessSpawnError } from './errors.js';
2
+ export declare function classifySpawnError(command: string, error: NodeJS.ErrnoException): ProcessSpawnError;
3
+ export declare function resolveWindowsSpawnArgs(command: string, args: string[], cmdExists: (commandName: string) => boolean): null | {
4
+ args: string[];
5
+ command: string;
6
+ };
@@ -0,0 +1,15 @@
1
+ import { ProcessSpawnError } from './errors.js';
2
+ export function classifySpawnError(command, error) {
3
+ if (error.code === 'ENOENT') {
4
+ return new ProcessSpawnError(`Command not found: ${command}. Install Claude Code from https://claude.ai/download.`, 'ENOENT');
5
+ }
6
+ if (error.code === 'EACCES') {
7
+ return new ProcessSpawnError(`Permission denied: ${command}. Check file permissions.`, 'EACCES');
8
+ }
9
+ return new ProcessSpawnError(`Failed to spawn ${command}: ${error.message}. Check that the command exists and is executable.`, error.code);
10
+ }
11
+ export function resolveWindowsSpawnArgs(command, args, cmdExists) {
12
+ if (!cmdExists(`${command}.cmd`))
13
+ return null;
14
+ return { command: 'cmd.exe', args: ['/c', command, ...args] };
15
+ }