@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,108 @@
1
+ /**
2
+ * Planning Game MCP adapter.
3
+ * Handles card ID detection, task enrichment, and completion updates.
4
+ */
5
+
6
+ const CARD_ID_PATTERN = /[A-Z0-9]{2,5}-(?:TSK|BUG|PCS|PRP|SPR|QA)-\d{4}/;
7
+
8
+ export function parseCardId(text) {
9
+ if (!text) return null;
10
+ const match = CARD_ID_PATTERN.exec(String(text));
11
+ return match ? match[0] : null;
12
+ }
13
+
14
+ function appendDescriptionSection(parts, card) {
15
+ if (card.descriptionStructured?.length) {
16
+ parts.push("", "### User Story");
17
+ for (const s of card.descriptionStructured) {
18
+ parts.push(`- **Como** ${s.role}`, ` **Quiero** ${s.goal}`, ` **Para** ${s.benefit}`);
19
+ }
20
+ } else if (card.description) {
21
+ parts.push("", "### Description", card.description);
22
+ }
23
+ }
24
+
25
+ function appendAcceptanceCriteriaSection(parts, card) {
26
+ if (card.acceptanceCriteriaStructured?.length) {
27
+ parts.push("", "### Acceptance Criteria");
28
+ for (const ac of card.acceptanceCriteriaStructured) {
29
+ if (ac.given && ac.when && ac.then) {
30
+ parts.push(`- **Given** ${ac.given}`, ` **When** ${ac.when}`, ` **Then** ${ac.then}`);
31
+ } else if (ac.raw) {
32
+ parts.push(`- ${ac.raw}`);
33
+ }
34
+ }
35
+ } else if (card.acceptanceCriteria) {
36
+ parts.push("", "### Acceptance Criteria", card.acceptanceCriteria);
37
+ }
38
+ }
39
+
40
+ function appendImplementationPlanSection(parts, card) {
41
+ if (!card.implementationPlan) return;
42
+ const plan = card.implementationPlan;
43
+ parts.push("", "### Implementation Plan");
44
+ if (plan.approach) parts.push(`**Approach:** ${plan.approach}`);
45
+ if (plan.steps?.length) {
46
+ parts.push("**Steps:**");
47
+ for (const step of plan.steps) {
48
+ parts.push(`1. ${step.description}`);
49
+ }
50
+ }
51
+ }
52
+
53
+ export function buildTaskFromCard(card) {
54
+ const parts = [`## ${card.cardId}: ${card.title}`];
55
+ appendDescriptionSection(parts, card);
56
+ appendAcceptanceCriteriaSection(parts, card);
57
+ appendImplementationPlanSection(parts, card);
58
+ return parts.join("\n");
59
+ }
60
+
61
+ export function buildCommitsPayload(gitLog) {
62
+ if (!gitLog?.length) return [];
63
+ return gitLog.map((entry) => ({
64
+ hash: entry.hash,
65
+ message: entry.message,
66
+ date: entry.date,
67
+ author: entry.author
68
+ }));
69
+ }
70
+
71
+ export function buildCompletionUpdates({ approved, commits, startDate, codeveloper }) {
72
+ if (!approved) return {};
73
+
74
+ const updates = {
75
+ status: "To Validate",
76
+ endDate: new Date().toISOString(),
77
+ developer: "dev_016",
78
+ commits: commits || []
79
+ };
80
+
81
+ if (startDate) updates.startDate = startDate;
82
+ if (codeveloper) updates.codeveloper = codeveloper;
83
+
84
+ return updates;
85
+ }
86
+
87
+ export function buildTaskPrompt({ task, card }) {
88
+ const cardId = parseCardId(task) || card?.cardId || null;
89
+ const prompt = card ? buildTaskFromCard(card) : task;
90
+ return { cardId, prompt };
91
+ }
92
+
93
+ export async function updateCardOnCompletion({
94
+ client,
95
+ projectId,
96
+ cardId,
97
+ firebaseId,
98
+ approved,
99
+ gitLog,
100
+ startDate,
101
+ codeveloper
102
+ }) {
103
+ if (!approved) return null;
104
+
105
+ const commits = buildCommitsPayload(gitLog);
106
+ const updates = buildCompletionUpdates({ approved, commits, startDate, codeveloper });
107
+ return client.updateCard({ projectId, cardId, firebaseId, updates });
108
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Automatic ADR generation from architect tradeoffs.
3
+ * Creates ADRs in Planning Game when PG is linked, or returns suggestions otherwise.
4
+ */
5
+
6
+ function buildAdr({ tradeoff, taskTitle }) {
7
+ return {
8
+ title: tradeoff,
9
+ status: "accepted",
10
+ context: `Architecture decision for task: ${taskTitle}`,
11
+ decision: tradeoff
12
+ };
13
+ }
14
+
15
+ export async function createArchitectADRs({ tradeoffs, pgTaskId, pgProject, taskTitle, mcpClient }) {
16
+ if (!tradeoffs?.length) {
17
+ return { created: 0, adrs: [] };
18
+ }
19
+
20
+ const hasPg = Boolean(pgTaskId && pgProject && mcpClient);
21
+
22
+ if (!hasPg) {
23
+ const adrs = tradeoffs.map(tradeoff => ({
24
+ ...buildAdr({ tradeoff, taskTitle }),
25
+ suggestion: true
26
+ }));
27
+ return { created: 0, adrs };
28
+ }
29
+
30
+ const adrs = [];
31
+ let created = 0;
32
+
33
+ for (const tradeoff of tradeoffs) {
34
+ const adr = buildAdr({ tradeoff, taskTitle });
35
+ try {
36
+ await mcpClient.createAdr({ projectId: pgProject, adr });
37
+ adrs.push(adr);
38
+ created++;
39
+ } catch {
40
+ // Log warning but don't block pipeline for a single ADR failure
41
+ }
42
+ }
43
+
44
+ return { created, adrs };
45
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Planning Game MCP client.
3
+ * Communicates with Planning Game via HTTP API or MCP tool calls.
4
+ *
5
+ * When Karajan runs as an MCP server (kj_run), the caller (Claude Code)
6
+ * is expected to provide card data directly via pgTask/pgProject flags.
7
+ *
8
+ * This client provides standalone HTTP access for CLI usage (kj run --pg-task).
9
+ * Requires planning_game.api_url in config or PG_API_URL env var.
10
+ */
11
+
12
+ import { withRetry } from "../utils/retry.js";
13
+
14
+ const DEFAULT_API_URL = "http://localhost:3000/api";
15
+ const DEFAULT_TIMEOUT_MS = 10000;
16
+
17
+ function getApiUrl() {
18
+ return process.env.PG_API_URL || DEFAULT_API_URL;
19
+ }
20
+
21
+ async function fetchWithTimeout(url, options = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
22
+ const controller = new AbortController();
23
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
24
+ try {
25
+ const response = await fetch(url, { ...options, signal: controller.signal });
26
+ if (!response.ok) {
27
+ const err = new Error(`Planning Game API error: ${response.status} ${response.statusText}`);
28
+ err.httpStatus = response.status;
29
+ err.retryAfter = response.headers?.get?.("retry-after") || null;
30
+ throw err;
31
+ }
32
+ return response;
33
+ } catch (error) {
34
+ if (error?.httpStatus) throw error;
35
+ if (error?.name === "AbortError") {
36
+ const err = new Error(`Planning Game API timeout after ${timeoutMs}ms`);
37
+ err.httpStatus = 408;
38
+ throw err;
39
+ }
40
+ throw new Error(`Planning Game network error: ${error?.message || "unknown error"}`, { cause: error });
41
+ } finally {
42
+ clearTimeout(timeoutId);
43
+ }
44
+ }
45
+
46
+ async function fetchWithRetry(url, options = {}, timeoutMs = DEFAULT_TIMEOUT_MS, retryOpts = {}) {
47
+ return withRetry(
48
+ () => fetchWithTimeout(url, options, timeoutMs),
49
+ { maxAttempts: 3, initialBackoffMs: 1000, ...retryOpts }
50
+ );
51
+ }
52
+
53
+ async function parseJsonResponse(response) {
54
+ try {
55
+ return await response.json();
56
+ } catch (error) {
57
+ throw new Error(`Planning Game invalid response: ${error?.message || "invalid JSON"}`, { cause: error });
58
+ }
59
+ }
60
+
61
+ export async function fetchCard({ projectId, cardId, timeoutMs = DEFAULT_TIMEOUT_MS }) {
62
+ const url = `${getApiUrl()}/projects/${encodeURIComponent(projectId)}/cards/${encodeURIComponent(cardId)}`;
63
+ const response = await fetchWithRetry(url, {}, timeoutMs);
64
+ const data = await parseJsonResponse(response);
65
+ return data?.card || data;
66
+ }
67
+
68
+ export async function updateCard({ projectId, cardId: _cardId, firebaseId, updates, timeoutMs = DEFAULT_TIMEOUT_MS }) {
69
+ const url = `${getApiUrl()}/projects/${encodeURIComponent(projectId)}/cards/${encodeURIComponent(firebaseId)}`;
70
+ const response = await fetchWithRetry(
71
+ url,
72
+ {
73
+ method: "PATCH",
74
+ headers: { "Content-Type": "application/json" },
75
+ body: JSON.stringify({ updates })
76
+ },
77
+ timeoutMs
78
+ );
79
+ return parseJsonResponse(response);
80
+ }
81
+
82
+ export async function createCard({ projectId, card, timeoutMs = DEFAULT_TIMEOUT_MS }) {
83
+ const url = `${getApiUrl()}/projects/${encodeURIComponent(projectId)}/cards`;
84
+ const response = await fetchWithRetry(
85
+ url,
86
+ {
87
+ method: "POST",
88
+ headers: { "Content-Type": "application/json" },
89
+ body: JSON.stringify(card)
90
+ },
91
+ timeoutMs
92
+ );
93
+ return parseJsonResponse(response);
94
+ }
95
+
96
+ export async function relateCards({ projectId, sourceCardId, targetCardId, relationType, timeoutMs = DEFAULT_TIMEOUT_MS }) {
97
+ const url = `${getApiUrl()}/projects/${encodeURIComponent(projectId)}/cards/relate`;
98
+ const response = await fetchWithRetry(
99
+ url,
100
+ {
101
+ method: "POST",
102
+ headers: { "Content-Type": "application/json" },
103
+ body: JSON.stringify({ sourceCardId, targetCardId, relationType })
104
+ },
105
+ timeoutMs
106
+ );
107
+ return parseJsonResponse(response);
108
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Planning Game decomposition.
3
+ * Creates subtask cards in PG with blocks/blockedBy chain when triage
4
+ * recommends decomposition and user accepts.
5
+ */
6
+
7
+ import { msg } from "../utils/messages.js";
8
+
9
+ export async function createDecompositionSubtasks({
10
+ client,
11
+ projectId,
12
+ parentCardId,
13
+ parentFirebaseId: _parentFirebaseId,
14
+ subtasks,
15
+ epic,
16
+ sprint,
17
+ codeveloper
18
+ }) {
19
+ if (!subtasks?.length || subtasks.length < 2) return [];
20
+
21
+ const created = [];
22
+
23
+ for (let i = 0; i < subtasks.length; i++) {
24
+ const card = {
25
+ type: "task",
26
+ title: subtasks[i],
27
+ descriptionStructured: [{
28
+ role: "developer",
29
+ goal: subtasks[i],
30
+ benefit: `Part ${i + 1}/${subtasks.length} of decomposed task ${parentCardId}`
31
+ }],
32
+ acceptanceCriteria: `Subtask ${i + 1} of ${parentCardId}: ${subtasks[i]}`
33
+ };
34
+
35
+ if (epic) card.epic = epic;
36
+ if (sprint) card.sprint = sprint;
37
+ if (codeveloper) card.codeveloper = codeveloper;
38
+
39
+ const result = await client.createCard({ projectId, card });
40
+ created.push({
41
+ cardId: result.cardId,
42
+ firebaseId: result.firebaseId,
43
+ title: subtasks[i],
44
+ index: i
45
+ });
46
+ }
47
+
48
+ // Chain blocks/blockedBy relationships: card[0] blocks card[1], card[1] blocks card[2], etc.
49
+ for (let i = 0; i < created.length - 1; i++) {
50
+ await client.relateCards({
51
+ projectId,
52
+ sourceCardId: created[i].cardId,
53
+ targetCardId: created[i + 1].cardId,
54
+ relationType: "blocks"
55
+ });
56
+ }
57
+
58
+ // Relate all subtasks to parent
59
+ for (const sub of created) {
60
+ await client.relateCards({
61
+ projectId,
62
+ sourceCardId: parentCardId,
63
+ targetCardId: sub.cardId,
64
+ relationType: "related"
65
+ });
66
+ }
67
+
68
+ return created;
69
+ }
70
+
71
+ export function buildDecompositionQuestion(subtasks, parentCardId, lang = "en") {
72
+ const lines = [
73
+ msg("triage_decompose", lang, { count: subtasks.length }),
74
+ ""
75
+ ];
76
+ for (let i = 0; i < subtasks.length; i++) {
77
+ lines.push(`${i + 1}. ${subtasks[i]}`);
78
+ }
79
+ lines.push(
80
+ "",
81
+ msg("triage_create_cards", lang, { cardId: parentCardId }),
82
+ msg("triage_sequential", lang),
83
+ "",
84
+ msg("triage_reply", lang)
85
+ );
86
+ return lines.join("\n");
87
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Planning Game pipeline adapter.
3
+ * Subscribes to pipeline events and handles PG card lifecycle updates.
4
+ * Decouples PG logic from the orchestrator — works as an event-driven plugin.
5
+ *
6
+ * Handles:
7
+ * - Marking card as "In Progress" at session start
8
+ * - Decomposing tasks into subtasks after triage
9
+ * - Marking card as "To Validate" on approved completion
10
+ *
11
+ * If PG is disabled or no pgTaskId is present, the adapter does nothing.
12
+ */
13
+
14
+ import { emitProgress, makeEvent } from "../utils/events.js";
15
+ import { addCheckpoint } from "../session/store.js";
16
+ import { appendPgCommits } from "../session/mutators.js";
17
+ import { getLang } from "../utils/messages.js";
18
+
19
+ /**
20
+ * Attach the PG adapter to a pipeline emitter.
21
+ * Call this once during runFlow() initialization.
22
+ *
23
+ * @param {object} opts
24
+ * @param {EventEmitter} opts.emitter - Pipeline event emitter
25
+ * @param {object} opts.session - Session object (mutated during pipeline)
26
+ * @param {object} opts.config - Resolved config
27
+ * @param {object} opts.logger - Logger instance
28
+ * @param {string|null} opts.pgTaskId - Planning Game card ID (e.g. "KJC-TSK-0099")
29
+ * @param {string|null} opts.pgProject - Planning Game project ID
30
+ * @returns {{ pgCard: object|null }} The fetched PG card (or null)
31
+ */
32
+ export async function initPgAdapter({ session: _session, config, logger, pgTaskId, pgProject }) {
33
+ if (!pgTaskId || !pgProject || config.planning_game?.enabled === false) {
34
+ return { pgCard: null };
35
+ }
36
+
37
+ const pgCard = await markPgCardInProgress({ pgTaskId, pgProject, config, logger });
38
+ return { pgCard };
39
+ }
40
+
41
+ /**
42
+ * Handle PG task decomposition after triage.
43
+ * Creates subtask cards in PG when triage recommends decomposition.
44
+ */
45
+ async function handlePgDecomposition({ triageResult, pgTaskId, pgProject, config, askQuestion, emitter, eventBase, session, stageResults, logger }) {
46
+ const shouldDecompose = triageResult.stageResult?.shouldDecompose
47
+ && triageResult.stageResult.subtasks?.length > 1
48
+ && pgTaskId
49
+ && pgProject
50
+ && config.planning_game?.enabled !== false
51
+ && askQuestion;
52
+
53
+ if (!shouldDecompose) return;
54
+
55
+ try {
56
+ const { buildDecompositionQuestion, createDecompositionSubtasks } = await import("./decomposition.js");
57
+ const { createCard, relateCards, fetchCard } = await import("./client.js");
58
+
59
+ const lang = getLang(config);
60
+ const question = buildDecompositionQuestion(triageResult.stageResult.subtasks, pgTaskId, lang);
61
+ const answer = await askQuestion(question);
62
+
63
+ const normalizedAnswer = (answer || "").trim().toLowerCase();
64
+ const isAccept = normalizedAnswer === "1" || normalizedAnswer === "yes" || normalizedAnswer === "sí" || normalizedAnswer === "si";
65
+ if (isAccept) {
66
+ const parentCard = await fetchCard({ projectId: pgProject, cardId: pgTaskId }).catch(() => null);
67
+ const createdSubtasks = await createDecompositionSubtasks({
68
+ client: { createCard, relateCards },
69
+ projectId: pgProject,
70
+ parentCardId: pgTaskId,
71
+ parentFirebaseId: parentCard?.firebaseId || null,
72
+ subtasks: triageResult.stageResult.subtasks,
73
+ epic: parentCard?.epic || null,
74
+ sprint: parentCard?.sprint || null,
75
+ codeveloper: config.planning_game?.codeveloper || null
76
+ });
77
+
78
+ stageResults.triage.pgSubtasks = createdSubtasks;
79
+ logger.info(`Planning Game: created ${createdSubtasks.length} subtasks from decomposition`);
80
+
81
+ emitProgress(
82
+ emitter,
83
+ makeEvent("pg:decompose", { ...eventBase, stage: "triage" }, {
84
+ message: `Created ${createdSubtasks.length} subtasks in Planning Game`,
85
+ detail: { subtasks: createdSubtasks.map((s) => ({ cardId: s.cardId, title: s.title })) }
86
+ })
87
+ );
88
+
89
+ await addCheckpoint(session, {
90
+ stage: "pg-decompose",
91
+ subtasksCreated: createdSubtasks.length,
92
+ cardIds: createdSubtasks.map((s) => s.cardId)
93
+ });
94
+ }
95
+ } catch (err) {
96
+ logger.warn(`Planning Game decomposition failed: ${err.message}`);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Mark PG card as "To Validate" on approved session completion.
102
+ * Merges commits from gitResult and session.pg_commits (accumulated during pipeline).
103
+ */
104
+ export async function markPgCardToValidate({ pgCard, pgProject, config, session, gitResult, logger }) {
105
+ if (!pgCard || !pgProject) return;
106
+
107
+ try {
108
+ const { updateCard } = await import("./client.js");
109
+ const { buildCompletionUpdates } = await import("./adapter.js");
110
+
111
+ // Merge commits: session.pg_commits (accumulated) + gitResult.commits (final)
112
+ const accumulatedCommits = session.pg_commits || [];
113
+ const finalCommits = gitResult?.commits || [];
114
+ const seenHashes = new Set(accumulatedCommits.map(c => c.hash));
115
+ const mergedCommits = [...accumulatedCommits];
116
+ for (const c of finalCommits) {
117
+ if (!seenHashes.has(c.hash)) {
118
+ mergedCommits.push(c);
119
+ }
120
+ }
121
+
122
+ const pgUpdates = buildCompletionUpdates({
123
+ approved: true,
124
+ commits: mergedCommits,
125
+ startDate: session.pg_card?.startDate || session.created_at,
126
+ codeveloper: config.planning_game?.codeveloper || null
127
+ });
128
+ await updateCard({
129
+ projectId: pgProject,
130
+ cardId: session.pg_task_id,
131
+ firebaseId: pgCard.firebaseId,
132
+ updates: pgUpdates
133
+ });
134
+ logger.info(`Planning Game: ${session.pg_task_id} → To Validate`);
135
+ } catch (err) {
136
+ logger.warn(`Planning Game: could not update ${session.pg_task_id} on completion: ${err.message}`);
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Convert a PG card's structured data into HU stories for the hu-reviewer stage.
142
+ * Returns an array of story objects ({id, text}) or null if the card lacks structured data.
143
+ *
144
+ * @param {object} pgCard - The PG card object (from fetchCard)
145
+ * @returns {Array<{id: string, text: string}>|null}
146
+ */
147
+ export function buildHuStoriesFromPgCard(pgCard) {
148
+ if (!pgCard?.descriptionStructured?.length) return null;
149
+
150
+ const parts = [];
151
+
152
+ // User stories (Como/Quiero/Para → As/I want/So that)
153
+ for (const s of pgCard.descriptionStructured) {
154
+ parts.push(`As ${s.role}, I want ${s.goal}, so that ${s.benefit}.`);
155
+ }
156
+
157
+ // Acceptance criteria
158
+ if (pgCard.acceptanceCriteriaStructured?.length) {
159
+ parts.push("", "Acceptance Criteria:");
160
+ for (const ac of pgCard.acceptanceCriteriaStructured) {
161
+ if (ac.given && ac.when && ac.then) {
162
+ parts.push(`- Given ${ac.given}, When ${ac.when}, Then ${ac.then}`);
163
+ } else if (ac.raw) {
164
+ parts.push(`- ${ac.raw}`);
165
+ }
166
+ }
167
+ } else if (pgCard.acceptanceCriteria) {
168
+ parts.push("", "Acceptance Criteria:", pgCard.acceptanceCriteria);
169
+ }
170
+
171
+ const storyId = pgCard.cardId || "HU-PG-001";
172
+ const storyText = parts.join("\n");
173
+
174
+ return [{ id: storyId, text: storyText }];
175
+ }
176
+
177
+ /**
178
+ * Accumulate a commit into the session's pg_commits array.
179
+ * Called after each successful commitAll during the iteration loop.
180
+ * Best-effort: never throws.
181
+ *
182
+ * @param {object} session - Pipeline session (mutated)
183
+ * @param {{ hash: string, message: string, date?: string, author?: string }} commitInfo
184
+ */
185
+ export function accumulateCommit(session, commitInfo) {
186
+ if (!session || !commitInfo?.hash) return;
187
+ appendPgCommits(session, [{
188
+ hash: commitInfo.hash,
189
+ message: commitInfo.message || "",
190
+ date: commitInfo.date || new Date().toISOString(),
191
+ author: commitInfo.author || "Karajan"
192
+ }]);
193
+ }
194
+
195
+ // --- Internal helpers ---
196
+
197
+ async function markPgCardInProgress({ pgTaskId, pgProject, config, logger }) {
198
+ try {
199
+ const { fetchCard, updateCard } = await import("./client.js");
200
+ const pgCard = await fetchCard({ projectId: pgProject, cardId: pgTaskId });
201
+ if (pgCard && pgCard.status !== "In Progress") {
202
+ await updateCard({
203
+ projectId: pgProject,
204
+ cardId: pgTaskId,
205
+ firebaseId: pgCard.firebaseId,
206
+ updates: {
207
+ status: "In Progress",
208
+ startDate: new Date().toISOString(),
209
+ developer: "dev_016",
210
+ codeveloper: config.planning_game?.codeveloper || null
211
+ }
212
+ });
213
+ logger.info(`Planning Game: ${pgTaskId} → In Progress`);
214
+ }
215
+ return pgCard;
216
+ } catch (err) {
217
+ logger.warn(`Planning Game: could not update ${pgTaskId}: ${err.message}`);
218
+ return null;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * TSK-0339: integration adapter shape — the orchestrator consumes tracker
224
+ * hooks via this neutral interface, not via direct imports. `registerPgAdapter`
225
+ * is called once at bootstrap when `config.planning_game.enabled` is true,
226
+ * wiring these hooks into `src/orchestrator/integrations.js` under the
227
+ * "tracker" slot.
228
+ *
229
+ * Adding a new tracker (GitHub Projects, Jira, Linear, …) means creating
230
+ * a sibling `src/adapters/<name>/adapter.js` with the same hook surface,
231
+ * nothing else in the orchestrator changes.
232
+ */
233
+ export const planningGameAdapter = {
234
+ name: "planning-game",
235
+ async onSessionStart(opts) { return initPgAdapter(opts); },
236
+ onCommit(session, commit) { accumulateCommit(session, commit); },
237
+ async onSessionApproved(opts) { return markPgCardToValidate(opts); },
238
+ buildHuStoriesFromCard(card) { return buildHuStoriesFromPgCard(card); },
239
+ async handleDecomposition(opts) { return handlePgDecomposition(opts); },
240
+ async createAdrsFromTradeoffs({ tradeoffs, pgTaskId, pgProject, taskTitle }) {
241
+ // Lazy-loaded to avoid pulling createArchitectADRs into every import.
242
+ const { createArchitectADRs } = await import("./architect-adrs.js");
243
+ const pgClient = await import("./client.js");
244
+ return createArchitectADRs({ tradeoffs, pgTaskId, pgProject, taskTitle, mcpClient: pgClient });
245
+ },
246
+ };
247
+
248
+ export async function registerPgAdapter() {
249
+ const { registerIntegration } = await import("../orchestrator/integrations.js");
250
+ registerIntegration("tracker", planningGameAdapter);
251
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Plugin loader: discovers and loads plugins from .karajan/plugins/ directories.
3
+ *
4
+ * Plugins are JS files that export a `register(api)` function.
5
+ * The `api` object provides: registerAgent, registerModel.
6
+ *
7
+ * Discovery order (all are loaded, not first-wins):
8
+ * 1. <project>/.karajan/plugins/*.js
9
+ * 2. ~/.karajan/plugins/*.js
10
+ */
11
+
12
+ import path from "node:path";
13
+ import { pathToFileURL } from "node:url";
14
+ import { getKarajanHome } from "../utils/paths.js";
15
+ import { registerAgent } from "../agents/index.js";
16
+
17
+ async function listPluginFiles(dir) {
18
+ try {
19
+ const { readdir } = await import("node:fs/promises");
20
+ const entries = await readdir(dir, { withFileTypes: true });
21
+ return entries
22
+ .filter((e) => e.isFile() && e.name.endsWith(".js"))
23
+ .map((e) => path.join(dir, e.name));
24
+ } catch { /* plugin dir does not exist */
25
+ return [];
26
+ }
27
+ }
28
+
29
+ async function loadPlugin(filePath, api, logger) {
30
+ try {
31
+ const mod = await import(pathToFileURL(filePath).href);
32
+ const registerFn = mod.register || mod.default?.register;
33
+ if (typeof registerFn !== "function") {
34
+ logger?.warn?.(`Plugin ${filePath}: no register() export found, skipping`);
35
+ return null;
36
+ }
37
+ const meta = registerFn(api);
38
+ const name = meta?.name || path.basename(filePath, ".js");
39
+ logger?.debug?.(`Plugin loaded: ${name} (${filePath})`);
40
+ return { name, path: filePath, meta };
41
+ } catch (error) {
42
+ logger?.warn?.(`Plugin ${filePath} failed to load: ${error.message}`);
43
+ return null;
44
+ }
45
+ }
46
+
47
+ export async function loadPlugins({ projectDir, logger } = {}) {
48
+ const dirs = [];
49
+
50
+ if (projectDir) {
51
+ dirs.push(path.join(projectDir, ".karajan", "plugins"));
52
+ }
53
+ dirs.push(path.join(getKarajanHome(), "plugins"));
54
+
55
+ const api = { registerAgent };
56
+
57
+ const loaded = [];
58
+ for (const dir of dirs) {
59
+ const files = await listPluginFiles(dir);
60
+ for (const file of files) {
61
+ const result = await loadPlugin(file, api, logger);
62
+ if (result) loaded.push(result);
63
+ }
64
+ }
65
+
66
+ return loaded;
67
+ }