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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Neural Node Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,88 @@
1
- # Temporary Holding Version
1
+ <!-- xcoder:version 3 | xcoder:task task-295e1f | xcoder:updated 2026-11-04T20:17:09.582Z | xcoder:subtask document-st-dd8fa0 -->
2
+ # xcoder-dna — shared runtime for the Xcoder agents
2
3
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
4
+ `xcoder-dna` is a **library**, not a CLI. It has no binary and nothing to run directly: it holds the reusable tools, skills, swarm, sub-agent runtime and orchestration primitives that the Xcoder agents are built from. Its public barrel, `src/index.ts`, is the only import path other packages may use.
5
+
6
+ ## Install
7
+
8
+ ```
9
+ npm install xcoder-dna
10
+ ```
11
+
12
+ Node >= 20 is required. Do not install this package globally — there is no executable to put on your PATH.
13
+
14
+ ## Quick start
15
+
16
+ ```ts
17
+ import { createLlmClient, log, buildIndex, ensureFreshIndex } from "xcoder-dna";
18
+
19
+ const index = buildIndex(process.cwd());
20
+ await ensureFreshIndex(process.cwd());
21
+ log.orchestrator(`indexed ${index.files.length} files`);
22
+
23
+ const llm = createLlmClient("orchestrator", { workspaceRoot: process.cwd() });
24
+ ```
25
+
26
+ ## Public API
27
+
28
+ The barrel is grouped by concern. Each identifier below is a real export; import it from the package root, never from a deep path.
29
+
30
+ | Area | Exports |
31
+ |---|---|
32
+ | LLM access | `createLlmClient`, `LlmClient`, `requestScope` |
33
+ | Logging and output | `log`, `getOutputHandler`, `getOutputPaths`, `redactSecrets`, `sanitizeForTerminal` |
34
+ | Workspace index | `buildIndex`, `ensureFreshIndex`, `createXcoderPaths` |
35
+ | Agents and runtime | `SubAgent`, `GenesisReActOrchestrator`, `SamuraiAgent`, `WorkerOrchestrator`, `InstanceSwarmOrchestrator`, `DuplicateActionDetector`, `runDebate`, `writeReport` |
36
+ | Orchestration | `decideHealing`, `getOrchestratorEngine`, `buildProgressSummaryMarkdown`, `resolveLessonFlag`, `loadLessons`, `recordLesson` |
37
+ | Defects | `scanForDefects`, `classifyDefectRouting`, `resolveDefect`, `loadDefectsIndex`, `upsertDefect` |
38
+ | Planning and DAG | `inlineIntoDependents`, `dagSnapshot`, `recomputeReady` |
39
+ | Backlog and sprints | `addBacklogItem`, `listBacklogItems`, `getBacklogItem`, `updateBacklogItem`, `runPoPick` |
40
+ | Benchmarking | `runBenchmark`, `compareReports` |
41
+ | Terminal and spinner | `setSpinnerStyle`, `getSpinnerStyle`, `createSpinner`, `AVAILABLE_SPINNER_STYLES`, `taskIntro`, `taskOutro`, `orchestratorNote`, `printCrash`, `printInterruptSummary` |
42
+ | Events and diagnostics | `xcoderEvents`, `emitXcoderEvent`, `enableProtocolErrorLogging`, `enableToolErrorLogging`, `maybePrintBanner` |
43
+ | Licensing | `requireLicense`, `isLicensedFeature`, `maybeRefreshLicense`, `createDefaultLicenseManager`, `LICENSE_REQUIRED_EXIT_CODE` |
44
+ | Command registrars | `registerTestCommand`, `registerSwarmCommand`, `registerTaskCommand`, `registerLicenseCommand` |
45
+ | Version | `XCODER_VERSION` |
46
+
47
+ Types such as `TaskRun`, `TaskSpec`, `SubtaskNode`, `SubtaskResult`, `LessonEntry`, `AgentRole`, `SdlcStage` and `SpinnerHandle` are exported alongside their values.
48
+
49
+ ## Process exit
50
+
51
+ This is a library; it never calls `process.exit` and sets no exit code itself. It does export `LICENSE_REQUIRED_EXIT_CODE` (`4`), which the CLIs relay when a licensed command runs without an active license.
52
+
53
+ ## Environment variables
54
+
55
+ `xcoder-dna` reads credentials and provider settings through the host agent's config (`~/.xcoder/config.json` or environment variables such as `XCODER_MODEL`); it never prompts for a key itself. Secrets are redacted by `redactSecrets` before they reach logs.
56
+
57
+ ## Dependency direction
58
+
59
+ `xcoder-dna` has **no internal dependencies** — it is the base of the workspace graph and imports no other workspace package. Everyone else depends on it:
60
+
61
+ ```
62
+ xcoder-dna <- @xcoder/litebro
63
+ <- @xcoder/qa-agent
64
+ <- @xcoder/sdlc-agent
65
+ ```
66
+
67
+ ## Build output
68
+
69
+ `npm run build` compiles TypeScript to `dist/` and then copies `skills/` to `dist/skills/`, so the skills catalogue ships inside the package. Only `dist/`, `README.md` and `LICENSE` are published.
70
+
71
+ ## Documentation contract
72
+
73
+ This README ships to npm, so it is gated like code by `packages/xcoder-dna/src/doc-readme.test.ts`. It asserts differently from the agent packages because this is a library: there is no bin, so no CLI section and no exit-code table are allowed. Instead every identifier named in the Public API table is checked against the barrel at `src/index.ts` — the single legal import path — so the README cannot claim an export the library does not have. Run it in isolation with:
74
+
75
+ ```
76
+ npx vitest run packages/xcoder-dna/src/doc-readme.test.ts
77
+ ```
78
+
79
+ ## Related packages
80
+
81
+ - [@xcoder/sdlc-agent](https://github.com/org/xcoder-sdlc/tree/main/packages/sdlc-agent) — the `xcoder` SDLC agent and `ba-v1`.
82
+ - [@xcoder/qa-agent](https://github.com/org/xcoder-sdlc/tree/main/packages/qa-agent) — the `bugfinder` QA agent.
83
+ - [@xcoder/litebro](https://github.com/org/xcoder-sdlc/tree/main/packages/litebro) — the tool-less planner/broker.
84
+ - [blueprint.md](https://github.com/org/xcoder-sdlc/blob/main/docs/blueprint.md) — architecture and component decomposition.
85
+
86
+ ## License
87
+
88
+ see [LICENSE](./LICENSE) for details.
@@ -0,0 +1,36 @@
1
+ import type { RaoStep, TokenUsage } from "../types.js";
2
+ import { LlmClient } from "../llm/client.js";
3
+ export interface DebateOptions {
4
+ workspaceRoot: string;
5
+ llm: LlmClient;
6
+ topic: string;
7
+ maxExchanges?: number;
8
+ model?: string;
9
+ debateId?: string;
10
+ }
11
+ export interface DebateTurn {
12
+ agent: "Sumurai" | "Ninj";
13
+ turnNumber: number;
14
+ raoTrace: RaoStep[];
15
+ finalAnswer: string | null;
16
+ tokenUsage: TokenUsage;
17
+ }
18
+ export interface DebateResult {
19
+ topic: string;
20
+ turns: DebateTurn[];
21
+ status: "resolved" | "unresolved" | "error";
22
+ errorMessage?: string;
23
+ totalTokenUsage: TokenUsage;
24
+ startedAt: string;
25
+ endedAt: string;
26
+ }
27
+ /**
28
+ * Orchestrates a turn-based debate between two SamuraiAgent instances
29
+ * (Sumurai and Ninj). Manages the transcript, iteration budget, and
30
+ * convergence detection. Returns a structured debate result regardless
31
+ * of whether the debate completed or failed mid-turn.
32
+ *
33
+ * Execution is sequential: Sumurai speaks first, then Ninj responds,
34
+ * alternating up to maxExchanges each.
35
+ */
36
+ export declare function runDebate(opts: DebateOptions): Promise<DebateResult>;
@@ -0,0 +1,300 @@
1
+ import { SamuraiAgent } from "./samurai-agent.js";
2
+ import { emitXcoderEvent } from "../events/bus.js";
3
+ import { randomUUID } from "node:crypto";
4
+ /**
5
+ * Orchestrates a turn-based debate between two SamuraiAgent instances
6
+ * (Sumurai and Ninj). Manages the transcript, iteration budget, and
7
+ * convergence detection. Returns a structured debate result regardless
8
+ * of whether the debate completed or failed mid-turn.
9
+ *
10
+ * Execution is sequential: Sumurai speaks first, then Ninj responds,
11
+ * alternating up to maxExchanges each.
12
+ */
13
+ export async function runDebate(opts) {
14
+ const maxExchanges = opts.maxExchanges ?? 20;
15
+ const debateId = opts.debateId ?? randomUUID();
16
+ const startedAt = new Date().toISOString();
17
+ const turns = [];
18
+ const totalTokenUsage = { inputTokens: 0, outputTokens: 0 };
19
+ // Emit debate:intro
20
+ emitXcoderEvent({
21
+ type: "debate:intro",
22
+ taskId: debateId,
23
+ data: { topic: opts.topic, debateId },
24
+ });
25
+ // Build the debate system prompt context — this is prepended to each
26
+ // agent's goal on every turn so they know their role and the debate rules.
27
+ const debateContextIntro = [
28
+ "# Dual-AI Debate: Sumurai vs Ninj",
29
+ `Topic: ${opts.topic}`,
30
+ "",
31
+ "You are participating in a structured debate. Rules:",
32
+ "1. Each turn you speak, address the topic AND respond to your opponent's last argument.",
33
+ "2. Be substantive — cite evidence from the workspace, files you've read, or logical reasoning.",
34
+ "3. When you believe the debate has reached a natural resolution, include a summary in your final_answer.",
35
+ "4. Keep each response focused — this is a debate, not a monologue.",
36
+ "",
37
+ ].join("\n");
38
+ // We create two agents with different system-prompt configurations.
39
+ // They share the same LlmClient and workspace but get distinct agent names.
40
+ const sumuraiAgent = new SamuraiAgent({
41
+ workspaceRoot: opts.workspaceRoot,
42
+ llm: opts.llm,
43
+ maxIterations: 20, // Each turn gets its own ReAct loop
44
+ model: opts.model,
45
+ packageJsonContext: null,
46
+ });
47
+ const ninjAgent = new SamuraiAgent({
48
+ workspaceRoot: opts.workspaceRoot,
49
+ llm: opts.llm,
50
+ maxIterations: 20,
51
+ model: opts.model,
52
+ packageJsonContext: null,
53
+ });
54
+ // Accumulated debate transcript — each agent sees the full history
55
+ let debateTranscript = debateContextIntro;
56
+ try {
57
+ for (let exchange = 0; exchange < maxExchanges; exchange++) {
58
+ // Sumurai's turn
59
+ const sumuraiTurnNumber = exchange * 2 + 1;
60
+ emitXcoderEvent({
61
+ type: "debate:turn-start",
62
+ taskId: debateId,
63
+ data: { agent: "Sumurai", turnNumber: sumuraiTurnNumber, role: exchange === 0 ? "opening" : "response" },
64
+ });
65
+ const sumuraiGoal = buildTurnGoal("Sumurai", opts.topic, debateTranscript, exchange, exchange === 0 ? "opening" : "response");
66
+ let sumuraiResult;
67
+ try {
68
+ sumuraiResult = await sumuraiAgent.runOnce(sumuraiGoal, {
69
+ onStep: (step) => {
70
+ if (step.action) {
71
+ emitXcoderEvent({
72
+ type: "debate:agent-action",
73
+ taskId: debateId,
74
+ data: { agent: "Sumurai", turnNumber: sumuraiTurnNumber, tool: step.action.tool, input: step.action.input },
75
+ });
76
+ }
77
+ else if (step.observation === "final_answer submitted") {
78
+ emitXcoderEvent({
79
+ type: "debate:agent-final",
80
+ taskId: debateId,
81
+ data: { agent: "Sumurai", turnNumber: sumuraiTurnNumber, summary: step.thought },
82
+ });
83
+ }
84
+ // Always emit thought
85
+ emitXcoderEvent({
86
+ type: "debate:agent-thought",
87
+ taskId: debateId,
88
+ data: { agent: "Sumurai", turnNumber: sumuraiTurnNumber, thought: step.thought },
89
+ });
90
+ // Emit observation if any
91
+ if (step.action) {
92
+ emitXcoderEvent({
93
+ type: "debate:agent-observation",
94
+ taskId: debateId,
95
+ data: { agent: "Sumurai", turnNumber: sumuraiTurnNumber, ok: step.observation !== undefined, observation: step.observation },
96
+ });
97
+ }
98
+ },
99
+ onTokens: (cumulative) => {
100
+ emitXcoderEvent({
101
+ type: "debate:agent-tokens",
102
+ taskId: debateId,
103
+ data: { agent: "Sumurai", turnNumber: sumuraiTurnNumber, cumulative },
104
+ });
105
+ },
106
+ });
107
+ }
108
+ catch (e) {
109
+ emitXcoderEvent({
110
+ type: "debate:outro",
111
+ taskId: debateId,
112
+ data: { status: "error", errorMessage: `Sumurai crashed on exchange ${exchange + 1}: ${e.message}`, totalTokenUsage, turns: turns.length },
113
+ });
114
+ return {
115
+ topic: opts.topic,
116
+ turns,
117
+ status: "error",
118
+ errorMessage: `Sumurai crashed on exchange ${exchange + 1}: ${e.message}`,
119
+ totalTokenUsage,
120
+ startedAt,
121
+ endedAt: new Date().toISOString(),
122
+ };
123
+ }
124
+ totalTokenUsage.inputTokens += sumuraiResult.tokenUsage.inputTokens;
125
+ totalTokenUsage.outputTokens += sumuraiResult.tokenUsage.outputTokens;
126
+ const sumuraiTurn = {
127
+ agent: "Sumurai",
128
+ turnNumber: sumuraiTurnNumber,
129
+ raoTrace: sumuraiResult.raoTrace,
130
+ finalAnswer: sumuraiResult.summary,
131
+ tokenUsage: sumuraiResult.tokenUsage,
132
+ };
133
+ turns.push(sumuraiTurn);
134
+ // Append Sumurai's contribution to debate transcript
135
+ debateTranscript += `\n\n## Sumurai (turn ${sumuraiTurnNumber})\n${sumuraiResult.summary}\n`;
136
+ // Ninj's turn
137
+ const ninjTurnNumber = exchange * 2 + 2;
138
+ emitXcoderEvent({
139
+ type: "debate:turn-start",
140
+ taskId: debateId,
141
+ data: { agent: "Ninj", turnNumber: ninjTurnNumber, role: "response" },
142
+ });
143
+ const ninjGoal = buildTurnGoal("Ninj", opts.topic, debateTranscript, exchange, "response");
144
+ let ninjResult;
145
+ try {
146
+ ninjResult = await ninjAgent.runOnce(ninjGoal, {
147
+ onStep: (step) => {
148
+ if (step.action) {
149
+ emitXcoderEvent({
150
+ type: "debate:agent-action",
151
+ taskId: debateId,
152
+ data: { agent: "Ninj", turnNumber: ninjTurnNumber, tool: step.action.tool, input: step.action.input },
153
+ });
154
+ }
155
+ else if (step.observation === "final_answer submitted") {
156
+ emitXcoderEvent({
157
+ type: "debate:agent-final",
158
+ taskId: debateId,
159
+ data: { agent: "Ninj", turnNumber: ninjTurnNumber, summary: step.thought },
160
+ });
161
+ }
162
+ emitXcoderEvent({
163
+ type: "debate:agent-thought",
164
+ taskId: debateId,
165
+ data: { agent: "Ninj", turnNumber: ninjTurnNumber, thought: step.thought },
166
+ });
167
+ if (step.action) {
168
+ emitXcoderEvent({
169
+ type: "debate:agent-observation",
170
+ taskId: debateId,
171
+ data: { agent: "Ninj", turnNumber: ninjTurnNumber, ok: step.observation !== undefined, observation: step.observation },
172
+ });
173
+ }
174
+ },
175
+ onTokens: (cumulative) => {
176
+ emitXcoderEvent({
177
+ type: "debate:agent-tokens",
178
+ taskId: debateId,
179
+ data: { agent: "Ninj", turnNumber: ninjTurnNumber, cumulative },
180
+ });
181
+ },
182
+ });
183
+ }
184
+ catch (e) {
185
+ emitXcoderEvent({
186
+ type: "debate:outro",
187
+ taskId: debateId,
188
+ data: { status: "error", errorMessage: `Ninj crashed on exchange ${exchange + 1}: ${e.message}`, totalTokenUsage, turns: turns.length },
189
+ });
190
+ return {
191
+ topic: opts.topic,
192
+ turns,
193
+ status: "error",
194
+ errorMessage: `Ninj crashed on exchange ${exchange + 1}: ${e.message}`,
195
+ totalTokenUsage,
196
+ startedAt,
197
+ endedAt: new Date().toISOString(),
198
+ };
199
+ }
200
+ totalTokenUsage.inputTokens += ninjResult.tokenUsage.inputTokens;
201
+ totalTokenUsage.outputTokens += ninjResult.tokenUsage.outputTokens;
202
+ const ninjTurn = {
203
+ agent: "Ninj",
204
+ turnNumber: ninjTurnNumber,
205
+ raoTrace: ninjResult.raoTrace,
206
+ finalAnswer: ninjResult.summary,
207
+ tokenUsage: ninjResult.tokenUsage,
208
+ };
209
+ turns.push(ninjTurn);
210
+ // Append Ninj's contribution to debate transcript
211
+ debateTranscript += `\n\n## Ninj (turn ${ninjTurnNumber})\n${ninjResult.summary}\n`;
212
+ // Convergence check: do both agents' summaries indicate resolution?
213
+ if (detectConvergence(sumuraiResult.summary, ninjResult.summary)) {
214
+ emitXcoderEvent({
215
+ type: "debate:outro",
216
+ taskId: debateId,
217
+ data: { status: "resolved", totalTokenUsage, turns: turns.length },
218
+ });
219
+ return {
220
+ topic: opts.topic,
221
+ turns,
222
+ status: "resolved",
223
+ totalTokenUsage,
224
+ startedAt,
225
+ endedAt: new Date().toISOString(),
226
+ };
227
+ }
228
+ }
229
+ // Exhausted max exchanges without convergence
230
+ emitXcoderEvent({
231
+ type: "debate:outro",
232
+ taskId: debateId,
233
+ data: { status: "unresolved", totalTokenUsage, turns: turns.length },
234
+ });
235
+ return {
236
+ topic: opts.topic,
237
+ turns,
238
+ status: "unresolved",
239
+ totalTokenUsage,
240
+ startedAt,
241
+ endedAt: new Date().toISOString(),
242
+ };
243
+ }
244
+ catch (e) {
245
+ // Catch-all for unexpected errors during the debate orchestration itself
246
+ emitXcoderEvent({
247
+ type: "debate:outro",
248
+ taskId: debateId,
249
+ data: { status: "error", errorMessage: `Debate orchestration failed: ${e.message}`, totalTokenUsage, turns: turns.length },
250
+ });
251
+ return {
252
+ topic: opts.topic,
253
+ turns,
254
+ status: "error",
255
+ errorMessage: `Debate orchestration failed: ${e.message}`,
256
+ totalTokenUsage,
257
+ startedAt,
258
+ endedAt: new Date().toISOString(),
259
+ };
260
+ }
261
+ }
262
+ /**
263
+ * Builds the goal string for a single debate turn.
264
+ * Includes the full debate transcript so far and instructions specific
265
+ * to whether this is an opening or response turn.
266
+ */
267
+ function buildTurnGoal(agentName, topic, transcript, exchange, role) {
268
+ const turnInstruction = role === "opening"
269
+ ? `You are ${agentName}, opening the debate. Present your initial position on the topic.`
270
+ : `You are ${agentName}, responding in the debate. Address your opponent's last points and strengthen your position.`;
271
+ return [
272
+ turnInstruction,
273
+ "",
274
+ "Debate transcript so far:",
275
+ `${transcript}`,
276
+ "",
277
+ `Exchange ${exchange + 1}: It is your turn to speak as ${agentName}. Provide your argument.`,
278
+ ].join("\n");
279
+ }
280
+ /**
281
+ * Simple heuristic for convergence detection: both agents' final summaries
282
+ * contain keywords indicating they've reached a conclusion.
283
+ */
284
+ function detectConvergence(sumuraiSummary, ninjSummary) {
285
+ const resolutionKeywords = [
286
+ "summary",
287
+ "conclusion",
288
+ "resolution",
289
+ "agreed",
290
+ "consensus",
291
+ "final",
292
+ "closing",
293
+ "settled",
294
+ ];
295
+ const sumuraiLower = sumuraiSummary.toLowerCase();
296
+ const ninjLower = ninjSummary.toLowerCase();
297
+ const sumuraiHasResolution = resolutionKeywords.some((kw) => sumuraiLower.includes(kw));
298
+ const ninjHasResolution = resolutionKeywords.some((kw) => ninjLower.includes(kw));
299
+ return sumuraiHasResolution && ninjHasResolution;
300
+ }
@@ -0,0 +1,7 @@
1
+ import type { DebateResult } from "./ai-chat-debate.js";
2
+ /**
3
+ * Formats a DebateResult into a timestamped Markdown report file and writes
4
+ * it to disk. If a partial error occurred, writes whatever turns were
5
+ * completed plus an error note at the end.
6
+ */
7
+ export declare function writeReport(result: DebateResult, outputDir: string): Promise<string>;
@@ -0,0 +1,100 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ /**
4
+ * Formats a DebateResult into a timestamped Markdown report file and writes
5
+ * it to disk. If a partial error occurred, writes whatever turns were
6
+ * completed plus an error note at the end.
7
+ */
8
+ export async function writeReport(result, outputDir) {
9
+ await fs.mkdir(outputDir, { recursive: true });
10
+ const ts = new Date()
11
+ .toISOString()
12
+ .replace(/[-:]/g, "")
13
+ .replace(/\..+/, "");
14
+ const filename = `ai-chat-report-${ts}.md`;
15
+ const filePath = path.join(outputDir, filename);
16
+ const md = formatReport(result);
17
+ await fs.writeFile(filePath, md, "utf-8");
18
+ return filePath;
19
+ }
20
+ /**
21
+ * Formats a DebateResult into Markdown.
22
+ */
23
+ function formatReport(result) {
24
+ const lines = [];
25
+ // Header
26
+ lines.push(`# AI Chat Debate Report: ${result.topic}`);
27
+ lines.push("");
28
+ lines.push(`- **Status**: ${result.status}`);
29
+ lines.push(`- **Started**: ${result.startedAt}`);
30
+ lines.push(`- **Ended**: ${result.endedAt}`);
31
+ lines.push(`- **Turns**: ${result.turns.length}`);
32
+ lines.push(`- **Total Token Usage**: ${result.totalTokenUsage.inputTokens} input / ${result.totalTokenUsage.outputTokens} output`);
33
+ if (result.errorMessage) {
34
+ lines.push(`- **Error**: ${result.errorMessage}`);
35
+ }
36
+ lines.push("");
37
+ lines.push("---");
38
+ lines.push("");
39
+ // Transcript
40
+ if (result.turns.length === 0) {
41
+ lines.push("_No debate turns were recorded._");
42
+ lines.push("");
43
+ }
44
+ else {
45
+ lines.push("## Debate Transcript");
46
+ lines.push("");
47
+ for (const turn of result.turns) {
48
+ lines.push(`### ${turn.agent} — Turn ${turn.turnNumber}`);
49
+ lines.push("");
50
+ if (turn.finalAnswer) {
51
+ lines.push(`**Final Answer:** ${turn.finalAnswer}`);
52
+ lines.push("");
53
+ }
54
+ else {
55
+ lines.push(`**Final Answer:** _(no final answer produced)_`);
56
+ lines.push("");
57
+ }
58
+ lines.push(`**Token Usage:** ${turn.tokenUsage.inputTokens} input / ${turn.tokenUsage.outputTokens} output`);
59
+ lines.push("");
60
+ // ReAct trace details
61
+ if (turn.raoTrace.length > 0) {
62
+ lines.push("<details>");
63
+ lines.push("<summary>ReAct Trace (click to expand)</summary>");
64
+ lines.push("");
65
+ lines.push("| # | Thought | Action | Observation |");
66
+ lines.push("|---|---------|--------|-------------|");
67
+ for (let i = 0; i < turn.raoTrace.length; i++) {
68
+ const step = turn.raoTrace[i];
69
+ const thought = escapeMarkdown(truncate(step.thought, 200));
70
+ const action = step.action
71
+ ? escapeMarkdown(`${step.action.tool}(${truncate(JSON.stringify(step.action.input), 100)})`)
72
+ : "—";
73
+ const observation = escapeMarkdown(truncate(step.observation, 200));
74
+ lines.push(`| ${i + 1} | ${thought} | ${action} | ${observation} |`);
75
+ }
76
+ lines.push("");
77
+ lines.push("</details>");
78
+ lines.push("");
79
+ }
80
+ lines.push("---");
81
+ lines.push("");
82
+ }
83
+ }
84
+ // Error note
85
+ if (result.errorMessage) {
86
+ lines.push("## Error");
87
+ lines.push("");
88
+ lines.push(`The debate did not complete successfully: ${result.errorMessage}`);
89
+ lines.push("");
90
+ }
91
+ return lines.join("\n");
92
+ }
93
+ function escapeMarkdown(text) {
94
+ return text.replace(/[|\\`*_{}[\]()#+\-.!]/g, "\\$&");
95
+ }
96
+ function truncate(text, maxLen) {
97
+ if (text.length <= maxLen)
98
+ return text;
99
+ return text.slice(0, maxLen - 3) + "...";
100
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Built directly from real evidence, not speculation: a production run's
3
+ * `code` subtask re-read the same design document 11 times across its
4
+ * attempts (multiple times WITHIN a single attempt, not just once per
5
+ * fresh retry) and repeatedly re-checked for files it hadn't created yet,
6
+ * leaving almost none of its 25-iteration budget for actual file writing.
7
+ * That pattern — the exact same (thought, action) pair recurring — is
8
+ * cheap to detect and, left unflagged, silently burns the entire
9
+ * iteration budget on zero net progress.
10
+ *
11
+ * Scope: per SubAgent.run() call (one attempt), not persisted across
12
+ * healing retries — a fresh attempt gets a fresh detector, since a brand
13
+ * new transcript legitimately has no memory of the previous attempt's
14
+ * actions anyway (that's `sdlc-orchestrator.ts`'s file-carryover
15
+ * healing hint's job, not this one's).
16
+ */
17
+ export interface DuplicateCheckResult {
18
+ isDuplicate: boolean;
19
+ priorIterations: number[];
20
+ /** True once total duplicate incidents in this attempt cross the abort threshold — the caller should stop the attempt rather than keep burning budget. */
21
+ stuck: boolean;
22
+ /** Non-null whenever isDuplicate is true — meant to be surfaced back to the model as part of the observation. */
23
+ warning: string | null;
24
+ }
25
+ export declare function actionKey(tool: string, input: unknown): string;
26
+ export declare class DuplicateActionDetector {
27
+ private abortAfterTotalDuplicates;
28
+ private seen;
29
+ private totalDuplicates;
30
+ /**
31
+ * @param abortAfterTotalDuplicates total duplicate incidents (not
32
+ * necessarily of the same action — any repeats, summed) across the
33
+ * whole attempt before it's treated as a stuck loop. 5 is deliberately
34
+ * generous: a couple of legitimate re-checks shouldn't trip this, but
35
+ * the 11-repeat pattern that motivated this class would trip it early
36
+ * instead of running to the full 25-iteration cap.
37
+ */
38
+ constructor(abortAfterTotalDuplicates?: number);
39
+ check(thought: string, tool: string, input: unknown, iteration: number): DuplicateCheckResult;
40
+ get duplicateCount(): number;
41
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Built directly from real evidence, not speculation: a production run's
3
+ * `code` subtask re-read the same design document 11 times across its
4
+ * attempts (multiple times WITHIN a single attempt, not just once per
5
+ * fresh retry) and repeatedly re-checked for files it hadn't created yet,
6
+ * leaving almost none of its 25-iteration budget for actual file writing.
7
+ * That pattern — the exact same (thought, action) pair recurring — is
8
+ * cheap to detect and, left unflagged, silently burns the entire
9
+ * iteration budget on zero net progress.
10
+ *
11
+ * Scope: per SubAgent.run() call (one attempt), not persisted across
12
+ * healing retries — a fresh attempt gets a fresh detector, since a brand
13
+ * new transcript legitimately has no memory of the previous attempt's
14
+ * actions anyway (that's `sdlc-orchestrator.ts`'s file-carryover
15
+ * healing hint's job, not this one's).
16
+ */
17
+ /** Recursively sorts object keys before stringifying, so two structurally-identical inputs compare equal regardless of key order the model happened to emit them in. */
18
+ function stableStringify(value) {
19
+ if (value === null || typeof value !== "object")
20
+ return JSON.stringify(value);
21
+ if (Array.isArray(value))
22
+ return `[${value.map(stableStringify).join(",")}]`;
23
+ const keys = Object.keys(value).sort();
24
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(",")}}`;
25
+ }
26
+ function normalizeThought(thought) {
27
+ return thought.trim().toLowerCase().replace(/\s+/g, " ");
28
+ }
29
+ export function actionKey(tool, input) {
30
+ return `${tool}::${stableStringify(input)}`;
31
+ }
32
+ export class DuplicateActionDetector {
33
+ abortAfterTotalDuplicates;
34
+ seen = new Map(); // "thought|||tool::input" -> iteration numbers where it occurred
35
+ totalDuplicates = 0;
36
+ /**
37
+ * @param abortAfterTotalDuplicates total duplicate incidents (not
38
+ * necessarily of the same action — any repeats, summed) across the
39
+ * whole attempt before it's treated as a stuck loop. 5 is deliberately
40
+ * generous: a couple of legitimate re-checks shouldn't trip this, but
41
+ * the 11-repeat pattern that motivated this class would trip it early
42
+ * instead of running to the full 25-iteration cap.
43
+ */
44
+ constructor(abortAfterTotalDuplicates = 5) {
45
+ this.abortAfterTotalDuplicates = abortAfterTotalDuplicates;
46
+ }
47
+ check(thought, tool, input, iteration) {
48
+ const key = `${normalizeThought(thought)}|||${actionKey(tool, input)}`;
49
+ const prior = this.seen.get(key) ?? [];
50
+ const isDuplicate = prior.length > 0;
51
+ if (isDuplicate)
52
+ this.totalDuplicates++;
53
+ this.seen.set(key, [...prior, iteration]);
54
+ const stuck = this.totalDuplicates >= this.abortAfterTotalDuplicates;
55
+ const warning = isDuplicate
56
+ ? `duplicate detected: this exact reasoning + action ("${tool}") was already tried at iteration ${prior.at(-1)}` +
57
+ `${prior.length > 1 ? ` (and ${prior.length - 1} time(s) before that)` : ""} — it produced no new information ` +
58
+ `last time. Try a genuinely different approach instead of repeating it.`
59
+ : null;
60
+ return { isDuplicate, priorIterations: prior, stuck, warning };
61
+ }
62
+ get duplicateCount() {
63
+ return this.totalDuplicates;
64
+ }
65
+ }