@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,280 @@
1
+ import fs from "node:fs/promises";
2
+ import { readFileSync } from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { isSea } from "node:sea";
6
+ import { getKarajanHome } from "./paths.js";
7
+
8
+ const CACHE_FILE = "update-check.json";
9
+ // KJC-TSK-0690: 6h — kj can ship several releases a day; a session should
10
+ // not work a full day blind. KJ_NO_UPDATE_CHECK=1 opts out (CI).
11
+ const CACHE_TTL_MS = 6 * 60 * 60 * 1000;
12
+ // MIG-A (KJC-TSK-0751): el nombre npm se lee del PROPIO manifest — con el
13
+ // dual-publish del scope, el mismo código vive como karajan-code y como
14
+ // @karajan-family/code y cada instalación se auto-actualiza por SU nombre.
15
+ // Lazy + fallback: en el bundle SEA no hay package.json junto al módulo.
16
+ let _pkgName;
17
+ export function packageName() {
18
+ if (_pkgName) return _pkgName;
19
+ try {
20
+ _pkgName = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).name || "karajan-code";
21
+ } catch {
22
+ _pkgName = "karajan-code";
23
+ }
24
+ return _pkgName;
25
+ }
26
+
27
+ // URL del registro con el nombre CODIFICADO — el scoped @karajan-family/code
28
+ // lleva @ y / que rompen la ruta sin encode (catch de codex).
29
+ export const registryLatestUrl = (name = packageName()) =>
30
+ `https://registry.npmjs.org/${encodeURIComponent(name)}/latest`;
31
+ const CHANGELOG_URL = "https://raw.githubusercontent.com/manufosela/karajan-code/main/CHANGELOG.md";
32
+ const HIGHLIGHT_MAX = 160;
33
+
34
+ /**
35
+ * First paragraph of a version's CHANGELOG section — the release headline
36
+ * ("Minor. **The method, enforced.** …"), bold stripped, truncated. Pure.
37
+ */
38
+ export function parseChangelogHighlight(markdown, version) {
39
+ const escapedVersion = version.replaceAll(".", String.raw`\.`);
40
+ const section = String(markdown).split(new RegExp(String.raw`^## \[${escapedVersion}\][^\n]*$`, "m"))[1];
41
+ if (!section) return null;
42
+ const firstLine = section.split(/^##|^###/m)[0].split("\n").map((l) => l.trim()).find(Boolean);
43
+ if (!firstLine) return null;
44
+ const clean = firstLine.replaceAll("**", "");
45
+ return clean.length > HIGHLIGHT_MAX ? `${clean.slice(0, HIGHLIGHT_MAX - 1)}…` : clean;
46
+ }
47
+
48
+ async function fetchHighlight(version) {
49
+ try {
50
+ const controller = new AbortController();
51
+ const timeout = setTimeout(() => controller.abort(), 3000);
52
+ const res = await fetch(CHANGELOG_URL, { signal: controller.signal });
53
+ clearTimeout(timeout);
54
+ if (!res.ok) return null;
55
+ return parseChangelogHighlight(await res.text(), version);
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+
61
+ const RAW_BASE = "https://raw.githubusercontent.com/manufosela/karajan-code/main/scripts";
62
+ export const INSTALL_SH_URL = `${RAW_BASE}/install-binary.sh`;
63
+ export const INSTALL_PS1_URL = `${RAW_BASE}/install-binary.ps1`;
64
+
65
+ /**
66
+ * Build the "how to update" line for the detected install channel.
67
+ * Pure and testable — no I/O.
68
+ * @param {{channel: "sea"|"npm"|"unknown", platform?: string}} opts
69
+ */
70
+ export function updateInstruction({ channel, platform = process.platform }) {
71
+ if (channel === "sea") {
72
+ return platform === "win32"
73
+ ? `Re-run the installer: irm ${INSTALL_PS1_URL} | iex`
74
+ : `Re-run the installer: curl -fsSL ${INSTALL_SH_URL} | sh`;
75
+ }
76
+ if (channel === "npm") {
77
+ return `Run: npm install -g ${packageName()}`;
78
+ }
79
+ // Channel unknown — offer both paths, never silently pick a wrong one.
80
+ return `Update: npm install -g ${packageName()} (or re-run the binary installer — see README)`;
81
+ }
82
+
83
+ /**
84
+ * Detect how this kj was installed: "sea" (standalone binary) or "npm"
85
+ * (global install / source tree). Falls back to "npm" if isSea() throws.
86
+ */
87
+ export function detectInstallChannel() {
88
+ try {
89
+ return isSea() ? "sea" : "npm";
90
+ } catch {
91
+ // isSea() unexpectedly threw ⇒ treat as npm / source tree, never block.
92
+ return "npm";
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Check npm for a newer version. Non-blocking, cached for 24h.
98
+ * Returns { updateAvailable, latest, current } or null if check fails/cached.
99
+ */
100
+ export async function checkForUpdate(currentVersion) {
101
+ if (process.env.KJ_NO_UPDATE_CHECK === "1") return null;
102
+ try {
103
+ const cachePath = path.join(getKarajanHome(), CACHE_FILE);
104
+
105
+ // Check cache first
106
+ try {
107
+ const raw = await fs.readFile(cachePath, "utf8");
108
+ const cache = JSON.parse(raw);
109
+ if (cache.checkedAt && Date.now() - cache.checkedAt < CACHE_TTL_MS) {
110
+ if (!cache.latest || cache.latest === currentVersion) return null;
111
+ // Only show update if latest is actually NEWER than current
112
+ if (compareVersions(cache.latest, currentVersion) > 0) {
113
+ return { updateAvailable: true, latest: cache.latest, current: currentVersion, highlight: cache.highlight || null };
114
+ }
115
+ return null;
116
+ }
117
+ } catch { /* no cache or expired */ }
118
+
119
+ // Fetch from npm (timeout 3s, don't block)
120
+ const controller = new AbortController();
121
+ const timeout = setTimeout(() => controller.abort(), 3000);
122
+ const res = await fetch(registryLatestUrl(), {
123
+ signal: controller.signal,
124
+ headers: { "Accept": "application/json" },
125
+ });
126
+ clearTimeout(timeout);
127
+
128
+ if (!res.ok) return null;
129
+ const data = await res.json();
130
+ const latest = data.version;
131
+
132
+ // KJC-TSK-0690: a NEWER version also fetches its headline once — the
133
+ // notice tells the user what it brings, not just that it exists.
134
+ const newer = latest !== currentVersion && compareVersions(latest, currentVersion) > 0;
135
+ const highlight = newer ? await fetchHighlight(latest) : null;
136
+
137
+ // Save cache
138
+ await fs.mkdir(getKarajanHome(), { recursive: true });
139
+ await fs.writeFile(cachePath, JSON.stringify({ latest, checkedAt: Date.now(), highlight }), "utf8");
140
+
141
+ if (newer) return { updateAvailable: true, latest, current: currentVersion, highlight };
142
+ return null;
143
+ } catch {
144
+ return null; // Network error, offline, etc. Never block.
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Print update notice if available. Call at CLI startup, non-blocking.
150
+ */
151
+ export async function printUpdateNotice(currentVersion) {
152
+ const result = await checkForUpdate(currentVersion);
153
+ if (result?.updateAvailable) {
154
+ const channel = detectInstallChannel();
155
+ console.log(`\n Update available: v${result.current} → v${result.latest}`);
156
+ if (result.highlight) console.log(` What it brings: ${result.highlight}`);
157
+ console.log(` ${updateInstruction({ channel })}`);
158
+ console.log(" Agent: tell your user and ask before updating — never update on your own.\n");
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Run the self-update (`kj update`), channel-aware (KJC-BUG-0106).
164
+ *
165
+ * npm channel: `npm install -g` with CAPTURED output — success shows only
166
+ * progress + result; npm's deprecation / allow-scripts / funding noise never
167
+ * reaches the user. On failure the captured output IS surfaced.
168
+ *
169
+ * sea channel (standalone binary): npm-installing would update a copy the
170
+ * PATH never resolves — the running binary stays old while `kj update`
171
+ * reports success. Instead the binary installer is re-run (downloaded to a
172
+ * temp file first, never piped from the network straight into a shell).
173
+ *
174
+ * Both channels end with a PATH probe: `kj --version` must report the new
175
+ * version, otherwise a stale copy shadows the update and the command fails
176
+ * LOUDLY naming the likely cause — never a silent "updated" that isn't.
177
+ *
178
+ * @param {Object} opts
179
+ * @param {string} opts.currentVersion - version of the running kj
180
+ * @param {(cmd: string, args: string[]) => Promise<{stdout: string, stderr: string}>} [opts.exec] - injectable runner (defaults to execa)
181
+ * @param {Console} [opts.logger]
182
+ * @param {"npm"|"sea"} [opts.channel] - injectable channel (defaults to detectInstallChannel())
183
+ * @param {typeof fetch} [opts.fetchFn] - injectable fetch (registry lookup + installer download)
184
+ * @returns {Promise<{ ok: boolean, alreadyLatest?: boolean, latest?: string, manual?: boolean }>}
185
+ */
186
+ export async function performSelfUpdate({ currentVersion, exec, logger = console, channel, fetchFn = fetch } = {}) {
187
+ const run = exec || (async (cmd, args) => (await import("execa")).execa(cmd, args));
188
+ const ch = channel || detectInstallChannel();
189
+ logger.log(`Current version: ${currentVersion}`);
190
+ logger.log("Checking for updates...");
191
+
192
+ let latest;
193
+ try {
194
+ // Registry over HTTP, not `npm view` — standalone-binary machines may
195
+ // not have npm at all.
196
+ const res = await fetchFn(registryLatestUrl(), {
197
+ headers: { Accept: "application/json" },
198
+ });
199
+ if (!res.ok) throw new Error(`registry responded ${res.status}`);
200
+ latest = (await res.json()).version;
201
+ } catch (err) {
202
+ logger.error(`Update failed: could not check the registry (${err.message})`);
203
+ return { ok: false };
204
+ }
205
+
206
+ if (latest === currentVersion) {
207
+ logger.log(`Already on the latest version (${currentVersion}).`);
208
+ return { ok: true, alreadyLatest: true, latest };
209
+ }
210
+
211
+ if (ch === "sea" && process.platform === "win32") {
212
+ // Executing a downloaded .ps1 from inside the binary is not supported
213
+ // yet — hand the user the exact command instead of half-updating.
214
+ logger.log(`Update available: ${currentVersion} → ${latest} (standalone binary).`);
215
+ logger.log(`${updateInstruction({ channel: "sea" })}`);
216
+ return { ok: true, latest, manual: true };
217
+ }
218
+
219
+ logger.log(`Updating ${currentVersion} → ${latest}... (this can take a few minutes)`);
220
+ try {
221
+ if (ch === "sea") {
222
+ // Re-run the binary installer: download to a temp file, then execute —
223
+ // never pipe the network straight into a shell.
224
+ const res = await fetchFn(INSTALL_SH_URL);
225
+ if (!res.ok) throw new Error(`installer download failed (${res.status})`);
226
+ const tmpScript = path.join(os.tmpdir(), `kj-install-${process.pid}.sh`);
227
+ await fs.writeFile(tmpScript, await res.text(), { mode: 0o700 });
228
+ try {
229
+ await run("sh", [tmpScript]);
230
+ } finally {
231
+ await fs.rm(tmpScript, { force: true });
232
+ }
233
+ } else {
234
+ // No stdio:inherit — capture and drop npm's warnings on the success path.
235
+ await run("npm", ["install", "-g", `${packageName()}@latest`]);
236
+ }
237
+ } catch (err) {
238
+ if (err.stdout) logger.error(err.stdout);
239
+ if (err.stderr) logger.error(err.stderr);
240
+ logger.error(`Update failed: ${err.shortMessage || err.message}`);
241
+ return { ok: false };
242
+ }
243
+
244
+ // The install succeeded — but is the kj the USER runs actually the new one?
245
+ const onPath = await verifyKjOnPath({ run, latest, logger });
246
+ if (!onPath) return { ok: false };
247
+ logger.log(`Updated to ${latest}. Restart Claude to pick up the new MCP server.`);
248
+ return { ok: true, latest };
249
+ }
250
+
251
+ /**
252
+ * Probe `kj --version` through the PATH and confirm it reports `latest`.
253
+ * A mismatch means a stale copy shadows the freshly installed one (e.g. a
254
+ * standalone binary in ~/.local/bin in front of the npm global prefix).
255
+ */
256
+ async function verifyKjOnPath({ run, latest, logger }) {
257
+ let reported;
258
+ try {
259
+ const { stdout } = await run("kj", ["--version"]);
260
+ reported = String(stdout).trim();
261
+ } catch (err) {
262
+ logger.error(`Update installed ${latest}, but running \`kj --version\` failed: ${err.shortMessage || err.message}`);
263
+ return false;
264
+ }
265
+ if (reported.includes(latest)) return true;
266
+ logger.error(`Update installed ${latest}, but the \`kj\` on your PATH still reports ${reported}.`);
267
+ logger.error("A stale copy is shadowing the update. Check `which -a kj` and remove the old one, or update through the channel that owns the first entry.");
268
+ return false;
269
+ }
270
+
271
+ /** Simple semver compare: returns >0 if a > b, <0 if a < b, 0 if equal */
272
+ function compareVersions(a, b) {
273
+ const pa = a.split(".").map(Number);
274
+ const pb = b.split(".").map(Number);
275
+ for (let i = 0; i < 3; i++) {
276
+ if ((pa[i] || 0) > (pb[i] || 0)) return 1;
277
+ if ((pa[i] || 0) < (pb[i] || 0)) return -1;
278
+ }
279
+ return 0;
280
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * RAG vector-store orphan collector — KJC-TSK-0499 PR2.
3
+ *
4
+ * Enumerates distinct `project_slug` rows in `~/.karajan/rag.db`,
5
+ * augments each with chunk count + last_indexed_{at,commit}, and
6
+ * marks as orphan the slugs whose basename does not resolve to a
7
+ * directory in any of the configured `projectRoots`.
8
+ *
9
+ * Read-only. Returns rows + a copy-paste sqlite3 command per orphan.
10
+ * Deliberate inverse of the RAG indexer: never opens the DB for write.
11
+ */
12
+ import fs from "node:fs/promises";
13
+ import path from "node:path";
14
+ import os from "node:os";
15
+ import { dbPath, openVecStore, projectSlug } from "../rag/vec-store.js";
16
+
17
+ const DEFAULT_ROOTS = [
18
+ path.join(os.homedir(), "ws_npm-packages"),
19
+ path.join(os.homedir(), "ws_firebase"),
20
+ path.join(os.homedir(), "projects"),
21
+ path.join(os.homedir(), "code"),
22
+ ];
23
+
24
+ async function listDirs(root) {
25
+ try {
26
+ const entries = await fs.readdir(root, { withFileTypes: true });
27
+ return entries.filter((e) => e.isDirectory()).map((e) => path.join(root, e.name));
28
+ } catch {
29
+ return [];
30
+ }
31
+ }
32
+
33
+ async function buildSlugIndex(roots) {
34
+ const index = new Map();
35
+ for (const root of roots) {
36
+ for (const dir of await listDirs(root)) {
37
+ const slug = projectSlug(dir);
38
+ if (slug && !index.has(slug)) index.set(slug, dir);
39
+ }
40
+ }
41
+ return index;
42
+ }
43
+
44
+ function purgeCommand(slug) {
45
+ const slugSafe = slug.replace(/'/g, "''");
46
+ return `sqlite3 ${dbPath()} "DELETE FROM chunks WHERE project_slug='${slugSafe}'; DELETE FROM vec_store_meta WHERE project_slug='${slugSafe}';"`;
47
+ }
48
+
49
+ /**
50
+ * Collect RAG vector-store orphans.
51
+ * @param {object} [opts]
52
+ * @param {string[]} [opts.projectRoots] — directories to look for live
53
+ * projects whose basename matches each slug. Defaults to the usual
54
+ * `~/ws_*`, `~/projects`, `~/code` set.
55
+ * @returns {Promise<{rows: Array, orphans: Array, errors: Array}>}
56
+ */
57
+ export async function collectVectorStoreOrphans({ projectRoots = DEFAULT_ROOTS } = {}) {
58
+ const rows = [];
59
+ const errors = [];
60
+ let db;
61
+ try { db = openVecStore(); } catch (e) {
62
+ return { rows, orphans: [], errors: [{ stage: "open", error: String(e?.message ?? e) }] };
63
+ }
64
+ try {
65
+ const stats = db.prepare(`
66
+ SELECT COALESCE(c.project_slug, '<null>') AS slug,
67
+ COUNT(c.id) AS chunkCount,
68
+ COALESCE(m.last_indexed_commit, '') AS lastCommit,
69
+ COALESCE(m.last_indexed_at, '') AS lastAt
70
+ FROM chunks c
71
+ LEFT JOIN vec_store_meta m ON m.project_slug = c.project_slug
72
+ GROUP BY c.project_slug
73
+ ORDER BY chunkCount DESC
74
+ `).all();
75
+ const slugIndex = await buildSlugIndex(projectRoots);
76
+ for (const r of stats) {
77
+ const resolved = slugIndex.get(r.slug) || null;
78
+ rows.push({ ...r, resolvedDir: resolved, orphan: !resolved && r.slug !== "<null>" });
79
+ }
80
+ } catch (e) {
81
+ errors.push({ stage: "query", error: String(e?.message ?? e) });
82
+ } finally {
83
+ try { db.close(); } catch { /* close errors are non-fatal */ }
84
+ }
85
+ const orphans = rows
86
+ .filter((r) => r.orphan)
87
+ .map((r) => ({ ...r, command: purgeCommand(r.slug) }));
88
+ return { rows, orphans, errors };
89
+ }
@@ -0,0 +1,47 @@
1
+ import { printBanner } from "./banner.js";
2
+
3
+ const A = {
4
+ reset: "\x1b[0m",
5
+ bold: "\x1b[1m",
6
+ dim: "\x1b[2m",
7
+ cyan: "\x1b[36m",
8
+ green: "\x1b[32m",
9
+ yellow: "\x1b[33m",
10
+ };
11
+
12
+ const QUICK_START = [
13
+ ["kj run <task>", "Run the full coder+reviewer pipeline"],
14
+ ["kj init", "Initialize config and setup"],
15
+ ["kj doctor", "Check environment and agent availability"],
16
+ ["kj status", "Show pipeline dashboard"],
17
+ ["kj report", "Show latest session report"],
18
+ ];
19
+
20
+ /**
21
+ * Print the CLI welcome screen.
22
+ * @param {object} opts
23
+ * @param {string} opts.version - Version string (required)
24
+ * @param {object} [opts.config] - Loaded KJ config (optional, shows configured agents)
25
+ */
26
+ export function printWelcomeScreen({ version, config = null }) {
27
+ printBanner(version, { force: true });
28
+
29
+ if (config) {
30
+ const coder = config.roles?.coder?.provider || config.coder || "claude";
31
+ const reviewer = config.roles?.reviewer?.provider || config.reviewer || "codex";
32
+ console.log(` ${A.bold}Agents${A.reset}`);
33
+ console.log(` ${A.dim}coder:${A.reset} ${coder}`);
34
+ console.log(` ${A.dim}reviewer:${A.reset} ${reviewer}`);
35
+ console.log();
36
+ }
37
+
38
+ console.log(` ${A.bold}Quick start${A.reset}`);
39
+ for (const [cmd, desc] of QUICK_START) {
40
+ const padded = cmd.padEnd(20);
41
+ console.log(` ${A.green}${padded}${A.reset} ${A.dim}${desc}${A.reset}`);
42
+ }
43
+
44
+ console.log();
45
+ console.log(` ${A.dim}Run ${A.reset}kj --help${A.dim} to see all commands.${A.reset}`);
46
+ console.log();
47
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Timeout wrapper for arbitrary promises.
3
+ *
4
+ * Produces a new Promise that resolves with the original value if the
5
+ * underlying promise settles within `ms`, or rejects with a TimeoutError if
6
+ * it doesn't. Intended for wrapping individual checks in the doctor/preflight
7
+ * runner so a slow HTTP probe cannot hang the whole pipeline.
8
+ *
9
+ * The original promise keeps running after timeout (we cannot cancel it
10
+ * without cooperation). Callers should avoid calling `withTimeout` on
11
+ * side-effectful operations they need to be sure completed.
12
+ */
13
+
14
+ export class TimeoutError extends Error {
15
+ constructor(label, ms) {
16
+ super(`Timeout after ${ms}ms${label ? ` (${label})` : ""}`);
17
+ this.name = "TimeoutError";
18
+ this.timeoutMs = ms;
19
+ this.label = label;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * @template T
25
+ * @param {Promise<T>} promise
26
+ * @param {number} ms
27
+ * @param {string} [label] - for error messages / logs
28
+ * @returns {Promise<T>}
29
+ */
30
+ export function withTimeout(promise, ms, label) {
31
+ if (!Number.isFinite(ms) || ms <= 0) return promise;
32
+
33
+ let timerId;
34
+ const timeout = new Promise((_resolve, reject) => {
35
+ timerId = setTimeout(() => reject(new TimeoutError(label, ms)), ms);
36
+ if (timerId && typeof timerId.unref === "function") timerId.unref();
37
+ });
38
+
39
+ return Promise.race([promise, timeout]).finally(() => {
40
+ if (timerId) clearTimeout(timerId);
41
+ });
42
+ }
@@ -0,0 +1,47 @@
1
+ import readline from "node:readline";
2
+
3
+ export function createWizard(inputStream = process.stdin, output = process.stdout) {
4
+ const rl = readline.createInterface({ input: inputStream, output, terminal: false });
5
+
6
+ function ask(question) {
7
+ return new Promise((resolve) => {
8
+ rl.question(question, (answer) => resolve(answer.trim()));
9
+ });
10
+ }
11
+
12
+ async function confirm(question, defaultValue = true) {
13
+ const hint = defaultValue ? "[Y/n]" : "[y/N]";
14
+ const answer = await ask(`${question} ${hint} `);
15
+ if (answer === "") return defaultValue;
16
+ return /^y(es)?$/i.test(answer);
17
+ }
18
+
19
+ async function input(question, defaultValue = "") {
20
+ const hint = defaultValue !== "" ? ` [${defaultValue}]` : "";
21
+ const answer = await ask(`${question}${hint} `);
22
+ return answer === "" ? defaultValue : answer;
23
+ }
24
+
25
+ async function select(question, options) {
26
+ output.write(`${question}\n`);
27
+ for (let i = 0; i < options.length; i++) {
28
+ const opt = options[i];
29
+ const label = opt.available === false ? `${opt.label} (not installed)` : opt.label;
30
+ output.write(` ${i + 1}) ${label}\n`);
31
+ }
32
+ const answer = await ask(`Choose [1-${options.length}]: `);
33
+ const idx = Number(answer) - 1;
34
+ if (idx >= 0 && idx < options.length) return options[idx].value;
35
+ return options[0].value;
36
+ }
37
+
38
+ function close() {
39
+ rl.close();
40
+ }
41
+
42
+ return { ask, confirm, input, select, close };
43
+ }
44
+
45
+ export function isTTY() {
46
+ return Boolean(process.stdin.isTTY);
47
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Core Web Vitals quality gate.
3
+ *
4
+ * Evaluates LCP, CLS and INP against Google's recommended thresholds
5
+ * and returns a structured verdict usable by the pipeline.
6
+ */
7
+
8
+ export const CWV_THRESHOLDS = {
9
+ lcp: { good: 2500, poor: 4000 },
10
+ cls: { good: 0.1, poor: 0.25 },
11
+ inp: { good: 200, poor: 500 }
12
+ };
13
+
14
+ /**
15
+ * Deep-merge custom thresholds on top of the defaults.
16
+ * Only overrides metrics/boundaries that the caller provides.
17
+ *
18
+ * @param {object} defaults - Base thresholds (e.g. CWV_THRESHOLDS)
19
+ * @param {object} [custom] - Partial overrides
20
+ * @returns {object} Merged thresholds
21
+ */
22
+ export function mergeThresholds(defaults, custom) {
23
+ if (!custom || typeof custom !== "object") return { ...defaults };
24
+
25
+ const merged = {};
26
+ for (const metric of Object.keys(defaults)) {
27
+ const base = defaults[metric];
28
+ const over = custom[metric];
29
+ if (over && typeof over === "object") {
30
+ merged[metric] = {
31
+ good: over.good !== undefined ? over.good : base.good,
32
+ poor: over.poor !== undefined ? over.poor : base.poor
33
+ };
34
+ } else {
35
+ merged[metric] = { ...base };
36
+ }
37
+ }
38
+
39
+ // Include any extra metrics the caller added that are not in defaults
40
+ for (const metric of Object.keys(custom)) {
41
+ if (!merged[metric] && typeof custom[metric] === "object") {
42
+ merged[metric] = { ...custom[metric] };
43
+ }
44
+ }
45
+
46
+ return merged;
47
+ }
48
+
49
+ function rateMetric(value, good, poor) {
50
+ if (value <= good) return "good";
51
+ if (value >= poor) return "poor";
52
+ return "needs-improvement";
53
+ }
54
+
55
+ /**
56
+ * Evaluate Core Web Vitals metrics against thresholds.
57
+ *
58
+ * @param {{ lcp?: number, cls?: number, inp?: number }} metrics
59
+ * @param {object} [customThresholds] - Optional per-metric overrides
60
+ * @returns {{
61
+ * pass: boolean,
62
+ * scores: Record<string, { value: number, rating: string }>,
63
+ * blocking: Array<{ metric: string, value: number, threshold: number, rating: string }>,
64
+ * advisory: Array<{ metric: string, value: number, threshold: number, rating: string }>
65
+ * }}
66
+ */
67
+ export function evaluateCwv(metrics, customThresholds) {
68
+ const thresholds = mergeThresholds(CWV_THRESHOLDS, customThresholds);
69
+
70
+ const scores = {};
71
+ const blocking = [];
72
+ const advisory = [];
73
+
74
+ for (const [metric, bounds] of Object.entries(thresholds)) {
75
+ const value = metrics[metric];
76
+ if (value === undefined || value === null) continue;
77
+
78
+ const rating = rateMetric(value, bounds.good, bounds.poor);
79
+ scores[metric] = { value, rating };
80
+
81
+ if (rating === "poor") {
82
+ blocking.push({ metric, value, threshold: bounds.poor, rating });
83
+ } else if (rating === "needs-improvement") {
84
+ advisory.push({ metric, value, threshold: bounds.good, rating });
85
+ }
86
+ }
87
+
88
+ return {
89
+ pass: blocking.length === 0,
90
+ scores,
91
+ blocking,
92
+ advisory
93
+ };
94
+ }