@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,79 @@
1
+ /**
2
+ * ai-surface — MCP inventory with drift detection (KJC-TSK-0694).
3
+ *
4
+ * Every new tool an agent gains is one more access. An inventory nobody
5
+ * reconciles is "the feeling of control without the control", so kj check
6
+ * flags what APPEARED since the last run and asks the user to own it.
7
+ * A nudge, never a gate. ~/.claude.json is scoped to its global block plus
8
+ * THIS project's entry — other projects' MCPs are not reachable here.
9
+ */
10
+
11
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
12
+ import os from "node:os";
13
+ import path from "node:path";
14
+
15
+ const sources = (projectDir, home) => [
16
+ { file: path.join(projectDir, ".mcp.json"), format: "json" },
17
+ { file: path.join(home, ".claude.json"), format: "json" },
18
+ { file: path.join(home, ".codex", "config.toml"), format: "toml" },
19
+ { file: path.join(home, ".gemini", "settings.json"), format: "json" },
20
+ ];
21
+
22
+ function jsonServerNames(text, projectDir) {
23
+ try {
24
+ const parsed = JSON.parse(text);
25
+ const names = new Set(Object.keys(parsed.mcpServers || {}));
26
+ for (const name of Object.keys(parsed.projects?.[projectDir]?.mcpServers || {})) names.add(name);
27
+ return names;
28
+ } catch {
29
+ return new Set();
30
+ }
31
+ }
32
+
33
+ const tomlServerNames = (text) =>
34
+ new Set([...text.matchAll(/^\s*\[mcp_servers\.["']?([^\]"']+)["']?\]/gm)].map((m) => m[1]));
35
+
36
+ /** Sorted `name (config-file)` entries for every MCP reachable in this project. */
37
+ export function collectAiSurface({ projectDir = process.cwd(), home = os.homedir() } = {}) {
38
+ const surface = new Set();
39
+ for (const { file, format } of sources(projectDir, home)) {
40
+ if (!existsSync(file)) continue;
41
+ let text;
42
+ try { text = readFileSync(file, "utf8"); } catch { continue; }
43
+ const names = format === "toml" ? tomlServerNames(text) : jsonServerNames(text, projectDir);
44
+ for (const name of names) surface.add(`${name} (${path.basename(file)})`);
45
+ }
46
+ return [...surface].sort();
47
+ }
48
+
49
+ /**
50
+ * Diff the current surface against the last-seen snapshot and persist the
51
+ * new state. First run records the baseline silently.
52
+ */
53
+ export function checkAiSurface({ projectDir = process.cwd(), home = os.homedir(), statePath = path.join(os.homedir(), ".karajan", "ai-surface.json"), extraSurface = [] } = {}) {
54
+ // KJC-TSK-0728: extraSurface carries entries the (async) caller collected
55
+ // outside config files — e.g. observed agent CLIs as "grok (cli)" — so
56
+ // they ride the same snapshot and the same "NEW since last check" drift.
57
+ const surface = [...new Set([...collectAiSurface({ projectDir, home }), ...extraSurface])].sort();
58
+ let state = {};
59
+ try { state = JSON.parse(readFileSync(statePath, "utf8")); } catch { /* first run or corrupt → baseline */ }
60
+ const prev = Array.isArray(state[projectDir]) ? state[projectDir] : null;
61
+ const added = prev ? surface.filter((e) => !prev.includes(e)) : [];
62
+ const removed = prev ? prev.filter((e) => !surface.includes(e)) : [];
63
+ state[projectDir] = surface;
64
+ try {
65
+ mkdirSync(path.dirname(statePath), { recursive: true });
66
+ writeFileSync(statePath, JSON.stringify(state, null, 2));
67
+ } catch { /* read-only FS — inventory still reports, just cannot remember */ }
68
+ return { surface, added, removed, first: !prev };
69
+ }
70
+
71
+ /** One line for kj check output. */
72
+ export function formatAiSurface({ surface, added, removed, first }) {
73
+ const head = `ai surface: ${surface.length} MCP(s)`;
74
+ if (first) return `${head} — baseline recorded`;
75
+ const parts = [head];
76
+ if (added.length) parts.push(`NEW since last check: ${added.join(", ")} — approved by you?`);
77
+ if (removed.length) parts.push(`gone: ${removed.join(", ")}`);
78
+ return parts.join(" · ");
79
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ai-trash safety net availability check (KJC-TSK-0391).
3
+ * Surfaces a WARN in `kj doctor` when the `kj-trash` binary is missing,
4
+ * since the PreToolUse hook cannot snapshot destructive ops without it.
5
+ * The remediation is `kj-trash install --claude-code` once the binary is
6
+ * on PATH (the workspace ships it with karajan-code).
7
+ */
8
+
9
+ import { detectAiTrash } from "../utils/ai-trash.js";
10
+ import { STRATEGY } from "./types.js";
11
+
12
+ function createAiTrashCheck() {
13
+ return {
14
+ name: "ai-trash",
15
+ label: "ai-trash safety net",
16
+ strategy: STRATEGY.MANUAL,
17
+ async detect() {
18
+ const res = await detectAiTrash();
19
+ if (res.available) {
20
+ return { ok: true, severity: "info", detail: "kj-trash present — preventive safety net active" };
21
+ }
22
+ return {
23
+ ok: false,
24
+ severity: "warn",
25
+ detail: "kj-trash not found — destructive ops unprotected",
26
+ fix: "Install karajan-code globally (npm i -g karajan-code) so kj-trash is on PATH, then run `kj-trash install --claude-code`",
27
+ };
28
+ },
29
+ };
30
+ }
31
+
32
+ export function getAiTrashChecks() {
33
+ return [createAiTrashCheck()];
34
+ }
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Binary / CLI availability checks.
3
+ *
4
+ * Covers:
5
+ * - Agent CLIs (claude, codex, gemini, aider, opencode)
6
+ * - Core binaries (node, npm, git)
7
+ * - Docker
8
+ * - Serena MCP (optional)
9
+ *
10
+ * All binary checks use `strategy: "manual"` because auto-installing binaries
11
+ * is invasive and platform-specific. Exception: Serena is `"prompt"` (we know
12
+ * the install command and can offer to run it).
13
+ */
14
+
15
+ import { checkBinary, KNOWN_AGENTS, detectObservedAgents } from "../utils/agent-detect.js";
16
+ import { runCommand } from "../utils/process.js";
17
+ import { withDocLink } from "../utils/doc-links.js";
18
+ import { getInstallHint, appliesToStack } from "../utils/install-hints.js";
19
+ import { STRATEGY } from "./types.js";
20
+
21
+ /**
22
+ * Check the presence of a named agent CLI (claude/codex/gemini/aider).
23
+ */
24
+ function createAgentCheck(agent) {
25
+ return {
26
+ name: `agent:${agent.name}`,
27
+ label: `Agent: ${agent.name}`,
28
+ strategy: STRATEGY.MANUAL,
29
+ async detect() {
30
+ const result = await checkBinary(agent.name);
31
+ return {
32
+ ok: result.ok,
33
+ severity: "warn", // missing one agent CLI shouldn't block — user may not use it
34
+ detail: result.ok ? `${result.version} (${result.path})` : "Not found",
35
+ fix: result.ok ? undefined : withDocLink(`Install: ${agent.install}`, "agent_not_found"),
36
+ };
37
+ },
38
+ };
39
+ }
40
+
41
+ /**
42
+ * KJC-TSK-0728 — ONE aggregate line for the observation census (agent CLIs
43
+ * kj sees but does not drive). Only FOUND CLIs are listed; the missing ones
44
+ * make no noise, and the check never fails. `detector` is injectable for
45
+ * tests.
46
+ */
47
+ export function createObservedAgentsCheck({ detector = detectObservedAgents } = {}) {
48
+ return {
49
+ name: "agents:observed",
50
+ label: "Agent CLIs observed (not driven)",
51
+ strategy: STRATEGY.MANUAL,
52
+ async detect() {
53
+ let found = [];
54
+ try {
55
+ found = (await detector()).filter((a) => a.available);
56
+ } catch { /* census is best-effort */ }
57
+ return {
58
+ ok: true,
59
+ severity: "info",
60
+ detail: found.length
61
+ ? found.map((a) => `${a.name} (${(a.version || "").split(" ").at(-1) || "?"})`).join(", ")
62
+ : "none detected",
63
+ };
64
+ },
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Check the presence of a core binary (node, npm, git).
70
+ */
71
+ function createCoreBinaryCheck(bin) {
72
+ return {
73
+ name: bin,
74
+ label: bin,
75
+ strategy: STRATEGY.MANUAL,
76
+ async detect() {
77
+ const result = await checkBinary(bin);
78
+ return {
79
+ ok: result.ok,
80
+ severity: "fail",
81
+ detail: result.ok ? result.version : "Not found",
82
+ fix: result.ok ? undefined : `Install ${bin} from its official website.`,
83
+ };
84
+ },
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Docker check. Manual strategy (platform-dependent install).
90
+ */
91
+ function createDockerCheck() {
92
+ return {
93
+ name: "docker",
94
+ label: "Docker",
95
+ strategy: STRATEGY.MANUAL,
96
+ async detect() {
97
+ const docker = await checkBinary("docker", "--version");
98
+ return {
99
+ ok: docker.ok,
100
+ severity: "warn", // only required if Sonar enabled; soft-fail here
101
+ detail: docker.ok ? docker.version : "Not found",
102
+ fix: docker.ok ? undefined : withDocLink("Install Docker: https://docs.docker.com/get-docker/", "sonar_docker"),
103
+ };
104
+ },
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Serena MCP (optional). Prompt strategy: we know how to install it.
110
+ */
111
+ function createSerenaCheck() {
112
+ return {
113
+ name: "serena",
114
+ label: "Serena MCP",
115
+ strategy: STRATEGY.MANUAL,
116
+ applies: (config) => config.serena?.enabled === true,
117
+ describe: "Install Serena via: uvx --from git+https://github.com/oraios/serena serena",
118
+ async detect() {
119
+ let ok;
120
+ try {
121
+ const res = await runCommand("serena", ["--version"]);
122
+ ok = res.exitCode === 0;
123
+ } catch {
124
+ ok = false;
125
+ }
126
+ return {
127
+ ok,
128
+ severity: "warn",
129
+ detail: ok ? "Available" : "Not found (prompts will still include Serena instructions)",
130
+ fix: ok ? undefined : "Install Serena: uvx --from git+https://github.com/oraios/serena serena --help",
131
+ };
132
+ },
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Audit-side external tool (semgrep, osv-scanner, lighthouse) check.
138
+ *
139
+ * These are not blockers: `kj audit` and `kj webperf` degrade to
140
+ * available:false when missing. We surface them in `kj doctor` so the
141
+ * user can see at a glance which audit dimensions are active, and we
142
+ * point to `kj install-tools` for one-line remediation.
143
+ *
144
+ * `lighthouse` is stack-gated: only flagged when the project is
145
+ * frontend / fullstack. On backend-only projects the check is a no-op
146
+ * (returns ok:true with detail "n/a") to keep doctor output focused.
147
+ */
148
+ function createAuditToolCheck(tool, { gatedByStack = false, label }) {
149
+ return {
150
+ name: `audit-tool:${tool}`,
151
+ label,
152
+ strategy: STRATEGY.MANUAL,
153
+ async detect({ config } = {}) {
154
+ if (gatedByStack) {
155
+ // Stack detection is best-effort — failing here just means we
156
+ // treat the project as backend-only (skip the check). Keeps the
157
+ // doctor pipeline resilient to weird repos.
158
+ let stack = null;
159
+ try {
160
+ const { detectProjectStack } = await import("../utils/stack-detect.js");
161
+ stack = await detectProjectStack(config?.projectDir || process.cwd());
162
+ } catch { /* ignore */ }
163
+ if (!appliesToStack(tool, stack)) {
164
+ return { ok: true, severity: "info", detail: "n/a (no frontend stack detected)" };
165
+ }
166
+ }
167
+ const result = await checkBinary(tool);
168
+ if (result.ok) {
169
+ return { ok: true, severity: "info", detail: result.version || "available" };
170
+ }
171
+ const hint = await getInstallHint(tool);
172
+ const fixLine = hint.command
173
+ ? `Run \`kj install-tools --only ${tool}\` or: ${hint.command}`
174
+ : `Run \`kj install-tools --only ${tool}\` or see ${hint.manualUrl}`;
175
+ return {
176
+ ok: false,
177
+ severity: "warn",
178
+ detail: "Not found — `kj audit` dimension will degrade",
179
+ fix: fixLine,
180
+ extra: { tool, suggested: hint.command, manager: hint.manager, manualUrl: hint.manualUrl },
181
+ };
182
+ },
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Aggregate: all binary-related checks for the current config.
188
+ * @returns {import("./types.js").Check[]}
189
+ */
190
+ export function getBinaryChecks() {
191
+ const checks = [];
192
+ for (const agent of KNOWN_AGENTS) {
193
+ checks.push(createAgentCheck(agent));
194
+ }
195
+ checks.push(createObservedAgentsCheck());
196
+ for (const bin of ["node", "npm", "git"]) {
197
+ checks.push(createCoreBinaryCheck(bin));
198
+ }
199
+ checks.push(createDockerCheck());
200
+ checks.push(createSerenaCheck());
201
+ // KJC-TSK v2.18 — surface audit-side tools in doctor so the user knows
202
+ // which dimensions will work. lighthouse is gated to frontend stacks.
203
+ checks.push(createAuditToolCheck("semgrep", { label: "Semgrep (audit/security)" }));
204
+ checks.push(createAuditToolCheck("osv-scanner", { label: "OSV-Scanner (audit/security)" }));
205
+ checks.push(createAuditToolCheck("lighthouse", { label: "Lighthouse (webperf)", gatedByStack: true }));
206
+ return checks;
207
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * CI infrastructure checks: required workflows, gh CLI, and GitHub secrets.
3
+ * Only applies when `config.ci.enabled === true`.
4
+ */
5
+
6
+ import path from "node:path";
7
+ import { exists } from "../utils/fs.js";
8
+ import { runCommand } from "../utils/process.js";
9
+ import { checkBinary } from "../utils/agent-detect.js";
10
+ import { STRATEGY } from "./types.js";
11
+
12
+ const REQUIRED_WORKFLOWS = ["kj-ci-gateway.yml", "automerge.yml", "houston-override.yml"];
13
+
14
+ function ciEnabled(config) {
15
+ return config.ci?.enabled === true;
16
+ }
17
+
18
+ function createWorkflowCheck(workflow) {
19
+ return {
20
+ name: `ci:workflow:${workflow}`,
21
+ label: `CI workflow: ${workflow}`,
22
+ strategy: STRATEGY.MANUAL,
23
+ applies: ciEnabled,
24
+ async detect({ config }) {
25
+ const projectDir = config.projectDir || process.cwd();
26
+ const wfPath = path.join(projectDir, ".github", "workflows", workflow);
27
+ const wfExists = await exists(wfPath);
28
+ return {
29
+ ok: wfExists,
30
+ severity: "fail",
31
+ detail: wfExists ? "Found" : "Not found",
32
+ fix: wfExists
33
+ ? undefined
34
+ : `Run 'kj init --scaffold-ci' or copy from karajan-code/templates/workflows/${workflow}`,
35
+ };
36
+ },
37
+ };
38
+ }
39
+
40
+ function createGhCliCheck() {
41
+ return {
42
+ name: "ci:gh",
43
+ label: "CI: gh CLI",
44
+ strategy: STRATEGY.MANUAL,
45
+ applies: ciEnabled,
46
+ async detect() {
47
+ const gh = await checkBinary("gh");
48
+ return {
49
+ ok: gh.ok,
50
+ severity: "fail",
51
+ detail: gh.ok ? gh.version : "Not found",
52
+ fix: gh.ok ? undefined : "Install GitHub CLI: https://cli.github.com/",
53
+ };
54
+ },
55
+ };
56
+ }
57
+
58
+ function createGhSecretsCheck() {
59
+ return {
60
+ name: "ci:secrets",
61
+ label: "CI: GitHub secrets",
62
+ strategy: STRATEGY.MANUAL,
63
+ applies: ciEnabled,
64
+ async detect() {
65
+ try {
66
+ const { detectRepo } = await import("../ci/repo.js");
67
+ const repo = await detectRepo();
68
+ if (!repo) {
69
+ return { ok: true, severity: "info", detail: "No GitHub repo detected (skipped)" };
70
+ }
71
+ const res = await runCommand("gh", ["api", `repos/${repo}/actions/secrets`, "--jq", ".secrets[].name"]);
72
+ if (res.exitCode !== 0) {
73
+ return { ok: true, severity: "info", detail: "Cannot query secrets (gh unauthenticated?)" };
74
+ }
75
+ const names = new Set(res.stdout.split("\n").map((s) => s.trim()));
76
+ const hasAppId = names.has("KJ_CI_APP_ID");
77
+ const hasKey = names.has("KJ_CI_PRIVATE_KEY");
78
+ const secretsOk = hasAppId && hasKey;
79
+ const missing = [!hasAppId && "KJ_CI_APP_ID", !hasKey && "KJ_CI_PRIVATE_KEY"].filter(Boolean).join(" ");
80
+ return {
81
+ ok: secretsOk,
82
+ severity: "fail",
83
+ detail: secretsOk ? "KJ_CI_APP_ID + KJ_CI_PRIVATE_KEY found" : `Missing: ${missing}`,
84
+ fix: secretsOk ? undefined : "Add KJ_CI_APP_ID and KJ_CI_PRIVATE_KEY as GitHub repository secrets",
85
+ };
86
+ } catch {
87
+ return { ok: true, severity: "info", detail: "Cannot check secrets (unexpected error, skipped)" };
88
+ }
89
+ },
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Aggregate of CI checks. Each check carries its own `applies` so the runner
95
+ * marks them SKIPPED when CI is disabled.
96
+ */
97
+ export function getCiChecks() {
98
+ const checks = [];
99
+ for (const wf of REQUIRED_WORKFLOWS) {
100
+ checks.push(createWorkflowCheck(wf));
101
+ }
102
+ checks.push(createGhCliCheck());
103
+ checks.push(createGhSecretsCheck());
104
+ return checks;
105
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Config and rule-file checks.
3
+ *
4
+ * Covers:
5
+ * - kj.config.yml existence (strategy: prompt — offer to run kj init)
6
+ * - Review / coder rules discovery (strategy: none, informational)
7
+ * - Agent config files: ~/.claude.json, ~/.codex/config.toml,
8
+ * ~/.karajan/kj.config.yml (strategy: manual — structural fixes needed)
9
+ */
10
+
11
+ import fs from "node:fs/promises";
12
+ import os from "node:os";
13
+ import path from "node:path";
14
+ import { exists } from "../utils/fs.js";
15
+ import { getConfigPath } from "../config.js";
16
+ import { resolveRoleMdPath, loadFirstExisting } from "../roles/base-role.js";
17
+ import { withDocLink } from "../utils/doc-links.js";
18
+ import { STRATEGY } from "./types.js";
19
+
20
+ /**
21
+ * kj.config.yml presence check.
22
+ */
23
+ function createConfigFileCheck() {
24
+ return {
25
+ name: "config",
26
+ label: "Config file",
27
+ strategy: STRATEGY.PROMPT,
28
+ describe: "Run 'kj init' to scaffold a default kj.config.yml",
29
+ async detect() {
30
+ const configPath = getConfigPath();
31
+ const configExists = await exists(configPath);
32
+ return {
33
+ ok: configExists,
34
+ severity: "fail",
35
+ detail: configExists ? configPath : "Not found",
36
+ fix: configExists ? undefined : withDocLink("Run 'kj init' to create the config file.", "config_missing"),
37
+ };
38
+ },
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Review rules (.md) informational check.
44
+ */
45
+ function createReviewRulesCheck() {
46
+ return {
47
+ name: "review-rules",
48
+ label: "Reviewer rules (.md)",
49
+ strategy: STRATEGY.NONE,
50
+ async detect({ config }) {
51
+ const projectDir = config.projectDir || process.cwd();
52
+ const paths = resolveRoleMdPath("reviewer", projectDir);
53
+ const rules = await loadFirstExisting(paths);
54
+ return {
55
+ ok: true,
56
+ severity: "info",
57
+ detail: rules ? "Found" : "Not found (will use defaults)",
58
+ };
59
+ },
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Coder rules (.md) informational check.
65
+ */
66
+ function createCoderRulesCheck() {
67
+ return {
68
+ name: "coder-rules",
69
+ label: "Coder rules (.md)",
70
+ strategy: STRATEGY.NONE,
71
+ async detect({ config }) {
72
+ const projectDir = config.projectDir || process.cwd();
73
+ const paths = resolveRoleMdPath("coder", projectDir);
74
+ const rules = await loadFirstExisting(paths);
75
+ return {
76
+ ok: true,
77
+ severity: "info",
78
+ detail: rules ? "Found" : "Not found (will use defaults)",
79
+ };
80
+ },
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Detect duplicate TOML table headers (e.g. [mcp_servers."karajan-mcp"] twice).
86
+ */
87
+ function findDuplicateTomlKeys(content) {
88
+ const tableHeaders = [];
89
+ const duplicates = [];
90
+ for (const line of content.split("\n")) {
91
+ const match = line.match(/^\s*\[([^\]]+)\]\s*$/);
92
+ if (match) {
93
+ const key = match[1].trim();
94
+ if (tableHeaders.includes(key)) {
95
+ duplicates.push(key);
96
+ } else {
97
+ tableHeaders.push(key);
98
+ }
99
+ }
100
+ }
101
+ return duplicates;
102
+ }
103
+
104
+ /**
105
+ * Claude config (~/.claude.json) validity.
106
+ */
107
+ function createClaudeConfigCheck() {
108
+ return {
109
+ name: "agent-config:claude",
110
+ label: "Agent config: claude (~/.claude.json)",
111
+ strategy: STRATEGY.MANUAL,
112
+ async detect() {
113
+ const home = os.homedir();
114
+ const claudeJsonPath = path.join(home, ".claude.json");
115
+ try {
116
+ const raw = await fs.readFile(claudeJsonPath, "utf8");
117
+ JSON.parse(raw);
118
+ return { ok: true, severity: "info", detail: "Valid JSON" };
119
+ } catch (err) {
120
+ if (err.code === "ENOENT") {
121
+ // Not configured: Claude may not be in use. Informational skip.
122
+ return { ok: true, severity: "info", detail: "Not present (skipped)" };
123
+ }
124
+ return {
125
+ ok: false,
126
+ severity: "warn",
127
+ detail: `Invalid JSON: ${err.message.split("\n")[0]}`,
128
+ fix: "Fix the JSON syntax in ~/.claude.json. Common issues: trailing commas, missing quotes.",
129
+ };
130
+ }
131
+ },
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Codex config (~/.codex/config.toml) validity.
137
+ */
138
+ function createCodexConfigCheck() {
139
+ return {
140
+ name: "agent-config:codex",
141
+ label: "Agent config: codex (~/.codex/config.toml)",
142
+ strategy: STRATEGY.MANUAL,
143
+ async detect() {
144
+ const home = os.homedir();
145
+ const codexTomlPath = path.join(home, ".codex", "config.toml");
146
+ try {
147
+ const raw = await fs.readFile(codexTomlPath, "utf8");
148
+ const duplicates = findDuplicateTomlKeys(raw);
149
+ if (duplicates.length > 0) {
150
+ return {
151
+ ok: false,
152
+ severity: "warn",
153
+ detail: `Duplicate TOML keys: ${duplicates.join(", ")}`,
154
+ fix: `Remove duplicate entries in ~/.codex/config.toml: ${duplicates.join(", ")}`,
155
+ };
156
+ }
157
+ return { ok: true, severity: "info", detail: "Valid TOML (no duplicate keys)" };
158
+ } catch (err) {
159
+ if (err.code === "ENOENT") {
160
+ return { ok: true, severity: "info", detail: "Not present (skipped)" };
161
+ }
162
+ return {
163
+ ok: false,
164
+ severity: "warn",
165
+ detail: `Cannot read: ${err.message.split("\n")[0]}`,
166
+ fix: "Check file permissions on ~/.codex/config.toml",
167
+ };
168
+ }
169
+ },
170
+ };
171
+ }
172
+
173
+ /**
174
+ * KJ config (~/.karajan/kj.config.yml) YAML validity (separate from existence).
175
+ */
176
+ function createKjConfigYamlCheck() {
177
+ return {
178
+ name: "agent-config:karajan",
179
+ label: "Agent config: karajan (kj.config.yml)",
180
+ strategy: STRATEGY.MANUAL,
181
+ async detect() {
182
+ const kjConfigPath = getConfigPath();
183
+ try {
184
+ const raw = await fs.readFile(kjConfigPath, "utf8");
185
+ const yaml = await import("js-yaml");
186
+ yaml.default.load(raw);
187
+ return { ok: true, severity: "info", detail: "Valid YAML" };
188
+ } catch (err) {
189
+ if (err.code === "ENOENT") {
190
+ // Covered by createConfigFileCheck — don't duplicate the failure
191
+ return { ok: true, severity: "info", detail: "Not present (covered by config check)" };
192
+ }
193
+ return {
194
+ ok: false,
195
+ severity: "fail",
196
+ detail: `Invalid YAML: ${err.message.split("\n")[0]}`,
197
+ fix: `Fix YAML syntax in ${kjConfigPath}. Run 'kj init' to regenerate if needed.`,
198
+ };
199
+ }
200
+ },
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Aggregate: all config-file-related checks.
206
+ * @returns {import("./types.js").Check[]}
207
+ */
208
+ export function getConfigFileChecks() {
209
+ return [
210
+ createConfigFileCheck(),
211
+ createReviewRulesCheck(),
212
+ createCoderRulesCheck(),
213
+ createClaudeConfigCheck(),
214
+ createCodexConfigCheck(),
215
+ createKjConfigYamlCheck(),
216
+ ];
217
+ }