@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,137 @@
1
+ // Smart role assignment based on available AI agents.
2
+ // Used by both kj init (interactive) and auto-init (non-interactive).
3
+
4
+ import { detectAvailableAgents } from "./agent-detect.js";
5
+
6
+ // Agent capability tiers (higher = more capable for complex reasoning)
7
+ const CAPABILITY_TIERS = {
8
+ claude: 5, // Best for reasoning, orchestration, complex tasks
9
+ codex: 4, // Strong coder, good reviewer
10
+ gemini: 3, // Good general purpose
11
+ aider: 2, // Good coder, limited reasoning
12
+ opencode: 2 // Similar to aider
13
+ };
14
+
15
+ // Role requirements: what capability level is ideal for each role
16
+ const ROLE_PREFERENCES = {
17
+ brain: { minTier: 4, prefer: "claude", description: "Karajan Brain (orchestrator)" },
18
+ // KJC-BUG-0113: Solomon preferred gemini, but Google retired the Gemini
19
+ // Code Assist CLI for individuals — a binary that answers --version yet
20
+ // dies with IneligibleTierError on every real call. Any machine with the
21
+ // stale CLI on PATH got a judge that could never rule. Claude matches
22
+ // the brain default; diversifyReviewer still picks a different agent
23
+ // when more than one healthy option exists.
24
+ solomon: { minTier: 3, prefer: "claude", description: "Solomon (judge/arbiter)" },
25
+ coder: { minTier: 2, prefer: "claude", description: "Coder" },
26
+ reviewer: { minTier: 3, prefer: "codex", description: "Reviewer" },
27
+ planner: { minTier: 4, prefer: "claude", description: "Planner" },
28
+ researcher: { minTier: 3, prefer: "claude", description: "Researcher" },
29
+ architect: { minTier: 4, prefer: "claude", description: "Architect" },
30
+ tester: { minTier: 3, prefer: "claude", description: "Tester" },
31
+ security: { minTier: 3, prefer: "claude", description: "Security" },
32
+ triage: { minTier: 3, prefer: "claude", description: "Triage" }
33
+ };
34
+
35
+ /**
36
+ * Assign the best available agent to a role.
37
+ * Prefers the role's preferred agent if available, then falls back by capability tier.
38
+ */
39
+ function assignRole(roleName, availableAgents) {
40
+ const pref = ROLE_PREFERENCES[roleName];
41
+ if (!pref) return availableAgents[0]?.name || "claude";
42
+
43
+ // Preferred agent available?
44
+ if (availableAgents.find(a => a.name === pref.prefer)) {
45
+ return pref.prefer;
46
+ }
47
+
48
+ // Sort by capability tier (descending) and pick the best available
49
+ const sorted = [...availableAgents].sort(
50
+ (a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
51
+ );
52
+
53
+ return sorted[0]?.name || "claude";
54
+ }
55
+
56
+ /**
57
+ * Try to diversify: if possible, use a different agent for reviewer than coder.
58
+ */
59
+ function diversifyReviewer(coderAgent, availableAgents) {
60
+ const alternatives = availableAgents.filter(a => a.name !== coderAgent);
61
+ if (alternatives.length === 0) return coderAgent;
62
+
63
+ const sorted = [...alternatives].sort(
64
+ (a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
65
+ );
66
+ return sorted[0].name;
67
+ }
68
+
69
+ /**
70
+ * Auto-assign all roles based on detected agents. Non-interactive.
71
+ * Returns a config-ready object with role assignments.
72
+ */
73
+ export async function autoAssignRoles(logger) {
74
+ const agents = await detectAvailableAgents();
75
+ const available = agents.filter(a => a.available);
76
+
77
+ if (available.length === 0) {
78
+ logger?.warn?.("No AI agents detected. Using claude as default for all roles.");
79
+ return { assignments: getDefaultAssignments("claude"), agents, available: [] };
80
+ }
81
+
82
+ logger?.info?.(`Detected ${available.length} AI agent(s): ${available.map(a => `${a.name} (${a.version})`).join(", ")}`);
83
+
84
+ const coder = assignRole("coder", available);
85
+ const reviewer = available.length > 1 ? diversifyReviewer(coder, available) : coder;
86
+ const brain = assignRole("brain", available);
87
+ const solomon = available.length > 1 ? diversifyReviewer(brain, available) : brain;
88
+
89
+ const assignments = {
90
+ brain,
91
+ solomon,
92
+ coder,
93
+ reviewer,
94
+ planner: assignRole("planner", available),
95
+ researcher: assignRole("researcher", available),
96
+ architect: assignRole("architect", available),
97
+ tester: assignRole("tester", available),
98
+ security: assignRole("security", available),
99
+ triage: assignRole("triage", available)
100
+ };
101
+
102
+ logger?.info?.(`Role assignments: Brain=${brain}, Solomon=${solomon}, Coder=${coder}, Reviewer=${reviewer}`);
103
+
104
+ return { assignments, agents, available };
105
+ }
106
+
107
+ function getDefaultAssignments(agent) {
108
+ return {
109
+ brain: agent, solomon: agent, coder: agent, reviewer: agent,
110
+ planner: agent, researcher: agent, architect: agent,
111
+ tester: agent, security: agent, triage: agent
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Apply role assignments to a Karajan config object.
117
+ */
118
+ export function applyRoleAssignments(config, assignments) {
119
+ config.coder = assignments.coder;
120
+ config.reviewer = assignments.reviewer;
121
+
122
+ const roleNames = ["coder", "reviewer", "planner", "researcher", "architect",
123
+ "tester", "security", "triage", "solomon"];
124
+
125
+ for (const role of roleNames) {
126
+ config.roles = config.roles || {};
127
+ config.roles[role] = config.roles[role] || {};
128
+ config.roles[role].provider = assignments[role] || assignments.coder;
129
+ }
130
+
131
+ // Brain is a new top-level config (not in roles yet — will be when KarajanBrainRole is implemented)
132
+ config.brain = { provider: assignments.brain };
133
+
134
+ return config;
135
+ }
136
+
137
+ export { CAPABILITY_TIERS };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * role-env — env allowlist for agent subprocesses (KJC-TSK-0693).
3
+ *
4
+ * Agents inherit only what their function requires: system essentials, the
5
+ * spawned CLI's own auth/config vars, and KJ_* lane vars. Long-lived secrets
6
+ * that no agent needs (cloud keys, registry tokens, DB URLs) never reach the
7
+ * child, so a compromised agent or an injected prompt cannot exfiltrate them.
8
+ * Escapes: `security.env_passthrough` (exact names or trailing-* globs) and
9
+ * `security.env_allowlist: false` to disable filtering entirely.
10
+ */
11
+
12
+ const EXACT = new Set([
13
+ "PATH", "Path", "HOME", "USER", "LOGNAME", "SHELL", "TERM", "COLORTERM", "LANG",
14
+ "TZ", "TMPDIR", "TMP", "TEMP", "EDITOR", "CI", "OLLAMA_HOST",
15
+ // Windows child-process essentials: executable resolution and profile dirs.
16
+ "SystemRoot", "SYSTEMROOT", "windir", "COMSPEC", "ComSpec", "PATHEXT",
17
+ "USERPROFILE", "HOMEDRIVE", "HOMEPATH", "APPDATA", "LOCALAPPDATA", "PROGRAMDATA",
18
+ // SSH agent socket: local-only handle, needed for git fetch/pull over SSH
19
+ // inside worktrees. Unusable off-machine, unlike a long-lived token.
20
+ "SSH_AUTH_SOCK", "SSH_AGENT_PID",
21
+ "HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY",
22
+ "http_proxy", "https_proxy", "no_proxy",
23
+ ]);
24
+
25
+ // Per-CLI auth/config families. GOOGLE_ covers GOOGLE_APPLICATION_CREDENTIALS
26
+ // (gemini via Vertex); npm_ covers npm_config_* that Node tooling reads.
27
+ const PREFIXES = [
28
+ "LC_", "XDG_", "KJ_", "NODE_", "npm_",
29
+ "ANTHROPIC_", "CLAUDE", "OPENAI_", "CODEX", "GEMINI", "GOOGLE_",
30
+ "QWEN", "DASHSCOPE_", "OPENCODE", "AIDER_", "OPENROUTER_",
31
+ ];
32
+
33
+ // Vars only ONE agent authenticates with — granting them globally would
34
+ // defeat the point (the coder does not need your GitHub token; copilot does).
35
+ export const AGENT_EXTRAS = {
36
+ copilot: ["GITHUB_", "GH_"],
37
+ kimi: ["KIMI_", "MOONSHOT_"],
38
+ };
39
+
40
+ const matches = (pattern, key) =>
41
+ pattern.endsWith("*") ? key.startsWith(pattern.slice(0, -1)) : key === pattern;
42
+
43
+ /**
44
+ * Filter an environment down to what the given agent's subprocess needs.
45
+ * @param {Record<string,string|undefined>} base - env to filter
46
+ * @param {{agent?: string|null, passthrough?: string[]}} [opts]
47
+ * @returns {Record<string,string|undefined>}
48
+ */
49
+ export function buildAgentEnv(base = process.env, { agent = null, passthrough = [] } = {}) {
50
+ const prefixes = [...PREFIXES, ...(AGENT_EXTRAS[agent] || [])];
51
+ const out = {};
52
+ for (const [key, value] of Object.entries(base)) {
53
+ if (EXACT.has(key) || prefixes.some((p) => key.startsWith(p)) || passthrough.some((p) => matches(p, key))) {
54
+ out[key] = value;
55
+ }
56
+ }
57
+ return out;
58
+ }
@@ -0,0 +1,18 @@
1
+ import { runCommand } from "./process.js";
2
+
3
+ /**
4
+ * Detect whether RTK (Rust Token Killer) is installed and available.
5
+ * @returns {Promise<{ available: boolean, version: string|null }>}
6
+ */
7
+ export async function detectRtk() {
8
+ try {
9
+ const result = await runCommand("rtk", ["--version"]);
10
+ if (result.exitCode === 0) {
11
+ const version = (result.stdout || "").trim() || null;
12
+ return { available: true, version };
13
+ }
14
+ return { available: false, version: null };
15
+ } catch { /* rtk binary not found */
16
+ return { available: false, version: null };
17
+ }
18
+ }
@@ -0,0 +1,38 @@
1
+ import { runCommand } from "./process.js";
2
+ import { getInstallCommand } from "./os-detect.js";
3
+ import { detectRtk } from "./rtk-detect.js";
4
+
5
+ /**
6
+ * Install RTK (Rust Token Killer) using the OS-appropriate command.
7
+ * @param {object} logger - Logger with info/warn methods
8
+ * @returns {Promise<{ ok: boolean, version: string|null, error: string|null }>}
9
+ */
10
+ export async function installRtk(logger) {
11
+ const command = getInstallCommand("rtk");
12
+
13
+ logger.info("Installing RTK (Rust Token Killer)...");
14
+
15
+ try {
16
+ const result = await runCommand("sh", ["-c", command], { timeout: 120_000 });
17
+
18
+ if (result.exitCode !== 0) {
19
+ const error = (result.stderr || "").trim() || `exit code ${result.exitCode}`;
20
+ logger.warn(`RTK install failed: ${error}`);
21
+ return { ok: false, version: null, error };
22
+ }
23
+
24
+ // Verify installation
25
+ const check = await detectRtk();
26
+ if (check.available) {
27
+ logger.info(`RTK ${check.version || ""} installed successfully.`);
28
+ return { ok: true, version: check.version, error: null };
29
+ }
30
+
31
+ logger.warn("RTK install command succeeded but rtk binary not found in PATH.");
32
+ return { ok: false, version: null, error: "Binary not found after install" };
33
+ } catch (err) {
34
+ const error = err.message || String(err);
35
+ logger.warn(`RTK install failed: ${error}`);
36
+ return { ok: false, version: null, error };
37
+ }
38
+ }
@@ -0,0 +1,87 @@
1
+ import { runCommand } from "./process.js";
2
+
3
+ /**
4
+ * Commands that RTK can safely wrap for token-optimized output.
5
+ */
6
+ export const RTK_SUPPORTED_COMMANDS = [
7
+ "git", "ls", "find", "grep", "cat", "head", "tail",
8
+ "wc", "diff", "tree", "du", "file"
9
+ ];
10
+
11
+ const supportedSet = new Set(RTK_SUPPORTED_COMMANDS);
12
+
13
+ /**
14
+ * Wrap a command with RTK if available and the command is in the whitelist.
15
+ * @param {string} command
16
+ * @param {string[]} args
17
+ * @param {boolean} rtkAvailable
18
+ * @returns {{ command: string, args: string[] }}
19
+ */
20
+ export function wrapWithRtk(command, args, rtkAvailable) {
21
+ if (rtkAvailable && supportedSet.has(command)) {
22
+ return { command: "rtk", args: [command, ...args] };
23
+ }
24
+ return { command, args };
25
+ }
26
+
27
+ /**
28
+ * Session-level accumulator for RTK byte savings.
29
+ */
30
+ export class RtkSavingsTracker {
31
+ constructor() {
32
+ this.originalBytes = 0;
33
+ this.rtkBytes = 0;
34
+ this.callCount = 0;
35
+ }
36
+
37
+ record(originalSize, rtkSize) {
38
+ this.originalBytes += originalSize;
39
+ this.rtkBytes += rtkSize;
40
+ this.callCount += 1;
41
+ }
42
+
43
+ summary() {
44
+ const savedBytes = this.originalBytes - this.rtkBytes;
45
+ const savedPct = this.originalBytes > 0
46
+ ? Number(((savedBytes / this.originalBytes) * 100).toFixed(1))
47
+ : 0;
48
+ const estimatedTokensSaved = Math.floor(savedBytes / 4);
49
+ return {
50
+ originalBytes: this.originalBytes,
51
+ rtkBytes: this.rtkBytes,
52
+ savedBytes,
53
+ savedPct,
54
+ estimatedTokensSaved,
55
+ callCount: this.callCount
56
+ };
57
+ }
58
+
59
+ /** Returns true if any commands were recorded. */
60
+ hasData() {
61
+ return this.callCount > 0;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Create a runner function that transparently wraps supported commands with RTK.
67
+ * @param {boolean} rtkAvailable
68
+ * @param {RtkSavingsTracker} [tracker] - Optional savings tracker
69
+ * @returns {(command: string, args?: string[], options?: object) => Promise<object>}
70
+ */
71
+ export function createRtkRunner(rtkAvailable, tracker = null) {
72
+ return async (command, args = [], options = {}) => {
73
+ const wrapped = wrapWithRtk(command, args, rtkAvailable);
74
+ const result = await runCommand(wrapped.command, wrapped.args, options);
75
+
76
+ if (tracker && rtkAvailable && supportedSet.has(command)) {
77
+ const outputSize = Buffer.byteLength(result.stdout || "", "utf8");
78
+ // For RTK-wrapped calls, the output is already compressed.
79
+ // We estimate the original size as outputSize (conservative — real savings
80
+ // would require running the command without RTK, which defeats the purpose).
81
+ // The tracker is useful when the caller provides real estimates externally.
82
+ tracker.record(outputSize, outputSize);
83
+ }
84
+
85
+ return result;
86
+ };
87
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Per-run context store — makes module-level state in `utils/git.js`,
3
+ * `review/diff-generator.js`, etc. safe under concurrent `runFlow` calls.
4
+ *
5
+ * Pre-v2.7.5 the orchestrator mutated module-scope variables at pipeline
6
+ * start:
7
+ * setDiffRunner(rtkRunner); setDiffProjectDir(diffScope);
8
+ * setGitRunner(rtkRunner);
9
+ * // …later…
10
+ * // every git/diff op reads those globals
11
+ *
12
+ * That is fine for a single-threaded CLI invocation but corrupts when the
13
+ * MCP server fields two `kj_run` tool calls in parallel: each run would
14
+ * overwrite the others' runner/projectDir during setup, and subsequent
15
+ * reads would see a mix.
16
+ *
17
+ * TSK-0338 isolates that state to a per-run AsyncLocalStorage scope.
18
+ * `runFlow` wraps its execution in `withRunContext(ctx, fn)`, and the
19
+ * read paths in git.js / diff-generator.js look up
20
+ * `getRunContext()?.runner` before falling back to the module-level
21
+ * `_runner` (kept as a back-compat entry for callers outside a
22
+ * `runFlow` — CLI helpers, tests — that set state directly).
23
+ *
24
+ * What lives here vs. elsewhere:
25
+ * - `runContext` (this module) — runner, projectDir, snapshot — the
26
+ * pieces git/diff touches synchronously on every op.
27
+ * - `PipelineContext` (src/orchestrator/pipeline-context.js) — the
28
+ * richer structure ferried between stages. The two could merge
29
+ * eventually, but PipelineContext is created after preflight, and
30
+ * the runner/projectDir must be in scope BEFORE preflight runs
31
+ * (which itself calls git commands).
32
+ *
33
+ * The invariant `tests/orchestrator/concurrent-runs.test.js` exercises
34
+ * the isolation: two parallel `withRunContext(A, …)` and
35
+ * `withRunContext(B, …)` see their own runner, not each other's.
36
+ */
37
+
38
+ import { AsyncLocalStorage } from "node:async_hooks";
39
+
40
+ /**
41
+ * @typedef {Object} RunContext
42
+ * @property {((command: string, args?: string[], options?: object) => Promise<object>)|null} [runner]
43
+ * Pipeline-scoped command runner. When present, git.js + diff-generator.js
44
+ * route commands through it instead of the default `runCommand`.
45
+ * @property {string|null} [projectDir]
46
+ * Directory scope for `git diff`. Prevents leaking unrelated subdir
47
+ * changes when `kj run` is invoked from a subpath of a monorepo.
48
+ * @property {Map<string, string>|null} [snapshot]
49
+ * Pre-coder filesystem snapshot for snapshot-based diff when git is
50
+ * unavailable (greenfield projects with no initial commit).
51
+ */
52
+
53
+ const runStore = new AsyncLocalStorage();
54
+
55
+ /**
56
+ * Run `fn` with `ctx` as the active RunContext. All reads of
57
+ * `getRunContext()` inside (including from awaited callees) see `ctx`.
58
+ * Concurrent `withRunContext` invocations are fully isolated from each
59
+ * other — that's what AsyncLocalStorage guarantees.
60
+ *
61
+ * @param {RunContext} ctx
62
+ * @param {() => Promise<any>} fn
63
+ * @returns {Promise<any>}
64
+ */
65
+ export function withRunContext(ctx, fn) {
66
+ return runStore.run(ctx ?? {}, fn);
67
+ }
68
+
69
+ /**
70
+ * @returns {RunContext|undefined} the active RunContext, or undefined when
71
+ * called outside any `withRunContext` scope (legacy CLI paths, tests).
72
+ */
73
+ export function getRunContext() {
74
+ return runStore.getStore();
75
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * File-based run logger.
3
+ *
4
+ * Writes progress events to a known file so that external tools
5
+ * (tail -f, kj_status, another Claude process) can monitor what
6
+ * Karajan is doing in real time.
7
+ *
8
+ * Log location: <projectDir>/.kj/run.log (overwritten each run)
9
+ */
10
+
11
+ import fs from "node:fs";
12
+ import path from "node:path";
13
+
14
+ const LOG_FILENAME = "run.log";
15
+
16
+ function resolveLogDir(baseDir) {
17
+ return path.join(baseDir || process.cwd(), ".kj");
18
+ }
19
+
20
+ function resolveLogPath(baseDir) {
21
+ return path.join(resolveLogDir(baseDir), LOG_FILENAME);
22
+ }
23
+
24
+ function ensureDir(dir) {
25
+ try {
26
+ fs.mkdirSync(dir, { recursive: true });
27
+ } catch { /* already exists */ }
28
+ }
29
+
30
+ function formatLine(event) {
31
+ const ts = new Date().toISOString().slice(11, 23);
32
+ const stage = event.stage || event.detail?.stage || "";
33
+ const type = event.type || "info";
34
+ const msg = event.message || "";
35
+ const extra = [];
36
+
37
+ if (event.detail?.provider) extra.push(`agent=${event.detail.provider}`);
38
+ if (event.detail?.lineCount !== undefined) extra.push(`lines=${event.detail.lineCount}`);
39
+ if (event.detail?.elapsedMs !== undefined) extra.push(`elapsed=${Math.round(event.detail.elapsedMs / 1000)}s`);
40
+ if (event.detail?.silenceMs !== undefined) extra.push(`silence=${Math.round(event.detail.silenceMs / 1000)}s`);
41
+ if (event.detail?.severity) extra.push(`severity=${event.detail.severity}`);
42
+ if (event.detail?.stream) extra.push(`stream=${event.detail.stream}`);
43
+ if (event.detail?.cooldownUntil) extra.push(`until=${event.detail.cooldownUntil}`);
44
+ if (event.detail?.retryCount !== undefined) extra.push(`retry=${event.detail.retryCount}/${event.detail.maxRetries || "?"}`);
45
+ if (event.detail?.remainingMs !== undefined) extra.push(`remaining=${Math.round(event.detail.remainingMs / 1000)}s`);
46
+
47
+ const extraStr = extra.length ? ` (${extra.join(", ")})` : "";
48
+ const stageStr = stage ? `[${stage}] ` : "";
49
+ return `${ts} [${type}] ${stageStr}${msg}${extraStr}`;
50
+ }
51
+
52
+ export function createRunLog(projectDir) {
53
+ const logPath = resolveLogPath(projectDir);
54
+ const logDir = resolveLogDir(projectDir);
55
+ ensureDir(logDir);
56
+
57
+ // Truncate/create the log file
58
+ fs.writeFileSync(logPath, `--- Karajan run started at ${new Date().toISOString()} ---\n`);
59
+
60
+ // Audit recommendation (perf-LOW): suggested createWriteStream + queue.
61
+ // Tried it; broke the contract. `readRunLog` (used by `kj_status`,
62
+ // `kj-tail`, and the HU board's chokidar tick) reads the file with
63
+ // `fs.readFileSync` and expects every prior write to be visible the
64
+ // moment the writer's `logEvent()` returns — which is what
65
+ // `fs.writeSync(fd, ...)` guarantees and `stream.write()` does NOT.
66
+ //
67
+ // The current shape is already opened-once: `fs.openSync(logPath, "a")`
68
+ // returns an fd that every subsequent `fs.writeSync` reuses (no extra
69
+ // open/close per call). The hot-path complaint was about the FALLBACK
70
+ // `fs.appendFileSync` line, which only fires when openSync itself
71
+ // fails (rare; FS error or RO mount).
72
+ let fd = null;
73
+ try {
74
+ fd = fs.openSync(logPath, "a");
75
+ } catch {
76
+ // If we can't open for append, use writeFile fallback
77
+ }
78
+
79
+ function write(line) {
80
+ try {
81
+ if (fd === null) {
82
+ fs.appendFileSync(logPath, line + "\n");
83
+ } else {
84
+ fs.writeSync(fd, line + "\n");
85
+ }
86
+ } catch { /* best-effort */ }
87
+ }
88
+
89
+ function logEvent(event) {
90
+ write(formatLine(event));
91
+ }
92
+
93
+ function logText(text) {
94
+ const ts = new Date().toISOString().slice(11, 23);
95
+ write(`${ts} ${text}`);
96
+ }
97
+
98
+ function close() {
99
+ try {
100
+ if (fd !== null) {
101
+ fs.closeSync(fd);
102
+ fd = null;
103
+ }
104
+ } catch { /* best-effort */ }
105
+ }
106
+
107
+ return {
108
+ logEvent,
109
+ logText,
110
+ close,
111
+ get path() { return logPath; }
112
+ };
113
+ }
114
+
115
+ const KJ_TOOLS = ["kj_run", "kj_code", "kj_plan"];
116
+
117
+ function detectRunStart(line, status) {
118
+ const started = KJ_TOOLS.some(t => line.includes(`[${t}] started`));
119
+ if (!started) return;
120
+ status.isRunning = true;
121
+ status.currentStage = KJ_TOOLS.find(t => line.includes(t));
122
+ const tsMatch = /^(\d{2}:\d{2}:\d{2}\.\d{3})/.exec(line);
123
+ if (tsMatch) status.startedAt = tsMatch[1];
124
+ }
125
+
126
+ function detectRunFinish(line, status) {
127
+ const isToolFinish = KJ_TOOLS.some(t => line.includes(`[${t}] finished`) || line.includes(`[${t}]`));
128
+ if (line.includes("finished") && isToolFinish) {
129
+ status.isRunning = false;
130
+ }
131
+ }
132
+
133
+ function detectStageTransitions(line, status) {
134
+ const stageStart = /\[(\w+):start\]/.exec(line);
135
+ if (stageStart) status.currentStage = stageStart[1];
136
+
137
+ const stageDone = /\[(\w+):done\]|\[(\w+)\] finished/.exec(line);
138
+ if (stageDone) {
139
+ const doneName = stageDone[1] || stageDone[2];
140
+ if (doneName === status.currentStage) status.currentStage = "idle";
141
+ }
142
+ }
143
+
144
+ function detectMetadata(line, status) {
145
+ const agentMatch = /agent=(\w+)/.exec(line);
146
+ if (agentMatch) status.currentAgent = agentMatch[1];
147
+
148
+ const iterMatch = /[Ii]teration\s+(\d+)/.exec(line);
149
+ if (iterMatch) status.iteration = Number.parseInt(iterMatch[1], 10);
150
+
151
+ if (/\[.*:fail\]|\[.*error\]/i.test(line) || line.includes("ERROR")) {
152
+ status.errors.push(line.trim());
153
+ }
154
+
155
+ if (line.includes("[standby]") || line.includes("standby")) {
156
+ status.currentStage = "standby";
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Parse the run log to extract current status information.
162
+ */
163
+ function parseRunStatus(lines) {
164
+ const status = {
165
+ currentStage: null,
166
+ currentAgent: null,
167
+ startedAt: null,
168
+ isRunning: false,
169
+ lastEvent: null,
170
+ iteration: null,
171
+ errors: []
172
+ };
173
+
174
+ for (const line of lines) {
175
+ detectRunStart(line, status);
176
+ detectRunFinish(line, status);
177
+ detectStageTransitions(line, status);
178
+ detectMetadata(line, status);
179
+ status.lastEvent = line.trim();
180
+ }
181
+
182
+ if (status.errors.length > 3) status.errors = status.errors.slice(-3);
183
+ return status;
184
+ }
185
+
186
+ /**
187
+ * Read the current run log contents.
188
+ * Returns the last N lines (default 50) plus a parsed status summary.
189
+ */
190
+ export function readRunLog(projectDir, maxLines = 50) {
191
+ const logPath = resolveLogPath(projectDir);
192
+ try {
193
+ const content = fs.readFileSync(logPath, "utf8");
194
+ const lines = content.split("\n").filter(Boolean);
195
+ const total = lines.length;
196
+ const shown = lines.slice(-maxLines);
197
+ const status = parseRunStatus(lines);
198
+ const MAX_LINE_CHARS = 2000;
199
+ const truncated = shown.map(l => l.length > MAX_LINE_CHARS ? l.slice(0, MAX_LINE_CHARS) + "… [truncated]" : l);
200
+ return {
201
+ ok: true,
202
+ path: logPath,
203
+ totalLines: total,
204
+ status,
205
+ lines: truncated,
206
+ summary: truncated.join("\n")
207
+ };
208
+ } catch (err) {
209
+ return {
210
+ ok: false,
211
+ path: logPath,
212
+ error: err.code === "ENOENT"
213
+ ? "No active run log found. Start a run with kj_run first."
214
+ : `Failed to read log: ${err.message}`
215
+ };
216
+ }
217
+ }
@@ -0,0 +1,9 @@
1
+ // Shim: run-registry now lives in karajan-core/run-registry so the
2
+ // hu-board workspace can consume it without a relative dep on the CLI
3
+ // src tree. KJC-TSK-0511 PR3.
4
+ export {
5
+ runsDir,
6
+ registerRun,
7
+ unregisterRun,
8
+ listActiveRuns,
9
+ } from "karajan-core/run-registry";
@@ -0,0 +1,12 @@
1
+ // Shim — the real implementation now lives in karajan-core/shared-paths.
2
+ // Kept here so CLI callers (src/**/*.js) keep importing
3
+ // "../utils/shared-paths.js" without churn during KJC-TSK-0511 (decouple
4
+ // @karajan/hu-board). Will be retired once every consumer migrates to
5
+ // the karajan-core import.
6
+ export {
7
+ SHARED_DIR_NAME,
8
+ getSharedRoot,
9
+ getSharedPlansDir,
10
+ getSharedHuStoriesDir,
11
+ isSharedPath,
12
+ } from "karajan-core/shared-paths";
@@ -0,0 +1,21 @@
1
+ import { runCommand } from "./process.js";
2
+
3
+ /**
4
+ * Detect whether Squeezr is installed and available.
5
+ * @returns {Promise<{ available: boolean, version: string|null }>}
6
+ */
7
+ export async function detectSqueezr() {
8
+ try {
9
+ const result = await runCommand("squeezr", ["--version"]);
10
+ if (result.exitCode === 0) {
11
+ // `squeezr --version` may append an "update available" banner box; keep
12
+ // just the semver so callers never render that noise (KJC-BUG-0088).
13
+ const raw = (result.stdout || "").trim();
14
+ const version = raw.match(/\d+\.\d+\.\d+[\w.-]*/)?.[0] || raw.split("\n")[0].trim() || null;
15
+ return { available: true, version };
16
+ }
17
+ return { available: false, version: null };
18
+ } catch { /* squeezr binary not found */
19
+ return { available: false, version: null };
20
+ }
21
+ }