xcoder-dna 0.0.0-stage → 1.3.1

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 (390) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -2
  3. package/dist/agents/ai-chat-debate.d.ts +36 -0
  4. package/dist/agents/ai-chat-debate.js +300 -0
  5. package/dist/agents/ai-chat-report-writer.d.ts +7 -0
  6. package/dist/agents/ai-chat-report-writer.js +100 -0
  7. package/dist/agents/duplicate-detector.d.ts +41 -0
  8. package/dist/agents/duplicate-detector.js +65 -0
  9. package/dist/agents/genesis-agent.d.ts +61 -0
  10. package/dist/agents/genesis-agent.js +340 -0
  11. package/dist/agents/samurai-agent.d.ts +53 -0
  12. package/dist/agents/samurai-agent.js +279 -0
  13. package/dist/agents/sub-agent.d.ts +56 -0
  14. package/dist/agents/sub-agent.js +353 -0
  15. package/dist/backlog/backlog-requirement-validator.d.ts +10 -0
  16. package/dist/backlog/backlog-requirement-validator.js +60 -0
  17. package/dist/backlog/backlog-store.d.ts +29 -0
  18. package/dist/backlog/backlog-store.js +148 -0
  19. package/dist/backlog/po-agent.d.ts +16 -0
  20. package/dist/backlog/po-agent.js +121 -0
  21. package/dist/backlog/types.d.ts +25 -0
  22. package/dist/backlog/types.js +4 -0
  23. package/dist/bench/run.d.ts +11 -0
  24. package/dist/bench/run.js +185 -0
  25. package/dist/bench/types.d.ts +50 -0
  26. package/dist/bench/types.js +1 -0
  27. package/dist/cli/swarm.d.ts +10 -0
  28. package/dist/cli/swarm.js +100 -0
  29. package/dist/cli/task.d.ts +14 -0
  30. package/dist/cli/task.js +121 -0
  31. package/dist/cli/wbc-arg.d.ts +6 -0
  32. package/dist/cli/wbc-arg.js +40 -0
  33. package/dist/cli/wbc.d.ts +45 -0
  34. package/dist/cli/wbc.js +98 -0
  35. package/dist/commands/license.d.ts +9 -0
  36. package/dist/commands/license.js +140 -0
  37. package/dist/commands/release.d.ts +44 -0
  38. package/dist/commands/release.js +180 -0
  39. package/dist/commands/test.d.ts +50 -0
  40. package/dist/commands/test.js +385 -0
  41. package/dist/config/loadConfig.d.ts +82 -0
  42. package/dist/config/loadConfig.js +240 -0
  43. package/dist/config/secure-mode.d.ts +29 -0
  44. package/dist/config/secure-mode.js +63 -0
  45. package/dist/config/user-config.d.ts +39 -0
  46. package/dist/config/user-config.js +202 -0
  47. package/dist/engine/reasoning-engine.d.ts +21 -0
  48. package/dist/engine/reasoning-engine.js +59 -0
  49. package/dist/events/bus.d.ts +22 -0
  50. package/dist/events/bus.js +18 -0
  51. package/dist/index.d.ts +79 -0
  52. package/dist/index.js +77 -0
  53. package/dist/indexing/ignoreRules.d.ts +1 -0
  54. package/dist/indexing/ignoreRules.js +53 -0
  55. package/dist/instance-swarm/instance-swarm-orchestrator.d.ts +57 -0
  56. package/dist/instance-swarm/instance-swarm-orchestrator.js +204 -0
  57. package/dist/instance-swarm/protocol-name-resolver.d.ts +23 -0
  58. package/dist/instance-swarm/protocol-name-resolver.js +64 -0
  59. package/dist/license/gate.d.ts +31 -0
  60. package/dist/license/gate.js +188 -0
  61. package/dist/license/http-client.d.ts +43 -0
  62. package/dist/license/http-client.js +195 -0
  63. package/dist/license/manager.d.ts +39 -0
  64. package/dist/license/manager.js +175 -0
  65. package/dist/license/receipt.d.ts +27 -0
  66. package/dist/license/receipt.js +108 -0
  67. package/dist/license/state-codec.d.ts +72 -0
  68. package/dist/license/state-codec.js +218 -0
  69. package/dist/license/state-paths.d.ts +17 -0
  70. package/dist/license/state-paths.js +64 -0
  71. package/dist/license/store.d.ts +44 -0
  72. package/dist/license/store.js +223 -0
  73. package/dist/license/trust-anchor.d.ts +24 -0
  74. package/dist/license/trust-anchor.js +74 -0
  75. package/dist/license/types.d.ts +34 -0
  76. package/dist/license/types.js +19 -0
  77. package/dist/llm/budget.d.ts +23 -0
  78. package/dist/llm/budget.js +58 -0
  79. package/dist/llm/client.d.ts +53 -0
  80. package/dist/llm/client.js +122 -0
  81. package/dist/llm/factory.d.ts +14 -0
  82. package/dist/llm/factory.js +32 -0
  83. package/dist/orchestrator/defect-logger.d.ts +31 -0
  84. package/dist/orchestrator/defect-logger.js +101 -0
  85. package/dist/orchestrator/defect-manager.d.ts +118 -0
  86. package/dist/orchestrator/defect-manager.js +338 -0
  87. package/dist/orchestrator/defect-migration.d.ts +14 -0
  88. package/dist/orchestrator/defect-migration.js +174 -0
  89. package/dist/orchestrator/defect-store.d.ts +48 -0
  90. package/dist/orchestrator/defect-store.js +76 -0
  91. package/dist/orchestrator/healing.d.ts +14 -0
  92. package/dist/orchestrator/healing.js +11 -0
  93. package/dist/orchestrator/interactive-steering.d.ts +64 -0
  94. package/dist/orchestrator/interactive-steering.js +107 -0
  95. package/dist/orchestrator/interrupt-handler.d.ts +30 -0
  96. package/dist/orchestrator/interrupt-handler.js +70 -0
  97. package/dist/orchestrator/lesson-manager.d.ts +25 -0
  98. package/dist/orchestrator/lesson-manager.js +122 -0
  99. package/dist/orchestrator/progress-summary.d.ts +15 -0
  100. package/dist/orchestrator/progress-summary.js +106 -0
  101. package/dist/orchestrator/reasoning-score.d.ts +49 -0
  102. package/dist/orchestrator/reasoning-score.js +117 -0
  103. package/dist/orchestrator/swarm.d.ts +36 -0
  104. package/dist/orchestrator/swarm.js +77 -0
  105. package/dist/orchestrator/task-factory.d.ts +15 -0
  106. package/dist/orchestrator/task-factory.js +176 -0
  107. package/dist/orchestrator/validation-gate.d.ts +23 -0
  108. package/dist/orchestrator/validation-gate.js +155 -0
  109. package/dist/protocol/react-contract.d.ts +136 -0
  110. package/dist/protocol/react-contract.js +698 -0
  111. package/dist/protocol/wks-protocol-manager.d.ts +22 -0
  112. package/dist/protocol/wks-protocol-manager.js +72 -0
  113. package/dist/sdlc-runtime/conversation-runner.d.ts +8 -0
  114. package/dist/sdlc-runtime/conversation-runner.js +64 -0
  115. package/dist/sdlc-runtime/dag-utils.d.ts +15 -0
  116. package/dist/sdlc-runtime/dag-utils.js +67 -0
  117. package/dist/sdlc-runtime/defect-integration.d.ts +7 -0
  118. package/dist/sdlc-runtime/defect-integration.js +99 -0
  119. package/dist/sdlc-runtime/execution-loop.d.ts +38 -0
  120. package/dist/sdlc-runtime/execution-loop.js +274 -0
  121. package/dist/sdlc-runtime/lesson-recorder.d.ts +9 -0
  122. package/dist/sdlc-runtime/lesson-recorder.js +27 -0
  123. package/dist/sdlc-runtime/plan-initializer.d.ts +47 -0
  124. package/dist/sdlc-runtime/plan-initializer.js +135 -0
  125. package/dist/sdlc-runtime/progress-persister.d.ts +10 -0
  126. package/dist/sdlc-runtime/progress-persister.js +34 -0
  127. package/dist/sdlc-runtime/protocol-loader.d.ts +10 -0
  128. package/dist/sdlc-runtime/protocol-loader.js +21 -0
  129. package/dist/sdlc-runtime/reporting.d.ts +24 -0
  130. package/dist/sdlc-runtime/reporting.js +68 -0
  131. package/dist/sdlc-runtime/sdlc-orchestrator.d.ts +59 -0
  132. package/dist/sdlc-runtime/sdlc-orchestrator.js +170 -0
  133. package/dist/sdlc-runtime/sdlc-skill.d.ts +44 -0
  134. package/dist/sdlc-runtime/sdlc-skill.js +148 -0
  135. package/dist/sdlc-runtime/steering-handler.d.ts +14 -0
  136. package/dist/sdlc-runtime/steering-handler.js +51 -0
  137. package/dist/sdlc-runtime/trace-recorder.d.ts +10 -0
  138. package/dist/sdlc-runtime/trace-recorder.js +7 -0
  139. package/dist/security/index.d.ts +16 -0
  140. package/dist/security/index.js +12 -0
  141. package/dist/security/input-screen.d.ts +30 -0
  142. package/dist/security/input-screen.js +75 -0
  143. package/dist/security/tool-call-guard.d.ts +16 -0
  144. package/dist/security/tool-call-guard.js +163 -0
  145. package/dist/security/untrusted-content.d.ts +34 -0
  146. package/dist/security/untrusted-content.js +63 -0
  147. package/dist/skills/advanced-dfir/SKILL.md +85 -0
  148. package/dist/skills/advanced-pentest-lab/SKILL.md +88 -0
  149. package/dist/skills/analyst/SKILL.md +55 -0
  150. package/dist/skills/architect/SKILL.md +54 -0
  151. package/dist/skills/aws/SKILL.md +92 -0
  152. package/dist/skills/azure/SKILL.md +90 -0
  153. package/dist/skills/bylaw-context.d.ts +45 -0
  154. package/dist/skills/bylaw-context.js +61 -0
  155. package/dist/skills/bylaw-review.d.ts +20 -0
  156. package/dist/skills/bylaw-review.js +101 -0
  157. package/dist/skills/conversation/SKILL.md +29 -0
  158. package/dist/skills/design-patterns/SKILL.md +190 -0
  159. package/dist/skills/devops/SKILL.md +55 -0
  160. package/dist/skills/directives.d.ts +20 -0
  161. package/dist/skills/directives.js +313 -0
  162. package/dist/skills/docker/SKILL.md +76 -0
  163. package/dist/skills/docker-expert/SKILL.md +56 -0
  164. package/dist/skills/enterprise-systems-analyst/SKILL.md +83 -0
  165. package/dist/skills/enterprise-systems-analyst/references/crm.md +41 -0
  166. package/dist/skills/enterprise-systems-analyst/references/erp.md +40 -0
  167. package/dist/skills/enterprise-systems-analyst/references/financial-systems.md +35 -0
  168. package/dist/skills/enterprise-systems-analyst/references/hcm.md +38 -0
  169. package/dist/skills/enterprise-systems-analyst/references/mrp.md +37 -0
  170. package/dist/skills/enterprise-systems-analyst/references/scm.md +32 -0
  171. package/dist/skills/ethical-hacking-methodology/SKILL.md +119 -0
  172. package/dist/skills/externalSkillLoader.d.ts +25 -0
  173. package/dist/skills/externalSkillLoader.js +65 -0
  174. package/dist/skills/externalSkillRegistry.d.ts +33 -0
  175. package/dist/skills/externalSkillRegistry.js +94 -0
  176. package/dist/skills/filesystem-management/SKILL.md +61 -0
  177. package/dist/skills/first-run-seed.d.ts +26 -0
  178. package/dist/skills/first-run-seed.js +75 -0
  179. package/dist/skills/git-vcs/SKILL.md +84 -0
  180. package/dist/skills/kafka/SKILL.md +89 -0
  181. package/dist/skills/kubernetes/SKILL.md +93 -0
  182. package/dist/skills/kubernetes-expert/SKILL.md +54 -0
  183. package/dist/skills/openshift/SKILL.md +93 -0
  184. package/dist/skills/pentester/SKILL.md +59 -0
  185. package/dist/skills/performance-tester/SKILL.md +57 -0
  186. package/dist/skills/playwright-ui-tester/SKILL.md +67 -0
  187. package/dist/skills/programmer/SKILL.md +58 -0
  188. package/dist/skills/project-scaffolding/SKILL.md +133 -0
  189. package/dist/skills/qa-engineer/SKILL.md +91 -0
  190. package/dist/skills/rca/SKILL.md +58 -0
  191. package/dist/skills/redhat/SKILL.md +92 -0
  192. package/dist/skills/rosa/SKILL.md +80 -0
  193. package/dist/skills/scrum-framework/SKILL.md +74 -0
  194. package/dist/skills/scrum-framework/references/artifacts_and_quality.md +79 -0
  195. package/dist/skills/scrum-framework/references/roles_and_events.md +105 -0
  196. package/dist/skills/scrum-master-agent/SKILL.md +74 -0
  197. package/dist/skills/scrum-master-agent/references/behaviors.md +56 -0
  198. package/dist/skills/sdlc-skill.d.ts +1 -0
  199. package/dist/skills/sdlc-skill.js +4 -0
  200. package/dist/skills/secops/SKILL.md +52 -0
  201. package/dist/skills/secure-architect.bylaws.d.ts +68 -0
  202. package/dist/skills/secure-architect.bylaws.js +525 -0
  203. package/dist/skills/seed-skills.d.ts +48 -0
  204. package/dist/skills/seed-skills.js +213 -0
  205. package/dist/skills/skill-authoring/SKILL.md +123 -0
  206. package/dist/skills/skill-header.d.ts +51 -0
  207. package/dist/skills/skill-header.js +163 -0
  208. package/dist/skills/skill-path-guard.d.ts +41 -0
  209. package/dist/skills/skill-path-guard.js +95 -0
  210. package/dist/skills/skillRouter.d.ts +51 -0
  211. package/dist/skills/skillRouter.js +90 -0
  212. package/dist/skills/skills-root.d.ts +64 -0
  213. package/dist/skills/skills-root.js +168 -0
  214. package/dist/skills/software-architect/SKILL.md +77 -0
  215. package/dist/skills/software-engineer/SKILL.md +74 -0
  216. package/dist/skills/solid-principles/SKILL.md +94 -0
  217. package/dist/skills/task-planning/SKILL.md +115 -0
  218. package/dist/skills/tester/SKILL.md +54 -0
  219. package/dist/skills/ubuntu/SKILL.md +87 -0
  220. package/dist/skills/ui-ux-design/SKILL.md +114 -0
  221. package/dist/skills/workspace-context/SKILL.md +103 -0
  222. package/dist/sprint/controller.d.ts +37 -0
  223. package/dist/sprint/controller.js +220 -0
  224. package/dist/sprint/dag-builder.d.ts +14 -0
  225. package/dist/sprint/dag-builder.js +105 -0
  226. package/dist/sprint/reporter.d.ts +11 -0
  227. package/dist/sprint/reporter.js +97 -0
  228. package/dist/sprint/state-store.d.ts +10 -0
  229. package/dist/sprint/state-store.js +71 -0
  230. package/dist/sprint/types.d.ts +24 -0
  231. package/dist/sprint/types.js +4 -0
  232. package/dist/store/file-version-store.d.ts +24 -0
  233. package/dist/store/file-version-store.js +73 -0
  234. package/dist/store/task-store.d.ts +90 -0
  235. package/dist/store/task-store.js +166 -0
  236. package/dist/task-ingest/architect-detailer.d.ts +43 -0
  237. package/dist/task-ingest/architect-detailer.js +141 -0
  238. package/dist/task-ingest/detail-schema.d.ts +9 -0
  239. package/dist/task-ingest/detail-schema.js +195 -0
  240. package/dist/task-ingest/detailed-run.d.ts +36 -0
  241. package/dist/task-ingest/detailed-run.js +108 -0
  242. package/dist/task-ingest/extract-id.d.ts +9 -0
  243. package/dist/task-ingest/extract-id.js +24 -0
  244. package/dist/task-ingest/index.d.ts +23 -0
  245. package/dist/task-ingest/index.js +14 -0
  246. package/dist/task-ingest/ingest.d.ts +45 -0
  247. package/dist/task-ingest/ingest.js +163 -0
  248. package/dist/task-ingest/list-ingested.d.ts +13 -0
  249. package/dist/task-ingest/list-ingested.js +30 -0
  250. package/dist/task-ingest/pending-filter.d.ts +30 -0
  251. package/dist/task-ingest/pending-filter.js +59 -0
  252. package/dist/task-ingest/scanner.d.ts +56 -0
  253. package/dist/task-ingest/scanner.js +216 -0
  254. package/dist/task-ingest/source-reader.d.ts +25 -0
  255. package/dist/task-ingest/source-reader.js +93 -0
  256. package/dist/task-ingest/spec-builder.d.ts +34 -0
  257. package/dist/task-ingest/spec-builder.js +89 -0
  258. package/dist/task-ingest/wbs-extract.d.ts +50 -0
  259. package/dist/task-ingest/wbs-extract.js +226 -0
  260. package/dist/task-ingest/wbs-parser.d.ts +36 -0
  261. package/dist/task-ingest/wbs-parser.js +170 -0
  262. package/dist/tools/apiTestTool.d.ts +37 -0
  263. package/dist/tools/apiTestTool.js +128 -0
  264. package/dist/tools/ast-tools.d.ts +183 -0
  265. package/dist/tools/ast-tools.js +853 -0
  266. package/dist/tools/browse-tool.d.ts +105 -0
  267. package/dist/tools/browse-tool.js +394 -0
  268. package/dist/tools/credential.d.ts +17 -0
  269. package/dist/tools/credential.js +32 -0
  270. package/dist/tools/dependency-graph.d.ts +23 -0
  271. package/dist/tools/dependency-graph.js +164 -0
  272. package/dist/tools/edit-tool.d.ts +34 -0
  273. package/dist/tools/edit-tool.js +95 -0
  274. package/dist/tools/file-header-manager.d.ts +27 -0
  275. package/dist/tools/file-header-manager.js +153 -0
  276. package/dist/tools/fs-tools.d.ts +154 -0
  277. package/dist/tools/fs-tools.js +337 -0
  278. package/dist/tools/git-tools.d.ts +79 -0
  279. package/dist/tools/git-tools.js +348 -0
  280. package/dist/tools/github-tool.d.ts +48 -0
  281. package/dist/tools/github-tool.js +147 -0
  282. package/dist/tools/globTool.d.ts +20 -0
  283. package/dist/tools/globTool.js +34 -0
  284. package/dist/tools/grepTool.d.ts +19 -0
  285. package/dist/tools/grepTool.js +44 -0
  286. package/dist/tools/index-freshness.d.ts +58 -0
  287. package/dist/tools/index-freshness.js +190 -0
  288. package/dist/tools/index-glob.d.ts +48 -0
  289. package/dist/tools/index-glob.js +175 -0
  290. package/dist/tools/load-skill-tool.d.ts +15 -0
  291. package/dist/tools/load-skill-tool.js +114 -0
  292. package/dist/tools/patch-tools.d.ts +58 -0
  293. package/dist/tools/patch-tools.js +153 -0
  294. package/dist/tools/playwright-tool.d.ts +66 -0
  295. package/dist/tools/playwright-tool.js +121 -0
  296. package/dist/tools/project-detect.d.ts +20 -0
  297. package/dist/tools/project-detect.js +87 -0
  298. package/dist/tools/prompt-guidance.d.ts +22 -0
  299. package/dist/tools/prompt-guidance.js +23 -0
  300. package/dist/tools/scheduleTool.d.ts +19 -0
  301. package/dist/tools/scheduleTool.js +181 -0
  302. package/dist/tools/search-tools.d.ts +27 -0
  303. package/dist/tools/search-tools.js +78 -0
  304. package/dist/tools/sed-tool.d.ts +66 -0
  305. package/dist/tools/sed-tool.js +402 -0
  306. package/dist/tools/shell-result.d.ts +11 -0
  307. package/dist/tools/shell-result.js +1 -0
  308. package/dist/tools/shell-tool.d.ts +45 -0
  309. package/dist/tools/shell-tool.js +141 -0
  310. package/dist/tools/siteCrawlerTool.d.ts +32 -0
  311. package/dist/tools/siteCrawlerTool.js +205 -0
  312. package/dist/tools/tool-registry.d.ts +67 -0
  313. package/dist/tools/tool-registry.js +596 -0
  314. package/dist/tools/validate-tool.d.ts +23 -0
  315. package/dist/tools/validate-tool.js +201 -0
  316. package/dist/tools/workspace-index.d.ts +46 -0
  317. package/dist/tools/workspace-index.js +173 -0
  318. package/dist/types.d.ts +222 -0
  319. package/dist/types.js +7 -0
  320. package/dist/updater/index.d.ts +14 -0
  321. package/dist/updater/index.js +120 -0
  322. package/dist/util/banner.d.ts +25 -0
  323. package/dist/util/banner.js +140 -0
  324. package/dist/util/command-suggester.d.ts +6 -0
  325. package/dist/util/command-suggester.js +25 -0
  326. package/dist/util/confirm-interrupt.d.ts +10 -0
  327. package/dist/util/confirm-interrupt.js +31 -0
  328. package/dist/util/continue-trigger.d.ts +11 -0
  329. package/dist/util/continue-trigger.js +20 -0
  330. package/dist/util/env-info.d.ts +18 -0
  331. package/dist/util/env-info.js +37 -0
  332. package/dist/util/file-access-log.d.ts +35 -0
  333. package/dist/util/file-access-log.js +140 -0
  334. package/dist/util/footer-manager.d.ts +124 -0
  335. package/dist/util/footer-manager.js +195 -0
  336. package/dist/util/footer-renderer.d.ts +67 -0
  337. package/dist/util/footer-renderer.js +319 -0
  338. package/dist/util/footer-state.d.ts +34 -0
  339. package/dist/util/footer-state.js +18 -0
  340. package/dist/util/footer-text.d.ts +51 -0
  341. package/dist/util/footer-text.js +74 -0
  342. package/dist/util/ids.d.ts +1 -0
  343. package/dist/util/ids.js +4 -0
  344. package/dist/util/levenshtein.d.ts +6 -0
  345. package/dist/util/levenshtein.js +34 -0
  346. package/dist/util/logger.d.ts +10 -0
  347. package/dist/util/logger.js +41 -0
  348. package/dist/util/logs.d.ts +26 -0
  349. package/dist/util/logs.js +88 -0
  350. package/dist/util/output-handler.d.ts +89 -0
  351. package/dist/util/output-handler.js +193 -0
  352. package/dist/util/output-interceptor.d.ts +18 -0
  353. package/dist/util/output-interceptor.js +49 -0
  354. package/dist/util/output-paths.d.ts +43 -0
  355. package/dist/util/output-paths.js +121 -0
  356. package/dist/util/package-json.d.ts +6 -0
  357. package/dist/util/package-json.js +36 -0
  358. package/dist/util/process-kill.d.ts +27 -0
  359. package/dist/util/process-kill.js +148 -0
  360. package/dist/util/protocol-error-logger.d.ts +33 -0
  361. package/dist/util/protocol-error-logger.js +73 -0
  362. package/dist/util/redact.d.ts +25 -0
  363. package/dist/util/redact.js +103 -0
  364. package/dist/util/scroll-region-guard.d.ts +33 -0
  365. package/dist/util/scroll-region-guard.js +63 -0
  366. package/dist/util/spinner.d.ts +15 -0
  367. package/dist/util/spinner.js +49 -0
  368. package/dist/util/terminal-output.d.ts +34 -0
  369. package/dist/util/terminal-output.js +1 -0
  370. package/dist/util/terminal-silent.d.ts +6 -0
  371. package/dist/util/terminal-silent.js +20 -0
  372. package/dist/util/terminal.d.ts +56 -0
  373. package/dist/util/terminal.js +124 -0
  374. package/dist/util/text-sanitize.d.ts +8 -0
  375. package/dist/util/text-sanitize.js +45 -0
  376. package/dist/util/thinking-spinner.d.ts +27 -0
  377. package/dist/util/thinking-spinner.js +189 -0
  378. package/dist/util/tool-error-logger.d.ts +33 -0
  379. package/dist/util/tool-error-logger.js +77 -0
  380. package/dist/util/tty.d.ts +13 -0
  381. package/dist/util/tty.js +16 -0
  382. package/dist/util/xcoder-paths.d.ts +56 -0
  383. package/dist/util/xcoder-paths.js +63 -0
  384. package/dist/version.d.ts +2 -0
  385. package/dist/version.js +4 -0
  386. package/dist/worker-agent/to-subtask-node.d.ts +35 -0
  387. package/dist/worker-agent/to-subtask-node.js +41 -0
  388. package/dist/worker-agent/worker-orchestrator.d.ts +104 -0
  389. package/dist/worker-agent/worker-orchestrator.js +201 -0
  390. package/package.json +38 -3
@@ -0,0 +1,121 @@
1
+ // xcoder:version 2 | xcoder:task task-c49600 | xcoder:updated 2026-08-13T13:52:10.297Z | xcoder:subtask code-st-6d79ef
2
+ import { shortId } from "../util/ids.js";
3
+ import { log } from "../util/logger.js";
4
+ import { SubAgent } from "../agents/sub-agent.js";
5
+ import { createLlmClient } from "../llm/factory.js";
6
+ import { BA_REQUIREMENTS_DIRECTIVE } from "../skills/directives.js";
7
+ // ---------------------------------------------------------------------------
8
+ // PO Agent — thin SubAgent wrapper for backlog pick
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Runs a one-shot business-analyst Sub Agent (Product Owner) to select
12
+ * the highest-priority item from the provided backlog list.
13
+ *
14
+ * Follows the exact pattern of `src/ba-runner.ts`: creates a standalone
15
+ * SubAgent (no SdlcOrchestrator DAG), runs a single subtask, parses the
16
+ * deliverable. On LLM failure, falls back to deterministic
17
+ * oldest-open-item selection and logs a warning.
18
+ */
19
+ export async function runPoPick(root, items, model) {
20
+ // Guard: only consider open items not already in a sprint.
21
+ const eligibleItems = items.filter((it) => it.status === "open" && it.sprintId === null);
22
+ if (eligibleItems.length === 0) {
23
+ throw new Error("No eligible backlog items — all open items are either in a sprint or have a different status.");
24
+ }
25
+ // Build a concise table for the LLM.
26
+ const itemTable = eligibleItems
27
+ .map((it) => `- id: ${it.id} | priority: ${it.priority ?? "(none)"} | title: ${it.title}`)
28
+ .join("\n");
29
+ const goal = `Select the highest-priority backlog item from the list below for the next implementation sprint. ` +
30
+ `Consider explicit priority labels, title urgency, and implicit risk/dependency signals. ` +
31
+ `Return ONLY a JSON object with keys: selectedId, title, reasoning (one sentence). ` +
32
+ `Backlog items:\n${itemTable}`;
33
+ // Create an LlmClient.
34
+ let llm;
35
+ try {
36
+ llm = createLlmClient("sub_agent", { model });
37
+ }
38
+ catch (e) {
39
+ log.fail(`PO Agent: failed to create LLM client: ${e.message}`);
40
+ return deterministicFallback(eligibleItems);
41
+ }
42
+ // Build a one-node SubtaskNode for the business analyst.
43
+ const nodeId = `po-${shortId("st")}`;
44
+ const subtaskNode = {
45
+ id: nodeId,
46
+ stage: "requirements",
47
+ role: "business-analyst",
48
+ engine: "react-v1",
49
+ dependsOn: [],
50
+ goal,
51
+ upstreamContext: {
52
+ backlogItems: eligibleItems.map(({ id, title, priority, status }) => ({
53
+ id,
54
+ title,
55
+ priority,
56
+ status,
57
+ })),
58
+ },
59
+ deliverableSpec: "A JSON object: { selectedId: string, title: string, reasoning: string }.",
60
+ acceptanceCriteria: [
61
+ {
62
+ id: "AC1",
63
+ type: "schema",
64
+ description: "selectedId matches one of the provided backlog item ids.",
65
+ },
66
+ {
67
+ id: "AC2",
68
+ type: "schema",
69
+ description: "reasoning is a non-empty string explaining the choice.",
70
+ },
71
+ ],
72
+ status: "ready",
73
+ healing: { attempts: 0, maxAttempts: 1, log: [] },
74
+ };
75
+ // Create the SubAgent with the BA requirements directive.
76
+ const taskId = shortId("task");
77
+ const agent = new SubAgent({
78
+ taskId,
79
+ workspaceRoot: root,
80
+ llm,
81
+ directiveOverride: BA_REQUIREMENTS_DIRECTIVE,
82
+ });
83
+ // Run the agent and parse the result.
84
+ try {
85
+ const result = await agent.run(subtaskNode);
86
+ const delivered = typeof result.deliverable === "string"
87
+ ? JSON.parse(result.deliverable)
88
+ : result.deliverable;
89
+ if (delivered &&
90
+ typeof delivered === "object" &&
91
+ "selectedId" in delivered &&
92
+ "title" in delivered &&
93
+ "reasoning" in delivered) {
94
+ const d = delivered;
95
+ // Validate that selectedId actually exists in the provided items.
96
+ if (eligibleItems.some((it) => it.id === d.selectedId)) {
97
+ return d;
98
+ }
99
+ log.fail(`PO Agent selected id "${d.selectedId}" which is not in the provided list — falling back to deterministic.`);
100
+ return deterministicFallback(eligibleItems);
101
+ }
102
+ log.fail("PO Agent returned an unrecognised deliverable shape — falling back to deterministic.");
103
+ return deterministicFallback(eligibleItems);
104
+ }
105
+ catch (e) {
106
+ log.fail(`PO Agent run threw unexpectedly: ${e.message}`);
107
+ return deterministicFallback(eligibleItems);
108
+ }
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Deterministic fallback — oldest open item
112
+ // ---------------------------------------------------------------------------
113
+ function deterministicFallback(items) {
114
+ log.dim("PO Agent: using deterministic oldest-first fallback.");
115
+ const oldest = items[0]; // items are already sorted by createdAt asc.
116
+ return {
117
+ selectedId: oldest.id,
118
+ title: oldest.title,
119
+ reasoning: `Deterministic fallback: selected oldest open item (${oldest.id}).`,
120
+ };
121
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Backlog data model types — see `.xcoder/design/backlog-management-design.md`.
3
+ */
4
+ export type BacklogStatus = "open" | "in-progress" | "done";
5
+ export interface BacklogItem {
6
+ id: string;
7
+ title: string;
8
+ description: string;
9
+ status: BacklogStatus;
10
+ priority?: string;
11
+ taskId?: string;
12
+ sprintId: string | null;
13
+ blockedReason: string | null;
14
+ sprintRunAt: string | null;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ }
18
+ export interface BacklogStoreMeta {
19
+ nextId: number;
20
+ }
21
+ /** Full shape of _backlog.json on disk */
22
+ export interface BacklogFile {
23
+ meta: BacklogStoreMeta;
24
+ items: BacklogItem[];
25
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Backlog data model types — see `.xcoder/design/backlog-management-design.md`.
3
+ */
4
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { BenchReport } from "./types.js";
2
+ export interface RunBenchmarkOptions {
3
+ fixturesDir: string;
4
+ outFile: string;
5
+ concurrency: number;
6
+ model?: string;
7
+ keepWorkspaces: boolean;
8
+ }
9
+ export declare function runBenchmark(opts: RunBenchmarkOptions): Promise<BenchReport>;
10
+ /** Compares this report's average reasoning score per fixture against a previous report — the actual "is this getting better over time" signal. */
11
+ export declare function compareReports(currentFile: string, previousFile: string): Promise<void>;
@@ -0,0 +1,185 @@
1
+ // xcoder:version 2 | xcoder:task task-c49600 | xcoder:updated 2026-08-13T13:52:44.290Z | xcoder:subtask code-st-6d79ef
2
+ import { promises as fs } from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { SdlcOrchestrator } from "../sdlc-runtime/sdlc-orchestrator.js";
6
+ import { buildTaskSpec } from "../orchestrator/task-factory.js";
7
+ import { buildIndex } from "../tools/workspace-index.js";
8
+ import { createLlmClient } from "../llm/factory.js";
9
+ /**
10
+ * WHY THIS EXISTS: "does this directive/skill/prompt change actually help"
11
+ * is otherwise a question you can only answer by vibes after running a
12
+ * task by hand a few times. This runs the same fixture set against the
13
+ * real orchestrator and the real model, and reports the four numbers that
14
+ * matter for comparing runs over time: how long it took (wall clock), how
15
+ * much it cost (tokens), how much back-and-forth it took (iterations), and
16
+ * whether it actually passed (status + reasoning score).
17
+ *
18
+ * COST WARNING: every fixture is a real Anthropic API call sequence, same
19
+ * as running `xcoder` normally. This is not free or instant to run.
20
+ */
21
+ async function loadFixtures(dir) {
22
+ const files = (await fs.readdir(dir)).filter((f) => f.endsWith(".json"));
23
+ const fixtures = [];
24
+ for (const file of files) {
25
+ const raw = await fs.readFile(path.join(dir, file), "utf8");
26
+ fixtures.push(JSON.parse(raw));
27
+ }
28
+ return fixtures;
29
+ }
30
+ async function seedWorkspace(root, seedFiles) {
31
+ if (!seedFiles)
32
+ return;
33
+ for (const [relPath, content] of Object.entries(seedFiles)) {
34
+ const full = path.join(root, relPath);
35
+ await fs.mkdir(path.dirname(full), { recursive: true });
36
+ await fs.writeFile(full, content, "utf8");
37
+ }
38
+ }
39
+ function sumTokens(a, b) {
40
+ return { inputTokens: a.inputTokens + b.inputTokens, outputTokens: a.outputTokens + b.outputTokens };
41
+ }
42
+ function summarizeRun(run, wallTimeMs, fixtureName, workspace) {
43
+ const subtasks = run.dag.map((n) => ({
44
+ subtaskId: n.id,
45
+ role: n.role,
46
+ status: n.status,
47
+ iterations: n.result?.iterations ?? 0,
48
+ tokenUsage: n.result?.tokenUsage ?? { inputTokens: 0, outputTokens: 0 },
49
+ reasoningScore: n.reasoningScore?.score ?? null,
50
+ healingAttempts: n.healing.attempts,
51
+ }));
52
+ const totalIterations = subtasks.reduce((sum, s) => sum + s.iterations, 0);
53
+ const scored = subtasks.filter((s) => s.reasoningScore !== null);
54
+ const avgReasoningScore = scored.length ? scored.reduce((sum, s) => sum + (s.reasoningScore ?? 0), 0) / scored.length : null;
55
+ return {
56
+ fixture: fixtureName,
57
+ workspace,
58
+ wallTimeMs,
59
+ status: run.status,
60
+ totalTokenUsage: run.totalTokenUsage,
61
+ totalIterations,
62
+ subtaskCount: subtasks.length,
63
+ escalationCount: run.escalations.length,
64
+ avgReasoningScore,
65
+ subtasks,
66
+ };
67
+ }
68
+ export async function runBenchmark(opts) {
69
+ const fixtures = await loadFixtures(opts.fixturesDir);
70
+ if (fixtures.length === 0) {
71
+ throw new Error(`no fixtures found in ${opts.fixturesDir} (expected *.json files matching BenchFixture)`);
72
+ }
73
+ const results = [];
74
+ let tokenTotal = { inputTokens: 0, outputTokens: 0 };
75
+ for (const fixture of fixtures) {
76
+ console.log(`\n=== ${fixture.name} ===`);
77
+ const scratchRoot = await fs.mkdtemp(path.join(os.tmpdir(), `xcoder-bench-${fixture.name}-`));
78
+ try {
79
+ await seedWorkspace(scratchRoot, fixture.seedFiles);
80
+ await buildIndex(scratchRoot);
81
+ let llm;
82
+ try {
83
+ llm = createLlmClient("orchestrator", { model: opts.model });
84
+ }
85
+ catch (e) {
86
+ results.push({
87
+ fixture: fixture.name,
88
+ workspace: scratchRoot,
89
+ wallTimeMs: 0,
90
+ status: "error",
91
+ totalTokenUsage: { inputTokens: 0, outputTokens: 0 },
92
+ totalIterations: 0,
93
+ subtaskCount: 0,
94
+ escalationCount: 0,
95
+ avgReasoningScore: null,
96
+ subtasks: [],
97
+ error: e.message,
98
+ });
99
+ continue;
100
+ }
101
+ const spec = buildTaskSpec(fixture.task, { code: fixture.code, design: fixture.design, defectDetail: fixture.defect, url: fixture.url, credentialRef: fixture.credentialRef }, { maxHealingAttempts: fixture.maxHealing ?? 2, concurrency: fixture.concurrency ?? opts.concurrency });
102
+ const orchestrator = new SdlcOrchestrator({
103
+ workspaceRoot: scratchRoot,
104
+ llm,
105
+ concurrency: fixture.concurrency ?? opts.concurrency,
106
+ });
107
+ const start = Date.now();
108
+ const run = await orchestrator.run(spec);
109
+ const wallTimeMs = Date.now() - start;
110
+ const result = summarizeRun(run, wallTimeMs, fixture.name, scratchRoot);
111
+ results.push(result);
112
+ tokenTotal = sumTokens(tokenTotal, result.totalTokenUsage);
113
+ }
114
+ catch (e) {
115
+ results.push({
116
+ fixture: fixture.name,
117
+ workspace: scratchRoot,
118
+ wallTimeMs: 0,
119
+ status: "error",
120
+ totalTokenUsage: { inputTokens: 0, outputTokens: 0 },
121
+ totalIterations: 0,
122
+ subtaskCount: 0,
123
+ escalationCount: 0,
124
+ avgReasoningScore: null,
125
+ subtasks: [],
126
+ error: e.message,
127
+ });
128
+ }
129
+ finally {
130
+ if (!opts.keepWorkspaces) {
131
+ await fs.rm(scratchRoot, { recursive: true, force: true });
132
+ }
133
+ else {
134
+ console.log(` workspace kept at: ${scratchRoot}`);
135
+ }
136
+ }
137
+ }
138
+ const report = {
139
+ runAt: new Date().toISOString(),
140
+ model: opts.model ?? process.env.XCODER_MODEL ?? "claude-sonnet-5",
141
+ results,
142
+ };
143
+ await fs.mkdir(path.dirname(opts.outFile), { recursive: true });
144
+ await fs.writeFile(opts.outFile, JSON.stringify(report, null, 2), "utf8");
145
+ printReportTable(report);
146
+ console.log(`\nTotal tokens this run: ${tokenTotal.inputTokens} in / ${tokenTotal.outputTokens} out`);
147
+ console.log(`Report written to: ${opts.outFile}`);
148
+ return report;
149
+ }
150
+ function printReportTable(report) {
151
+ console.log("\n" + "Task".padEnd(28) + "Status".padEnd(12) + "Time".padEnd(10) + "Tokens (in/out)".padEnd(20) + "Iters".padEnd(8) + "Score");
152
+ console.log("-".repeat(90));
153
+ for (const r of report.results) {
154
+ const time = r.error ? "—" : `${(r.wallTimeMs / 1000).toFixed(1)}s`;
155
+ const tokens = r.error ? "—" : `${r.totalTokenUsage.inputTokens}/${r.totalTokenUsage.outputTokens}`;
156
+ const score = r.avgReasoningScore !== null ? r.avgReasoningScore.toFixed(0) : "—";
157
+ console.log(r.fixture.padEnd(28) +
158
+ (r.error ? "error" : r.status).padEnd(12) +
159
+ time.padEnd(10) +
160
+ tokens.padEnd(20) +
161
+ String(r.totalIterations).padEnd(8) +
162
+ score);
163
+ if (r.error)
164
+ console.log(` ! ${r.error}`);
165
+ }
166
+ }
167
+ /** Compares this report's average reasoning score per fixture against a previous report — the actual "is this getting better over time" signal. */
168
+ export async function compareReports(currentFile, previousFile) {
169
+ const current = JSON.parse(await fs.readFile(currentFile, "utf8"));
170
+ const previous = JSON.parse(await fs.readFile(previousFile, "utf8"));
171
+ console.log(`\nComparing ${path.basename(currentFile)} vs ${path.basename(previousFile)}:\n`);
172
+ for (const cur of current.results) {
173
+ const prev = previous.results.find((p) => p.fixture === cur.fixture);
174
+ if (!prev) {
175
+ console.log(`${cur.fixture.padEnd(28)} (no previous run to compare)`);
176
+ continue;
177
+ }
178
+ const scoreDelta = (cur.avgReasoningScore ?? 0) - (prev.avgReasoningScore ?? 0);
179
+ const tokenDelta = cur.totalTokenUsage.inputTokens + cur.totalTokenUsage.outputTokens - (prev.totalTokenUsage.inputTokens + prev.totalTokenUsage.outputTokens);
180
+ const iterDelta = cur.totalIterations - prev.totalIterations;
181
+ const arrow = (n) => (n > 0 ? "▲" : n < 0 ? "▼" : "=");
182
+ console.log(`${cur.fixture.padEnd(28)} score ${arrow(scoreDelta)}${Math.abs(scoreDelta).toFixed(0)} ` +
183
+ `tokens ${arrow(tokenDelta)}${Math.abs(tokenDelta)} iterations ${arrow(iterDelta)}${Math.abs(iterDelta)}`);
184
+ }
185
+ }
@@ -0,0 +1,50 @@
1
+ import type { TokenUsage } from "../types.js";
2
+ /**
3
+ * A benchmark fixture is a self-contained, reproducible task: an optional
4
+ * set of seed files written into a fresh scratch workspace before the run,
5
+ * plus the same inputs `xcoder`'s CLI would take. Fixtures are checked into
6
+ * `src/bench/fixtures/*.json` so a benchmark run is exactly reproducible
7
+ * run to run — the only thing that varies is the model's behavior, which
8
+ * is the whole point of running it repeatedly over time.
9
+ */
10
+ export interface BenchFixture {
11
+ name: string;
12
+ description: string;
13
+ /** relPath -> file content, written into the scratch workspace before the run */
14
+ seedFiles?: Record<string, string>;
15
+ task: string;
16
+ code?: string;
17
+ design?: string;
18
+ defect?: string;
19
+ url?: string;
20
+ credentialRef?: string;
21
+ concurrency?: number;
22
+ maxHealing?: number;
23
+ }
24
+ export interface SubtaskBenchResult {
25
+ subtaskId: string;
26
+ role: string;
27
+ status: string;
28
+ iterations: number;
29
+ tokenUsage: TokenUsage;
30
+ reasoningScore: number | null;
31
+ healingAttempts: number;
32
+ }
33
+ export interface BenchResult {
34
+ fixture: string;
35
+ workspace: string;
36
+ wallTimeMs: number;
37
+ status: string;
38
+ totalTokenUsage: TokenUsage;
39
+ totalIterations: number;
40
+ subtaskCount: number;
41
+ escalationCount: number;
42
+ avgReasoningScore: number | null;
43
+ subtasks: SubtaskBenchResult[];
44
+ error?: string;
45
+ }
46
+ export interface BenchReport {
47
+ runAt: string;
48
+ model: string;
49
+ results: BenchResult[];
50
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import { Command } from "commander";
2
+ /**
3
+ * Register the `xcoder swarm` subcommand.
4
+ *
5
+ * Runs an instance swarm: multiple SubAgents dispatched concurrently
6
+ * against a goal, with a protocol section injected from wks_protocol.md.
7
+ * Includes a master spinner for the overall run, per-worker lifecycle
8
+ * callbacks, and a color-coded summary printed on completion.
9
+ */
10
+ export declare function registerSwarmCommand(parent: Command): void;
@@ -0,0 +1,100 @@
1
+ import path from "node:path";
2
+ import { createLlmClient } from "../llm/factory.js";
3
+ import { InstanceSwarmOrchestrator, } from "../instance-swarm/instance-swarm-orchestrator.js";
4
+ import { getOrBuildIndex } from "../tools/workspace-index.js";
5
+ import { log } from "../util/logger.js";
6
+ import { createSpinner } from "../util/spinner.js";
7
+ import { printSwarmSummary } from "../util/terminal.js";
8
+ /**
9
+ * Register the `xcoder swarm` subcommand.
10
+ *
11
+ * Runs an instance swarm: multiple SubAgents dispatched concurrently
12
+ * against a goal, with a protocol section injected from wks_protocol.md.
13
+ * Includes a master spinner for the overall run, per-worker lifecycle
14
+ * callbacks, and a color-coded summary printed on completion.
15
+ */
16
+ export function registerSwarmCommand(parent) {
17
+ parent
18
+ .command("swarm <goal...>")
19
+ .description("Run an instance swarm: multiple SubAgents dispatched concurrently against a goal, with a protocol section injected.")
20
+ .option("--protocol <name>", "protocol name (coder, tester, architect, ui-ux, secops, devops)")
21
+ .option("-m, --model <name>", "override the LLM model (default: env XCODER_MODEL or deepseek-chat)")
22
+ .option("-w, --workspace <dir>", "workspace root", process.cwd())
23
+ .option("--concurrency <n>", "number of concurrent SubAgents", "1")
24
+ .option("--max-iterations <n>", "max iterations per SubAgent", "200")
25
+ .action(async (goalParts, opts) => {
26
+ const root = path.resolve(opts.workspace);
27
+ const goal = goalParts.join(" ");
28
+ if (!opts.protocol) {
29
+ log.fail("--protocol is required (coder, tester, architect, ui-ux, secops, devops)");
30
+ process.exitCode = 1;
31
+ return;
32
+ }
33
+ await getOrBuildIndex(root);
34
+ let llm;
35
+ try {
36
+ llm = createLlmClient("instance_agent", { model: opts.model });
37
+ }
38
+ catch (e) {
39
+ log.fail(e.message);
40
+ process.exitCode = 1;
41
+ return;
42
+ }
43
+ const concurrency = parseInt(opts.concurrency, 10);
44
+ const maxIterations = parseInt(opts.maxIterations, 10);
45
+ log.dim(`swarm goal: ${goal}`);
46
+ log.dim(`protocol: ${opts.protocol} concurrency: ${concurrency}`);
47
+ // ── Master spinner: keeps the CLI alive while workers run ──
48
+ const spinner = createSpinner(`Dispatching swarm (${concurrency} worker${concurrency > 1 ? "s" : ""})…`);
49
+ const orchestrator = new InstanceSwarmOrchestrator({
50
+ workspaceRoot: root,
51
+ llm,
52
+ concurrency,
53
+ maxIterations,
54
+ hooks: {
55
+ onWorkerStart: (_wi, workerId) => {
56
+ spinner.stop(`Worker started: ${workerId}`);
57
+ // Re-start the spinner for the next wait
58
+ spinner.stop(`Dispatching swarm (${concurrency} worker${concurrency > 1 ? "s" : ""})…`);
59
+ },
60
+ onWorkerFinish: (_wi, workerId, crashed, summary) => {
61
+ const preview = summary.length > 80 ? summary.slice(0, 77) + "..." : summary;
62
+ const icon = crashed ? "✗" : "✓";
63
+ const color = crashed
64
+ ? log.fail.bind(log)
65
+ : log.ok.bind(log);
66
+ // Temporarily stop the spinner to print the worker result,
67
+ // then we'll print a final summary at the end.
68
+ spinner.stop(`${icon} ${workerId}: ${preview}`);
69
+ },
70
+ onWorkerError: (_wi, workerId, error) => {
71
+ log.fail(`Worker ${workerId} error: ${error}`);
72
+ },
73
+ },
74
+ });
75
+ let swarmResult;
76
+ try {
77
+ swarmResult = await orchestrator.run(goal, opts.protocol);
78
+ }
79
+ catch (e) {
80
+ spinner.fail(`swarm orchestration failed: ${e.message}`);
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ spinner.stop("Swarm complete.");
85
+ // ── Color-coded summary ──
86
+ printSwarmSummary({
87
+ instanceId: swarmResult.instanceId,
88
+ status: swarmResult.status,
89
+ errors: swarmResult.errors,
90
+ workerCount: swarmResult.results.length,
91
+ crashedCount: swarmResult.results.filter((r) => r.result.crashed).length,
92
+ totalInputTokens: swarmResult.totalTokenUsage.inputTokens,
93
+ totalOutputTokens: swarmResult.totalTokenUsage.outputTokens,
94
+ outputDir: swarmResult.outputDir,
95
+ });
96
+ if (swarmResult.status === "failed") {
97
+ process.exitCode = 1;
98
+ }
99
+ });
100
+ }
@@ -0,0 +1,14 @@
1
+ import type { Command } from "commander";
2
+ /**
3
+ * Register the `xcoder task` subcommand tree:
4
+ *
5
+ * xcoder task add --from <path> [--force]
6
+ * xcoder task list
7
+ * xcoder task scan [--dir <path>] [--dry-run] [--json] [--force]
8
+ *
9
+ * `add` and `scan` record intent and exit 0 without running anything or
10
+ * spending a single token. For both, exit 1 is a hard failure; 2 and 3 stay
11
+ * reserved for escalated and halted *runs*, which ingestion never produces.
12
+ * Skips and unchanged files are a successful scan, not a failure.
13
+ */
14
+ export declare function registerTaskCommand(parent: Command): void;
@@ -0,0 +1,121 @@
1
+ // xcoder:version 5 | xcoder:task task-cee5a1 | xcoder:updated 2026-10-23T12:58:17.067Z | xcoder:subtask code-st-f13216
2
+ // `xcoder task` — ingest scannable task runs from markdown/WBS sources.
3
+ //
4
+ // Registered the same way as `swarm` and `test`: one exported
5
+ // `register...Command(parent)` so `sdlc-cli.ts` stays a thin composition root.
6
+ // All real work lives in `src/task-ingest/` — these actions only translate
7
+ // results into exit codes and sanitized terminal output.
8
+ import path from "node:path";
9
+ import { ingestTask, listIngestedTasks, scanMarkdownTasks } from "../task-ingest/index.js";
10
+ import { sanitizeForTerminal } from "../util/text-sanitize.js";
11
+ import { log } from "../util/logger.js";
12
+ function workspaceRoot(parent) {
13
+ return path.resolve(parent.opts().workspace ?? process.cwd());
14
+ }
15
+ /**
16
+ * Register the `xcoder task` subcommand tree:
17
+ *
18
+ * xcoder task add --from <path> [--force]
19
+ * xcoder task list
20
+ * xcoder task scan [--dir <path>] [--dry-run] [--json] [--force]
21
+ *
22
+ * `add` and `scan` record intent and exit 0 without running anything or
23
+ * spending a single token. For both, exit 1 is a hard failure; 2 and 3 stay
24
+ * reserved for escalated and halted *runs*, which ingestion never produces.
25
+ * Skips and unchanged files are a successful scan, not a failure.
26
+ */
27
+ export function registerTaskCommand(parent) {
28
+ const taskCmd = parent
29
+ .command("task")
30
+ .description("Manage task runs that are scannable by status/incomplete/resume.");
31
+ taskCmd
32
+ .command("add")
33
+ .description("Create a scannable task run from a markdown/WBS source file. Records intent only — it does not run the task.")
34
+ .requiredOption("--from <path>", "workspace-relative path to the source file")
35
+ .option("--force", "replace a task that already has completed or in-flight subtasks", false)
36
+ .action(async (opts) => {
37
+ const root = workspaceRoot(parent);
38
+ const result = await ingestTask({
39
+ workspaceRoot: root,
40
+ from: opts.from,
41
+ force: opts.force === true,
42
+ });
43
+ if (!result.ok) {
44
+ log.fail(`${result.code}: ${sanitizeForTerminal(result.message, 300)}`);
45
+ process.exitCode = 1;
46
+ return;
47
+ }
48
+ const verb = result.created ? "created" : "unchanged";
49
+ const source = sanitizeForTerminal(result.sourcePath, 80);
50
+ const count = `${result.nodeCount} subtask${result.nodeCount === 1 ? "" : "s"}, first: ${result.firstStage}`;
51
+ log.ok(`${verb} ${result.taskId} from ${source} (${count})`);
52
+ log.raw(`next: ${result.nextCommand}`);
53
+ });
54
+ taskCmd
55
+ .command("list")
56
+ .description("List task runs and the source file each was ingested from.")
57
+ .action(async () => {
58
+ const root = workspaceRoot(parent);
59
+ const tasks = await listIngestedTasks(root);
60
+ if (!tasks.length) {
61
+ log.ok(`no task runs found in ${root}`);
62
+ return;
63
+ }
64
+ const header = `${"TASK ID".padEnd(16)} ${"STATUS".padEnd(12)} ${"N".padEnd(4)} ${"SOURCE".padEnd(32)} GOAL`;
65
+ log.raw(header);
66
+ log.raw("-".repeat(header.length));
67
+ for (const t of tasks) {
68
+ const source = t.sourcePath ?? "(free-text)";
69
+ log.raw(`${t.taskId.padEnd(16)} ${t.status.padEnd(12)} ${String(t.nodeCount).padEnd(4)} ${sanitizeForTerminal(source, 32).padEnd(32)} ${sanitizeForTerminal(t.goal, 48)}`);
70
+ }
71
+ });
72
+ taskCmd
73
+ .command("scan")
74
+ .description("Discover .md task files in a directory and ingest each one. Skips progress summaries and non-task files.")
75
+ .option("--dir <path>", "directory to scan (defaults to the task store directory)")
76
+ .option("--dry-run", "report what would be ingested without writing anything", false)
77
+ .option("--force", "replace tasks that already have completed or in-flight subtasks", false)
78
+ .option("--json", "machine output: the scan report only, no prose", false)
79
+ .action(async (opts) => {
80
+ const root = workspaceRoot(parent);
81
+ const result = await scanMarkdownTasks({
82
+ workspaceRoot: root,
83
+ dir: opts.dir,
84
+ dryRun: opts.dryRun === true,
85
+ force: opts.force === true,
86
+ });
87
+ if (opts.json === true) {
88
+ log.raw(JSON.stringify(result, null, 2));
89
+ }
90
+ else {
91
+ const mode = opts.dryRun === true ? " (dry run)" : "";
92
+ log.raw(`scanned ${sanitizeForTerminal(result.dir, 120)}${mode} — ${result.scanned} markdown file(s)`);
93
+ for (const o of result.created) {
94
+ log.ok(`would create/created ${o.taskId ?? "?"} from ${sanitizeForTerminal(o.sourcePath, 100)}`);
95
+ }
96
+ for (const o of result.unchanged) {
97
+ log.dim(`unchanged ${o.taskId ?? "?"} from ${sanitizeForTerminal(o.sourcePath, 100)}`);
98
+ }
99
+ for (const o of result.skipped) {
100
+ log.dim(`skipped ${sanitizeForTerminal(o.sourcePath, 100)} (${o.reason ?? "skipped"})`);
101
+ }
102
+ for (const o of result.failed) {
103
+ log.fail(`failed ${sanitizeForTerminal(o.sourcePath, 100)} ${o.code ?? "error"}: ${sanitizeForTerminal(o.message ?? "", 200)}`);
104
+ }
105
+ if (result.dirError) {
106
+ log.fail(`${result.dirError.code}: ${sanitizeForTerminal(result.dirError.message, 300)}`);
107
+ }
108
+ }
109
+ // Exit 1 only for a hard failure: the directory itself was unusable, or
110
+ // every candidate that looked like a task failed. Skips and unchanged
111
+ // files are a successful scan. 2 and 3 stay reserved for escalated and
112
+ // halted *runs*.
113
+ if (result.dirError) {
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+ if (result.failed.length > 0 && result.created.length === 0 && result.unchanged.length === 0) {
118
+ process.exitCode = 1;
119
+ }
120
+ });
121
+ }
@@ -0,0 +1,6 @@
1
+ export interface WbcArg {
2
+ value?: string;
3
+ argv: string[];
4
+ error?: string;
5
+ }
6
+ export declare function extractWbcArg(argv: string[]): WbcArg;