@rryando/arcs 3.10.0 → 4.0.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 (366) hide show
  1. package/README.md +172 -146
  2. package/dist/cli/agent-registry.d.ts +12 -0
  3. package/dist/cli/agent-registry.d.ts.map +1 -0
  4. package/dist/cli/agent-registry.js +67 -0
  5. package/dist/cli/agent-registry.js.map +1 -0
  6. package/dist/cli/arcs-flash.d.ts +2 -0
  7. package/dist/cli/arcs-flash.d.ts.map +1 -0
  8. package/dist/cli/arcs-flash.js +68 -0
  9. package/dist/cli/arcs-flash.js.map +1 -0
  10. package/dist/cli/arcs-orchestrate-caveman.d.ts +2 -14
  11. package/dist/cli/arcs-orchestrate-caveman.d.ts.map +1 -1
  12. package/dist/cli/arcs-orchestrate-caveman.js +6 -97
  13. package/dist/cli/arcs-orchestrate-caveman.js.map +1 -1
  14. package/dist/cli/arcs-orchestrate.d.ts +1 -1
  15. package/dist/cli/arcs-orchestrate.d.ts.map +1 -1
  16. package/dist/cli/arcs-orchestrate.js +40 -383
  17. package/dist/cli/arcs-orchestrate.js.map +1 -1
  18. package/dist/cli/bundle-installer.d.ts +10 -4
  19. package/dist/cli/bundle-installer.d.ts.map +1 -1
  20. package/dist/cli/bundle-installer.js +99 -6
  21. package/dist/cli/bundle-installer.js.map +1 -1
  22. package/dist/cli/commands/batch.js +4 -0
  23. package/dist/cli/commands/batch.js.map +1 -1
  24. package/dist/cli/commands/hooks.d.ts +76 -0
  25. package/dist/cli/commands/hooks.d.ts.map +1 -0
  26. package/dist/cli/commands/hooks.js +436 -0
  27. package/dist/cli/commands/hooks.js.map +1 -0
  28. package/dist/cli/commands/index.d.ts +2 -0
  29. package/dist/cli/commands/index.d.ts.map +1 -1
  30. package/dist/cli/commands/index.js +2 -0
  31. package/dist/cli/commands/index.js.map +1 -1
  32. package/dist/cli/commands/project.js +27 -0
  33. package/dist/cli/commands/project.js.map +1 -1
  34. package/dist/cli/commands/task.js +16 -1
  35. package/dist/cli/commands/task.js.map +1 -1
  36. package/dist/cli/commands/web.d.ts +2 -0
  37. package/dist/cli/commands/web.d.ts.map +1 -0
  38. package/dist/cli/commands/web.js +66 -0
  39. package/dist/cli/commands/web.js.map +1 -0
  40. package/dist/cli/config.d.ts +46 -3
  41. package/dist/cli/config.d.ts.map +1 -1
  42. package/dist/cli/config.js +95 -38
  43. package/dist/cli/config.js.map +1 -1
  44. package/dist/cli/instructions.d.ts +32 -7
  45. package/dist/cli/instructions.d.ts.map +1 -1
  46. package/dist/cli/instructions.js +99 -34
  47. package/dist/cli/instructions.js.map +1 -1
  48. package/dist/cli/orchestrator-shared-blocks.d.ts +31 -0
  49. package/dist/cli/orchestrator-shared-blocks.d.ts.map +1 -0
  50. package/dist/cli/orchestrator-shared-blocks.js +148 -0
  51. package/dist/cli/orchestrator-shared-blocks.js.map +1 -0
  52. package/dist/cli/setup.d.ts.map +1 -1
  53. package/dist/cli/setup.js +230 -91
  54. package/dist/cli/setup.js.map +1 -1
  55. package/dist/retrieval/index-builder.d.ts.map +1 -1
  56. package/dist/retrieval/index-builder.js +29 -1
  57. package/dist/retrieval/index-builder.js.map +1 -1
  58. package/dist/shared/session-vocabulary.d.ts +88 -0
  59. package/dist/shared/session-vocabulary.d.ts.map +1 -0
  60. package/dist/shared/session-vocabulary.js +114 -0
  61. package/dist/shared/session-vocabulary.js.map +1 -0
  62. package/dist/utils/claude-code-hook-install.d.ts +80 -0
  63. package/dist/utils/claude-code-hook-install.d.ts.map +1 -0
  64. package/dist/utils/claude-code-hook-install.js +211 -0
  65. package/dist/utils/claude-code-hook-install.js.map +1 -0
  66. package/dist/utils/claude-transcript.d.ts +206 -0
  67. package/dist/utils/claude-transcript.d.ts.map +1 -0
  68. package/dist/utils/claude-transcript.js +384 -0
  69. package/dist/utils/claude-transcript.js.map +1 -0
  70. package/dist/utils/diagram-generator.d.ts +1 -1
  71. package/dist/utils/diagram-generator.d.ts.map +1 -1
  72. package/dist/utils/diagram-generator.js +3 -2
  73. package/dist/utils/diagram-generator.js.map +1 -1
  74. package/dist/utils/errors.d.ts +6 -2
  75. package/dist/utils/errors.d.ts.map +1 -1
  76. package/dist/utils/errors.js +12 -0
  77. package/dist/utils/errors.js.map +1 -1
  78. package/dist/utils/git.d.ts +21 -0
  79. package/dist/utils/git.d.ts.map +1 -1
  80. package/dist/utils/git.js +65 -1
  81. package/dist/utils/git.js.map +1 -1
  82. package/dist/utils/hook-contract.d.ts +36 -0
  83. package/dist/utils/hook-contract.d.ts.map +1 -0
  84. package/dist/utils/hook-contract.js +35 -0
  85. package/dist/utils/hook-contract.js.map +1 -0
  86. package/dist/utils/hook-token-store.d.ts +61 -0
  87. package/dist/utils/hook-token-store.d.ts.map +1 -0
  88. package/dist/utils/hook-token-store.js +86 -0
  89. package/dist/utils/hook-token-store.js.map +1 -0
  90. package/dist/utils/json-schemas.d.ts +186 -2
  91. package/dist/utils/json-schemas.d.ts.map +1 -1
  92. package/dist/utils/json-schemas.js +48 -4
  93. package/dist/utils/json-schemas.js.map +1 -1
  94. package/dist/utils/knowledge-store.d.ts +7 -1
  95. package/dist/utils/knowledge-store.d.ts.map +1 -1
  96. package/dist/utils/knowledge-store.js +97 -65
  97. package/dist/utils/knowledge-store.js.map +1 -1
  98. package/dist/utils/plan-store.d.ts +8 -0
  99. package/dist/utils/plan-store.d.ts.map +1 -1
  100. package/dist/utils/plan-store.js +98 -59
  101. package/dist/utils/plan-store.js.map +1 -1
  102. package/dist/utils/project-resolver.d.ts +8 -0
  103. package/dist/utils/project-resolver.d.ts.map +1 -1
  104. package/dist/utils/project-resolver.js +7 -2
  105. package/dist/utils/project-resolver.js.map +1 -1
  106. package/dist/utils/session-store.d.ts +339 -0
  107. package/dist/utils/session-store.d.ts.map +1 -0
  108. package/dist/utils/session-store.js +577 -0
  109. package/dist/utils/session-store.js.map +1 -0
  110. package/dist/utils/storage-utils.d.ts +31 -0
  111. package/dist/utils/storage-utils.d.ts.map +1 -1
  112. package/dist/utils/storage-utils.js +116 -5
  113. package/dist/utils/storage-utils.js.map +1 -1
  114. package/dist/utils/task-store.d.ts +7 -0
  115. package/dist/utils/task-store.d.ts.map +1 -1
  116. package/dist/utils/task-store.js +73 -23
  117. package/dist/utils/task-store.js.map +1 -1
  118. package/dist/web-client/assets/GraphCanvas-CTyf_XXQ.js +1 -0
  119. package/dist/web-client/assets/MarkdownEditor-af2vwQOX.js +77 -0
  120. package/dist/web-client/assets/abnfDiagram-VRR7QNED-CdxcKX9t.js +1 -0
  121. package/dist/web-client/assets/arc-Bfaogrm1.js +1 -0
  122. package/dist/web-client/assets/architecture-TIHT7OUA-Bt2-DmfV.js +1 -0
  123. package/dist/web-client/assets/architectureDiagram-ZJ3FMSHR-DOISDv6o.js +36 -0
  124. package/dist/web-client/assets/array-BifhSqXX.js +1 -0
  125. package/dist/web-client/assets/blockDiagram-677ZJIJ3-DKwtbttM.js +132 -0
  126. package/dist/web-client/assets/c4Diagram-LMCZKHZV-CilqK-Mm.js +10 -0
  127. package/dist/web-client/assets/channel-C2mb9np_.js +1 -0
  128. package/dist/web-client/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  129. package/dist/web-client/assets/chunk-32BRIVSS-C79m1mkG.js +1 -0
  130. package/dist/web-client/assets/chunk-52WLFC77-C6WelGWJ.js +10 -0
  131. package/dist/web-client/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  132. package/dist/web-client/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  133. package/dist/web-client/assets/chunk-C7G6YPKG-DLg7ryWI.js +1 -0
  134. package/dist/web-client/assets/chunk-EX3LRPZG-DjWgo4gL.js +231 -0
  135. package/dist/web-client/assets/chunk-FWX5IMBZ-BgS9p_zy.js +2 -0
  136. package/dist/web-client/assets/chunk-HOUHSVGY-DuVR7dZO.js +1 -0
  137. package/dist/web-client/assets/chunk-ICXQ74PX-Y8DlnIJM.js +2 -0
  138. package/dist/web-client/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  139. package/dist/web-client/assets/chunk-KEIR6QF5-DEvma7oi.js +161 -0
  140. package/dist/web-client/assets/chunk-MOJQB5TN-BEM3QgeD.js +88 -0
  141. package/dist/web-client/assets/chunk-OGEWGWER-DlM8LxGr.js +1 -0
  142. package/dist/web-client/assets/chunk-PUDLZKDR-c6cqNVTx.js +156 -0
  143. package/dist/web-client/assets/chunk-Q4XR5HBZ-C5lNmcka.js +70 -0
  144. package/dist/web-client/assets/chunk-RYQCIY6F-np2RyIY1.js +1 -0
  145. package/dist/web-client/assets/chunk-V7JOEXUC-nSswxvSG.js +206 -0
  146. package/dist/web-client/assets/chunk-VAUOI2AC-CqJkCkT0.js +1 -0
  147. package/dist/web-client/assets/chunk-VR4S4FIN-D3pFchin.js +1 -0
  148. package/dist/web-client/assets/chunk-WYO6CB5R-BI9c-NzI.js +125 -0
  149. package/dist/web-client/assets/chunk-XXDRQBXY-BvKO0v-W.js +1 -0
  150. package/dist/web-client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  151. package/dist/web-client/assets/chunk-ZGVPDNZ5-CKTF2kLR.js +62 -0
  152. package/dist/web-client/assets/chunk-ZIRB5QZD-BpeS1aZ7.js +32 -0
  153. package/dist/web-client/assets/classDiagram-OUVF2IWQ-CPd_w3Zr.js +1 -0
  154. package/dist/web-client/assets/classDiagram-v2-EOCWNBFH-CPd_w3Zr.js +1 -0
  155. package/dist/web-client/assets/cose-bilkent-JH36ORCC-BebHqzgp.js +1 -0
  156. package/dist/web-client/assets/cynefin-VYW2F7L2-BrJrnfh1.js +1 -0
  157. package/dist/web-client/assets/cynefinDiagram-TSTJHNR4-9jYzPWJZ.js +62 -0
  158. package/dist/web-client/assets/cytoscape-fcose-peAzqedC.js +1 -0
  159. package/dist/web-client/assets/cytoscape.esm-C3UvhD5t.js +321 -0
  160. package/dist/web-client/assets/dagre-Buvkdvvj.js +1 -0
  161. package/dist/web-client/assets/dagre-VKFMJZFB-B705Djpu.js +4 -0
  162. package/dist/web-client/assets/defaultLocale-BFoDCU3G.js +1 -0
  163. package/dist/web-client/assets/diagram-FQU43EPY-BfQAlUlJ.js +3 -0
  164. package/dist/web-client/assets/diagram-G47NLZAW-s1YDe06A.js +24 -0
  165. package/dist/web-client/assets/diagram-NH7WQ7WH-Dy3z11Hc.js +24 -0
  166. package/dist/web-client/assets/diagram-OA4YK3LP-Bius2xUN.js +30 -0
  167. package/dist/web-client/assets/diagram-WEI45ONY-D7x4VcHM.js +41 -0
  168. package/dist/web-client/assets/dist-B_J_HbC0.js +1 -0
  169. package/dist/web-client/assets/ebnfDiagram-CCIWWBDH-CBg1xrmD.js +1 -0
  170. package/dist/web-client/assets/erDiagram-Q63AITRT-CJRvTFvd.js +85 -0
  171. package/dist/web-client/assets/eventmodeling-45OFAUF4-CTKRC2Yj.js +1 -0
  172. package/dist/web-client/assets/flowDiagram-23GEKE2U-CaZjFyU1.js +1 -0
  173. package/dist/web-client/assets/ganttDiagram-NO4QXBWP-C_LsypZ4.js +292 -0
  174. package/dist/web-client/assets/gitGraph-TEB2WS4Q-Dx2XxdGk.js +1 -0
  175. package/dist/web-client/assets/gitGraphDiagram-IHSO6WYX-DiKWkGWQ.js +106 -0
  176. package/dist/web-client/assets/graphlib-DS17s2tU.js +1 -0
  177. package/dist/web-client/assets/index-CYwhkPtc.js +60 -0
  178. package/dist/web-client/assets/index-wSzUPvml.css +2 -0
  179. package/dist/web-client/assets/info-DKCQHKI2-DORwHenK.js +1 -0
  180. package/dist/web-client/assets/infoDiagram-FWYZ7A6U-CQecXS1E.js +2 -0
  181. package/dist/web-client/assets/init-C-OQMol4.js +1 -0
  182. package/dist/web-client/assets/ishikawaDiagram-FXEZZL3T-CWhj60Zp.js +70 -0
  183. package/dist/web-client/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  184. package/dist/web-client/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  185. package/dist/web-client/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  186. package/dist/web-client/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  187. package/dist/web-client/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  188. package/dist/web-client/assets/journeyDiagram-5HDEW3XC-Cj3z2U8u.js +139 -0
  189. package/dist/web-client/assets/kanban-definition-HUTT4EX6-DFmBRenP.js +89 -0
  190. package/dist/web-client/assets/katex-DolUETbr.js +257 -0
  191. package/dist/web-client/assets/line-C_Hxz9xb.js +1 -0
  192. package/dist/web-client/assets/linear-DeUiD2wj.js +1 -0
  193. package/dist/web-client/assets/map-BaFkSB1l.js +1 -0
  194. package/dist/web-client/assets/mermaid-parser.core-E3xRdzPn.js +7 -0
  195. package/dist/web-client/assets/mermaid.core-C2_CcotH.js +11 -0
  196. package/dist/web-client/assets/mindmap-definition-LN4V7U3C-Bs7VxPid.js +96 -0
  197. package/dist/web-client/assets/ordinal-BDEzSJ7C.js +1 -0
  198. package/dist/web-client/assets/packet-7NZHBO7P-D2nqso7i.js +1 -0
  199. package/dist/web-client/assets/path-COt_16Va.js +1 -0
  200. package/dist/web-client/assets/pegDiagram-2B236MQR-Cepo1sIu.js +1 -0
  201. package/dist/web-client/assets/pie-RZYD4A2V-Sx0IGbXt.js +1 -0
  202. package/dist/web-client/assets/pieDiagram-ENE6RG2P-D-PMDNhk.js +39 -0
  203. package/dist/web-client/assets/quadrantDiagram-ABIIQ3AL-BNGC7Fms.js +7 -0
  204. package/dist/web-client/assets/radar-I7S5WNFK-CFf_-2OC.js +1 -0
  205. package/dist/web-client/assets/railroad-3IZDKUUU-BvZeVRGh.js +1 -0
  206. package/dist/web-client/assets/railroad-abnf-AHOZXSZD-DnGh6x2O.js +1 -0
  207. package/dist/web-client/assets/railroad-ebnf-EBAXGLYW-CGfgCoaE.js +1 -0
  208. package/dist/web-client/assets/railroad-peg-LSFZ7HO6-BzQxYdqp.js +1 -0
  209. package/dist/web-client/assets/railroadDiagram-RFXS5EU6-D0iK_k84.js +1 -0
  210. package/dist/web-client/assets/requirementDiagram-TGXJPOKE-BPdsw9tz.js +84 -0
  211. package/dist/web-client/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  212. package/dist/web-client/assets/rough.esm-By172zw-.js +1 -0
  213. package/dist/web-client/assets/sankeyDiagram-HTMAVEWB-maA6ukOJ.js +40 -0
  214. package/dist/web-client/assets/sequenceDiagram-DBY2YBRQ-DKmAjmgr.js +162 -0
  215. package/dist/web-client/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  216. package/dist/web-client/assets/src-oBChb5qS.js +1 -0
  217. package/dist/web-client/assets/stateDiagram-2N3HPSRC-esxmzk3w.js +1 -0
  218. package/dist/web-client/assets/stateDiagram-v2-6OUMAXLB-hcBqlOLc.js +1 -0
  219. package/dist/web-client/assets/swimlanes-5IMT3BWC-DFd-wGBv.js +2 -0
  220. package/dist/web-client/assets/swimlanesDiagram-G3AALYLV-DbSrPBYr.js +8 -0
  221. package/dist/web-client/assets/timeline-definition-FHXFAJF6-C7SG8MQH.js +120 -0
  222. package/dist/web-client/assets/treeView-QDETBFTQ-M0rhxbs2.js +1 -0
  223. package/dist/web-client/assets/treemap-6X3UGDF4-BQfkQxSh.js +1 -0
  224. package/dist/web-client/assets/vennDiagram-L72KCM5P-CyIlb8ju.js +34 -0
  225. package/dist/web-client/assets/wardley-OPB4EBWU-EE-7q8M1.js +1 -0
  226. package/dist/web-client/assets/wardleyDiagram-EHGQE667-bY8XdYYS.js +78 -0
  227. package/dist/web-client/assets/xychartDiagram-FW5EYKEG-AhuXJ3de.js +7 -0
  228. package/dist/web-client/index.html +15 -0
  229. package/dist/web-server/app.d.ts +16 -0
  230. package/dist/web-server/app.d.ts.map +1 -0
  231. package/dist/web-server/app.js +77 -0
  232. package/dist/web-server/app.js.map +1 -0
  233. package/dist/web-server/claude-runner.d.ts +188 -0
  234. package/dist/web-server/claude-runner.d.ts.map +1 -0
  235. package/dist/web-server/claude-runner.js +599 -0
  236. package/dist/web-server/claude-runner.js.map +1 -0
  237. package/dist/web-server/hook-auth.d.ts +12 -0
  238. package/dist/web-server/hook-auth.d.ts.map +1 -0
  239. package/dist/web-server/hook-auth.js +36 -0
  240. package/dist/web-server/hook-auth.js.map +1 -0
  241. package/dist/web-server/index.d.ts +23 -0
  242. package/dist/web-server/index.d.ts.map +1 -0
  243. package/dist/web-server/index.js +50 -0
  244. package/dist/web-server/index.js.map +1 -0
  245. package/dist/web-server/opencode-client.d.ts +123 -0
  246. package/dist/web-server/opencode-client.d.ts.map +1 -0
  247. package/dist/web-server/opencode-client.js +514 -0
  248. package/dist/web-server/opencode-client.js.map +1 -0
  249. package/dist/web-server/permission-policy.d.ts +46 -0
  250. package/dist/web-server/permission-policy.d.ts.map +1 -0
  251. package/dist/web-server/permission-policy.js +96 -0
  252. package/dist/web-server/permission-policy.js.map +1 -0
  253. package/dist/web-server/prompt-assembly.d.ts +454 -0
  254. package/dist/web-server/prompt-assembly.d.ts.map +1 -0
  255. package/dist/web-server/prompt-assembly.js +1122 -0
  256. package/dist/web-server/prompt-assembly.js.map +1 -0
  257. package/dist/web-server/respond.d.ts +33 -0
  258. package/dist/web-server/respond.d.ts.map +1 -0
  259. package/dist/web-server/respond.js +79 -0
  260. package/dist/web-server/respond.js.map +1 -0
  261. package/dist/web-server/routes/collections.d.ts +11 -0
  262. package/dist/web-server/routes/collections.d.ts.map +1 -0
  263. package/dist/web-server/routes/collections.js +217 -0
  264. package/dist/web-server/routes/collections.js.map +1 -0
  265. package/dist/web-server/routes/discovery.d.ts +7 -0
  266. package/dist/web-server/routes/discovery.d.ts.map +1 -0
  267. package/dist/web-server/routes/discovery.js +159 -0
  268. package/dist/web-server/routes/discovery.js.map +1 -0
  269. package/dist/web-server/routes/events.d.ts +6 -0
  270. package/dist/web-server/routes/events.d.ts.map +1 -0
  271. package/dist/web-server/routes/events.js +25 -0
  272. package/dist/web-server/routes/events.js.map +1 -0
  273. package/dist/web-server/routes/hook-events.d.ts +44 -0
  274. package/dist/web-server/routes/hook-events.d.ts.map +1 -0
  275. package/dist/web-server/routes/hook-events.js +320 -0
  276. package/dist/web-server/routes/hook-events.js.map +1 -0
  277. package/dist/web-server/routes/projects.d.ts +7 -0
  278. package/dist/web-server/routes/projects.d.ts.map +1 -0
  279. package/dist/web-server/routes/projects.js +272 -0
  280. package/dist/web-server/routes/projects.js.map +1 -0
  281. package/dist/web-server/routes/sessions.d.ts +18 -0
  282. package/dist/web-server/routes/sessions.d.ts.map +1 -0
  283. package/dist/web-server/routes/sessions.js +1298 -0
  284. package/dist/web-server/routes/sessions.js.map +1 -0
  285. package/dist/web-server/routes/workspace.d.ts +27 -0
  286. package/dist/web-server/routes/workspace.d.ts.map +1 -0
  287. package/dist/web-server/routes/workspace.js +280 -0
  288. package/dist/web-server/routes/workspace.js.map +1 -0
  289. package/dist/web-server/run-event-log.d.ts +167 -0
  290. package/dist/web-server/run-event-log.d.ts.map +1 -0
  291. package/dist/web-server/run-event-log.js +468 -0
  292. package/dist/web-server/run-event-log.js.map +1 -0
  293. package/dist/web-server/security.d.ts +7 -0
  294. package/dist/web-server/security.d.ts.map +1 -0
  295. package/dist/web-server/security.js +41 -0
  296. package/dist/web-server/security.js.map +1 -0
  297. package/dist/web-server/session-reconciler.d.ts +162 -0
  298. package/dist/web-server/session-reconciler.d.ts.map +1 -0
  299. package/dist/web-server/session-reconciler.js +363 -0
  300. package/dist/web-server/session-reconciler.js.map +1 -0
  301. package/dist/web-server/static.d.ts +17 -0
  302. package/dist/web-server/static.d.ts.map +1 -0
  303. package/dist/web-server/static.js +79 -0
  304. package/dist/web-server/static.js.map +1 -0
  305. package/dist/web-server/storage.d.ts +17 -0
  306. package/dist/web-server/storage.d.ts.map +1 -0
  307. package/dist/web-server/storage.js +42 -0
  308. package/dist/web-server/storage.js.map +1 -0
  309. package/dist/web-server/watcher.d.ts +37 -0
  310. package/dist/web-server/watcher.d.ts.map +1 -0
  311. package/dist/web-server/watcher.js +181 -0
  312. package/dist/web-server/watcher.js.map +1 -0
  313. package/dist/web-server/web-auth.d.ts +17 -0
  314. package/dist/web-server/web-auth.d.ts.map +1 -0
  315. package/dist/web-server/web-auth.js +33 -0
  316. package/dist/web-server/web-auth.js.map +1 -0
  317. package/dist/web-server/web-token.d.ts +39 -0
  318. package/dist/web-server/web-token.d.ts.map +1 -0
  319. package/dist/web-server/web-token.js +71 -0
  320. package/dist/web-server/web-token.js.map +1 -0
  321. package/opencode/arcs/bundle-runtime.json +5 -13
  322. package/opencode/arcs/manifest.json +215 -151
  323. package/opencode/arcs/prompts/arcs-docs.txt +53 -47
  324. package/opencode/arcs/prompts/arcs-flash.txt +190 -0
  325. package/opencode/arcs/prompts/arcs-orchestrate-caveman.txt +116 -422
  326. package/opencode/arcs/prompts/arcs-orchestrate.txt +114 -341
  327. package/opencode/arcs/prompts/code-reviewer.txt +37 -98
  328. package/opencode/arcs/prompts/devil-advocate.txt +44 -115
  329. package/opencode/arcs/prompts/graph-explorer.txt +31 -179
  330. package/opencode/arcs/prompts/software-engineer.txt +24 -6
  331. package/opencode/arcs/prompts/tech-architect.txt +25 -9
  332. package/opencode/arcs/skills/brainstorming/SKILL.md +65 -105
  333. package/opencode/arcs/skills/deep-pr-review/SKILL.md +5 -5
  334. package/opencode/arcs/skills/deep-pr-review/review-template.md +1 -1
  335. package/opencode/arcs/skills/enriching-codegraph-proposals/SKILL.md +17 -18
  336. package/opencode/arcs/skills/executing-plans/SKILL.md +26 -234
  337. package/opencode/arcs/skills/implementation/SKILL.md +61 -0
  338. package/opencode/arcs/skills/init-project/SKILL.md +16 -15
  339. package/opencode/arcs/skills/install-claude-code-hook/SKILL.md +143 -0
  340. package/opencode/arcs/skills/systematic-debugging/SKILL.md +7 -7
  341. package/opencode/arcs/skills/test-driven-development/SKILL.md +1 -1
  342. package/opencode/arcs/skills/to-diagram/SKILL.md +8 -3
  343. package/opencode/arcs/skills/writing-knowledge/SKILL.md +7 -6
  344. package/opencode/arcs/skills/writing-plans/SKILL.md +80 -130
  345. package/opencode/arcs/skills/writing-plans/plan-document-reviewer-prompt.md +38 -30
  346. package/package.json +14 -6
  347. package/scripts/build-opencode-bundle.mjs +22 -7
  348. package/scripts/claude-code-session-hook.mjs +171 -0
  349. package/scripts/deploy-claudecode-bundle.mjs +206 -132
  350. package/scripts/deploy-opencode-bundle.mjs +181 -5
  351. package/scripts/lib/bundle-helpers.mjs +26 -0
  352. package/scripts/lint-bundle.mjs +123 -3
  353. package/skills/explore-dag.md +5 -3
  354. package/skills/init-project.md +27 -26
  355. package/skills/orchestrate.md +29 -13
  356. package/skills/update-docs.md +8 -13
  357. package/opencode/arcs/prompts/docs-researcher.txt +0 -79
  358. package/opencode/arcs/prompts/oncall-ops.txt +0 -85
  359. package/opencode/arcs/skills/code-agent/SKILL.md +0 -63
  360. package/opencode/arcs/skills/executing-plans/code-quality-reviewer-prompt.md +0 -57
  361. package/opencode/arcs/skills/executing-plans/implementer-prompt.md +0 -152
  362. package/opencode/arcs/skills/executing-plans/spec-reviewer-prompt.md +0 -91
  363. package/opencode/arcs/skills/quick-dev/SKILL.md +0 -52
  364. package/opencode/arcs/skills/requesting-code-review/SKILL.md +0 -59
  365. package/opencode/arcs/skills/requesting-code-review/code-reviewer.md +0 -139
  366. package/opencode/arcs/skills/the-ladder/SKILL.md +0 -54
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ARCS ↔ Claude Code session-bridge hook.
4
+ *
5
+ * Registered four times in settings.json (SessionStart, UserPromptSubmit,
6
+ * SessionEnd, Stop) and dispatches internally on the `hook_event_name` field
7
+ * Claude Code writes to stdin. Install with `arcs hooks install-claude-code
8
+ * <slug>`, which generates the token and prints the snippet to paste.
9
+ *
10
+ * Two of the four can put text in front of the model: SessionStart mirrors
11
+ * ARCS's staged environment (project, workspace, DAG position) into the new
12
+ * session, and UserPromptSubmit delivers messages queued from the web UI. Both
13
+ * emit Claude Code's `hookSpecificOutput` envelope on stdout; the other two
14
+ * print nothing.
15
+ *
16
+ * HARD RULE: this script never blocks the session. Any failure — ARCS not
17
+ * running, token rejected, timeout, malformed JSON — is swallowed, nothing is
18
+ * printed, and the exit code stays 0. Exit code 2 (the "block" signal) is never
19
+ * produced. A broken bridge must be invisible, never an obstacle to the user's
20
+ * actual Claude Code session.
21
+ *
22
+ * Config comes from the environment, assigned inline in the settings.json
23
+ * command string:
24
+ * ARCS_HOOK_TOKEN per-project token (required)
25
+ * ARCS_HOOK_SLUG ARCS project slug (required)
26
+ * ARCS_HOOK_URL ARCS web server URL (default http://127.0.0.1:4173)
27
+ */
28
+
29
+ // DEFAULT_URL and EVENTS are literals on purpose: this file runs standalone out
30
+ // of the user's settings.json and importing ARCS would give the HARD RULE above
31
+ // a way to fail. `src/utils/hook-contract.ts` owns the same two values for the
32
+ // TypeScript side, and `test/hook-contract-parity.test.ts` parses THIS source
33
+ // and fails if the two ever diverge — so keep the shapes greppable: a
34
+ // double-quoted DEFAULT_URL, and a flat `new Set([...])` of string literals.
35
+ const DEFAULT_URL = "http://127.0.0.1:4173";
36
+ /** Short by design: a hung ARCS server must not stall prompt submission. */
37
+ const TIMEOUT_MS = 1500;
38
+ const EVENTS = new Set(["SessionStart", "UserPromptSubmit", "SessionEnd", "Stop"]);
39
+ /**
40
+ * Refusal bound on a context block the server sends, in characters.
41
+ *
42
+ * The server caps the SessionStart block at 2500 (`SESSION_START_STAGE_CAP` in
43
+ * `src/web-server/routes/hook-events.ts`); this is the CLIENT's own limit, so a
44
+ * misbehaving, mismatched or hostile ARCS cannot shove an unbounded body into
45
+ * the head of the user's live session. Over the bound the block is dropped
46
+ * whole rather than clipped — a clip would sever a wrapper's closing delimiter.
47
+ * `test/claude-code-hook-script.test.ts` parses this literal and fails if the
48
+ * server's cap ever climbs above it, so the two cannot silently cross.
49
+ */
50
+ const MAX_CONTEXT_CHARS = 4000;
51
+
52
+ /** Never rejects: an unreadable stdin yields "" and the run turns into a no-op. */
53
+ function readStdin() {
54
+ return new Promise((resolveStdin) => {
55
+ let raw = "";
56
+ let settled = false;
57
+ const finish = () => {
58
+ if (settled) return;
59
+ settled = true;
60
+ clearTimeout(timer);
61
+ process.stdin.destroy();
62
+ resolveStdin(raw);
63
+ };
64
+ const timer = setTimeout(finish, TIMEOUT_MS);
65
+
66
+ process.stdin.setEncoding("utf-8");
67
+ process.stdin.on("data", (chunk) => {
68
+ raw += chunk;
69
+ });
70
+ process.stdin.on("end", finish);
71
+ process.stdin.on("error", finish);
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Labelled and separated so the agent can tell queued out-of-band instructions
77
+ * from the prompt the user just typed.
78
+ */
79
+ function formatQueued(messages) {
80
+ const body = messages.map((m, i) => `[${i + 1}] ${String(m).trim()}`).join("\n\n");
81
+ return `Messages queued from the ARCS web UI, delivered at this checkpoint:\n\n${body}`;
82
+ }
83
+
84
+ async function main() {
85
+ const raw = await readStdin();
86
+ if (!raw.trim()) return;
87
+
88
+ const event = JSON.parse(raw);
89
+ const eventName = event?.hook_event_name;
90
+ const sessionId = event?.session_id;
91
+ if (!EVENTS.has(eventName) || typeof sessionId !== "string" || !sessionId) return;
92
+
93
+ const token = process.env.ARCS_HOOK_TOKEN;
94
+ const slug = process.env.ARCS_HOOK_SLUG;
95
+ if (!token || !slug) return;
96
+ const baseUrl = (process.env.ARCS_HOOK_URL || DEFAULT_URL).replace(/\/+$/, "");
97
+
98
+ const response = await fetch(`${baseUrl}/api/hook/${encodeURIComponent(slug)}/event`, {
99
+ method: "POST",
100
+ headers: {
101
+ "content-type": "application/json",
102
+ authorization: `Bearer ${token}`,
103
+ },
104
+ body: JSON.stringify({
105
+ hook_event_name: eventName,
106
+ session_id: sessionId,
107
+ ...(typeof event.cwd === "string" && { cwd: event.cwd }),
108
+ ...(typeof event.source === "string" && { source: event.source }),
109
+ ...(typeof event.reason === "string" && { reason: event.reason }),
110
+ ...(typeof event.transcript_path === "string" && { transcript_path: event.transcript_path }),
111
+ }),
112
+ signal: AbortSignal.timeout(TIMEOUT_MS),
113
+ });
114
+ if (!response.ok) return;
115
+
116
+ // Two events can inject context: SessionStart mirrors ARCS's staged
117
+ // environment into the fresh session, UserPromptSubmit delivers whatever the
118
+ // web UI queued. SessionEnd and Stop are pure notifications and answer with
119
+ // empty stdout.
120
+ if (eventName !== "SessionStart" && eventName !== "UserPromptSubmit") return;
121
+
122
+ const envelope = await response.json();
123
+
124
+ if (eventName === "SessionStart") {
125
+ const staged = envelope?.data?.stagedContext;
126
+ // Every rejection here is a silent no-op, never a repair: an absent field,
127
+ // a non-string, an empty string and an oversized body all mean "ARCS has
128
+ // nothing usable to stage", and the session proceeds exactly as if the
129
+ // bridge were not installed.
130
+ if (typeof staged !== "string" || staged === "" || staged.length > MAX_CONTEXT_CHARS) return;
131
+
132
+ process.stdout.write(
133
+ JSON.stringify({
134
+ hookSpecificOutput: {
135
+ hookEventName: "SessionStart",
136
+ additionalContext: staged,
137
+ },
138
+ }),
139
+ );
140
+ return;
141
+ }
142
+
143
+ const messages = envelope?.data?.queuedMessages;
144
+ if (!Array.isArray(messages) || messages.length === 0) return;
145
+
146
+ process.stdout.write(
147
+ JSON.stringify({
148
+ hookSpecificOutput: {
149
+ hookEventName: "UserPromptSubmit",
150
+ additionalContext: formatQueued(messages),
151
+ },
152
+ }),
153
+ );
154
+ }
155
+
156
+ // Belt and braces around the hard rule: even a bug in this file (or a stray
157
+ // async rejection) must not surface as a non-zero exit for the user.
158
+ process.on("uncaughtException", () => {
159
+ process.exitCode = 0;
160
+ });
161
+ process.on("unhandledRejection", () => {
162
+ process.exitCode = 0;
163
+ });
164
+
165
+ // No process.exit(): letting the event loop drain guarantees stdout is flushed
166
+ // before the process ends, and the default exit code is already 0.
167
+ main()
168
+ .catch(() => {})
169
+ .finally(() => {
170
+ process.exitCode = 0;
171
+ });
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+
2
3
  // Deploy claudecode ARCS bundle from repo to Claude Code config.
3
4
  //
4
5
  // Direction: repo → config ONLY. Never writes config → repo.
@@ -8,7 +9,9 @@
8
9
  // 2. Skills tree → <destination>/skills/arcs-<name>/...
9
10
  // (Claude Code skills must be flat under skills/; we use the `arcs-`
10
11
  // prefix as a namespace so orphan pruning never touches user skills.)
11
- // 3. Default agent → settings.json `agent` field set to "arcs-orchestrate"
12
+ // 3. Default agent → settings.json `agent` field, resolved from an
13
+ // explicit DEPLOY_PRIMARY_AGENT selection, else through the
14
+ // DEFAULT_AGENT_PRECEDENCE list (default: "arcs-orchestrate")
12
15
  //
13
16
  // Env vars:
14
17
  // DEPLOY_BUNDLE_ROOT — override bundle root (default: opencode/arcs)
@@ -16,10 +19,13 @@
16
19
  // DEPLOY_PROJECT_ROOT — override project root (default: repository root)
17
20
  // DEPLOY_SCOPE — `global` or `project` (default: `global`)
18
21
  // DEPLOY_DRY_RUN — "false" to actually write; anything else = dry-run (default: dry-run)
22
+ // DEPLOY_PRIMARY_AGENT — user-selected default primary agent id; empty/unset falls
23
+ // back to DEFAULT_AGENT_PRECEDENCE
19
24
  //
20
25
  // Outputs JSON to stdout: DeployResult
21
26
  // Exit code: 0 on success, 1 on error.
22
27
 
28
+ import { createHash } from "node:crypto";
23
29
  import {
24
30
  existsSync,
25
31
  mkdirSync,
@@ -32,7 +38,13 @@ import {
32
38
  import { homedir } from "node:os";
33
39
  import { dirname, relative, resolve } from "node:path";
34
40
  import { fileURLToPath } from "node:url";
35
- import { wireCodegraphMcp, wireRtk } from "./lib/bundle-helpers.mjs";
41
+ import {
42
+ isActiveAgentForMode,
43
+ isRetiredAgentForMode,
44
+ validateRetirementReplacements,
45
+ wireCodegraphMcp,
46
+ wireRtk,
47
+ } from "./lib/bundle-helpers.mjs";
36
48
 
37
49
  const scriptDir = dirname(fileURLToPath(import.meta.url));
38
50
  const repoRoot = resolve(scriptDir, "..");
@@ -67,9 +79,30 @@ const dryRun = process.env.DEPLOY_DRY_RUN !== "false";
67
79
 
68
80
  const destination = scope === "project" ? projectRoot : configRoot;
69
81
 
70
- const DEFAULT_AGENT = "arcs-orchestrate";
71
82
  const SKILL_PREFIX = "arcs-";
72
83
 
84
+ function isPromptPath(value) {
85
+ if (typeof value !== "string" || value.includes("\\")) return false;
86
+ const segments = value.split("/");
87
+ return (
88
+ segments.length >= 2 &&
89
+ segments[0] === "prompts" &&
90
+ segments.slice(1).every((segment) => segment !== "" && segment !== "." && segment !== "..") &&
91
+ segments.at(-1).endsWith(".txt")
92
+ );
93
+ }
94
+
95
+ function resolveBundlePromptPath(value) {
96
+ if (!isPromptPath(value)) throw new Error(`Invalid bundle prompt path: ${value}`);
97
+ const promptsRoot = resolve(bundleRoot, "prompts");
98
+ const resolvedPath = resolve(promptsRoot, ...value.split("/").slice(1));
99
+ const relativePath = relative(promptsRoot, resolvedPath);
100
+ if (relativePath.split(/[\\/]/).includes("..")) {
101
+ throw new Error(`Bundle prompt path escapes prompts/: ${value}`);
102
+ }
103
+ return resolvedPath;
104
+ }
105
+
73
106
  // ---------------------------------------------------------------------------
74
107
  // Model tier configuration
75
108
  // ---------------------------------------------------------------------------
@@ -81,102 +114,80 @@ const tierModels = {
81
114
  light: process.env.DEPLOY_MODEL_LIGHT || "inherit",
82
115
  };
83
116
 
84
- /** Maps each agent stem to a tier. Falls back to "standard". */
85
- const agentTierMap = {
86
- "software-engineer": "heavy",
87
- "docs-researcher": "heavy",
88
- "arcs-docs": "heavy",
89
- "oncall-ops": "heavy",
90
- "arcs-orchestrate": "standard",
91
- "arcs-orchestrate-caveman": "standard",
92
- "devil-advocate": "standard",
93
- "graph-explorer": "light",
94
- "code-reviewer": "light",
95
- "tech-architect": "light",
96
- };
117
+ function readAgentRegistry() {
118
+ const manifestPath = resolve(bundleRoot, "manifest.json");
119
+ if (!existsSync(manifestPath)) throw new Error(`Agent registry not found at ${manifestPath}`);
120
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
121
+ if (!Array.isArray(manifest.agents))
122
+ throw new Error("Invalid agent registry: agents must be an array");
123
+
124
+ const ids = new Set();
125
+ const sources = new Set();
126
+ const destinations = new Set();
127
+ for (const agent of manifest.agents) {
128
+ const valid =
129
+ agent &&
130
+ typeof agent.id === "string" &&
131
+ /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agent.id) &&
132
+ ["active", "retired"].includes(agent.status) &&
133
+ ["primary", "subagent"].includes(agent.kind) &&
134
+ ["heavy", "standard", "light"].includes(agent.tier) &&
135
+ Array.isArray(agent.modes) &&
136
+ agent.modes.length > 0 &&
137
+ agent.modes.every((mode) => ["opencode", "claudecode"].includes(mode)) &&
138
+ isPromptPath(agent.source) &&
139
+ isPromptPath(agent.destination) &&
140
+ typeof agent.description === "string" &&
141
+ agent.description.length > 0 &&
142
+ agent.permissions &&
143
+ ["allow", "deny"].includes(agent.permissions.edit) &&
144
+ ["allow", "deny"].includes(agent.permissions.bash) &&
145
+ ["allow", "deny"].includes(agent.permissions.webfetch) &&
146
+ ["allow", "deny"].includes(agent.permissions.mcp) &&
147
+ ["allow", "deny"].includes(agent.permissions.task);
148
+ if (!valid) throw new Error(`Invalid agent registry record: ${JSON.stringify(agent)}`);
149
+ if (ids.has(agent.id)) throw new Error(`Duplicate agent registry id: ${agent.id}`);
150
+ if (sources.has(agent.source))
151
+ throw new Error(`Duplicate agent registry source: ${agent.source}`);
152
+ if (destinations.has(agent.destination))
153
+ throw new Error(`Duplicate agent registry destination: ${agent.destination}`);
154
+ ids.add(agent.id);
155
+ sources.add(agent.source);
156
+ destinations.add(agent.destination);
157
+ }
158
+ validateRetirementReplacements(manifest.agents);
159
+ return manifest.agents;
160
+ }
97
161
 
98
- // Agent descriptions mirror opencode/arcs/manifest.json (canonical) — keep in sync.
99
- const agentMetadata = {
100
- "software-engineer": {
101
- name: "Software Engineer",
102
- description:
103
- "Implementation specialist. Writes code, runs tests, ships features. Loads quick-dev, code-agent, test-driven-development, and executing-plans skills as needed.",
104
- tools: "Read, Write, Edit, Glob, Grep, Bash",
105
- model: "inherit",
106
- },
107
- "devil-advocate": {
108
- name: "Devil's Advocate",
109
- description:
110
- "Adversarial phase-gate agent. Checks work at phase boundaries using KISS/YAGNI/DRY principles. Runs tests, reads diffs, delivers pass/block verdicts. Cannot edit code.",
111
- tools: "Read, Glob, Grep, Bash",
112
- model: "inherit",
113
- },
114
- "graph-explorer": {
115
- name: "Graph Explorer",
116
- description:
117
- "DAG-first codebase and knowledge exploration specialist. Queries arcs search, related, and context first, then codegraph MCP code-intelligence tools, before falling back to raw file-system tools. Replaces vanilla explore for ARCS projects.",
118
- tools: "Read, Glob, Grep, Bash",
119
- model: "inherit",
120
- },
121
- "tech-architect": {
122
- name: "Technical Architect",
123
- description:
124
- "Architecture and analysis specialist. Deep structural reasoning, refactor guidance, trade-off evaluation, and root cause analysis without making hasty edits.",
125
- tools: "Read, Glob, Grep, Bash",
126
- model: "inherit",
127
- },
128
- "code-reviewer": {
129
- name: "Code Reviewer",
130
- description:
131
- "Reviews code changes for production readiness and catches correctness, maintainability, and testing issues.",
132
- tools: "Read, Glob, Grep, Bash",
133
- model: "inherit",
134
- },
135
- "arcs-docs": {
136
- name: "ARCS Docs Specialist",
137
- description:
138
- "ARCS documentation specialist. Manages plans, knowledge entries, diagrams, and DAG health. Knows ARCS structure intimately.",
139
- tools: "Read, Write, Edit, Glob, Grep, Bash",
140
- model: "inherit",
141
- },
142
- "docs-researcher": {
143
- name: "Docs Researcher",
144
- description:
145
- "Handles documentation writing, research synthesis, OCR-adjacent extraction, and document-heavy analysis tasks.",
146
- tools: "Read, Write, Edit, Glob, Grep, Bash",
147
- model: "inherit",
148
- },
149
- "oncall-ops": {
150
- name: "On-Call Ops",
151
- description:
152
- "Debugging and diagnosis specialist. Finds root causes through systematic investigation, log triage, bisect, and performance profiling.",
153
- tools: "Read, Write, Edit, Glob, Grep, Bash",
154
- model: "inherit",
155
- },
156
- "arcs-orchestrate": {
157
- name: "ARCS Orchestrator",
158
- description:
159
- "The central coordinator for executing plans, managing agent dispatch, and handling DAG workflows.",
160
- // Task is required: orchestrators dispatch sub-agents. Omitting it leaves
161
- // the delegator with no way to delegate.
162
- tools: "Task, Read, Write, Edit, Glob, Grep, Bash",
163
- model: "inherit",
164
- },
165
- "arcs-orchestrate-caveman": {
166
- name: "ARCS Orchestrator (Caveman)",
167
- description:
168
- "A terse, high-efficiency orchestrator that drives tasks without extra commentary.",
169
- // Task is required: orchestrators dispatch sub-agents. Omitting it leaves
170
- // the delegator with no way to delegate.
171
- tools: "Task, Read, Write, Edit, Glob, Grep, Bash",
172
- model: "inherit",
173
- },
174
- };
162
+ function claudeTools(agent) {
163
+ const tools = [];
164
+ if (agent.permissions.task === "allow") tools.push("Task");
165
+ tools.push("Read");
166
+ if (agent.permissions.edit === "allow") tools.push("Write", "Edit");
167
+ tools.push("Glob", "Grep");
168
+ if (agent.permissions.bash === "allow") tools.push("Bash");
169
+ return tools.join(", ");
170
+ }
175
171
 
176
172
  function ensureParentDir(filePath) {
177
173
  mkdirSync(dirname(filePath), { recursive: true });
178
174
  }
179
175
 
176
+ function sha256(content) {
177
+ return createHash("sha256").update(content).digest("hex");
178
+ }
179
+
180
+ function readInstalledManifest() {
181
+ const manifestPath = resolve(destination, configRelativePath(".arcs-bundle.json"));
182
+ if (!existsSync(manifestPath)) return null;
183
+ try {
184
+ const value = JSON.parse(readFileSync(manifestPath, "utf-8"));
185
+ return value?.bundleId === "arcs-claudecode-bundle" ? value : null;
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+
180
191
  function configRelativePath(suffix) {
181
192
  return scope === "project" ? `.claude/${suffix}` : suffix;
182
193
  }
@@ -204,26 +215,23 @@ function buildAgentSources() {
204
215
  throw new Error(`Prompts directory not found at ${promptsDir}`);
205
216
  }
206
217
 
207
- const promptFiles = readdirSync(promptsDir).filter((f) => f.endsWith(".txt"));
208
- const sources = [];
209
-
218
+ const registry = readAgentRegistry();
219
+ const registeredSources = new Set(registry.map((agent) => agent.source));
220
+ const promptFiles = readdirSync(promptsDir).filter((file) => file.endsWith(".txt"));
210
221
  for (const file of promptFiles) {
211
- const stem = file.slice(0, -4);
212
- const sourcePath = resolve(promptsDir, file);
213
- const promptContent = readFileSync(sourcePath, "utf-8");
222
+ const source = `prompts/${file}`;
223
+ if (!registeredSources.has(source)) throw new Error(`Unregistered prompt file: ${source}`);
224
+ }
214
225
 
215
- const meta = agentMetadata[stem] || {
216
- name: stem
217
- .split("-")
218
- .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
219
- .join(" "),
220
- description: `ARCS ${stem} agent.`,
221
- tools: "Read, Write, Edit, Glob, Grep, Bash",
222
- model: "inherit",
223
- };
226
+ const sources = [];
224
227
 
225
- const tier = agentTierMap[stem] || "standard";
226
- const model = tierModels[tier];
228
+ for (const agent of registry.filter((record) => isActiveAgentForMode(record, "claudecode"))) {
229
+ const stem = agent.id;
230
+ const sourcePath = resolveBundlePromptPath(agent.source);
231
+ if (!existsSync(sourcePath))
232
+ throw new Error(`Registered agent prompt not found: ${agent.source}`);
233
+ const promptContent = readFileSync(sourcePath, "utf-8");
234
+ const model = tierModels[agent.tier];
227
235
 
228
236
  // Claude Code requires `name` to be a kebab-case identifier (lowercase
229
237
  // letters + hyphens). The filename stem already satisfies this and is
@@ -231,17 +239,12 @@ function buildAgentSources() {
231
239
  // `description`. The default-agent setting (DEFAULT_AGENT) references this
232
240
  // same stem, so it resolves. Display names with spaces/parens/apostrophes
233
241
  // (meta.name) are invalid here and caused intermittent init failures.
234
- const toolsCsv = meta.tools
235
- .split(",")
236
- .map((t) => t.trim())
237
- .join(", ");
238
-
239
242
  const compiledContent = [
240
243
  "---",
241
244
  `name: ${stem}`,
242
- `description: ${meta.description}`,
245
+ `description: ${agent.description}`,
243
246
  `model: ${model}`,
244
- `tools: ${toolsCsv}`,
247
+ `tools: ${claudeTools(agent)}`,
245
248
  "---",
246
249
  "",
247
250
  promptContent,
@@ -289,7 +292,47 @@ function buildSkillSources() {
289
292
  // 3. settings.json merge — set default agent
290
293
  // ---------------------------------------------------------------------------
291
294
 
295
+ // Which primary becomes the deployed default is an explicit, ordered policy —
296
+ // never "whichever active primary happens to come first in manifest.json".
297
+ // Registry array order must not be able to promote an agent: a new primary
298
+ // (e.g. the speed-optimized arcs-flash) becomes eligible only by being listed
299
+ // here, and only at the rank it is listed at. Earlier entries always win, so a
300
+ // lower-ranked primary is a fallback, never a silent replacement.
301
+ const DEFAULT_AGENT_PRECEDENCE = ["arcs-orchestrate", "arcs-orchestrate-caveman", "arcs-flash"];
302
+
303
+ function isSelectablePrimary(agent) {
304
+ return Boolean(agent) && agent.kind === "primary" && isActiveAgentForMode(agent, "claudecode");
305
+ }
306
+
307
+ function selectDefaultAgent(registry) {
308
+ // An explicit user selection outranks the pinned precedence — but only when it
309
+ // names a real Claude-Code-active primary. A user who asked for X must never
310
+ // silently get Y, so an unusable selection hard-fails instead of degrading
311
+ // into the precedence walk.
312
+ const requestedId = (process.env.DEPLOY_PRIMARY_AGENT ?? "").trim();
313
+ if (requestedId !== "") {
314
+ const requested = registry.find((record) => record.id === requestedId);
315
+ if (isSelectablePrimary(requested)) return requested;
316
+ const selectable = registry.filter(isSelectablePrimary).map((record) => record.id);
317
+ throw new Error(
318
+ `DEPLOY_PRIMARY_AGENT "${requestedId}" is not an active Claude Code primary agent. Selectable: ${selectable.join(", ") || "(none)"}`,
319
+ );
320
+ }
321
+
322
+ for (const id of DEFAULT_AGENT_PRECEDENCE) {
323
+ const agent = registry.find((record) => record.id === id);
324
+ if (isSelectablePrimary(agent)) {
325
+ return agent;
326
+ }
327
+ }
328
+ throw new Error(
329
+ `No active Claude Code primary agent in default precedence: ${DEFAULT_AGENT_PRECEDENCE.join(", ")}`,
330
+ );
331
+ }
332
+
292
333
  function planSettingsUpdate() {
334
+ const defaultAgent = selectDefaultAgent(readAgentRegistry());
335
+
293
336
  const settingsConfigRelative = configRelativePath("settings.json");
294
337
  const settingsAbsolute = resolve(destination, settingsConfigRelative);
295
338
 
@@ -308,7 +351,7 @@ function planSettingsUpdate() {
308
351
  }
309
352
  }
310
353
 
311
- const merged = { ...parsed, agent: DEFAULT_AGENT };
354
+ const merged = { ...parsed, agent: defaultAgent.id };
312
355
  const serialized = `${JSON.stringify(merged, null, 2)}\n`;
313
356
 
314
357
  let status;
@@ -328,6 +371,8 @@ function planSettingsUpdate() {
328
371
  // ---------------------------------------------------------------------------
329
372
 
330
373
  function main() {
374
+ const registry = readAgentRegistry();
375
+ const previousManifest = readInstalledManifest();
331
376
  const agentSources = buildAgentSources();
332
377
  const skillSources = buildSkillSources();
333
378
  const settingsPlan = planSettingsUpdate();
@@ -375,20 +420,6 @@ function main() {
375
420
  // Orphans
376
421
  const filesRemoved = [];
377
422
 
378
- // Agent orphans — only `.md` files whose stem we recognize from agentMetadata
379
- const agentsTargetDir = resolve(destination, configRelativePath("agents"));
380
- const activeAgentStems = new Set(agentSources.map((f) => f.stem));
381
- if (existsSync(agentsTargetDir)) {
382
- for (const entry of readdirSync(agentsTargetDir, { withFileTypes: true })) {
383
- if (entry.isFile() && entry.name.endsWith(".md")) {
384
- const stem = entry.name.slice(0, -3);
385
- if (agentMetadata[stem] && !activeAgentStems.has(stem)) {
386
- filesRemoved.push(configRelativePath(`agents/${entry.name}`));
387
- }
388
- }
389
- }
390
- }
391
-
392
423
  // Skill orphans — only `arcs-*/` directories that aren't in current source.
393
424
  // The prefix gives us a safe namespace; foreign user skills are never touched.
394
425
  const skillsTargetDir = resolve(destination, configRelativePath("skills"));
@@ -405,6 +436,22 @@ function main() {
405
436
  }
406
437
  }
407
438
 
439
+ const retiredById = new Map(
440
+ registry
441
+ .filter((agent) => isRetiredAgentForMode(agent, "claudecode"))
442
+ .map((agent) => [agent.id, agent]),
443
+ );
444
+ for (const ownership of previousManifest?.agents ?? []) {
445
+ const retired = retiredById.get(ownership.id);
446
+ if (!retired) continue;
447
+ const expectedDestination = configRelativePath(`agents/${retired.id}.md`);
448
+ if (ownership.promptDestination !== expectedDestination) continue;
449
+ const installedPath = resolve(destination, ownership.promptDestination);
450
+ if (existsSync(installedPath) && sha256(readFileSync(installedPath)) === ownership.sourceHash) {
451
+ filesRemoved.push(ownership.promptDestination);
452
+ }
453
+ }
454
+
408
455
  // Pass 2: Write if not dry-run
409
456
  if (!dryRun) {
410
457
  for (const { compiledContent, configRelative } of agentSources) {
@@ -432,6 +479,33 @@ function main() {
432
479
  rmSync(abs, { recursive: isDir, force: true });
433
480
  }
434
481
  }
482
+
483
+ const installedManifestPath = resolve(destination, configRelativePath(".arcs-bundle.json"));
484
+ ensureParentDir(installedManifestPath);
485
+ writeFileSync(
486
+ installedManifestPath,
487
+ `${JSON.stringify(
488
+ {
489
+ bundleId: "arcs-claudecode-bundle",
490
+ installMode: `claudecode-${scope}`,
491
+ sourceBundleVersion: "deploy-script",
492
+ sourceBundleHash: sha256(readFileSync(resolve(bundleRoot, "manifest.json"))),
493
+ installedAt: new Date().toISOString(),
494
+ // Persisted so a later `arcs init` can reuse the previous tier
495
+ // selection instead of re-prompting for it.
496
+ tierModels,
497
+ ownedPaths: [],
498
+ agents: agentSources.map((agent) => ({
499
+ id: agent.stem,
500
+ promptDestination: agent.configRelative,
501
+ sourceHash: sha256(agent.compiledContent),
502
+ })),
503
+ },
504
+ null,
505
+ 2,
506
+ )}\n`,
507
+ "utf-8",
508
+ );
435
509
  }
436
510
 
437
511
  // Best-effort: wire the codegraph MCP server. Skipped on dry-run; never fatal.