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,32 @@
1
+ // xcoder:version 1 | xcoder:task task-c49600 | xcoder:updated 2026-08-13T13:51:25.757Z | xcoder:subtask code-st-6d79ef
2
+ import { LlmClient } from "./client.js";
3
+ import { loadLlmConfigFile, resolveLlmConfig, } from "../config/loadConfig.js";
4
+ /**
5
+ * Sole production constructor path for LLM clients. Resolves the effective
6
+ * per-role configuration from `.xcoder/config/llm.yaml` (or built-in
7
+ * DeepSeek defaults) and returns a transport ready for that role.
8
+ *
9
+ * Precedence in `resolveLlmConfig`: role block → `default` block → built-in
10
+ * DeepSeek; `XCODER_MODEL` applies to `model` only.
11
+ */
12
+ export function createLlmClient(role, overrides = {}) {
13
+ const file = loadLlmConfigFile();
14
+ const config = resolveLlmConfig(role, file);
15
+ const opts = configToClientOptions(config);
16
+ return new LlmClient({
17
+ ...opts,
18
+ model: overrides.model ?? opts.model,
19
+ maxTokens: overrides.maxTokens ?? opts.maxTokens,
20
+ });
21
+ }
22
+ function configToClientOptions(config) {
23
+ return {
24
+ provider: config.provider ?? "deepseek",
25
+ baseUrl: config.base_url,
26
+ endpoint: config.endpoint,
27
+ model: config.model,
28
+ maxTokens: config.max_tokens,
29
+ temperature: config.temperature,
30
+ apiKeyEnv: config.api_key_env,
31
+ };
32
+ }
@@ -0,0 +1,31 @@
1
+ export interface DefectLogEntry {
2
+ timestamp: string;
3
+ defectId: string;
4
+ event: "discovered" | "fix_attempt_start" | "fix_attempt_result" | "resolved" | "closed" | "reopened";
5
+ detail: string;
6
+ metadata?: Record<string, unknown>;
7
+ }
8
+ export interface MigrationEntry {
9
+ timestamp: string;
10
+ oldPath: string;
11
+ newPath: string;
12
+ defectId: string;
13
+ status: "migrated" | "skipped" | "failed";
14
+ reason: string;
15
+ }
16
+ /**
17
+ * Appends one JSON line to `.log/defect-rca-check.log`. Creates the
18
+ * directory and file if they don't exist. Follows the 1MB rollover
19
+ * pattern from `logs.ts`.
20
+ */
21
+ export declare function logDefectEvent(workspaceRoot: string, entry: DefectLogEntry): Promise<void>;
22
+ /**
23
+ * Reads and parses the NDJSON log file. If `defectId` is provided,
24
+ * filters to events for that defect only. Used by the orchestrator to
25
+ * reconstruct the RCA check status.
26
+ */
27
+ export declare function readDefectLog(workspaceRoot: string, defectId?: string): Promise<DefectLogEntry[]>;
28
+ /**
29
+ * Writes migration audit records to `.log/migration.log` in NDJSON format.
30
+ */
31
+ export declare function logMigration(workspaceRoot: string, entries: MigrationEntry[]): Promise<void>;
@@ -0,0 +1,101 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ // ---------------------------------------------------------------------------
4
+ // Path resolution
5
+ // ---------------------------------------------------------------------------
6
+ const MAX_BYTES = 1_000_000; // 1MB rollover threshold
7
+ function logFilePath(workspaceRoot) {
8
+ const logDir = process.env.XCODER_LOG_DIR ?? ".log";
9
+ return path.join(workspaceRoot, logDir, "defect-rca-check.log");
10
+ }
11
+ function migrationLogPath(workspaceRoot) {
12
+ const logDir = process.env.XCODER_LOG_DIR ?? ".log";
13
+ return path.join(workspaceRoot, logDir, "migration.log");
14
+ }
15
+ // ---------------------------------------------------------------------------
16
+ // Internal helpers
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * Appends a line to a file, with a 1MB rollover pattern matching `logs.ts`.
20
+ */
21
+ async function appendWithRollover(filePath, line) {
22
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
23
+ const entry = line.endsWith("\n") ? line : line + "\n";
24
+ let currentSize = 0;
25
+ try {
26
+ currentSize = (await fs.stat(filePath)).size;
27
+ }
28
+ catch {
29
+ currentSize = 0;
30
+ }
31
+ if (currentSize + Buffer.byteLength(entry, "utf8") > MAX_BYTES) {
32
+ const rolled = filePath.replace(/(\.[^.]+)$/, ".1$1");
33
+ try {
34
+ await fs.rm(rolled, { force: true });
35
+ await fs.rename(filePath, rolled);
36
+ }
37
+ catch {
38
+ // best-effort; if the rename fails just keep appending to the current file
39
+ }
40
+ }
41
+ await fs.appendFile(filePath, entry, "utf8");
42
+ }
43
+ function ts() {
44
+ return new Date().toISOString();
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // Public API
48
+ // ---------------------------------------------------------------------------
49
+ /**
50
+ * Appends one JSON line to `.log/defect-rca-check.log`. Creates the
51
+ * directory and file if they don't exist. Follows the 1MB rollover
52
+ * pattern from `logs.ts`.
53
+ */
54
+ export async function logDefectEvent(workspaceRoot, entry) {
55
+ await appendWithRollover(logFilePath(workspaceRoot), JSON.stringify(entry));
56
+ }
57
+ /**
58
+ * Reads and parses the NDJSON log file. If `defectId` is provided,
59
+ * filters to events for that defect only. Used by the orchestrator to
60
+ * reconstruct the RCA check status.
61
+ */
62
+ export async function readDefectLog(workspaceRoot, defectId) {
63
+ const file = logFilePath(workspaceRoot);
64
+ let raw = "";
65
+ try {
66
+ raw = await fs.readFile(file, "utf-8");
67
+ }
68
+ catch {
69
+ return [];
70
+ }
71
+ const entries = [];
72
+ for (const line of raw.split("\n")) {
73
+ const trimmed = line.trim();
74
+ if (!trimmed)
75
+ continue;
76
+ try {
77
+ const parsed = JSON.parse(trimmed);
78
+ if (parsed &&
79
+ typeof parsed === "object" &&
80
+ typeof parsed.timestamp === "string" &&
81
+ typeof parsed.defectId === "string" &&
82
+ typeof parsed.event === "string") {
83
+ if (!defectId || parsed.defectId === defectId) {
84
+ entries.push(parsed);
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // Skip malformed lines.
90
+ }
91
+ }
92
+ return entries;
93
+ }
94
+ /**
95
+ * Writes migration audit records to `.log/migration.log` in NDJSON format.
96
+ */
97
+ export async function logMigration(workspaceRoot, entries) {
98
+ for (const entry of entries) {
99
+ await appendWithRollover(migrationLogPath(workspaceRoot), JSON.stringify(entry));
100
+ }
101
+ }
@@ -0,0 +1,118 @@
1
+ import type { Role, SdlcStage, SubtaskNode, TaskSpec } from "../types.js";
2
+ import type { DefectsIndex } from "./defect-store.js";
3
+ /**
4
+ * Parsed representation of a defect RCA file written by a tester.
5
+ * The file format must follow the Markdown contract defined in the
6
+ * design: a `# DEFECT-NNNN` title line followed by `## Observed
7
+ * Behaviour`, `## Expected Behaviour`, `## Reproduction Steps`,
8
+ * `## Root Cause Hypothesis`, `## Affected Files`, and `## Severity`.
9
+ */
10
+ export interface DefectFile {
11
+ id: string;
12
+ path: string;
13
+ discoveredBy: string;
14
+ observedBehaviour: string;
15
+ expectedBehaviour: string;
16
+ reproductionSteps: string;
17
+ rootCauseHypothesis: string;
18
+ affectedFiles: string[];
19
+ severity: "low" | "medium" | "high" | "critical";
20
+ }
21
+ /**
22
+ * The shape of `upstreamContext.defect` that a `fix_defect` node carries.
23
+ */
24
+ export interface DefectContext {
25
+ defectId: string;
26
+ defectPath: string;
27
+ rca: {
28
+ observedBehaviour: string;
29
+ expectedBehaviour: string;
30
+ rootCauseHypothesis: string;
31
+ affectedFiles: string[];
32
+ severity: "low" | "medium" | "high" | "critical";
33
+ };
34
+ }
35
+ /**
36
+ * Context passed to `defectManagerDecide` — this interface is retained
37
+ * for backwards compatibility but the decision logic now lives in
38
+ * `SdlcOrchestrator.handleResult`.
39
+ * @deprecated Use direct store/logger operations instead.
40
+ */
41
+ export interface DefectActionContext {
42
+ dag: SubtaskNode[];
43
+ newDefects: DefectFile[];
44
+ /** Any fix_defect node in the DAG that was tasked with this defect
45
+ * and has now completed (passed or failed). */
46
+ completedFixNodes: {
47
+ nodeId: string;
48
+ defectPath: string;
49
+ passed: boolean;
50
+ }[];
51
+ /** The workspace root, needed for file-existence checks. */
52
+ workspaceRoot: string;
53
+ }
54
+ /**
55
+ * Scans the defects directory for files matching `defect[0-9]{4}.md`.
56
+ * The directory is resolved via `createXcoderPaths` (respects XCODER_DIR),
57
+ * or `XCODER_DEFECT_DIR` env var as override. A file is "new" if its id
58
+ * is not in the index at all, OR if the index entry has `status: 'closed'`
59
+ * and the file has been modified since `lastUpdated` (reopened). Returns
60
+ * parsed DefectFile array sorted by ID ascending.
61
+ */
62
+ export declare function scanForDefects(workspaceRoot: string, index: DefectsIndex): Promise<DefectFile[]>;
63
+ /**
64
+ * Determines which role should receive a `fix_defect` node for the given
65
+ * defect. The v1 rule is simple: look at the tester's immediate upstream
66
+ * node in the DAG. If it was a `code` stage, route to `programmer`; if it
67
+ * was a `refactor` stage, route to `refactorer`.
68
+ *
69
+ * In the orchestrator integration, the caller (handleResult) knows which
70
+ * tester node discovered the defect, so it can look up that node's
71
+ * `dependsOn` and pass the upstream stage directly.
72
+ */
73
+ export declare function classifyDefectRouting(upstreamStage: SdlcStage | undefined): Role;
74
+ /**
75
+ * Constructs a self-contained `fix_defect` `SubtaskNode` with the defect
76
+ * path and RCA inlined into `upstreamContext`, ready to be injected into
77
+ * the DAG.
78
+ */
79
+ export declare function buildFixDefectNode(defect: DefectFile, role: Role, spec: TaskSpec, dependsOn: string[]): SubtaskNode;
80
+ /**
81
+ * Builds the goal text for a `fix_defect` node. When a defect path is
82
+ * present in upstreamContext, the goal becomes: "Confirm the defect
83
+ * described in {defectPath} no longer reproduces, via a real test run."
84
+ *
85
+ * Exported so task-factory.ts can reuse it for its own `buildGoalText`.
86
+ */
87
+ export declare function buildFixDefectGoal(defectPath: string): string;
88
+ /**
89
+ * Called by the orchestrator when a fix_defect passes verification.
90
+ * Updates the `_defects.json` entry status to "resolved", sets
91
+ * `resolvedAt` and `resolvedBy`, logs the lifecycle event, and
92
+ * optionally archives the RCA file to `.xcoder/defects/archive/`.
93
+ */
94
+ export declare function resolveDefect(workspaceRoot: string, defectId: string, nodeId: string): Promise<void>;
95
+ /**
96
+ * Called by the orchestrator when a fix_defect node is created. Updates
97
+ * the `_defects.json` entry to add a `FixAttempt` record and sets status
98
+ * to `in_progress`. Logs the lifecycle event.
99
+ */
100
+ export declare function recordFixAttempt(workspaceRoot: string, defectId: string, nodeId: string, attemptNumber: number): Promise<void>;
101
+ /**
102
+ * The Defect Manager's main entry point — retains the original signature
103
+ * for backwards compatibility. The orchestrator now handles the decision
104
+ * logic directly in `handleResult` since it has direct access to the
105
+ * store and logger.
106
+ *
107
+ * @deprecated Decision logic is now inlined in `SdlcOrchestrator.handleResult`.
108
+ */
109
+ export declare function defectManagerDecide(ctx: DefectActionContext): {
110
+ type: "replan";
111
+ patch: {
112
+ addNodes: SubtaskNode[];
113
+ };
114
+ } | {
115
+ type: "escalate";
116
+ subtaskId: string;
117
+ reason: string;
118
+ } | null;
@@ -0,0 +1,338 @@
1
+ import { shortId } from "../util/ids.js";
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ import { loadDefectsIndex, upsertDefect } from "./defect-store.js";
5
+ import { logDefectEvent } from "./defect-logger.js";
6
+ import { createXcoderPaths } from "../util/xcoder-paths.js";
7
+ // ---------------------------------------------------------------------------
8
+ // Scanning
9
+ // ---------------------------------------------------------------------------
10
+ /** Pattern that defect files must match: defect followed by exactly four digits, then .md. */
11
+ const DEFECT_FILE_RE = /^defect(\d{4})\.md$/;
12
+ /**
13
+ * Scans the defects directory for files matching `defect[0-9]{4}.md`.
14
+ * The directory is resolved via `createXcoderPaths` (respects XCODER_DIR),
15
+ * or `XCODER_DEFECT_DIR` env var as override. A file is "new" if its id
16
+ * is not in the index at all, OR if the index entry has `status: 'closed'`
17
+ * and the file has been modified since `lastUpdated` (reopened). Returns
18
+ * parsed DefectFile array sorted by ID ascending.
19
+ */
20
+ export async function scanForDefects(workspaceRoot, index) {
21
+ const scanDir = process.env.XCODER_DEFECT_DIR ?? createXcoderPaths(workspaceRoot).defectsDir();
22
+ const defectsDir = path.resolve(workspaceRoot, scanDir);
23
+ let entries = [];
24
+ try {
25
+ entries = await fs.readdir(defectsDir);
26
+ }
27
+ catch {
28
+ // No defects directory or it's unreadable — nothing to scan.
29
+ return [];
30
+ }
31
+ const newDefects = [];
32
+ for (const entry of entries) {
33
+ const match = entry.match(DEFECT_FILE_RE);
34
+ if (!match)
35
+ continue;
36
+ const numericId = match[1];
37
+ const defectId = `DEFECT-${numericId}`;
38
+ const fullPath = path.join(defectsDir, entry);
39
+ const relativePath = path.relative(workspaceRoot, fullPath).replace(/\\/g, "/");
40
+ // Check index: skip if already known and not reopened.
41
+ const existing = index[defectId];
42
+ if (existing && existing.status !== "closed") {
43
+ // Already tracked and not closed — skip.
44
+ continue;
45
+ }
46
+ if (existing && existing.status === "closed") {
47
+ // Check if file was modified since it was resolved (reopened).
48
+ try {
49
+ const stat = await fs.stat(fullPath);
50
+ const fileMtime = stat.mtime.toISOString();
51
+ if (fileMtime <= existing.lastUpdated) {
52
+ // File hasn't been touched since resolution — still closed.
53
+ continue;
54
+ }
55
+ // File modified after resolution — treat as reopened.
56
+ }
57
+ catch {
58
+ // File unreadable — skip.
59
+ continue;
60
+ }
61
+ }
62
+ try {
63
+ const content = await fs.readFile(fullPath, "utf-8");
64
+ const defect = parseDefectFile(content, relativePath, numericId);
65
+ if (defect)
66
+ newDefects.push(defect);
67
+ }
68
+ catch {
69
+ // File unreadable — skip it.
70
+ }
71
+ }
72
+ newDefects.sort((a, b) => a.id.localeCompare(b.id));
73
+ return newDefects;
74
+ }
75
+ /**
76
+ * Parses the contents of a single defect Markdown file into a `DefectFile`.
77
+ * Returns `null` if the file doesn't conform to the minimum required
78
+ * structure (a `# DEFECT-` title and at least one recognised section).
79
+ */
80
+ function parseDefectFile(content, relativePath, numericId) {
81
+ const titleMatch = content.match(/^#\s+DEFECT-(\d+)/m);
82
+ const id = titleMatch ? `DEFECT-${titleMatch[1]}` : `DEFECT-${numericId}`;
83
+ // Extract sections by heading — case-insensitive, `##` prefix.
84
+ const sections = extractSections(content);
85
+ const discoveredBy = sections["discovered by"] ??
86
+ sections["**discovered by:**"] ??
87
+ extractInlineMeta(content, /\*\*Discovered by:\*\*\s*(.*)/i) ??
88
+ "unknown";
89
+ const severityRaw = (sections["severity"] ??
90
+ extractInlineMeta(content, /\*\*Severity:\*\*\s*(.*)/i) ??
91
+ "medium").trim().toLowerCase();
92
+ const severity = ["low", "medium", "high", "critical"].includes(severityRaw)
93
+ ? severityRaw
94
+ : "medium";
95
+ const observedBehaviour = sections["observed behaviour"] ?? sections["observed behavior"] ?? "";
96
+ const expectedBehaviour = sections["expected behaviour"] ?? sections["expected behavior"] ?? "";
97
+ const reproductionSteps = sections["reproduction steps"] ?? "";
98
+ const rootCauseHypothesis = sections["root cause hypothesis"] ?? "";
99
+ const affectedFilesRaw = sections["affected files"] ?? "";
100
+ const affectedFiles = affectedFilesRaw
101
+ .split(/\n/)
102
+ .map((line) => line.trim())
103
+ .filter((line) => line.startsWith("- ") || line.startsWith("*"))
104
+ .map((line) => line.replace(/^[-*]\s+/, "").replace(/`/g, "").trim())
105
+ .filter(Boolean);
106
+ // Must have at least the core RCA fields populated.
107
+ if (!observedBehaviour && !expectedBehaviour && !rootCauseHypothesis)
108
+ return null;
109
+ return {
110
+ id,
111
+ path: relativePath,
112
+ discoveredBy,
113
+ observedBehaviour,
114
+ expectedBehaviour,
115
+ reproductionSteps,
116
+ rootCauseHypothesis,
117
+ affectedFiles,
118
+ severity,
119
+ };
120
+ }
121
+ /**
122
+ * Extracts sections from Markdown content keyed by `## Heading` lines.
123
+ * Headings are normalised to lowercase for lookup. Body runs until the
124
+ * next `##` heading or EOF.
125
+ */
126
+ function extractSections(content) {
127
+ const result = {};
128
+ const lines = content.split("\n");
129
+ let currentHeading = null;
130
+ let currentBody = [];
131
+ for (const line of lines) {
132
+ const headingMatch = line.match(/^##\s+(.+)/);
133
+ if (headingMatch) {
134
+ if (currentHeading) {
135
+ result[currentHeading.toLowerCase()] = currentBody.join("\n").trim();
136
+ }
137
+ currentHeading = headingMatch[1].trim();
138
+ currentBody = [];
139
+ }
140
+ else if (currentHeading) {
141
+ currentBody.push(line);
142
+ }
143
+ }
144
+ if (currentHeading) {
145
+ result[currentHeading.toLowerCase()] = currentBody.join("\n").trim();
146
+ }
147
+ return result;
148
+ }
149
+ /** Extracts a value from an inline bold-meta line like `**Key:** value`. */
150
+ function extractInlineMeta(content, regex) {
151
+ const match = content.match(regex);
152
+ return match ? match[1].trim() : null;
153
+ }
154
+ // ---------------------------------------------------------------------------
155
+ // Routing
156
+ // ---------------------------------------------------------------------------
157
+ /**
158
+ * Determines which role should receive a `fix_defect` node for the given
159
+ * defect. The v1 rule is simple: look at the tester's immediate upstream
160
+ * node in the DAG. If it was a `code` stage, route to `programmer`; if it
161
+ * was a `refactor` stage, route to `refactorer`.
162
+ *
163
+ * In the orchestrator integration, the caller (handleResult) knows which
164
+ * tester node discovered the defect, so it can look up that node's
165
+ * `dependsOn` and pass the upstream stage directly.
166
+ */
167
+ export function classifyDefectRouting(upstreamStage) {
168
+ if (upstreamStage === "code")
169
+ return "programmer";
170
+ if (upstreamStage === "refactor")
171
+ return "refactorer";
172
+ // Fallback: if unsure, route to programmer (the safer default — new code is more likely).
173
+ return "programmer";
174
+ }
175
+ // ---------------------------------------------------------------------------
176
+ // Node construction
177
+ // ---------------------------------------------------------------------------
178
+ /**
179
+ * Constructs a self-contained `fix_defect` `SubtaskNode` with the defect
180
+ * path and RCA inlined into `upstreamContext`, ready to be injected into
181
+ * the DAG.
182
+ */
183
+ export function buildFixDefectNode(defect, role, spec, dependsOn) {
184
+ const nodeId = `fix_defect-${shortId("df")}`;
185
+ const defectContext = {
186
+ defectId: defect.id,
187
+ defectPath: defect.path,
188
+ rca: {
189
+ observedBehaviour: defect.observedBehaviour,
190
+ expectedBehaviour: defect.expectedBehaviour,
191
+ rootCauseHypothesis: defect.rootCauseHypothesis,
192
+ affectedFiles: defect.affectedFiles,
193
+ severity: defect.severity,
194
+ },
195
+ };
196
+ const goal = buildFixDefectGoal(defect.path);
197
+ return {
198
+ id: nodeId,
199
+ stage: "fix_defect",
200
+ role,
201
+ engine: "react-v1",
202
+ dependsOn,
203
+ goal,
204
+ upstreamContext: { defect: defectContext },
205
+ deliverableSpec: "Confirmation the original defect no longer reproduces, via a real test run.",
206
+ acceptanceCriteria: [
207
+ {
208
+ id: "AC1",
209
+ type: "command",
210
+ description: "A targeted re-run confirms the original defect no longer reproduces.",
211
+ },
212
+ ],
213
+ status: "pending",
214
+ healing: {
215
+ attempts: 0,
216
+ maxAttempts: spec.constraints.maxHealingAttempts,
217
+ log: [],
218
+ },
219
+ };
220
+ }
221
+ /**
222
+ * Builds the goal text for a `fix_defect` node. When a defect path is
223
+ * present in upstreamContext, the goal becomes: "Confirm the defect
224
+ * described in {defectPath} no longer reproduces, via a real test run."
225
+ *
226
+ * Exported so task-factory.ts can reuse it for its own `buildGoalText`.
227
+ */
228
+ export function buildFixDefectGoal(defectPath) {
229
+ return `Confirm the defect described in ${defectPath} no longer reproduces, via a real test run.`;
230
+ }
231
+ // ---------------------------------------------------------------------------
232
+ // Defect lifecycle helpers
233
+ // ---------------------------------------------------------------------------
234
+ /**
235
+ * Called by the orchestrator when a fix_defect passes verification.
236
+ * Updates the `_defects.json` entry status to "resolved", sets
237
+ * `resolvedAt` and `resolvedBy`, logs the lifecycle event, and
238
+ * optionally archives the RCA file to `.xcoder/defects/archive/`.
239
+ */
240
+ export async function resolveDefect(workspaceRoot, defectId, nodeId) {
241
+ const index = await loadDefectsIndex(workspaceRoot);
242
+ const record = index[defectId];
243
+ if (!record)
244
+ return;
245
+ const now = new Date().toISOString();
246
+ record.status = "resolved";
247
+ record.resolvedAt = now;
248
+ record.resolvedBy = nodeId;
249
+ record.lastUpdated = now;
250
+ // Mark the latest fix attempt as passed.
251
+ if (record.fixAttempts.length > 0) {
252
+ const last = record.fixAttempts[record.fixAttempts.length - 1];
253
+ last.completedAt = now;
254
+ last.passed = true;
255
+ last.notes = `Resolved by ${nodeId}`;
256
+ }
257
+ await upsertDefect(workspaceRoot, record);
258
+ // Log lifecycle event.
259
+ await logDefectEvent(workspaceRoot, {
260
+ timestamp: now,
261
+ defectId,
262
+ event: "resolved",
263
+ detail: `Defect ${defectId} resolved by ${nodeId}`,
264
+ metadata: { fixNodeId: nodeId },
265
+ });
266
+ // Optionally archive the RCA file.
267
+ try {
268
+ const scanDir = process.env.XCODER_DEFECT_DIR ?? createXcoderPaths(workspaceRoot).defectsDir();
269
+ const archiveDir = path.join(path.resolve(workspaceRoot, scanDir), "archive");
270
+ const srcPath = path.join(workspaceRoot, record.path);
271
+ const basename = path.basename(record.path);
272
+ const destPath = path.join(archiveDir, basename);
273
+ await fs.mkdir(archiveDir, { recursive: true });
274
+ await fs.rename(srcPath, destPath);
275
+ }
276
+ catch {
277
+ // Archive is best-effort — file may already have been moved or deleted.
278
+ }
279
+ }
280
+ /**
281
+ * Called by the orchestrator when a fix_defect node is created. Updates
282
+ * the `_defects.json` entry to add a `FixAttempt` record and sets status
283
+ * to `in_progress`. Logs the lifecycle event.
284
+ */
285
+ export async function recordFixAttempt(workspaceRoot, defectId, nodeId, attemptNumber) {
286
+ const index = await loadDefectsIndex(workspaceRoot);
287
+ const record = index[defectId];
288
+ if (!record)
289
+ return;
290
+ const now = new Date().toISOString();
291
+ record.status = "in_progress";
292
+ record.lastUpdated = now;
293
+ record.fixAttempts.push({
294
+ attemptNumber,
295
+ fixNodeId: nodeId,
296
+ startedAt: now,
297
+ completedAt: undefined,
298
+ passed: false,
299
+ notes: undefined,
300
+ });
301
+ await upsertDefect(workspaceRoot, record);
302
+ // Log lifecycle event.
303
+ await logDefectEvent(workspaceRoot, {
304
+ timestamp: now,
305
+ defectId,
306
+ event: "fix_attempt_start",
307
+ detail: `Fix attempt ${attemptNumber} started by ${nodeId}`,
308
+ metadata: { fixNodeId: nodeId, attemptNumber },
309
+ });
310
+ }
311
+ // ---------------------------------------------------------------------------
312
+ // Decision function
313
+ // ---------------------------------------------------------------------------
314
+ /**
315
+ * The Defect Manager's main entry point — retains the original signature
316
+ * for backwards compatibility. The orchestrator now handles the decision
317
+ * logic directly in `handleResult` since it has direct access to the
318
+ * store and logger.
319
+ *
320
+ * @deprecated Decision logic is now inlined in `SdlcOrchestrator.handleResult`.
321
+ */
322
+ export function defectManagerDecide(ctx) {
323
+ for (const completed of ctx.completedFixNodes) {
324
+ if (!completed.passed) {
325
+ return {
326
+ type: "escalate",
327
+ subtaskId: completed.nodeId,
328
+ reason: `Unresolved defect ${completed.defectPath} after healing exhaustion`,
329
+ };
330
+ }
331
+ }
332
+ if (ctx.newDefects.length === 0)
333
+ return null;
334
+ return {
335
+ type: "replan",
336
+ patch: { addNodes: [] },
337
+ };
338
+ }
@@ -0,0 +1,14 @@
1
+ import type { DefectRecord } from "./defect-store.js";
2
+ /**
3
+ * One-time auto-detection and migration of a legacy `defects/` directory
4
+ * into `.xcoder/defects/`. Runs once per workspace lifetime (guarded by a
5
+ * `.xcoder/.migrated` sentinel file).
6
+ *
7
+ * If the sentinel is absent, checks for a `defects/` directory. If found,
8
+ * moves all `defect*.md` files to `.xcoder/defects/`, writes a
9
+ * `_defects.json` with `status: 'open'` for each, writes
10
+ * `.log/migration.log`, creates the sentinel, and returns the migrated
11
+ * records. If `defects/` doesn't exist, still creates the sentinel to
12
+ * avoid future checks.
13
+ */
14
+ export declare function migrateLegacyDefects(workspaceRoot: string): Promise<DefectRecord[]>;