@karajan-family/code 4.21.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 (746) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +98 -0
  3. package/bin/karajan-mcp.js +2 -0
  4. package/bin/kj-rag-mcp.js +75 -0
  5. package/bin/kj-tail +361 -0
  6. package/bin/kj.js +2 -0
  7. package/docs/README.es.md +80 -0
  8. package/docs/karajan-code-logo-small.png +0 -0
  9. package/library/logical-clocks-lamport.md +40 -0
  10. package/package.json +140 -0
  11. package/packages/ai-trash/README.md +37 -0
  12. package/packages/ai-trash/bin/kj-trash.js +10 -0
  13. package/packages/ai-trash/package.json +43 -0
  14. package/packages/ai-trash/src/cli.js +200 -0
  15. package/packages/ai-trash/src/destructive-parser.js +74 -0
  16. package/packages/ai-trash/src/git-snapshot.js +128 -0
  17. package/packages/ai-trash/src/hook.js +137 -0
  18. package/packages/ai-trash/src/index.js +14 -0
  19. package/packages/ai-trash/src/install.js +73 -0
  20. package/packages/ai-trash/src/logger.js +60 -0
  21. package/packages/ai-trash/src/manifest.js +91 -0
  22. package/packages/ai-trash/src/permissions.js +26 -0
  23. package/packages/ai-trash/src/snapshot.js +66 -0
  24. package/packages/ai-trash/src/ulid.js +66 -0
  25. package/packages/hu-board/README.md +69 -0
  26. package/packages/hu-board/package.json +28 -0
  27. package/packages/hu-board/public/app.js +259 -0
  28. package/packages/hu-board/public/index.html +77 -0
  29. package/packages/hu-board/public/pipeline.css +132 -0
  30. package/packages/hu-board/public/pipeline.html +48 -0
  31. package/packages/hu-board/public/pipeline.js +200 -0
  32. package/packages/hu-board/public/rag.html +21 -0
  33. package/packages/hu-board/public/rag.js +39 -0
  34. package/packages/hu-board/public/styles.css +973 -0
  35. package/packages/hu-board/public/utils/api.js +139 -0
  36. package/packages/hu-board/public/utils/board-view.js +473 -0
  37. package/packages/hu-board/public/utils/command-launcher.js +213 -0
  38. package/packages/hu-board/public/utils/config-editor.js +181 -0
  39. package/packages/hu-board/public/utils/dashboard-view.js +103 -0
  40. package/packages/hu-board/public/utils/formatters.js +300 -0
  41. package/packages/hu-board/public/utils/graph-view.js +216 -0
  42. package/packages/hu-board/public/utils/hu-actions.js +224 -0
  43. package/packages/hu-board/public/utils/init-listeners.js +180 -0
  44. package/packages/hu-board/public/utils/log-panel.js +222 -0
  45. package/packages/hu-board/public/utils/modals.js +309 -0
  46. package/packages/hu-board/public/utils/plan-rollup-view.js +53 -0
  47. package/packages/hu-board/public/utils/preflight-view.js +89 -0
  48. package/packages/hu-board/public/utils/project-actions.js +143 -0
  49. package/packages/hu-board/public/utils/project-picker-view.js +139 -0
  50. package/packages/hu-board/public/utils/run-launcher.js +169 -0
  51. package/packages/hu-board/public/utils/server-push.js +252 -0
  52. package/packages/hu-board/public/utils/sessions-view.js +199 -0
  53. package/packages/hu-board/public/utils/story-detail-view.js +324 -0
  54. package/packages/hu-board/public/utils/story-edit-form.js +271 -0
  55. package/packages/hu-board/public/wiki.html +32 -0
  56. package/packages/hu-board/public/wiki.js +53 -0
  57. package/packages/hu-board/src/auth.js +92 -0
  58. package/packages/hu-board/src/boot-info.js +16 -0
  59. package/packages/hu-board/src/cleanup-zombies.js +145 -0
  60. package/packages/hu-board/src/command-runner.js +133 -0
  61. package/packages/hu-board/src/config-yaml.js +531 -0
  62. package/packages/hu-board/src/db.js +963 -0
  63. package/packages/hu-board/src/ephemeral-cleaner.js +196 -0
  64. package/packages/hu-board/src/event-bus.js +58 -0
  65. package/packages/hu-board/src/format.js +207 -0
  66. package/packages/hu-board/src/hu-zombie-reaper.js +103 -0
  67. package/packages/hu-board/src/journal-parser.js +180 -0
  68. package/packages/hu-board/src/plan-mutations.js +424 -0
  69. package/packages/hu-board/src/preflight.js +286 -0
  70. package/packages/hu-board/src/routes/api.js +1374 -0
  71. package/packages/hu-board/src/routes/pipeline.js +45 -0
  72. package/packages/hu-board/src/routes/rag.js +42 -0
  73. package/packages/hu-board/src/routes/wiki.js +43 -0
  74. package/packages/hu-board/src/run-tracker.js +121 -0
  75. package/packages/hu-board/src/server.js +438 -0
  76. package/packages/hu-board/src/sync.js +732 -0
  77. package/packages/hu-board/src/token-store.js +56 -0
  78. package/packages/hu-board/src/zombie-reaper.js +206 -0
  79. package/scripts/ai-attribution-guard.yml +84 -0
  80. package/scripts/audit-test-diet.mjs +151 -0
  81. package/scripts/build-sea.mjs +150 -0
  82. package/scripts/diet-baseline.mjs +170 -0
  83. package/scripts/dual-publish.mjs +67 -0
  84. package/scripts/esbuild-sea.config.mjs +273 -0
  85. package/scripts/git-hooks/post-merge +18 -0
  86. package/scripts/install-binary.ps1 +174 -0
  87. package/scripts/install-binary.sh +159 -0
  88. package/scripts/install-guard-all-repos.sh +85 -0
  89. package/scripts/install-kj.sh +193 -0
  90. package/scripts/install.js +901 -0
  91. package/scripts/install.sh +7 -0
  92. package/scripts/postinstall.js +117 -0
  93. package/scripts/protect-all-repos.sh +88 -0
  94. package/scripts/quickstart-gate.mjs +97 -0
  95. package/scripts/regen-arch-stats.sh +71 -0
  96. package/scripts/setup-multi-instance.sh +150 -0
  97. package/scripts/verify-pack.mjs +278 -0
  98. package/src/activity-log.js +59 -0
  99. package/src/agents/agy-agent.js +62 -0
  100. package/src/agents/aider-agent.js +78 -0
  101. package/src/agents/availability.js +52 -0
  102. package/src/agents/base-agent.js +134 -0
  103. package/src/agents/claude-agent.js +413 -0
  104. package/src/agents/codex-agent.js +112 -0
  105. package/src/agents/copilot-agent.js +65 -0
  106. package/src/agents/gemini-agent.js +85 -0
  107. package/src/agents/host-agent.js +38 -0
  108. package/src/agents/index.js +59 -0
  109. package/src/agents/kimi-agent.js +45 -0
  110. package/src/agents/model-registry.js +137 -0
  111. package/src/agents/opencode-agent.js +72 -0
  112. package/src/agents/qwen-agent.js +20 -0
  113. package/src/agents/resolve-bin.js +73 -0
  114. package/src/audit/agent-readiness.js +259 -0
  115. package/src/audit/ai-slop-findings.js +102 -0
  116. package/src/audit/audit-fallback.js +66 -0
  117. package/src/audit/audit-history-display.js +61 -0
  118. package/src/audit/audit-history.js +102 -0
  119. package/src/audit/basal-cost.js +281 -0
  120. package/src/audit/circular-deps.js +144 -0
  121. package/src/audit/dead-exports.js +186 -0
  122. package/src/audit/deterministic-summary.js +327 -0
  123. package/src/audit/harness-scorecard.js +100 -0
  124. package/src/audit/harness-section.js +81 -0
  125. package/src/audit/infra-findings.js +100 -0
  126. package/src/audit/injection-findings.js +114 -0
  127. package/src/audit/issue-filter.js +133 -0
  128. package/src/audit/osv-findings.js +167 -0
  129. package/src/audit/plan-adherence.js +224 -0
  130. package/src/audit/semgrep-findings.js +129 -0
  131. package/src/audit/sonar-findings.js +93 -0
  132. package/src/audit/webperf-input.js +133 -0
  133. package/src/autonomy/arbiter-role.js +71 -0
  134. package/src/autonomy/arbiter.js +22 -0
  135. package/src/autonomy/decider.js +18 -0
  136. package/src/autonomy/decision-resolver.js +58 -0
  137. package/src/autonomy/outcome-report.js +55 -0
  138. package/src/autonomy/policy.js +41 -0
  139. package/src/autonomy/stage-ask.js +30 -0
  140. package/src/bootstrap.js +276 -0
  141. package/src/brain/agent-error-classifier.js +116 -0
  142. package/src/brain/decision-tracker.js +125 -0
  143. package/src/brain/decisor.js +243 -0
  144. package/src/brain/solomon-consult.js +171 -0
  145. package/src/brain/standby-scheduler.js +8 -0
  146. package/src/brain/standby-store.js +12 -0
  147. package/src/brain/with-brain-recovery.js +235 -0
  148. package/src/budget/comparison.js +96 -0
  149. package/src/canvas/parse-md.js +238 -0
  150. package/src/canvas/schema.js +101 -0
  151. package/src/canvas/to-flat.js +85 -0
  152. package/src/canvas/validate.js +163 -0
  153. package/src/checks/ai-surface.js +79 -0
  154. package/src/checks/ai-trash.js +34 -0
  155. package/src/checks/binaries.js +207 -0
  156. package/src/checks/ci.js +105 -0
  157. package/src/checks/config-files.js +217 -0
  158. package/src/checks/dir-setup.js +103 -0
  159. package/src/checks/guarantee-level.js +38 -0
  160. package/src/checks/hardware.js +150 -0
  161. package/src/checks/harness-scorecard.js +41 -0
  162. package/src/checks/mcp-health.js +169 -0
  163. package/src/checks/method.js +73 -0
  164. package/src/checks/native-build.js +67 -0
  165. package/src/checks/node.js +70 -0
  166. package/src/checks/ollama.js +41 -0
  167. package/src/checks/orphans.js +77 -0
  168. package/src/checks/ports.js +188 -0
  169. package/src/checks/project-checks.js +245 -0
  170. package/src/checks/qmd.js +41 -0
  171. package/src/checks/rag-hooks.js +54 -0
  172. package/src/checks/release-check.js +102 -0
  173. package/src/checks/rtk.js +36 -0
  174. package/src/checks/runner.js +326 -0
  175. package/src/checks/skills.js +53 -0
  176. package/src/checks/sonar.js +67 -0
  177. package/src/checks/squeezr.js +36 -0
  178. package/src/checks/system.js +53 -0
  179. package/src/checks/tokens.js +172 -0
  180. package/src/checks/types.js +103 -0
  181. package/src/ci/dispatch.js +99 -0
  182. package/src/ci/index.js +3 -0
  183. package/src/ci/pr-diff.js +26 -0
  184. package/src/ci/repo.js +45 -0
  185. package/src/cli/_shared.js +30 -0
  186. package/src/cli/advanced-commands.js +61 -0
  187. package/src/cli/register-meta.js +772 -0
  188. package/src/cli/register-pipeline.js +335 -0
  189. package/src/cli/register-plan.js +224 -0
  190. package/src/cli/register-roles-skills.js +54 -0
  191. package/src/cli/register-sonar.js +28 -0
  192. package/src/cli/register-standby.js +26 -0
  193. package/src/cli.js +155 -0
  194. package/src/commands/advanced.js +31 -0
  195. package/src/commands/agent-run.js +63 -0
  196. package/src/commands/agents.js +105 -0
  197. package/src/commands/architect.js +123 -0
  198. package/src/commands/audit.js +430 -0
  199. package/src/commands/autorun.js +49 -0
  200. package/src/commands/board.js +458 -0
  201. package/src/commands/check.js +40 -0
  202. package/src/commands/clean.js +145 -0
  203. package/src/commands/code.js +45 -0
  204. package/src/commands/config.js +74 -0
  205. package/src/commands/discover.js +105 -0
  206. package/src/commands/doctor.js +251 -0
  207. package/src/commands/env.js +207 -0
  208. package/src/commands/harden.js +203 -0
  209. package/src/commands/hu.js +210 -0
  210. package/src/commands/identity.js +60 -0
  211. package/src/commands/init.js +950 -0
  212. package/src/commands/install-tools.js +432 -0
  213. package/src/commands/mutate.js +94 -0
  214. package/src/commands/ollama.js +44 -0
  215. package/src/commands/onboard.js +45 -0
  216. package/src/commands/plan/_shared.js +55 -0
  217. package/src/commands/plan/add-hu.js +23 -0
  218. package/src/commands/plan/delete.js +9 -0
  219. package/src/commands/plan/fix.js +99 -0
  220. package/src/commands/plan/generate.js +532 -0
  221. package/src/commands/plan/index.js +13 -0
  222. package/src/commands/plan/list.js +21 -0
  223. package/src/commands/plan/migrate-result.js +41 -0
  224. package/src/commands/plan/ready.js +46 -0
  225. package/src/commands/plan/remove-hu.js +17 -0
  226. package/src/commands/plan/share.js +85 -0
  227. package/src/commands/plan/show.js +81 -0
  228. package/src/commands/plan/unshare.js +41 -0
  229. package/src/commands/plan/validate.js +20 -0
  230. package/src/commands/plan.js +17 -0
  231. package/src/commands/policy.js +164 -0
  232. package/src/commands/privacy.js +45 -0
  233. package/src/commands/qmd.js +86 -0
  234. package/src/commands/rag-mcp.js +18 -0
  235. package/src/commands/rag.js +173 -0
  236. package/src/commands/report-issue.js +77 -0
  237. package/src/commands/report.js +469 -0
  238. package/src/commands/researcher.js +54 -0
  239. package/src/commands/resume.js +68 -0
  240. package/src/commands/review-gate.js +355 -0
  241. package/src/commands/review.js +89 -0
  242. package/src/commands/roles.js +116 -0
  243. package/src/commands/run.js +185 -0
  244. package/src/commands/scan.js +18 -0
  245. package/src/commands/skills.js +86 -0
  246. package/src/commands/sonar.js +53 -0
  247. package/src/commands/standby.js +117 -0
  248. package/src/commands/start.js +121 -0
  249. package/src/commands/status.js +36 -0
  250. package/src/commands/sync.js +103 -0
  251. package/src/commands/telemetry.js +70 -0
  252. package/src/commands/tournament.js +85 -0
  253. package/src/commands/triage.js +78 -0
  254. package/src/commands/undo.js +62 -0
  255. package/src/commands/watch.js +46 -0
  256. package/src/commands/webperf.js +162 -0
  257. package/src/commands/worktree.js +76 -0
  258. package/src/config/defaults.js +270 -0
  259. package/src/config/loader.js +204 -0
  260. package/src/config/overrides.js +220 -0
  261. package/src/config/role-resolver.js +171 -0
  262. package/src/config/schema.js +299 -0
  263. package/src/config/test-harness.js +78 -0
  264. package/src/config.js +34 -0
  265. package/src/domains/domain-loader.js +245 -0
  266. package/src/domains/domain-registry.js +140 -0
  267. package/src/domains/domain-synthesizer.js +129 -0
  268. package/src/environment/adr.js +45 -0
  269. package/src/environment/board-access.js +97 -0
  270. package/src/environment/board-select.js +59 -0
  271. package/src/environment/briefs.js +129 -0
  272. package/src/environment/issue-report.js +72 -0
  273. package/src/environment/mcp-wiring.js +44 -0
  274. package/src/environment/playbook.js +127 -0
  275. package/src/git/automation.js +334 -0
  276. package/src/git/hu-automation.js +171 -0
  277. package/src/git/hu-snapshot.js +10 -0
  278. package/src/golden/asserter.js +92 -0
  279. package/src/golden/loader.js +52 -0
  280. package/src/golden/runner.js +92 -0
  281. package/src/golden/schema.js +41 -0
  282. package/src/guards/intent-guard.js +161 -0
  283. package/src/guards/output-guard.js +149 -0
  284. package/src/guards/perf-guard.js +126 -0
  285. package/src/guards/policy-guard.js +90 -0
  286. package/src/guards/policy-resolver.js +85 -0
  287. package/src/guards/secret-redactor.js +71 -0
  288. package/src/harden/advisory.js +203 -0
  289. package/src/harden/alternatives.js +50 -0
  290. package/src/harden/check.js +81 -0
  291. package/src/harden/config-engine.js +128 -0
  292. package/src/harden/config-templates.js +122 -0
  293. package/src/harden/guidelines-engine.js +48 -0
  294. package/src/harden/guidelines-templates.js +36 -0
  295. package/src/harden/harden-engine.js +80 -0
  296. package/src/harden/harness-hooks.js +107 -0
  297. package/src/harden/hook-commands.js +25 -0
  298. package/src/harden/hook-templates.js +183 -0
  299. package/src/harden/interactive.js +76 -0
  300. package/src/harden/sentinel-hooks.js +721 -0
  301. package/src/harden/stack-roots.js +105 -0
  302. package/src/harden/test-on-push.js +38 -0
  303. package/src/harden/workflow-engine.js +116 -0
  304. package/src/harden/workflow-templates.js +285 -0
  305. package/src/hu/acceptance-runner.js +138 -0
  306. package/src/hu/auto-generator.js +358 -0
  307. package/src/hu/graph.js +71 -0
  308. package/src/hu/lazy-planner.js +109 -0
  309. package/src/hu/model-router.js +108 -0
  310. package/src/hu/parallel-executor.js +94 -0
  311. package/src/hu/split-validator.js +143 -0
  312. package/src/hu/splitting-detector.js +158 -0
  313. package/src/hu/splitting-generator.js +175 -0
  314. package/src/hu/store.js +392 -0
  315. package/src/hu/worktree-bootstrap.js +59 -0
  316. package/src/identity/bootstrap.js +48 -0
  317. package/src/identity/compare.js +38 -0
  318. package/src/identity/detect.js +51 -0
  319. package/src/identity/store.js +66 -0
  320. package/src/infrastructure/command-runner.js +44 -0
  321. package/src/infrastructure/environment.js +38 -0
  322. package/src/infrastructure/file-system-service.js +63 -0
  323. package/src/infrastructure/mocks.js +182 -0
  324. package/src/lang/chunk-go.js +94 -0
  325. package/src/lang/chunk-java.js +90 -0
  326. package/src/lang/chunk-python.js +88 -0
  327. package/src/lang/chunk-rust.js +102 -0
  328. package/src/lang/go.js +14 -0
  329. package/src/lang/java.js +16 -0
  330. package/src/lang/js.js +8 -0
  331. package/src/lang/python.js +14 -0
  332. package/src/lang/registry.js +79 -0
  333. package/src/lang/rust.js +14 -0
  334. package/src/lang/tree-sitter-loader.js +45 -0
  335. package/src/mcp/direct-role-runner.js +112 -0
  336. package/src/mcp/error-classifiers.js +66 -0
  337. package/src/mcp/handlers/direct-handlers.js +486 -0
  338. package/src/mcp/handlers/hu-handlers.js +93 -0
  339. package/src/mcp/handlers/management-handlers.js +265 -0
  340. package/src/mcp/handlers/rag-handler.js +52 -0
  341. package/src/mcp/handlers/run-handler.js +313 -0
  342. package/src/mcp/orphan-guard.js +131 -0
  343. package/src/mcp/preflight.js +47 -0
  344. package/src/mcp/progress.js +149 -0
  345. package/src/mcp/response-compressor.js +81 -0
  346. package/src/mcp/run-kj.js +135 -0
  347. package/src/mcp/server-handlers.js +79 -0
  348. package/src/mcp/server.js +66 -0
  349. package/src/mcp/shared-helpers.js +297 -0
  350. package/src/mcp/sovereignty-guard.js +112 -0
  351. package/src/mcp/suggest-handler.js +92 -0
  352. package/src/mcp/tool-arg-normalizers.js +16 -0
  353. package/src/mcp/tools.js +432 -0
  354. package/src/mutate/diff-scope.js +105 -0
  355. package/src/mutate/reviewer-signal.js +76 -0
  356. package/src/mutate/runner.js +72 -0
  357. package/src/mutate/tool-registry.js +90 -0
  358. package/src/onboarder/cache.js +24 -0
  359. package/src/onboarder/collectors/framework-multilang.js +64 -0
  360. package/src/onboarder/collectors/index.js +136 -0
  361. package/src/orchestrator/agent-fallback.js +81 -0
  362. package/src/orchestrator/brain-coordinator.js +186 -0
  363. package/src/orchestrator/ci-integration.js +139 -0
  364. package/src/orchestrator/config-init.js +510 -0
  365. package/src/orchestrator/direct-actions.js +217 -0
  366. package/src/orchestrator/drivers/error-recovery.js +287 -0
  367. package/src/orchestrator/drivers/init-context.js +227 -0
  368. package/src/orchestrator/drivers/iteration-loop.js +380 -0
  369. package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +69 -0
  370. package/src/orchestrator/drivers/iteration-phases/guards.js +84 -0
  371. package/src/orchestrator/drivers/iteration-phases/handle-approved.js +29 -0
  372. package/src/orchestrator/drivers/iteration-phases/quality-gates.js +114 -0
  373. package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +60 -0
  374. package/src/orchestrator/drivers/post-loop.js +383 -0
  375. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +136 -0
  376. package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +47 -0
  377. package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +84 -0
  378. package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +391 -0
  379. package/src/orchestrator/drivers/pre-loop.js +507 -0
  380. package/src/orchestrator/drivers/run-hu-batch.js +427 -0
  381. package/src/orchestrator/feedback-enrichment.js +140 -0
  382. package/src/orchestrator/feedback-queue.js +151 -0
  383. package/src/orchestrator/flow-control.js +170 -0
  384. package/src/orchestrator/flow-runner.js +364 -0
  385. package/src/orchestrator/fs-leak-detector.js +210 -0
  386. package/src/orchestrator/hu-scheduler.js +114 -0
  387. package/src/orchestrator/hu-sub-pipeline.js +616 -0
  388. package/src/orchestrator/integrations.js +81 -0
  389. package/src/orchestrator/iteration-gate.js +73 -0
  390. package/src/orchestrator/iteration-stages.js +9 -0
  391. package/src/orchestrator/parallel-limiter.js +74 -0
  392. package/src/orchestrator/pipeline-context.js +72 -0
  393. package/src/orchestrator/post-loop-stages.js +468 -0
  394. package/src/orchestrator/pre-loop-stages.js +11 -0
  395. package/src/orchestrator/preflight-checks.js +462 -0
  396. package/src/orchestrator/repair/repair-detector.js +117 -0
  397. package/src/orchestrator/repair/repair-runner.js +142 -0
  398. package/src/orchestrator/reviewer-fallback.js +45 -0
  399. package/src/orchestrator/role-output-compressor.js +189 -0
  400. package/src/orchestrator/session-journal.js +308 -0
  401. package/src/orchestrator/solomon-escalation.js +305 -0
  402. package/src/orchestrator/solomon-rules.js +212 -0
  403. package/src/orchestrator/stages/architect-stage.js +172 -0
  404. package/src/orchestrator/stages/coder-stage.js +480 -0
  405. package/src/orchestrator/stages/domain-curator-stage.js +82 -0
  406. package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +127 -0
  407. package/src/orchestrator/stages/hu-reviewer-stage.js +394 -0
  408. package/src/orchestrator/stages/perf-stage.js +140 -0
  409. package/src/orchestrator/stages/planner-stage.js +85 -0
  410. package/src/orchestrator/stages/rag-context-stage.js +77 -0
  411. package/src/orchestrator/stages/rag-preload-decisor.js +58 -0
  412. package/src/orchestrator/stages/research-stage.js +69 -0
  413. package/src/orchestrator/stages/reviewer-stage.js +422 -0
  414. package/src/orchestrator/stages/sonar-stage.js +421 -0
  415. package/src/orchestrator/stages/stage-classes.js +84 -0
  416. package/src/orchestrator/stages/stage-executor.js +155 -0
  417. package/src/orchestrator/stages/tdd-discipline-stage.js +56 -0
  418. package/src/orchestrator/stages/tool-judge-stage.js +53 -0
  419. package/src/orchestrator/stages/triage-stage.js +172 -0
  420. package/src/orchestrator/standby.js +71 -0
  421. package/src/orchestrator/verification-gate.js +183 -0
  422. package/src/orchestrator.js +22 -0
  423. package/src/plan/adr-generator.js +170 -0
  424. package/src/plan/adr-loader.js +60 -0
  425. package/src/plan/plan-executor.js +100 -0
  426. package/src/plan/plan-fixer.js +192 -0
  427. package/src/plan/plan-hu-ops.js +16 -0
  428. package/src/plan/plan-id.js +4 -0
  429. package/src/plan/plan-migrate-result.js +24 -0
  430. package/src/plan/plan-reviewer.js +236 -0
  431. package/src/plan/plan-schema.js +334 -0
  432. package/src/plan/plan-store.js +260 -0
  433. package/src/plan/plan-structural-pass.js +122 -0
  434. package/src/plan/plan-validation.js +4 -0
  435. package/src/plan/preflight-hu.js +105 -0
  436. package/src/plan/spec-detector.js +61 -0
  437. package/src/plan/tests-synthesizer.js +131 -0
  438. package/src/planning-game/adapter.js +108 -0
  439. package/src/planning-game/architect-adrs.js +45 -0
  440. package/src/planning-game/client.js +108 -0
  441. package/src/planning-game/decomposition.js +87 -0
  442. package/src/planning-game/pipeline-adapter.js +251 -0
  443. package/src/plugins/loader.js +67 -0
  444. package/src/policy/add.js +111 -0
  445. package/src/policy/decisions.js +42 -0
  446. package/src/policy/engine.js +82 -0
  447. package/src/policy/exceptions.js +60 -0
  448. package/src/privacy/onboarding.js +35 -0
  449. package/src/privacy/scan.js +120 -0
  450. package/src/prompts/arbiter.js +38 -0
  451. package/src/prompts/architect.js +103 -0
  452. package/src/prompts/audit.js +474 -0
  453. package/src/prompts/coder.js +287 -0
  454. package/src/prompts/diff-clip.js +27 -0
  455. package/src/prompts/discover.js +222 -0
  456. package/src/prompts/hu-reviewer.js +219 -0
  457. package/src/prompts/planner.js +312 -0
  458. package/src/prompts/prompt-layout.js +80 -0
  459. package/src/prompts/prompt-resolver.js +120 -0
  460. package/src/prompts/reviewer.js +75 -0
  461. package/src/prompts/rtk-snippet.js +25 -0
  462. package/src/prompts/spec-reviewer.js +66 -0
  463. package/src/prompts/split-signal.js +82 -0
  464. package/src/prompts/start-decision.js +52 -0
  465. package/src/prompts/tool-correctness-judge.js +31 -0
  466. package/src/prompts/triage.js +57 -0
  467. package/src/rag/auto-update.js +72 -0
  468. package/src/rag/chunker-ast.js +56 -0
  469. package/src/rag/chunker.js +132 -0
  470. package/src/rag/embedder.js +2 -0
  471. package/src/rag/embedders/_cloud-base.js +2 -0
  472. package/src/rag/embedders/cohere.js +2 -0
  473. package/src/rag/embedders/factory.js +2 -0
  474. package/src/rag/embedders/mistral.js +2 -0
  475. package/src/rag/embedders/onnx.js +2 -0
  476. package/src/rag/embedders/openai.js +2 -0
  477. package/src/rag/embedders/voyage.js +2 -0
  478. package/src/rag/eval.js +61 -0
  479. package/src/rag/governed-embedder.js +39 -0
  480. package/src/rag/indexer.js +199 -0
  481. package/src/rag/library.js +62 -0
  482. package/src/rag/ollama-capability.js +59 -0
  483. package/src/rag/ollama-manager.js +98 -0
  484. package/src/rag/onnx-fallback.js +69 -0
  485. package/src/rag/rerank.js +4 -0
  486. package/src/rag/retriever.js +2 -0
  487. package/src/rag/vec-store.js +17 -0
  488. package/src/rag/watcher.js +62 -0
  489. package/src/rag/where-parser.js +4 -0
  490. package/src/repeat-detector.js +88 -0
  491. package/src/review/card-first.js +99 -0
  492. package/src/review/card-verify.js +83 -0
  493. package/src/review/diff-generator.js +112 -0
  494. package/src/review/gate-gitignore.js +77 -0
  495. package/src/review/git-stash-helper.js +104 -0
  496. package/src/review/mutation-pregate.js +48 -0
  497. package/src/review/one-shot-review.js +122 -0
  498. package/src/review/parser.js +80 -0
  499. package/src/review/policy-gate.js +26 -0
  500. package/src/review/profiles.js +66 -0
  501. package/src/review/reviewer-fallback.js +125 -0
  502. package/src/review/schema.js +31 -0
  503. package/src/review/scope-filter.js +152 -0
  504. package/src/review/snapshot-diff.js +122 -0
  505. package/src/review/solomon-arbitration.js +113 -0
  506. package/src/review/sonar-pregate.js +63 -0
  507. package/src/review/tdd-discipline.js +90 -0
  508. package/src/review/tdd-policy.js +69 -0
  509. package/src/review/tests-with-code.js +33 -0
  510. package/src/review/verdict-store.js +87 -0
  511. package/src/review/workspace.js +21 -0
  512. package/src/roles/agent-role.js +194 -0
  513. package/src/roles/architect-role.js +77 -0
  514. package/src/roles/audit-role.js +258 -0
  515. package/src/roles/base-role.js +165 -0
  516. package/src/roles/coder-role.js +107 -0
  517. package/src/roles/commiter-role.js +110 -0
  518. package/src/roles/discover-role.js +81 -0
  519. package/src/roles/domain-curator-role.js +141 -0
  520. package/src/roles/hu-reviewer-role.js +64 -0
  521. package/src/roles/impeccable-role.js +85 -0
  522. package/src/roles/index.js +18 -0
  523. package/src/roles/karajan-brain-role.js +134 -0
  524. package/src/roles/onboarder-role.js +61 -0
  525. package/src/roles/perf-role.js +122 -0
  526. package/src/roles/planner-role.js +151 -0
  527. package/src/roles/refactorer-role.js +30 -0
  528. package/src/roles/repairer-role.js +181 -0
  529. package/src/roles/researcher-role.js +70 -0
  530. package/src/roles/reviewer-role.js +104 -0
  531. package/src/roles/security-role.js +73 -0
  532. package/src/roles/solomon-role.js +265 -0
  533. package/src/roles/sonar-role.js +70 -0
  534. package/src/roles/spec-reviewer-role.js +106 -0
  535. package/src/roles/tester-role.js +235 -0
  536. package/src/roles/tool-correctness-judge-role.js +78 -0
  537. package/src/roles/triage-role.js +99 -0
  538. package/src/session/journal/decisions-writer.js +200 -0
  539. package/src/session/journal/iteration-logger.js +194 -0
  540. package/src/session/journal/summary-writer.js +320 -0
  541. package/src/session/journal/tree-writer.js +164 -0
  542. package/src/session/journal/write-all.js +89 -0
  543. package/src/session/mutators.js +339 -0
  544. package/src/session/runtime-overrides.js +59 -0
  545. package/src/session/store.js +106 -0
  546. package/src/session-cleanup.js +116 -0
  547. package/src/skills/addyosmani-catalog.js +315 -0
  548. package/src/skills/addyosmani-role-map.js +139 -0
  549. package/src/skills/openskills-client.js +157 -0
  550. package/src/skills/semantic-detector.js +167 -0
  551. package/src/skills/skill-detector.js +385 -0
  552. package/src/skills/skill-loader.js +219 -0
  553. package/src/skills/skills-cache.js +128 -0
  554. package/src/sonar/api.js +128 -0
  555. package/src/sonar/cloud-scanner.js +78 -0
  556. package/src/sonar/config-resolver.js +88 -0
  557. package/src/sonar/credentials.js +60 -0
  558. package/src/sonar/discovery.js +124 -0
  559. package/src/sonar/enforcer.js +19 -0
  560. package/src/sonar/issue-filter.js +12 -0
  561. package/src/sonar/manager.js +181 -0
  562. package/src/sonar/project-key.js +120 -0
  563. package/src/sonar/scanner.js +307 -0
  564. package/src/sonar/token-bootstrap.js +205 -0
  565. package/src/sonar/token-recovery.js +67 -0
  566. package/src/spec-review/refine-loop.js +58 -0
  567. package/src/spec-review/run-spec-review.js +119 -0
  568. package/src/start/assessment.js +74 -0
  569. package/src/start/maturity.js +73 -0
  570. package/src/start/start-decider-role.js +79 -0
  571. package/src/start/sweep.js +157 -0
  572. package/src/sync/apply-canvas-patch.js +55 -0
  573. package/src/sync/detect-drift.js +113 -0
  574. package/src/tournament/crown.js +88 -0
  575. package/src/tournament/judge.js +150 -0
  576. package/src/tournament/run.js +142 -0
  577. package/src/tournament/scoreboard.js +124 -0
  578. package/src/tracker-bootstrap.js +44 -0
  579. package/src/types/agent.js +55 -0
  580. package/src/types/config.js +114 -0
  581. package/src/types/hu.js +47 -0
  582. package/src/types/index.js +38 -0
  583. package/src/types/policy.js +43 -0
  584. package/src/types/session.js +75 -0
  585. package/src/types/solomon.js +87 -0
  586. package/src/types/stage.js +68 -0
  587. package/src/utils/agent-detect.js +93 -0
  588. package/src/utils/ai-trash.js +48 -0
  589. package/src/utils/async-lock.js +31 -0
  590. package/src/utils/atomic-write.js +6 -0
  591. package/src/utils/banner.js +66 -0
  592. package/src/utils/binary-sources.js +70 -0
  593. package/src/utils/board-prompt-bridge.js +108 -0
  594. package/src/utils/budget.js +229 -0
  595. package/src/utils/cli-ask-question.js +93 -0
  596. package/src/utils/cli-progress.js +220 -0
  597. package/src/utils/cli-run-log.js +83 -0
  598. package/src/utils/cwd-confirm.js +39 -0
  599. package/src/utils/derive-project-name-from-cwd.js +119 -0
  600. package/src/utils/display/event-handlers.js +403 -0
  601. package/src/utils/display/formatters.js +132 -0
  602. package/src/utils/display/header.js +47 -0
  603. package/src/utils/display/resume-hint.js +41 -0
  604. package/src/utils/display/session-summary.js +118 -0
  605. package/src/utils/display/solomon.js +42 -0
  606. package/src/utils/display/spec-findings.js +44 -0
  607. package/src/utils/doc-links.js +29 -0
  608. package/src/utils/docker-install.js +34 -0
  609. package/src/utils/escape-regexp.js +15 -0
  610. package/src/utils/events.js +35 -0
  611. package/src/utils/fs.js +19 -0
  612. package/src/utils/garbage-collector.js +481 -0
  613. package/src/utils/git.js +279 -0
  614. package/src/utils/home-migration.js +87 -0
  615. package/src/utils/injection-guard.js +186 -0
  616. package/src/utils/install-hints.js +180 -0
  617. package/src/utils/json-extract.js +64 -0
  618. package/src/utils/locale.js +59 -0
  619. package/src/utils/logger.js +96 -0
  620. package/src/utils/managed-markers.js +93 -0
  621. package/src/utils/manifest-sniff.js +82 -0
  622. package/src/utils/messages.js +61 -0
  623. package/src/utils/model-selector.js +107 -0
  624. package/src/utils/os-detect.js +79 -0
  625. package/src/utils/paths.js +13 -0
  626. package/src/utils/pending-user-action.js +95 -0
  627. package/src/utils/port-check.js +6 -0
  628. package/src/utils/port-occupant.js +96 -0
  629. package/src/utils/pricing.js +29 -0
  630. package/src/utils/process.js +4 -0
  631. package/src/utils/project-detect.js +160 -0
  632. package/src/utils/prompt-project-name.js +35 -0
  633. package/src/utils/provider-env.js +116 -0
  634. package/src/utils/qmd-collection.js +72 -0
  635. package/src/utils/qmd-detect.js +18 -0
  636. package/src/utils/qmd-install.js +37 -0
  637. package/src/utils/quota-simulator.js +56 -0
  638. package/src/utils/rate-limit-detector.js +181 -0
  639. package/src/utils/repo-cleaner.js +79 -0
  640. package/src/utils/retry.js +88 -0
  641. package/src/utils/role-assigner.js +137 -0
  642. package/src/utils/role-env.js +58 -0
  643. package/src/utils/rtk-detect.js +18 -0
  644. package/src/utils/rtk-install.js +38 -0
  645. package/src/utils/rtk-wrapper.js +87 -0
  646. package/src/utils/run-context.js +75 -0
  647. package/src/utils/run-log.js +217 -0
  648. package/src/utils/run-registry.js +9 -0
  649. package/src/utils/shared-paths.js +12 -0
  650. package/src/utils/squeezr-detect.js +21 -0
  651. package/src/utils/squeezr-install.js +37 -0
  652. package/src/utils/stack-detect.js +135 -0
  653. package/src/utils/stall-detector.js +159 -0
  654. package/src/utils/status-dashboard.js +254 -0
  655. package/src/utils/task-file.js +109 -0
  656. package/src/utils/telemetry.js +124 -0
  657. package/src/utils/templates-root.js +61 -0
  658. package/src/utils/tool-call-extractor.js +56 -0
  659. package/src/utils/tool-governor.js +116 -0
  660. package/src/utils/tool-installer.js +93 -0
  661. package/src/utils/update-check.js +280 -0
  662. package/src/utils/vector-store-orphans.js +89 -0
  663. package/src/utils/welcome.js +47 -0
  664. package/src/utils/with-timeout.js +42 -0
  665. package/src/utils/wizard.js +47 -0
  666. package/src/webperf/cwv-gate.js +94 -0
  667. package/src/webperf/devtools-detect.js +112 -0
  668. package/src/webperf/scanner.js +209 -0
  669. package/src/webperf/webperf-role-integration.js +66 -0
  670. package/templates/coder-rules.md +45 -0
  671. package/templates/docker-compose.sonar.yml +60 -0
  672. package/templates/domains/example-dental.md +57 -0
  673. package/templates/kj.config.yml +128 -0
  674. package/templates/review-rules.md +17 -0
  675. package/templates/roles/architect/anthropic.md +74 -0
  676. package/templates/roles/architect/default.md +72 -0
  677. package/templates/roles/architect/google.md +61 -0
  678. package/templates/roles/architect/openai.md +60 -0
  679. package/templates/roles/architect/opencode.md +59 -0
  680. package/templates/roles/architect.md +76 -0
  681. package/templates/roles/audit.md +68 -0
  682. package/templates/roles/coder/anthropic.md +81 -0
  683. package/templates/roles/coder/default.md +78 -0
  684. package/templates/roles/coder/google.md +87 -0
  685. package/templates/roles/coder/openai.md +68 -0
  686. package/templates/roles/coder/opencode.md +58 -0
  687. package/templates/roles/coder.md +152 -0
  688. package/templates/roles/commiter.md +44 -0
  689. package/templates/roles/discover.md +167 -0
  690. package/templates/roles/domain-curator.md +52 -0
  691. package/templates/roles/hu-reviewer.md +236 -0
  692. package/templates/roles/impeccable-design.md +87 -0
  693. package/templates/roles/impeccable.md +125 -0
  694. package/templates/roles/karajan-brain.md +95 -0
  695. package/templates/roles/onboarder.md +45 -0
  696. package/templates/roles/planner/anthropic.md +59 -0
  697. package/templates/roles/planner/default.md +57 -0
  698. package/templates/roles/planner/google.md +75 -0
  699. package/templates/roles/planner/openai.md +55 -0
  700. package/templates/roles/planner/opencode.md +62 -0
  701. package/templates/roles/planner.md +61 -0
  702. package/templates/roles/refactorer.md +48 -0
  703. package/templates/roles/repairer.md +103 -0
  704. package/templates/roles/researcher.md +41 -0
  705. package/templates/roles/reviewer/anthropic.md +61 -0
  706. package/templates/roles/reviewer/default.md +62 -0
  707. package/templates/roles/reviewer/google.md +63 -0
  708. package/templates/roles/reviewer/openai.md +57 -0
  709. package/templates/roles/reviewer/opencode.md +42 -0
  710. package/templates/roles/reviewer-paranoid.md +38 -0
  711. package/templates/roles/reviewer-relaxed.md +34 -0
  712. package/templates/roles/reviewer-strict.md +37 -0
  713. package/templates/roles/reviewer.md +62 -0
  714. package/templates/roles/security.md +54 -0
  715. package/templates/roles/solomon/anthropic.md +71 -0
  716. package/templates/roles/solomon/default.md +83 -0
  717. package/templates/roles/solomon/google.md +61 -0
  718. package/templates/roles/solomon/openai.md +53 -0
  719. package/templates/roles/solomon/opencode.md +55 -0
  720. package/templates/roles/solomon.md +83 -0
  721. package/templates/roles/sonar.md +49 -0
  722. package/templates/roles/spec-reviewer.md +47 -0
  723. package/templates/roles/tester.md +50 -0
  724. package/templates/roles/triage.md +69 -0
  725. package/templates/skills/kj-architect.md +45 -0
  726. package/templates/skills/kj-audit.md +63 -0
  727. package/templates/skills/kj-board.md +16 -0
  728. package/templates/skills/kj-code.md +51 -0
  729. package/templates/skills/kj-csv-transform.md +40 -0
  730. package/templates/skills/kj-data-report.md +44 -0
  731. package/templates/skills/kj-discover.md +24 -0
  732. package/templates/skills/kj-rag-query.md +50 -0
  733. package/templates/skills/kj-review.md +47 -0
  734. package/templates/skills/kj-run.md +73 -0
  735. package/templates/skills/kj-security.md +49 -0
  736. package/templates/skills/kj-sonar.md +41 -0
  737. package/templates/skills/kj-sql-analysis.md +40 -0
  738. package/templates/skills/kj-test.md +40 -0
  739. package/templates/workflows/automerge.yml +30 -0
  740. package/templates/workflows/houston-override.yml +46 -0
  741. package/templates/workflows/kj-ci-gateway.yml +58 -0
  742. package/vendor/tree-sitter-grammars/README.md +21 -0
  743. package/vendor/tree-sitter-grammars/go.wasm +0 -0
  744. package/vendor/tree-sitter-grammars/java.wasm +0 -0
  745. package/vendor/tree-sitter-grammars/python.wasm +0 -0
  746. package/vendor/tree-sitter-grammars/rust.wasm +0 -0
@@ -0,0 +1,772 @@
1
+ import { discoverCommand } from "../commands/discover.js";
2
+ import { triageCommand } from "../commands/triage.js";
3
+ import { researcherCommand } from "../commands/researcher.js";
4
+ import { architectCommand } from "../commands/architect.js";
5
+ import { onboardCommand } from "../commands/onboard.js";
6
+ import { startCommand } from "../commands/start.js";
7
+ import { identityCommand } from "../commands/identity.js";
8
+ import { ragIndexCommand, ragQueryCommand, ragInstallHooksCommand, ragEvalCommand } from "../commands/rag.js";
9
+ import { qmdQueryCommand } from "../commands/qmd.js";
10
+ import { ragMcpCommand } from "../commands/rag-mcp.js";
11
+ import { watchStartCommand, watchStopCommand, watchStatusCommand } from "../commands/watch.js";
12
+ import { auditCommand } from "../commands/audit.js";
13
+ import { resumeCommand } from "../commands/resume.js";
14
+ import { boardCommand } from "../commands/board.js";
15
+ import { webperfCommand } from "../commands/webperf.js";
16
+ import { undoCommand } from "../commands/undo.js";
17
+ import { syncCommand } from "../commands/sync.js";
18
+ import { cleanCommand } from "../commands/clean.js";
19
+ import { checkCommand } from "../commands/check.js";
20
+ import { mutateCommand } from "../commands/mutate.js";
21
+ import { hardenCommand } from "../commands/harden.js";
22
+ import { telemetryPreviewCommand, telemetryStatusCommand } from "../commands/telemetry.js";
23
+ import { envInstallCommand, briefCommand } from "../commands/env.js";
24
+ import { runReleaseCheck } from "../checks/release-check.js";
25
+ import { agentRunCommand } from "../commands/agent-run.js";
26
+ import { reportIssueCommand } from "../commands/report-issue.js";
27
+ import { huCommand } from "../commands/hu.js";
28
+ import { worktreeCommand } from "../commands/worktree.js";
29
+ import { addAdr, listAdrs } from "../environment/adr.js";
30
+ import { formatAdvancedIndex } from "../commands/advanced.js";
31
+ import { policyAddCommand } from "../policy/add.js";
32
+ import { withConfig } from "./_shared.js";
33
+ import { existsSync } from "node:fs";
34
+ import { join } from "node:path";
35
+ import { spawnSync } from "node:child_process";
36
+ import { verifySentinelScripts, resolveSentinelRoot } from "../harden/sentinel-hooks.js";
37
+
38
+ /**
39
+ * Register the "meta" / single-role / housekeeping commands: pre-pipeline
40
+ * analysis (discover, triage, researcher, architect, audit), session
41
+ * management (resume, board, undo) and maintenance (update, sync, clean).
42
+ *
43
+ * Note: `triage` lives here (not in pipeline) because it's a single-role
44
+ * analysis command in the same family as discover / researcher /
45
+ * architect / audit, none of which run the full agent loop.
46
+ */
47
+ export function registerMeta(program, { pkgVersion }) {
48
+ program
49
+ .command("discover")
50
+ .description("Analyze task for gaps, ambiguities and missing info")
51
+ .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
52
+ .option("--task-file <path>", "Read the task from a file (e.g. .md)")
53
+ .option("--mode <name>", "Discovery mode: gaps|momtest|wendel|classify|jtbd", "gaps")
54
+ .option("--discover <name>", "Override discover agent")
55
+ .option("--discover-model <name>", "Override discover model")
56
+ .option("--json", "Output raw JSON")
57
+ .action(async (task, flags) => {
58
+ await withConfig(pkgVersion, "discover", flags, async ({ config, logger }) => {
59
+ const { resolveTaskInput } = await import("../utils/task-file.js");
60
+ const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger });
61
+ await discoverCommand({ task: resolvedTask, config, logger, mode: flags.mode, json: flags.json });
62
+ });
63
+ });
64
+
65
+ program
66
+ .command("triage")
67
+ .description("Classify task complexity and recommend pipeline roles")
68
+ .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
69
+ .option("--task-file <path>", "Read the task from a file (e.g. .md)")
70
+ .option("--triage <name>", "Override triage agent")
71
+ .option("--triage-model <name>", "Override triage model")
72
+ .option("--json", "Output raw JSON")
73
+ .action(async (task, flags) => {
74
+ await withConfig(pkgVersion, "triage", flags, async ({ config, logger }) => {
75
+ const { resolveTaskInput } = await import("../utils/task-file.js");
76
+ const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger });
77
+ await triageCommand({ task: resolvedTask, config, logger, json: flags.json });
78
+ });
79
+ });
80
+
81
+ program
82
+ .command("researcher")
83
+ .description("Research codebase for a task (files, patterns, constraints)")
84
+ .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
85
+ .option("--task-file <path>", "Read the task from a file (e.g. .md)")
86
+ .option("--researcher <name>", "Override researcher agent")
87
+ .option("--researcher-model <name>", "Override researcher model")
88
+ .action(async (task, flags) => {
89
+ await withConfig(pkgVersion, "researcher", flags, async ({ config, logger }) => {
90
+ const { resolveTaskInput } = await import("../utils/task-file.js");
91
+ const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger });
92
+ await researcherCommand({ task: resolvedTask, config, logger });
93
+ });
94
+ });
95
+
96
+ program
97
+ .command("architect")
98
+ .description("Design solution architecture (layers, patterns, contracts)")
99
+ .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
100
+ .option("--task-file <path>", "Read the task from a file (e.g. .md)")
101
+ .option("--architect <name>", "Override architect agent")
102
+ .option("--architect-model <name>", "Override architect model")
103
+ .option("--context <text>", "Additional context (e.g. researcher output)")
104
+ .option("--json", "Output raw JSON")
105
+ .action(async (task, flags) => {
106
+ await withConfig(pkgVersion, "architect", flags, async ({ config, logger }) => {
107
+ const { resolveTaskInput } = await import("../utils/task-file.js");
108
+ const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger });
109
+ await architectCommand({ task: resolvedTask, config, logger, context: flags.context, json: flags.json });
110
+ });
111
+ });
112
+
113
+ program
114
+ .command("onboard")
115
+ .description("Analyze an existing codebase (brownfield) and produce an Architecture Brief")
116
+ .option("--no-synth", "Skip the LLM synthesis step, dump raw collectors only")
117
+ .option("--output <path>", "Override the default ~/.karajan/onboarding/<slug>.md target")
118
+ .action(async (flags) => {
119
+ await withConfig(pkgVersion, "onboard", flags, async ({ config, logger }) => {
120
+ await onboardCommand({ config, logger, flags });
121
+ });
122
+ });
123
+
124
+ // IDN-A (KJC-TSK-0762, epic KJC-PCS-0079): identity lock per clone.
125
+ const identityCmd = program
126
+ .command("identity")
127
+ .description("Identity lock: which gh account and git email this clone is worked with (.karajan/identity.local.yml, never tracked)");
128
+ identityCmd
129
+ .command("show", { isDefault: true })
130
+ .description("Declared identity vs the active one (exit 2 on mismatch or when undeclared)")
131
+ .action(async (flags) => {
132
+ await withConfig(pkgVersion, "identity-show", flags, async ({ config }) => {
133
+ process.exitCode = await identityCommand({ action: "show", config, flags });
134
+ });
135
+ });
136
+ identityCmd
137
+ .command("set")
138
+ .description("Declare this clone's identity from the active gh session and git config (or --gh/--email)")
139
+ .option("--gh <user>", "gh account to bind")
140
+ .option("--email <email>", "git email to bind")
141
+ .option("--yes", "Do not ask for confirmation")
142
+ .action(async (flags) => {
143
+ await withConfig(pkgVersion, "identity-set", flags, async ({ config }) => {
144
+ process.exitCode = await identityCommand({ action: "set", config, flags });
145
+ });
146
+ });
147
+
148
+ program
149
+ .command("start")
150
+ .description("Single entry point: assess the project and recommend the next step")
151
+ .argument("[task]", "What you want to do (optional natural-language goal)")
152
+ .option("--maturity <type>", "Declare project maturity: new|existing|legacy")
153
+ .option("--yes", "Non-interactive: emit assessment + recommendation, apply nothing")
154
+ .option("--json", "Output the assessment + decision as JSON")
155
+ .action(async (task, flags) => {
156
+ await withConfig(pkgVersion, "start", flags, async ({ config, logger }) => {
157
+ await startCommand({ task, config, logger, flags });
158
+ });
159
+ });
160
+
161
+ // ENV-A1 (KJC-TSK-0639) — Karajan Environment v4: the host agent
162
+ // orchestrates, Karajan installs the method it must follow.
163
+ const env = program.command("env").description("Karajan Environment (v4) — playbook for host agents");
164
+ env.command("install")
165
+ .description("Install/refresh the Karajan playbook for any host agent (CLAUDE.md, AGENTS.md, GEMINI.md)")
166
+ .option("--target <target>", "claude | codex | gemini | all", "all")
167
+ .option("--no-rag", "Skip building the RAG index when the project has none (ENV-E1)")
168
+ .option("--no-enforce", "Skip installing the git hooks + verdict gate (KJC-BUG-0133 — installing IS activating; skipping this leaves the method narratable)")
169
+ .action(async (flags) => {
170
+ await withConfig(pkgVersion, "env-install", flags, async ({ config, logger }) => {
171
+ const r = await envInstallCommand({ config, logger, flags });
172
+ // KJC-TSK-0659: exit 3 = pending user action (RAG cannot index) —
173
+ // a driving agent must stop and wait, never continue degraded.
174
+ if (Number.isInteger(r?.exitCode) && r.exitCode !== 0) process.exit(r.exitCode);
175
+ });
176
+ });
177
+
178
+ // AB-D (KJC-TSK-0654): the brain's inter-agent bus.
179
+ const agentCmd = program.command("agent").description("Delegate work to another AI agent (the brain's bus)");
180
+ agentCmd.command("run <agent> <task>")
181
+ .description("Run a task on the named agent and print its output (exit 0/1)")
182
+ .option("--json", "Machine-readable output: {ok, agent, output, usage}")
183
+ .option("--timeout-minutes <n>", "Hard timeout for the delegated task")
184
+ .action(async (agent, task, flags) => {
185
+ await withConfig(pkgVersion, "agent-run", flags, async ({ config, logger }) => {
186
+ await agentRunCommand({ agent, task, config, logger, flags });
187
+ });
188
+ });
189
+
190
+ // AB-H (KJC-TSK-0658): board writes + repo ADRs for the brain.
191
+ // KJC-TSK-0679: isolated lanes for the host agent — ordering a command
192
+ // beats ordering a practice an agent can narrate without doing.
193
+ const wt = program.command("worktree").description("Isolated task lanes (git worktrees) for the host agent");
194
+ wt.command("start <slug>")
195
+ .description("Create a lane: worktree + feat/<slug> branch + dependency bootstrap")
196
+ .action(async (slug, flags) => {
197
+ await withConfig(pkgVersion, "worktree", flags, async ({ config }) => {
198
+ await worktreeCommand({ config, action: "start", args: [slug], flags });
199
+ });
200
+ });
201
+ wt.command("list")
202
+ .description("List the active lanes")
203
+ .action(async (flags) => {
204
+ await withConfig(pkgVersion, "worktree", flags, async ({ config }) => {
205
+ await worktreeCommand({ config, action: "list", flags });
206
+ });
207
+ });
208
+ wt.command("done <slug>")
209
+ .option("--force", "Remove the lane even with uncommitted changes")
210
+ .description("Remove a merged lane (refuses uncommitted changes without --force)")
211
+ .action(async (slug, flags) => {
212
+ await withConfig(pkgVersion, "worktree", flags, async ({ config }) => {
213
+ await worktreeCommand({ config, action: "done", args: [slug], flags });
214
+ });
215
+ });
216
+
217
+ const hu = program.command("hu").description("Track work in the HU Board from any host agent (card first)");
218
+ hu.command("add <title>")
219
+ .option("--id <shortId>", "Human-readable short id")
220
+ .option("--ac <criterion>", "Acceptance criterion (repeatable; multiline strings split per line)", (v, acc) => [...acc, v], [])
221
+ .option("--tests <test>", "Acceptance test (repeatable; multiline strings split per line)", (v, acc) => [...acc, v], [])
222
+ .option("--scope <text>", "Scope of the story (files/areas)")
223
+ .option("--task-type <type>", "sw | infra | doc | add-tests | refactor")
224
+ .option("--criteria <text>", "Legacy alias for a single acceptance criterion")
225
+ .option("--json", "Machine-readable output")
226
+ .action(async (title, flags) => {
227
+ await withConfig(pkgVersion, "hu", flags, async ({ config }) => {
228
+ await huCommand({ config, action: "add", args: [title], flags });
229
+ });
230
+ });
231
+ hu.command("move <id> <status>")
232
+ .option("--json", "Machine-readable output")
233
+ .action(async (id, status, flags) => {
234
+ await withConfig(pkgVersion, "hu", flags, async ({ config }) => {
235
+ await huCommand({ config, action: "move", args: [id, status], flags });
236
+ });
237
+ });
238
+ hu.command("list")
239
+ .option("--json", "Machine-readable output")
240
+ .action(async (flags) => {
241
+ await withConfig(pkgVersion, "hu", flags, async ({ config }) => {
242
+ await huCommand({ config, action: "list", flags });
243
+ });
244
+ });
245
+
246
+ const adr = program.command("adr").description("Architecture decision records in .karajan/adrs/ (git-tracked)");
247
+ adr.command("add <title>")
248
+ .requiredOption("--decision <text>", "The decision itself")
249
+ .option("--context <text>", "Why this came up")
250
+ .option("--consequences <text>", "Trade-offs accepted")
251
+ .option("--json", "Machine-readable output")
252
+ .action(async (title, flags) => {
253
+ await withConfig(pkgVersion, "adr", flags, async ({ config }) => {
254
+ const res = await addAdr(config?.projectDir || process.cwd(), { title, ...flags });
255
+ console.log(flags.json ? JSON.stringify(res) : `✓ ADR ${res.number} created: ${res.file} — commit it`);
256
+ });
257
+ });
258
+ adr.command("list")
259
+ .option("--json", "Machine-readable output")
260
+ .action(async (flags) => {
261
+ await withConfig(pkgVersion, "adr", flags, async ({ config }) => {
262
+ const adrs = await listAdrs(config?.projectDir || process.cwd());
263
+ if (flags.json) { console.log(JSON.stringify(adrs)); return; }
264
+ for (const a of adrs) console.log(`${String(a.number).padStart(4, "0")} ${a.status.padEnd(10)} ${a.title}`);
265
+ if (adrs.length === 0) console.log("no ADRs yet — create one with: kj adr add \"<title>\" --decision \"...\"");
266
+ });
267
+ });
268
+
269
+ // AB-F (KJC-TSK-0655): self-healing — the brain files kj frictions upstream.
270
+ program
271
+ .command("report-issue")
272
+ .description("Report a kj bug/friction to the public repo (sanitized; publishing needs --publish)")
273
+ .requiredOption("--title <text>", "One-line summary")
274
+ .option("--description <text>", "What happened and what you expected")
275
+ .option("--command <cmd>", "The kj command involved")
276
+ .option("--error <text>", "The error output (it will be sanitized)")
277
+ .option("--publish", "Create the issue via the gh CLI (confirm with your user first)")
278
+ .option("--force", "Skip the similar-issues check")
279
+ .option("--json", "Machine-readable output")
280
+ .action(async (flags) => {
281
+ await reportIssueCommand({ logger: console, flags });
282
+ });
283
+
284
+ // AB-C (KJC-TSK-0652): role briefs for the brain (any host agent).
285
+ program
286
+ .command("brief")
287
+ .description("Show the distilled method of a pipeline role (for the host agent to execute)")
288
+ .argument("[role]", "triage | planner | researcher | architect | tester | security | audit")
289
+ .option("--json", "Machine-readable output")
290
+ .action(async (role, flags) => {
291
+ await withConfig(pkgVersion, "brief", flags, async ({ config }) => {
292
+ briefCommand({ config, flags, role });
293
+ });
294
+ });
295
+
296
+ // KJC-TSK-0712 — memory is the reminder, the check is the guarantee.
297
+ const release = program.command("release").description("Release ceremony helpers");
298
+ release.command("check")
299
+ .description("Verify the release checklist deterministically (manifest vs CHANGELOG vs tags, privacy scan of publishable files, plus the project's release_check.items); exit 1 lists exactly what is missing")
300
+ .option("--json", "Machine-readable result")
301
+ .action(async (flags) => {
302
+ await withConfig(pkgVersion, "release-check", flags, async ({ config }) => {
303
+ const res = await runReleaseCheck({ projectDir: config?.projectDir || process.cwd(), config });
304
+ if (flags.json) process.stdout.write(`${JSON.stringify(res)}\n`);
305
+ else {
306
+ for (const c of res.checks) console.log(` ${c.ok ? "✓" : "✗"} ${c.name}: ${c.detail}`);
307
+ console.log(res.ok ? `release check: ready to release ${res.version ?? ""}`.trim() : "release check: NOT ready — fix the red items first");
308
+ }
309
+ process.exitCode = res.ok ? 0 : 1;
310
+ });
311
+ });
312
+
313
+ // KJC-TSK-0733 PL-A — policy as code: motor determinista en modo warn.
314
+ const policyCmd = program.command("policy").description("Policy as code (.karajan/policy.yml, vocabulario cerrado): eval/check deterministas, grant con caducidad, anchor del decision log — deny en commit y CI");
315
+ policyCmd.command("eval")
316
+ .description("Evalúa UNA tool call: imprime {decision, rule_id, reason}; --strict devuelve exit 2 en deny (contrato para adaptadores de hooks)")
317
+ .option("--role <role>", "Rol del agente", "coder")
318
+ .option("--tool <tool>", "Tool (Write, Edit, Bash…)")
319
+ .option("--input <json>", "tool_input en JSON")
320
+ .option("--strict", "Exit 2 si deny")
321
+ .action(async (flags) => {
322
+ await withConfig(pkgVersion, "policy-eval", flags, async ({ config }) => {
323
+ const { policyCommand } = await import("../commands/policy.js");
324
+ process.exitCode = await policyCommand({ action: "eval", config, flags });
325
+ });
326
+ });
327
+ policyCmd.command("grant")
328
+ .description("Concede una excepción PERMANENTE con caducidad a una regla NO-security: quién (identidad), regla exacta, justificación y hasta cuándo — GOV-B")
329
+ .option("--rule <rule_id>", "Regla exacta (p.ej. roles.coder.write.deny)")
330
+ .option("--until <iso>", "Caducidad ISO-8601 (p.ej. 2026-09-01T00:00:00Z)")
331
+ .option("--reason <text>", "Justificación escrita en el momento")
332
+ .action(async (flags) => {
333
+ await withConfig(pkgVersion, "policy-grant", flags, async ({ config }) => {
334
+ const { policyCommand } = await import("../commands/policy.js");
335
+ process.exitCode = await policyCommand({ action: "grant", config, flags });
336
+ });
337
+ });
338
+ policyCmd.command("add")
339
+ .description("Traduce una regla hablada al vocabulario cerrado de policy.yml — propone el diff y SOLO escribe con --yes (PL-C)")
340
+ .argument("<text...>", "La regla en lenguaje natural")
341
+ .option("--yes", "Aplicar el diff propuesto")
342
+ .action(async (textParts, flags) => {
343
+ await withConfig(pkgVersion, "policy-add", flags, async ({ config, logger }) => {
344
+ process.exitCode = await policyAddCommand({ text: textParts.join(" "), config, flags, logger });
345
+ });
346
+ });
347
+ policyCmd.command("anchor")
348
+ .description("Verifica la cadena del decision log y sella su head-hash en .karajan/policy-anchor.json (trackeado) — anclaje temporal en la historia de git, GOV-C2")
349
+ .action(async (flags) => {
350
+ await withConfig(pkgVersion, "policy-anchor", flags, async ({ config }) => {
351
+ const { policyCommand } = await import("../commands/policy.js");
352
+ process.exitCode = await policyCommand({ action: "anchor", config, flags });
353
+ });
354
+ });
355
+ policyCmd.command("check")
356
+ .description("Comprueba el diff (staged, o base...head con --range) contra la policy — warn por defecto; --strict devuelve exit 2 si hay violación enforcement=deny (tier C, merge-blocking)")
357
+ .option("--role <role>", "Rol del agente", "coder")
358
+ .option("--range <ref>", "Evalúa un rango git (p.ej. origin/main...HEAD) en vez del staged (CI)")
359
+ .option("--strict", "Exit 2 si hay violación con enforcement=deny")
360
+ .option("--json", "Machine-readable")
361
+ .action(async (flags) => {
362
+ await withConfig(pkgVersion, "policy-check", flags, async ({ config }) => {
363
+ const { policyCommand } = await import("../commands/policy.js");
364
+ process.exitCode = await policyCommand({ action: "check", config, flags });
365
+ });
366
+ });
367
+
368
+ // KJC-TSK-0713 — the Sentinel: the method state the harness hooks record.
369
+ const sentinel = program.command("sentinel").description("Deterministic method supervisor wired into the harness hooks (Claude Code)");
370
+ sentinel.command("status")
371
+ .description("Print the per-session method facts (sources/tests edited, escapes used) and any open violation the Stop gate would block on")
372
+ .action(() => {
373
+ const script = join(resolveSentinelRoot(), ".karajan", "harness", "stop.mjs");
374
+ if (!existsSync(script)) {
375
+ console.log("sentinel: not installed in this project — run `kj harden` (standard profile or higher)");
376
+ process.exitCode = 1;
377
+ return;
378
+ }
379
+ process.exitCode = spawnSync("node", [script, "--status"], { stdio: "inherit" }).status ?? 0;
380
+ });
381
+ sentinel.command("verify")
382
+ .description("Verify the harness scripts match this kj install — the root of trust is the installed package, not the project tree; exit 1 lists what was modified")
383
+ .option("--json", "Machine-readable result")
384
+ .action((flags) => {
385
+ const res = verifySentinelScripts();
386
+ if (flags.json) process.stdout.write(`${JSON.stringify(res)}\n`);
387
+ else console.log(res.ok ? "sentinel verify: scripts intactos" : `sentinel verify: modificados fuera de kj harden: ${res.mismatched.join(", ")} — restaura con kj harden`);
388
+ process.exitCode = res.ok ? 0 : 1;
389
+ });
390
+
391
+ // KJC-TSK-0704 — the outbound privacy boundary: audit before anything ships.
392
+ const privacy = program.command("privacy").description("Personal-data (PII) auditing of outbound boundaries: staged diffs, build outputs, docs trees");
393
+ privacy.command("scan [paths...]")
394
+ .description("Scan files/dirs for personal data, always masked in output: denylist hits (~/.karajan/privacy.yml) block with exit 1, generic PII (email/phone/DNI/NIE/IBAN/card via karajan-rag redactPII) warns")
395
+ .option("--staged", "Scan the ADDED lines of the staged diff instead of paths")
396
+ .option("--json", "Machine-readable result (stdout carries exactly one JSON document)")
397
+ .action(async (paths, flags) => {
398
+ const { privacyScanCommand } = await import("../commands/privacy.js");
399
+ await privacyScanCommand({ paths, flags });
400
+ });
401
+
402
+ const rag = program.command("rag").description("Retrieval-augmented search over Karajan plans, onboarding briefs and project code");
403
+ rag.command("index")
404
+ .description("Index plans + onboarding (and optionally project sources) into the local vector store")
405
+ .option("--with-sources", "Also index the projectDir's JS/TS files")
406
+ .option("--since <ref>", "Only re-index files changed since <ref> ('auto' uses the last indexed commit; falls back to full index if unset). KJC-TSK-0455.")
407
+ .option("--json", "Output the totals as JSON")
408
+ .action(async (flags) => {
409
+ await withConfig(pkgVersion, "rag-index", flags, async ({ config, logger }) => {
410
+ await ragIndexCommand({ config, logger, flags });
411
+ });
412
+ });
413
+ rag.command("install-hooks")
414
+ .description("Install the post-merge git hook so the RAG index auto-refreshes after pulls/merges (KJC-TSK-0455)")
415
+ .option("--json", "Output the result as JSON")
416
+ .action(async (flags) => {
417
+ await withConfig(pkgVersion, "rag-install-hooks", flags, async ({ config, logger }) => {
418
+ await ragInstallHooksCommand({ config, logger, flags });
419
+ });
420
+ });
421
+ rag.command("query <text>")
422
+ .description("Run a semantic query against the indexed RAG corpus")
423
+ .option("--no-rag-update", "Skip the pre-query drift delta-update (ENV-E1)")
424
+ .option("--scope <scope>", "plans | code | onboarding | all (default: all)", "all")
425
+ .option("--top-k <n>", "Number of hits to return (default: 5)", "5")
426
+ .option("--project <slug>", "Filter by project slug. Pass 'all' to query across every indexed project. Default: cwd basename")
427
+ // KJC-BUG-0070 — the global `--mode` flag maps to `review_mode` in
428
+ // src/config/overrides.js. We expose the rag-specific knob under
429
+ // `--rag-mode` to avoid the collision (which crashed the command on
430
+ // first call). Internally we rebind to `flags.mode` so the handler
431
+ // in src/commands/rag.js stays untouched.
432
+ .option("--rag-mode <mode>", "hybrid (default) | semantic (cosine only) | keyword (BM25 only)", "hybrid")
433
+ .option("--alpha <n>", "Hybrid weight for semantic component (0..1). Default 0.6", "0.6")
434
+ .option("--where <clause>", "Metadata filter, e.g. 'symbol=loadConfig' or 'hu_id=HU-003 AND kind=plan'")
435
+ .option("--library", "Query the distilled engineering canon (pattern cards shipped with kj + ~/.karajan/library + project .karajan/library) instead of the project corpus. Cards carry problem signatures, when-NOT-to-apply and canonical citations (KJC-TSK-0697).")
436
+ .option("--rerank", "Apply cross-encoder rerank to top-K (needs @huggingface/transformers, slower but more precise)")
437
+ .option("--rerank-model <name>", "Cross-encoder model id. Default: Xenova/ms-marco-MiniLM-L-6-v2")
438
+ .option("--json", "Output the hits as JSON")
439
+ .action(async (text, flags) => {
440
+ // Stash the rag-specific mode and remove it from the flags object so
441
+ // applyScalarAndBooleanOverrides cannot see a `flags.mode` and write
442
+ // out.review_mode = "hybrid" — that would fail the schema validator.
443
+ const ragMode = flags.ragMode;
444
+ delete flags.ragMode;
445
+ await withConfig(pkgVersion, "rag-query", flags, async ({ config, logger }) => {
446
+ await ragQueryCommand({ text, config, logger, flags: { ...flags, mode: ragMode } });
447
+ });
448
+ });
449
+ // KJC-TSK-0483 — `kj rag eval` runs the golden-query harness and reports
450
+ // recall@5/recall@10/MRR. `--min-recall` turns it into a CI gate.
451
+ rag.command("eval")
452
+ .description("Score the retriever against a golden query set (recall@k + MRR)")
453
+ .option("--golden <path>", "Path to golden queries JSON (default: tests/rag/golden-queries.json)")
454
+ .option("--top-k <n>", "Number of hits to retrieve per query (default: 10)", "10")
455
+ .option("--min-recall <n>", "Fail (exit 1) if aggregated recall@5 falls below this threshold")
456
+ .option("--project <slug>", "Filter by project slug. Pass 'all' to query across every indexed project.")
457
+ .option("--json", "Emit the full report as JSON")
458
+ .action(async (flags) => {
459
+ await withConfig(pkgVersion, "rag-eval", flags, async ({ config, logger }) => {
460
+ await ragEvalCommand({ config, logger, flags });
461
+ });
462
+ });
463
+
464
+ // KJC-TSK-0492 PR3 — `kj rag mcp` exposes the kj-rag-mcp binary under the
465
+ // familiar `kj rag <subcommand>` surface so users discover it without
466
+ // grepping bin/. The action dynamic-imports the binary, which takes over
467
+ // stdio for MCP transport; the CLI process never returns.
468
+ rag.command("mcp")
469
+ .description("Start the standalone RAG MCP server (kj_rag_query + kj_rag_index only). Same as running `kj-rag-mcp` directly")
470
+ .action(async () => {
471
+ await ragMcpCommand();
472
+ });
473
+
474
+ // KJC-TSK-0509 — `kj qmd query` is a thin wrapper around the upstream
475
+ // `qmd` binary that auto-resolves the project's collection (rag = agent
476
+ // context; qmd = human wiki). One subcommand for now; index/add live in
477
+ // `kj init` and `kj rag install-hooks` (post-merge reindex).
478
+ const qmd = program.command("qmd").description("Semantic search over the per-project QMD wiki (docs/, .reviews/, .karajan/plans/)");
479
+ qmd.command("query <text>")
480
+ .description("Run a qmd query against the wiki collection of the current project")
481
+ .option("--collection <name>", "Override the auto-resolved <slug>-<suffix> collection name")
482
+ .option("--scope <name>", "docs (default) | reviews | plans", "docs")
483
+ .option("--top-k <n>", "Number of hits to return (1..50, default 10)", "10")
484
+ .option("--fast", "Skip the LLM reranker (faster, slightly noisier hits)")
485
+ .option("--json", "Emit the raw JSON array for piping to jq")
486
+ .action(async (text, flags) => {
487
+ await withConfig(pkgVersion, "qmd-query", flags, async ({ config, logger }) => {
488
+ await qmdQueryCommand({ text, config, logger, flags });
489
+ });
490
+ });
491
+
492
+ // KJC-TSK-0441 — `kj watch [start|stop|status]` for live RAG re-index.
493
+ const watch = program.command("watch").description("Live RAG re-index daemon");
494
+ watch.command("start").description("Start the watcher daemon").option("--foreground", "Run in foreground (do not detach)").option("--with-sources", "Watch project source files too").action(async (flags) => {
495
+ await withConfig(pkgVersion, "watch:start", flags, async ({ config, logger }) => watchStartCommand({ config, logger, flags }));
496
+ });
497
+ watch.command("stop").description("Stop the watcher daemon").action(async () => {
498
+ await withConfig(pkgVersion, "watch:stop", {}, async ({ logger }) => watchStopCommand({ logger }));
499
+ });
500
+ watch.command("status").description("Report watcher daemon state").action(async () => {
501
+ await withConfig(pkgVersion, "watch:status", {}, async ({ logger }) => watchStatusCommand({ logger }));
502
+ });
503
+
504
+ program
505
+ .command("audit")
506
+ .description("Analyze codebase health (read-only)")
507
+ .argument("[task]", "Task description. If absent, defaults to a full-codebase analysis. Use --task-file to point at a .md.")
508
+ .option("--task-file <path>", "Read the task from a file (e.g. .md)")
509
+ .option("--dimensions <list>", "Comma-separated: security,quality,performance,architecture,testing,accessibility (default: all; accessibility auto-skipped on detected backend-only projects)", "all")
510
+ .option("--json", "Output raw JSON")
511
+ .option("--agent-readiness", "Score the repo for AI-agent readability (llms.txt, SKILL.md coverage, page token budgets, robots allowlist, heading hierarchy). LLM-free; uses [path] or cwd as the audit target. See issue #542.")
512
+ .option("--path <dir>", "Path to audit (used with --agent-readiness; defaults to cwd)")
513
+ .option("--no-sonar", "Skip the SonarQube findings collector (faster, less context). Sonar findings are also skipped automatically when SonarQube is unreachable.")
514
+ .option("--no-osv", "Skip the OSV-Scanner vulnerability collector. Findings are also skipped automatically when osv-scanner is not installed.")
515
+ .option("--no-semgrep", "Skip the Semgrep SAST collector. Findings are also skipped automatically when semgrep is not installed (install via 'pipx install semgrep' or 'brew install semgrep').")
516
+ .option("--no-harness", "Skip the AI Harness Scorecard stage (Docker one-shot). Auto-skipped when Docker is unavailable. Each run is also persisted to .karajan/audit-history.db (KJC-TSK-0472) for diff/trend tracking.")
517
+ .option("--no-ai-slop", "Skip the AI-slop tells collector (deterministic regex scan for tautologic comments, banner separators, boilerplate docstrings, magic fallbacks, redundant JSDoc). KJC-TSK-0503.")
518
+ .option("--trend", "Append a sparkline of the harness score across the last 10 runs (uses .karajan/audit-history.db). KJC-TSK-0473.")
519
+ .option("--report-file <path>", "Write the audit report to disk in addition to stdout. <path> may be a file (extension drives format: .md or .json) or a directory (creates audit-<ISO>.<md|json> inside). $KJ_AUDIT_REPORT_DIR env var is used as default directory if no --report-file is given.")
520
+ .option("--deterministic-only", "Skip the LLM analysis entirely. Print/persist only the deterministic findings (basalCost, sonar, stack, growth-delta, webperf). Zero tokens spent. Compatible with --report-file and --json.")
521
+ .option("--security", "Focused deterministic security pass: prompt-injection scan over the agent-context surface (CLAUDE.md/AGENTS.md/templates/.rulesync/.karajan) + OSV + Semgrep + Sonar. Skips basal-cost, webperf, madge, knip, ai-slop, harness and the LLM — zero tokens. Designed for agents to self-invoke when a task touches sensitive surface (KJC-TSK-0695).")
522
+ .option("-y, --yes", "Auto-confirm the 'Continue with LLM analysis?' prompt. Useful in scripts that want the full audit non-interactively. CI/non-TTY paths already auto-confirm without this flag.")
523
+ .action(async (task, flags) => {
524
+ await withConfig(pkgVersion, "audit", flags, async ({ config, logger }) => {
525
+ let resolvedTask = task;
526
+ if (flags.taskFile) {
527
+ const { readTaskFile } = await import("../utils/task-file.js");
528
+ resolvedTask = await readTaskFile(flags.taskFile, { projectDir: config.projectDir });
529
+ }
530
+ // commander resolves --no-sonar to flags.sonar=false (negation flag).
531
+ // We translate to the explicit `noSonar: true` shape AuditRole expects.
532
+ await auditCommand({
533
+ task: resolvedTask || "Analyze the full codebase",
534
+ config, logger,
535
+ dimensions: flags.dimensions, json: flags.json,
536
+ agentReadiness: Boolean(flags.agentReadiness),
537
+ path: flags.path,
538
+ noSonar: flags.sonar === false,
539
+ noOsv: flags.osv === false,
540
+ noSemgrep: flags.semgrep === false,
541
+ noHarness: flags.harness === false,
542
+ noAiSlop: flags.aiSlop === false,
543
+ reportFile: flags.reportFile || null,
544
+ deterministicOnly: Boolean(flags.deterministicOnly),
545
+ security: Boolean(flags.security),
546
+ yes: Boolean(flags.yes),
547
+ trend: Boolean(flags.trend),
548
+ });
549
+ });
550
+ });
551
+
552
+ program
553
+ .command("webperf")
554
+ .description("Run a Lighthouse web-perf scan against a URL — Core Web Vitals + opportunities")
555
+ .argument("<url>", "Target URL (e.g. http://localhost:3000)")
556
+ .option("--mobile", "Use the Lighthouse mobile preset (default: desktop)")
557
+ .option("--json", "Output raw JSON")
558
+ .option("--no-persist", "Don't write the result into ~/.karajan/webperf/<slug>/last.json (kj audit reads it from there)")
559
+ .action(async (url, flags) => {
560
+ await withConfig(pkgVersion, "webperf", flags, async ({ config, logger }) => {
561
+ const result = await webperfCommand({
562
+ url,
563
+ config, logger,
564
+ mobile: Boolean(flags.mobile),
565
+ json: Boolean(flags.json),
566
+ persist: flags.persist !== false,
567
+ });
568
+ // Exit with non-zero when the verdict is FAIL so CI can gate.
569
+ if (result && result.ok === false) process.exitCode = 1;
570
+ });
571
+ });
572
+
573
+ program
574
+ .command("resume")
575
+ .description("Resume a paused session")
576
+ .argument("<sessionId>")
577
+ .option("--answer <text>", "Answer to the question that caused the pause")
578
+ .option("--non-interactive", "Agents/CI: auto-answer prompts with their safe defaults; stop when there is none. Also enabled by KJ_NON_INTERACTIVE=1.")
579
+ .option("--json", "Output JSON only")
580
+ .action(async (sessionId, flags) => {
581
+ await withConfig(pkgVersion, "resume", flags, async ({ config, logger }) => {
582
+ const res = await resumeCommand({ sessionId, answer: flags.answer, config, logger, flags });
583
+ // KJC-TSK-0674 (issue #1289): same contract as kj run — an aborted
584
+ // resume must be observable by CI.
585
+ if (res?.aborted) process.exitCode = 1;
586
+ });
587
+ });
588
+
589
+ program
590
+ .command("update")
591
+ .description("Update karajan-code to the latest version from npm")
592
+ .action(async () => {
593
+ // Output-capturing self-update: npm's deprecation/allow-scripts/funding
594
+ // warnings are hidden on success and only surfaced when the install fails.
595
+ const { performSelfUpdate } = await import("../utils/update-check.js");
596
+ const result = await performSelfUpdate({ currentVersion: pkgVersion });
597
+ if (!result.ok) process.exit(1);
598
+ });
599
+
600
+ program
601
+ .command("board [action]")
602
+ .description("Manage HU Board (start|stop|status|open|cleanup)")
603
+ .option("--port <number>", "Port (default: 4000)", "4000")
604
+ .option("--bind <host>", "Bind host (default: 127.0.0.1; use 0.0.0.0 to expose on LAN — token auth auto-enforced)")
605
+ .action(async (action = "start", opts) => {
606
+ await withConfig(pkgVersion, "board", opts, async ({ config, logger }) => {
607
+ // KJC-TSK-0684 (issue #1287): an external board is the source of
608
+ // truth — don't start (or advertise) a parallel HU Board. "stop"
609
+ // stays allowed so a leftover daemon can be cleaned up.
610
+ if (config?.state_backend === "external" && action !== "stop") {
611
+ const name = config?.board?.name || "an external board";
612
+ console.log(`⚠ this project's board lives in ${name} (state_backend: external) — kj does not run a parallel HU Board here.`);
613
+ return;
614
+ }
615
+ const port = Number(opts.port) || config.hu_board?.port || 4000;
616
+ const bind = opts.bind || config.hu_board?.bind || "127.0.0.1";
617
+ await boardCommand({ action, port, bind, logger });
618
+ });
619
+ });
620
+
621
+ program
622
+ .command("undo")
623
+ .description("Revert last pipeline run")
624
+ .option("--hard", "Discard all changes (default: soft reset, keeps changes staged)")
625
+ .action(async (flags) => {
626
+ await withConfig(pkgVersion, "undo", flags, async ({ logger }) => {
627
+ const result = await undoCommand({ hard: !!flags.hard, logger });
628
+ if (!result.ok) process.exit(1);
629
+ });
630
+ });
631
+
632
+ program
633
+ .command("sync")
634
+ .description("Detect drift between code and the latest plan. Read-only by default; --apply writes a patch back to the Canvas.")
635
+ .option("--plan <planId>", "Sync against a specific plan instead of the latest")
636
+ .option("--json", "Emit machine-readable JSON instead of human output")
637
+ .option("--apply", "Write the drift report into the source Canvas (creates a .bak backup)")
638
+ .action(async (flags) => {
639
+ await withConfig(pkgVersion, "sync", flags, async ({ config, logger }) => {
640
+ await syncCommand({ config, logger, planId: flags.plan, json: flags.json, apply: Boolean(flags.apply) });
641
+ });
642
+ });
643
+
644
+ // KJC-TSK-0496 — surface the exact telemetry payload without sending it,
645
+ // and report whether telemetry is currently enabled. Read-only inspection
646
+ // commands so users can audit the contract without grepping the source.
647
+ const telemetry = program.command("telemetry").description("Inspect what Karajan telemetry sends and whether it's enabled (never opens a socket)");
648
+ telemetry.command("preview")
649
+ .description("Print the exact JSON payload for every event type (install, cli_command, pipeline_complete) — no network call")
650
+ .option("--json", "Emit the full preview as JSON")
651
+ .action(async (flags) => {
652
+ await withConfig(pkgVersion, "telemetry:preview", flags, async ({ config, logger }) => {
653
+ await telemetryPreviewCommand({ config, logger, version: pkgVersion, json: Boolean(flags.json) });
654
+ });
655
+ });
656
+ telemetry.command("status")
657
+ .description("Report whether telemetry is enabled and where the endpoint lives")
658
+ .option("--json", "Emit the status as JSON")
659
+ .action(async (flags) => {
660
+ await withConfig(pkgVersion, "telemetry:status", flags, async ({ config, logger }) => {
661
+ await telemetryStatusCommand({ config, logger, json: Boolean(flags.json) });
662
+ });
663
+ });
664
+
665
+ program
666
+ .command("clean")
667
+ .description("Garbage-collect stale plans, sessions and HU batches (dry-run by default)")
668
+ .option("--yes", "Actually delete — without this flag, only prints what would be removed")
669
+ .option("--nuke", "Retention=0 everywhere + wipe HU board DB. \"I want it all gone\"")
670
+ .option("--plan-days <n>", "Keep finalised plans (approved/rejected/executed) for N days (default: 30)")
671
+ .option("--draft-days <n>", "Keep draft plans for N days (default: 60)")
672
+ .option("--session-days <n>", "Keep finalised sessions for N days (default: 7)")
673
+ .option("--hu-days <n>", "Keep HU story batches for N days (default: 14)")
674
+ .option("--repo", "Also report repo-level candidates (merged branches, dist/, coverage/, *.tmp, *.bak)")
675
+ .option("--repo-days <n>", "Age threshold for repo artifacts in days (default: 7)")
676
+ .option("--repo-base <ref>", "Base ref to detect merged branches (default: origin/main)")
677
+ .option("--vector-stores", "Also report orphan RAG vector-store entries in ~/.karajan/rag.db")
678
+ .option("--project-roots <list>", "Colon-separated directories to scan for live projects (default: ~/ws_*, ~/projects, ~/code)")
679
+ .option("--all", "Shortcut for --repo --vector-stores (full read-only cleanup audit)")
680
+ .action(async (flags) => {
681
+ const allOn = Boolean(flags.all);
682
+ await cleanCommand({
683
+ yes: Boolean(flags.yes),
684
+ nuke: Boolean(flags.nuke),
685
+ repo: Boolean(flags.repo) || allOn,
686
+ repoDays: flags.repoDays ? Number(flags.repoDays) : undefined,
687
+ repoBase: flags.repoBase || undefined,
688
+ vectorStores: Boolean(flags.vectorStores) || allOn,
689
+ projectRoots: flags.projectRoots ? flags.projectRoots.split(":").filter(Boolean) : undefined,
690
+ planDays: flags.planDays ? Number(flags.planDays) : undefined,
691
+ draftDays: flags.draftDays ? Number(flags.draftDays) : undefined,
692
+ sessionDays: flags.sessionDays ? Number(flags.sessionDays) : undefined,
693
+ huDays: flags.huDays ? Number(flags.huDays) : undefined,
694
+ });
695
+ });
696
+
697
+ program
698
+ .command("harden")
699
+ .description("Install the quality harness (git hooks) into this repo — idempotent")
700
+ .option("--profile <name>", "minimal | standard | strict", "standard")
701
+ .option("--no-config", "Skip lint/format/commit config files (hooks only)")
702
+ .option("--no-ci", "Skip CI quality workflows")
703
+ .option("--no-guidelines", "Skip AI-agent guideline files (AGENTS.md/CLAUDE.md)")
704
+ .option("--mutation", "Also seed an opt-in nightly/manual mutation CI job (never a PR gate)")
705
+ .option("--only <dirs...>", "Harden only these language roots (e.g. frontend backend)")
706
+ .option("--exclude <globs...>", "Skip language roots matching these globs (e.g. wrappers)")
707
+ .option("--report", "Read-only: show what kj would add/improve, change nothing")
708
+ .option("--interactive", "Adopt the kj standard piece by piece (default keeps yours)")
709
+ .option("--dry-run", "Show what would change without writing")
710
+ .option("--json", "Emit machine-readable JSON")
711
+ .action(async (flags) => {
712
+ await withConfig(pkgVersion, "harden", flags, async ({ logger }) => {
713
+ await hardenCommand({
714
+ profile: flags.profile,
715
+ config: flags.config !== false,
716
+ ci: flags.ci !== false,
717
+ guidelines: flags.guidelines !== false,
718
+ mutation: Boolean(flags.mutation),
719
+ only: flags.only ?? [],
720
+ exclude: flags.exclude ?? [],
721
+ report: Boolean(flags.report),
722
+ interactive: Boolean(flags.interactive),
723
+ dryRun: Boolean(flags.dryRun),
724
+ json: Boolean(flags.json),
725
+ logger,
726
+ });
727
+ });
728
+ });
729
+
730
+ program
731
+ .command("check")
732
+ .description("Verify the quality harness installed by kj harden (drift gate)")
733
+ .option("--profile <name>", "minimal | standard | strict", "standard")
734
+ .option("--json", "Emit machine-readable JSON")
735
+ .action(async (flags) => {
736
+ const code = await withConfig(pkgVersion, "check", flags, async ({ logger }) =>
737
+ checkCommand({ profile: flags.profile, json: Boolean(flags.json), logger })
738
+ );
739
+ if (Number.isInteger(code)) process.exit(code);
740
+ });
741
+
742
+ program
743
+ .command("mutate")
744
+ .description("Diff-scoped mutation testing (¿cazan tus tests los mutantes de tu cambio?)")
745
+ .argument("[path]", "Target explícito a mutar (omite el diff)")
746
+ .option("--since <ref>", "Ref git contra la que sacar el diff", "HEAD~1")
747
+ .option("--max-survivors <n>", "Supervivientes tolerados antes de exit 1", "0")
748
+ .option("--json", "Emitir el resultado normalizado como JSON")
749
+ .action(async (pathArg, flags) => {
750
+ const code = await withConfig(pkgVersion, "mutate", flags, async ({ logger }) =>
751
+ mutateCommand({
752
+ path: pathArg,
753
+ since: flags.since,
754
+ maxSurvivors: Number(flags.maxSurvivors),
755
+ json: Boolean(flags.json),
756
+ logger,
757
+ })
758
+ );
759
+ if (Number.isInteger(code)) process.exit(code);
760
+ });
761
+
762
+ // KJC-TSK-0582: index of the advanced/specialized commands kept out of the
763
+ // flat `kj --help` list. Descriptions are read from commander itself so they
764
+ // never drift from each command's own --description.
765
+ program
766
+ .command("advanced")
767
+ .description("List advanced & specialized commands, grouped by area")
768
+ .action(() => {
769
+ const descriptions = Object.fromEntries(program.commands.map((c) => [c.name(), c.description()]));
770
+ console.log(formatAdvancedIndex(descriptions));
771
+ });
772
+ }