@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,167 @@
1
+ /**
2
+ * Semantic skill detection using the triage classifier.
3
+ *
4
+ * The regex-based detector (skill-detector.js) is fast but shallow: it only
5
+ * catches dependencies that name themselves explicitly. A task like
6
+ * "add a feature flag system" might benefit from an "a/b-testing" skill
7
+ * that regex cannot guess without an exhaustive keyword list.
8
+ *
9
+ * Semantic mode asks the classifier agent to pick skills from a known
10
+ * catalog given the task text and the skills already detected by regex.
11
+ * The catalog is intentionally small and curated — we don't hit the
12
+ * openskills.cc marketplace API (not available). If the classifier is
13
+ * unavailable (missing provider / missing API key), we return [] and the
14
+ * pipeline keeps working with the regex-only result.
15
+ */
16
+
17
+ import { createAgent } from "../agents/index.js";
18
+ import { resolveRole } from "../config.js";
19
+ import { withBrainRecovery } from "../brain/with-brain-recovery.js";
20
+
21
+ /**
22
+ * Curated catalog of skills the classifier is allowed to suggest. Keeping
23
+ * this small prevents the model from hallucinating non-existent skills and
24
+ * bounds the tokens spent on the prompt.
25
+ */
26
+ export const SEMANTIC_CATALOG = [
27
+ "astro", "nextjs", "react", "vue", "svelte", "angular",
28
+ "express", "fastify", "nestjs",
29
+ "java", "kotlin", "go", "rust", "ruby", "php", "dotnet", "elixir",
30
+ "python", "python-data", "python-ml", "pytest-patterns",
31
+ "django", "flask", "fastapi",
32
+ "sql-analysis", "prisma", "mongodb",
33
+ "owasp-top-10", "security-checklist",
34
+ "java-code-review", "python-code-review",
35
+ "frontend-design", "csv-transform", "data-report",
36
+ "vitest-patterns", "jest-patterns", "playwright-patterns", "cypress-patterns",
37
+ ];
38
+
39
+ const PROMPT = (task, catalog, alreadyDetected) => `You are a classifier that picks which domain skills would help solve a task.
40
+
41
+ Task:
42
+ """${task}"""
43
+
44
+ Already detected skills (do NOT repeat, but consider the task context they imply):
45
+ ${alreadyDetected.length > 0 ? alreadyDetected.join(", ") : "(none)"}
46
+
47
+ From this exact catalog, output a JSON array with the names of 0 to 5 additional skills that would meaningfully help. Output ONLY the JSON array, no prose.
48
+
49
+ Catalog (pick strict matches only):
50
+ ${catalog.join(", ")}
51
+
52
+ Rules:
53
+ - Only names from the catalog. Do NOT invent.
54
+ - Prefer precision over recall: empty array is a valid answer when nothing fits.
55
+ - Do NOT include already-detected skills.
56
+ - Respond with a single JSON array, e.g. ["python-data","sql-analysis"]
57
+ `;
58
+
59
+ function tryParseArray(raw) {
60
+ if (!raw) return [];
61
+ try {
62
+ const m = String(raw).match(/\[[^\]]*\]/);
63
+ if (!m) return [];
64
+ const parsed = JSON.parse(m[0]);
65
+ if (!Array.isArray(parsed)) return [];
66
+ return parsed.filter((s) => typeof s === "string");
67
+ } catch {
68
+ return [];
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Ask the classifier for additional skills.
74
+ *
75
+ * @param {Object} args
76
+ * @param {string} args.task
77
+ * @param {string[]} args.alreadyDetected
78
+ * @param {Object} args.config - Karajan config
79
+ * @param {Object} [args.logger]
80
+ * @returns {Promise<string[]>}
81
+ */
82
+ export async function refineSkillsSemantically({ task, alreadyDetected = [], config, logger }) {
83
+ if (!task || typeof task !== "string") return [];
84
+ let provider;
85
+ try {
86
+ provider = resolveRole(config, "triage")?.provider
87
+ || resolveRole(config, "planner")?.provider
88
+ || resolveRole(config, "coder")?.provider;
89
+ } catch {
90
+ provider = null;
91
+ }
92
+ if (!provider) {
93
+ logger?.debug?.("semantic-detector: no classifier provider — skipping");
94
+ return [];
95
+ }
96
+
97
+ let agent;
98
+ try {
99
+ agent = createAgent(provider, config, logger);
100
+ } catch (err) {
101
+ logger?.debug?.(`semantic-detector: classifier unavailable (${err.message}) — skipping`);
102
+ return [];
103
+ }
104
+ if (!agent || typeof agent.runTask !== "function") {
105
+ logger?.debug?.("semantic-detector: classifier agent has no runTask() — skipping");
106
+ return [];
107
+ }
108
+
109
+ const prompt = PROMPT(task, SEMANTIC_CATALOG, alreadyDetected);
110
+ // KJC-TSK-0413 step D: wrap with Brain Recovery. semantic-detector usa
111
+ // signature legacy `runTask(prompt, opts)` — adapter normaliza al estándar
112
+ // `runTask({ prompt, timeoutMs })` que withBrainRecovery espera.
113
+ const adapter = {
114
+ provider: agent.provider,
115
+ runTask: (args) => agent.runTask(args.prompt, { timeoutMs: args.timeoutMs }),
116
+ };
117
+ let res;
118
+ try {
119
+ res = await withBrainRecovery({
120
+ agent: adapter,
121
+ taskArgs: { prompt, timeoutMs: 30_000 },
122
+ role: "semantic-detector",
123
+ logger,
124
+ });
125
+ } catch (err) {
126
+ logger?.warn?.(`semantic-detector: classifier call failed (${err.message}) — skipping`);
127
+ return [];
128
+ }
129
+ if (!res?.ok) {
130
+ // En test env el sleep es no-op así que abort viene rápido. Skip-on-fail
131
+ // sigue siendo el comportamiento — semantic detection es best-effort.
132
+ logger?.debug?.(`semantic-detector: classifier returned not-ok (${res?.recovery?.class || "unknown"}) — skipping`);
133
+ return [];
134
+ }
135
+
136
+ const suggested = tryParseArray(res.output || res.result?.raw || "");
137
+ const allowed = new Set(SEMANTIC_CATALOG);
138
+ const alreadySet = new Set(alreadyDetected.map((s) => s.toLowerCase()));
139
+ return suggested
140
+ .map((s) => String(s).trim())
141
+ .filter((s) => s && allowed.has(s) && !alreadySet.has(s.toLowerCase()))
142
+ .slice(0, 5);
143
+ }
144
+
145
+ /**
146
+ * Resolve the effective skills mode from config + flags.
147
+ * Precedence: flags.skillsMode > config.skills.mode > config.testHarness.defaultSkillsMode > "auto".
148
+ *
149
+ * The testHarness default lets the test harness opt out of semantic
150
+ * detection without each orchestrator test having to mock this module.
151
+ * Production code reads `config.testHarness.defaultSkillsMode` only;
152
+ * the legacy global override is documented and exclusively read in
153
+ * src/config/test-harness.js (ESLint rule #557 blocks any reintroduction
154
+ * of `globalThis.__KJ_*` outside that one file). Legacy callers without
155
+ * a fully-loaded config still work because `config.testHarness` is
156
+ * undefined → falls through to `"auto"`.
157
+ *
158
+ * @param {Object} config
159
+ * @param {Object} [flags]
160
+ * @returns {"auto"|"regex"|"semantic"|"none"}
161
+ */
162
+ export function resolveSkillsMode(config, flags = {}) {
163
+ const defaultMode = config?.testHarness?.defaultSkillsMode || "auto";
164
+ const candidate = flags.skillsMode ?? config?.skills?.mode ?? defaultMode;
165
+ const valid = new Set(["auto", "regex", "semantic", "none"]);
166
+ return valid.has(candidate) ? candidate : "auto";
167
+ }
@@ -0,0 +1,385 @@
1
+ /**
2
+ * Detects needed skills from task description and project files,
3
+ * then auto-installs them via OpenSkills if available.
4
+ */
5
+
6
+ import fs from "node:fs/promises";
7
+ import path from "node:path";
8
+ import { loadAvailableSkills } from "./skill-loader.js";
9
+ import { isOpenSkillsAvailable, installSkill, removeSkill } from "./openskills-client.js";
10
+ import { isFresh as isCacheFresh, recordInstall as recordSkillInstall } from "./skills-cache.js";
11
+
12
+ /**
13
+ * Known frameworks detectable from package.json dependencies.
14
+ * Maps dependency name to the skill name to search for.
15
+ */
16
+ const PKG_JSON_FRAMEWORKS = {
17
+ astro: "astro",
18
+ next: "nextjs",
19
+ react: "react",
20
+ "react-dom": "react",
21
+ vue: "vue",
22
+ svelte: "svelte",
23
+ "@angular/core": "angular",
24
+ express: "express",
25
+ fastify: "fastify",
26
+ "@nestjs/core": "nestjs",
27
+ // DB / ORM
28
+ prisma: "prisma",
29
+ "@prisma/client": "prisma",
30
+ knex: "sql-analysis",
31
+ sequelize: "sql-analysis",
32
+ typeorm: "sql-analysis",
33
+ mongoose: "mongodb",
34
+ "better-sqlite3": "sql-analysis",
35
+ // Testing
36
+ vitest: "vitest-patterns",
37
+ jest: "jest-patterns",
38
+ "@playwright/test": "playwright-patterns",
39
+ cypress: "cypress-patterns",
40
+ };
41
+
42
+ /**
43
+ * Python dependency names (from requirements.txt or pyproject.toml) mapping
44
+ * to their canonical skill.
45
+ */
46
+ const PYTHON_DEPS = {
47
+ pandas: "python-data",
48
+ numpy: "python-data",
49
+ scipy: "python-data",
50
+ "scikit-learn": "python-ml",
51
+ sklearn: "python-ml",
52
+ tensorflow: "python-ml",
53
+ torch: "python-ml",
54
+ pytorch: "python-ml",
55
+ pytest: "pytest-patterns",
56
+ django: "python-django",
57
+ flask: "python-flask",
58
+ fastapi: "python-fastapi",
59
+ sqlalchemy: "sql-analysis",
60
+ };
61
+
62
+ /**
63
+ * Language markers: file presence maps to a skill name.
64
+ * Reuses the same concept as src/utils/project-detect.js LANGUAGE_MARKERS.
65
+ */
66
+ const LANGUAGE_FILE_MARKERS = [
67
+ { file: "pom.xml", skill: "java" },
68
+ { file: "build.gradle", skill: "java" },
69
+ { file: "build.gradle.kts", skill: "kotlin" },
70
+ { file: "go.mod", skill: "go" },
71
+ { file: "Cargo.toml", skill: "rust" },
72
+ { file: "pyproject.toml", skill: "python" },
73
+ { file: "requirements.txt", skill: "python" },
74
+ { file: "setup.py", skill: "python" },
75
+ { file: "Gemfile", skill: "ruby" },
76
+ { file: "pubspec.yaml", skill: "flutter" },
77
+ { file: "Package.swift", skill: "swift" },
78
+ { file: "phpunit.xml", skill: "php" },
79
+ { file: "composer.json", skill: "php" },
80
+ { file: "mix.exs", skill: "elixir" },
81
+ { file: "rebar.config", skill: "erlang" },
82
+ ];
83
+
84
+ /**
85
+ * File EXTENSIONS whose presence anywhere under projectDir adds a skill.
86
+ * Uses a shallow-recursive glob with a cutoff to avoid walking node_modules.
87
+ */
88
+ const EXTENSION_MARKERS = [
89
+ { ext: ".csproj", skill: "dotnet" },
90
+ { ext: ".sln", skill: "dotnet" },
91
+ { ext: ".ipynb", skill: "python-data" },
92
+ { ext: ".prisma", skill: "prisma" },
93
+ ];
94
+
95
+ /**
96
+ * Files detected as "SQL / database schema" when they exist at repo root.
97
+ * Used in addition to EXTENSION_MARKERS for *.sql anywhere in the repo.
98
+ */
99
+ const SQL_MARKER_FILES = [
100
+ "schema.sql",
101
+ "schema.prisma",
102
+ "migrations",
103
+ "db/migrate",
104
+ ];
105
+
106
+ const DIRECTORIES_TO_SKIP = new Set([
107
+ "node_modules", ".git", ".kj", ".karajan", "dist", "build", ".next", "out",
108
+ "target", ".venv", "venv", "__pycache__", ".vitest-cache", "coverage",
109
+ ]);
110
+
111
+ /**
112
+ * Patterns to detect framework/skill mentions in the task text.
113
+ * Each entry: regex pattern (case-insensitive) -> skill name.
114
+ */
115
+ const TASK_TEXT_PATTERNS = [
116
+ { pattern: /\bastro\b/i, skill: "astro" },
117
+ { pattern: /\bnext\.?js\b/i, skill: "nextjs" },
118
+ { pattern: /\breact\b/i, skill: "react" },
119
+ { pattern: /\bvue\b/i, skill: "vue" },
120
+ { pattern: /\bsvelte\b/i, skill: "svelte" },
121
+ { pattern: /\bangular\b/i, skill: "angular" },
122
+ { pattern: /\bexpress\b/i, skill: "express" },
123
+ { pattern: /\bfastify\b/i, skill: "fastify" },
124
+ { pattern: /\bnest\.?js\b/i, skill: "nestjs" },
125
+ { pattern: /\bjava\b/i, skill: "java" },
126
+ { pattern: /\bkotlin\b/i, skill: "kotlin" },
127
+ { pattern: /\bgo(?:lang)?\b/i, skill: "go" },
128
+ { pattern: /\brust\b/i, skill: "rust" },
129
+ { pattern: /\bpython\b/i, skill: "python" },
130
+ { pattern: /\bdjango\b/i, skill: "python" },
131
+ { pattern: /\bflask\b/i, skill: "python" },
132
+ { pattern: /\bruby\b/i, skill: "ruby" },
133
+ { pattern: /\bflutter\b/i, skill: "flutter" },
134
+ { pattern: /\bswift\b/i, skill: "swift" },
135
+ { pattern: /\bphp\b/i, skill: "php" },
136
+ { pattern: /\bSQL\b/i, skill: "sql-analysis" },
137
+ { pattern: /\bquer(?:y|ies)\b/i, skill: "sql-analysis" },
138
+ { pattern: /\bdatabase\b/i, skill: "sql-analysis" },
139
+ { pattern: /\bCSV\b/i, skill: "csv-transform" },
140
+ { pattern: /\btransform\b/i, skill: "csv-transform" },
141
+ { pattern: /\bparse\b/i, skill: "csv-transform" },
142
+ { pattern: /\breport\b/i, skill: "data-report" },
143
+ { pattern: /\banalysis\b/i, skill: "data-report" },
144
+ { pattern: /\bfindings\b/i, skill: "data-report" },
145
+ // Frontend/backend broad categories
146
+ { pattern: /\bfrontend\b/i, skill: "frontend-design" },
147
+ { pattern: /\bCSS\b/i, skill: "frontend-design" },
148
+ { pattern: /\bHTML\b/i, skill: "frontend-design" },
149
+ { pattern: /\bbackend\b/i, skill: "express" },
150
+ { pattern: /\bnode\.?js\b/i, skill: "express" },
151
+ { pattern: /\bAPI\b/, skill: "express" },
152
+ { pattern: /\bwebsocket\b/i, skill: "express" },
153
+ { pattern: /\breal[- ]time\b/i, skill: "express" },
154
+ ];
155
+
156
+ /**
157
+ * Analyze the task and project to determine what skills might be needed.
158
+ *
159
+ * @param {string} task - The task description text.
160
+ * @param {string} projectDir - Absolute path to project root.
161
+ * @param {{ includeExtensions?: boolean, maxDepth?: number }} [options]
162
+ * - includeExtensions: scan for file extensions (.csproj, .ipynb, .sql...)
163
+ * that signal a stack. Default true. Disable to avoid the shallow walk
164
+ * in very large repos or in tests.
165
+ * - maxDepth: bound the walk (default 3 directories deep).
166
+ * @returns {Promise<string[]>} Array of unique skill names to search for.
167
+ */
168
+ export async function detectNeededSkills(task, projectDir, options = {}) {
169
+ const { includeExtensions = true, maxDepth = 3 } = options;
170
+ const needed = new Set();
171
+
172
+ // 1. Scan package.json for known frameworks and JS-ecosystem deps
173
+ if (projectDir) {
174
+ try {
175
+ const pkgRaw = await fs.readFile(path.join(projectDir, "package.json"), "utf8");
176
+ const pkg = JSON.parse(pkgRaw);
177
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
178
+ for (const [dep, skill] of Object.entries(PKG_JSON_FRAMEWORKS)) {
179
+ if (allDeps[dep]) {
180
+ needed.add(skill);
181
+ }
182
+ }
183
+ } catch { /* no package.json or parse error — skip */ }
184
+
185
+ // 2. Language marker files at repo root
186
+ for (const marker of LANGUAGE_FILE_MARKERS) {
187
+ try {
188
+ await fs.access(path.join(projectDir, marker.file));
189
+ needed.add(marker.skill);
190
+ } catch { /* file not found — skip */ }
191
+ }
192
+
193
+ // 3. Python deps from requirements.txt / pyproject.toml
194
+ await collectPythonDeps(projectDir, needed);
195
+
196
+ // 4. File extension markers (.csproj, .ipynb, .prisma, *.sql)
197
+ if (includeExtensions) {
198
+ await collectExtensionMarkers(projectDir, maxDepth, needed);
199
+ }
200
+
201
+ // 5. SQL / DB schema markers at well-known paths
202
+ for (const candidate of SQL_MARKER_FILES) {
203
+ try {
204
+ await fs.access(path.join(projectDir, candidate));
205
+ needed.add("sql-analysis");
206
+ } catch { /* skip */ }
207
+ }
208
+ }
209
+
210
+ // 6. Task text patterns
211
+ if (task) {
212
+ for (const { pattern, skill } of TASK_TEXT_PATTERNS) {
213
+ if (pattern.test(task)) {
214
+ needed.add(skill);
215
+ }
216
+ }
217
+ }
218
+
219
+ return Array.from(needed);
220
+ }
221
+
222
+ async function collectPythonDeps(projectDir, needed) {
223
+ // requirements.txt — each non-comment line is "name==ver" or "name>=ver"
224
+ try {
225
+ const raw = await fs.readFile(path.join(projectDir, "requirements.txt"), "utf8");
226
+ for (const line of raw.split("\n")) {
227
+ const trimmed = line.trim().split("#")[0].trim();
228
+ if (!trimmed) continue;
229
+ const name = trimmed.split(/[<>=!~[\s]/)[0].toLowerCase();
230
+ const skill = PYTHON_DEPS[name];
231
+ if (skill) needed.add(skill);
232
+ }
233
+ } catch { /* no requirements.txt */ }
234
+
235
+ // pyproject.toml — simple heuristic scan for dependency names. A full TOML
236
+ // parse would need a dep; we just look for quoted names, which is fine.
237
+ try {
238
+ const raw = await fs.readFile(path.join(projectDir, "pyproject.toml"), "utf8");
239
+ const lower = raw.toLowerCase();
240
+ for (const [name, skill] of Object.entries(PYTHON_DEPS)) {
241
+ if (lower.includes(`"${name}"`) || lower.includes(`'${name}'`)) {
242
+ needed.add(skill);
243
+ }
244
+ }
245
+ } catch { /* no pyproject.toml */ }
246
+ }
247
+
248
+ async function collectExtensionMarkers(projectDir, maxDepth, needed) {
249
+ // Build a lookup by extension for fast decisions.
250
+ const byExt = new Map(EXTENSION_MARKERS.map((m) => [m.ext, m.skill]));
251
+ const extensions = new Set(byExt.keys());
252
+ extensions.add(".sql");
253
+ let sqlFound = false;
254
+
255
+ async function walk(dir, depth) {
256
+ if (depth > maxDepth) return;
257
+ let entries;
258
+ try {
259
+ entries = await fs.readdir(dir, { withFileTypes: true });
260
+ } catch {
261
+ return;
262
+ }
263
+ for (const entry of entries) {
264
+ if (entry.isDirectory()) {
265
+ if (DIRECTORIES_TO_SKIP.has(entry.name)) continue;
266
+ if (entry.name.startsWith(".")) continue;
267
+ await walk(path.join(dir, entry.name), depth + 1);
268
+ continue;
269
+ }
270
+ if (!entry.isFile()) continue;
271
+ const ext = path.extname(entry.name).toLowerCase();
272
+ if (!extensions.has(ext)) continue;
273
+ if (ext === ".sql") {
274
+ sqlFound = true;
275
+ continue;
276
+ }
277
+ const skill = byExt.get(ext);
278
+ if (skill) needed.add(skill);
279
+ }
280
+ }
281
+
282
+ await walk(projectDir, 0);
283
+ if (sqlFound) needed.add("sql-analysis");
284
+ }
285
+
286
+ /**
287
+ * Auto-install needed skills that are not yet installed.
288
+ *
289
+ * When the `openskills` CLI is not available, this function degrades
290
+ * gracefully: it returns `osAvailable: false` and `wouldHaveUsed` with the
291
+ * list of skills that would have been installed if the CLI had been present.
292
+ * Callers (e.g. the orchestrator) can surface this info in the session
293
+ * report without blocking execution.
294
+ *
295
+ * @param {string[]} neededSkills - Skill names to ensure are installed.
296
+ * @param {string} projectDir - Absolute path to project root.
297
+ * @returns {Promise<{
298
+ * installed: string[],
299
+ * failed: string[],
300
+ * alreadyInstalled: string[],
301
+ * wouldHaveUsed: string[],
302
+ * osAvailable: boolean
303
+ * }>}
304
+ */
305
+ export async function autoInstallSkills(neededSkills, projectDir) {
306
+ const result = { installed: [], failed: [], alreadyInstalled: [], wouldHaveUsed: [], osAvailable: true };
307
+
308
+ if (!neededSkills || neededSkills.length === 0) {
309
+ return result;
310
+ }
311
+
312
+ // Check which skills are already installed locally
313
+ const existingSkills = await loadAvailableSkills(projectDir);
314
+ const existingNames = new Set(existingSkills.map(s => s.name.toLowerCase()));
315
+
316
+ // Check if OpenSkills is available
317
+ const osAvailable = await isOpenSkillsAvailable();
318
+ if (!osAvailable) {
319
+ result.osAvailable = false;
320
+ // Report what we would have installed so the session report can surface
321
+ // the recommendation — "install openskills globally to enable: X, Y, Z".
322
+ result.wouldHaveUsed = neededSkills.filter((s) => !existingNames.has(s.toLowerCase()));
323
+ return result;
324
+ }
325
+
326
+ for (const skillName of neededSkills) {
327
+ if (existingNames.has(skillName.toLowerCase())) {
328
+ result.alreadyInstalled.push(skillName);
329
+ continue;
330
+ }
331
+
332
+ // Cache short-circuit: if we installed this skill in the last 7 days,
333
+ // assume it's still good and skip the `npx openskills install` call
334
+ // (which can take 10-30s). Running sessions can opt out by clearing
335
+ // the cache with `kj skills clear-cache`.
336
+ if (await isCacheFresh(skillName)) {
337
+ result.alreadyInstalled.push(skillName);
338
+ continue;
339
+ }
340
+
341
+ try {
342
+ const installResult = await installSkill(skillName, { projectDir });
343
+ if (installResult.ok) {
344
+ const installedName = installResult.name || skillName;
345
+ result.installed.push(installedName);
346
+ await recordSkillInstall(installedName, { source: skillName }).catch(() => {});
347
+ } else {
348
+ result.failed.push(skillName);
349
+ }
350
+ } catch { /* skill install threw */
351
+ result.failed.push(skillName);
352
+ }
353
+ }
354
+
355
+ return result;
356
+ }
357
+
358
+ /**
359
+ * Remove skills that were auto-installed during this session.
360
+ * @param {string[]} skillNames - Skill names to remove.
361
+ * @param {string} projectDir - Absolute path to project root.
362
+ * @returns {Promise<{removed: string[], failed: string[]}>}
363
+ */
364
+ export async function cleanupAutoInstalledSkills(skillNames, projectDir) {
365
+ const result = { removed: [], failed: [] };
366
+
367
+ if (!skillNames || skillNames.length === 0) {
368
+ return result;
369
+ }
370
+
371
+ for (const name of skillNames) {
372
+ try {
373
+ const removeResult = await removeSkill(name, { projectDir });
374
+ if (removeResult.ok) {
375
+ result.removed.push(name);
376
+ } else {
377
+ result.failed.push(name);
378
+ }
379
+ } catch { /* skill removal threw */
380
+ result.failed.push(name);
381
+ }
382
+ }
383
+
384
+ return result;
385
+ }