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,220 @@
1
+ // xcoder:version 1 | xcoder:task task-8c3c2b | xcoder:updated 2026-08-04T08:26:22.973Z | xcoder:subtask code-st-71e0aa
2
+ /**
3
+ * Sprint Controller — coordinates the full sprint lifecycle.
4
+ *
5
+ * Design contract: `.xcoder/design/sprint-framework-design.md` §4.1
6
+ */
7
+ import { promises as fs } from "node:fs";
8
+ import { SdlcOrchestrator } from "../sdlc-runtime/sdlc-orchestrator.js";
9
+ import { buildTaskSpec } from "../orchestrator/task-factory.js";
10
+ import { listBacklogItems, updateBacklogItem } from "../backlog/backlog-store.js";
11
+ import { runPoPick } from "../backlog/po-agent.js";
12
+ import { shortId } from "../util/ids.js";
13
+ import { log } from "../util/logger.js";
14
+ import { buildSprintDag } from "./dag-builder.js";
15
+ import { saveSprintRun, loadActiveSprintRun, loadSprintRun, deleteSprintRun, listSprintRuns, } from "./state-store.js";
16
+ import { writeGateRejectionReport, writeRetroReport, } from "./reporter.js";
17
+ // ---------------------------------------------------------------------------
18
+ // sprintStart
19
+ // ---------------------------------------------------------------------------
20
+ export async function sprintStart(opts) {
21
+ const { workspaceRoot: root, llm, concurrency } = opts;
22
+ // 1. Load open backlog items.
23
+ const openItems = await listBacklogItems(root, "open");
24
+ if (openItems.length === 0) {
25
+ throw new Error("No open backlog items available for a sprint.");
26
+ }
27
+ // 2. Use PO Agent to pick the highest-priority eligible item.
28
+ const pickResult = await runPoPick(root, openItems);
29
+ const sprintRunId = `${pickResult.selectedId}-sprint-${shortId("sr")}`;
30
+ log.ok(`PO picked: ${pickResult.selectedId} — ${pickResult.title}`);
31
+ log.dim(`Reasoning: ${pickResult.reasoning}`);
32
+ // 3. Update the item: sprintId, status=in-progress, sprintRunAt.
33
+ const now = new Date().toISOString();
34
+ await updateBacklogItem(root, pickResult.selectedId, {
35
+ sprintId: sprintRunId,
36
+ status: "in-progress",
37
+ sprintRunAt: now,
38
+ });
39
+ log.ok(`${pickResult.selectedId} → in-progress (sprint: ${sprintRunId})`);
40
+ // 4. Build a TaskSpec from the backlog item.
41
+ const taskText = pickResult.title;
42
+ const spec = buildTaskSpec(taskText, {}, {
43
+ budgetUsd: undefined,
44
+ maxHealingAttempts: 2,
45
+ concurrency,
46
+ });
47
+ log.orchestrator(`task ${spec.taskId}: ${spec.goal}`);
48
+ // 5. Build sprint DAG with quality-gate nodes.
49
+ const dag = buildSprintDag(spec);
50
+ // 6. Create and save SprintRun.
51
+ const sprintRun = {
52
+ sprintRunId,
53
+ backlogItemId: pickResult.selectedId,
54
+ taskId: spec.taskId,
55
+ status: "running",
56
+ dag,
57
+ currentStage: "requirements",
58
+ gateResults: [],
59
+ startedAt: now,
60
+ completedAt: null,
61
+ totalTokenUsage: { inputTokens: 0, outputTokens: 0 },
62
+ };
63
+ await saveSprintRun(root, sprintRun);
64
+ // 7. Run via the SdlcOrchestrator with the augmented DAG.
65
+ const orchestrator = new SdlcOrchestrator({
66
+ workspaceRoot: root,
67
+ llm,
68
+ concurrency,
69
+ });
70
+ const taskRun = await orchestrator.run(spec, dag);
71
+ // Accumulate token usage.
72
+ sprintRun.totalTokenUsage = taskRun.totalTokenUsage;
73
+ // 8. Post-orchestrator: check each gate node's result from the orchestrator's DAG.
74
+ const gateFailures = extractGateFailures(taskRun.dag);
75
+ sprintRun.gateResults = gateFailures;
76
+ if (gateFailures.some((g) => !g.passed)) {
77
+ // At least one gate failed — mark item as blocked.
78
+ const firstFailure = gateFailures.find((g) => !g.passed);
79
+ sprintRun.status = "blocked";
80
+ sprintRun.completedAt = new Date().toISOString();
81
+ await saveSprintRun(root, sprintRun);
82
+ await updateBacklogItem(root, pickResult.selectedId, {
83
+ blockedReason: `${firstFailure.role}: ${firstFailure.reason}`,
84
+ });
85
+ await writeGateRejectionReport(root, pickResult.selectedId, sprintRunId, firstFailure);
86
+ log.fail(`Sprint ${sprintRunId} blocked by ${firstFailure.role} gate: ${firstFailure.reason}`);
87
+ return {
88
+ sprintRunId,
89
+ backlogItemId: pickResult.selectedId,
90
+ taskId: spec.taskId,
91
+ outcome: "blocked",
92
+ gateFailures,
93
+ };
94
+ }
95
+ // All gates passed — mark item as done.
96
+ sprintRun.status = "done";
97
+ sprintRun.completedAt = new Date().toISOString();
98
+ await saveSprintRun(root, sprintRun);
99
+ await updateBacklogItem(root, pickResult.selectedId, {
100
+ status: "done",
101
+ taskId: spec.taskId,
102
+ sprintId: null,
103
+ blockedReason: null,
104
+ });
105
+ // Write retrospective.
106
+ await writeRetroReport(root, sprintRun);
107
+ log.ok(`Sprint ${sprintRunId} completed successfully — ${pickResult.selectedId} marked done.`);
108
+ return {
109
+ sprintRunId,
110
+ backlogItemId: pickResult.selectedId,
111
+ taskId: spec.taskId,
112
+ outcome: "done",
113
+ gateFailures,
114
+ };
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // sprintStatus
118
+ // ---------------------------------------------------------------------------
119
+ export async function sprintStatus(root) {
120
+ const active = await loadActiveSprintRun(root);
121
+ if (!active) {
122
+ log.dim("No active sprint found.");
123
+ return { active: false };
124
+ }
125
+ return {
126
+ active: true,
127
+ sprintRunId: active.sprintRunId,
128
+ backlogItemId: active.backlogItemId,
129
+ currentStage: active.currentStage,
130
+ taskStatus: active.status,
131
+ gateResults: active.gateResults,
132
+ };
133
+ }
134
+ // ---------------------------------------------------------------------------
135
+ // sprintRetro
136
+ // ---------------------------------------------------------------------------
137
+ export async function sprintRetro(root, sprintRunId) {
138
+ let run = null;
139
+ if (sprintRunId) {
140
+ run = await loadSprintRun(root, sprintRunId);
141
+ }
142
+ else {
143
+ // Default: most recent non-running sprint.
144
+ const all = await listSprintRuns(root);
145
+ const completed = all.filter((r) => r.status === "done" || r.status === "aborted" || r.status === "blocked");
146
+ if (completed.length > 0) {
147
+ completed.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
148
+ run = completed[0];
149
+ }
150
+ }
151
+ if (!run) {
152
+ throw new Error(sprintRunId
153
+ ? `Sprint run "${sprintRunId}" not found.`
154
+ : "No completed sprint runs found for retrospective.");
155
+ }
156
+ const reportPath = await writeRetroReport(root, run);
157
+ // Read back the contents.
158
+ try {
159
+ const contents = await fs.readFile(reportPath, "utf-8");
160
+ return { reportPath, contents };
161
+ }
162
+ catch {
163
+ return { reportPath, contents: "" };
164
+ }
165
+ }
166
+ // ---------------------------------------------------------------------------
167
+ // sprintAbort
168
+ // ---------------------------------------------------------------------------
169
+ export async function sprintAbort(root) {
170
+ const active = await loadActiveSprintRun(root);
171
+ if (!active) {
172
+ throw new Error("No active sprint to abort.");
173
+ }
174
+ // Reset the item.
175
+ await updateBacklogItem(root, active.backlogItemId, {
176
+ sprintId: null,
177
+ blockedReason: null,
178
+ status: "open",
179
+ });
180
+ // Remove the sprint run file.
181
+ await deleteSprintRun(root, active.sprintRunId);
182
+ log.ok(`Sprint ${active.sprintRunId} aborted — ${active.backlogItemId} reverted to open.`);
183
+ return { revertedItemId: active.backlogItemId };
184
+ }
185
+ // ---------------------------------------------------------------------------
186
+ // Helpers
187
+ // ---------------------------------------------------------------------------
188
+ /**
189
+ * Walk the DAG and extract pass/fail results from quality-gate nodes.
190
+ */
191
+ function extractGateFailures(dag) {
192
+ const results = [];
193
+ for (const node of dag) {
194
+ if (node.stage === "quality_gate" &&
195
+ (node.role === "scrum-master" ||
196
+ node.role === "system-architect" ||
197
+ node.role === "security-lead")) {
198
+ const role = node.role;
199
+ if (node.result?.deliverable) {
200
+ const d = node.result.deliverable;
201
+ results.push({
202
+ role,
203
+ passed: Boolean(d.passed),
204
+ reason: String(d.reason ?? "No reason provided"),
205
+ subtaskId: node.id,
206
+ });
207
+ }
208
+ else {
209
+ // Node didn't produce a result — likely never ran or crashed.
210
+ results.push({
211
+ role,
212
+ passed: false,
213
+ reason: `Gate node ${node.id} did not produce a result (status: ${node.status})`,
214
+ subtaskId: node.id,
215
+ });
216
+ }
217
+ }
218
+ }
219
+ return results;
220
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Sprint DAG Builder — extends the default linear SDLC DAG by inserting
3
+ * quality‑gate SubtaskNodes after specific stages.
4
+ *
5
+ * Pipeline:
6
+ * requirements → [Scrum Master gate] → design → [System Architect gate]
7
+ * → code → test → [Security Lead gate] → done
8
+ */
9
+ import type { SubtaskNode, TaskSpec } from "../types.js";
10
+ /**
11
+ * Build a sprint DAG from a TaskSpec by inserting quality-gate nodes
12
+ * into the default linear plan at specific checkpoints.
13
+ */
14
+ export declare function buildSprintDag(spec: TaskSpec): SubtaskNode[];
@@ -0,0 +1,105 @@
1
+ // xcoder:version 4 | xcoder:task task-f1ac77 | xcoder:updated 2026-10-17T04:10:51.927Z | xcoder:subtask code-st-1d0003
2
+ /**
3
+ * Sprint DAG Builder — extends the default linear SDLC DAG by inserting
4
+ * quality‑gate SubtaskNodes after specific stages.
5
+ *
6
+ * Pipeline:
7
+ * requirements → [Scrum Master gate] → design → [System Architect gate]
8
+ * → code → test → [Security Lead gate] → done
9
+ */
10
+ import { buildInitialPlan } from "../orchestrator/task-factory.js";
11
+ import { shortId } from "../util/ids.js";
12
+ import { inferLayers } from "../skills/secure-architect.bylaws.js";
13
+ /**
14
+ * Build a sprint DAG from a TaskSpec by inserting quality-gate nodes
15
+ * into the default linear plan at specific checkpoints.
16
+ */
17
+ export function buildSprintDag(spec) {
18
+ const baseDag = buildInitialPlan(spec);
19
+ return insertQualityGates(baseDag);
20
+ }
21
+ function insertQualityGates(nodes) {
22
+ const result = [];
23
+ for (const node of nodes) {
24
+ result.push(node);
25
+ // Insert quality gates after specific stages.
26
+ if (node.stage === "requirements") {
27
+ result.push(buildGateNode("scrum-master", node, gateDirectives.scrumMaster));
28
+ }
29
+ else if (node.stage === "design") {
30
+ result.push(buildGateNode("system-architect", node, gateDirectives.systemArchitect));
31
+ }
32
+ else if (node.stage === "test") {
33
+ result.push(buildGateNode("security-lead", node, gateDirectives.securityLead));
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+ function buildGateNode(role, reviewed, goal) {
39
+ const id = `gate-${role.replace(/-/g, "-")}-${shortId("st")}`;
40
+ const acceptanceCriteria = [
41
+ {
42
+ id: "AC1",
43
+ type: "schema",
44
+ description: "deliverable contains passed: boolean and reason: string",
45
+ },
46
+ ];
47
+ if (role === "security-lead") {
48
+ // Second, independent check: the agent's own `passed` claim is AC1, the
49
+ // bylaws module's verdict over its own findings is AC2. Disagreement
50
+ // between them fails the gate. Scope is frozen here, at build time,
51
+ // because the gate's own goal is static boilerplate and re-inferring it
52
+ // later would silently narrow scope to core + cross-cutting.
53
+ acceptanceCriteria.push({
54
+ id: "AC2",
55
+ type: "bylaw-review",
56
+ description: "every in-scope bylaw has a finding; no failed MUST/MUST_NOT; " +
57
+ "SHOULD deviations carry a named riskOwner",
58
+ bylawLayers: [...inferLayers(reviewed.goal)],
59
+ });
60
+ }
61
+ return {
62
+ id,
63
+ stage: "quality_gate",
64
+ role,
65
+ engine: "react-v1",
66
+ dependsOn: [reviewed.id],
67
+ goal,
68
+ upstreamContext: { reviewedNodeId: reviewed.id, reviewedGoal: reviewed.goal },
69
+ deliverableSpec: role === "security-lead"
70
+ ? "A verdict — must be a JSON object { passed: boolean, reason: string, findings: [{ bylawId, status, note?, riskOwner? }] } in the final_answer deliverable, with exactly one finding per in-scope bylaw."
71
+ : "A pass/fail verdict with a reason — must be a JSON object { passed: boolean, reason: string } in the final_answer deliverable.",
72
+ acceptanceCriteria,
73
+ status: "pending",
74
+ healing: { attempts: 0, maxAttempts: 1, log: [] },
75
+ };
76
+ }
77
+ const gateDirectives = {
78
+ scrumMaster: `
79
+ Review the requirements document produced by the requirements-analyst stage
80
+ immediately before this gate. Validate:
81
+ 1. The document exists and is well‑formed (has Goal, Non‑Goals, Constraints,
82
+ Acceptance Criteria sections).
83
+ 2. All acceptance criteria are concrete and testable — not hand‑wavy.
84
+ 3. Every open question from the requirements stage is either answered or
85
+ explicitly deferred with a stakeholder note.
86
+ Return a JSON object: { "passed": true/false, "reason": "..." }.`.trim(),
87
+ systemArchitect: `
88
+ Review the design document produced by the architect stage immediately
89
+ before this gate. Validate:
90
+ 1. Every component named in the requirements has a defined interface.
91
+ 2. Every import/reference points to a file that actually exists in the workspace
92
+ index (use the glob tool to verify).
93
+ 3. No new pattern‑breaking dependency is introduced — the design must conform
94
+ to existing workspace conventions (check the workspace index for a
95
+ package.json, tsconfig, eslint config, etc.).
96
+ Return a JSON object: { "passed": true/false, "reason": "..." }.`.trim(),
97
+ securityLead: `
98
+ Run the project's security checks:
99
+ 1. Execute "npm audit" (or appropriate command from the project's tooling)
100
+ and parse its output. The default threshold for blocking is: any "critical"
101
+ or "high" severity finding blocks the sprint.
102
+ 2. Search the workspace for common vulnerability patterns: hard‑coded secrets,
103
+ unvalidated user input reaching eval/system calls, missing auth guards.
104
+ Return a JSON object: { "passed": true/false, "reason": "..." }.`.trim(),
105
+ };
@@ -0,0 +1,11 @@
1
+ import type { GateResult, SprintRun } from "./types.js";
2
+ /**
3
+ * Write a gate rejection report for a specific failed gate.
4
+ * Returns the absolute path to the written file.
5
+ */
6
+ export declare function writeGateRejectionReport(root: string, backlogItemId: string, sprintRunId: string, gate: GateResult): Promise<string>;
7
+ /**
8
+ * Write a sprint retrospective report from a completed or aborted SprintRun.
9
+ * Returns the absolute path to the written file.
10
+ */
11
+ export declare function writeRetroReport(root: string, run: SprintRun): Promise<string>;
@@ -0,0 +1,97 @@
1
+ // xcoder:version 1 | xcoder:task task-b190f1 | xcoder:updated 2026-08-03T10:31:20.691Z | xcoder:subtask code-st-167a5d
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ import { getOutputPaths } from "../util/output-paths.js";
5
+ // ---------------------------------------------------------------------------
6
+ // Path resolution
7
+ // ---------------------------------------------------------------------------
8
+ function reportsDir(root) {
9
+ // The root parameter is preserved for backward compatibility but no longer
10
+ // drives the path — OutputPaths singleton is the single source of truth.
11
+ return getOutputPaths({ cwd: root }).sprintReportsDir();
12
+ }
13
+ // ---------------------------------------------------------------------------
14
+ // Gate rejection report
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Write a gate rejection report for a specific failed gate.
18
+ * Returns the absolute path to the written file.
19
+ */
20
+ export async function writeGateRejectionReport(root, backlogItemId, sprintRunId, gate) {
21
+ const dir = reportsDir(root);
22
+ await fs.mkdir(dir, { recursive: true });
23
+ const fileName = `sprint-${backlogItemId}.md`;
24
+ const filePath = path.join(dir, fileName);
25
+ const content = [
26
+ `# Sprint Gate Rejection — ${backlogItemId}`,
27
+ "",
28
+ `- **Gate:** ${gate.role}`,
29
+ `- **Timestamp:** ${new Date().toISOString()}`,
30
+ `- **Rejection Reason:** ${gate.reason}`,
31
+ `- **Sprint Run ID:** ${sprintRunId}`,
32
+ "",
33
+ ].join("\n");
34
+ await fs.writeFile(filePath, content, "utf-8");
35
+ return filePath;
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Retrospective report
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Write a sprint retrospective report from a completed or aborted SprintRun.
42
+ * Returns the absolute path to the written file.
43
+ */
44
+ export async function writeRetroReport(root, run) {
45
+ const dir = reportsDir(root);
46
+ await fs.mkdir(dir, { recursive: true });
47
+ const fileName = `sprint-${run.backlogItemId}-retro.md`;
48
+ const filePath = path.join(dir, fileName);
49
+ const started = new Date(run.startedAt);
50
+ const completed = run.completedAt ? new Date(run.completedAt) : new Date();
51
+ const durationMs = completed.getTime() - started.getTime();
52
+ const duration = humanReadableDuration(durationMs);
53
+ const rows = [
54
+ `# Sprint Retrospective — ${run.backlogItemId}`,
55
+ "",
56
+ `- **Completed Item(s):** ${run.backlogItemId}`,
57
+ `- **Started:** ${run.startedAt}`,
58
+ `- **Completed:** ${run.completedAt ?? "N/A"}`,
59
+ `- **Duration:** ${duration}`,
60
+ `- **Status:** ${run.status}`,
61
+ "",
62
+ "## Gate Results",
63
+ "",
64
+ "| Gate | Passed | Reason |",
65
+ "|------|--------|--------|",
66
+ ];
67
+ if (run.gateResults.length > 0) {
68
+ for (const g of run.gateResults) {
69
+ rows.push(`| ${g.role} | ${g.passed ? "✅" : "❌"} | ${g.reason.slice(0, 80)} |`);
70
+ }
71
+ }
72
+ else {
73
+ rows.push("| (no gates run) | — | — |");
74
+ }
75
+ rows.push("", "## Token Usage", "");
76
+ rows.push(`- **Input tokens:** ${run.totalTokenUsage.inputTokens}`);
77
+ rows.push(`- **Output tokens:** ${run.totalTokenUsage.outputTokens}`);
78
+ rows.push("");
79
+ const content = rows.join("\n");
80
+ await fs.writeFile(filePath, content, "utf-8");
81
+ return filePath;
82
+ }
83
+ // ---------------------------------------------------------------------------
84
+ // Helpers
85
+ // ---------------------------------------------------------------------------
86
+ function humanReadableDuration(ms) {
87
+ const seconds = Math.floor(ms / 1000);
88
+ if (seconds < 60)
89
+ return `${seconds}s`;
90
+ const minutes = Math.floor(seconds / 60);
91
+ const remainingSeconds = seconds % 60;
92
+ if (minutes < 60)
93
+ return `${minutes}m ${remainingSeconds}s`;
94
+ const hours = Math.floor(minutes / 60);
95
+ const remainingMinutes = minutes % 60;
96
+ return `${hours}h ${remainingMinutes}m ${remainingSeconds}s`;
97
+ }
@@ -0,0 +1,10 @@
1
+ import type { SprintRun } from "./types.js";
2
+ export declare function saveSprintRun(root: string, run: SprintRun): Promise<void>;
3
+ export declare function loadSprintRun(root: string, sprintRunId: string): Promise<SprintRun | null>;
4
+ /**
5
+ * Loads the most recently started SprintRun that is still active
6
+ * (status "running" or "blocked"), sorted by startedAt descending.
7
+ */
8
+ export declare function loadActiveSprintRun(root: string): Promise<SprintRun | null>;
9
+ export declare function deleteSprintRun(root: string, sprintRunId: string): Promise<void>;
10
+ export declare function listSprintRuns(root: string): Promise<SprintRun[]>;
@@ -0,0 +1,71 @@
1
+ // xcoder:version 1 | xcoder:task swarm-swarm-is-b22287 | xcoder:updated 2026-08-04T12:10:29.441Z | xcoder:subtask swarm-swarm-is-b22287/0
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ import { createXcoderPaths } from "../util/xcoder-paths.js";
5
+ // ---------------------------------------------------------------------------
6
+ // CRUD operations
7
+ // ---------------------------------------------------------------------------
8
+ export async function saveSprintRun(root, run) {
9
+ const paths = createXcoderPaths(root);
10
+ const dir = paths.sprintRunsDir();
11
+ await fs.mkdir(dir, { recursive: true });
12
+ const file = paths.sprintRunFile(run.sprintRunId);
13
+ const tmp = `${file}.tmp`;
14
+ await fs.writeFile(tmp, JSON.stringify(run, null, 2), "utf8");
15
+ await fs.rename(tmp, file);
16
+ }
17
+ export async function loadSprintRun(root, sprintRunId) {
18
+ const file = createXcoderPaths(root).sprintRunFile(sprintRunId);
19
+ try {
20
+ const raw = await fs.readFile(file, "utf-8");
21
+ return JSON.parse(raw);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ /**
28
+ * Loads the most recently started SprintRun that is still active
29
+ * (status "running" or "blocked"), sorted by startedAt descending.
30
+ */
31
+ export async function loadActiveSprintRun(root) {
32
+ const runs = await listSprintRuns(root);
33
+ const active = runs.filter((r) => r.status === "running" || r.status === "blocked");
34
+ if (active.length === 0)
35
+ return null;
36
+ active.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
37
+ return active[0];
38
+ }
39
+ export async function deleteSprintRun(root, sprintRunId) {
40
+ const file = createXcoderPaths(root).sprintRunFile(sprintRunId);
41
+ try {
42
+ await fs.unlink(file);
43
+ }
44
+ catch {
45
+ // File doesn't exist — that's fine.
46
+ }
47
+ }
48
+ export async function listSprintRuns(root) {
49
+ const dir = createXcoderPaths(root).sprintRunsDir();
50
+ let entries;
51
+ try {
52
+ entries = await fs.readdir(dir);
53
+ }
54
+ catch {
55
+ return [];
56
+ }
57
+ const runs = [];
58
+ for (const entry of entries) {
59
+ if (!entry.endsWith(".json"))
60
+ continue;
61
+ const filePath = path.join(dir, entry);
62
+ try {
63
+ const raw = await fs.readFile(filePath, "utf-8");
64
+ runs.push(JSON.parse(raw));
65
+ }
66
+ catch {
67
+ // Skip malformed files.
68
+ }
69
+ }
70
+ return runs;
71
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Sprint framework data model types — see `.xcoder/design/sprint-framework-design.md`.
3
+ */
4
+ import type { SubtaskNode, TokenUsage } from "../types.js";
5
+ export type SprintRunStatus = "running" | "done" | "aborted" | "blocked";
6
+ export interface GateResult {
7
+ role: "scrum-master" | "system-architect" | "security-lead";
8
+ passed: boolean;
9
+ reason: string;
10
+ /** The subtask node id that ran this gate, for traceability. */
11
+ subtaskId?: string;
12
+ }
13
+ export interface SprintRun {
14
+ sprintRunId: string;
15
+ backlogItemId: string;
16
+ taskId: string;
17
+ status: SprintRunStatus;
18
+ dag: SubtaskNode[];
19
+ currentStage: string;
20
+ gateResults: GateResult[];
21
+ startedAt: string;
22
+ completedAt: string | null;
23
+ totalTokenUsage: TokenUsage;
24
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Sprint framework data model types — see `.xcoder/design/sprint-framework-design.md`.
3
+ */
4
+ export {};
@@ -0,0 +1,24 @@
1
+ /** Keyed by workspace-relative posix path. Timestamps in ISO 8601. */
2
+ export type FileVersionsIndex = Record<string, {
3
+ version: number;
4
+ lastTask: string;
5
+ lastSubtask: string;
6
+ lastUpdated: string;
7
+ }>;
8
+ export interface HeaderMeta {
9
+ version: number;
10
+ taskId: string;
11
+ subtaskId: string;
12
+ timestamp: string;
13
+ }
14
+ /**
15
+ * Reads .xcoder/file-versions.json, parses it, returns the index.
16
+ * Returns an empty index if the file doesn't exist or is malformed.
17
+ */
18
+ export declare function loadFileVersions(workspaceRoot: string): Promise<FileVersionsIndex>;
19
+ /**
20
+ * Loads the index, looks up relPath, increments version by 1 (or sets to 1
21
+ * if new), updates lastTask/lastSubtask/lastUpdated, saves the index
22
+ * atomically (temp + rename), returns the new HeaderMeta.
23
+ */
24
+ export declare function incrementFileVersion(workspaceRoot: string, relPath: string, taskId: string, subtaskId: string): Promise<HeaderMeta>;
@@ -0,0 +1,73 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ // ---------------------------------------------------------------------------
4
+ // Paths
5
+ // ---------------------------------------------------------------------------
6
+ function versionsPath(workspaceRoot) {
7
+ return path.join(workspaceRoot, ".xcoder", "file-versions.json");
8
+ }
9
+ // ---------------------------------------------------------------------------
10
+ // Public API
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Reads .xcoder/file-versions.json, parses it, returns the index.
14
+ * Returns an empty index if the file doesn't exist or is malformed.
15
+ */
16
+ export async function loadFileVersions(workspaceRoot) {
17
+ try {
18
+ const raw = await fs.readFile(versionsPath(workspaceRoot), "utf8");
19
+ const parsed = JSON.parse(raw);
20
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
21
+ return {};
22
+ }
23
+ // Validate entries have the expected shape
24
+ const sanitized = {};
25
+ for (const [k, v] of Object.entries(parsed)) {
26
+ const entry = v;
27
+ if (typeof entry?.version === "number" &&
28
+ typeof entry?.lastTask === "string" &&
29
+ typeof entry?.lastSubtask === "string") {
30
+ sanitized[k] = {
31
+ version: entry.version,
32
+ lastTask: entry.lastTask,
33
+ lastSubtask: entry.lastSubtask,
34
+ lastUpdated: typeof entry.lastUpdated === "string" ? entry.lastUpdated : new Date().toISOString(),
35
+ };
36
+ }
37
+ }
38
+ return sanitized;
39
+ }
40
+ catch {
41
+ return {};
42
+ }
43
+ }
44
+ /**
45
+ * Loads the index, looks up relPath, increments version by 1 (or sets to 1
46
+ * if new), updates lastTask/lastSubtask/lastUpdated, saves the index
47
+ * atomically (temp + rename), returns the new HeaderMeta.
48
+ */
49
+ export async function incrementFileVersion(workspaceRoot, relPath, taskId, subtaskId) {
50
+ const index = await loadFileVersions(workspaceRoot);
51
+ const posix = relPath.replace(/\\/g, "/");
52
+ const existing = index[posix];
53
+ const newVersion = existing ? existing.version + 1 : 1;
54
+ const timestamp = new Date().toISOString();
55
+ index[posix] = {
56
+ version: newVersion,
57
+ lastTask: taskId,
58
+ lastSubtask: subtaskId,
59
+ lastUpdated: timestamp,
60
+ };
61
+ await atomicWrite(workspaceRoot, index);
62
+ return { version: newVersion, taskId, subtaskId, timestamp };
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Internal: atomic write
66
+ // ---------------------------------------------------------------------------
67
+ async function atomicWrite(workspaceRoot, index) {
68
+ const target = versionsPath(workspaceRoot);
69
+ const tmp = target + ".tmp." + Date.now();
70
+ await fs.mkdir(path.dirname(target), { recursive: true });
71
+ await fs.writeFile(tmp, JSON.stringify(index, null, 2), "utf8");
72
+ await fs.rename(tmp, target);
73
+ }