aiwcli 0.15.7 → 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 (272) hide show
  1. package/README.md +106 -1125
  2. package/bin/run.js +0 -4
  3. package/dist/capabilities/installation/control-plane/clear-command.d.ts +2 -0
  4. package/dist/capabilities/installation/control-plane/clear-command.js +32 -3
  5. package/dist/capabilities/installation/control-plane/init-command.js +2 -2
  6. package/dist/capabilities/launch/contracts.d.ts +39 -4
  7. package/dist/capabilities/launch/control-plane/execute-launch.js +158 -119
  8. package/dist/capabilities/launch/runtime-core/launch-decisions.d.ts +82 -0
  9. package/dist/capabilities/launch/runtime-core/launch-decisions.js +202 -0
  10. package/dist/commands/branch.d.ts +1 -1
  11. package/dist/commands/branch.js +1 -1
  12. package/dist/commands/launch.d.ts +0 -5
  13. package/dist/commands/launch.js +2 -37
  14. package/dist/lib/config.js +1 -2
  15. package/dist/lib/context/context-store.js +28 -2
  16. package/dist/lib/core-installer.d.ts +1 -1
  17. package/dist/lib/core-installer.js +6 -27
  18. package/dist/lib/debug.d.ts +0 -10
  19. package/dist/lib/debug.js +0 -10
  20. package/dist/lib/env-sanitizer.d.ts +25 -0
  21. package/dist/lib/env-sanitizer.js +46 -0
  22. package/dist/lib/errors.d.ts +0 -13
  23. package/dist/lib/errors.js +0 -15
  24. package/dist/lib/git-exclude-manager.js +1 -1
  25. package/dist/lib/hooks/context-monitor-logic.d.ts +6 -0
  26. package/dist/lib/hooks/context-monitor-logic.js +25 -0
  27. package/dist/lib/hooks/hook-utils.js +11 -0
  28. package/dist/lib/hooks/prompt-binding-logic.d.ts +7 -0
  29. package/dist/lib/hooks/prompt-binding-logic.js +50 -0
  30. package/dist/lib/hooks/session-end-logic.js +2 -14
  31. package/dist/lib/install-state.js +6 -13
  32. package/dist/lib/json-io.d.ts +12 -0
  33. package/dist/lib/json-io.js +30 -0
  34. package/dist/lib/multiplexer.d.ts +43 -35
  35. package/dist/lib/multiplexer.js +21 -2
  36. package/dist/lib/multiplexers/psmux.d.ts +14 -34
  37. package/dist/lib/multiplexers/psmux.js +70 -130
  38. package/dist/lib/multiplexers/tmux.d.ts +11 -19
  39. package/dist/lib/multiplexers/tmux.js +79 -120
  40. package/dist/lib/multiplexers/wezterm.d.ts +38 -0
  41. package/dist/lib/multiplexers/wezterm.js +225 -0
  42. package/dist/lib/mux-utils.d.ts +4 -3
  43. package/dist/lib/mux-utils.js +7 -13
  44. package/dist/lib/prompt-file-manager.d.ts +23 -0
  45. package/dist/lib/prompt-file-manager.js +41 -0
  46. package/dist/lib/runtime/agent-launcher.d.ts +67 -0
  47. package/dist/lib/runtime/agent-launcher.js +262 -0
  48. package/dist/lib/runtime/aiw-cli.d.ts +2 -0
  49. package/dist/lib/runtime/aiw-cli.js +3 -1
  50. package/dist/lib/runtime/cli-args.d.ts +5 -2
  51. package/dist/lib/runtime/cli-args.js +18 -3
  52. package/dist/lib/runtime/inference.js +3 -14
  53. package/dist/lib/runtime/models.d.ts +6 -0
  54. package/dist/lib/runtime/models.js +6 -0
  55. package/dist/lib/runtime/state-io.d.ts +2 -1
  56. package/dist/lib/runtime/state-io.js +9 -4
  57. package/dist/lib/runtime/utils.d.ts +8 -0
  58. package/dist/lib/runtime/utils.js +31 -1
  59. package/dist/lib/schemas.d.ts +250 -0
  60. package/dist/lib/schemas.js +216 -0
  61. package/dist/lib/sentinel-manager.d.ts +32 -0
  62. package/dist/lib/sentinel-manager.js +62 -0
  63. package/dist/lib/sentinel-wrapper.d.ts +1 -0
  64. package/dist/lib/sentinel-wrapper.js +12 -3
  65. package/dist/lib/settings-hierarchy.js +3 -20
  66. package/dist/lib/shell-adapters/bash-adapter.d.ts +18 -0
  67. package/dist/lib/shell-adapters/bash-adapter.js +69 -0
  68. package/dist/lib/shell-adapters/index.d.ts +5 -0
  69. package/dist/lib/shell-adapters/index.js +7 -0
  70. package/dist/lib/shell-adapters/powershell-adapter.d.ts +18 -0
  71. package/dist/lib/shell-adapters/powershell-adapter.js +62 -0
  72. package/dist/lib/shell-adapters/shell-adapter.d.ts +45 -0
  73. package/dist/lib/shell-adapters/shell-adapter.js +5 -0
  74. package/dist/lib/spawn-errors.d.ts +3 -0
  75. package/dist/lib/spawn-errors.js +15 -1
  76. package/dist/lib/spinner.d.ts +0 -5
  77. package/dist/lib/spinner.js +0 -16
  78. package/dist/lib/template-installer.d.ts +10 -0
  79. package/dist/lib/template-installer.js +4 -4
  80. package/dist/lib/terminal-strategy.d.ts +1 -0
  81. package/dist/lib/terminal-strategy.js +12 -6
  82. package/dist/lib/terminal.d.ts +7 -5
  83. package/dist/lib/terminal.js +42 -19
  84. package/dist/lib/tmux-primitives.d.ts +0 -2
  85. package/dist/lib/tmux-primitives.js +0 -4
  86. package/dist/lib/tmux-session.js +2 -1
  87. package/dist/lib/windsurf-hooks-hierarchy.js +6 -23
  88. package/dist/platform/launch.d.ts +2 -1
  89. package/dist/platform/launch.js +1 -0
  90. package/dist/templates/CLAUDE.md +0 -1
  91. package/dist/templates/cc-native/.claude/settings.json +0 -10
  92. package/dist/templates/cc-native/TEMPLATE-SCHEMA.md +11 -4
  93. package/dist/templates/cc-native/_cc-native/cc-native.config.json +3 -7
  94. package/dist/templates/cc-native/_cc-native/hooks/CLAUDE.md +26 -47
  95. package/dist/templates/cc-native/_cc-native/hooks/cc-native-plan-review.ts +7 -9
  96. package/dist/templates/cc-native/_cc-native/hooks/enhance_plan_post_write.ts +2 -3
  97. package/dist/templates/cc-native/_cc-native/hooks/mark_questions_asked.ts +2 -2
  98. package/dist/templates/cc-native/_cc-native/hooks/plan_questions_early.ts +0 -25
  99. package/dist/templates/cc-native/_cc-native/hooks/validate_task_prompt.ts +4 -4
  100. package/dist/templates/cc-native/_cc-native/lib-ts/.mocharc.json +9 -0
  101. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/aggregate-agents.test.ts +118 -0
  102. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/artifacts.test.ts +234 -0
  103. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cc-native-state.test.ts +170 -0
  104. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/cli-output-parser.test.ts +73 -0
  105. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/config.test.ts +64 -0
  106. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/constants.test.ts +40 -0
  107. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/debug.test.ts +42 -0
  108. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/exports.test.ts +58 -0
  109. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/helpers.ts +107 -0
  110. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/add-plan-context.hook.test.ts +97 -0
  111. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-questions.hook.test.ts +81 -0
  112. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/hooks/plan-review.hook.test.ts +71 -0
  113. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/json-parser.test.ts +99 -0
  114. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator-agent.test.ts +288 -0
  115. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/orchestrator.test.ts +48 -0
  116. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/reviewers.test.ts +32 -0
  117. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/state.test.ts +124 -0
  118. package/dist/templates/cc-native/_cc-native/lib-ts/__tests__/verdict.test.ts +93 -0
  119. package/dist/templates/cc-native/_cc-native/lib-ts/agent-selection.ts +163 -0
  120. package/dist/templates/cc-native/_cc-native/lib-ts/aggregate-agents.ts +6 -14
  121. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/format.ts +597 -599
  122. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/index.ts +26 -26
  123. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/tracker.ts +106 -107
  124. package/dist/templates/cc-native/_cc-native/{artifacts/lib → lib-ts/artifacts}/write.ts +118 -119
  125. package/dist/templates/cc-native/_cc-native/lib-ts/artifacts.ts +21 -0
  126. package/dist/templates/cc-native/_cc-native/lib-ts/cc-native-state.ts +16 -15
  127. package/dist/templates/cc-native/_cc-native/lib-ts/cli-output-parser.ts +132 -10
  128. package/dist/templates/cc-native/_cc-native/lib-ts/constants.ts +6 -6
  129. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/corroboration.ts +119 -119
  130. package/dist/templates/cc-native/_cc-native/lib-ts/debug.ts +1 -2
  131. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/graduation.ts +132 -132
  132. package/dist/templates/cc-native/_cc-native/lib-ts/index.ts +88 -86
  133. package/dist/templates/cc-native/_cc-native/lib-ts/json-parser.ts +5 -6
  134. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/orchestrator.ts +70 -70
  135. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/output-builder.ts +130 -121
  136. package/dist/templates/cc-native/_cc-native/lib-ts/package-lock.json +1679 -0
  137. package/dist/templates/cc-native/_cc-native/lib-ts/package.json +24 -0
  138. package/dist/templates/cc-native/_cc-native/lib-ts/plan-discovery.ts +4 -4
  139. package/dist/templates/cc-native/_cc-native/lib-ts/plan-enhancement.ts +1 -6
  140. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/plan-questions.ts +101 -101
  141. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/review-pipeline.ts +511 -543
  142. package/dist/templates/cc-native/_cc-native/lib-ts/reviewers/__tests__/agent-providers.test.ts +262 -0
  143. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/agent.ts +71 -85
  144. package/dist/templates/{core/lib-ts/agent-exec → cc-native/_cc-native/lib-ts/reviewers/base}/base-agent.ts +138 -152
  145. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/index.ts +12 -12
  146. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/claude-agent.ts +66 -57
  147. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/codex-agent.ts +185 -200
  148. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/gemini-agent.ts +39 -40
  149. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/providers/orchestrator-claude-agent.ts +196 -224
  150. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/schemas.ts +201 -201
  151. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/reviewers/types.ts +21 -23
  152. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/hyde.test.ts +365 -0
  153. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/__tests__/ollama-client.test.ts +223 -0
  154. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/embedding-indexer.ts +12 -16
  155. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/hyde.ts +3 -2
  156. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/index.ts +31 -31
  157. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/logger.ts +6 -7
  158. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/ollama-client.ts +7 -9
  159. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/retrieval-pipeline.ts +14 -17
  160. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-indexer.ts +37 -41
  161. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-loader.ts +33 -43
  162. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/transcript-searcher.ts +20 -20
  163. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/types.ts +8 -9
  164. package/dist/templates/cc-native/_cc-native/lib-ts/rlm/vector-store.ts +3 -4
  165. package/dist/templates/cc-native/_cc-native/lib-ts/settings.ts +50 -126
  166. package/dist/templates/cc-native/_cc-native/lib-ts/state.ts +19 -21
  167. package/dist/templates/cc-native/_cc-native/lib-ts/types.ts +13 -88
  168. package/dist/templates/cc-native/_cc-native/{plan-review/lib → lib-ts}/verdict.ts +72 -72
  169. package/dist/templates/cc-native/_cc-native/plan-review/CLAUDE.md +35 -0
  170. package/dist/templates/cc-native/_cc-native/plan-review/lib/agent-selection.ts +1 -1
  171. package/dist/templates/cc-native/_cc-native/scripts/council_debate.ts +242 -0
  172. package/dist/templates/cc-native/_cc-native/scripts/council_debate_simple.ts +294 -0
  173. package/dist/templates/cc-native/_cc-native/{plan-review/workflows → workflows}/specdev.md +9 -9
  174. package/dist/templates/core/.claude/skills/codex/SKILL.md +25 -0
  175. package/dist/templates/core/.claude/skills/devin/SKILL.md +25 -0
  176. package/dist/templates/core/.claude/skills/handoff/SKILL.md +11 -0
  177. package/dist/templates/core/.claude/skills/handoff-resume/SKILL.md +11 -0
  178. package/dist/templates/core/.claude/skills/meta-plan/SKILL.md +13 -0
  179. package/dist/templates/core/.codex/skills/codex/SKILL.md +13 -0
  180. package/dist/templates/core/.codex/skills/devin/SKILL.md +19 -0
  181. package/dist/templates/core/.codex/skills/handoff/SKILL.md +11 -0
  182. package/dist/templates/core/.codex/skills/handoff-resume/SKILL.md +11 -0
  183. package/dist/templates/core/.codex/{workflows/meta-plan.md → skills/meta-plan/SKILL.md} +6 -0
  184. package/dist/templates/core/{.cognition → .devin}/AGENTS.md +2 -2
  185. package/dist/templates/core/.devin/skills/codex/SKILL.md +19 -0
  186. package/dist/templates/core/.devin/skills/devin/SKILL.md +13 -0
  187. package/dist/templates/core/.devin/skills/handoff/SKILL.md +11 -0
  188. package/dist/templates/core/.devin/skills/handoff-resume/SKILL.md +11 -0
  189. package/dist/templates/core/.devin/skills/meta-plan/SKILL.md +13 -0
  190. package/dist/templates/core/.windsurf/workflows/handoff-resume.md +9 -0
  191. package/dist/templates/core/hooks-ts/archive_plan.ts +1 -21
  192. package/dist/templates/core/hooks-ts/file-suggestion.ts +1 -19
  193. package/dist/templates/core/hooks-ts/pre_compact.ts +5 -18
  194. package/dist/templates/core/lib-ts/context/context-store.ts +29 -2
  195. package/dist/templates/core/lib-ts/hooks/hook-utils.ts +11 -0
  196. package/dist/templates/core/lib-ts/hooks/session-end-logic.ts +2 -13
  197. package/dist/templates/core/lib-ts/runtime/agent-launcher.ts +74 -0
  198. package/dist/templates/core/lib-ts/runtime/aiw-cli.ts +4 -2
  199. package/dist/templates/core/lib-ts/runtime/cli-args.ts +18 -4
  200. package/dist/templates/core/lib-ts/runtime/inference.ts +3 -15
  201. package/dist/templates/core/lib-ts/runtime/models.ts +7 -0
  202. package/dist/templates/core/lib-ts/runtime/state-io.ts +9 -4
  203. package/dist/templates/core/lib-ts/runtime/utils.ts +30 -1
  204. package/dist/templates/core/lib-ts/schemas.ts +233 -0
  205. package/dist/templates/core/scripts/resolve-run.ts +34 -2
  206. package/dist/templates/core/scripts/status_line.ts +1 -1
  207. package/dist/templates/core/skills/codex/CLAUDE.md +9 -4
  208. package/dist/templates/core/skills/codex/SKILL.md +6 -0
  209. package/dist/templates/core/skills/codex/lib/codex-watcher.ts +3 -10
  210. package/dist/templates/core/skills/codex/scripts/launch-codex.ts +26 -26
  211. package/dist/templates/core/skills/devin/CLAUDE.md +63 -6
  212. package/dist/templates/core/skills/devin/lib/devin-watcher.ts +116 -96
  213. package/dist/templates/core/skills/devin/scripts/launch-devin.ts +22 -21
  214. package/dist/templates/core/skills/handoff-system/CLAUDE.md +1 -1
  215. package/oclif.manifest.json +4 -4
  216. package/package.json +4 -4
  217. package/dist/lib/base-command.d.ts +0 -1
  218. package/dist/lib/base-command.js +0 -1
  219. package/dist/lib/env-compat.d.ts +0 -18
  220. package/dist/lib/env-compat.js +0 -23
  221. package/dist/lib/launch-options.d.ts +0 -1
  222. package/dist/lib/launch-options.js +0 -1
  223. package/dist/lib/stdin.d.ts +0 -48
  224. package/dist/lib/stdin.js +0 -60
  225. package/dist/templates/cc-native/_cc-native/CLAUDE.md +0 -73
  226. package/dist/templates/cc-native/_cc-native/artifacts/CLAUDE.md +0 -64
  227. package/dist/templates/cc-native/_cc-native/lib-ts/CLAUDE.md +0 -70
  228. package/dist/templates/cc-native/_cc-native/plan-review/CODING-STANDARDS-CHECKLIST.md +0 -75
  229. package/dist/templates/cc-native/_cc-native/plan-review/agents/CLAUDE.md +0 -143
  230. package/dist/templates/cc-native/_cc-native/plan-review/agents/PLAN-ORCHESTRATOR.md +0 -213
  231. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-questions/PLAN-QUESTIONER.md +0 -70
  232. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-EVOLUTION.md +0 -62
  233. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-PATTERNS.md +0 -61
  234. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ARCH-STRUCTURE.md +0 -62
  235. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/ASSUMPTION-TRACER.md +0 -56
  236. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CLARITY-AUDITOR.md +0 -53
  237. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-FEASIBILITY.md +0 -66
  238. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-GAPS.md +0 -70
  239. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/COMPLETENESS-ORDERING.md +0 -62
  240. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/CONSTRAINT-VALIDATOR.md +0 -72
  241. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-ADR-VALIDATOR.md +0 -61
  242. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DESIGN-SCALE-MATCHER.md +0 -64
  243. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DEVILS-ADVOCATE.md +0 -56
  244. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/DOCUMENTATION-PHILOSOPHY.md +0 -86
  245. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HANDOFF-READINESS.md +0 -59
  246. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/HIDDEN-COMPLEXITY.md +0 -58
  247. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/INCREMENTAL-DELIVERY.md +0 -66
  248. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-DEPENDENCY.md +0 -62
  249. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-FMEA.md +0 -66
  250. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-PREMORTEM.md +0 -71
  251. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/RISK-REVERSIBILITY.md +0 -74
  252. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SCOPE-BOUNDARY.md +0 -77
  253. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SIMPLICITY-GUARDIAN.md +0 -62
  254. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/SKEPTIC.md +0 -68
  255. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-BEHAVIOR-AUDITOR.md +0 -61
  256. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-CHARACTERIZATION.md +0 -71
  257. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-FIRST-VALIDATOR.md +0 -61
  258. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TESTDRIVEN-PYRAMID-ANALYZER.md +0 -61
  259. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-COSTS.md +0 -67
  260. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/TRADEOFF-STAKEHOLDERS.md +0 -65
  261. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-COVERAGE.md +0 -74
  262. package/dist/templates/cc-native/_cc-native/plan-review/agents/plan-review/VERIFY-STRENGTH.md +0 -69
  263. package/dist/templates/cc-native/_cc-native/plan-review/lib/reviewers/base/base-agent.ts +0 -7
  264. package/dist/templates/core/.codex/workflows/codex.md +0 -17
  265. package/dist/templates/core/.codex/workflows/handoff.md +0 -5
  266. package/dist/templates/core/lib-ts/agent-exec/backends/headless.ts +0 -34
  267. package/dist/templates/core/lib-ts/agent-exec/backends/index.ts +0 -6
  268. package/dist/templates/core/lib-ts/agent-exec/backends/tmux.ts +0 -148
  269. package/dist/templates/core/lib-ts/agent-exec/execution-backend.ts +0 -50
  270. package/dist/templates/core/lib-ts/agent-exec/index.ts +0 -6
  271. package/dist/templates/core/lib-ts/agent-exec/structured-output.ts +0 -165
  272. /package/dist/templates/core/{.cognition → .devin}/config.json +0 -0
@@ -0,0 +1,234 @@
1
+ import { expect } from "chai";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import {
5
+ formatReviewMarkdown,
6
+ formatCombinedMarkdown,
7
+ buildInlineReviewSummary,
8
+ extractTopIssuesText,
9
+ buildHighIssuesDocument,
10
+ buildCombinedJson,
11
+ generateReviewIndex,
12
+ } from "../artifacts.js";
13
+ import {
14
+ createSampleReviewerResult,
15
+ createSampleCombinedResult,
16
+ createTempDir,
17
+ cleanupTempDir,
18
+ } from "./helpers.js";
19
+
20
+ describe("artifacts", () => {
21
+ describe("formatReviewMarkdown", () => {
22
+ it("includes overall verdict in output", () => {
23
+ const results = [createSampleReviewerResult({ name: "claude", verdict: "pass" })];
24
+ const md = formatReviewMarkdown(results, "pass");
25
+ expect(md).to.include("PASS");
26
+ expect(md).to.include("Claude");
27
+ });
28
+
29
+ it("handles empty results", () => {
30
+ const md = formatReviewMarkdown([], "pass");
31
+ expect(md).to.include("PASS");
32
+ });
33
+
34
+ it("includes custom title", () => {
35
+ const md = formatReviewMarkdown([], "pass", "Custom Review Title");
36
+ expect(md).to.include("Custom Review Title");
37
+ });
38
+
39
+ it("marks default summaries with warning", () => {
40
+ const result = createSampleReviewerResult({
41
+ data: {
42
+ verdict: "pass",
43
+ summary: "No summary provided.",
44
+ summary_source: "default",
45
+ issues: [],
46
+ missing_sections: [],
47
+ questions: [],
48
+ },
49
+ });
50
+ const md = formatReviewMarkdown([result], "pass");
51
+ expect(md).to.include("⚠️");
52
+ });
53
+ });
54
+
55
+ describe("formatCombinedMarkdown", () => {
56
+ it("includes plan hash and overall verdict", () => {
57
+ const combined = createSampleCombinedResult();
58
+ const md = formatCombinedMarkdown(combined);
59
+ expect(md).to.include("abc123def456");
60
+ expect(md).to.include("PASS");
61
+ });
62
+
63
+ it("includes orchestration section when present", () => {
64
+ const combined = createSampleCombinedResult();
65
+ const md = formatCombinedMarkdown(combined);
66
+ expect(md).to.include("Orchestration");
67
+ expect(md).to.include("medium");
68
+ });
69
+
70
+ it("includes agent reviewer sections", () => {
71
+ const combined = createSampleCombinedResult({
72
+ agents: {
73
+ "test-agent": createSampleReviewerResult({ name: "test-agent", verdict: "warn" }),
74
+ },
75
+ });
76
+ const md = formatCombinedMarkdown(combined);
77
+ expect(md).to.include("test-agent");
78
+ expect(md).to.include("warn");
79
+ });
80
+ });
81
+
82
+ describe("buildInlineReviewSummary", () => {
83
+ it("includes overall verdict", () => {
84
+ const combined = createSampleCombinedResult();
85
+ const summary = buildInlineReviewSummary(combined);
86
+ expect(summary).to.include("PASS");
87
+ });
88
+
89
+ it("lists high-severity issues", () => {
90
+ const combined = createSampleCombinedResult({
91
+ agents: {
92
+ test: createSampleReviewerResult({
93
+ name: "test",
94
+ data: {
95
+ verdict: "warn",
96
+ summary: "Issues found",
97
+ summary_source: "reviewer",
98
+ issues: [
99
+ { severity: "high", category: "security", issue: "SQL injection", suggested_fix: "Use parameterized queries" },
100
+ ],
101
+ missing_sections: [],
102
+ questions: [],
103
+ },
104
+ }),
105
+ },
106
+ });
107
+ const summary = buildInlineReviewSummary(combined);
108
+ expect(summary).to.include("SQL injection");
109
+ expect(summary).to.include("security");
110
+ });
111
+
112
+ it("truncates to maxChars", () => {
113
+ const combined = createSampleCombinedResult();
114
+ const summary = buildInlineReviewSummary(combined, 5, 20);
115
+ expect(summary.length).to.be.at.most(20);
116
+ });
117
+ });
118
+
119
+ describe("extractTopIssuesText", () => {
120
+ it("returns default message for no issues", () => {
121
+ const combined = createSampleCombinedResult();
122
+ const text = extractTopIssuesText(combined);
123
+ expect(text).to.equal("Review found critical issues");
124
+ });
125
+
126
+ it("extracts high-severity issues from reviewers", () => {
127
+ const combined = createSampleCombinedResult({
128
+ agents: {
129
+ r1: createSampleReviewerResult({
130
+ name: "r1",
131
+ data: {
132
+ verdict: "fail",
133
+ summary: "Problems",
134
+ summary_source: "reviewer",
135
+ issues: [{ severity: "high", category: "security", issue: "XSS vulnerability", suggested_fix: "sanitize" }],
136
+ missing_sections: [],
137
+ questions: [],
138
+ },
139
+ }),
140
+ },
141
+ });
142
+ const text = extractTopIssuesText(combined);
143
+ expect(text).to.include("XSS vulnerability");
144
+ expect(text).to.include("r1");
145
+ });
146
+ });
147
+
148
+ describe("buildHighIssuesDocument", () => {
149
+ it("reports no high-severity issues when none exist", () => {
150
+ const combined = createSampleCombinedResult();
151
+ const doc = buildHighIssuesDocument(combined);
152
+ expect(doc).to.include("No high-severity issues found");
153
+ });
154
+
155
+ it("lists high-severity issues by reviewer", () => {
156
+ const combined = createSampleCombinedResult({
157
+ agents: {
158
+ "security-agent": createSampleReviewerResult({
159
+ name: "security-agent",
160
+ verdict: "fail",
161
+ data: {
162
+ verdict: "fail",
163
+ summary: "Critical",
164
+ summary_source: "reviewer",
165
+ issues: [
166
+ { severity: "high", category: "auth", issue: "Missing auth check", suggested_fix: "Add middleware" },
167
+ { severity: "low", category: "style", issue: "Formatting", suggested_fix: "Run prettier" },
168
+ ],
169
+ missing_sections: [],
170
+ questions: [],
171
+ },
172
+ }),
173
+ },
174
+ });
175
+ const doc = buildHighIssuesDocument(combined);
176
+ expect(doc).to.include("Missing auth check");
177
+ expect(doc).to.not.include("Formatting"); // low severity excluded
178
+ });
179
+ });
180
+
181
+ describe("buildCombinedJson", () => {
182
+ it("includes metadata with plan hash", () => {
183
+ const combined = createSampleCombinedResult();
184
+ const json = buildCombinedJson(combined);
185
+ expect((json.metadata as any).plan_hash).to.equal("abc123def456");
186
+ });
187
+
188
+ it("includes overall verdict", () => {
189
+ const combined = createSampleCombinedResult();
190
+ const json = buildCombinedJson(combined);
191
+ expect((json.overall as any).verdict).to.equal("pass");
192
+ });
193
+
194
+ it("excludes low-severity issues from JSON", () => {
195
+ const combined = createSampleCombinedResult({
196
+ agents: {
197
+ test: createSampleReviewerResult({
198
+ name: "test",
199
+ data: {
200
+ verdict: "warn",
201
+ summary: "ok",
202
+ summary_source: "reviewer",
203
+ issues: [
204
+ { severity: "high", category: "sec", issue: "important", suggested_fix: "fix" },
205
+ { severity: "low", category: "style", issue: "trivial", suggested_fix: "ignore" },
206
+ ],
207
+ missing_sections: [],
208
+ questions: [],
209
+ },
210
+ }),
211
+ },
212
+ });
213
+ const json = buildCombinedJson(combined);
214
+ const reviewers = json.agents as Record<string, any>;
215
+ expect(reviewers.test.issues).to.have.length(1);
216
+ expect(reviewers.test.issues[0].issue).to.equal("important");
217
+ });
218
+ });
219
+
220
+ describe("generateReviewIndex", () => {
221
+ it("includes plan hash and verdict in frontmatter", () => {
222
+ const combined = createSampleCombinedResult();
223
+ const index = generateReviewIndex(combined);
224
+ expect(index).to.include("plan_hash: abc123def456");
225
+ expect(index).to.include("overall_verdict: pass");
226
+ });
227
+
228
+ it("includes iteration number when provided", () => {
229
+ const combined = createSampleCombinedResult();
230
+ const index = generateReviewIndex(combined, 2);
231
+ expect(index).to.include("iteration: 2");
232
+ });
233
+ });
234
+ });
@@ -0,0 +1,170 @@
1
+ import { expect } from "chai";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import {
5
+ getCcNativeState,
6
+ saveCcNativeState,
7
+ isPlanAlreadyReviewed,
8
+ wasPlanPreviouslyDenied,
9
+ markPlanReviewed,
10
+ wasQuestionsAsked,
11
+ markQuestionsAsked,
12
+ getStuckDetectionState,
13
+ updateStuckDetectionState,
14
+ } from "../cc-native-state.js";
15
+ import {
16
+ createTempDir,
17
+ cleanupTempDir,
18
+ setProjectRoot,
19
+ createSampleState,
20
+ createSampleIndex,
21
+ writeStateJson,
22
+ writeIndexJson,
23
+ } from "./helpers.js";
24
+
25
+ describe("cc-native-state", () => {
26
+ let tmpDir: string;
27
+ let restoreRoot: () => void;
28
+ const sessionId = "test-session-123";
29
+ const contextId = "test-context";
30
+
31
+ beforeEach(() => {
32
+ tmpDir = createTempDir("ccnstate-test-");
33
+ restoreRoot = setProjectRoot(tmpDir);
34
+
35
+ // Set up context with session binding
36
+ const state = createSampleState({
37
+ id: contextId,
38
+ session_ids: [sessionId],
39
+ last_session: { session_id: sessionId, saved_at: "2026-02-08T10:30:00.000", save_reason: "test" },
40
+ });
41
+ writeStateJson(tmpDir, contextId, state);
42
+ writeIndexJson(tmpDir, createSampleIndex(
43
+ { [contextId]: { summary: "Test", mode: "active", last_active: "2026-02-08T10:30:00.000" } },
44
+ { [sessionId]: contextId },
45
+ ));
46
+ });
47
+
48
+ afterEach(() => {
49
+ restoreRoot();
50
+ cleanupTempDir(tmpDir);
51
+ });
52
+
53
+ describe("getCcNativeState", () => {
54
+ it("returns null when no cc_native key", () => {
55
+ const result = getCcNativeState(sessionId, tmpDir);
56
+ expect(result).to.be.null;
57
+ });
58
+
59
+ it("returns cc_native object when present", () => {
60
+ // Manually add cc_native to state
61
+ const statePath = path.join(tmpDir, "_output", "contexts", contextId, "state.json");
62
+ const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
63
+ state.cc_native = { plan_review: { plan_hash: "abc", reviewed_at: "now", decision: "allow" } };
64
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
65
+
66
+ const result = getCcNativeState(sessionId, tmpDir);
67
+ expect(result).to.not.be.null;
68
+ expect(result!.plan_review?.plan_hash).to.equal("abc");
69
+ });
70
+
71
+ it("returns null for unknown session", () => {
72
+ expect(getCcNativeState("nonexistent", tmpDir)).to.be.null;
73
+ });
74
+ });
75
+
76
+ describe("isPlanAlreadyReviewed", () => {
77
+ it("returns false when no cc_native state", () => {
78
+ expect(isPlanAlreadyReviewed(sessionId, "hash123", tmpDir)).to.be.false;
79
+ });
80
+
81
+ it("returns true when plan hash matches", () => {
82
+ const statePath = path.join(tmpDir, "_output", "contexts", contextId, "state.json");
83
+ const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
84
+ state.cc_native = { plan_review: { plan_hash: "hash123", reviewed_at: "now", decision: "allow" } };
85
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
86
+
87
+ expect(isPlanAlreadyReviewed(sessionId, "hash123", tmpDir)).to.be.true;
88
+ });
89
+
90
+ it("returns false when plan hash does not match", () => {
91
+ const statePath = path.join(tmpDir, "_output", "contexts", contextId, "state.json");
92
+ const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
93
+ state.cc_native = { plan_review: { plan_hash: "other", reviewed_at: "now", decision: "allow" } };
94
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
95
+
96
+ expect(isPlanAlreadyReviewed(sessionId, "hash123", tmpDir)).to.be.false;
97
+ });
98
+ });
99
+
100
+ describe("wasPlanPreviouslyDenied", () => {
101
+ it("returns false when no review state", () => {
102
+ expect(wasPlanPreviouslyDenied(sessionId, "hash123", tmpDir)).to.be.false;
103
+ });
104
+
105
+ it("returns true for deny decision", () => {
106
+ const statePath = path.join(tmpDir, "_output", "contexts", contextId, "state.json");
107
+ const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
108
+ state.cc_native = { plan_review: { plan_hash: "hash123", reviewed_at: "now", decision: "deny" } };
109
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
110
+
111
+ expect(wasPlanPreviouslyDenied(sessionId, "hash123", tmpDir)).to.be.true;
112
+ });
113
+
114
+ it("returns true for hook_deny_iteration decision", () => {
115
+ const statePath = path.join(tmpDir, "_output", "contexts", contextId, "state.json");
116
+ const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
117
+ state.cc_native = { plan_review: { plan_hash: "hash123", reviewed_at: "now", decision: "hook_deny_iteration" } };
118
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
119
+
120
+ expect(wasPlanPreviouslyDenied(sessionId, "hash123", tmpDir)).to.be.true;
121
+ });
122
+
123
+ it("returns false for allow decision", () => {
124
+ const statePath = path.join(tmpDir, "_output", "contexts", contextId, "state.json");
125
+ const state = JSON.parse(fs.readFileSync(statePath, "utf-8"));
126
+ state.cc_native = { plan_review: { plan_hash: "abc123", reviewed_at: "now", decision: "allow" } };
127
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
128
+
129
+ expect(wasPlanPreviouslyDenied(sessionId, "hash123", tmpDir)).to.be.false;
130
+ });
131
+ });
132
+
133
+ describe("wasQuestionsAsked", () => {
134
+ it("returns false when no questions state", () => {
135
+ expect(wasQuestionsAsked(sessionId, tmpDir)).to.be.false;
136
+ });
137
+ });
138
+
139
+ describe("markQuestionsAsked", () => {
140
+ it("marks questions as asked", () => {
141
+ const result = markQuestionsAsked(sessionId, tmpDir);
142
+ expect(result).to.be.true;
143
+ expect(wasQuestionsAsked(sessionId, tmpDir)).to.be.true;
144
+ });
145
+ });
146
+
147
+ describe("getStuckDetectionState", () => {
148
+ it("returns null when no stuck detection state", () => {
149
+ expect(getStuckDetectionState(sessionId, tmpDir)).to.be.null;
150
+ });
151
+ });
152
+
153
+ describe("updateStuckDetectionState", () => {
154
+ it("saves and retrieves stuck detection state", () => {
155
+ const stuckState = {
156
+ error_hashes: ["hash1"],
157
+ file_edits: { "file.ts": 3 },
158
+ test_failures: 2,
159
+ tool_calls_since_suggestion: 5,
160
+ suggestion_count: 1,
161
+ };
162
+ const ok = updateStuckDetectionState(sessionId, tmpDir, stuckState as any);
163
+ expect(ok).to.be.true;
164
+
165
+ const retrieved = getStuckDetectionState(sessionId, tmpDir);
166
+ expect(retrieved).to.not.be.null;
167
+ expect(retrieved!.error_hashes).to.deep.equal(["hash1"]);
168
+ });
169
+ });
170
+ });
@@ -0,0 +1,73 @@
1
+ import { expect } from "chai";
2
+ import { parseCliOutput } from "../cli-output-parser.js";
3
+
4
+ describe("cli-output-parser", () => {
5
+ describe("parseCliOutput", () => {
6
+ it("extracts structured_output from root dict", () => {
7
+ const input = JSON.stringify({
8
+ structured_output: { verdict: "pass", summary: "ok" },
9
+ });
10
+ const result = parseCliOutput(input);
11
+ expect(result).to.deep.equal({ verdict: "pass", summary: "ok" });
12
+ });
13
+
14
+ it("extracts StructuredOutput from assistant message", () => {
15
+ const input = JSON.stringify({
16
+ type: "assistant",
17
+ message: {
18
+ content: [
19
+ { name: "StructuredOutput", input: { verdict: "warn", summary: "issues found" } },
20
+ ],
21
+ },
22
+ });
23
+ const result = parseCliOutput(input);
24
+ expect(result).to.deep.equal({ verdict: "warn", summary: "issues found" });
25
+ });
26
+
27
+ it("extracts StructuredOutput from event list", () => {
28
+ const input = JSON.stringify([
29
+ { type: "system" },
30
+ {
31
+ type: "assistant",
32
+ message: {
33
+ content: [
34
+ { name: "StructuredOutput", input: { verdict: "fail" } },
35
+ ],
36
+ },
37
+ },
38
+ ]);
39
+ const result = parseCliOutput(input);
40
+ expect(result).to.deep.equal({ verdict: "fail" });
41
+ });
42
+
43
+ it("falls back to heuristic for non-JSON input", () => {
44
+ const result = parseCliOutput('Some text {"verdict": "pass"} more text');
45
+ expect(result).to.deep.equal({ verdict: "pass" });
46
+ });
47
+
48
+ it("returns null for empty string", () => {
49
+ expect(parseCliOutput("")).to.be.null;
50
+ });
51
+
52
+ it("returns null for plain text without JSON", () => {
53
+ expect(parseCliOutput("just plain text")).to.be.null;
54
+ });
55
+
56
+ it("handles assistant message without StructuredOutput tool", () => {
57
+ const input = JSON.stringify({
58
+ type: "assistant",
59
+ message: {
60
+ content: [{ name: "SomeOtherTool", input: {} }],
61
+ },
62
+ });
63
+ // Falls through to heuristic, which will find the JSON object
64
+ const result = parseCliOutput(input);
65
+ expect(result).to.not.be.null;
66
+ });
67
+
68
+ it("handles empty event list", () => {
69
+ const result = parseCliOutput("[]");
70
+ expect(result).to.be.null;
71
+ });
72
+ });
73
+ });
@@ -0,0 +1,64 @@
1
+ import { expect } from "chai";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { loadConfig, getDisplaySettings } from "../config.js";
5
+ import { DEFAULT_DISPLAY } from "../types.js";
6
+ import { createTempDir, cleanupTempDir } from "./helpers.js";
7
+
8
+ describe("config", () => {
9
+ let tmpDir: string;
10
+
11
+ beforeEach(() => { tmpDir = createTempDir("config-test-"); });
12
+ afterEach(() => cleanupTempDir(tmpDir));
13
+
14
+ describe("loadConfig", () => {
15
+ it("returns empty object when config file missing", () => {
16
+ const result = loadConfig(tmpDir);
17
+ expect(result).to.deep.equal({});
18
+ });
19
+
20
+ it("loads valid config file", () => {
21
+ const configDir = path.join(tmpDir, "_cc-native");
22
+ fs.mkdirSync(configDir, { recursive: true });
23
+ fs.writeFileSync(
24
+ path.join(configDir, "cc-native.config.json"),
25
+ JSON.stringify({ orchestrator: { enabled: true, model: "haiku" } }),
26
+ );
27
+ const result = loadConfig(tmpDir);
28
+ expect(result).to.have.property("orchestrator");
29
+ });
30
+
31
+ it("returns empty object for malformed JSON", () => {
32
+ const configDir = path.join(tmpDir, "_cc-native");
33
+ fs.mkdirSync(configDir, { recursive: true });
34
+ fs.writeFileSync(
35
+ path.join(configDir, "cc-native.config.json"),
36
+ "not json{{{",
37
+ );
38
+ const result = loadConfig(tmpDir);
39
+ expect(result).to.deep.equal({});
40
+ });
41
+ });
42
+
43
+ describe("getDisplaySettings", () => {
44
+ it("returns defaults when no config", () => {
45
+ const result = getDisplaySettings({}, "agents");
46
+ expect(result).to.deep.equal(DEFAULT_DISPLAY);
47
+ });
48
+
49
+ it("merges root display overrides", () => {
50
+ const result = getDisplaySettings({ display: { maxIssues: 5 } }, "agents");
51
+ expect(result.maxIssues).to.equal(5);
52
+ expect(result.maxQuestions).to.equal(DEFAULT_DISPLAY.maxQuestions);
53
+ });
54
+
55
+ it("section-specific overrides take priority over root", () => {
56
+ const config = {
57
+ display: { maxIssues: 10 },
58
+ agents: { display: { maxIssues: 3 } },
59
+ };
60
+ const result = getDisplaySettings(config as any, "agents");
61
+ expect(result.maxIssues).to.equal(3);
62
+ });
63
+ });
64
+ });
@@ -0,0 +1,40 @@
1
+ import { expect } from "chai";
2
+ import * as path from "node:path";
3
+ import * as os from "node:os";
4
+ import { validatePlanPath, PLANS_DIR, MAX_PLAN_PATH_LENGTH } from "../constants.js";
5
+
6
+ describe("constants", () => {
7
+ describe("validatePlanPath", () => {
8
+ it("accepts valid plan path within PLANS_DIR", () => {
9
+ const validPath = path.join(PLANS_DIR, "my-plan.md");
10
+ const result = validatePlanPath(validPath);
11
+ expect(result).to.equal(path.resolve(validPath));
12
+ });
13
+
14
+ it("throws on empty path", () => {
15
+ expect(() => validatePlanPath("")).to.throw(/Invalid plan path length/);
16
+ });
17
+
18
+ it("throws on path exceeding max length", () => {
19
+ const longPath = path.join(PLANS_DIR, "a".repeat(MAX_PLAN_PATH_LENGTH));
20
+ expect(() => validatePlanPath(longPath)).to.throw(/Invalid plan path length/);
21
+ });
22
+
23
+ it("throws on null byte injection", () => {
24
+ expect(() => validatePlanPath(PLANS_DIR + "/test\x00.md")).to.throw(/Null bytes/);
25
+ });
26
+
27
+ it("throws on path outside PLANS_DIR", () => {
28
+ const outsidePath = path.join(os.tmpdir(), "evil-plan.md");
29
+ expect(() => validatePlanPath(outsidePath)).to.throw(/Path outside allowed directory/);
30
+ });
31
+
32
+ it("resolves to absolute path", () => {
33
+ // This test depends on CWD being inside PLANS_DIR, which typically won't be
34
+ // So we test with an absolute path
35
+ const absPath = path.join(PLANS_DIR, "test-plan.md");
36
+ const result = validatePlanPath(absPath);
37
+ expect(path.isAbsolute(result)).to.be.true;
38
+ });
39
+ });
40
+ });
@@ -0,0 +1,42 @@
1
+ import { expect } from "chai";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { getDebugDir, cleanupDebugFolder } from "../debug.js";
5
+ import { createTempDir, cleanupTempDir } from "./helpers.js";
6
+
7
+ describe("debug", () => {
8
+ let tmpDir: string;
9
+
10
+ beforeEach(() => { tmpDir = createTempDir("debug-test-"); });
11
+ afterEach(() => cleanupTempDir(tmpDir));
12
+
13
+ describe("getDebugDir", () => {
14
+ it("creates debug directory under context path", () => {
15
+ const result = getDebugDir(tmpDir);
16
+ expect(result).to.equal(path.join(tmpDir, "debug"));
17
+ expect(fs.existsSync(result)).to.be.true;
18
+ });
19
+
20
+ it("returns same path on subsequent calls", () => {
21
+ const first = getDebugDir(tmpDir);
22
+ const second = getDebugDir(tmpDir);
23
+ expect(first).to.equal(second);
24
+ });
25
+ });
26
+
27
+ describe("cleanupDebugFolder", () => {
28
+ it("removes existing debug directory", () => {
29
+ const debugDir = path.join(tmpDir, "debug");
30
+ fs.mkdirSync(debugDir, { recursive: true });
31
+ fs.writeFileSync(path.join(debugDir, "test.log"), "data");
32
+
33
+ cleanupDebugFolder(tmpDir);
34
+ expect(fs.existsSync(debugDir)).to.be.false;
35
+ });
36
+
37
+ it("does nothing when debug directory does not exist", () => {
38
+ // Should not throw
39
+ cleanupDebugFolder(tmpDir);
40
+ });
41
+ });
42
+ });
@@ -0,0 +1,58 @@
1
+ import { expect } from "chai";
2
+
3
+ describe("exports", () => {
4
+ it("all public functions are importable from index", async () => {
5
+ const mod = await import("../index.js");
6
+
7
+ // Verdict
8
+ expect(mod.worstVerdict).to.be.a("function");
9
+ expect(mod.computeReviewDecision).to.be.a("function");
10
+
11
+ // JSON parsing
12
+ expect(mod.parseJsonMaybe).to.be.a("function");
13
+ expect(mod.coerceToReview).to.be.a("function");
14
+
15
+ // CLI parsing
16
+ expect(mod.parseCliOutput).to.be.a("function");
17
+
18
+ // Config
19
+ expect(mod.loadConfig).to.be.a("function");
20
+ expect(mod.getDisplaySettings).to.be.a("function");
21
+
22
+ // Constants
23
+ expect(mod.validatePlanPath).to.be.a("function");
24
+ expect(mod.PLANS_DIR).to.be.a("string");
25
+
26
+ // State
27
+ expect(mod.getStateFilePath).to.be.a("function");
28
+ expect(mod.loadState).to.be.a("function");
29
+ expect(mod.getIterationState).to.be.a("function");
30
+ expect(mod.shouldContinueIterating).to.be.a("function");
31
+
32
+ // CC-native state
33
+ expect(mod.getCcNativeState).to.be.a("function");
34
+ expect(mod.isPlanAlreadyReviewed).to.be.a("function");
35
+ expect(mod.markPlanReviewed).to.be.a("function");
36
+
37
+ // Orchestrator
38
+ expect(mod.buildOrchestratorSchema).to.be.a("function");
39
+ expect(mod.runOrchestrator).to.be.a("function");
40
+
41
+ // Aggregate agents
42
+ expect(mod.aggregateAgents).to.be.a("function");
43
+ expect(mod.extractFrontmatter).to.be.a("function");
44
+
45
+ // Artifacts
46
+ expect(mod.formatReviewMarkdown).to.be.a("function");
47
+ expect(mod.buildCombinedJson).to.be.a("function");
48
+ expect(mod.buildInlineReviewSummary).to.be.a("function");
49
+
50
+ // Reviewers
51
+ expect(mod.AgentReviewer).to.be.a("function");
52
+
53
+ // Schemas
54
+ expect(mod.REVIEW_SCHEMA).to.be.an("object");
55
+ expect(mod.ORCHESTRATOR_SCHEMA).to.be.an("object");
56
+ expect(mod.DEFAULT_DISPLAY).to.be.an("object");
57
+ });
58
+ });