@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,334 @@
1
+ /**
2
+ * Git automation helpers for the pipeline.
3
+ * Extracted from orchestrator.js for testability and reuse.
4
+ */
5
+
6
+ import { addCheckpoint } from "../session/store.js";
7
+ import { stampStagedVerdict } from "../review/verdict-store.js";
8
+ import {
9
+ ensureGitRepo,
10
+ currentBranch,
11
+ hasCommits,
12
+ fetchBase,
13
+ syncBaseBranch,
14
+ ensureBranchUpToDateWithBase,
15
+ createBranch,
16
+ buildBranchName,
17
+ commitAll,
18
+ pushBranch,
19
+ createPullRequest,
20
+ listPendingPaths,
21
+ hasRemote
22
+ } from "../utils/git.js";
23
+
24
+ /**
25
+ * Karajan writes / updates several internal directories during a pipeline
26
+ * run (the workspace scaffold + the session journal). When they're the
27
+ * ONLY thing pending at finalization, the post-loop commit shouldn't
28
+ * inherit the user task's `feat:` message — it should be a clear
29
+ * `chore: scaffold karajan workspace` so `git log --oneline` reads:
30
+ *
31
+ * 2d770aa docs: add JSDoc comment to index.js
32
+ * abc1234 chore: scaffold karajan workspace
33
+ * 8a95ef0 initial
34
+ *
35
+ * A path counts as scaffolding when it lives at one of these prefixes
36
+ * OR is the project's root `.gitignore` (we extend it to include
37
+ * stack-specific entries during triage).
38
+ */
39
+ const KARAJAN_SCAFFOLD_PREFIXES = [
40
+ ".karajan/",
41
+ ".reviews/",
42
+ ".kj/",
43
+ ".agent/",
44
+ ];
45
+
46
+ function isKarajanScaffoldPath(p) {
47
+ if (p === ".gitignore") return true;
48
+ return KARAJAN_SCAFFOLD_PREFIXES.some((prefix) => p.startsWith(prefix));
49
+ }
50
+
51
+ /**
52
+ * @param {string[]} paths
53
+ * @returns {boolean} true when every pending path is a Karajan internal
54
+ */
55
+ export function pendingPathsAreOnlyKarajanScaffold(paths) {
56
+ if (!Array.isArray(paths) || paths.length === 0) return false;
57
+ return paths.every(isKarajanScaffoldPath);
58
+ }
59
+
60
+ /**
61
+ * Map the taskType (as classified by triage) to the matching
62
+ * Conventional Commits prefix. When triage hasn't run or the type is
63
+ * unknown we default to `feat:` (the pre-fix behaviour).
64
+ */
65
+ const TASK_TYPE_TO_PREFIX = {
66
+ doc: "docs",
67
+ "add-tests": "test",
68
+ refactor: "refactor",
69
+ infra: "chore",
70
+ sw: "feat",
71
+ };
72
+
73
+ function prefixForTaskType(taskType) {
74
+ return TASK_TYPE_TO_PREFIX[taskType] || "feat";
75
+ }
76
+
77
+ export function commitMessageFromTask(task, taskType = null) {
78
+ const clean = String(task || "")
79
+ .replaceAll(/\s+/g, " ")
80
+ .trim();
81
+ const prefix = prefixForTaskType(taskType);
82
+ return `${prefix}: ${clean.slice(0, 72) || "karajan update"}`;
83
+ }
84
+
85
+ /**
86
+ * Build the message used by `finalizeGitAutomation` for the post-loop
87
+ * commit. Two paths:
88
+ * - When the only pending changes are Karajan scaffold files
89
+ * (.gitignore, .karajan/, .reviews/, ...), use a fixed
90
+ * `chore: scaffold karajan workspace` message. This avoids the
91
+ * "duplicate feat:" git log seen when triage extends .gitignore
92
+ * for a freshly detected stack and the coder already committed
93
+ * the user-visible change.
94
+ * - Otherwise, fall back to `commitMessageFromTask(task, taskType)`,
95
+ * respecting the type for the prefix.
96
+ */
97
+ export function buildFinalizeCommitMessage({ task, taskType, pendingPaths }) {
98
+ if (pendingPathsAreOnlyKarajanScaffold(pendingPaths)) {
99
+ return "chore: scaffold karajan workspace";
100
+ }
101
+ return commitMessageFromTask(task, taskType);
102
+ }
103
+
104
+ export async function prepareGitAutomation({ config, task, logger, session }) {
105
+ const enabled = config.git.auto_commit || config.git.auto_push || config.git.auto_pr;
106
+ if (!enabled) return { enabled: false };
107
+
108
+ if (!(await ensureGitRepo())) {
109
+ throw new Error("Git automation requested but current directory is not a git repository");
110
+ }
111
+
112
+ const baseBranch = config.base_branch;
113
+ const autoRebase = config.git.auto_rebase !== false;
114
+ const repoHasCommits = await hasCommits();
115
+
116
+ // New repo without commits: create branch directly (no fetch/sync possible)
117
+ if (!repoHasCommits) {
118
+ const created = buildBranchName(config.git.branch_prefix || "feat/", task);
119
+ // git checkout -b works even without commits (creates orphan-like branch on first commit)
120
+ await createBranch(created);
121
+ logger.info(`New repo — created working branch: ${created}`);
122
+ await addCheckpoint(session, { stage: "git-prep", branch: created, created: true, newRepo: true });
123
+ return { enabled: true, branch: created, baseBranch, autoRebase };
124
+ }
125
+
126
+ await fetchBase(baseBranch).catch(() => {
127
+ // No remote — skip fetch (new project without push)
128
+ logger.info("No remote configured — skipping fetch");
129
+ });
130
+
131
+ let branch;
132
+ try {
133
+ branch = await currentBranch();
134
+ } catch {
135
+ // HEAD exists but branch detection failed — unusual, treat as main
136
+ branch = baseBranch;
137
+ }
138
+
139
+ if (branch === baseBranch) {
140
+ await syncBaseBranch({ baseBranch, autoRebase }).catch(() => {
141
+ // No remote tracking — skip sync for new projects
142
+ });
143
+ const created = buildBranchName(config.git.branch_prefix || "feat/", task);
144
+ await createBranch(created);
145
+ branch = created;
146
+ logger.info(`Created working branch: ${branch}`);
147
+ await addCheckpoint(session, { stage: "git-prep", branch, created: true });
148
+ } else {
149
+ await ensureBranchUpToDateWithBase({ branch, baseBranch, autoRebase }).catch(() => {
150
+ // No remote tracking — skip rebase for new projects
151
+ logger.info("No remote tracking — skipping rebase check");
152
+ });
153
+ await addCheckpoint(session, { stage: "git-prep", branch, created: false });
154
+ }
155
+
156
+ return { enabled: true, branch, baseBranch, autoRebase };
157
+ }
158
+
159
+ export function buildPrBody({ task: _task, stageResults }) {
160
+ const sections = ["Created by Karajan Code."];
161
+
162
+ const approach = stageResults?.planner?.approach;
163
+ if (approach) {
164
+ sections.push("", "## Approach", approach);
165
+ }
166
+
167
+ const steps = stageResults?.planner?.steps;
168
+ if (steps?.length) {
169
+ sections.push("", "## Steps");
170
+ for (let i = 0; i < steps.length; i++) {
171
+ sections.push(`${i + 1}. ${steps[i]}`);
172
+ }
173
+ }
174
+
175
+ const triageSubtasks = stageResults?.triage?.subtasks;
176
+ const shouldDecompose = stageResults?.triage?.shouldDecompose;
177
+ const pendingSubtasks = shouldDecompose && triageSubtasks?.length > 1 ? triageSubtasks.slice(1) : [];
178
+ if (pendingSubtasks.length > 0) {
179
+ sections.push("", "## Pending subtasks", "This PR addresses part of a larger task. The following subtasks were identified but not included:");
180
+ for (const subtask of pendingSubtasks) {
181
+ sections.push(`- [ ] ${subtask}`);
182
+ }
183
+ }
184
+
185
+ return sections.join("\n");
186
+ }
187
+
188
+ /**
189
+ * Create an early PR after the first coder iteration (Karajan CI flow).
190
+ * Commits, pushes, and creates a PR before the reviewer runs.
191
+ * Returns { prNumber, prUrl, commits } or null if nothing to commit.
192
+ */
193
+ export async function earlyPrCreation({ gitCtx, task, logger, session, stageResults = null }) {
194
+ if (!gitCtx?.enabled) return null;
195
+
196
+ const commitMsg = commitMessageFromTask(task);
197
+ const commitResult = await commitAll(commitMsg);
198
+ if (!commitResult.committed) {
199
+ logger.info("earlyPrCreation: no changes to commit");
200
+ return null;
201
+ }
202
+
203
+ const commits = commitResult.commit ? [commitResult.commit] : [];
204
+ await addCheckpoint(session, { stage: "ci-commit", committed: true });
205
+
206
+ await pushBranch(gitCtx.branch);
207
+ await addCheckpoint(session, { stage: "ci-push", branch: gitCtx.branch });
208
+ logger.info(`Pushed branch for early PR: ${gitCtx.branch}`);
209
+
210
+ const body = buildPrBody({ task, stageResults });
211
+ const prUrl = await createPullRequest({
212
+ baseBranch: gitCtx.baseBranch,
213
+ branch: gitCtx.branch,
214
+ title: commitMessageFromTask(task),
215
+ body
216
+ });
217
+ await addCheckpoint(session, { stage: "ci-pr", branch: gitCtx.branch, pr: prUrl });
218
+ logger.info(`Early PR created: ${prUrl}`);
219
+
220
+ // Extract PR number from URL (e.g. https://github.com/owner/repo/pull/42)
221
+ const prNumber = Number.parseInt(prUrl.split("/").pop(), 10) || null;
222
+ return { prNumber, prUrl, commits };
223
+ }
224
+
225
+ /**
226
+ * Incremental push after each coder iteration (Karajan CI flow).
227
+ * Commits and pushes without creating a new PR.
228
+ */
229
+ export async function incrementalPush({ gitCtx, task, logger, session }) {
230
+ if (!gitCtx?.enabled) return null;
231
+
232
+ const commitMsg = commitMessageFromTask(task);
233
+ const commitResult = await commitAll(commitMsg);
234
+ if (!commitResult.committed) {
235
+ logger.info("incrementalPush: no changes to commit");
236
+ return null;
237
+ }
238
+
239
+ const commits = commitResult.commit ? [commitResult.commit] : [];
240
+ await addCheckpoint(session, { stage: "ci-incremental-commit", committed: true });
241
+
242
+ await pushBranch(gitCtx.branch);
243
+ await addCheckpoint(session, { stage: "ci-incremental-push", branch: gitCtx.branch });
244
+ logger.info(`Incremental push: ${gitCtx.branch}`);
245
+
246
+ return { commits };
247
+ }
248
+
249
+ export async function finalizeGitAutomation({ config, gitCtx, task, logger, session, stageResults = null }) {
250
+ if (!gitCtx?.enabled) return { git: "disabled", commits: [] };
251
+
252
+ // Take a snapshot of pending paths BEFORE staging so we can decide
253
+ // whether what's about to be committed is just Karajan scaffolding
254
+ // (in which case we use `chore: scaffold karajan workspace`) or a
255
+ // real, user-visible change (in which case we honour the task's
256
+ // taskType for the Conventional Commits prefix).
257
+ const taskType = stageResults?.triage?.taskType ?? null;
258
+ let pendingPaths = [];
259
+ if (config.git.auto_commit) {
260
+ try {
261
+ pendingPaths = await listPendingPaths();
262
+ } catch { /* best-effort — fall back to default message */ }
263
+ }
264
+
265
+ const commitMsg =
266
+ config.git.commit_message
267
+ || buildFinalizeCommitMessage({ task, taskType, pendingPaths });
268
+
269
+ let committed = false;
270
+ const commits = [];
271
+ if (config.git.auto_commit) {
272
+ // ENV-F1: this path only runs after the pipeline's reviewer approved,
273
+ // so stamp that verdict for the staged diff — the v4 pre-commit gate
274
+ // (when the repo opted in) accepts the pipeline's own commit.
275
+ const commitResult = await commitAll(commitMsg, null, {
276
+ beforeCommit: () => stampStagedVerdict({
277
+ projectDir: config?.projectDir || process.cwd(),
278
+ reviewer: config?.reviewer || "pipeline-reviewer",
279
+ summary: `kj run session ${session?.id || ""}: reviewer approved`.trim(),
280
+ }),
281
+ });
282
+ committed = commitResult.committed;
283
+ if (commitResult.commit) {
284
+ commits.push(commitResult.commit);
285
+ }
286
+ await addCheckpoint(session, { stage: "git-commit", committed });
287
+ logger.info(committed ? "Committed changes" : "No changes to commit");
288
+ }
289
+
290
+ // KJC-BUG-0112: without an `origin` remote (the quickstart scenario:
291
+ // fresh folder + git init) push/PR automation has nothing to talk to —
292
+ // fetchBase used to throw here and escalate to Solomon on EVERY
293
+ // iteration, burning the whole budget on an expected condition.
294
+ const remoteAvailable = (config.git.auto_push || config.git.auto_pr)
295
+ ? await hasRemote()
296
+ : false;
297
+ if ((config.git.auto_push || config.git.auto_pr) && !remoteAvailable) {
298
+ logger.info("No remote configured — skipping push/PR automation");
299
+ await addCheckpoint(session, { stage: "git-push", skipped: "no-remote" });
300
+ }
301
+
302
+ if (remoteAvailable && (config.git.auto_push || config.git.auto_pr)) {
303
+ await fetchBase(gitCtx.baseBranch);
304
+ await ensureBranchUpToDateWithBase({
305
+ branch: gitCtx.branch,
306
+ baseBranch: gitCtx.baseBranch,
307
+ autoRebase: gitCtx.autoRebase
308
+ });
309
+ await addCheckpoint(session, { stage: "git-rebase-check", branch: gitCtx.branch });
310
+ }
311
+
312
+ if (remoteAvailable && (config.git.auto_push || config.git.auto_pr)) {
313
+ await pushBranch(gitCtx.branch);
314
+ await addCheckpoint(session, { stage: "git-push", branch: gitCtx.branch });
315
+ logger.info(`Pushed branch: ${gitCtx.branch}`);
316
+ }
317
+
318
+ let prUrl = session.ci_pr_url || null;
319
+ if (remoteAvailable && config.git.auto_pr && !prUrl) {
320
+ const body = buildPrBody({ task, stageResults });
321
+ prUrl = await createPullRequest({
322
+ baseBranch: gitCtx.baseBranch,
323
+ branch: gitCtx.branch,
324
+ title: commitMessageFromTask(task),
325
+ body
326
+ });
327
+ await addCheckpoint(session, { stage: "git-pr", branch: gitCtx.branch, pr: prUrl });
328
+ logger.info("Pull request created");
329
+ } else if (prUrl) {
330
+ logger.info(`PR already exists (CI flow): ${prUrl}`);
331
+ }
332
+
333
+ return { committed, branch: gitCtx.branch, prUrl, pr: prUrl, commits };
334
+ }
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Per-HU git automation: branch, commit, push, PR per HU story.
3
+ * Called from the HU sub-pipeline wrapper in orchestrator.js.
4
+ */
5
+ import { commitAll, pushBranch, createPullRequest, hasChanges } from "../utils/git.js";
6
+ import { runCommand } from "../utils/process.js";
7
+
8
+ /**
9
+ * Build a git-safe branch name for an HU story.
10
+ * @param {string} prefix - e.g. "feat/"
11
+ * @param {object} story - HU story {id, title}
12
+ * @returns {string}
13
+ */
14
+ export function buildHuBranchName(prefix, story) {
15
+ const baseSlug = String(story.title || story.id || "hu")
16
+ .toLowerCase()
17
+ .replaceAll(/[^a-z0-9]+/g, "-")
18
+ .replaceAll(/^-+|-+$/g, "")
19
+ .slice(0, 40);
20
+ return `${prefix}${story.id}-${baseSlug}`;
21
+ }
22
+
23
+ /**
24
+ * Resolve the base branch for a given HU based on its dependencies.
25
+ * If it has no blocked_by, uses config.base_branch.
26
+ * If it has parents, uses the last-created parent branch (assumes parents ran first).
27
+ *
28
+ * @param {object} story - the HU story
29
+ * @param {Map<string,string>} huBranches - map of huId → branchName (already created)
30
+ * @param {string} baseBranch - config.base_branch fallback
31
+ * @returns {string} base branch name
32
+ */
33
+ export function resolveHuBase(story, huBranches, baseBranch) {
34
+ const parents = story.blocked_by || [];
35
+ if (parents.length === 0) return baseBranch;
36
+ // Walk parents in reverse order of declaration to find the most recent one
37
+ for (let i = parents.length - 1; i >= 0; i--) {
38
+ const parentBranch = huBranches.get(parents[i]);
39
+ if (parentBranch) return parentBranch;
40
+ }
41
+ return baseBranch;
42
+ }
43
+
44
+ /**
45
+ * Resolve to an actually-existing local ref. Tries the preferred branch
46
+ * first, then `main` and `master`, then plain `HEAD` as last resort.
47
+ *
48
+ * Why: N6 plan-flow dogfooding (2026-05-07) on a `git init -q` repo
49
+ * with `init.defaultBranch=master` produced 7 identical warnings:
50
+ * `failed to create branch feat/...-001 from main:
51
+ * fatal: 'main' is not a commit and a branch can't be created`.
52
+ * Every HU then fell back to running on the original branch, which
53
+ * defeats the per-HU isolation the sub-pipeline was supposed to give.
54
+ *
55
+ * The configured base_branch is honoured when it exists; otherwise we
56
+ * pick the most likely default. HEAD always exists once the repo has
57
+ * any commit, so the fallback never throws past the gate.
58
+ *
59
+ * @param {string} preferred
60
+ * @returns {Promise<string>}
61
+ */
62
+ async function resolveExistingBranchRef(preferred) {
63
+ const candidates = [preferred, "main", "master", "HEAD"]
64
+ .filter((c, i, arr) => c && arr.indexOf(c) === i); // unique, truthy
65
+ for (const ref of candidates) {
66
+ const probe = await runCommand("git", ["rev-parse", "--verify", "--quiet", ref], {});
67
+ if (probe.exitCode === 0) return ref;
68
+ }
69
+ return preferred; // give up; caller will surface the original error
70
+ }
71
+
72
+ /**
73
+ * Create a branch for an HU starting from its resolved base.
74
+ * Returns the branch name created (or null if git automation is disabled).
75
+ *
76
+ * @param {object} params
77
+ * @param {object} params.story
78
+ * @param {Map} params.huBranches
79
+ * @param {object} params.config
80
+ * @param {object} params.logger
81
+ * @returns {Promise<string|null>}
82
+ */
83
+ export async function prepareHuBranch({ story, huBranches, config, logger }) {
84
+ if (!config.git?.auto_commit && !config.git?.auto_push && !config.git?.auto_pr) {
85
+ return null;
86
+ }
87
+ const baseBranch = resolveHuBase(story, huBranches, config.base_branch || "main");
88
+ const effectiveBase = await resolveExistingBranchRef(baseBranch);
89
+ if (effectiveBase !== baseBranch) {
90
+ logger.info(`HU git: configured base '${baseBranch}' not found locally — using '${effectiveBase}' instead`);
91
+ }
92
+ const prefix = config.git?.branch_prefix || "feat/";
93
+ const branchName = buildHuBranchName(prefix, story);
94
+
95
+ // Checkout from the resolved base. Use `git checkout -B` to overwrite if rerun.
96
+ const res = await runCommand("git", ["checkout", "-B", branchName, effectiveBase], {});
97
+ if (res.exitCode !== 0) {
98
+ logger.warn(`HU git: failed to create branch ${branchName} from ${effectiveBase}: ${res.stderr}`);
99
+ return null;
100
+ }
101
+ huBranches.set(story.id, branchName);
102
+ logger.info(`HU ${story.id}: branch '${branchName}' from '${effectiveBase}'`);
103
+ return branchName;
104
+ }
105
+
106
+ /**
107
+ * After an HU is approved, commit its changes and optionally push + create PR.
108
+ *
109
+ * @param {object} params
110
+ * @param {object} params.story
111
+ * @param {string} params.branchName
112
+ * @param {object} params.config
113
+ * @param {object} params.logger
114
+ * @returns {Promise<{committed: boolean, pushed: boolean, prUrl: string|null}>}
115
+ */
116
+ export async function finalizeHuCommit({ story, branchName, config, logger, cwd = null }) {
117
+ const result = { committed: false, pushed: false, prUrl: null };
118
+ if (!branchName) return result;
119
+
120
+ const changed = await hasChanges(cwd);
121
+ if (!changed) {
122
+ logger.info(`HU ${story.id}: no changes to commit`);
123
+ return result;
124
+ }
125
+
126
+ const title = story.title || story.id;
127
+ const commitMsg = `feat(${story.id}): ${title}`;
128
+ if (config.git?.auto_commit) {
129
+ const commitRes = await commitAll(commitMsg, cwd);
130
+ if (commitRes) {
131
+ result.committed = true;
132
+ logger.info(`HU ${story.id}: committed on '${branchName}'`);
133
+ }
134
+ }
135
+
136
+ if (config.git?.auto_push && result.committed) {
137
+ try {
138
+ await pushBranch(branchName, cwd);
139
+ result.pushed = true;
140
+ logger.info(`HU ${story.id}: pushed '${branchName}'`);
141
+ } catch (err) {
142
+ logger.warn(`HU ${story.id}: push failed: ${err.message}`);
143
+ }
144
+ }
145
+
146
+ if (config.git?.auto_pr && result.pushed) {
147
+ try {
148
+ const prBody = [
149
+ `## HU ${story.id}: ${title}`,
150
+ "",
151
+ story.certified?.text || "",
152
+ "",
153
+ "### Acceptance criteria",
154
+ ...(story.acceptance_criteria || []).map(c => `- ${c}`)
155
+ ].join("\n");
156
+ const url = await createPullRequest({
157
+ baseBranch: config.base_branch || "main",
158
+ branch: branchName,
159
+ title: commitMsg,
160
+ body: prBody,
161
+ cwd
162
+ });
163
+ result.prUrl = url;
164
+ logger.info(`HU ${story.id}: PR created ${url}`);
165
+ } catch (err) {
166
+ logger.warn(`HU ${story.id}: PR creation failed: ${err.message}`);
167
+ }
168
+ }
169
+
170
+ return result;
171
+ }
@@ -0,0 +1,10 @@
1
+ // Shim de compatibilidad: hu-snapshot vive ahora en karajan-core.
2
+ // Mantenemos esta ruta para que callers internos del CLI (orchestrator,
3
+ // runners) sigan funcionando sin tocar imports.
4
+ export {
5
+ snapshotRefForHu,
6
+ createHuSnapshot,
7
+ hasHuSnapshot,
8
+ restoreHuSnapshot,
9
+ removeHuSnapshot,
10
+ } from "karajan-core/hu-snapshot";
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Golden tasks asserter (KJC-TSK-0374). Parses a `summary.md` produced
3
+ * by a real `kj run` and compares it against a GoldenTask's structural
4
+ * expectations. Pure: no I/O, no subprocess. Subprocess driver lands
5
+ * in PR-3a; the 3 fixtures + baseline + spec land in PR-3b.
6
+ *
7
+ * Three of the five assertion families live here (the ones derivable
8
+ * from summary.md alone): expected_commits_min, expected_audit_status,
9
+ * expected_plan_adherence_min. expected_test_files and
10
+ * allowed_loc_range need filesystem access — PR-3a wires those.
11
+ */
12
+
13
+ import { escapeRegExp } from "../utils/escape-regexp.js";
14
+
15
+ const COMMIT_LINE = /^- `([^`]+)`\s+(.*)$/;
16
+ const SCORE_LINE = /^\*\*Score\*\*:\s*(\d+)\s*\/\s*100/m;
17
+ const AUDIT_ROW = /^\|\s*`audit`\s*\|\s*([^|]+?)\s*\|/m;
18
+
19
+ function extractSection(content, heading) {
20
+ const re = new RegExp(`^## ${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^## |\\Z)`, "m");
21
+ const m = content.match(re);
22
+ return m ? m[1].trim() : "";
23
+ }
24
+
25
+ function parseCommits(content) {
26
+ const section = extractSection(content, "Commits");
27
+ if (!section || /No commits/.test(section)) return [];
28
+ return section
29
+ .split("\n")
30
+ .map((line) => line.match(COMMIT_LINE))
31
+ .filter(Boolean)
32
+ .map(([, hash, message]) => ({ hash, message }));
33
+ }
34
+
35
+ function parseAuditStatus(content) {
36
+ const m = content.match(AUDIT_ROW);
37
+ if (!m) return null;
38
+ const cell = m[1];
39
+ if (/✅|pass/i.test(cell)) return "pass";
40
+ if (/❌|fail/i.test(cell)) return "fail";
41
+ if (/⚠|warn/i.test(cell)) return "warning";
42
+ return null;
43
+ }
44
+
45
+ function parsePlanAdherence(content) {
46
+ const section = extractSection(content, "Plan adherence");
47
+ if (!section) return null;
48
+ const m = section.match(SCORE_LINE);
49
+ if (!m) return null;
50
+ const score = Number(m[1]);
51
+ return Number.isFinite(score) ? score : null;
52
+ }
53
+
54
+ export function parseSummary(content) {
55
+ const text = String(content || "");
56
+ return {
57
+ commits: parseCommits(text),
58
+ auditStatus: parseAuditStatus(text),
59
+ planAdherenceScore: parsePlanAdherence(text),
60
+ };
61
+ }
62
+
63
+ export function assertFromSummary(task, parsed) {
64
+ const failures = [];
65
+
66
+ const fail = (kind, expected, actual, message) => failures.push({ kind, expected, actual, message });
67
+
68
+ if (parsed.commits.length < task.expected_commits_min) {
69
+ fail("commits_min", `>= ${task.expected_commits_min}`, parsed.commits.length,
70
+ `expected at least ${task.expected_commits_min} commit(s); got ${parsed.commits.length}`);
71
+ }
72
+
73
+ if (parsed.auditStatus !== task.expected_audit_status) {
74
+ const got = parsed.auditStatus === null ? "no audit row in summary" : `"${parsed.auditStatus}"`;
75
+ fail("audit_status", task.expected_audit_status, parsed.auditStatus,
76
+ `expected audit "${task.expected_audit_status}"; got ${got}`);
77
+ }
78
+
79
+ if (typeof task.expected_plan_adherence_min === "number") {
80
+ const score = parsed.planAdherenceScore;
81
+ const min = task.expected_plan_adherence_min;
82
+ if (score === null) {
83
+ fail("plan_adherence_missing", `>= ${min}`, null,
84
+ `expected plan adherence >= ${min}; summary has no Plan adherence section`);
85
+ } else if (score < min) {
86
+ fail("plan_adherence_below", `>= ${min}`, score,
87
+ `expected plan adherence >= ${min}; got ${score}`);
88
+ }
89
+ }
90
+
91
+ return { ok: failures.length === 0, failures };
92
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Golden tasks loader (KJC-TSK-0374). Reads + validates JSON files
3
+ * under a directory; aggregates errors; rejects duplicate ids.
4
+ */
5
+
6
+ import fs from "node:fs/promises";
7
+ import path from "node:path";
8
+ import { safeParseGoldenTask } from "./schema.js";
9
+
10
+ export async function loadGoldenTasks(dir) {
11
+ const entries = await fs.readdir(dir, { withFileTypes: true }).catch((err) => {
12
+ throw new Error(`golden tasks directory not readable: ${dir} (${err.code || err.message})`);
13
+ });
14
+ const jsonFiles = entries
15
+ .filter((e) => e.isFile() && e.name.endsWith(".json"))
16
+ .map((e) => path.join(dir, e.name))
17
+ .sort();
18
+
19
+ const tasks = [];
20
+ const errors = [];
21
+ const seenIds = new Map();
22
+
23
+ for (const filePath of jsonFiles) {
24
+ let raw;
25
+ try {
26
+ const content = await fs.readFile(filePath, "utf8");
27
+ raw = JSON.parse(content);
28
+ } catch (err) {
29
+ errors.push(`${path.basename(filePath)}: invalid JSON (${err.message})`);
30
+ continue;
31
+ }
32
+ const result = safeParseGoldenTask(raw);
33
+ if (!result.ok) {
34
+ const summary = result.issues.map((iss) => ` - ${iss.path || "(root)"}: ${iss.message}`).join("\n");
35
+ errors.push(`${path.basename(filePath)}:\n${summary}`);
36
+ continue;
37
+ }
38
+ const existing = seenIds.get(result.task.id);
39
+ if (existing) {
40
+ errors.push(`${path.basename(filePath)}: duplicate id "${result.task.id}" (also in ${existing})`);
41
+ continue;
42
+ }
43
+ seenIds.set(result.task.id, path.basename(filePath));
44
+ tasks.push(result.task);
45
+ }
46
+
47
+ if (errors.length > 0) {
48
+ throw new Error(`golden tasks failed validation:\n${errors.join("\n")}`);
49
+ }
50
+
51
+ return { tasks };
52
+ }