@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,103 @@
1
+ /**
2
+ * Ensure ~/.karajan/ directory tree exists. Strategy: auto — creating
3
+ * directories under the user's home is non-invasive.
4
+ */
5
+
6
+ import fs from "node:fs/promises";
7
+ import os from "node:os";
8
+ import path from "node:path";
9
+ import { STRATEGY } from "./types.js";
10
+ import { getKarajanHome } from "../utils/paths.js";
11
+
12
+ const REQUIRED_DIRS = [
13
+ "", // ~/.karajan/
14
+ "sessions",
15
+ "skills-cache",
16
+ "logs",
17
+ ];
18
+
19
+ /**
20
+ * @internal Exported for dynamic import from tests/checks/dir-setup.test.js
21
+ * and tests/checks/auto-remediation-e2e.test.js. Knip false positive.
22
+ */
23
+ export function createKarajanDirsCheck() {
24
+ return {
25
+ name: "karajan-dirs",
26
+ label: "~/.karajan directory tree",
27
+ strategy: STRATEGY.AUTO,
28
+ describe: "Create missing ~/.karajan subdirectories",
29
+ async detect() {
30
+ // KJC-TSK-0420: KARAJAN_HOME / KJ_HOME aware via getKarajanHome().
31
+ const root = getKarajanHome();
32
+ const home = os.homedir(); // still needed for path.relative() below
33
+ const missing = [];
34
+ for (const sub of REQUIRED_DIRS) {
35
+ const full = sub ? path.join(root, sub) : root;
36
+ try {
37
+ const stat = await fs.stat(full);
38
+ if (!stat.isDirectory()) missing.push(full);
39
+ } catch {
40
+ missing.push(full);
41
+ }
42
+ }
43
+ if (missing.length === 0) {
44
+ return { ok: true, severity: "info", detail: `All ${REQUIRED_DIRS.length} directories present under ${root}` };
45
+ }
46
+ return {
47
+ ok: false,
48
+ severity: "fail",
49
+ detail: `Missing: ${missing.map((m) => path.relative(home, m)).join(", ")}`,
50
+ fix: `mkdir -p ${missing.join(" ")}`,
51
+ extra: { missing },
52
+ };
53
+ },
54
+ async remediate({ extra }) {
55
+ const missing = extra?.missing || [];
56
+ for (const dir of missing) {
57
+ await fs.mkdir(dir, { recursive: true });
58
+ }
59
+ return {
60
+ fixed: true,
61
+ detail: `Created ${missing.length} director${missing.length === 1 ? "y" : "ies"} under ~/.karajan`,
62
+ };
63
+ },
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Detect a populated legacy `~/.kj/` left over from before
69
+ * KJC-PCS-0047 PR 3. The auto-migrator (src/utils/home-migration.js)
70
+ * moves its contents to `~/.karajan/` on the next `kj` invocation,
71
+ * so the fix is simply "run any kj command". Severity is `warn`
72
+ * (informational) because the legacy dir does not break anything —
73
+ * it just won't get read by the board until the migration runs.
74
+ * @internal Exported for dynamic import from tests.
75
+ */
76
+ export function createLegacyKjHomeCheck() {
77
+ return {
78
+ name: "legacy-kj-home",
79
+ label: "legacy ~/.kj/ directory",
80
+ strategy: STRATEGY.MANUAL,
81
+ describe: "Detect unmigrated ~/.kj/ left over from pre-2.19 layout",
82
+ async detect() {
83
+ const legacy = path.join(os.homedir(), ".kj");
84
+ try {
85
+ const entries = await fs.readdir(legacy);
86
+ if (entries.length === 0) return { ok: true, severity: "info", detail: "Empty legacy ~/.kj/" };
87
+ const marker = path.join(getKarajanHome(), ".kj-migrated.json"); // KJC-TSK-0420
88
+ try { await fs.access(marker); return { ok: true, severity: "info", detail: "Already migrated" }; }
89
+ catch { /* no marker, still pending */ }
90
+ return {
91
+ ok: false,
92
+ severity: "warn",
93
+ detail: `~/.kj/ still has ${entries.length} entries; will be migrated on the next kj invocation`,
94
+ fix: "Run any kj command (e.g. `kj doctor`) — the migrator runs automatically",
95
+ };
96
+ } catch { return { ok: true, severity: "info", detail: "No legacy ~/.kj/" }; }
97
+ },
98
+ };
99
+ }
100
+
101
+ export function getDirSetupChecks() {
102
+ return [createKarajanDirsCheck(), createLegacyKjHomeCheck()];
103
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Guarantee level en runtime (KJC-TSK-0756, hallazgo de campo de Pedro):
3
+ * la doctrina "kj jamás finge una supervisión que no puede aplicar" vivía
4
+ * solo en el README — ahora kj doctor la DECLARA para el host actual, con
5
+ * el porqué. El acoplamiento a Claude es UNA capa (tier A: hooks síncronos
6
+ * bloqueantes, que hoy solo ese harness expone) y es decisión de ADR
7
+ * (v4.13), no accidente; el tier B (git gates) es el suelo agnóstico.
8
+ */
9
+ import { existsSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { detectHostAgent } from "../utils/agent-detect.js";
12
+
13
+ /** Pure: computes the three tiers from observable facts. */
14
+ export function guaranteeLevel({ host, harnessWired, policyDeclared, policyWorkflow }) {
15
+ const tierA = host === "claude" && harnessWired
16
+ ? { active: true, reason: "Claude Code expone hooks síncronos bloqueantes y el harness del Sentinel está instalado (kj harden)" }
17
+ : host === "claude"
18
+ ? { active: false, reason: "host Claude sin harness instalado — corre kj harden para activar la supervisión en el turno" }
19
+ : { active: false, reason: `el host ${host ?? "desconocido"} no expone hooks síncronos bloqueantes — no se finge la supervisión; el tier B sigue siendo el suelo de garantía` };
20
+ const tierB = { active: true, reason: "los gates viven en el repositorio, no en el harness: cualquier host, el diff violador no entra" };
21
+ const tierC = policyDeclared && policyWorkflow
22
+ ? { active: true, reason: "kj-policy.yml re-verifica el PR contra la policy declarada (merge-blocking)" }
23
+ : policyDeclared
24
+ ? { active: false, reason: "hay policy declarada pero sin workflow de CI — corre kj harden para sembrar kj-policy.yml" }
25
+ : { active: false, reason: "sin .karajan/policy.yml declarada — el tier C solo existe donde hay policy que verificar" };
26
+ return { host: host ?? null, tierA, tierB, tierC };
27
+ }
28
+
29
+ /** Facts from disk + env; injectable for tests. */
30
+ export function collectGuaranteeFacts({ projectDir = process.cwd(), deps = {} } = {}) {
31
+ const { detectHost = detectHostAgent, exists = existsSync } = deps;
32
+ return guaranteeLevel({
33
+ host: detectHost(),
34
+ harnessWired: exists(join(projectDir, ".karajan", "harness", "pretooluse-sentinel.mjs")),
35
+ policyDeclared: exists(join(projectDir, ".karajan", "policy.yml")),
36
+ policyWorkflow: exists(join(projectDir, ".github", "workflows", "kj-policy.yml")),
37
+ });
38
+ }
@@ -0,0 +1,150 @@
1
+ // Advisory hardware checks: warn (not fail) so the pipeline keeps running.
2
+ // RAM < 4 GB silently OOM-kills the RAG embedder; disk < 5 GB corrupts
3
+ // Ollama model shards. GPU detection is best-effort and never throws.
4
+
5
+ import os from "node:os";
6
+ import { statfs } from "node:fs/promises";
7
+ import { spawn } from "node:child_process";
8
+ import { STRATEGY } from "./types.js";
9
+
10
+ const RAM_WARN_GB = 4;
11
+ const RAM_RECOMMENDED_GB = 8;
12
+ const DISK_WARN_GB = 5;
13
+ const DISK_RECOMMENDED_GB = 20;
14
+ const GPU_DETECT_TIMEOUT_MS = 1500;
15
+
16
+ const bytesToGb = (bytes) => Math.round((bytes / 1024 ** 3) * 10) / 10;
17
+ const info = (detail, extra) => ({ ok: true, severity: "info", detail, extra });
18
+ const warn = (detail, fix, extra) => ({ ok: false, severity: "warn", detail, fix, extra });
19
+
20
+ function createRamCheck() {
21
+ return {
22
+ name: "hw-ram",
23
+ label: "System RAM",
24
+ strategy: STRATEGY.MANUAL,
25
+ async detect() {
26
+ const totalGb = bytesToGb(os.totalmem());
27
+ const freeGb = bytesToGb(os.freemem());
28
+ const base = `${totalGb} GB total, ${freeGb} GB free`;
29
+ if (totalGb < RAM_WARN_GB) {
30
+ return warn(
31
+ `${base} (RAG embedder needs >=${RAM_WARN_GB} GB)`,
32
+ "Disable local RAG (kj init --no-rag) or switch rag.embedder.provider to openai/voyage/cohere.",
33
+ { totalGb, freeGb, threshold: RAM_WARN_GB }
34
+ );
35
+ }
36
+ if (totalGb < RAM_RECOMMENDED_GB) {
37
+ return info(`${base} (>=${RAM_RECOMMENDED_GB} GB recommended for parallel runs)`, { totalGb, freeGb });
38
+ }
39
+ return info(base, { totalGb, freeGb });
40
+ },
41
+ };
42
+ }
43
+
44
+ function createCpuCheck() {
45
+ return {
46
+ name: "hw-cpu",
47
+ label: "CPU",
48
+ strategy: STRATEGY.NONE,
49
+ async detect() {
50
+ const cpus = os.cpus();
51
+ const model = cpus[0]?.model?.trim() || "unknown";
52
+ const cores = cpus.length;
53
+ const arch = os.arch();
54
+ return info(`${cores} cores, ${arch} (${model})`, { cores, arch, model });
55
+ },
56
+ };
57
+ }
58
+
59
+ function createDiskCheck() {
60
+ return {
61
+ name: "hw-disk",
62
+ label: "Disk space (cwd)",
63
+ strategy: STRATEGY.MANUAL,
64
+ async detect() {
65
+ try {
66
+ const stat = await statfs(process.cwd());
67
+ const freeGb = bytesToGb(stat.bsize * stat.bavail);
68
+ if (freeGb < DISK_WARN_GB) {
69
+ return warn(
70
+ `${freeGb} GB free (>=${DISK_WARN_GB} GB recommended)`,
71
+ "Free disk space. Ollama models alone take 3-5 GB; the RAG store grows ~50 MB per 1k LOC indexed.",
72
+ { freeGb, threshold: DISK_WARN_GB }
73
+ );
74
+ }
75
+ const note = freeGb < DISK_RECOMMENDED_GB ? ` (>=${DISK_RECOMMENDED_GB} GB recommended)` : "";
76
+ return info(`${freeGb} GB free${note}`, { freeGb });
77
+ } catch (err) {
78
+ return info(`Cannot read free disk space: ${err.message}`);
79
+ }
80
+ },
81
+ };
82
+ }
83
+
84
+ function runGpuCommand(cmd, args) {
85
+ return new Promise((resolve) => {
86
+ let stdout = "";
87
+ let settled = false;
88
+ const finish = (value) => {
89
+ if (settled) return;
90
+ settled = true;
91
+ resolve(value);
92
+ };
93
+ try {
94
+ const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "ignore"] });
95
+ const timer = setTimeout(() => {
96
+ try { child.kill("SIGKILL"); } catch { /* noop */ }
97
+ finish(null);
98
+ }, GPU_DETECT_TIMEOUT_MS);
99
+ child.stdout.on("data", (chunk) => { stdout += chunk.toString(); });
100
+ child.on("error", () => { clearTimeout(timer); finish(null); });
101
+ child.on("close", (code) => {
102
+ clearTimeout(timer);
103
+ finish(code === 0 ? stdout : null);
104
+ });
105
+ } catch {
106
+ finish(null);
107
+ }
108
+ });
109
+ }
110
+
111
+ async function detectGpu() {
112
+ const platform = process.platform;
113
+ if (platform === "linux" || platform === "win32") {
114
+ const out = await runGpuCommand("nvidia-smi", ["--query-gpu=name", "--format=csv,noheader"]);
115
+ const model = out?.split("\n").map((l) => l.trim()).find(Boolean);
116
+ if (model) return { vendor: "NVIDIA", model };
117
+ return null;
118
+ }
119
+ if (platform === "darwin") {
120
+ const out = await runGpuCommand("system_profiler", ["SPDisplaysDataType"]);
121
+ if (!out) return null;
122
+ const match = out.match(/Chipset Model:\s*(.+)/);
123
+ if (!match) return null;
124
+ const model = match[1].trim();
125
+ const vendor = /Apple/i.test(model) ? "Apple" : /AMD|Radeon/i.test(model) ? "AMD" : /Intel/i.test(model) ? "Intel" : "GPU";
126
+ return { vendor, model };
127
+ }
128
+ return null;
129
+ }
130
+
131
+ function createGpuCheck() {
132
+ return {
133
+ name: "hw-gpu",
134
+ label: "GPU",
135
+ strategy: STRATEGY.NONE,
136
+ async detect() {
137
+ const gpu = await detectGpu();
138
+ if (!gpu) {
139
+ return info("No discrete GPU detected (CPU-only)", { detected: false });
140
+ }
141
+ return info(`${gpu.vendor} ${gpu.model}`, { detected: true, vendor: gpu.vendor, model: gpu.model });
142
+ },
143
+ };
144
+ }
145
+
146
+ export function getHardwareChecks() {
147
+ return [createRamCheck(), createCpuCheck(), createDiskCheck(), createGpuCheck()];
148
+ }
149
+
150
+ export const __test = { RAM_WARN_GB, RAM_RECOMMENDED_GB, DISK_WARN_GB, DISK_RECOMMENDED_GB, GPU_DETECT_TIMEOUT_MS, bytesToGb, detectGpu };
@@ -0,0 +1,41 @@
1
+ // KJC-TSK-0470 — `kj doctor` check for the AI Harness Scorecard image.
2
+ // Reports Disabled / Docker missing / Image not pulled / OK. The image
3
+ // is pulled lazily by `kj audit` on first use; this check is informational.
4
+ import { isDockerAvailable, isHarnessImagePresent, normalizeHarnessConfig } from "../audit/harness-scorecard.js";
5
+ import { STRATEGY } from "./types.js";
6
+
7
+ function harnessEnabled(config) { return config?.audit?.harness?.enabled !== false; }
8
+
9
+ function createHarnessScorecardCheck() {
10
+ return {
11
+ name: "harness-scorecard",
12
+ label: "AI Harness Scorecard (audit)",
13
+ strategy: STRATEGY.NONE,
14
+ async detect({ config }) {
15
+ const cfg = normalizeHarnessConfig(config?.audit?.harness || {});
16
+ if (!harnessEnabled(config)) {
17
+ return { ok: true, severity: "info", detail: "Disabled in config (audit.harness.enabled=false)" };
18
+ }
19
+ let docker; try { docker = await isDockerAvailable(); } catch { docker = false; }
20
+ if (!docker) return {
21
+ ok: false, severity: "warn",
22
+ detail: "Docker not available — kj audit will skip the harness step.",
23
+ fix: "Install Docker (or run `kj audit --no-harness` to silence this).",
24
+ extra: { docker: false, image: cfg.image },
25
+ };
26
+ let cached; try { cached = await isHarnessImagePresent(cfg.image); } catch { cached = false; }
27
+ if (!cached) return {
28
+ ok: true, severity: "info",
29
+ detail: `Will be pulled on first \`kj audit\` run (${cfg.image}).`,
30
+ extra: { docker: true, cached: false, image: cfg.image },
31
+ };
32
+ return {
33
+ ok: true, severity: "info",
34
+ detail: `Image cached locally (${cfg.image}).`,
35
+ extra: { docker: true, cached: true, image: cfg.image },
36
+ };
37
+ },
38
+ };
39
+ }
40
+
41
+ export function getHarnessScorecardChecks() { return [createHarnessScorecardCheck()]; }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * MCP server health checks.
3
+ *
4
+ * Karajan integrates with several MCP servers — karajan-mcp (stdio), Serena,
5
+ * Sonar MCP, Planning Game MCP, etc. This module verifies they respond to
6
+ * a minimal JSON-RPC `initialize` call within a short deadline.
7
+ *
8
+ * For stdio MCPs that Karajan spawns itself (karajan-mcp), a failed ping is
9
+ * auto-remediable by re-spawning. External MCPs (Serena) are warn-only.
10
+ */
11
+
12
+ import { spawn } from "node:child_process";
13
+ import { fileURLToPath } from "node:url";
14
+ import path from "node:path";
15
+ import { STRATEGY } from "./types.js";
16
+ import { withTimeout, TimeoutError } from "../utils/with-timeout.js";
17
+ import { checkBinary } from "../utils/agent-detect.js";
18
+
19
+ const PING_TIMEOUT_MS = 3000;
20
+
21
+ /**
22
+ * Send a JSON-RPC `initialize` to an MCP server over stdio and wait for
23
+ * any response. Kills the process immediately after.
24
+ *
25
+ * @param {string} command
26
+ * @param {string[]} args
27
+ * @returns {Promise<{ok: boolean, detail: string}>}
28
+ */
29
+ async function pingMcpStdio(command, args) {
30
+ const handshake = () =>
31
+ new Promise((resolve) => {
32
+ let child;
33
+ try {
34
+ child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
35
+ } catch (err) {
36
+ resolve({ ok: false, detail: `spawn failed: ${err.message}` });
37
+ return;
38
+ }
39
+ let settled = false;
40
+ const finish = (ok, detail) => {
41
+ if (settled) return;
42
+ settled = true;
43
+ try {
44
+ child.kill();
45
+ } catch { /* already exited */ }
46
+ resolve({ ok, detail });
47
+ };
48
+ child.on("error", (err) => finish(false, `process error: ${err.message}`));
49
+ child.on("exit", (code) => {
50
+ if (!settled) finish(false, `exited with code ${code} before response`);
51
+ });
52
+ child.stdout.on("data", (buf) => {
53
+ const text = buf.toString();
54
+ // Any JSON-RPC response line counts as alive.
55
+ if (text.includes("\"jsonrpc\"") || text.includes("\"result\"") || text.includes("\"error\"")) {
56
+ finish(true, "Responded to initialize");
57
+ }
58
+ });
59
+ // Send initialize request
60
+ const req = JSON.stringify({
61
+ jsonrpc: "2.0",
62
+ id: 1,
63
+ method: "initialize",
64
+ params: {
65
+ protocolVersion: "2024-11-05",
66
+ clientInfo: { name: "kj-doctor", version: "1.0.0" },
67
+ capabilities: {},
68
+ },
69
+ });
70
+ try {
71
+ child.stdin.write(req + "\n");
72
+ } catch (err) {
73
+ finish(false, `stdin write failed: ${err.message}`);
74
+ }
75
+ });
76
+ try {
77
+ return await withTimeout(handshake(), PING_TIMEOUT_MS, "mcp-ping");
78
+ } catch (err) {
79
+ if (err instanceof TimeoutError) {
80
+ return { ok: false, detail: `No response within ${PING_TIMEOUT_MS}ms` };
81
+ }
82
+ return { ok: false, detail: err.message };
83
+ }
84
+ }
85
+
86
+ /**
87
+ * karajan-mcp health — stdio server bundled with this package.
88
+ * Strategy: auto (we can re-spawn it ourselves).
89
+ *
90
+ * @internal Exported for dynamic import from tests/checks/mcp-health.test.js.
91
+ * Knip false positive.
92
+ */
93
+ export function createKarajanMcpCheck() {
94
+ return {
95
+ name: "mcp:karajan",
96
+ label: "MCP: karajan-mcp",
97
+ strategy: STRATEGY.AUTO,
98
+ describe: "Respawn karajan-mcp stdio process",
99
+ async detect() {
100
+ const binPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../bin/karajan-mcp.js");
101
+ const result = await pingMcpStdio(process.execPath, [binPath]);
102
+ return {
103
+ ok: result.ok,
104
+ severity: result.ok ? "info" : "warn",
105
+ // KJC-BUG-0118: the MCP is OPTIONAL in the v4 environment (the host
106
+ // agent drives kj via CLI) — a dead MCP must read as a degraded
107
+ // optional, never as a broken install. The standalone (curl) binary
108
+ // cannot run it at all (no bundled native modules).
109
+ detail: result.ok
110
+ ? result.detail
111
+ : `karajan-mcp did not respond: ${result.detail} — OPTIONAL in v4: your agent runs kj directly; only shell-less hosts need MCP`,
112
+ fix: result.ok ? undefined : "Only if you need MCP: install via npm (`npm i -g karajan-code`) — the standalone binary does not bundle it",
113
+ extra: { binPath },
114
+ };
115
+ },
116
+ async remediate({ extra }) {
117
+ // Spawn once detached so the MCP client can pick it up for subsequent runs.
118
+ // This is idempotent: if one instance is already listening, another will
119
+ // coexist over a different pipe.
120
+ try {
121
+ spawn(process.execPath, [extra.binPath], { detached: true, stdio: "ignore" }).unref();
122
+ return { fixed: true, detail: "Re-spawned karajan-mcp in background" };
123
+ } catch (err) {
124
+ return { fixed: false, detail: `Failed to respawn: ${err.message}` };
125
+ }
126
+ },
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Serena MCP — external tool the user installs themselves. Warn only when
132
+ * enabled in config. Strategy: manual (we don't manage its lifecycle).
133
+ *
134
+ * @internal Exported for dynamic import from tests/checks/mcp-health.test.js.
135
+ * Knip false positive.
136
+ */
137
+ export function createSerenaMcpCheck() {
138
+ return {
139
+ name: "mcp:serena",
140
+ label: "MCP: serena",
141
+ strategy: STRATEGY.MANUAL,
142
+ applies: (config) => config?.serena?.enabled === true,
143
+ async detect() {
144
+ const bin = await checkBinary("serena");
145
+ if (!bin.ok) {
146
+ return {
147
+ ok: false,
148
+ severity: "warn",
149
+ detail: "serena binary not on PATH",
150
+ fix: "Install Serena: uvx --from git+https://github.com/oraios/serena serena",
151
+ };
152
+ }
153
+ const result = await pingMcpStdio("serena", ["start", "--mcp"]);
154
+ return {
155
+ ok: result.ok,
156
+ severity: result.ok ? "info" : "warn",
157
+ detail: result.ok ? "Serena responded to initialize" : `No response: ${result.detail}`,
158
+ fix: result.ok ? undefined : "Restart Serena manually and verify connectivity.",
159
+ };
160
+ },
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Aggregate of MCP health checks. Only enabled servers run their ping.
166
+ */
167
+ export function getMcpHealthChecks() {
168
+ return [createKarajanMcpCheck(), createSerenaMcpCheck()];
169
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Method report (KJC-TSK-0689, MG-D of épica KJC-PCS-0068). Individual
3
+ * deviations can each be legitimate — the AGGREGATE trail is the drift
4
+ * detector. Three measurable signals over the recent history: commit
5
+ * subjects without a card reference, review verdicts by workspace
6
+ * ([root] vs lanes), and source commits without a single test change.
7
+ * Informative by design; only a card-ref drought turns it into a warn.
8
+ */
9
+ import { readdirSync, readFileSync } from "node:fs";
10
+ import path from "node:path";
11
+ import { runCommand } from "../utils/process.js";
12
+ import { checkTestsWithCode } from "../review/tests-with-code.js";
13
+ import { CARD_REF_RE } from "../review/card-first.js";
14
+ import { STRATEGY } from "./types.js";
15
+
16
+ function recentVerdicts(projectDir, sample) {
17
+ try {
18
+ const dir = path.join(projectDir, ".karajan", "reviews");
19
+ return readdirSync(dir).filter((f) => f.endsWith(".json"))
20
+ .map((f) => JSON.parse(readFileSync(path.join(dir, f), "utf8")))
21
+ .sort((a, b) => String(b.timestamp).localeCompare(String(a.timestamp)))
22
+ .slice(0, sample);
23
+ } catch {
24
+ return [];
25
+ }
26
+ }
27
+
28
+ export async function collectMethodStats({ projectDir, run = runCommand, sample = 20 } = {}) {
29
+ const subjectsRes = await run("git", ["log", `-${sample}`, "--no-merges", "--format=%s"], { cwd: projectDir });
30
+ const subjects = subjectsRes.exitCode === 0 ? subjectsRes.stdout.split("\n").filter(Boolean) : [];
31
+
32
+ // "@%h" carries a % so git treats it as a literal format string — a bare
33
+ // "@" is rejected as an unknown pretty alias (caught in a live smoke).
34
+ const blocksRes = await run("git", ["log", `-${Math.min(sample, 10)}`, "--no-merges", "--name-only", "--format=@%h"], { cwd: projectDir });
35
+ const blocks = blocksRes.exitCode === 0
36
+ ? blocksRes.stdout.split(/^@.*$/m).map((b) => b.split("\n").map((l) => l.trim()).filter(Boolean)).filter((b) => b.length > 0)
37
+ : [];
38
+ const offenders = blocks.filter((files) => checkTestsWithCode({ config: {}, stagedFiles: files, env: {} }).mode !== "pass").length;
39
+
40
+ const verdicts = recentVerdicts(projectDir, sample);
41
+ const stamped = verdicts.filter((v) => v.workspace);
42
+
43
+ return {
44
+ commits: { total: subjects.length, withCard: subjects.filter((s) => CARD_REF_RE.test(s)).length },
45
+ verdicts: { total: verdicts.length, stamped: stamped.length, root: stamped.filter((v) => v.workspace === "root").length },
46
+ testless: { sampled: blocks.length, offenders },
47
+ };
48
+ }
49
+
50
+ export function formatMethodStats(s) {
51
+ return `commits with card ref ${s.commits.withCard}/${s.commits.total} · verdict workspaces root ${s.verdicts.root}/${s.verdicts.stamped || 0} stamped (${s.verdicts.total} total) · source commits without tests ${s.testless.offenders}/${s.testless.sampled}`;
52
+ }
53
+
54
+ function createMethodCheck() {
55
+ return {
56
+ name: "method",
57
+ label: "Method adherence (recent history)",
58
+ strategy: STRATEGY.NONE,
59
+ async detect({ config = {}, projectDir = process.cwd(), run = runCommand } = {}) {
60
+ const stats = await collectMethodStats({ projectDir, run, sample: config.method_gates?.report_sample || 20 });
61
+ const detail = formatMethodStats(stats);
62
+ const drought = stats.commits.total >= 5 && stats.commits.withCard / stats.commits.total < 0.5;
63
+ if (drought) {
64
+ return { ok: false, severity: "warn", detail: `most recent commits carry no card reference — ${detail}` };
65
+ }
66
+ return { ok: true, severity: "info", detail };
67
+ },
68
+ };
69
+ }
70
+
71
+ export function getMethodChecks() {
72
+ return [createMethodCheck()];
73
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Native build availability check (KJC-BUG-0092).
3
+ *
4
+ * better-sqlite3 ships a native addon compiled in a postinstall step. pnpm
5
+ * blocks dependency build scripts by default (ERR_PNPM_IGNORED_BUILDS), so a
6
+ * `pnpm add -g karajan-code` leaves the addon uncompiled: `kj --version` still
7
+ * works (it never opens a DB) but any DB-backed command (board, rag, cost
8
+ * tracking) crashes with "Cannot find module 'better-sqlite3'". This surfaces a
9
+ * WARN in `kj doctor` with the exact remedy instead of a cryptic runtime crash.
10
+ */
11
+
12
+ import { STRATEGY } from "./types.js";
13
+
14
+ /** pnpm lays packages out under a `.pnpm` virtual store and symlinks them in. */
15
+ function isPnpmInstall() {
16
+ return (
17
+ import.meta.url.includes("/.pnpm/") ||
18
+ (process.env.npm_config_user_agent || "").includes("pnpm")
19
+ );
20
+ }
21
+
22
+ /** Force the native binding to load by opening an in-memory database. */
23
+ async function defaultLoadDb() {
24
+ const Database = (await import("better-sqlite3")).default;
25
+ new Database(":memory:").close();
26
+ }
27
+
28
+ export function createNativeBuildCheck({ loadDb = defaultLoadDb, isPnpm = isPnpmInstall } = {}) {
29
+ return {
30
+ name: "native-build",
31
+ label: "native modules (better-sqlite3)",
32
+ strategy: STRATEGY.MANUAL,
33
+ async detect() {
34
+ try {
35
+ await loadDb();
36
+ return {
37
+ ok: true,
38
+ severity: "info",
39
+ detail: "better-sqlite3 native addon loads — DB-backed commands available",
40
+ };
41
+ } catch (err) {
42
+ const firstLine = String(err?.message || err).split("\n")[0];
43
+ if (isPnpm()) {
44
+ return {
45
+ ok: false,
46
+ severity: "warn",
47
+ detail: "better-sqlite3 native build was skipped — pnpm blocks dependency build scripts by default",
48
+ fix: "Approve the build then reinstall: `pnpm approve-builds better-sqlite3` — or install with npm: `npm i -g karajan-code`",
49
+ };
50
+ }
51
+ return {
52
+ ok: false,
53
+ severity: "warn",
54
+ // KJC-BUG-0118: the standalone (curl) binary ships without native
55
+ // modules by design — name the consequence (RAG/board/MCP need the
56
+ // npm install) instead of implying the install is broken.
57
+ detail: `better-sqlite3 failed to load: ${firstLine} — DB-backed features (RAG, board, MCP) unavailable; the standalone binary does not bundle native modules`,
58
+ fix: "Reinstall to rebuild native modules: `npm i -g karajan-code`",
59
+ };
60
+ }
61
+ },
62
+ };
63
+ }
64
+
65
+ export function getNativeBuildChecks() {
66
+ return [createNativeBuildCheck()];
67
+ }