@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,165 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { getKarajanHome } from "../utils/paths.js";
4
+ import { loadRoleInstructions } from "../prompts/prompt-resolver.js";
5
+
6
+ const ROLE_EVENTS = {
7
+ START: "role:start",
8
+ END: "role:end",
9
+ ERROR: "role:error"
10
+ };
11
+
12
+ /**
13
+ * Legacy flat resolver. Kept for back-compat with external callers and
14
+ * existing tests that assert the 3-entry candidate list. New code should use
15
+ * `loadRoleInstructions()` from src/prompts/prompt-resolver.js, which
16
+ * additionally tries per-provider and per-role subdirectories.
17
+ */
18
+ function resolveRoleMdPath(roleName, projectDir) {
19
+ const fileName = `${roleName}.md`;
20
+ const candidates = [];
21
+
22
+ if (projectDir) {
23
+ candidates.push(path.join(projectDir, ".karajan", "roles", fileName));
24
+ }
25
+
26
+ candidates.push(path.join(getKarajanHome(), "roles", fileName));
27
+
28
+ const builtIn = path.resolve(
29
+ path.dirname(new URL(import.meta.url).pathname),
30
+ "..",
31
+ "..",
32
+ "templates",
33
+ "roles",
34
+ fileName
35
+ );
36
+ candidates.push(builtIn);
37
+
38
+ return candidates;
39
+ }
40
+
41
+ async function loadFirstExisting(paths) {
42
+ for (const p of paths) {
43
+ try {
44
+ return await fs.readFile(p, "utf8");
45
+ } catch { /* file not found */
46
+ continue;
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+
52
+ /**
53
+ * Base class for every pipeline role (coder, reviewer, planner, refactorer,
54
+ * researcher, architect, triage, discover, tester, security, impeccable,
55
+ * hu-reviewer, audit, solomon, commiter, karajan-brain, domain-curator).
56
+ *
57
+ * Conceptual mapping for developers coming from other ecosystems:
58
+ * `BaseRole` (and every subclass) is Karajan's equivalent of a **Flow** in the
59
+ * Genkit sense — a named, composable unit of work with a prompt, an invocation
60
+ * and a parsed output. The important difference: a Karajan Role executes over
61
+ * a **subprocess CLI** (`claude`, `codex`, `gemini`, `aider`, `opencode`), not
62
+ * by calling an HTTP provider API. No PTY, no long-lived session — each run
63
+ * is a fresh subprocess with state on disk under `~/.karajan/sessions/`.
64
+ *
65
+ * See `docs/COMPARISON.md` for the full positioning.
66
+ *
67
+ * @alias Flow — similar to Genkit Flow but executed over subprocess CLIs, not API calls.
68
+ */
69
+ export class BaseRole {
70
+ constructor({ name, config, logger, emitter = null }) {
71
+ if (!name) throw new Error("Role name is required");
72
+ this.name = name;
73
+ this.config = config || {};
74
+ this.logger = logger;
75
+ this.emitter = emitter;
76
+ this.instructions = null;
77
+ this._initialized = false;
78
+ this._startTime = null;
79
+ this._output = null;
80
+ }
81
+
82
+ async init(context = {}) {
83
+ this.context = context;
84
+ const projectDir = this.config.projectDir || process.cwd();
85
+ // Subclasses (AgentRole) can override resolveProvider to expose the
86
+ // provider slug for the active role, which lets the prompt resolver
87
+ // pick a per-provider template variant when available.
88
+ const provider = typeof this.resolveProvider === "function"
89
+ ? this.resolveProvider()
90
+ : null;
91
+ const { instructions, path: templatePath, resolvedProvider, fellBack } = await loadRoleInstructions({
92
+ role: this.name,
93
+ provider,
94
+ projectDir,
95
+ logger: this.logger,
96
+ });
97
+ this.instructions = instructions;
98
+ this._templatePath = templatePath;
99
+ this._resolvedProvider = resolvedProvider;
100
+ this._promptFellBack = fellBack;
101
+ this._initialized = true;
102
+ }
103
+
104
+ async execute(_input) {
105
+ throw new Error(`${this.name}: execute() not implemented`);
106
+ }
107
+
108
+ report() {
109
+ return {
110
+ role: this.name,
111
+ ok: this._output?.ok ?? false,
112
+ result: this._output?.result ?? null,
113
+ summary: this._output?.summary ?? "",
114
+ timestamp: new Date().toISOString()
115
+ };
116
+ }
117
+
118
+ validate(output) {
119
+ if (!output) return { valid: false, reason: "Output is null or undefined" };
120
+ if (typeof output.ok !== "boolean") return { valid: false, reason: "Output.ok must be a boolean" };
121
+ return { valid: true, reason: "" };
122
+ }
123
+
124
+ async run(input) {
125
+ this._ensureInitialized();
126
+ this._startTime = Date.now();
127
+ this._emitEvent(ROLE_EVENTS.START, { input });
128
+
129
+ try {
130
+ const output = await this.execute(input);
131
+ this._output = output;
132
+
133
+ const validation = this.validate(output);
134
+ if (!validation.valid) {
135
+ throw new Error(`${this.name} output validation failed: ${validation.reason}`);
136
+ }
137
+
138
+ this._emitEvent(ROLE_EVENTS.END, { output: this.report() });
139
+ return output;
140
+ } catch (error) {
141
+ this._emitEvent(ROLE_EVENTS.ERROR, { error: error.message });
142
+ throw error;
143
+ }
144
+ }
145
+
146
+ _ensureInitialized() {
147
+ if (!this._initialized) {
148
+ throw new Error(`${this.name}: init() must be called before run()`);
149
+ }
150
+ }
151
+
152
+ _emitEvent(type, detail = {}) {
153
+ if (!this.emitter) return;
154
+ this.emitter.emit(type, {
155
+ role: this.name,
156
+ iteration: this.context?.iteration ?? 0,
157
+ sessionId: this.context?.sessionId ?? null,
158
+ elapsed: this._startTime ? Date.now() - this._startTime : 0,
159
+ timestamp: new Date().toISOString(),
160
+ ...detail
161
+ });
162
+ }
163
+ }
164
+
165
+ export { ROLE_EVENTS, resolveRoleMdPath, loadFirstExisting };
@@ -0,0 +1,107 @@
1
+ import { AgentRole } from "./agent-role.js";
2
+ import { buildCoderPromptLayout } from "../prompts/coder.js";
3
+ import { joinLayout } from "../prompts/prompt-layout.js";
4
+ import { isHostAgent } from "../utils/agent-detect.js";
5
+ import { HostAgent } from "../agents/host-agent.js";
6
+ import { detectProjectStack } from "../utils/stack-detect.js";
7
+ import { detectTestFramework } from "../utils/project-detect.js";
8
+
9
+ export class CoderRole extends AgentRole {
10
+ constructor(opts) {
11
+ super({ ...opts, name: "coder" });
12
+ this._askHost = opts.askHost || null;
13
+ }
14
+
15
+ resolveProvider() {
16
+ return this.config?.roles?.coder?.provider || this.config?.coder || "claude";
17
+ }
18
+
19
+ createAgentInstance(provider) {
20
+ // KJC-BUG-0129 (issues #1301/#1303): running INSIDE an agent does not
21
+ // make it "the host executor" — delegating sent the full instruction
22
+ // prompt through elicitInput as a hanging board "question". A CLI
23
+ // provider spawns as a subprocess ALWAYS; host delegation is explicit
24
+ // opt-in (roles.coder.host_delegation: true) for MCP-only setups.
25
+ if (this._askHost && isHostAgent(provider)) {
26
+ if (this.config?.roles?.coder?.host_delegation === true) {
27
+ this.logger.info(`Host-as-coder: delegating to host AI (roles.coder.host_delegation, skipping ${provider} subprocess)`);
28
+ return new HostAgent(this.config, this.logger, { askHost: this._askHost });
29
+ }
30
+ this.logger.info(`Running inside ${provider} — spawning it as a subprocess anyway (set roles.coder.host_delegation: true to delegate to the host)`);
31
+ }
32
+ return this._createAgent(provider, this.config, this.logger);
33
+ }
34
+
35
+ extractInput(input) {
36
+ if (typeof input === "string") {
37
+ return {
38
+ task: input,
39
+ reviewerFeedback: null, sonarSummary: null, deferredContext: null,
40
+ acceptanceTests: null,
41
+ adrs: null, specSection: null, reviewerFindings: null, huId: null,
42
+ projectDir: null,
43
+ onOutput: null
44
+ };
45
+ }
46
+ return {
47
+ task: input?.task || this.context?.task || "",
48
+ reviewerFeedback: input?.reviewerFeedback || null,
49
+ sonarSummary: input?.sonarSummary || null,
50
+ deferredContext: input?.deferredContext || null,
51
+ // Tests-first (v2.7.5): the coder reads these as the gate it
52
+ // must satisfy. Only the plan-backed HU path populates this;
53
+ // the standard single-task `kj run` flow leaves it null.
54
+ acceptanceTests: input?.acceptanceTests || null,
55
+ // PR F (v2.7.5): per-HU planning context. ADRs constrain HOW,
56
+ // specSection ties this HU to a SPEC heading, reviewerFindings
57
+ // are filtered to entries that mention this HU. All four are
58
+ // null for non-plan-backed runs, which keeps the legacy flow
59
+ // byte-for-byte identical.
60
+ adrs: Array.isArray(input?.adrs) ? input.adrs : null,
61
+ specSection: input?.specSection || null,
62
+ reviewerFindings: input?.reviewerFindings || null,
63
+ huId: input?.huId || null,
64
+ // PAR-E2 (KJC-TSK-0629): per-call project root. Worktree lanes pass
65
+ // their lane dir here; the shared role instance keeps its own config.
66
+ projectDir: input?.projectDir || null,
67
+ // PAR-H (KJC-TSK-0631): per-call subprocess env (lane slot vars).
68
+ env: input?.env || null,
69
+ onOutput: input?.onOutput || null
70
+ };
71
+ }
72
+
73
+ async buildPrompt({ task, reviewerFeedback, sonarSummary, deferredContext, acceptanceTests, adrs, specSection, reviewerFindings, huId, projectDir: laneProjectDir }) {
74
+ const projectDir = laneProjectDir || this.config?.projectDir || null;
75
+ // KJC sesgo-de-stack: pasar stack/testFramework al prompt para que
76
+ // el coder no asuma JS/vitest en proyectos Python / Go / Rust /
77
+ // Ruby. audit-role.js y tester-role.js ya lo hacen así.
78
+ let stack = null;
79
+ let testFramework = null;
80
+ if (projectDir) {
81
+ try { stack = await detectProjectStack(projectDir); } catch { /* best-effort */ }
82
+ try { testFramework = await detectTestFramework(projectDir); } catch { /* best-effort */ }
83
+ }
84
+ const layout = await buildCoderPromptLayout({
85
+ task, reviewerFeedback, sonarSummary, deferredContext, acceptanceTests,
86
+ adrs, specSection, reviewerFindings, huId,
87
+ coderRules: this.instructions,
88
+ methodology: this.config?.development?.methodology || "tdd",
89
+ serenaEnabled: Boolean(this.config?.serena?.enabled),
90
+ rtkAvailable: Boolean(this.config?.rtk?.available),
91
+ productContext: this.config?.productContext || null,
92
+ domainContext: this.config?.domainContext || null,
93
+ projectDir,
94
+ stack, testFramework,
95
+ provider: this._resolvedProvider || (typeof this.resolveProvider === "function" ? this.resolveProvider() : null)
96
+ });
97
+ // Φ1-D: prompt is the joined layout (identical for every agent);
98
+ // the buckets ride along so ClaudeAgent can system-split them.
99
+ return { prompt: joinLayout(layout), stablePrompt: layout.stable, volatilePrompt: layout.volatile };
100
+ }
101
+
102
+ buildSuccessResult(parsed, provider, agentResult) {
103
+ return { ...agentResult, output: agentResult.output || "", provider };
104
+ }
105
+
106
+ buildSummary() { return "Coder completed"; }
107
+ }
@@ -0,0 +1,110 @@
1
+ import { BaseRole } from "./base-role.js";
2
+ import { stampStagedVerdict } from "../review/verdict-store.js";
3
+ import {
4
+ ensureGitRepo,
5
+ currentBranch,
6
+ fetchBase,
7
+ ensureBranchUpToDateWithBase,
8
+ hasChanges,
9
+ commitAll,
10
+ pushBranch,
11
+ createPullRequest,
12
+ revParse,
13
+ hasRemote
14
+ } from "../utils/git.js";
15
+
16
+ function buildCommitMessage(task) {
17
+ const clean = String(task || "")
18
+ .replaceAll(/\s+/g, " ")
19
+ .trim();
20
+ const prefix = "feat: ";
21
+ const maxBody = 72 - prefix.length;
22
+ return `${prefix}${clean.slice(0, maxBody) || "update"}`;
23
+ }
24
+
25
+ function buildPrTitle(task) {
26
+ const clean = String(task || "")
27
+ .replaceAll(/\s+/g, " ")
28
+ .trim();
29
+ return clean.slice(0, 70) || "Karajan update";
30
+ }
31
+
32
+ export class CommiterRole extends BaseRole {
33
+ constructor({ config, logger, emitter = null }) {
34
+ super({ name: "commiter", config, logger, emitter });
35
+ }
36
+
37
+ async execute(input) {
38
+ const { task, commitMessage, push = false, createPr = false } = input || {};
39
+
40
+ const isRepo = await ensureGitRepo();
41
+ if (!isRepo) {
42
+ return {
43
+ ok: false,
44
+ result: { error: "Current directory is not a git repository" },
45
+ summary: "Commiter failed: not a git repo"
46
+ };
47
+ }
48
+
49
+ const branch = await currentBranch();
50
+ const changes = await hasChanges();
51
+
52
+ if (!changes) {
53
+ return {
54
+ ok: true,
55
+ result: { branch, committed: false, commitHash: null, prUrl: null },
56
+ summary: "No changes to commit"
57
+ };
58
+ }
59
+
60
+ const msg = commitMessage || buildCommitMessage(task);
61
+ // ENV-F1 (KJC-TSK-0643): CommiterRole runs after the HU review passed —
62
+ // stamp the pipeline's verdict so the v4 gate accepts this commit.
63
+ await commitAll(msg, null, {
64
+ beforeCommit: () => stampStagedVerdict({
65
+ projectDir: this.config?.projectDir || process.cwd(),
66
+ reviewer: this.config?.reviewer || "pipeline-reviewer",
67
+ summary: "kj pipeline (commiter role): review passed",
68
+ }),
69
+ });
70
+ const commitHash = await revParse("HEAD");
71
+
72
+ // KJC-BUG-0112: no `origin` remote (quickstart scenario) → skip
73
+ // push/PR instead of throwing on fetch.
74
+ const remoteAvailable = push ? await hasRemote() : false;
75
+ if (push && !remoteAvailable) {
76
+ this.logger?.info?.("No remote configured — skipping push/PR");
77
+ }
78
+ if (push && remoteAvailable) {
79
+ const baseBranch = this.config.base_branch || "main";
80
+ await fetchBase(baseBranch);
81
+ await ensureBranchUpToDateWithBase({
82
+ branch,
83
+ baseBranch,
84
+ autoRebase: true
85
+ });
86
+ await pushBranch(branch);
87
+ }
88
+
89
+ let prUrl = null;
90
+ if (push && createPr && remoteAvailable) {
91
+ const baseBranch = this.config.base_branch || "main";
92
+ prUrl = await createPullRequest({
93
+ baseBranch,
94
+ branch,
95
+ title: buildPrTitle(task),
96
+ body: `Task: ${task || "N/A"}`
97
+ });
98
+ }
99
+
100
+ const parts = [`Committed on ${branch}`];
101
+ if (push) parts.push("pushed");
102
+ if (prUrl) parts.push(`PR: ${prUrl}`);
103
+
104
+ return {
105
+ ok: true,
106
+ result: { branch, committed: true, commitHash, prUrl },
107
+ summary: parts.join(", ")
108
+ };
109
+ }
110
+ }
@@ -0,0 +1,81 @@
1
+ import { AgentRole } from "./agent-role.js";
2
+ import { buildDiscoverPrompt, parseDiscoverOutput } from "../prompts/discover.js";
3
+
4
+ function pluralize(count, singular, plural) {
5
+ return `${count} ${count === 1 ? singular : plural}`;
6
+ }
7
+
8
+ const MODE_FIELDS = {
9
+ momtest: { key: "momTestQuestions", fallback: [] },
10
+ wendel: { key: "wendelChecklist", fallback: [] },
11
+ classify: { key: "classification", fallback: null },
12
+ jtbd: { key: "jtbds", fallback: [] }
13
+ };
14
+
15
+ function buildSummary(parsed, mode) {
16
+ const gapCount = parsed.gaps?.length || 0;
17
+ const parts = [];
18
+ if (gapCount > 0) parts.push(`${pluralize(gapCount, "gap", "gaps")} found`);
19
+ if (mode === "momtest") {
20
+ const qCount = parsed.momTestQuestions?.length || 0;
21
+ if (qCount > 0) parts.push(`${pluralize(qCount, "Mom Test question", "Mom Test questions")}`);
22
+ }
23
+ if (mode === "wendel") {
24
+ const failCount = (parsed.wendelChecklist || []).filter(c => c.status === "fail").length;
25
+ if (failCount > 0) parts.push(`${pluralize(failCount, "Wendel condition", "Wendel conditions")} failed`);
26
+ }
27
+ if (mode === "classify" && parsed.classification) {
28
+ parts.push(`type: ${parsed.classification.type}, risk: ${parsed.classification.adoptionRisk}`);
29
+ }
30
+ if (mode === "jtbd") {
31
+ const jCount = parsed.jtbds?.length || 0;
32
+ if (jCount > 0) parts.push(`${pluralize(jCount, "JTBD", "JTBDs")} generated`);
33
+ }
34
+ if (parts.length === 0) return "Discovery complete: task is ready";
35
+ return `Discovery complete: ${parts.join(", ")} (verdict: ${parsed.verdict})`;
36
+ }
37
+
38
+ export class DiscoverRole extends AgentRole {
39
+ constructor(opts) {
40
+ super({ ...opts, name: "discover" });
41
+ }
42
+
43
+ async execute(input) {
44
+ const task = typeof input === "string" ? input : input?.task || this.context?.task || "";
45
+ const onOutput = typeof input === "string" ? null : input?.onOutput || null;
46
+ const mode = typeof input === "object" ? input?.mode || "gaps" : "gaps";
47
+ const context = typeof input === "object" ? input?.context || null : null;
48
+
49
+ const provider = this.resolveProvider();
50
+ const agent = this.createAgentInstance(provider);
51
+
52
+ const prompt = buildDiscoverPrompt({ task, instructions: this.instructions, mode, context });
53
+ const runArgs = { prompt, role: "discover" };
54
+ if (onOutput) runArgs.onOutput = onOutput;
55
+ const result = await agent.runTask(runArgs);
56
+
57
+ if (!result.ok) {
58
+ return {
59
+ ok: false,
60
+ result: { error: result.error || result.output || "Discovery failed", provider, mode },
61
+ summary: `Discovery failed: ${result.error || "unknown error"}`,
62
+ usage: result.usage
63
+ };
64
+ }
65
+
66
+ try {
67
+ const parsed = parseDiscoverOutput(result.output);
68
+ if (!parsed) {
69
+ return { ok: true, result: { verdict: "ready", gaps: [], mode, raw: result.output, provider }, summary: "Discovery complete (unstructured output)", usage: result.usage };
70
+ }
71
+
72
+ const resultObj = { verdict: parsed.verdict, gaps: parsed.gaps, mode, provider };
73
+ const fieldDef = MODE_FIELDS[mode];
74
+ if (fieldDef) resultObj[fieldDef.key] = parsed[fieldDef.key] ?? fieldDef.fallback;
75
+
76
+ return { ok: true, result: resultObj, summary: buildSummary(parsed, mode), usage: result.usage };
77
+ } catch {
78
+ return { ok: true, result: { verdict: "ready", gaps: [], mode, raw: result.output, provider }, summary: "Discovery complete (unstructured output)", usage: result.usage };
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Domain Curator role.
3
+ * Discovers, proposes and synthesizes domain knowledge for the pipeline.
4
+ * Operates deterministically (loader + registry + synthesizer) — no LLM call needed
5
+ * unless the user wants to generate domain knowledge from scratch.
6
+ */
7
+
8
+ import { loadDomains } from "../domains/domain-loader.js";
9
+ import { DomainRegistry } from "../domains/domain-registry.js";
10
+ import { synthesizeDomainContext } from "../domains/domain-synthesizer.js";
11
+
12
+ export class DomainCuratorRole {
13
+ constructor({ config, logger }) {
14
+ this.config = config;
15
+ this.logger = logger;
16
+ }
17
+
18
+ /**
19
+ * Execute domain curation.
20
+ * @param {Object} input
21
+ * @param {string} input.task — the task description
22
+ * @param {string[]} input.domainHints — keywords from triage
23
+ * @param {Function & {interactive: boolean}} [input.askQuestion] — interactive question function
24
+ * @param {string} [input.projectDir] — project root
25
+ * @returns {Promise<{ok: boolean, result: Object, summary: string}>}
26
+ */
27
+ async execute({ task, domainHints = [], askQuestion = null, projectDir = null }) {
28
+ // 1. Load domains from filesystem
29
+ const fileDomains = await loadDomains(projectDir);
30
+
31
+ // 2. Search registry for additional matches
32
+ let registryDomains = [];
33
+ if (domainHints.length > 0) {
34
+ try {
35
+ const registry = await DomainRegistry.load();
36
+ registryDomains = registry.search(domainHints);
37
+ } catch {
38
+ this.logger.warn("Domain Curator: failed to load registry, continuing with file domains only");
39
+ }
40
+ }
41
+
42
+ // 3. Deduplicate (file domains take precedence over registry entries)
43
+ const allDomains = deduplicateDomains(fileDomains, registryDomains);
44
+
45
+ // 4. No domains found
46
+ if (allDomains.length === 0) {
47
+ if (askQuestion?.interactive) {
48
+ const answer = await askQuestion({
49
+ message: "No domain knowledge found for this task.\nDo you have domain documents to provide, or should the pipeline continue without domain context?",
50
+ type: "confirm"
51
+ });
52
+ // For now, just log. Future: support document ingestion.
53
+ if (answer === true) {
54
+ this.logger.info("Domain Curator: user indicated domain documents available — future feature");
55
+ }
56
+ } else {
57
+ this.logger.warn("Domain Curator: no domain knowledge found, continuing without domain context");
58
+ }
59
+
60
+ return {
61
+ ok: true,
62
+ result: {
63
+ selectedDomains: [],
64
+ domainContext: null,
65
+ domainsFound: 0,
66
+ domainsUsed: 0,
67
+ source: "none"
68
+ },
69
+ summary: "Domain Curator: no domains found"
70
+ };
71
+ }
72
+
73
+ // 5. Propose selection to user (if interactive) or use all
74
+ let selectedDomains;
75
+
76
+ if (askQuestion?.interactive && allDomains.length > 1) {
77
+ const options = allDomains.map(d => ({
78
+ id: d.name,
79
+ label: `${d.name} (v${d.version || "?"}) — ${d.description || "no description"}`,
80
+ default: true
81
+ }));
82
+
83
+ const selected = await askQuestion({
84
+ message: `Found ${allDomains.length} domain knowledge package(s):`,
85
+ type: "multi-select",
86
+ options,
87
+ defaults: allDomains.map(d => d.name)
88
+ });
89
+
90
+ if (Array.isArray(selected) && selected.length > 0) {
91
+ const selectedSet = new Set(selected);
92
+ selectedDomains = allDomains.filter(d => selectedSet.has(d.name));
93
+ } else {
94
+ selectedDomains = allDomains; // fallback to all
95
+ }
96
+ } else {
97
+ // Single domain or non-interactive: use all
98
+ selectedDomains = allDomains;
99
+ }
100
+
101
+ // 6. Synthesize context
102
+ const domainContext = synthesizeDomainContext({
103
+ task,
104
+ domainHints,
105
+ selectedDomains
106
+ });
107
+
108
+ const source = selectedDomains.some(d => d.origin === "project") ? "project+user" : "user";
109
+
110
+ return {
111
+ ok: true,
112
+ result: {
113
+ selectedDomains: selectedDomains.map(d => d.name),
114
+ domainContext: domainContext || null,
115
+ domainsFound: allDomains.length,
116
+ domainsUsed: selectedDomains.length,
117
+ source
118
+ },
119
+ summary: `Domain Curator: ${selectedDomains.length}/${allDomains.length} domain(s) selected`
120
+ };
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Deduplicate domains — file domains override registry entries by name.
126
+ */
127
+ function deduplicateDomains(fileDomains, registryDomains) {
128
+ const byName = new Map();
129
+
130
+ // Registry entries first (lower priority)
131
+ for (const rd of registryDomains) {
132
+ if (rd.name) byName.set(rd.name, rd);
133
+ }
134
+
135
+ // File domains override
136
+ for (const fd of fileDomains) {
137
+ if (fd.name) byName.set(fd.name, fd);
138
+ }
139
+
140
+ return Array.from(byName.values());
141
+ }
@@ -0,0 +1,64 @@
1
+ import { AgentRole } from "./agent-role.js";
2
+ import { buildHuReviewerPrompt, parseHuReviewerOutput } from "../prompts/hu-reviewer.js";
3
+
4
+ const EMPTY_BATCH = { total: 0, certified: 0, needs_rewrite: 0, needs_context: 0, consolidated_questions: "" };
5
+
6
+ export class HuReviewerRole extends AgentRole {
7
+ constructor(opts) {
8
+ super({ ...opts, name: "hu-reviewer" });
9
+ }
10
+
11
+ resolveProvider() {
12
+ return (
13
+ this.config?.roles?.["hu-reviewer"]?.provider ||
14
+ this.config?.roles?.hu_reviewer?.provider ||
15
+ this.config?.roles?.coder?.provider ||
16
+ "claude"
17
+ );
18
+ }
19
+
20
+ extractInput(input) {
21
+ return {
22
+ stories: input?.stories || [],
23
+ context: input?.context || null,
24
+ onOutput: input?.onOutput || null
25
+ };
26
+ }
27
+
28
+ async buildPrompt({ stories, context }) {
29
+ const prompt = buildHuReviewerPrompt({
30
+ stories, instructions: this.instructions, context,
31
+ productContext: this.config?.productContext || null,
32
+ domainContext: this.config?.domainContext || null
33
+ });
34
+ return { prompt };
35
+ }
36
+
37
+ parseOutput(raw) { return parseHuReviewerOutput(raw); }
38
+
39
+ buildSuccessResult(parsed, provider) {
40
+ return { evaluations: parsed.evaluations, batch_summary: parsed.batch_summary, provider };
41
+ }
42
+
43
+ buildSummary(parsed) {
44
+ const bs = parsed.batch_summary;
45
+ const parts = [`${bs.total} HU(s) evaluated`];
46
+ if (bs.certified > 0) parts.push(`${bs.certified} certified`);
47
+ if (bs.needs_rewrite > 0) parts.push(`${bs.needs_rewrite} need rewrite`);
48
+ if (bs.needs_context > 0) parts.push(`${bs.needs_context} need context`);
49
+ return `HU Review complete: ${parts.join(", ")}`;
50
+ }
51
+
52
+ handleParseNull(agentResult, provider) {
53
+ return {
54
+ ok: true,
55
+ result: { evaluations: [], batch_summary: { ...EMPTY_BATCH }, raw: agentResult.output, provider },
56
+ summary: "HU Review complete (unstructured output)",
57
+ usage: agentResult.usage
58
+ };
59
+ }
60
+
61
+ handleParseError(_err, agentResult, provider) {
62
+ return this.handleParseNull(agentResult, provider);
63
+ }
64
+ }