@aiwg/cli 0.0.0-bootstrap.0 → 2026.7.18

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 (467) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -1
  3. package/bin/aiwg.mjs +349 -0
  4. package/dist/src/a2a/agent-card.js +145 -0
  5. package/dist/src/a2a/client.js +411 -0
  6. package/dist/src/a2a/hitl-cli.js +171 -0
  7. package/dist/src/a2a/hitl-driver.js +370 -0
  8. package/dist/src/a2a/hitl.js +181 -0
  9. package/dist/src/a2a/http.js +193 -0
  10. package/dist/src/a2a/jcs.js +128 -0
  11. package/dist/src/a2a/jws.js +187 -0
  12. package/dist/src/a2a/types.js +24 -0
  13. package/dist/src/a2a/webhook.js +240 -0
  14. package/dist/src/activity-log/cli.js +348 -0
  15. package/dist/src/activity-log/parser.js +81 -0
  16. package/dist/src/activity-log/types.js +50 -0
  17. package/dist/src/agents/agent-deployer.js +367 -0
  18. package/dist/src/agents/agent-packager.js +271 -0
  19. package/dist/src/agents/agent-validator.js +271 -0
  20. package/dist/src/agents/grounding/knowledge-base.js +161 -0
  21. package/dist/src/agents/grounding/types.js +12 -0
  22. package/dist/src/agents/index.js +10 -0
  23. package/dist/src/agents/packaged-agent-inventory.js +75 -0
  24. package/dist/src/agents/types.js +7 -0
  25. package/dist/src/api/index.d.ts +10 -0
  26. package/dist/src/api/index.js +10 -0
  27. package/dist/src/artifacts/address-parser.js +73 -0
  28. package/dist/src/artifacts/audit/cli.js +183 -0
  29. package/dist/src/artifacts/audit/drift.js +122 -0
  30. package/dist/src/artifacts/audit/types.js +12 -0
  31. package/dist/src/artifacts/backends/graphology-backend.js +160 -0
  32. package/dist/src/artifacts/backends/json-backend.js +129 -0
  33. package/dist/src/artifacts/backends/sqlite-backend.js +199 -0
  34. package/dist/src/artifacts/browser-export.js +622 -0
  35. package/dist/src/artifacts/capability-resolver.js +94 -0
  36. package/dist/src/artifacts/checksum-manifest.js +91 -0
  37. package/dist/src/artifacts/citation-parser.js +162 -0
  38. package/dist/src/artifacts/cli.js +1486 -0
  39. package/dist/src/artifacts/corpus-tools/citation-densify.js +311 -0
  40. package/dist/src/artifacts/corpus-tools/cli.js +393 -0
  41. package/dist/src/artifacts/corpus-tools/corpus-graph.js +225 -0
  42. package/dist/src/artifacts/corpus-tools/curator.js +186 -0
  43. package/dist/src/artifacts/corpus-tools/discovery-log.js +70 -0
  44. package/dist/src/artifacts/corpus-tools/funder-network.js +141 -0
  45. package/dist/src/artifacts/corpus-tools/induction-audit.js +233 -0
  46. package/dist/src/artifacts/corpus-tools/integrity-scan.js +202 -0
  47. package/dist/src/artifacts/corpus-tools/profile-communities.js +166 -0
  48. package/dist/src/artifacts/corpus-tools/profile-edges.js +72 -0
  49. package/dist/src/artifacts/corpus-tools/profile-embed.js +113 -0
  50. package/dist/src/artifacts/corpus-tools/profile-generate-fm.js +167 -0
  51. package/dist/src/artifacts/corpus-tools/profile-generate.js +181 -0
  52. package/dist/src/artifacts/corpus-tools/profile-metrics.js +98 -0
  53. package/dist/src/artifacts/corpus-tools/profile-status.js +86 -0
  54. package/dist/src/artifacts/corpus-tools/profile-temporal.js +139 -0
  55. package/dist/src/artifacts/corpus-tools/radar-init.js +93 -0
  56. package/dist/src/artifacts/corpus-tools/radar-report.js +118 -0
  57. package/dist/src/artifacts/corpus-tools/radar-shared.js +189 -0
  58. package/dist/src/artifacts/corpus-tools/radar-status.js +68 -0
  59. package/dist/src/artifacts/corpus-tools/sidecar-lint.js +233 -0
  60. package/dist/src/artifacts/corpus-tools/sidecar-repair.js +277 -0
  61. package/dist/src/artifacts/corpus-tools/snapshot.js +591 -0
  62. package/dist/src/artifacts/corpus-tools/source-types.js +164 -0
  63. package/dist/src/artifacts/corpus-tools/vision-extract.js +243 -0
  64. package/dist/src/artifacts/corpus-views/build.js +126 -0
  65. package/dist/src/artifacts/corpus-views/corpus-config.js +124 -0
  66. package/dist/src/artifacts/corpus-views/ref-parser.js +437 -0
  67. package/dist/src/artifacts/corpus-views/renderers.js +353 -0
  68. package/dist/src/artifacts/corpus-views/taxonomies.js +131 -0
  69. package/dist/src/artifacts/dep-graph.js +173 -0
  70. package/dist/src/artifacts/discover-facets.js +375 -0
  71. package/dist/src/artifacts/embedding-index.js +354 -0
  72. package/dist/src/artifacts/enrichment/cli.js +240 -0
  73. package/dist/src/artifacts/enrichment/prompt.js +47 -0
  74. package/dist/src/artifacts/enrichment/store.js +90 -0
  75. package/dist/src/artifacts/enrichment/types.js +12 -0
  76. package/dist/src/artifacts/fortemi-core-query-adapter.js +475 -0
  77. package/dist/src/artifacts/fortemi-core-sync.js +251 -0
  78. package/dist/src/artifacts/fortemi-shard-export.js +44 -0
  79. package/dist/src/artifacts/fulltext.js +108 -0
  80. package/dist/src/artifacts/graph-backend.js +51 -0
  81. package/dist/src/artifacts/graph-query.js +247 -0
  82. package/dist/src/artifacts/hybrid-query.js +225 -0
  83. package/dist/src/artifacts/index-builder.js +1089 -0
  84. package/dist/src/artifacts/index-reader.js +112 -0
  85. package/dist/src/artifacts/index-status.js +193 -0
  86. package/dist/src/artifacts/legacy-index-migration.js +169 -0
  87. package/dist/src/artifacts/move.js +154 -0
  88. package/dist/src/artifacts/operational-state.js +239 -0
  89. package/dist/src/artifacts/prebuilt-build-lock.js +49 -0
  90. package/dist/src/artifacts/query-engine.js +1955 -0
  91. package/dist/src/artifacts/source-graph.js +529 -0
  92. package/dist/src/artifacts/stats.js +169 -0
  93. package/dist/src/artifacts/types.js +606 -0
  94. package/dist/src/artifacts/views/cli.js +293 -0
  95. package/dist/src/artifacts/views/definition.js +170 -0
  96. package/dist/src/artifacts/views/store.js +149 -0
  97. package/dist/src/artifacts/views/types.js +8 -0
  98. package/dist/src/artifacts/watcher.js +255 -0
  99. package/dist/src/catalog/builtin-models.json +636 -0
  100. package/dist/src/catalog/cli.js +228 -0
  101. package/dist/src/catalog/cli.mjs +289 -0
  102. package/dist/src/catalog/index.js +15 -0
  103. package/dist/src/catalog/loader.js +217 -0
  104. package/dist/src/catalog/loader.mjs +251 -0
  105. package/dist/src/catalog/sources.json +41 -0
  106. package/dist/src/catalog/types.js +8 -0
  107. package/dist/src/channel/manager.mjs +504 -0
  108. package/dist/src/cli/agent-spawn.js +178 -0
  109. package/dist/src/cli/cli-extension-loader.js +245 -0
  110. package/dist/src/cli/command-log.js +275 -0
  111. package/dist/src/cli/config-loader.js +232 -0
  112. package/dist/src/cli/env.js +82 -0
  113. package/dist/src/cli/errors.js +150 -0
  114. package/dist/src/cli/find-package-root.js +40 -0
  115. package/dist/src/cli/git-hooks.js +250 -0
  116. package/dist/src/cli/handlers/agentcard.js +206 -0
  117. package/dist/src/cli/handlers/artifacts.js +76 -0
  118. package/dist/src/cli/handlers/best-practices-audit.js +280 -0
  119. package/dist/src/cli/handlers/cockpit.js +137 -0
  120. package/dist/src/cli/handlers/command-log.js +37 -0
  121. package/dist/src/cli/handlers/daemon.js +59 -0
  122. package/dist/src/cli/handlers/diagnose.js +300 -0
  123. package/dist/src/cli/handlers/execution-mode.js +105 -0
  124. package/dist/src/cli/handlers/feedback.js +341 -0
  125. package/dist/src/cli/handlers/help.js +147 -0
  126. package/dist/src/cli/handlers/index.js +302 -0
  127. package/dist/src/cli/handlers/init.js +179 -0
  128. package/dist/src/cli/handlers/install.js +129 -0
  129. package/dist/src/cli/handlers/issues.js +46 -0
  130. package/dist/src/cli/handlers/lint.js +42 -0
  131. package/dist/src/cli/handlers/local-executor.js +315 -0
  132. package/dist/src/cli/handlers/marketplace.js +168 -0
  133. package/dist/src/cli/handlers/mc.js +1010 -0
  134. package/dist/src/cli/handlers/models.js +352 -0
  135. package/dist/src/cli/handlers/packages.js +155 -0
  136. package/dist/src/cli/handlers/ralph-launcher.js +717 -0
  137. package/dist/src/cli/handlers/ralph.js +575 -0
  138. package/dist/src/cli/handlers/refresh.js +432 -0
  139. package/dist/src/cli/handlers/regenerate.js +336 -0
  140. package/dist/src/cli/handlers/repo-access.js +109 -0
  141. package/dist/src/cli/handlers/run.js +165 -0
  142. package/dist/src/cli/handlers/runtime-info.js +301 -0
  143. package/dist/src/cli/handlers/sandbox.js +197 -0
  144. package/dist/src/cli/handlers/scaffolding.js +149 -0
  145. package/dist/src/cli/handlers/script-runner.js +121 -0
  146. package/dist/src/cli/handlers/sdlc-accelerate.js +148 -0
  147. package/dist/src/cli/handlers/serve.js +1835 -0
  148. package/dist/src/cli/handlers/session.js +348 -0
  149. package/dist/src/cli/handlers/setup.js +440 -0
  150. package/dist/src/cli/handlers/skill-lint.js +367 -0
  151. package/dist/src/cli/handlers/skill-usage.js +74 -0
  152. package/dist/src/cli/handlers/steward.js +567 -0
  153. package/dist/src/cli/handlers/subcommands.js +1702 -0
  154. package/dist/src/cli/handlers/team.js +337 -0
  155. package/dist/src/cli/handlers/types.js +11 -0
  156. package/dist/src/cli/handlers/use.js +2772 -0
  157. package/dist/src/cli/handlers/utilities.js +703 -0
  158. package/dist/src/cli/handlers/version.js +134 -0
  159. package/dist/src/cli/handlers/workspace-context.js +93 -0
  160. package/dist/src/cli/handlers/workspace.js +126 -0
  161. package/dist/src/cli/help-generator.js +178 -0
  162. package/dist/src/cli/hooks/builtin/activity-log-hook.js +126 -0
  163. package/dist/src/cli/hooks/executor.js +96 -0
  164. package/dist/src/cli/hooks/index.js +15 -0
  165. package/dist/src/cli/hooks/registry.js +143 -0
  166. package/dist/src/cli/hooks/types.js +13 -0
  167. package/dist/src/cli/log.js +492 -0
  168. package/dist/src/cli/project-isolation/detect.js +70 -0
  169. package/dist/src/cli/project-isolation/index.js +7 -0
  170. package/dist/src/cli/project-isolation/signals.js +17 -0
  171. package/dist/src/cli/project-isolation/warning.js +102 -0
  172. package/dist/src/cli/prompt-utils.js +155 -0
  173. package/dist/src/cli/provider-deployment-plan.js +126 -0
  174. package/dist/src/cli/provider-resolution.js +119 -0
  175. package/dist/src/cli/router.js +305 -0
  176. package/dist/src/cli/scope-resolver.js +392 -0
  177. package/dist/src/cli/skill-usage.js +616 -0
  178. package/dist/src/cli/ui.js +224 -0
  179. package/dist/src/cli/watch-service.js +203 -0
  180. package/dist/src/cli/workflow-orchestrator.js +478 -0
  181. package/dist/src/cli/workspace-signals.js +321 -0
  182. package/dist/src/community/footer.js +14 -0
  183. package/dist/src/community/links.js +123 -0
  184. package/dist/src/community/milestones.js +46 -0
  185. package/dist/src/community/nudge-policy.js +93 -0
  186. package/dist/src/config/aiwg-config.js +883 -0
  187. package/dist/src/config/cli.js +703 -0
  188. package/dist/src/config/gitignore.js +156 -0
  189. package/dist/src/config/project-artifacts.js +76 -0
  190. package/dist/src/config/user-config.js +428 -0
  191. package/dist/src/config/user-registry.js +127 -0
  192. package/dist/src/config/workspace.js +276 -0
  193. package/dist/src/contributors/detect.js +39 -0
  194. package/dist/src/contributors/discover.js +172 -0
  195. package/dist/src/contributors/heuristic.js +186 -0
  196. package/dist/src/contributors/index.js +11 -0
  197. package/dist/src/contributors/types.js +13 -0
  198. package/dist/src/contributors/validation.js +116 -0
  199. package/dist/src/data/community.schema.json +43 -0
  200. package/dist/src/data/community.yaml +16 -0
  201. package/dist/src/extensions/capability-index.js +270 -0
  202. package/dist/src/extensions/claude-hooks-installer.js +268 -0
  203. package/dist/src/extensions/commands/definitions.js +3485 -0
  204. package/dist/src/extensions/deployment-registration.js +463 -0
  205. package/dist/src/extensions/index.js +22 -0
  206. package/dist/src/extensions/loader.js +132 -0
  207. package/dist/src/extensions/managed-marker.js +100 -0
  208. package/dist/src/extensions/manifest.js +196 -0
  209. package/dist/src/extensions/project-local-activity.js +114 -0
  210. package/dist/src/extensions/project-local-discovery.js +261 -0
  211. package/dist/src/extensions/project-local-doctor.js +281 -0
  212. package/dist/src/extensions/project-local-gitignore.js +176 -0
  213. package/dist/src/extensions/project-local-paths.js +121 -0
  214. package/dist/src/extensions/project-local-promote.js +218 -0
  215. package/dist/src/extensions/project-local-remove.js +373 -0
  216. package/dist/src/extensions/project-local-scaffold.js +252 -0
  217. package/dist/src/extensions/project-quickref.js +291 -0
  218. package/dist/src/extensions/registry.js +368 -0
  219. package/dist/src/extensions/shadow-resolver.js +271 -0
  220. package/dist/src/extensions/types.js +86 -0
  221. package/dist/src/extensions/upstream-registry.js +195 -0
  222. package/dist/src/extensions/validation.js +631 -0
  223. package/dist/src/features/catalog.js +88 -0
  224. package/dist/src/features/cli.js +197 -0
  225. package/dist/src/features/installer.js +57 -0
  226. package/dist/src/features/paths.js +14 -0
  227. package/dist/src/features/runtime.js +21 -0
  228. package/dist/src/features/status.js +134 -0
  229. package/dist/src/hooks/laziness-detection.js +532 -0
  230. package/dist/src/intake/git-history-analyzer.js +486 -0
  231. package/dist/src/intake/index.js +9 -0
  232. package/dist/src/issues/cli.js +327 -0
  233. package/dist/src/issues/index.js +5 -0
  234. package/dist/src/issues/live.js +154 -0
  235. package/dist/src/issues/local.js +666 -0
  236. package/dist/src/issues/sync.js +143 -0
  237. package/dist/src/issues/types.js +2 -0
  238. package/dist/src/issues/workflows.js +164 -0
  239. package/dist/src/kb/cli.js +173 -0
  240. package/dist/src/lint/cli.js +171 -0
  241. package/dist/src/lint/loader.js +225 -0
  242. package/dist/src/lint/reporters.js +141 -0
  243. package/dist/src/lint/runner.js +364 -0
  244. package/dist/src/lint/types.js +10 -0
  245. package/dist/src/marketplace/cache.js +110 -0
  246. package/dist/src/marketplace/identifier.js +63 -0
  247. package/dist/src/marketplace/registry.js +36 -0
  248. package/dist/src/marketplace/sources/clawhub.js +53 -0
  249. package/dist/src/marketplace/sources/git.js +45 -0
  250. package/dist/src/marketplace/types.js +9 -0
  251. package/dist/src/mcp/adapters/codex-runtime.js +224 -0
  252. package/dist/src/mcp/cli.mjs +1197 -0
  253. package/dist/src/mcp/elicitation.mjs +149 -0
  254. package/dist/src/mcp/helpers.mjs +287 -0
  255. package/dist/src/mcp/index.mjs +11 -0
  256. package/dist/src/mcp/profiles.js +263 -0
  257. package/dist/src/mcp/profiles.mjs +360 -0
  258. package/dist/src/mcp/registry.js +376 -0
  259. package/dist/src/mcp/registry.mjs +387 -0
  260. package/dist/src/mcp/server.mjs +633 -0
  261. package/dist/src/mcp/test-simple.mjs +271 -0
  262. package/dist/src/mcp/tools/command-run.mjs +101 -0
  263. package/dist/src/mcp/tools/discovery.mjs +291 -0
  264. package/dist/src/mcp/tools/interaction.mjs +87 -0
  265. package/dist/src/mcp/tools/orchestration.mjs +320 -0
  266. package/dist/src/mcp/tools/subsystems.mjs +640 -0
  267. package/dist/src/memory/cli.js +166 -0
  268. package/dist/src/memory/project-registry.js +282 -0
  269. package/dist/src/metrics/artifact-metrics.js +184 -0
  270. package/dist/src/metrics/context-budget.js +174 -0
  271. package/dist/src/metrics/token-counter.js +133 -0
  272. package/dist/src/models/config-loader.js +228 -0
  273. package/dist/src/models/index.js +22 -0
  274. package/dist/src/models/model-capabilities.v1.json +120 -0
  275. package/dist/src/models/model-catalog.v1.json +96 -0
  276. package/dist/src/models/model-discovery.js +521 -0
  277. package/dist/src/models/provider-models.js +73 -0
  278. package/dist/src/models/provider-policy.js +273 -0
  279. package/dist/src/models/resolver.js +245 -0
  280. package/dist/src/models/router.js +70 -0
  281. package/dist/src/models/types.js +8 -0
  282. package/dist/src/models/wrapper-deployment.js +178 -0
  283. package/dist/src/models/wrapper-route.js +54 -0
  284. package/dist/src/ops/cli.js +268 -0
  285. package/dist/src/ops/registry.js +623 -0
  286. package/dist/src/packages/adapters/clawhub.js +113 -0
  287. package/dist/src/packages/adapters/git.js +153 -0
  288. package/dist/src/packages/adapters/gitea.js +93 -0
  289. package/dist/src/packages/adapters/github.js +69 -0
  290. package/dist/src/packages/adapters/local-cache.js +89 -0
  291. package/dist/src/packages/package-registry.js +143 -0
  292. package/dist/src/packages/registry.js +238 -0
  293. package/dist/src/packages/types.js +11 -0
  294. package/dist/src/plugin/cross-framework-ops.js +475 -0
  295. package/dist/src/plugin/framework-config-loader.js +235 -0
  296. package/dist/src/plugin/framework-detector.js +186 -0
  297. package/dist/src/plugin/framework-isolator.js +341 -0
  298. package/dist/src/plugin/framework-migration.js +371 -0
  299. package/dist/src/plugin/metadata-validator.js +906 -0
  300. package/dist/src/plugin/plugin-installer.js +436 -0
  301. package/dist/src/plugin/plugin-status.js +369 -0
  302. package/dist/src/plugin/plugin-uninstaller.js +473 -0
  303. package/dist/src/plugin/registry-validator.js +344 -0
  304. package/dist/src/plugin/skill-command-translator.js +415 -0
  305. package/dist/src/plugin/workspace-creator.js +189 -0
  306. package/dist/src/plugin/workspace-migrator.js +821 -0
  307. package/dist/src/policy/authorization.js +390 -0
  308. package/dist/src/policy/repo-access.js +215 -0
  309. package/dist/src/provenance/cli.js +16 -0
  310. package/dist/src/providers/capability-matrix.js +300 -0
  311. package/dist/src/providers/capability-matrix.yaml +514 -0
  312. package/dist/src/providers/provider-definitions.js +977 -0
  313. package/dist/src/providers/provider-definitions.mjs +159 -0
  314. package/dist/src/providers/provider-inventory.js +169 -0
  315. package/dist/src/quality/feedback-ab.js +174 -0
  316. package/dist/src/quality/feedback-collector.js +176 -0
  317. package/dist/src/quality/feedback-tracker.js +123 -0
  318. package/dist/src/quality/patterns/adr.json +24 -0
  319. package/dist/src/quality/patterns/sad.json +24 -0
  320. package/dist/src/quality/patterns/test-plan.json +24 -0
  321. package/dist/src/quality/patterns/use-case.json +24 -0
  322. package/dist/src/quality/scoring.js +157 -0
  323. package/dist/src/reflections/cli.js +15 -0
  324. package/dist/src/release/plan.js +139 -0
  325. package/dist/src/research/cache/manager.js +227 -0
  326. package/dist/src/research/clients/arxiv.js +156 -0
  327. package/dist/src/research/clients/base.js +197 -0
  328. package/dist/src/research/clients/crossref.js +112 -0
  329. package/dist/src/research/clients/semantic-scholar.js +126 -0
  330. package/dist/src/research/clients/unpaywall.js +87 -0
  331. package/dist/src/research/index.js +14 -0
  332. package/dist/src/research/query-cli.js +336 -0
  333. package/dist/src/research/services/acquisition.js +313 -0
  334. package/dist/src/research/services/archival.js +225 -0
  335. package/dist/src/research/services/citation.js +279 -0
  336. package/dist/src/research/services/discovery.js +243 -0
  337. package/dist/src/research/services/documentation.js +269 -0
  338. package/dist/src/research/services/index.js +14 -0
  339. package/dist/src/research/services/provenance.js +279 -0
  340. package/dist/src/research/services/quality.js +370 -0
  341. package/dist/src/research/services/types.js +7 -0
  342. package/dist/src/research/storage-cli.js +20 -0
  343. package/dist/src/research/types.js +47 -0
  344. package/dist/src/resources/index.d.ts +2 -0
  345. package/dist/src/resources/index.js +2 -0
  346. package/dist/src/resources/web-release.d.ts +89 -0
  347. package/dist/src/resources/web-release.js +886 -0
  348. package/dist/src/rlm/cache/cli.js +162 -0
  349. package/dist/src/rlm/cache/hash.js +35 -0
  350. package/dist/src/rlm/cache/store.js +170 -0
  351. package/dist/src/rlm/cache/types.js +8 -0
  352. package/dist/src/rlm/cli.js +650 -0
  353. package/dist/src/serve/a2a-terminal-observer.js +120 -0
  354. package/dist/src/serve/agent-router.js +205 -0
  355. package/dist/src/serve/dispatch-router.js +171 -0
  356. package/dist/src/serve/executor-registry.js +715 -0
  357. package/dist/src/serve/mission-conductor.js +177 -0
  358. package/dist/src/serve/orchestrator-adapter.js +113 -0
  359. package/dist/src/serve/orchestrator-override.js +94 -0
  360. package/dist/src/serve/orchestrator-pty.js +133 -0
  361. package/dist/src/serve/pty-bridge.js +799 -0
  362. package/dist/src/serve/sandbox-registry.js +832 -0
  363. package/dist/src/serve/screen-reader.js +228 -0
  364. package/dist/src/serve/stack-adapters.js +68 -0
  365. package/dist/src/serve/telemetry.js +143 -0
  366. package/dist/src/skills/adapters/clawhub.js +250 -0
  367. package/dist/src/skills/adapters/local.js +335 -0
  368. package/dist/src/skills/adapters/openclaw.js +316 -0
  369. package/dist/src/skills/cli.js +334 -0
  370. package/dist/src/skills/registry.js +117 -0
  371. package/dist/src/skills/run.js +259 -0
  372. package/dist/src/skills/runtime.js +94 -0
  373. package/dist/src/skills/types.js +10 -0
  374. package/dist/src/smiths/agentsmith/demo.js +116 -0
  375. package/dist/src/smiths/agentsmith/examples.js +300 -0
  376. package/dist/src/smiths/agentsmith/generator.js +503 -0
  377. package/dist/src/smiths/agentsmith/index.js +11 -0
  378. package/dist/src/smiths/agentsmith/types.js +8 -0
  379. package/dist/src/smiths/commandsmith/example.js +220 -0
  380. package/dist/src/smiths/commandsmith/generator.js +288 -0
  381. package/dist/src/smiths/commandsmith/index.js +41 -0
  382. package/dist/src/smiths/commandsmith/templates.js +296 -0
  383. package/dist/src/smiths/commandsmith/types.js +7 -0
  384. package/dist/src/smiths/context-pipeline/aiwg-md.js +104 -0
  385. package/dist/src/smiths/context-pipeline/allowlist.js +195 -0
  386. package/dist/src/smiths/context-pipeline/claude-hook.js +127 -0
  387. package/dist/src/smiths/context-pipeline/discovery.js +187 -0
  388. package/dist/src/smiths/context-pipeline/external-links-section.js +49 -0
  389. package/dist/src/smiths/context-pipeline/finalization.js +147 -0
  390. package/dist/src/smiths/context-pipeline/generator.js +477 -0
  391. package/dist/src/smiths/context-pipeline/index.js +30 -0
  392. package/dist/src/smiths/context-pipeline/legacy-inject.js +103 -0
  393. package/dist/src/smiths/context-pipeline/managed-hook.js +95 -0
  394. package/dist/src/smiths/context-pipeline/overflow.js +212 -0
  395. package/dist/src/smiths/context-pipeline/parallelism-section.js +94 -0
  396. package/dist/src/smiths/context-pipeline/provider-policy.js +64 -0
  397. package/dist/src/smiths/context-pipeline/sanitizer.js +93 -0
  398. package/dist/src/smiths/context-pipeline/types.js +23 -0
  399. package/dist/src/smiths/context-pipeline/workspace-context.js +988 -0
  400. package/dist/src/smiths/hook-bridge/codex-translator.js +129 -0
  401. package/dist/src/smiths/hook-bridge/copilot-translator.js +64 -0
  402. package/dist/src/smiths/hook-bridge/factory-translator.js +43 -0
  403. package/dist/src/smiths/hook-bridge/hermes-translator.js +88 -0
  404. package/dist/src/smiths/hook-bridge/index.js +79 -0
  405. package/dist/src/smiths/hook-bridge/loader.js +116 -0
  406. package/dist/src/smiths/hook-bridge/shim.js +89 -0
  407. package/dist/src/smiths/hook-bridge/types.js +31 -0
  408. package/dist/src/smiths/index.js +39 -0
  409. package/dist/src/smiths/mcpsmith/analyzers/cli-analyzer.js +390 -0
  410. package/dist/src/smiths/mcpsmith/example.js +119 -0
  411. package/dist/src/smiths/mcpsmith/generator.js +236 -0
  412. package/dist/src/smiths/mcpsmith/index.js +17 -0
  413. package/dist/src/smiths/mcpsmith/types.js +10 -0
  414. package/dist/src/smiths/platform-paths.js +101 -0
  415. package/dist/src/smiths/skillsmith/codex-sidecar.js +85 -0
  416. package/dist/src/smiths/skillsmith/collision-detector.js +249 -0
  417. package/dist/src/smiths/skillsmith/demo.js +83 -0
  418. package/dist/src/smiths/skillsmith/examples.js +161 -0
  419. package/dist/src/smiths/skillsmith/generator.js +316 -0
  420. package/dist/src/smiths/skillsmith/index.js +12 -0
  421. package/dist/src/smiths/skillsmith/namespace-adapter.js +180 -0
  422. package/dist/src/smiths/skillsmith/platform-resolver.js +157 -0
  423. package/dist/src/smiths/skillsmith/types.js +9 -0
  424. package/dist/src/smiths/toolsmith/index.js +10 -0
  425. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +710 -0
  426. package/dist/src/smiths/toolsmith/types.js +8 -0
  427. package/dist/src/storage/backends/fortemi.js +227 -0
  428. package/dist/src/storage/backends/fs.js +134 -0
  429. package/dist/src/storage/backends/logseq.js +309 -0
  430. package/dist/src/storage/backends/obsidian.js +233 -0
  431. package/dist/src/storage/cli.js +468 -0
  432. package/dist/src/storage/config.js +272 -0
  433. package/dist/src/storage/index.js +108 -0
  434. package/dist/src/storage/subsystem-cli.js +201 -0
  435. package/dist/src/storage/types.js +33 -0
  436. package/dist/src/testing/corpus/corpus-builder.js +383 -0
  437. package/dist/src/testing/corpus/ground-truth-manager.js +460 -0
  438. package/dist/src/testing/corpus/index.js +10 -0
  439. package/dist/src/testing/fixtures/index.js +9 -0
  440. package/dist/src/testing/fixtures/test-data-factory.js +472 -0
  441. package/dist/src/testing/generators/index.js +11 -0
  442. package/dist/src/testing/generators/test-case-generator.js +393 -0
  443. package/dist/src/testing/generators/test-code-generator.js +384 -0
  444. package/dist/src/testing/generators/use-case-parser.js +325 -0
  445. package/dist/src/testing/index.js +11 -0
  446. package/dist/src/tracker/capability-protocol.js +118 -0
  447. package/dist/src/update/checker.mjs +396 -0
  448. package/dist/src/update/notifier.mjs +235 -0
  449. package/dist/src/writing/content-diversifier.js +804 -0
  450. package/dist/src/writing/example-generator.js +959 -0
  451. package/dist/src/writing/example-templates.js +99 -0
  452. package/dist/src/writing/pattern-library.js +486 -0
  453. package/dist/src/writing/patterns/banned-phrases.json +4413 -0
  454. package/dist/src/writing/patterns/formulaic-structures.json +1300 -0
  455. package/dist/src/writing/patterns/generic-adjectives.json +1510 -0
  456. package/dist/src/writing/patterns/hedging-language.json +2096 -0
  457. package/dist/src/writing/patterns/transition-words.json +1285 -0
  458. package/dist/src/writing/patterns/weak-verbs.json +1112 -0
  459. package/dist/src/writing/prompt-optimizer.js +660 -0
  460. package/dist/src/writing/prompt-templates.js +583 -0
  461. package/dist/src/writing/scoring-config-loader.js +168 -0
  462. package/dist/src/writing/validation-engine.js +595 -0
  463. package/dist/src/writing/validation-rules.js +380 -0
  464. package/dist/src/writing/voice-analyzer.js +439 -0
  465. package/dist/src/writing/voice-calibration.js +661 -0
  466. package/dist/src/writing/voice-profiles.json +588 -0
  467. package/package.json +65 -9
@@ -0,0 +1,717 @@
1
+ /**
2
+ * Ralph External Process Launcher
3
+ *
4
+ * Spawns the external Ralph supervisor as a detached background process
5
+ * that survives terminal closure and can be managed across sessions.
6
+ *
7
+ * @implements @.aiwg/working/issue-ralph-external-completion.md
8
+ * @issue #275
9
+ * @security docs/ralph-external-security.md
10
+ *
11
+ * SECURITY WARNING
12
+ * ================
13
+ * This module launches Claude Code sessions with --dangerously-skip-permissions.
14
+ * Spawned sessions can read/write ANY file and execute ANY command without
15
+ * user confirmation. Sessions run as detached daemons for extended periods
16
+ * without human oversight.
17
+ *
18
+ * BEFORE USING:
19
+ * - Read docs/ralph-external-security.md
20
+ * - Understand all security implications
21
+ * - Set appropriate limits (budget, iterations, timeout)
22
+ * - Ensure clean git state for rollback capability
23
+ * - Have monitoring and abort procedures ready
24
+ */
25
+ import { spawn } from 'child_process';
26
+ import { join } from 'path';
27
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, rmSync, readdirSync, copyFileSync, statSync, openSync, readSync, closeSync, } from 'fs';
28
+ import { getProviderConfig } from '../agent-spawn.js';
29
+ import { AiwgError, EXIT_CODES } from '../errors.js';
30
+ import { projectAiwgPath } from '../../config/project-artifacts.js';
31
+ /**
32
+ * Get the path to the external Ralph orchestrator
33
+ */
34
+ export function getOrchestratorPath(frameworkRoot) {
35
+ return join(frameworkRoot, 'tools', 'ralph-external', 'index.mjs');
36
+ }
37
+ /**
38
+ * Get the registry directory path
39
+ */
40
+ export function getRegistryDir(projectRoot) {
41
+ return projectAiwgPath(projectRoot, 'ralph-external');
42
+ }
43
+ /**
44
+ * Get the registry file path
45
+ */
46
+ export function getRegistryPath(projectRoot) {
47
+ return join(getRegistryDir(projectRoot), 'registry.json');
48
+ }
49
+ /**
50
+ * Generate a unique loop ID
51
+ */
52
+ export function generateLoopId(objective) {
53
+ const slug = objective
54
+ .toLowerCase()
55
+ .replace(/[^a-z0-9]+/g, '-')
56
+ .replace(/^-+|-+$/g, '')
57
+ .slice(0, 30);
58
+ const shortId = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
59
+ return `ralph-${slug}-${shortId}`;
60
+ }
61
+ /**
62
+ * Build command-line arguments for the external Ralph process
63
+ */
64
+ export function buildArgs(options) {
65
+ const args = [options.objective];
66
+ args.push('--completion', options.completionCriteria);
67
+ if (options.maxIterations) {
68
+ args.push('--max-iterations', String(options.maxIterations));
69
+ }
70
+ if (options.model) {
71
+ args.push('--model', options.model);
72
+ }
73
+ if (options.budget) {
74
+ args.push('--budget', String(options.budget));
75
+ }
76
+ if (options.maxTotalTokens) {
77
+ args.push('--max-total-tokens', String(options.maxTotalTokens));
78
+ }
79
+ if (options.maxOutputTokens) {
80
+ args.push('--max-output-tokens', String(options.maxOutputTokens));
81
+ }
82
+ if (options.maxToolCalls) {
83
+ args.push('--max-tool-calls', String(options.maxToolCalls));
84
+ }
85
+ if (options.maxTotalCost) {
86
+ args.push('--max-total-cost', String(options.maxTotalCost));
87
+ }
88
+ if (options.maxWallClockMinutes) {
89
+ args.push('--max-wall-clock-minutes', String(options.maxWallClockMinutes));
90
+ }
91
+ if (options.explorationQuota) {
92
+ args.push('--exploration-quota', String(options.explorationQuota));
93
+ }
94
+ if (options.budgetStopPolicy) {
95
+ args.push('--budget-stop-policy', options.budgetStopPolicy);
96
+ }
97
+ if (options.timeout) {
98
+ args.push('--timeout', String(options.timeout));
99
+ }
100
+ if (options.mcpConfig) {
101
+ args.push('--mcp-config', options.mcpConfig);
102
+ }
103
+ if (options.giteaIssue) {
104
+ args.push('--gitea-issue');
105
+ }
106
+ if (options.memory !== undefined) {
107
+ args.push('--memory', String(options.memory));
108
+ }
109
+ if (options.crossTask === false) {
110
+ args.push('--no-cross-task');
111
+ }
112
+ if (options.enableAnalytics === false) {
113
+ args.push('--no-analytics');
114
+ }
115
+ if (options.enableBestOutput === false) {
116
+ args.push('--no-best-output');
117
+ }
118
+ if (options.enableEarlyStopping === false) {
119
+ args.push('--no-early-stopping');
120
+ }
121
+ if (options.provider && options.provider !== 'claude') {
122
+ args.push('--provider', options.provider);
123
+ }
124
+ if (options.dangerous) {
125
+ args.push('--dangerous');
126
+ }
127
+ if (options.params) {
128
+ args.push('--params', options.params);
129
+ }
130
+ if (options.verbose) {
131
+ args.push('--verbose');
132
+ }
133
+ if (options.logFile) {
134
+ args.push('--log-file', options.logFile);
135
+ }
136
+ return args;
137
+ }
138
+ /**
139
+ * Enforce `parallelism.max_parallel_ralph_loops` from `.aiwg/aiwg.config`.
140
+ * Hard-fails (throws AiwgError) when the count of running + live Ralph loops
141
+ * already meets or exceeds the cap. Non-fatal when no config or config read
142
+ * fails — caller proceeds with launch.
143
+ *
144
+ * Extracted so the cap-check logic is unit-testable independently of the
145
+ * detached-process spawn machinery.
146
+ *
147
+ * @implements #1361
148
+ */
149
+ export async function assertRalphParallelismCap(projectRoot) {
150
+ let cfg;
151
+ let resolveParallelism;
152
+ try {
153
+ const mod = await import('../../config/aiwg-config.js');
154
+ resolveParallelism = mod.resolveParallelism;
155
+ cfg = await mod.readAiwgConfig(projectRoot);
156
+ }
157
+ catch {
158
+ return; // Config unreadable — non-fatal, let launch proceed
159
+ }
160
+ if (!cfg)
161
+ return;
162
+ const resolved = resolveParallelism(cfg.parallelism, cfg.providers[0]);
163
+ const launcherRegistry = loadLauncherRegistry(projectRoot);
164
+ const activeCount = Object.values(launcherRegistry.loops).filter((l) => l.status === 'running' && isProcessAlive(l.pid)).length;
165
+ if (activeCount >= resolved.max_parallel_ralph_loops) {
166
+ throw new AiwgError({
167
+ code: 'ERR_RALPH_PARALLELISM_CAP',
168
+ message: `Project parallelism cap reached: ${activeCount}/${resolved.max_parallel_ralph_loops} Ralph loops already running.`,
169
+ hint: `Wait for an existing loop to finish ('aiwg ralph-status'), or bump the cap ('aiwg config set --project parallelism.max_parallel_ralph_loops N').`,
170
+ exitCode: EXIT_CODES.GENERAL,
171
+ });
172
+ }
173
+ }
174
+ /**
175
+ * Launch the external Ralph process as a detached daemon
176
+ */
177
+ export async function launchExternalRalph(frameworkRoot, projectRoot, options) {
178
+ const orchestratorPath = getOrchestratorPath(frameworkRoot);
179
+ if (!existsSync(orchestratorPath)) {
180
+ throw new AiwgError({
181
+ code: 'ERR_RALPH_ORCHESTRATOR_MISSING',
182
+ message: `External Ralph orchestrator not found at: ${orchestratorPath}`,
183
+ hint: 'Run `aiwg use ralph` to deploy the orchestrator, or `npm run build` in the dev repo',
184
+ exitCode: EXIT_CODES.GENERAL,
185
+ });
186
+ }
187
+ const registryDir = getRegistryDir(projectRoot);
188
+ mkdirSync(registryDir, { recursive: true });
189
+ // #1361: Enforce project-level max_parallel_ralph_loops cap. Hard fail
190
+ // (not queue) — Ralph loops are long-running, silent queueing would be
191
+ // surprising. Tell the operator what's running and how to lift the cap.
192
+ await assertRalphParallelismCap(projectRoot);
193
+ const loopId = options.loopId || generateLoopId(options.objective);
194
+ const loopDir = join(registryDir, 'loops', loopId);
195
+ mkdirSync(loopDir, { recursive: true });
196
+ // Create output file for the detached process
197
+ const outputFile = join(loopDir, 'daemon-output.log');
198
+ const sessionStdoutFile = join(loopDir, 'outputs', '001-stdout.log');
199
+ const sessionStderrFile = join(loopDir, 'outputs', '001-stderr.log');
200
+ const promptFile = join(loopDir, 'prompts', '001-prompt.md');
201
+ // Build arguments
202
+ const args = buildArgs(options);
203
+ // Create output file descriptors
204
+ const { openSync, closeSync } = await import('fs');
205
+ const outFd = openSync(outputFile, 'w');
206
+ // Spawn detached process
207
+ const child = spawn('node', [orchestratorPath, ...args], {
208
+ detached: true,
209
+ stdio: ['ignore', outFd, outFd],
210
+ cwd: projectRoot,
211
+ env: {
212
+ ...process.env,
213
+ RALPH_LOOP_ID: loopId,
214
+ RALPH_DETACHED: 'true',
215
+ ...(options.provider ? { RALPH_PROVIDER: options.provider } : {}),
216
+ ...(options.dangerous ? {
217
+ RALPH_DANGEROUS: 'true',
218
+ RALPH_DANGEROUS_FLAG: getProviderConfig(options.provider ?? 'claude').dangerousFlag ?? '',
219
+ } : {}),
220
+ ...(options.params ? { RALPH_EXTRA_PARAMS: options.params } : {}),
221
+ },
222
+ });
223
+ // Detach from parent - let it run independently
224
+ child.unref();
225
+ closeSync(outFd);
226
+ const pid = child.pid;
227
+ if (!pid) {
228
+ throw new AiwgError({
229
+ code: 'ERR_RALPH_SPAWN_FAILED',
230
+ message: 'Failed to start external Ralph process — no PID returned by spawn',
231
+ hint: 'Check system resources (ulimit -u) and that `node` is on PATH',
232
+ exitCode: EXIT_CODES.GENERAL,
233
+ });
234
+ }
235
+ // Record the loop in our launcher registry (backup to the external-multi-loop-state-manager)
236
+ const launcherRegistry = loadLauncherRegistry(projectRoot);
237
+ launcherRegistry.loops[loopId] = {
238
+ loopId,
239
+ pid,
240
+ objective: options.objective,
241
+ completionCriteria: options.completionCriteria,
242
+ status: 'running',
243
+ startedAt: new Date().toISOString(),
244
+ lastUpdate: new Date().toISOString(),
245
+ iteration: 0,
246
+ maxIterations: options.maxIterations || 5,
247
+ outputFile,
248
+ sessionStdoutFile,
249
+ sessionStderrFile,
250
+ promptFile,
251
+ provider: options.provider,
252
+ };
253
+ saveLauncherRegistry(projectRoot, launcherRegistry);
254
+ return {
255
+ success: true,
256
+ loopId,
257
+ pid,
258
+ message: `agent loop started (${loopId}). Check status: aiwg ralph-status`,
259
+ registryPath: getRegistryPath(projectRoot),
260
+ };
261
+ }
262
+ /**
263
+ * Load the launcher registry
264
+ */
265
+ export function loadLauncherRegistry(projectRoot) {
266
+ const registryPath = join(getRegistryDir(projectRoot), 'launcher-registry.json');
267
+ if (!existsSync(registryPath)) {
268
+ return {
269
+ version: '1.0.0',
270
+ loops: {},
271
+ updatedAt: new Date().toISOString(),
272
+ };
273
+ }
274
+ try {
275
+ return JSON.parse(readFileSync(registryPath, 'utf8'));
276
+ }
277
+ catch {
278
+ return {
279
+ version: '1.0.0',
280
+ loops: {},
281
+ updatedAt: new Date().toISOString(),
282
+ };
283
+ }
284
+ }
285
+ /**
286
+ * Save the launcher registry
287
+ */
288
+ export function saveLauncherRegistry(projectRoot, registry) {
289
+ const registryDir = getRegistryDir(projectRoot);
290
+ mkdirSync(registryDir, { recursive: true });
291
+ const registryPath = join(registryDir, 'launcher-registry.json');
292
+ registry.updatedAt = new Date().toISOString();
293
+ writeFileSync(registryPath, JSON.stringify(registry, null, 2));
294
+ }
295
+ /**
296
+ * Check if a process is still running
297
+ */
298
+ export function isProcessAlive(pid) {
299
+ try {
300
+ process.kill(pid, 0);
301
+ return true;
302
+ }
303
+ catch {
304
+ return false;
305
+ }
306
+ }
307
+ /**
308
+ * Get status of all agent loops.
309
+ * Detects stale entries (>24h without heartbeat) and auto-cleans completed entries.
310
+ */
311
+ export function getLoopStatuses(projectRoot, options = {}) {
312
+ const registry = loadLauncherRegistry(projectRoot);
313
+ const statuses = [];
314
+ const staleThresholdMs = 24 * 60 * 60 * 1000; // 24 hours
315
+ let registryDirty = false;
316
+ for (const [loopId, entry] of Object.entries(registry.loops)) {
317
+ // Update status based on process liveness
318
+ if (entry.status === 'running' && !isProcessAlive(entry.pid)) {
319
+ // Process died - mark as failed unless we can determine it completed
320
+ const stateFile = join(getRegistryDir(projectRoot), 'loops', loopId, 'session-state.json');
321
+ if (existsSync(stateFile)) {
322
+ try {
323
+ const state = JSON.parse(readFileSync(stateFile, 'utf8'));
324
+ entry.status = state.status || 'failed';
325
+ entry.iteration = state.currentIteration || entry.iteration;
326
+ }
327
+ catch {
328
+ entry.status = 'failed';
329
+ }
330
+ }
331
+ else {
332
+ entry.status = 'failed';
333
+ }
334
+ registryDirty = true;
335
+ }
336
+ // Detect stale entries (>24h since last update)
337
+ const lastUpdateAge = Date.now() - new Date(entry.lastUpdate).getTime();
338
+ if (lastUpdateAge > staleThresholdMs && entry.status === 'running') {
339
+ entry.stale = true;
340
+ }
341
+ // Auto-clean completed entries if requested
342
+ if (options.autoCleanCompleted && (entry.status === 'completed')) {
343
+ cleanupCompletedLoop(projectRoot, loopId);
344
+ registryDirty = true;
345
+ continue; // Don't include in statuses
346
+ }
347
+ statuses.push(entry);
348
+ }
349
+ if (registryDirty) {
350
+ saveLauncherRegistry(projectRoot, registry);
351
+ }
352
+ return statuses;
353
+ }
354
+ /**
355
+ * Abort a running agent loop by killing its process
356
+ */
357
+ export function abortLoop(projectRoot, loopId) {
358
+ const registry = loadLauncherRegistry(projectRoot);
359
+ // If no loopId specified, find the most recent running loop
360
+ if (!loopId) {
361
+ const runningLoops = Object.values(registry.loops)
362
+ .filter((l) => l.status === 'running' && isProcessAlive(l.pid))
363
+ .sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
364
+ if (runningLoops.length === 0) {
365
+ return { success: false, message: 'No running agent loops found' };
366
+ }
367
+ loopId = runningLoops[0].loopId;
368
+ }
369
+ const entry = registry.loops[loopId];
370
+ if (!entry) {
371
+ return { success: false, message: `Loop not found: ${loopId}` };
372
+ }
373
+ if (!isProcessAlive(entry.pid)) {
374
+ entry.status = 'aborted';
375
+ saveLauncherRegistry(projectRoot, registry);
376
+ return { success: true, message: `Loop ${loopId} was already stopped` };
377
+ }
378
+ try {
379
+ process.kill(entry.pid, 'SIGTERM');
380
+ entry.status = 'aborted';
381
+ entry.lastUpdate = new Date().toISOString();
382
+ saveLauncherRegistry(projectRoot, registry);
383
+ return { success: true, message: `Aborted loop ${loopId} (PID: ${entry.pid})` };
384
+ }
385
+ catch (error) {
386
+ return {
387
+ success: false,
388
+ message: `Failed to kill process ${entry.pid}: ${error instanceof Error ? error.message : String(error)}`,
389
+ };
390
+ }
391
+ }
392
+ /**
393
+ * Resume an interrupted agent loop
394
+ */
395
+ export async function resumeLoop(frameworkRoot, projectRoot, loopId, overrides) {
396
+ const orchestratorPath = getOrchestratorPath(frameworkRoot);
397
+ if (!existsSync(orchestratorPath)) {
398
+ throw new AiwgError({
399
+ code: 'ERR_RALPH_ORCHESTRATOR_MISSING',
400
+ message: `External Ralph orchestrator not found at: ${orchestratorPath}`,
401
+ hint: 'Run `aiwg use ralph` to deploy the orchestrator',
402
+ exitCode: EXIT_CODES.GENERAL,
403
+ });
404
+ }
405
+ // Build resume arguments
406
+ const args = ['--resume'];
407
+ if (overrides?.maxIterations) {
408
+ args.push('--max-iterations', String(overrides.maxIterations));
409
+ }
410
+ const registryDir = getRegistryDir(projectRoot);
411
+ mkdirSync(registryDir, { recursive: true });
412
+ // Find loop to resume
413
+ const registry = loadLauncherRegistry(projectRoot);
414
+ let targetLoopId = loopId;
415
+ if (!targetLoopId) {
416
+ // Find most recent non-running loop
417
+ const resumable = Object.values(registry.loops)
418
+ .filter((l) => l.status !== 'running' || !isProcessAlive(l.pid))
419
+ .sort((a, b) => new Date(b.lastUpdate).getTime() - new Date(a.lastUpdate).getTime());
420
+ if (resumable.length === 0) {
421
+ throw new AiwgError({
422
+ code: 'ERR_RALPH_NO_RESUMABLE',
423
+ message: 'No loops available to resume',
424
+ hint: 'Start a new loop with: aiwg ralph "<objective>"',
425
+ exitCode: EXIT_CODES.USAGE,
426
+ });
427
+ }
428
+ targetLoopId = resumable[0].loopId;
429
+ }
430
+ const entry = registry.loops[targetLoopId];
431
+ if (!entry) {
432
+ throw new AiwgError({
433
+ code: 'ERR_RALPH_LOOP_NOT_FOUND',
434
+ message: `Loop not found: ${targetLoopId}`,
435
+ hint: 'List available loops with: aiwg ralph-status',
436
+ exitCode: EXIT_CODES.USAGE,
437
+ });
438
+ }
439
+ const loopDir = join(registryDir, 'loops', targetLoopId);
440
+ const outputFile = join(loopDir, 'daemon-output.log');
441
+ // Create output file descriptor
442
+ const { openSync, closeSync } = await import('fs');
443
+ const outFd = openSync(outputFile, 'a'); // Append mode for resume
444
+ // Spawn detached process
445
+ const child = spawn('node', [orchestratorPath, ...args], {
446
+ detached: true,
447
+ stdio: ['ignore', outFd, outFd],
448
+ cwd: projectRoot,
449
+ env: {
450
+ ...process.env,
451
+ RALPH_LOOP_ID: targetLoopId,
452
+ RALPH_DETACHED: 'true',
453
+ },
454
+ });
455
+ child.unref();
456
+ closeSync(outFd);
457
+ const pid = child.pid;
458
+ if (!pid) {
459
+ throw new AiwgError({
460
+ code: 'ERR_RALPH_SPAWN_FAILED',
461
+ message: 'Failed to start external Ralph process — no PID returned by spawn',
462
+ hint: 'Check system resources (ulimit -u) and that `node` is on PATH',
463
+ exitCode: EXIT_CODES.GENERAL,
464
+ });
465
+ }
466
+ // Update registry
467
+ entry.pid = pid;
468
+ entry.status = 'running';
469
+ entry.lastUpdate = new Date().toISOString();
470
+ if (overrides?.maxIterations) {
471
+ entry.maxIterations = overrides.maxIterations;
472
+ }
473
+ saveLauncherRegistry(projectRoot, registry);
474
+ return {
475
+ success: true,
476
+ loopId: targetLoopId,
477
+ pid,
478
+ message: `Resumed agent loop (${targetLoopId}). Check status: aiwg ralph-status`,
479
+ registryPath: getRegistryPath(projectRoot),
480
+ };
481
+ }
482
+ /**
483
+ * Clean up a completed loop: remove from launcher-registry and delete working state.
484
+ * Preserves completion reports by moving them to the ralph-external root before deletion.
485
+ *
486
+ * @param projectRoot - Project root directory
487
+ * @param loopId - Loop ID to clean up
488
+ * @param options - Cleanup options
489
+ * @returns Object with success status and details
490
+ */
491
+ export function cleanupCompletedLoop(projectRoot, loopId, options = {}) {
492
+ const registryDir = getRegistryDir(projectRoot);
493
+ const loopDir = join(registryDir, 'loops', loopId);
494
+ const preserved = [];
495
+ // Preserve completion reports before deleting the loop directory
496
+ if (existsSync(loopDir)) {
497
+ try {
498
+ const files = readdirSync(loopDir);
499
+ for (const file of files) {
500
+ if (file.startsWith('completion-') && file.endsWith('.md')) {
501
+ const dest = join(registryDir, file);
502
+ copyFileSync(join(loopDir, file), dest);
503
+ preserved.push(dest);
504
+ }
505
+ }
506
+ }
507
+ catch {
508
+ // Non-fatal: proceed with cleanup even if report preservation fails
509
+ }
510
+ if (options.archive) {
511
+ // Move to archive instead of deleting
512
+ const archiveDir = join(registryDir, 'archive', loopId);
513
+ mkdirSync(join(registryDir, 'archive'), { recursive: true });
514
+ try {
515
+ const { renameSync } = require('fs');
516
+ renameSync(loopDir, archiveDir);
517
+ }
518
+ catch {
519
+ // If rename fails (cross-device), fall through to deletion
520
+ }
521
+ }
522
+ else {
523
+ // Delete working state
524
+ try {
525
+ rmSync(loopDir, { recursive: true, force: true });
526
+ }
527
+ catch {
528
+ // Non-fatal
529
+ }
530
+ }
531
+ }
532
+ // Remove entry from launcher registry
533
+ const registry = loadLauncherRegistry(projectRoot);
534
+ if (registry.loops[loopId]) {
535
+ delete registry.loops[loopId];
536
+ saveLauncherRegistry(projectRoot, registry);
537
+ }
538
+ return {
539
+ success: true,
540
+ message: `Cleaned up loop ${loopId}`,
541
+ preserved,
542
+ };
543
+ }
544
+ /**
545
+ * Clean up internal Ralph state after successful completion.
546
+ * Deletes current-loop.json, heartbeats, and iteration working state.
547
+ * Preserves completion report files.
548
+ *
549
+ * @param projectRoot - Project root directory
550
+ * @returns Object with success status and what was cleaned
551
+ */
552
+ export function cleanupInternalRalph(projectRoot) {
553
+ const ralphDir = projectAiwgPath(projectRoot, 'ralph');
554
+ const cleaned = [];
555
+ const preserved = [];
556
+ if (!existsSync(ralphDir)) {
557
+ return { success: true, cleaned: [], preserved: [] };
558
+ }
559
+ // Check if current-loop.json exists and is completed
560
+ const currentLoopPath = join(ralphDir, 'current-loop.json');
561
+ if (existsSync(currentLoopPath)) {
562
+ try {
563
+ const state = JSON.parse(readFileSync(currentLoopPath, 'utf8'));
564
+ if (state.status === 'completed' || state.status === 'success') {
565
+ rmSync(currentLoopPath, { force: true });
566
+ cleaned.push('current-loop.json');
567
+ }
568
+ }
569
+ catch {
570
+ // If we can't parse it, leave it alone
571
+ }
572
+ }
573
+ // Clean up heartbeats directory
574
+ const heartbeatsDir = join(ralphDir, 'heartbeats');
575
+ if (existsSync(heartbeatsDir)) {
576
+ try {
577
+ rmSync(heartbeatsDir, { recursive: true, force: true });
578
+ cleaned.push('heartbeats/');
579
+ }
580
+ catch {
581
+ // Non-fatal
582
+ }
583
+ }
584
+ // Clean up iterations working state (but preserve completion reports)
585
+ const iterationsDir = join(ralphDir, 'iterations');
586
+ if (existsSync(iterationsDir)) {
587
+ try {
588
+ rmSync(iterationsDir, { recursive: true, force: true });
589
+ cleaned.push('iterations/');
590
+ }
591
+ catch {
592
+ // Non-fatal
593
+ }
594
+ }
595
+ // Log preserved completion reports
596
+ try {
597
+ const files = readdirSync(ralphDir);
598
+ for (const file of files) {
599
+ if (file.startsWith('completion-') && file.endsWith('.md')) {
600
+ preserved.push(file);
601
+ }
602
+ }
603
+ }
604
+ catch {
605
+ // Non-fatal
606
+ }
607
+ return { success: true, cleaned, preserved };
608
+ }
609
+ /**
610
+ * Clean up completed/failed loops from registry
611
+ */
612
+ export function cleanupRegistry(projectRoot, keepDays = 7) {
613
+ const registry = loadLauncherRegistry(projectRoot);
614
+ const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1000;
615
+ let cleaned = 0;
616
+ for (const [loopId, entry] of Object.entries(registry.loops)) {
617
+ if (entry.status !== 'running') {
618
+ const lastUpdate = new Date(entry.lastUpdate).getTime();
619
+ if (lastUpdate < cutoff) {
620
+ delete registry.loops[loopId];
621
+ cleaned++;
622
+ }
623
+ }
624
+ }
625
+ if (cleaned > 0) {
626
+ saveLauncherRegistry(projectRoot, registry);
627
+ }
628
+ return cleaned;
629
+ }
630
+ /**
631
+ * Attach to a running agent loop's output stream.
632
+ *
633
+ * Tails the loop's daemon-output.log to stdout in real-time.
634
+ * Ctrl+C detaches (the background loop keeps running).
635
+ * Returns a Promise that resolves when the user detaches or the loop exits.
636
+ */
637
+ export function attachToLoopOutput(projectRoot, loopId) {
638
+ const registry = loadLauncherRegistry(projectRoot);
639
+ const entries = Object.values(registry.loops);
640
+ let entry;
641
+ if (loopId) {
642
+ entry = registry.loops[loopId];
643
+ if (!entry) {
644
+ return Promise.reject(new Error(`Loop not found: ${loopId}`));
645
+ }
646
+ }
647
+ else {
648
+ // Use most recently started running loop
649
+ const running = entries
650
+ .filter((e) => e.status === 'running' && isProcessAlive(e.pid))
651
+ .sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
652
+ if (running.length === 0) {
653
+ return Promise.reject(new Error('No running loops to attach to. Use --loop-id to specify a loop.'));
654
+ }
655
+ entry = running[0];
656
+ }
657
+ const outputFile = entry.outputFile;
658
+ const attachedLoopId = entry.loopId;
659
+ return new Promise((resolve) => {
660
+ let offset = 0;
661
+ // Print any existing content
662
+ try {
663
+ const stats = statSync(outputFile);
664
+ if (stats.size > 0) {
665
+ const fd = openSync(outputFile, 'r');
666
+ const buf = Buffer.alloc(stats.size);
667
+ readSync(fd, buf, 0, stats.size, 0);
668
+ closeSync(fd);
669
+ process.stdout.write(buf);
670
+ offset = stats.size;
671
+ }
672
+ }
673
+ catch {
674
+ // Log file may not exist yet — will appear shortly
675
+ }
676
+ // Poll for new content every 250 ms. .unref() so the interval cannot
677
+ // outlive the resolve() path and hold the event loop alive.
678
+ const interval = setInterval(() => {
679
+ try {
680
+ const stats = statSync(outputFile);
681
+ if (stats.size > offset) {
682
+ const newBytes = stats.size - offset;
683
+ const fd = openSync(outputFile, 'r');
684
+ const buf = Buffer.alloc(newBytes);
685
+ readSync(fd, buf, 0, newBytes, offset);
686
+ closeSync(fd);
687
+ process.stdout.write(buf);
688
+ offset = stats.size;
689
+ }
690
+ // Stop polling if the process has exited
691
+ if (!isProcessAlive(registry.loops[attachedLoopId]?.pid ?? 0)) {
692
+ clearInterval(interval);
693
+ process.removeListener('SIGINT', onSigint);
694
+ process.stdout.write('\n[ralph-attach] Loop process has exited.\n');
695
+ resolve();
696
+ }
697
+ }
698
+ catch {
699
+ // File may be temporarily unavailable during rotation — ignore
700
+ }
701
+ }, 250);
702
+ interval.unref?.();
703
+ // Ctrl+C detaches without stopping the loop. Registered with named handler
704
+ // + process.once so we can remove it cleanly on process-exit path and so
705
+ // it does not accumulate across re-attach cycles within a single CLI run.
706
+ const onSigint = () => {
707
+ clearInterval(interval);
708
+ process.stdout.write('\n\nDetached from loop output. Loop continues in background.\n');
709
+ process.stdout.write(` Status: aiwg ralph-status\n`);
710
+ process.stdout.write(` Re-attach: aiwg ralph-attach --loop-id ${attachedLoopId}\n`);
711
+ process.stdout.write(` Abort: aiwg ralph-abort --loop-id ${attachedLoopId}\n`);
712
+ resolve();
713
+ };
714
+ process.once('SIGINT', onSigint);
715
+ });
716
+ }
717
+ //# sourceMappingURL=ralph-launcher.js.map