@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,432 @@
1
+ export const tools = [
2
+ {
3
+ name: "kj_init",
4
+ description: "Initialize karajan-code config, review rules, and SonarQube",
5
+ inputSchema: {
6
+ type: "object",
7
+ properties: {
8
+ kjHome: { type: "string", description: "Optional KJ_HOME directory" },
9
+ timeoutMs: { type: "number", description: "Optional command timeout in ms" }
10
+ }
11
+ }
12
+ },
13
+ {
14
+ name: "kj_doctor",
15
+ description: "Check system dependencies, agent CLIs, ports, tokens and MCP health — auto-remediates when possible",
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ kjHome: { type: "string" },
20
+ timeoutMs: { type: "number" },
21
+ checkOnly: { type: "boolean", description: "Detect only, do not apply fixes" },
22
+ yes: { type: "boolean", description: "Auto-confirm prompts for invasive remediations" },
23
+ json: { type: "boolean", description: "Emit machine-readable JSON output" },
24
+ verbose: { type: "boolean", description: "Include fix hints and timing per check" }
25
+ }
26
+ }
27
+ },
28
+ {
29
+ name: "kj_config",
30
+ description: "Show kj configuration",
31
+ inputSchema: {
32
+ type: "object",
33
+ properties: {
34
+ json: { type: "boolean" },
35
+ kjHome: { type: "string" }
36
+ }
37
+ }
38
+ },
39
+ {
40
+ name: "kj_scan",
41
+ description: "Run SonarQube scan for current project",
42
+ inputSchema: {
43
+ type: "object",
44
+ properties: {
45
+ kjHome: { type: "string" },
46
+ sonarToken: { type: "string" },
47
+ timeoutMs: { type: "number" }
48
+ }
49
+ }
50
+ },
51
+ {
52
+ name: "kj_run",
53
+ description:
54
+ "Run the full Karajan pipeline. IMPORTANT: Pass the user's task description exactly as they wrote it. Do NOT group, split, reorder, or modify tasks yourself. Karajan handles decomposition, role activation, iteration, and quality gates internally. Do NOT override pipeline parameters (enableHuReviewer, mode, methodology) unless the user explicitly requested it. If you have observations about the task, use kj_suggest instead.",
55
+ inputSchema: {
56
+ type: "object",
57
+ properties: {
58
+ task: { type: "string", description: "Task description for the coder (can include a Planning Game card ID like KJC-TSK-0042). Either `task` or `taskFile` is required." },
59
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md (or any text file) whose contents become the task description. Relative paths resolve against projectDir." },
60
+ plan: { type: "string", description: "Plan ID from kj_plan. Loads persisted plan context and skips researcher/architect/planner stages." },
61
+ projectDir: { type: "string", description: "Absolute path to the project directory. Required when KJ MCP server runs from a different directory than the target project." },
62
+ pgTask: { type: "string", description: "Planning Game card ID (e.g., KJC-TSK-0042). If provided, fetches full card details as task context and updates card status on completion." },
63
+ pgProject: { type: "string", description: "Planning Game project ID (e.g., 'Karajan Code'). Required when pgTask is used." },
64
+ planner: { type: "string" },
65
+ coder: { type: "string" },
66
+ reviewer: { type: "string" },
67
+ refactorer: { type: "string" },
68
+ plannerModel: { type: "string" },
69
+ coderModel: { type: "string" },
70
+ reviewerModel: { type: "string" },
71
+ refactorerModel: { type: "string" },
72
+ enablePlanner: { type: "boolean" },
73
+ enableReviewer: { type: "boolean" },
74
+ enableRefactorer: { type: "boolean" },
75
+ enableResearcher: { type: "boolean" },
76
+ enableTester: { type: "boolean" },
77
+ enableSecurity: { type: "boolean" },
78
+ enableImpeccable: { type: "boolean" },
79
+ enablePerf: { type: "boolean" },
80
+ enableTriage: { type: "boolean" },
81
+ enableDiscover: { type: "boolean" },
82
+ enableArchitect: { type: "boolean" },
83
+ enableHuReviewer: { type: "boolean" },
84
+ architectModel: { type: "string" },
85
+ huFile: { type: "string", description: "Path to YAML file with HU stories to certify before coding" },
86
+ enableSerena: { type: "boolean" },
87
+ enableCi: { type: "boolean", description: "Enable Karajan CI (early PR + dispatch comments/reviews)" },
88
+ reviewerFallback: { type: "string" },
89
+ reviewerRetries: { type: "number" },
90
+ mode: { type: "string" },
91
+ maxIterations: { type: "number" },
92
+ maxIterationMinutes: { type: "number" },
93
+ maxTotalMinutes: { type: "number" },
94
+ baseBranch: { type: "string" },
95
+ baseRef: { type: "string" },
96
+ methodology: { type: "string", enum: ["tdd", "standard"] },
97
+ autoCommit: { type: "boolean" },
98
+ autoPush: { type: "boolean" },
99
+ autoPr: { type: "boolean" },
100
+ autoRebase: { type: "boolean" },
101
+ branchPrefix: { type: "string" },
102
+ autoSimplify: { type: "boolean", description: "Auto-simplify pipeline for simple tasks (level trivial/simple). Disable with false to force full pipeline." },
103
+ smartModels: { type: "boolean", description: "Enable/disable smart model selection based on triage complexity" },
104
+ checkpointInterval: { type: "number", description: "Minutes between interactive checkpoints (default: 5). Set 0 to disable." },
105
+ taskType: { type: "string", enum: ["sw", "infra", "doc", "add-tests", "refactor"], description: "Explicit task type for policy resolution. Overrides triage classification." },
106
+ quiet: { type: "boolean", description: "Suppress raw agent output lines, show only stage status (default: true). Set false for verbose output." },
107
+ noSonar: { type: "boolean" },
108
+ design: { type: "boolean", description: "Activate design refactoring mode. Impeccable role applies design changes instead of just auditing." },
109
+ enableSonarcloud: { type: "boolean", description: "Enable SonarCloud scan (complementary to SonarQube)" },
110
+ kjHome: { type: "string" },
111
+ sonarToken: { type: "string" },
112
+ timeoutMs: { type: "number" },
113
+ domain: { type: "string", description: "Domain knowledge: inline text describing the project domain, or absolute path to a .md file. Auto-saved to .karajan/domains/ for the curator." },
114
+ brain: { type: "string", enum: ["on", "off"], description: "Brain decisor: on|off. Controls whether intent-driven routing overrides pipeline flags." },
115
+ forceRole: { type: "array", items: { type: "string" }, description: "Force roles ON regardless of triage (e.g. [\"security\"])" },
116
+ skipRole: { type: "array", items: { type: "string" }, description: "Force roles OFF regardless of triage (e.g. [\"tester\"])" },
117
+ specReviewMode: { type: "string", enum: ["auto", "skip"], description: "Pre-pipeline spec-reviewer behaviour (KJC-PCS-0048). `auto` (default): the role runs, findings stream to the client via progress events; the pipeline continues regardless. `skip`: bypass the reviewer entirely (mirrors the --skip-spec-review CLI flag)." }
118
+ }
119
+ }
120
+ },
121
+ {
122
+ name: "kj_resume",
123
+ description:
124
+ "Resume a paused, stopped, or failed session by ID. For paused sessions, provide an answer. For stopped/failed sessions, re-runs the flow from scratch. Sends real-time progress notifications via MCP logging.",
125
+ inputSchema: {
126
+ type: "object",
127
+ required: ["sessionId"],
128
+ properties: {
129
+ sessionId: { type: "string", description: "Session ID to resume" },
130
+ answer: { type: "string", description: "Answer to the question that caused the pause" },
131
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
132
+ kjHome: { type: "string" }
133
+ }
134
+ }
135
+ },
136
+ {
137
+ name: "kj_report",
138
+ description: "Read latest or list session reports. Use trace=true for chronological stage-by-stage breakdown with timing and token usage.",
139
+ inputSchema: {
140
+ type: "object",
141
+ properties: {
142
+ list: { type: "boolean" },
143
+ sessionId: { type: "string" },
144
+ format: { type: "string", enum: ["text", "json"] },
145
+ trace: { type: "boolean", description: "Show chronological trace of all pipeline stages" },
146
+ currency: { type: "string", enum: ["usd", "eur"], description: "Display costs in this currency" },
147
+ pgTask: { type: "string", description: "Filter reports by Planning Game card ID (e.g., KJC-TSK-0042)" },
148
+ kjHome: { type: "string" }
149
+ }
150
+ }
151
+ },
152
+ {
153
+ name: "kj_roles",
154
+ description: "List pipeline roles or show the template instructions for a specific role. Use action='list' to see all roles with their provider and status. Use action='show' with roleName to read the .md template.",
155
+ inputSchema: {
156
+ type: "object",
157
+ properties: {
158
+ action: { type: "string", enum: ["list", "show"], description: "Action: list all roles or show a specific role template" },
159
+ roleName: { type: "string", description: "Role name to show (e.g. coder, reviewer, triage, reviewer-paranoid)" },
160
+ kjHome: { type: "string" }
161
+ }
162
+ }
163
+ },
164
+ {
165
+ name: "kj_agents",
166
+ description: "List or change which AI agent (provider) is assigned to each pipeline role. Use action='list' to see current assignments. Use action='set' with role and provider to change it persistently (writes to kj.config.yml, no restart needed).",
167
+ inputSchema: {
168
+ type: "object",
169
+ properties: {
170
+ action: { type: "string", enum: ["list", "set"], description: "Action: list current agents or set a role's provider" },
171
+ role: { type: "string", description: "Role to change (e.g. coder, reviewer, planner, triage)" },
172
+ provider: { type: "string", description: "New provider to assign (e.g. claude, codex, gemini, aider)" },
173
+ kjHome: { type: "string" }
174
+ }
175
+ }
176
+ },
177
+ {
178
+ name: "kj_preflight",
179
+ description: "Confirm or adjust agent configuration before first kj_run/kj_code. REQUIRED before running any task via MCP. Show the config to the human, get their confirmation or adjustments, then call this tool with their response.",
180
+ inputSchema: {
181
+ type: "object",
182
+ required: ["humanResponse"],
183
+ properties: {
184
+ humanResponse: { type: "string", description: "The human's response: 'ok' to confirm defaults, or specific changes like 'use gemini as coder'" },
185
+ coder: { type: "string", description: "Override coder for this session" },
186
+ reviewer: { type: "string", description: "Override reviewer for this session" },
187
+ tester: { type: "string", description: "Override tester for this session" },
188
+ security: { type: "string", description: "Override security for this session" },
189
+ solomon: { type: "string", description: "Override solomon for this session" },
190
+ enableTester: { type: "boolean", description: "Enable/disable tester for this session" },
191
+ enableSecurity: { type: "boolean", description: "Enable/disable security for this session" }
192
+ }
193
+ }
194
+ },
195
+ {
196
+ name: "kj_code",
197
+ description: "Run coder-only mode. Pass the user's task exactly as described. Do NOT split or reinterpret the task.",
198
+ inputSchema: {
199
+ type: "object",
200
+ properties: {
201
+ task: { type: "string", description: "Task description. Either `task` or `taskFile` is required." },
202
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
203
+ coder: { type: "string" },
204
+ coderModel: { type: "string" },
205
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
206
+ kjHome: { type: "string" }
207
+ }
208
+ }
209
+ },
210
+ {
211
+ name: "kj_review",
212
+ description: "Run reviewer-only mode against current diff. Do NOT filter or pre-process the diff before passing it.",
213
+ inputSchema: {
214
+ type: "object",
215
+ properties: {
216
+ task: { type: "string", description: "Task description. Either `task` or `taskFile` is required." },
217
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
218
+ reviewer: { type: "string" },
219
+ reviewerModel: { type: "string" },
220
+ baseRef: { type: "string" },
221
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
222
+ kjHome: { type: "string" }
223
+ }
224
+ }
225
+ },
226
+ {
227
+ name: "kj_status",
228
+ description: "Show real-time status and log of the current or last Karajan run. Returns a parsed status (current stage, agent, iteration, errors) plus recent log lines. Use this to monitor progress while kj_run/kj_plan/kj_code is executing.",
229
+ inputSchema: {
230
+ type: "object",
231
+ properties: {
232
+ lines: { type: "number", description: "Number of log lines to show (default 50)" }
233
+ }
234
+ }
235
+ },
236
+ {
237
+ name: "kj_plan",
238
+ description: "Generate implementation plan for a task. Pass the task as the user described it. Karajan's planner decides the approach.",
239
+ inputSchema: {
240
+ type: "object",
241
+ properties: {
242
+ task: { type: "string", description: "Task description. Either `task` or `taskFile` is required." },
243
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
244
+ planner: { type: "string" },
245
+ plannerModel: { type: "string" },
246
+ coder: { type: "string", description: "Legacy alias for planner" },
247
+ coderModel: { type: "string", description: "Legacy alias for plannerModel" },
248
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
249
+ kjHome: { type: "string" },
250
+ specReviewMode: { type: "string", enum: ["auto", "skip"], description: "Pre-planner spec-reviewer behaviour (KJC-PCS-0048). `auto` (default): runs the reviewer, findings stream as progress, planner continues. `skip`: bypass entirely." }
251
+ }
252
+ }
253
+ },
254
+ {
255
+ name: "kj_discover",
256
+ description: "Analyze a task for gaps, ambiguities, and missing information before execution. Returns a verdict (ready/needs_validation) with structured gap list. Can read task details from Planning Game if pgTask is provided.",
257
+ inputSchema: {
258
+ type: "object",
259
+ properties: {
260
+ task: { type: "string", description: "Task description to analyze for gaps. Either `task` or `taskFile` is required." },
261
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
262
+ mode: { type: "string", enum: ["gaps", "momtest", "wendel", "classify", "jtbd"], description: "Discovery mode: gaps (default), momtest (Mom Test questions), wendel (behavior change checklist), classify (START/STOP/DIFFERENT), or jtbd (Jobs-to-be-Done)" },
263
+ context: { type: "string", description: "Additional context for the analysis (e.g., research output)" },
264
+ pgTask: { type: "string", description: "Planning Game card ID (e.g., KJC-TSK-0042). If provided, fetches full card details as additional context." },
265
+ pgProject: { type: "string", description: "Planning Game project ID. Required when pgTask is used." },
266
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
267
+ kjHome: { type: "string" }
268
+ }
269
+ }
270
+ },
271
+ {
272
+ name: "kj_triage",
273
+ description: "Classify task complexity and recommend which pipeline roles to activate. Returns level (trivial/simple/medium/complex), taskType, recommended roles, and optional decomposition.",
274
+ inputSchema: {
275
+ type: "object",
276
+ properties: {
277
+ task: { type: "string", description: "Task description to classify. Either `task` or `taskFile` is required." },
278
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
279
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
280
+ kjHome: { type: "string" }
281
+ }
282
+ }
283
+ },
284
+ {
285
+ name: "kj_researcher",
286
+ description: "Research the codebase for a task. Identifies affected files, patterns, constraints, prior decisions, risks, and test coverage.",
287
+ inputSchema: {
288
+ type: "object",
289
+ properties: {
290
+ task: { type: "string", description: "Task description to research. Either `task` or `taskFile` is required." },
291
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
292
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
293
+ kjHome: { type: "string" }
294
+ }
295
+ }
296
+ },
297
+ {
298
+ name: "kj_architect",
299
+ description: "Design solution architecture for a task. Returns layers, patterns, data model, API contracts, tradeoffs, and a verdict (ready/needs_clarification).",
300
+ inputSchema: {
301
+ type: "object",
302
+ properties: {
303
+ task: { type: "string", description: "Task description to architect. Either `task` or `taskFile` is required." },
304
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file." },
305
+ context: { type: "string", description: "Additional context (e.g., researcher output)" },
306
+ projectDir: { type: "string", description: "Absolute path to the project directory" },
307
+ kjHome: { type: "string" }
308
+ }
309
+ }
310
+ },
311
+ {
312
+ name: "kj_audit",
313
+ description: "Analyze codebase health without modifying files. Returns findings across security, code quality, performance, architecture, and testing dimensions.",
314
+ inputSchema: {
315
+ type: "object",
316
+ properties: {
317
+ task: { type: "string", description: "Optional focus for the audit. If absent (and no taskFile), defaults to a full-codebase analysis." },
318
+ taskFile: { type: "string", description: "Alternative to `task`: path to a .md/text file with the audit focus." },
319
+ projectDir: { type: "string", description: "Absolute path to the project to audit" },
320
+ dimensions: { type: "string", description: "Comma-separated dimensions to analyze: security,codeQuality,performance,architecture,testing (default: all)" },
321
+ kjHome: { type: "string" }
322
+ }
323
+ }
324
+ },
325
+ {
326
+ name: "kj_board",
327
+ description: "Start, stop, or check status of the HU Board dashboard",
328
+ inputSchema: {
329
+ type: "object",
330
+ properties: {
331
+ action: { type: "string", enum: ["start", "stop", "status"], description: "Action to perform (default: status)" },
332
+ port: { type: "number", description: "Port (default: 4000)" }
333
+ }
334
+ }
335
+ },
336
+ {
337
+ name: "kj_hu",
338
+ description: "Manage user stories (HUs) in the local board",
339
+ inputSchema: {
340
+ type: "object",
341
+ required: ["action"],
342
+ properties: {
343
+ action: { type: "string", enum: ["create", "update", "list", "get"], description: "Action to perform" },
344
+ title: { type: "string", description: "HU title (required for create)" },
345
+ description: { type: "string", description: "HU description" },
346
+ acceptanceCriteria: { type: "string", description: "Acceptance criteria" },
347
+ huId: { type: "string", description: "HU ID (required for update/get)" },
348
+ status: { type: "string", description: "HU status (for create/update)", enum: ["pending", "coding", "reviewing", "done", "failed", "blocked"] },
349
+ projectDir: { type: "string", description: "Project directory (defaults to cwd)" }
350
+ }
351
+ }
352
+ },
353
+ {
354
+ name: "kj_suggest",
355
+ description: "Propose an observation or suggestion to Karajan's Solomon engine. Solomon will evaluate it and decide whether to accept, reject, or ask the human. You CANNOT override pipeline decisions through this tool, only propose.",
356
+ inputSchema: {
357
+ type: "object",
358
+ required: ["suggestion"],
359
+ properties: {
360
+ suggestion: { type: "string", description: "What you observed or want to propose" },
361
+ context: { type: "string", description: "Additional context (current HU, iteration, etc.)" },
362
+ projectDir: { type: "string", description: "Project directory" }
363
+ }
364
+ }
365
+ },
366
+ {
367
+ name: "kj_skills",
368
+ description: "Manage OpenSkills for domain-specific agent knowledge. Install skills from the marketplace or GitHub repos to give coders domain expertise.",
369
+ inputSchema: {
370
+ type: "object",
371
+ properties: {
372
+ action: { type: "string", enum: ["install", "remove", "list", "read"], description: "Action to perform" },
373
+ source: { type: "string", description: "Skill source: marketplace name, GitHub URL, or local path (for install)" },
374
+ name: { type: "string", description: "Skill name (for remove/read)" },
375
+ global: { type: "boolean", description: "Install globally (~/.agent/skills/) instead of project-local" },
376
+ projectDir: { type: "string", description: "Project directory" }
377
+ },
378
+ required: ["action"]
379
+ }
380
+ },
381
+ {
382
+ name: "kj_undo",
383
+ description: "Revert the last pipeline run by resetting to the pre-pipeline commit. Default: soft reset (keeps changes staged). Use hard=true to discard all changes.",
384
+ inputSchema: {
385
+ type: "object",
386
+ properties: {
387
+ hard: { type: "boolean", description: "If true, discard all changes (git reset --hard). Default: false (soft reset, keeps changes staged)." },
388
+ projectDir: { type: "string", description: "Absolute path to the project directory" }
389
+ }
390
+ }
391
+ },
392
+ {
393
+ name: "kj_clean",
394
+ description: "Garbage-collect stale Karajan state: orphan plans (project dir no longer exists), finalised plans/sessions past their retention window, and HU story batches. Dry-run by default; pass yes=true to actually delete. Use nuke=true to wipe everything (retention=0 on every bucket + drop the HU board SQLite DB).",
395
+ inputSchema: {
396
+ type: "object",
397
+ properties: {
398
+ yes: { type: "boolean", description: "If true, actually delete. Default false (dry-run: returns the list of items that would be removed without touching disk)." },
399
+ nuke: { type: "boolean", description: "If true, retention=0 on every bucket + wipe the HU board DB (stops the board first if running). The \"I want it all gone right now\" button." },
400
+ planDays: { type: "number", description: "Keep finalised plans (approved/rejected/executed) for this many days. Default: 30." },
401
+ draftDays: { type: "number", description: "Keep draft plans for this many days. Default: 60." },
402
+ sessionDays: { type: "number", description: "Keep finalised sessions for this many days. Default: 7." },
403
+ huDays: { type: "number", description: "Keep HU story batches for this many days. Default: 14." }
404
+ }
405
+ }
406
+ },
407
+ {
408
+ name: "kj_rag_query",
409
+ description: "Run a semantic search across the indexed Karajan plans, onboarding briefs and (optionally) project source code. Returns the top-K nearest chunks with their metadata so the agent can quote prior decisions, locate where a concept was last implemented, or pull architectural context without re-walking the repo. The store is empty until `kj_rag_index` (or `kj rag index` CLI) has been run at least once on this project; in that case the response carries `empty: true`.",
410
+ inputSchema: {
411
+ type: "object",
412
+ properties: {
413
+ text: { type: "string", description: "The natural-language query." },
414
+ topK: { type: "number", description: "Max number of hits to return. Default: 5." },
415
+ scope: { type: "string", description: "Filter by chunk kind: 'plans' | 'code' | 'onboarding' | 'all' (default)." },
416
+ projectDir: { type: "string", description: "Absolute path to the project directory" }
417
+ },
418
+ required: ["text"]
419
+ }
420
+ },
421
+ {
422
+ name: "kj_rag_index",
423
+ description: "(Re)index this project's Karajan-managed assets — every plan-*.json under ~/.karajan/plans/<slug>/ plus the onboarding brief at ~/.karajan/onboarding/<slug>.md — into the local vector store. Idempotent: a re-run replaces the chunks for each source, never appends duplicates. Pass `withSources: true` to also index the project's JS/TS files (skips node_modules / .git / dist / etc.). Required as a one-time bootstrap before kj_rag_query returns anything; safe to re-run after every `kj plan generate`.",
424
+ inputSchema: {
425
+ type: "object",
426
+ properties: {
427
+ withSources: { type: "boolean", description: "Also index .js/.ts files under projectDir. Default false." },
428
+ projectDir: { type: "string", description: "Absolute path to the project directory" }
429
+ }
430
+ }
431
+ }
432
+ ];
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Diff-scoping for mutation testing. Translates a git range (`--since <ref>`)
3
+ * into changed source files + line ranges, then into the scope flags of the
4
+ * tool resolved by the registry (`src/mutate/tool-registry.js`). Mutating only
5
+ * what the coder just touched is what makes mutation testing cheap and useful.
6
+ * The git call is injectable so the pure logic is testable without a repo.
7
+ */
8
+
9
+ import { runCommand } from "../utils/process.js";
10
+ import { getMutationTool } from "./tool-registry.js";
11
+
12
+ const SOURCE_EXTENSIONS = {
13
+ javascript: [".js", ".mjs", ".cjs", ".jsx"],
14
+ typescript: [".ts", ".tsx"],
15
+ python: [".py"],
16
+ php: [".php"],
17
+ go: [".go"],
18
+ java: [".java"],
19
+ };
20
+
21
+ const HUNK = /^@@ -\S+ \+(\d+)(?:,(\d+))?/;
22
+
23
+ /**
24
+ * Parse `git diff --unified=0` into new-side line ranges per file. Deleted
25
+ * files (`+++ /dev/null`) are omitted — there is nothing to mutate.
26
+ * @returns {Record<string, Array<[number, number]>>}
27
+ */
28
+ export function parseUnifiedDiff(diffText) {
29
+ const ranges = {};
30
+ let current = null;
31
+ for (const line of String(diffText || "").split("\n")) {
32
+ if (line.startsWith("+++ ")) {
33
+ const target = line.slice(4).trim();
34
+ current = target === "/dev/null" ? null : target.replace(/^b\//, "");
35
+ if (current) ranges[current] ??= [];
36
+ continue;
37
+ }
38
+ if (!current) continue;
39
+ const match = HUNK.exec(line);
40
+ if (!match) continue;
41
+ const start = Number(match[1]);
42
+ const count = match[2] === undefined ? 1 : Number(match[2]);
43
+ if (count > 0) ranges[current].push([start, start + count - 1]);
44
+ }
45
+ return ranges;
46
+ }
47
+
48
+ /** @returns {string[]} source extensions for a language ([] if unsupported) */
49
+ export function sourceExtensions(language) {
50
+ return SOURCE_EXTENSIONS[language] ?? [];
51
+ }
52
+
53
+ /** Keep only files whose extension belongs to the language's source set. */
54
+ export function filterSourceFiles(files, language) {
55
+ const exts = sourceExtensions(language);
56
+ if (exts.length === 0) return [];
57
+ return files.filter((file) => exts.some((ext) => file.endsWith(ext)));
58
+ }
59
+
60
+ /**
61
+ * Build the tool's scope arguments for the changed source files. `ranges`
62
+ * (per-file changed line ranges) is only consumed by Stryker (`path:start-end`).
63
+ * @param {{language: string, files: string[], ranges?: Record<string, Array<[number, number]>>}} params
64
+ */
65
+ export function buildScope({ language, files, ranges }) {
66
+ const tool = getMutationTool(language);
67
+ if (!tool.supported) {
68
+ return { supported: false, reason: tool.reason, empty: true, args: [] };
69
+ }
70
+ const source = filterSourceFiles(files ?? [], language);
71
+ if (source.length === 0) {
72
+ return { supported: true, tool: tool.id, empty: true, targets: [], args: [] };
73
+ }
74
+ const targets =
75
+ tool.id === "stryker" && ranges
76
+ ? source.flatMap((file) =>
77
+ (ranges[file] ?? [[undefined, undefined]]).map(([start, end]) =>
78
+ start === undefined ? file : `${file}:${start}-${end}`,
79
+ ),
80
+ )
81
+ : source;
82
+ const value = targets.join(tool.scope.separator);
83
+ const args = tool.scope.flag ? [tool.scope.flag, value] : [value];
84
+ return { supported: true, tool: tool.id, empty: false, targets, args };
85
+ }
86
+
87
+ /**
88
+ * Fetch the diff for `since..toRef` and compute the mutation scope. `run` is
89
+ * the injectable git runner (defaults to `runCommand`).
90
+ * @param {{since: string, language: string, toRef?: string, run?: Function}} params
91
+ */
92
+ export async function getDiffScope({ since, language, toRef = "HEAD", staged = false, run = runCommand }) {
93
+ // MUT-A (KJC-TSK-0716): staged=true scopea al ÍNDICE (git diff --cached) —
94
+ // lo que el review gate evalúa. since..HEAD con since=HEAD sería un diff
95
+ // VACÍO y el pre-gate no mutaría nada (catch de codex, agravado).
96
+ const args = staged ? ["diff", "--unified=0", "--cached"] : ["diff", "--unified=0", `${since}..${toRef}`];
97
+ const result = await run("git", args).catch(
98
+ () => null,
99
+ );
100
+ if (!result || result.exitCode !== 0) {
101
+ return { supported: true, empty: true, targets: [], args: [] };
102
+ }
103
+ const ranges = parseUnifiedDiff(result.stdout);
104
+ return buildScope({ language, files: Object.keys(ranges), ranges });
105
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Reviewer opt-in mutation signal (KJC-TSK-0588). OFF by default: only when
3
+ * `KJ_REVIEW_MUTATION` is set does the reviewer run `kj mutate` scoped to the
4
+ * diff and fold surviving mutants into its verdict as a weak-test signal.
5
+ * A null return means "add nothing" → the default-off prompt stays identical.
6
+ */
7
+
8
+ import { mutateCommand } from "../commands/mutate.js";
9
+
10
+ const DEFAULT_SINCE = "HEAD~1";
11
+ const ENABLED = /^(1|true|yes|on)$/i;
12
+
13
+ /** True when the reviewer mutation opt-in is switched on via env. */
14
+ export function isMutationReviewEnabled(env = process.env) {
15
+ return ENABLED.test(String(env?.KJ_REVIEW_MUTATION ?? "").trim());
16
+ }
17
+
18
+ // Drives `kj mutate --json` over the diff, capturing its output instead of
19
+ // printing it, and returns {code, result} where result is the normalized JSON.
20
+ async function defaultRun({ since, projectDir }) {
21
+ const lines = [];
22
+ const code = await mutateCommand({
23
+ since,
24
+ projectDir,
25
+ json: true,
26
+ maxSurvivors: Number.POSITIVE_INFINITY,
27
+ logger: { info: (m) => lines.push(String(m)) },
28
+ });
29
+ const jsonLine = [...lines].reverse().find((l) => l.trim().startsWith("{"));
30
+ return { code, result: jsonLine ? JSON.parse(jsonLine) : null };
31
+ }
32
+
33
+ function unavailableNote() {
34
+ return [
35
+ "## Mutation testing (advisory)",
36
+ "Mutation testing was requested but could not run on this diff (unsupported",
37
+ "stack or tool unavailable). Treat it as unavailable — do not infer test",
38
+ "quality from its absence.",
39
+ ].join("\n");
40
+ }
41
+
42
+ function survivorSection(survivors) {
43
+ const lines = survivors.map((s) => `- ${s.file}:${s.line ?? "?"} (${s.mutator ?? s.status})`);
44
+ return [
45
+ "## Mutation testing (advisory signal)",
46
+ "The following mutants survived over the changed lines — the tests did not",
47
+ "catch these deliberate defects, so the covering tests are weak. Weigh this",
48
+ "as a signal about test quality, not as a hard blocker on its own:",
49
+ ...lines,
50
+ ].join("\n");
51
+ }
52
+
53
+ /**
54
+ * Build the reviewer's mutation-signal prompt section, or null to add nothing.
55
+ * `run` ({since, projectDir}) → {code, result} is injectable for tests.
56
+ * @returns {Promise<string|null>}
57
+ */
58
+ export async function buildReviewerMutationSignal({
59
+ enabled,
60
+ since = DEFAULT_SINCE,
61
+ projectDir = process.cwd(),
62
+ run = defaultRun,
63
+ } = {}) {
64
+ if (!enabled) return null;
65
+ let outcome;
66
+ try {
67
+ outcome = await run({ since, projectDir });
68
+ } catch {
69
+ return unavailableNote();
70
+ }
71
+ const { code, result } = outcome ?? {};
72
+ if (code === 1 || code === 2) return unavailableNote();
73
+ const survivors = result?.survived ?? [];
74
+ if (survivors.length === 0) return null;
75
+ return survivorSection(survivors);
76
+ }