@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,66 @@
1
+ /**
2
+ * Karajan Code ASCII banner with brand colors.
3
+ *
4
+ * Brand palette:
5
+ * #AACCEE steel blue (primary text)
6
+ * #88CC88 green (accents, robot eyes)
7
+ * #464000 dark olive
8
+ * #444411 charcoal (secondary text)
9
+ */
10
+
11
+ const C = {
12
+ blue: "\x1b[38;2;170;204;238m", // #AACCEE
13
+ green: "\x1b[38;2;100;190;100m", // green accents
14
+ gray: "\x1b[38;2;140;140;140m", // borders/dim
15
+ white: "\x1b[38;2;220;220;220m", // bright text
16
+ charcoal: "\x1b[38;2;100;100;80m", // #444411 approx
17
+ bold: "\x1b[1m",
18
+ dim: "\x1b[2m",
19
+ reset: "\x1b[0m"
20
+ };
21
+
22
+ const R = C.reset;
23
+
24
+ const BANNER_LINES = [
25
+ ``,
26
+ `${C.gray} ╭───────────╮`,
27
+ `${C.gray} │ ${C.green}~${C.gray} │`,
28
+ `${C.gray} │ ${C.green}|${C.gray} ${C.green}|${C.gray} │ ${C.charcoal}|`,
29
+ `${C.gray} | ${C.green}v${C.gray} │ ${C.charcoal}/`,
30
+ `${C.gray} ${C.charcoal}\\${C.gray} ╰───────────╯${C.charcoal}/`,
31
+ `${C.charcoal} \\${C.gray} ╭───${C.white}⋈${C.gray}───╮ ${C.charcoal}/`,
32
+ `${C.charcoal} \\${C.gray} ${C.charcoal}/`,
33
+ `${C.gray} ╰───────╯`,
34
+ ``,
35
+ ` ${C.bold}${C.blue}╦╔═ ╔═╗ ╦═╗ ╔═╗ ╦ ╔═╗ ╔╗╔${R}`,
36
+ ` ${C.bold}${C.blue}╠╩╗ ╠═╣ ╠╦╝ ╠═╣ ║ ╠═╣ ║║║${R}`,
37
+ ` ${C.bold}${C.blue}╩ ╩ ╩ ╩ ╩╚═ ╩ ╩ ╚╝ ╩ ╩ ╝╚╝${R}`,
38
+ ` ${C.bold}${C.white} C O D E${R} %%VERSION%%`,
39
+ ` ${C.charcoal}multiagent coding orchestrator${R}`,
40
+ ``,
41
+ ];
42
+
43
+ /**
44
+ * Print the Karajan Code ASCII banner.
45
+ * @param {string} version - Package version to display
46
+ * @param {object} [opts]
47
+ * @param {boolean} [opts.compact] - Skip mascot, show only text
48
+ * @param {boolean} [opts.force] - Print even without TTY
49
+ */
50
+ export function printBanner(version, opts = {}) {
51
+ if (!opts.force && !process.stdout.isTTY) return;
52
+
53
+ const versionTag = `${C.dim}v${version}${R}`;
54
+
55
+ if (opts.compact) {
56
+ console.log();
57
+ for (const line of BANNER_LINES.slice(10)) {
58
+ console.log(line.replace("%%VERSION%%", versionTag));
59
+ }
60
+ return;
61
+ }
62
+
63
+ for (const line of BANNER_LINES) {
64
+ console.log(line.replace("%%VERSION%%", versionTag));
65
+ }
66
+ }
@@ -0,0 +1,70 @@
1
+ // Standalone install routes for tools with no package manager available
2
+ // (KJC-TSK-0607). On a machine with no pipx/brew/go, `kj install-tools`
3
+ // still needs a way to install osv-scanner and semgrep.
4
+ //
5
+ // · osv-scanner ships a single static binary per platform on its GitHub
6
+ // releases — we build the /latest/download URL for the current platform.
7
+ // · semgrep has no single static binary; we offer the most viable concrete
8
+ // command (Docker image if docker exists, otherwise bootstrapping pipx).
9
+
10
+ const OSV_BASE = "https://github.com/google/osv-scanner/releases/latest/download";
11
+
12
+ function osvOs(platform) {
13
+ if (platform === "linux") return "linux";
14
+ if (platform === "darwin") return "darwin";
15
+ if (platform === "win32") return "windows";
16
+ return null;
17
+ }
18
+
19
+ function osvArch(arch) {
20
+ if (arch === "x64") return "amd64";
21
+ if (arch === "arm64") return "arm64";
22
+ return null;
23
+ }
24
+
25
+ /**
26
+ * Build the osv-scanner static-binary download source for a platform+arch,
27
+ * or null when the combination has no published asset.
28
+ *
29
+ * @returns {{ url: string, name: string }|null}
30
+ */
31
+ export function osvScannerSource(platform = process.platform, arch = process.arch) {
32
+ const os = osvOs(platform);
33
+ const a = osvArch(arch);
34
+ if (!os || !a) return null;
35
+ const ext = os === "windows" ? ".exe" : "";
36
+ return { url: `${OSV_BASE}/osv-scanner_${os}_${a}${ext}`, name: `osv-scanner${ext}` };
37
+ }
38
+
39
+ /**
40
+ * Most viable concrete route to install semgrep without a package manager.
41
+ * Returns a command the user sees before it runs — never a bare docs URL.
42
+ *
43
+ * @returns {{ via: "docker"|"pipx", command: string }}
44
+ */
45
+ export function semgrepFallback(available = {}) {
46
+ if (available.docker) return { via: "docker", command: "docker pull semgrep/semgrep" };
47
+ // KJC-BUG-0120 (issue #1256): on Debian/Ubuntu-like systems the system
48
+ // Python is externally managed (PEP 668) and often ships without pip at
49
+ // all — `python3 -m pip install --user` is guaranteed to fail there.
50
+ // pipx must come from the distro's own package manager.
51
+ if (available.apt) return { via: "apt", command: "sudo apt update && sudo apt install -y pipx && pipx install semgrep" };
52
+ if (available.dnf) return { via: "dnf", command: "sudo dnf install -y pipx && pipx install semgrep" };
53
+ return { via: "pipx", command: "python3 -m pip install --user pipx && pipx install semgrep" };
54
+ }
55
+
56
+ /**
57
+ * Resolve the standalone route for a tool when no package manager matched.
58
+ * · binary → download a static binary into ~/.local/bin.
59
+ * · command → run/show a concrete install command.
60
+ *
61
+ * @returns {{ kind: "binary", url: string, name: string }|{ kind: "command", via: string, command: string }|null}
62
+ */
63
+ export function resolveStandalone(tool, available = {}, platform = process.platform, arch = process.arch) {
64
+ if (tool === "osv-scanner") {
65
+ const src = osvScannerSource(platform, arch);
66
+ return src ? { kind: "binary", ...src } : null;
67
+ }
68
+ if (tool === "semgrep") return { kind: "command", ...semgrepFallback(available) };
69
+ return null;
70
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * File-based RPC between a non-interactive Karajan run and the HU
3
+ * Board. When the runner needs an answer to a question (Solomon
4
+ * escalation, max-iterations resolution, anything wired to
5
+ * askQuestion) and stdin is unavailable (the board's ▶ Run plan
6
+ * spawns with stdio=ignore), it writes a prompt JSON to a known
7
+ * directory and polls for an "answer" sibling file. The board's
8
+ * chokidar watcher sees the prompt and surfaces it as a modal; the
9
+ * user's answer is POSTed back, written as the answer file, and the
10
+ * runner picks it up and resolves.
11
+ *
12
+ * Why files instead of a socket / SSE-back-channel:
13
+ * - Zero new server in the runner. A detached child has no listening
14
+ * port; opening one would mean discovery + auth + cleanup.
15
+ * - Survives a runner restart: if the user kills + resumes, the
16
+ * pending prompt is still on disk and the board can re-show it.
17
+ * - The board already watches `~/.karajan/`; one more glob is cheap.
18
+ *
19
+ * Layout:
20
+ * $KJ_HOME/prompts/<promptId>.json - { sessionId, question, context, createdAt }
21
+ * $KJ_HOME/prompts/<promptId>.answer.json - { answer, answeredAt } (written by board)
22
+ *
23
+ * The bridge owns the lifecycle: write the prompt, poll until the
24
+ * answer arrives, delete BOTH files, return the answer string (or
25
+ * null when the user picked "stop"). Aborts cleanly on signal or on
26
+ * a configurable timeout (default 30 min — long enough for a coffee).
27
+ */
28
+
29
+ import { mkdir, writeFile, readFile, unlink, stat } from "node:fs/promises";
30
+ import { join } from "node:path";
31
+ import { randomUUID } from "node:crypto";
32
+
33
+ const POLL_INTERVAL_MS = 500;
34
+ const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000; // 30 min
35
+
36
+ // Delegated to src/utils/paths.js so KARAJAN_HOME, KJ_HOME (with
37
+ // deprecation warning), VITEST tmp and the default all share one
38
+ // precedence chain — KJC-TSK-0420.
39
+ import { getPromptsDir } from "./paths.js";
40
+
41
+ function exists(path) {
42
+ return stat(path).then(() => true, () => false);
43
+ }
44
+
45
+ /**
46
+ * Publish a prompt + wait for the answer. Returns the answer string,
47
+ * `null` when the user explicitly picked "stop", or rejects on
48
+ * timeout / abort.
49
+ *
50
+ * @param {object} args
51
+ * @param {string} args.sessionId
52
+ * @param {string} args.question
53
+ * @param {object} [args.context] - serialised verbatim into the prompt JSON
54
+ * @param {number} [args.timeoutMs]
55
+ * @param {AbortSignal} [args.signal]
56
+ * @param {object} [args.logger] - { info, warn } — optional, for breadcrumbs
57
+ * @returns {Promise<string|null>}
58
+ */
59
+ export async function askThroughBoard({ sessionId, question, context = null, timeoutMs = DEFAULT_TIMEOUT_MS, signal = null, logger = null } = {}) {
60
+ if (!question) throw new Error("askThroughBoard: question is required");
61
+
62
+ const dir = getPromptsDir();
63
+ await mkdir(dir, { recursive: true });
64
+
65
+ const promptId = `prompt-${Date.now()}-${randomUUID().slice(0, 8)}`;
66
+ const promptPath = join(dir, `${promptId}.json`);
67
+ const answerPath = join(dir, `${promptId}.answer.json`);
68
+
69
+ const payload = {
70
+ promptId,
71
+ sessionId: sessionId || null,
72
+ question,
73
+ context: context || null,
74
+ createdAt: new Date().toISOString(),
75
+ };
76
+ await writeFile(promptPath, JSON.stringify(payload, null, 2), "utf-8");
77
+ logger?.info?.(`[prompt-bridge] published ${promptId} — waiting for answer via the board`);
78
+
79
+ const startedAt = Date.now();
80
+ try {
81
+ while (true) {
82
+ if (signal?.aborted) throw new Error("askThroughBoard: aborted");
83
+ if (Date.now() - startedAt > timeoutMs) {
84
+ throw new Error(`askThroughBoard: timed out after ${Math.round(timeoutMs / 1000)}s waiting for answer to ${promptId}`);
85
+ }
86
+ if (await exists(answerPath)) {
87
+ const raw = await readFile(answerPath, "utf-8");
88
+ let answer;
89
+ try { ({ answer } = JSON.parse(raw)); } catch { answer = null; }
90
+ await unlink(answerPath).catch(() => {});
91
+ await unlink(promptPath).catch(() => {});
92
+ if (typeof answer === "string" && answer.trim().toLowerCase() === "stop") return null;
93
+ return typeof answer === "string" ? answer.trim() : null;
94
+ }
95
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
96
+ }
97
+ } catch (err) {
98
+ // Best-effort cleanup of the prompt file on error so it doesn't
99
+ // get stuck pending on the board forever.
100
+ await unlink(promptPath).catch(() => {});
101
+ throw err;
102
+ }
103
+ }
104
+
105
+ /** Test seam — exposes the resolved prompts dir for assertions. */
106
+ export function _getPromptsDirForTests() {
107
+ return getPromptsDir();
108
+ }
@@ -0,0 +1,229 @@
1
+ import { calculateUsageCostUsd, DEFAULT_MODEL_PRICING, mergePricing } from "./pricing.js";
2
+
3
+ /**
4
+ * Estimate token counts from character lengths when CLIs don't report usage.
5
+ * Rough heuristic: ~4 characters per token for English text.
6
+ */
7
+ export function estimateTokens(promptLength, responseLength) {
8
+ return {
9
+ tokens_in: Math.ceil((promptLength || 0) / 4),
10
+ tokens_out: Math.ceil((responseLength || 0) / 4),
11
+ estimated: true
12
+ };
13
+ }
14
+
15
+ export function extractUsageMetrics(result, defaultModel = null) {
16
+ const usage = result?.usage || result?.metrics || {};
17
+ const tokens_in =
18
+ result?.tokens_in ??
19
+ usage?.tokens_in ??
20
+ usage?.input_tokens ??
21
+ usage?.prompt_tokens ??
22
+ 0;
23
+ const tokens_out =
24
+ result?.tokens_out ??
25
+ usage?.tokens_out ??
26
+ usage?.output_tokens ??
27
+ usage?.completion_tokens ??
28
+ 0;
29
+ const cached_tokens =
30
+ result?.cached_tokens ??
31
+ usage?.cached_tokens ??
32
+ usage?.cache_read_input_tokens ??
33
+ usage?.prompt_tokens_details?.cached_tokens ??
34
+ usage?.cachedContentTokenCount ??
35
+ 0;
36
+ const cost_usd =
37
+ result?.cost_usd ??
38
+ usage?.cost_usd ??
39
+ usage?.usd_cost ??
40
+ usage?.cost;
41
+ const model =
42
+ result?.model ??
43
+ usage?.model ??
44
+ usage?.model_name ??
45
+ usage?.model_id ??
46
+ defaultModel ??
47
+ null;
48
+
49
+ // If no real token data AND no explicit cost, estimate from prompt/output sizes.
50
+ // Primary: uses result.promptSize when explicitly provided.
51
+ // Fallback: estimates from result.output or result.error text length.
52
+ let estimated = false;
53
+ let finalTokensIn = tokens_in;
54
+ let finalTokensOut = tokens_out;
55
+ const hasExplicitCost = cost_usd !== undefined && cost_usd !== null && cost_usd !== "";
56
+ if (!tokens_in && !tokens_out && !hasExplicitCost) {
57
+ const outputText = result?.output || result?.error || result?.summary || "";
58
+ const promptSize = result?.promptSize || 0;
59
+ const MIN_TEXT_FOR_ESTIMATION = 40;
60
+ if (promptSize > 0 || outputText.length >= MIN_TEXT_FOR_ESTIMATION) {
61
+ const est = estimateTokens(promptSize, outputText.length);
62
+ finalTokensIn = est.tokens_in;
63
+ finalTokensOut = est.tokens_out;
64
+ estimated = true;
65
+ }
66
+ }
67
+
68
+ return { tokens_in: finalTokensIn, tokens_out: finalTokensOut, cached_tokens, cost_usd, model, estimated };
69
+ }
70
+
71
+ function toSafeNumber(value) {
72
+ const n = Number(value);
73
+ if (!Number.isFinite(n) || n < 0) return 0;
74
+ return n;
75
+ }
76
+
77
+ function roundUsd(value) {
78
+ return Number(toSafeNumber(value).toFixed(6));
79
+ }
80
+
81
+ function normalizeLimit(limit) {
82
+ if (limit === null || limit === undefined || limit === "") return null;
83
+ const n = Number(limit);
84
+ if (!Number.isFinite(n) || n < 0) return null;
85
+ return n;
86
+ }
87
+
88
+ function addToBreakdown(map, key, entry) {
89
+ const current = map[key] || { tokens_in: 0, tokens_out: 0, cached_tokens: 0, total_tokens: 0, total_cost_usd: 0, count: 0 };
90
+ current.tokens_in += entry.tokens_in;
91
+ current.tokens_out += entry.tokens_out;
92
+ current.cached_tokens += entry.cached_tokens || 0;
93
+ current.total_tokens += entry.tokens_in + entry.tokens_out;
94
+ current.total_cost_usd = roundUsd(current.total_cost_usd + entry.cost_usd);
95
+ current.count += 1;
96
+ map[key] = current;
97
+ }
98
+
99
+ export class BudgetTracker {
100
+ constructor(options = {}) {
101
+ this.entries = [];
102
+ this.pricing = mergePricing(DEFAULT_MODEL_PRICING, options.pricing || {});
103
+ }
104
+
105
+ record({ role, provider, model, tokens_in, tokens_out, cached_tokens, cost_usd, duration_ms, stage_index, estimated } = {}) {
106
+ const safeTokensIn = toSafeNumber(tokens_in);
107
+ const safeTokensOut = toSafeNumber(tokens_out);
108
+ const safeCached = toSafeNumber(cached_tokens);
109
+ const hasExplicitCost = cost_usd !== undefined && cost_usd !== null && cost_usd !== "";
110
+ const modelName = model || provider || null;
111
+ const computedCost = calculateUsageCostUsd({
112
+ provider: provider,
113
+ model: modelName,
114
+ tokens_in: safeTokensIn,
115
+ tokens_out: safeTokensOut,
116
+ pricing: this.pricing
117
+ });
118
+ const entry = {
119
+ role: role || "unknown",
120
+ provider: provider || "unknown",
121
+ model: modelName,
122
+ timestamp: new Date().toISOString(),
123
+ tokens_in: safeTokensIn,
124
+ tokens_out: safeTokensOut,
125
+ cached_tokens: safeCached,
126
+ cost_usd: roundUsd(hasExplicitCost ? cost_usd : computedCost)
127
+ };
128
+ if (duration_ms !== undefined && duration_ms !== null) {
129
+ entry.duration_ms = toSafeNumber(duration_ms);
130
+ }
131
+ if (stage_index !== undefined && stage_index !== null) {
132
+ entry.stage_index = Number(stage_index);
133
+ }
134
+ if (estimated) {
135
+ entry.estimated = true;
136
+ }
137
+ this.entries.push(entry);
138
+ return entry;
139
+ }
140
+
141
+ total() {
142
+ return this._aggregate(this.entries);
143
+ }
144
+
145
+ _aggregate(entries) {
146
+ let tokensIn = 0;
147
+ let tokensOut = 0;
148
+ let cached = 0;
149
+ let totalCost = 0;
150
+ for (const entry of entries) {
151
+ tokensIn += entry.tokens_in;
152
+ tokensOut += entry.tokens_out;
153
+ cached += entry.cached_tokens || 0;
154
+ totalCost = roundUsd(totalCost + entry.cost_usd);
155
+ }
156
+ return { tokens_in: tokensIn, tokens_out: tokensOut, cached_tokens: cached, cost_usd: totalCost };
157
+ }
158
+
159
+ /**
160
+ * Snapshot cursor (Φ0-E). Returns an opaque marker pointing at the current
161
+ * end of the entries log. Pair with `since(cursor)` to compute per-HU deltas
162
+ * without resetting global accumulators (per-HU isolation).
163
+ */
164
+ cursor() {
165
+ return this.entries.length;
166
+ }
167
+
168
+ since(cursor = 0) {
169
+ const start = Number.isFinite(cursor) && cursor >= 0 ? Math.min(cursor, this.entries.length) : 0;
170
+ const slice = this.entries.slice(start);
171
+ return { ...this._aggregate(slice), count: slice.length };
172
+ }
173
+
174
+ remaining(limit) {
175
+ const n = normalizeLimit(limit);
176
+ if (n === null) return Infinity;
177
+ return roundUsd(n - this.total().cost_usd);
178
+ }
179
+
180
+ isOverBudget(limit) {
181
+ const n = normalizeLimit(limit);
182
+ if (n === null) return false;
183
+ return this.total().cost_usd > n;
184
+ }
185
+
186
+ hasUsageData() {
187
+ return this.entries.length > 0 && (this.total().tokens_in > 0 || this.total().tokens_out > 0 || this.total().cost_usd > 0);
188
+ }
189
+
190
+ summary() {
191
+ const totals = this.total();
192
+ const byRole = {};
193
+
194
+ for (const entry of this.entries) {
195
+ addToBreakdown(byRole, entry.role, entry);
196
+ }
197
+
198
+ const hasEstimates = this.entries.some(e => e.estimated);
199
+ const result = {
200
+ total_tokens: totals.tokens_in + totals.tokens_out,
201
+ total_cached_tokens: totals.cached_tokens,
202
+ total_cost_usd: totals.cost_usd,
203
+ breakdown_by_role: byRole,
204
+ entries: [...this.entries],
205
+ usage_available: this.hasUsageData()
206
+ };
207
+ if (hasEstimates) result.includes_estimates = true;
208
+ return result;
209
+ }
210
+
211
+ trace() {
212
+ return this.entries.map((entry, index) => {
213
+ const item = {
214
+ index: entry.stage_index ?? index,
215
+ role: entry.role,
216
+ provider: entry.provider,
217
+ model: entry.model,
218
+ timestamp: entry.timestamp,
219
+ duration_ms: entry.duration_ms ?? null,
220
+ tokens_in: entry.tokens_in,
221
+ tokens_out: entry.tokens_out,
222
+ cached_tokens: entry.cached_tokens || 0,
223
+ cost_usd: entry.cost_usd
224
+ };
225
+ if (entry.estimated) item.estimated = true;
226
+ return item;
227
+ });
228
+ }
229
+ }
@@ -0,0 +1,93 @@
1
+ import readline from "node:readline";
2
+
3
+ /**
4
+ * Shared askQuestion factory used by `kj run` and `kj resume`.
5
+ *
6
+ * Pre-fix (KJC-BUG-0081 round 1), `src/commands/run.js` got the guard
7
+ * but `src/commands/resume.js` kept its own copy without the guard, so
8
+ * `kj resume --yes` in non-TTY mode still hung on the HU Board bridge.
9
+ * Centralising the three paths here means both commands honour the
10
+ * same contract and a future fix only needs to land in one place.
11
+ *
12
+ * Three paths:
13
+ * 1. Interactive TTY: prompt via readline (developer terminal).
14
+ * 2. No TTY + `flags.yes`: caller asked NOT to be prompted → write
15
+ * question + context to stderr, return null so the run aborts
16
+ * fast and loud (CI / scripted / `kj audit --yes` desatendido).
17
+ * 3. No TTY without `flags.yes` (HU Board ▶ Run plan with
18
+ * `stdio=ignore`): publish through the file-based bridge so the
19
+ * board can surface a modal; block until the user answers.
20
+ *
21
+ * @param {object} [opts]
22
+ * @param {string|null} [opts.sessionId]
23
+ * @param {object} [opts.flags]
24
+ * @returns {(question: string, context?: object) => Promise<string|null>}
25
+ */
26
+ export function createCliAskQuestion(opts = {}) {
27
+ const { sessionId = null, flags = {} } = opts;
28
+ return async (question, context) => {
29
+ const stdinReadable = process.stdin && process.stdin.readable !== false;
30
+ const isInteractive = Boolean(process.stdin?.isTTY) && stdinReadable;
31
+ // KJC-TSK-0674 (issue #1289): agents and CI enable the same contract
32
+ // as --yes explicitly, via --non-interactive or KJ_NON_INTERACTIVE=1,
33
+ // instead of blocking forever on a board modal nobody is watching.
34
+ // Explicit mode wins even when a (pseudo-)TTY is attached.
35
+ const forcedNonInteractive = flags?.nonInteractive || process.env.KJ_NON_INTERACTIVE === "1";
36
+ if (!isInteractive || forcedNonInteractive) {
37
+ const nonInteractive = forcedNonInteractive || flags?.yes;
38
+ if (nonInteractive) {
39
+ // KJC-BUG-0109: a question that declares a safe default is answered
40
+ // with it — --yes means "press Enter for me", not "abort on any
41
+ // gate". Questions without a declared default keep failing loud.
42
+ const fallback = typeof context?.defaultAnswer === "string" && context.defaultAnswer.trim()
43
+ ? context.defaultAnswer.trim() : null;
44
+ if (fallback) {
45
+ process.stderr.write(`\n[non-interactive] Auto-answering with declared default "${fallback}": ${question}\n`);
46
+ return fallback;
47
+ }
48
+ process.stderr.write(
49
+ `\n[non-interactive] Pipeline asked a question that cannot be auto-answered:\n`
50
+ + ` ❓ ${question}\n`
51
+ + (context?.detail ? ` Context: ${JSON.stringify(context.detail)}\n` : "")
52
+ + ` Stopping the session. Re-run interactively (TTY or HU Board) to answer it,\n`
53
+ + ` or pass --skip-spec-review / a more complete spec so the question never appears.\n`
54
+ );
55
+ return null;
56
+ }
57
+ const { askThroughBoard } = await import("./board-prompt-bridge.js");
58
+ console.log(`\n❓ ${question}`);
59
+ if (context?.detail) {
60
+ console.log(` Context: ${JSON.stringify(context.detail, null, 2)}`);
61
+ }
62
+ console.log(
63
+ "\n[non-interactive] Routing the prompt to the HU Board.\n"
64
+ + " Open http://localhost:4000 — a modal will appear asking for your answer.\n"
65
+ + " This process is now waiting; closing the board does NOT cancel the run.\n"
66
+ + " Running from an agent or CI with nobody watching the board? Re-run with\n"
67
+ + " --non-interactive (or KJ_NON_INTERACTIVE=1) to auto-answer safe defaults instead."
68
+ );
69
+ try {
70
+ return await askThroughBoard({ sessionId, question, context });
71
+ } catch (err) {
72
+ console.log(`\n[prompt-bridge] ${err.message} — stopping the session.`);
73
+ return null;
74
+ }
75
+ }
76
+
77
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
78
+ return new Promise((resolve) => {
79
+ console.log(`\n❓ ${question}`);
80
+ if (context?.detail) {
81
+ console.log(` Context: ${JSON.stringify(context.detail, null, 2)}`);
82
+ }
83
+ rl.question("\n> Your response (or 'stop' to exit): ", (answer) => {
84
+ rl.close();
85
+ if (answer.trim().toLowerCase() === "stop") {
86
+ resolve(null);
87
+ } else {
88
+ resolve(answer.trim());
89
+ }
90
+ });
91
+ });
92
+ };
93
+ }