xcoder-dna 0.0.0-stage → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/LICENSE +66 -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 +39 -4
@@ -0,0 +1,120 @@
1
+ /** Auto-Update Module — §3.5 of design-desktop-installer.md */
2
+ import { createWriteStream, createReadStream } from "node:fs";
3
+ import { unlink, mkdir } from "node:fs/promises";
4
+ import { pipeline } from "node:stream/promises";
5
+ import { createHash } from "node:crypto";
6
+ import { spawn } from "node:child_process";
7
+ import os from "node:os";
8
+ import path from "node:path";
9
+ function getPlatformExtension() {
10
+ switch (process.platform) {
11
+ case "win32": return "exe";
12
+ case "darwin": return "dmg";
13
+ case "linux": return "deb";
14
+ default: return "tar.gz";
15
+ }
16
+ }
17
+ function getPlatformSuffix() {
18
+ const pmap = { win32: "win", darwin: "macos", linux: "linux" };
19
+ const arch = process.arch === "arm64" ? "arm64" : "x64";
20
+ return `${pmap[process.platform] || process.platform}-${arch}`;
21
+ }
22
+ function semverCompare(a, b) {
23
+ const pa = a.replace(/^v/, "").split(".").map(Number);
24
+ const pb = b.replace(/^v/, "").split(".").map(Number);
25
+ for (let i = 0; i < 3; i++) {
26
+ const da = pa[i] || 0;
27
+ const db = pb[i] || 0;
28
+ if (da !== db)
29
+ return da - db;
30
+ }
31
+ return 0;
32
+ }
33
+ async function sha256stream(filePath) {
34
+ const hash = createHash("sha256");
35
+ const stream = createReadStream(filePath);
36
+ for await (const chunk of stream) {
37
+ hash.update(chunk);
38
+ }
39
+ return hash.digest("hex");
40
+ }
41
+ function runProcess(cmd, args) {
42
+ return new Promise((resolve, reject) => {
43
+ const proc = spawn(cmd, args, { stdio: "inherit" });
44
+ proc.on("close", (code) => {
45
+ code === 0 ? resolve() : reject(new Error(`${cmd} exited ${code}`));
46
+ });
47
+ });
48
+ }
49
+ export async function checkForUpdate(opts) {
50
+ const defaultValue = {
51
+ updateAvailable: false, latestVersion: null, downloadUrl: null, releaseNotes: null,
52
+ };
53
+ try {
54
+ const url = `https://api.github.com/repos/${opts.repo}/releases/latest`;
55
+ const response = await fetch(url, {
56
+ headers: {
57
+ Accept: "application/vnd.github+json",
58
+ "User-Agent": `xcoder-updater/${opts.currentVersion}`,
59
+ },
60
+ });
61
+ if (!response.ok)
62
+ return defaultValue;
63
+ const release = (await response.json());
64
+ const latestVersion = release.tag_name.replace(/^v/, "");
65
+ if (semverCompare(latestVersion, opts.currentVersion) <= 0) {
66
+ return { ...defaultValue, latestVersion };
67
+ }
68
+ const platformSuffix = getPlatformSuffix();
69
+ const ext = getPlatformExtension();
70
+ const assetPattern = `xcoder-${latestVersion}-${platformSuffix}.${ext}`;
71
+ const asset = release.assets.find((a) => a.name === assetPattern);
72
+ if (!asset) {
73
+ return { ...defaultValue, latestVersion, releaseNotes: release.body };
74
+ }
75
+ return {
76
+ updateAvailable: true,
77
+ latestVersion,
78
+ downloadUrl: asset.browser_download_url,
79
+ releaseNotes: release.body,
80
+ };
81
+ }
82
+ catch {
83
+ return defaultValue;
84
+ }
85
+ }
86
+ export async function downloadAndApplyUpdate(downloadUrl, sha256Url) {
87
+ const tmpDir = path.join(os.tmpdir(), "xcoder-update");
88
+ await mkdir(tmpDir, { recursive: true });
89
+ const ext = getPlatformExtension();
90
+ const installerPath = path.join(tmpDir, `xcoder-update.${ext}`);
91
+ try {
92
+ const response = await fetch(downloadUrl);
93
+ if (!response.ok) {
94
+ throw new Error(`Download failed: ${response.status}`);
95
+ }
96
+ const fileStream = createWriteStream(installerPath);
97
+ await pipeline(response.body, fileStream);
98
+ const shaResponse = await fetch(sha256Url);
99
+ if (shaResponse.ok) {
100
+ const expectedHash = (await shaResponse.text()).trim().split(/\s+/)[0];
101
+ const actualHash = await sha256stream(installerPath);
102
+ if (expectedHash !== actualHash) {
103
+ throw new Error(`SHA256 mismatch`);
104
+ }
105
+ }
106
+ if (process.platform === "win32") {
107
+ await runProcess(installerPath, ["/S"]);
108
+ }
109
+ else if (process.platform === "darwin") {
110
+ console.log(`Update downloaded to ${installerPath}`);
111
+ console.log(`Please open the DMG and copy Xcoder SDLC.app to /Applications.`);
112
+ }
113
+ else {
114
+ await runProcess("sudo", ["dpkg", "-i", installerPath]);
115
+ }
116
+ }
117
+ finally {
118
+ await unlink(installerPath).catch(() => { });
119
+ }
120
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Write the full banner to stdout as one buffered frame.
3
+ *
4
+ * Unconditional — performs no gating (use maybePrintBanner for that). The
5
+ * content is a compile-time constant: no env var, path, model name, session id
6
+ * or other runtime data is ever interpolated, so terminal escape injection via
7
+ * this surface is structurally impossible.
8
+ */
9
+ export declare function printBanner(): void;
10
+ /**
11
+ * Whether the banner may be shown for this invocation.
12
+ *
13
+ * Pure predicate — no writes, no memoisation, safe to call repeatedly. Gate
14
+ * order is fixed and first hit wins; every ambiguity resolves to "no banner"
15
+ * because a false positive corrupts piped or machine-parseable output while a
16
+ * false negative costs one cosmetic line.
17
+ */
18
+ export declare function isBannerEnabled(argv?: readonly string[]): boolean;
19
+ /**
20
+ * Gated banner emission, at most once per process.
21
+ *
22
+ * @param argv token list inspected for suppressing flags; defaults to process.argv.
23
+ * @returns true if this call wrote a banner; false if suppressed or already printed.
24
+ */
25
+ export declare function maybePrintBanner(argv?: readonly string[]): boolean;
@@ -0,0 +1,140 @@
1
+ // xcoder:version 2 | xcoder:task task-46e4c0 | xcoder:updated 2026-10-25T16:36:43.632Z | xcoder:subtask code-st-1329b0
2
+ // banner.ts — the Xcoder SDLC ASCII banner.
3
+ //
4
+ // Render manually with: npx tsx src/util/banner.ts
5
+ //
6
+ // This module is side-effect free at import time. Entry points call
7
+ // maybePrintBanner() so the banner is gated (interactive stdout, --json,
8
+ // --help/--version, --no-color, XCODER_NO_BANNER) and emitted at most once
9
+ // per process.
10
+ import { pathToFileURL } from "node:url";
11
+ import { isInteractiveStdout } from "./tty.js";
12
+ const FONT = {
13
+ X: ["██╗ ██╗", "╚██╗██╔╝", " ╚███╔╝ ", " ██╔██╗ ", "██╔╝ ██╗", "╚═╝ ╚═╝"],
14
+ C: [" ██████╗", "██╔════╝", "██║ ", "██║ ", "╚██████╗", " ╚═════╝"],
15
+ O: [" ██████╗ ", "██╔═══██╗", "██║ ██║", "██║ ██║", "╚██████╔╝", " ╚═════╝ "],
16
+ D: ["██████╗ ", "██╔══██╗", "██║ ██║", "██║ ██║", "██████╔╝", "╚═════╝ "],
17
+ E: ["███████╗", "██╔════╝", "█████╗ ", "██╔══╝ ", "███████╗", "╚══════╝"],
18
+ R: ["██████╗ ", "██╔══██╗", "██████╔╝", "██╔══██╗", "██║ ██║", "╚═╝ ╚═╝"],
19
+ S: ["███████╗", "██╔════╝", "███████╗", "╚════██║", "███████║", "╚══════╝"],
20
+ L: ["██╗ ", "██║ ", "██║ ", "██║ ", "███████╗", "╚══════╝"],
21
+ " ": [" ", " ", " ", " ", " ", " "],
22
+ };
23
+ const RESET = "\x1b[0m";
24
+ const BOLD = "\x1b[1m";
25
+ const DIM = "\x1b[2m";
26
+ const rgb = (r, g, b) => `\x1b[38;2;${r};${g};${b}m`;
27
+ // Linear gradient between two RGB colors
28
+ function lerp(a, b, t) {
29
+ return a.map((v, i) => Math.round(v + (b[i] - v) * t));
30
+ }
31
+ function render(text) {
32
+ const rows = Array(6).fill("");
33
+ for (const ch of text.toUpperCase()) {
34
+ const glyph = FONT[ch] ?? FONT[" "];
35
+ const width = Math.max(...glyph.map((l) => l.length));
36
+ glyph.forEach((line, i) => (rows[i] += line.padEnd(width)));
37
+ }
38
+ return rows;
39
+ }
40
+ function gradient(line, from, to) {
41
+ const chars = [...line];
42
+ return (chars
43
+ .map((c, i) => {
44
+ if (c === " ")
45
+ return c;
46
+ const [r, g, b] = lerp(from, to, i / Math.max(chars.length - 1, 1));
47
+ return `${rgb(r, g, b)}${c}`;
48
+ })
49
+ .join("") + RESET);
50
+ }
51
+ function center(text, width) {
52
+ const visible = text.replace(/\x1b\[[0-9;]*m/g, "");
53
+ const pad = Math.max(0, Math.floor((width - visible.length) / 2));
54
+ return " ".repeat(pad) + text;
55
+ }
56
+ /**
57
+ * Write the full banner to stdout as one buffered frame.
58
+ *
59
+ * Unconditional — performs no gating (use maybePrintBanner for that). The
60
+ * content is a compile-time constant: no env var, path, model name, session id
61
+ * or other runtime data is ever interpolated, so terminal escape injection via
62
+ * this surface is structurally impossible.
63
+ */
64
+ export function printBanner() {
65
+ const cyan = [0, 229, 255];
66
+ const violet = [168, 85, 247];
67
+ const xcoder = render("XCODER");
68
+ const sdlc = render("SDLC");
69
+ const width = Math.max(...xcoder.map((l) => l.length), ...sdlc.map((l) => l.length));
70
+ const rule = rgb(...violet) + "═".repeat(width) + RESET;
71
+ const lines = ["", rule, ""];
72
+ for (const line of xcoder)
73
+ lines.push(gradient(line, cyan, violet));
74
+ lines.push("");
75
+ for (const line of sdlc)
76
+ lines.push(gradient(line, violet, cyan));
77
+ lines.push("", rule);
78
+ lines.push(center(`${BOLD}${rgb(0, 229, 255)}By Neural Node Labs${RESET}`, width));
79
+ lines.push(center(`${DIM}Sir John Nueva${RESET}`, width));
80
+ lines.push("");
81
+ // One write: cannot interleave with an ora spinner and is trivially testable.
82
+ process.stdout.write(lines.join("\n") + "\n");
83
+ }
84
+ /**
85
+ * Exact-token match (`--flag` or `--flag=value`), so a positional value that
86
+ * happens to contain a flag spelling cannot suppress the banner.
87
+ */
88
+ function hasFlag(argv, ...names) {
89
+ return argv.some((arg) => names.includes(arg.split("=", 1)[0]));
90
+ }
91
+ /**
92
+ * Whether the banner may be shown for this invocation.
93
+ *
94
+ * Pure predicate — no writes, no memoisation, safe to call repeatedly. Gate
95
+ * order is fixed and first hit wins; every ambiguity resolves to "no banner"
96
+ * because a false positive corrupts piped or machine-parseable output while a
97
+ * false negative costs one cosmetic line.
98
+ */
99
+ export function isBannerEnabled(argv = process.argv) {
100
+ // 1. Explicit operator opt-out wins over everything. Unset, empty, "0" and
101
+ // "false" (case-insensitive) mean "not opted out"; any other value means
102
+ // disabled — an operator should not have to guess a spelling.
103
+ const optOut = process.env.XCODER_NO_BANNER;
104
+ if (optOut !== undefined) {
105
+ const value = optOut.toLowerCase();
106
+ if (value !== "" && value !== "0" && value !== "false")
107
+ return false;
108
+ }
109
+ // 2. Machine-readable output must stay parseable (worker writes JSON to stdout).
110
+ if (hasFlag(argv, "--json"))
111
+ return false;
112
+ // 3. Help and version text is asserted verbatim.
113
+ if (hasFlag(argv, "--help", "-h", "--version", "-V"))
114
+ return false;
115
+ // 4. Read argv because `--no-color` only lands in process.env after parse.
116
+ if (hasFlag(argv, "--no-color"))
117
+ return false;
118
+ // 5. Pipes, redirection, CI and NO_COLOR.
119
+ return isInteractiveStdout();
120
+ }
121
+ let alreadyPrinted = false;
122
+ /**
123
+ * Gated banner emission, at most once per process.
124
+ *
125
+ * @param argv token list inspected for suppressing flags; defaults to process.argv.
126
+ * @returns true if this call wrote a banner; false if suppressed or already printed.
127
+ */
128
+ export function maybePrintBanner(argv = process.argv) {
129
+ if (alreadyPrinted)
130
+ return false;
131
+ if (!isBannerEnabled(argv))
132
+ return false;
133
+ printBanner();
134
+ alreadyPrinted = true;
135
+ return true;
136
+ }
137
+ // ESM self-run guard: `npx tsx src/util/banner.ts` must still render.
138
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
139
+ printBanner();
140
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Given an unknown command name and a list of known commands, return up to
3
+ * `maxSuggestions` (default 3) closest matches sorted by Levenshtein distance
4
+ * then alphabetically, filtered to a maximum distance of `threshold` (default 3).
5
+ */
6
+ export declare function suggestCommands(unknown: string, known: string[], maxSuggestions?: number, threshold?: number): string[];
@@ -0,0 +1,25 @@
1
+ // xcoder:version 1 | xcoder:task task-c776f2 | xcoder:updated 2026-08-03T19:28:41.385Z | xcoder:subtask code-st-5c254e
2
+ import { levenshtein } from "./levenshtein.js";
3
+ /**
4
+ * Given an unknown command name and a list of known commands, return up to
5
+ * `maxSuggestions` (default 3) closest matches sorted by Levenshtein distance
6
+ * then alphabetically, filtered to a maximum distance of `threshold` (default 3).
7
+ */
8
+ export function suggestCommands(unknown, known, maxSuggestions = 3, threshold = 3) {
9
+ const target = unknown.toLowerCase();
10
+ const candidates = [];
11
+ for (const cmd of known) {
12
+ const distance = levenshtein(target, cmd);
13
+ if (distance <= threshold) {
14
+ candidates.push({ name: cmd, distance });
15
+ }
16
+ }
17
+ // Sort by distance ascending, then alphabetically by command name
18
+ candidates.sort((a, b) => {
19
+ if (a.distance !== b.distance) {
20
+ return a.distance - b.distance;
21
+ }
22
+ return a.name.localeCompare(b.name);
23
+ });
24
+ return candidates.slice(0, maxSuggestions).map((c) => c.name);
25
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Display a Yes/No confirmation dialog using @clack/prompts.
3
+ *
4
+ * Callers are responsible for toggling raw mode on/off around the
5
+ * call — this utility assumes stdin is in cooked mode when called
6
+ * (Tradeoff 4: caller-owned lifecycle for clear ownership).
7
+ *
8
+ * @returns true if the user confirms Yes, false otherwise (including on cancel or error).
9
+ */
10
+ export declare function confirmInterrupt(): Promise<boolean>;
@@ -0,0 +1,31 @@
1
+ // xcoder:version 3 | xcoder:task task-0684a6 | xcoder:updated 2026-08-03T10:25:48.381Z | xcoder:subtask test-st-5ed700
2
+ import * as clack from "@clack/prompts";
3
+ /**
4
+ * Display a Yes/No confirmation dialog using @clack/prompts.
5
+ *
6
+ * Callers are responsible for toggling raw mode on/off around the
7
+ * call — this utility assumes stdin is in cooked mode when called
8
+ * (Tradeoff 4: caller-owned lifecycle for clear ownership).
9
+ *
10
+ * @returns true if the user confirms Yes, false otherwise (including on cancel or error).
11
+ */
12
+ export async function confirmInterrupt() {
13
+ try {
14
+ const answer = await clack.confirm({
15
+ message: "Do you want to interrupt the current run?",
16
+ active: "Yes",
17
+ inactive: "No",
18
+ initialValue: false,
19
+ });
20
+ // clack.confirm returns boolean | symbol (for cancel)
21
+ if (clack.isCancel(answer)) {
22
+ return false;
23
+ }
24
+ // Coerce to strict boolean: true on Yes, false on anything else (No, null, undefined, etc.)
25
+ return Boolean(answer);
26
+ }
27
+ catch {
28
+ // If the prompt fails for any reason (e.g. non-TTY), default to not interrupting.
29
+ return false;
30
+ }
31
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Matches the plain-language way people actually ask to keep going:
3
+ * "continue", "resume", "keep going", "carry on" — with or without more
4
+ * words after it ("continue on the UI", "continue write code"). This is
5
+ * what makes typing "continue" resume the actual unfinished task instead
6
+ * of Task Factory building a brand-new DAG from scratch and re-deriving
7
+ * requirements/design it already has — see `SdlcOrchestrator.resume()`.
8
+ * A referenced document supplies new task context and must go through
9
+ * normal task planning, even when the goal starts with "continue".
10
+ */
11
+ export declare function isContinueTrigger(taskText: string): boolean;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Matches the plain-language way people actually ask to keep going:
3
+ * "continue", "resume", "keep going", "carry on" — with or without more
4
+ * words after it ("continue on the UI", "continue write code"). This is
5
+ * what makes typing "continue" resume the actual unfinished task instead
6
+ * of Task Factory building a brand-new DAG from scratch and re-deriving
7
+ * requirements/design it already has — see `SdlcOrchestrator.resume()`.
8
+ * A referenced document supplies new task context and must go through
9
+ * normal task planning, even when the goal starts with "continue".
10
+ */
11
+ export function isContinueTrigger(taskText) {
12
+ const text = taskText.trim();
13
+ if (!/^(continue|resume|keep going|carry on)\b/i.test(text))
14
+ return false;
15
+ // Anchor each whitespace-delimited token so a long non-path token is
16
+ // scanned once rather than retried at every character. Accept closing
17
+ // Markdown/quotation punctuation, but not suffixes such as .md.backup.
18
+ const referencesDocument = text.split(/\s+/).some((token) => /^\S+\.(?:md|mdx|txt|rst|pdf|docx?|ya?ml|json)["'`\])}>,;:.!?]*$/i.test(token));
19
+ return !referencesDocument;
20
+ }
@@ -0,0 +1,18 @@
1
+ export interface EnvironmentInfo {
2
+ platform: NodeJS.Platform;
3
+ isWindows: boolean;
4
+ shellHint: string;
5
+ pathSep: string;
6
+ release: string;
7
+ }
8
+ export declare function getEnvironmentInfo(): EnvironmentInfo;
9
+ /**
10
+ * Injected into every Sub Agent's system prompt. This exists because a
11
+ * model that assumes `ls`, `grep`, `rm -rf`, `cat`, or unix path
12
+ * separators will happily emit a `run_command` action that fails outright
13
+ * on native Windows — and with no isolation around that failure, it looked
14
+ * like the agent "couldn't refactor" when it was actually just running the
15
+ * wrong shell dialect. Telling it up front, plus giving it glob/grep/edit
16
+ * tools that work identically on every platform, closes that gap.
17
+ */
18
+ export declare function environmentPromptBlock(env: EnvironmentInfo): string;
@@ -0,0 +1,37 @@
1
+ import os from "node:os";
2
+ export function getEnvironmentInfo() {
3
+ const platform = process.platform;
4
+ const isWindows = platform === "win32";
5
+ return {
6
+ platform,
7
+ isWindows,
8
+ pathSep: isWindows ? "\\" : "/",
9
+ release: os.release(),
10
+ shellHint: isWindows
11
+ ? "PowerShell or cmd.exe (unless run under WSL/Git Bash, in which case a real unix shell is available)"
12
+ : "a POSIX shell (bash/zsh/sh)",
13
+ };
14
+ }
15
+ /**
16
+ * Injected into every Sub Agent's system prompt. This exists because a
17
+ * model that assumes `ls`, `grep`, `rm -rf`, `cat`, or unix path
18
+ * separators will happily emit a `run_command` action that fails outright
19
+ * on native Windows — and with no isolation around that failure, it looked
20
+ * like the agent "couldn't refactor" when it was actually just running the
21
+ * wrong shell dialect. Telling it up front, plus giving it glob/grep/edit
22
+ * tools that work identically on every platform, closes that gap.
23
+ */
24
+ export function environmentPromptBlock(env) {
25
+ const warning = env.isWindows
26
+ ? `You are running on Windows (${env.release}), most likely under ${env.shellHint}. ` +
27
+ `Unix-only commands (\`ls\`, \`grep\`, \`cat\`, \`rm -rf\`, \`&&\` chaining in cmd.exe, \`/\`-only paths) ` +
28
+ `may not exist or may behave differently here. Prefer the \`glob\`, \`grep\`, \`read_file\`, \`edit_file\`, ` +
29
+ `and \`write_file\` tools over shell equivalents for anything file-related — they work identically on every ` +
30
+ `platform. Only reach for \`run_command\` for things that genuinely need a real process (build/test/lint/` +
31
+ `type-check commands, git, package managers), and use PowerShell-compatible syntax when you do.`
32
+ : `You are running on ${env.platform} under ${env.shellHint}. Standard unix commands are available via ` +
33
+ `\`run_command\`, but still prefer \`glob\`/\`grep\`/\`read_file\`/\`edit_file\` over shelling out to ` +
34
+ `\`find\`/\`grep\`/\`cat\`/\`sed\` for file operations — they're faster, and their output is structured ` +
35
+ `instead of raw text you'd have to re-parse.`;
36
+ return `## Runtime environment\n${warning}`;
37
+ }
@@ -0,0 +1,35 @@
1
+ export type FileOp = "read" | "write" | "search" | "list" | "index" | "exec" | "git" | "skill" | "lesson";
2
+ export interface FileAccess {
3
+ op: FileOp;
4
+ /** Workspace-relative path / glob (as the agent supplied it), or the command line. */
5
+ target: string;
6
+ kind: "path" | "glob" | "dir" | "cmd";
7
+ }
8
+ /** Strip obvious secrets before a command line is written to disk. */
9
+ export declare function redactSecrets(text: string): string;
10
+ /** Pure: map a tool name + input to the files/commands it touches. Never throws. */
11
+ export declare function extractFileAccess(toolName: string, input: unknown): FileAccess[];
12
+ /**
13
+ * Record one line per task run describing the index freshness gate.
14
+ *
15
+ * Reuses the existing `index` FileOp and the same log sink as every other
16
+ * tool call — the gate is observability, not a new datastore.
17
+ */
18
+ export declare function logIndexRefresh(root: string, result: {
19
+ action: string;
20
+ reason: string;
21
+ counts?: {
22
+ added: number;
23
+ removed: number;
24
+ changed: number;
25
+ };
26
+ durationMs?: number;
27
+ }, ctx?: {
28
+ taskId: string;
29
+ subtaskId: string;
30
+ }): Promise<void>;
31
+ /** Best-effort: write one `files.log` line per file/command the call touched. Never throws. */
32
+ export declare function logFileAccess(root: string, toolName: string, input: unknown, ok: boolean, ctx?: {
33
+ taskId: string;
34
+ subtaskId: string;
35
+ }): Promise<void>;
@@ -0,0 +1,140 @@
1
+ // xcoder:version 1 | xcoder:task task-e16f85 | xcoder:updated 2026-10-30T18:14:32.237Z | xcoder:subtask code-st-791be4
2
+ // Describes which files / commands a tool call touches, for `files.log`.
3
+ import { appendFiles } from "./logs.js";
4
+ const MAX_CMD = 2000;
5
+ /** Strip obvious secrets before a command line is written to disk. */
6
+ export function redactSecrets(text) {
7
+ return text
8
+ .replace(/\b(?:sk-[A-Za-z0-9_-]{16,}|gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})\b/g, "[REDACTED]")
9
+ .replace(/(:\/\/[^\s:@/]+:)[^\s@/]+@/g, "$1[REDACTED]@")
10
+ .replace(/(authorization:\s*(?:bearer|basic)\s+)\S+/gi, "$1[REDACTED]")
11
+ .replace(/\b([A-Z][A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD)=)\S+/g, "$1[REDACTED]");
12
+ }
13
+ const str = (v) => (typeof v === "string" && v.length > 0 ? v : undefined);
14
+ /** Pure: map a tool name + input to the files/commands it touches. Never throws. */
15
+ export function extractFileAccess(toolName, input) {
16
+ const i = (input && typeof input === "object" ? input : {});
17
+ const out = [];
18
+ const path = (op, v, kind = "path") => {
19
+ const t = str(v);
20
+ if (t)
21
+ out.push({ op, target: t, kind });
22
+ };
23
+ switch (toolName) {
24
+ case "read_file":
25
+ case "read_outline":
26
+ case "read_full_file":
27
+ case "get_dependency_graph":
28
+ case "validate_file":
29
+ path("read", i.path);
30
+ break;
31
+ case "read_multiple_files":
32
+ if (Array.isArray(i.files))
33
+ for (const f of i.files)
34
+ path("read", f?.path);
35
+ break;
36
+ case "write_file":
37
+ case "edit_file":
38
+ case "line_patch":
39
+ case "apply_unified_diff":
40
+ case "update_function":
41
+ case "rename_symbol":
42
+ path("write", i.path);
43
+ break;
44
+ case "sed_tool":
45
+ path("write", i.path);
46
+ path("write", i.glob, "glob");
47
+ break;
48
+ case "list_dir":
49
+ path("list", i.dir, "dir");
50
+ break;
51
+ case "glob":
52
+ path("search", i.pattern, "glob");
53
+ break;
54
+ case "grep":
55
+ path("search", i.pathGlob ?? "**/*", "glob");
56
+ break;
57
+ case "search_ast":
58
+ path("search", i.pathGlob ?? "**/*", "glob");
59
+ break;
60
+ case "search_workspace":
61
+ case "reindex_workspace":
62
+ out.push({ op: "index", target: ".", kind: "dir" });
63
+ break;
64
+ case "git_diff":
65
+ case "git_log":
66
+ out.push({ op: "git", target: str(i.path) ?? ".", kind: "path" });
67
+ break;
68
+ case "github_clone":
69
+ out.push({ op: "write", target: str(i.dir) ?? ".", kind: "dir" });
70
+ break;
71
+ case "github_commit":
72
+ case "github_push":
73
+ out.push({ op: "git", target: str(i.cwd) ?? ".", kind: "dir" });
74
+ break;
75
+ case "load_skill":
76
+ out.push({ op: "skill", target: str(i.role) ?? str(i.keyword) ?? "*", kind: "path" });
77
+ break;
78
+ case "record_lesson":
79
+ out.push({ op: "lesson", target: ".xcoder/lesson.md", kind: "path" });
80
+ break;
81
+ case "browse":
82
+ if (Array.isArray(i.steps)) {
83
+ for (const st of i.steps) {
84
+ if (st?.op === "screenshot")
85
+ out.push({ op: "write", target: str(st.path) ?? ".xcoder/screenshots", kind: str(st.path) ? "path" : "dir" });
86
+ }
87
+ }
88
+ break;
89
+ case "run_command":
90
+ path("exec", i.command, "cmd");
91
+ break;
92
+ case "schedule":
93
+ if (str(i.command))
94
+ path("exec", i.command, "cmd");
95
+ break;
96
+ default:
97
+ break;
98
+ }
99
+ return out;
100
+ }
101
+ function oneLine(s) {
102
+ return s.replace(/\r?\n/g, "\\n");
103
+ }
104
+ /**
105
+ * Record one line per task run describing the index freshness gate.
106
+ *
107
+ * Reuses the existing `index` FileOp and the same log sink as every other
108
+ * tool call — the gate is observability, not a new datastore.
109
+ */
110
+ export async function logIndexRefresh(root, result, ctx) {
111
+ try {
112
+ const taskId = ctx?.taskId ?? "session";
113
+ const subtaskId = ctx?.subtaskId ?? "-";
114
+ const c = result.counts ?? { added: 0, removed: 0, changed: 0 };
115
+ const line = [
116
+ "tool=workspace_index op=index ok=true",
117
+ `dir=.,action=${result.action},reason=${result.reason}`,
118
+ `added=${c.added},removed=${c.removed},changed=${c.changed}`,
119
+ `durationMs=${result.durationMs ?? 0}`,
120
+ ].join(" ");
121
+ await appendFiles(root, taskId, subtaskId, oneLine(redactSecrets(line)));
122
+ }
123
+ catch {
124
+ // logging must never affect the task
125
+ }
126
+ }
127
+ /** Best-effort: write one `files.log` line per file/command the call touched. Never throws. */
128
+ export async function logFileAccess(root, toolName, input, ok, ctx) {
129
+ try {
130
+ const taskId = ctx?.taskId ?? "session";
131
+ const subtaskId = ctx?.subtaskId ?? "-";
132
+ for (const a of extractFileAccess(toolName, input)) {
133
+ const field = a.kind === "cmd" ? `cmd=${oneLine(redactSecrets(a.target)).slice(0, MAX_CMD)}` : `${a.kind}=${oneLine(a.target)}`;
134
+ await appendFiles(root, taskId, subtaskId, `tool=${toolName} op=${a.op} ok=${ok} ${field}`);
135
+ }
136
+ }
137
+ catch {
138
+ // logging must never affect the tool call
139
+ }
140
+ }