@rryando/arcs 3.9.2 → 3.11.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 (331) 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 -373
  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 +168 -15
  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 +36 -0
  25. package/dist/cli/commands/hooks.d.ts.map +1 -0
  26. package/dist/cli/commands/hooks.js +298 -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 +56 -0
  39. package/dist/cli/commands/web.js.map +1 -0
  40. package/dist/cli/config.d.ts +32 -0
  41. package/dist/cli/config.d.ts.map +1 -1
  42. package/dist/cli/config.js +56 -0
  43. package/dist/cli/config.js.map +1 -1
  44. package/dist/cli/instructions.d.ts +19 -6
  45. package/dist/cli/instructions.d.ts.map +1 -1
  46. package/dist/cli/instructions.js +62 -32
  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 +159 -85
  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/utils/claude-code-hook-install.d.ts +80 -0
  59. package/dist/utils/claude-code-hook-install.d.ts.map +1 -0
  60. package/dist/utils/claude-code-hook-install.js +146 -0
  61. package/dist/utils/claude-code-hook-install.js.map +1 -0
  62. package/dist/utils/claude-transcript.d.ts +127 -0
  63. package/dist/utils/claude-transcript.d.ts.map +1 -0
  64. package/dist/utils/claude-transcript.js +353 -0
  65. package/dist/utils/claude-transcript.js.map +1 -0
  66. package/dist/utils/diagram-generator.d.ts +1 -1
  67. package/dist/utils/diagram-generator.d.ts.map +1 -1
  68. package/dist/utils/diagram-generator.js +3 -2
  69. package/dist/utils/diagram-generator.js.map +1 -1
  70. package/dist/utils/errors.d.ts +6 -2
  71. package/dist/utils/errors.d.ts.map +1 -1
  72. package/dist/utils/errors.js +12 -0
  73. package/dist/utils/errors.js.map +1 -1
  74. package/dist/utils/hook-token-store.d.ts +22 -0
  75. package/dist/utils/hook-token-store.d.ts.map +1 -0
  76. package/dist/utils/hook-token-store.js +43 -0
  77. package/dist/utils/hook-token-store.js.map +1 -0
  78. package/dist/utils/json-schemas.d.ts +186 -2
  79. package/dist/utils/json-schemas.d.ts.map +1 -1
  80. package/dist/utils/json-schemas.js +48 -4
  81. package/dist/utils/json-schemas.js.map +1 -1
  82. package/dist/utils/knowledge-store.d.ts +7 -1
  83. package/dist/utils/knowledge-store.d.ts.map +1 -1
  84. package/dist/utils/knowledge-store.js +97 -65
  85. package/dist/utils/knowledge-store.js.map +1 -1
  86. package/dist/utils/plan-store.d.ts +8 -0
  87. package/dist/utils/plan-store.d.ts.map +1 -1
  88. package/dist/utils/plan-store.js +98 -59
  89. package/dist/utils/plan-store.js.map +1 -1
  90. package/dist/utils/project-resolver.d.ts +8 -0
  91. package/dist/utils/project-resolver.d.ts.map +1 -1
  92. package/dist/utils/project-resolver.js +7 -2
  93. package/dist/utils/project-resolver.js.map +1 -1
  94. package/dist/utils/session-store.d.ts +113 -0
  95. package/dist/utils/session-store.d.ts.map +1 -0
  96. package/dist/utils/session-store.js +312 -0
  97. package/dist/utils/session-store.js.map +1 -0
  98. package/dist/utils/storage-utils.d.ts +31 -0
  99. package/dist/utils/storage-utils.d.ts.map +1 -1
  100. package/dist/utils/storage-utils.js +116 -5
  101. package/dist/utils/storage-utils.js.map +1 -1
  102. package/dist/utils/task-store.d.ts +7 -0
  103. package/dist/utils/task-store.d.ts.map +1 -1
  104. package/dist/utils/task-store.js +73 -23
  105. package/dist/utils/task-store.js.map +1 -1
  106. package/dist/web-client/assets/GraphCanvas-dNyZ458L.js +1 -0
  107. package/dist/web-client/assets/MarkdownEditor-BmU9mdkN.js +77 -0
  108. package/dist/web-client/assets/abnfDiagram-VRR7QNED-D1BFBoeF.js +1 -0
  109. package/dist/web-client/assets/arc-Bfaogrm1.js +1 -0
  110. package/dist/web-client/assets/architecture-TIHT7OUA-CJqI5wNI.js +1 -0
  111. package/dist/web-client/assets/architectureDiagram-ZJ3FMSHR-CA8hTWUK.js +36 -0
  112. package/dist/web-client/assets/array-BifhSqXX.js +1 -0
  113. package/dist/web-client/assets/blockDiagram-677ZJIJ3-CQpb_KwX.js +132 -0
  114. package/dist/web-client/assets/c4Diagram-LMCZKHZV-BhpHX84V.js +10 -0
  115. package/dist/web-client/assets/channel-C8DlmyVe.js +1 -0
  116. package/dist/web-client/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  117. package/dist/web-client/assets/chunk-32BRIVSS-BUusQQa_.js +1 -0
  118. package/dist/web-client/assets/chunk-52WLFC77-nNYwlftl.js +10 -0
  119. package/dist/web-client/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  120. package/dist/web-client/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  121. package/dist/web-client/assets/chunk-C7G6YPKG-D0a-yqnK.js +1 -0
  122. package/dist/web-client/assets/chunk-EX3LRPZG-IDuRMN-4.js +231 -0
  123. package/dist/web-client/assets/chunk-FWX5IMBZ-D_spTcqi.js +2 -0
  124. package/dist/web-client/assets/chunk-HOUHSVGY-C-bcxwZS.js +1 -0
  125. package/dist/web-client/assets/chunk-ICXQ74PX-CjmK2bAM.js +2 -0
  126. package/dist/web-client/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  127. package/dist/web-client/assets/chunk-KEIR6QF5-DEvma7oi.js +161 -0
  128. package/dist/web-client/assets/chunk-MOJQB5TN-Bkc08KWY.js +88 -0
  129. package/dist/web-client/assets/chunk-OGEWGWER-BAAYYvG9.js +1 -0
  130. package/dist/web-client/assets/chunk-PUDLZKDR-WXbPY7NM.js +156 -0
  131. package/dist/web-client/assets/chunk-Q4XR5HBZ-DcbnjxQE.js +70 -0
  132. package/dist/web-client/assets/chunk-RYQCIY6F-np2RyIY1.js +1 -0
  133. package/dist/web-client/assets/chunk-V7JOEXUC-C6t75PAp.js +206 -0
  134. package/dist/web-client/assets/chunk-VAUOI2AC-DVrJ0Ic7.js +1 -0
  135. package/dist/web-client/assets/chunk-VR4S4FIN-MOOFvGS0.js +1 -0
  136. package/dist/web-client/assets/chunk-WYO6CB5R-sK7Y2NZD.js +125 -0
  137. package/dist/web-client/assets/chunk-XXDRQBXY-BvKO0v-W.js +1 -0
  138. package/dist/web-client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  139. package/dist/web-client/assets/chunk-ZGVPDNZ5-a13RQsku.js +62 -0
  140. package/dist/web-client/assets/chunk-ZIRB5QZD-BpeS1aZ7.js +32 -0
  141. package/dist/web-client/assets/classDiagram-OUVF2IWQ-p32N1P_G.js +1 -0
  142. package/dist/web-client/assets/classDiagram-v2-EOCWNBFH-p32N1P_G.js +1 -0
  143. package/dist/web-client/assets/cose-bilkent-JH36ORCC-BebHqzgp.js +1 -0
  144. package/dist/web-client/assets/cynefin-VYW2F7L2-D8xaH-wO.js +1 -0
  145. package/dist/web-client/assets/cynefinDiagram-TSTJHNR4-Bt__EqJW.js +62 -0
  146. package/dist/web-client/assets/cytoscape-fcose-peAzqedC.js +1 -0
  147. package/dist/web-client/assets/cytoscape.esm-C3UvhD5t.js +321 -0
  148. package/dist/web-client/assets/dagre-Buvkdvvj.js +1 -0
  149. package/dist/web-client/assets/dagre-VKFMJZFB-Bwgjwflz.js +4 -0
  150. package/dist/web-client/assets/defaultLocale-BFoDCU3G.js +1 -0
  151. package/dist/web-client/assets/diagram-FQU43EPY-CaPDVUq2.js +3 -0
  152. package/dist/web-client/assets/diagram-G47NLZAW-BQLB9YYA.js +24 -0
  153. package/dist/web-client/assets/diagram-NH7WQ7WH-BWo84w8Y.js +24 -0
  154. package/dist/web-client/assets/diagram-OA4YK3LP-bKn6Pz5s.js +30 -0
  155. package/dist/web-client/assets/diagram-WEI45ONY-BRqV5Oy6.js +41 -0
  156. package/dist/web-client/assets/dist-B_J_HbC0.js +1 -0
  157. package/dist/web-client/assets/ebnfDiagram-CCIWWBDH-DhUXL1-7.js +1 -0
  158. package/dist/web-client/assets/erDiagram-Q63AITRT-HXAQQ-_F.js +85 -0
  159. package/dist/web-client/assets/eventmodeling-45OFAUF4-Bj5P8mZJ.js +1 -0
  160. package/dist/web-client/assets/flowDiagram-23GEKE2U-37BztFri.js +1 -0
  161. package/dist/web-client/assets/ganttDiagram-NO4QXBWP-D-Ddf_Ii.js +292 -0
  162. package/dist/web-client/assets/gitGraph-TEB2WS4Q-BmHzs0uF.js +1 -0
  163. package/dist/web-client/assets/gitGraphDiagram-IHSO6WYX-YnQWrlh_.js +106 -0
  164. package/dist/web-client/assets/graphlib-DS17s2tU.js +1 -0
  165. package/dist/web-client/assets/index-3mNPVkix.css +2 -0
  166. package/dist/web-client/assets/index-DCWxuIeQ.js +58 -0
  167. package/dist/web-client/assets/info-DKCQHKI2-DCT_B7RN.js +1 -0
  168. package/dist/web-client/assets/infoDiagram-FWYZ7A6U-D-le1Zhq.js +2 -0
  169. package/dist/web-client/assets/init-C-OQMol4.js +1 -0
  170. package/dist/web-client/assets/ishikawaDiagram-FXEZZL3T-Jr1x2VJB.js +70 -0
  171. package/dist/web-client/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  172. package/dist/web-client/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  173. package/dist/web-client/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  174. package/dist/web-client/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  175. package/dist/web-client/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  176. package/dist/web-client/assets/journeyDiagram-5HDEW3XC-BF9ELxj-.js +139 -0
  177. package/dist/web-client/assets/kanban-definition-HUTT4EX6-C4fJqAxu.js +89 -0
  178. package/dist/web-client/assets/katex-DolUETbr.js +257 -0
  179. package/dist/web-client/assets/line-7N7ikFxa.js +1 -0
  180. package/dist/web-client/assets/linear-DeUiD2wj.js +1 -0
  181. package/dist/web-client/assets/map-BaFkSB1l.js +1 -0
  182. package/dist/web-client/assets/mermaid-parser.core-QbC1icPt.js +7 -0
  183. package/dist/web-client/assets/mermaid.core-C26d_UJm.js +11 -0
  184. package/dist/web-client/assets/mindmap-definition-LN4V7U3C-D6TV1JDf.js +96 -0
  185. package/dist/web-client/assets/ordinal-BDEzSJ7C.js +1 -0
  186. package/dist/web-client/assets/packet-7NZHBO7P-CR1vrGj3.js +1 -0
  187. package/dist/web-client/assets/path-COt_16Va.js +1 -0
  188. package/dist/web-client/assets/pegDiagram-2B236MQR-xOMBBtfV.js +1 -0
  189. package/dist/web-client/assets/pie-RZYD4A2V-BbWuhjwy.js +1 -0
  190. package/dist/web-client/assets/pieDiagram-ENE6RG2P-MsfnsqgW.js +39 -0
  191. package/dist/web-client/assets/quadrantDiagram-ABIIQ3AL-BoI7zKXF.js +7 -0
  192. package/dist/web-client/assets/radar-I7S5WNFK-CbYXKToJ.js +1 -0
  193. package/dist/web-client/assets/railroad-3IZDKUUU-6LxHDkLe.js +1 -0
  194. package/dist/web-client/assets/railroad-abnf-AHOZXSZD-2Dg9wu0J.js +1 -0
  195. package/dist/web-client/assets/railroad-ebnf-EBAXGLYW-C_E2ot0R.js +1 -0
  196. package/dist/web-client/assets/railroad-peg-LSFZ7HO6-Bs9UQR1b.js +1 -0
  197. package/dist/web-client/assets/railroadDiagram-RFXS5EU6-D6RUoUki.js +1 -0
  198. package/dist/web-client/assets/requirementDiagram-TGXJPOKE-B6k4BDpE.js +84 -0
  199. package/dist/web-client/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
  200. package/dist/web-client/assets/rough.esm-By172zw-.js +1 -0
  201. package/dist/web-client/assets/sankeyDiagram-HTMAVEWB-BUDF-UFr.js +40 -0
  202. package/dist/web-client/assets/sequenceDiagram-DBY2YBRQ-D6GqcsUi.js +162 -0
  203. package/dist/web-client/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  204. package/dist/web-client/assets/src-oBChb5qS.js +1 -0
  205. package/dist/web-client/assets/stateDiagram-2N3HPSRC-WfJCQAK5.js +1 -0
  206. package/dist/web-client/assets/stateDiagram-v2-6OUMAXLB-BCMWGnsJ.js +1 -0
  207. package/dist/web-client/assets/swimlanes-5IMT3BWC-BtMo82mC.js +2 -0
  208. package/dist/web-client/assets/swimlanesDiagram-G3AALYLV-DmudmLcK.js +8 -0
  209. package/dist/web-client/assets/timeline-definition-FHXFAJF6-CoAmv2Sn.js +120 -0
  210. package/dist/web-client/assets/treeView-QDETBFTQ-BWsKzE1s.js +1 -0
  211. package/dist/web-client/assets/treemap-6X3UGDF4-i_qGtB3o.js +1 -0
  212. package/dist/web-client/assets/vennDiagram-L72KCM5P-DYkiLe-P.js +34 -0
  213. package/dist/web-client/assets/wardley-OPB4EBWU-Daaqr1Vp.js +1 -0
  214. package/dist/web-client/assets/wardleyDiagram-EHGQE667-Bofbsg3J.js +78 -0
  215. package/dist/web-client/assets/xychartDiagram-FW5EYKEG-KNF4VTfL.js +7 -0
  216. package/dist/web-client/index.html +15 -0
  217. package/dist/web-server/app.d.ts +13 -0
  218. package/dist/web-server/app.d.ts.map +1 -0
  219. package/dist/web-server/app.js +58 -0
  220. package/dist/web-server/app.js.map +1 -0
  221. package/dist/web-server/claude-runner.d.ts +86 -0
  222. package/dist/web-server/claude-runner.d.ts.map +1 -0
  223. package/dist/web-server/claude-runner.js +320 -0
  224. package/dist/web-server/claude-runner.js.map +1 -0
  225. package/dist/web-server/hook-auth.d.ts +12 -0
  226. package/dist/web-server/hook-auth.d.ts.map +1 -0
  227. package/dist/web-server/hook-auth.js +36 -0
  228. package/dist/web-server/hook-auth.js.map +1 -0
  229. package/dist/web-server/index.d.ts +23 -0
  230. package/dist/web-server/index.d.ts.map +1 -0
  231. package/dist/web-server/index.js +49 -0
  232. package/dist/web-server/index.js.map +1 -0
  233. package/dist/web-server/opencode-client.d.ts +123 -0
  234. package/dist/web-server/opencode-client.d.ts.map +1 -0
  235. package/dist/web-server/opencode-client.js +514 -0
  236. package/dist/web-server/opencode-client.js.map +1 -0
  237. package/dist/web-server/respond.d.ts +33 -0
  238. package/dist/web-server/respond.d.ts.map +1 -0
  239. package/dist/web-server/respond.js +79 -0
  240. package/dist/web-server/respond.js.map +1 -0
  241. package/dist/web-server/routes/collections.d.ts +11 -0
  242. package/dist/web-server/routes/collections.d.ts.map +1 -0
  243. package/dist/web-server/routes/collections.js +217 -0
  244. package/dist/web-server/routes/collections.js.map +1 -0
  245. package/dist/web-server/routes/discovery.d.ts +7 -0
  246. package/dist/web-server/routes/discovery.d.ts.map +1 -0
  247. package/dist/web-server/routes/discovery.js +159 -0
  248. package/dist/web-server/routes/discovery.js.map +1 -0
  249. package/dist/web-server/routes/events.d.ts +6 -0
  250. package/dist/web-server/routes/events.d.ts.map +1 -0
  251. package/dist/web-server/routes/events.js +25 -0
  252. package/dist/web-server/routes/events.js.map +1 -0
  253. package/dist/web-server/routes/hook-events.d.ts +19 -0
  254. package/dist/web-server/routes/hook-events.d.ts.map +1 -0
  255. package/dist/web-server/routes/hook-events.js +135 -0
  256. package/dist/web-server/routes/hook-events.js.map +1 -0
  257. package/dist/web-server/routes/projects.d.ts +7 -0
  258. package/dist/web-server/routes/projects.d.ts.map +1 -0
  259. package/dist/web-server/routes/projects.js +272 -0
  260. package/dist/web-server/routes/projects.js.map +1 -0
  261. package/dist/web-server/routes/sessions.d.ts +16 -0
  262. package/dist/web-server/routes/sessions.d.ts.map +1 -0
  263. package/dist/web-server/routes/sessions.js +442 -0
  264. package/dist/web-server/routes/sessions.js.map +1 -0
  265. package/dist/web-server/security.d.ts +7 -0
  266. package/dist/web-server/security.d.ts.map +1 -0
  267. package/dist/web-server/security.js +41 -0
  268. package/dist/web-server/security.js.map +1 -0
  269. package/dist/web-server/static.d.ts +10 -0
  270. package/dist/web-server/static.d.ts.map +1 -0
  271. package/dist/web-server/static.js +36 -0
  272. package/dist/web-server/static.js.map +1 -0
  273. package/dist/web-server/storage.d.ts +17 -0
  274. package/dist/web-server/storage.d.ts.map +1 -0
  275. package/dist/web-server/storage.js +42 -0
  276. package/dist/web-server/storage.js.map +1 -0
  277. package/dist/web-server/watcher.d.ts +37 -0
  278. package/dist/web-server/watcher.d.ts.map +1 -0
  279. package/dist/web-server/watcher.js +181 -0
  280. package/dist/web-server/watcher.js.map +1 -0
  281. package/opencode/arcs/bundle-runtime.json +5 -14
  282. package/opencode/arcs/manifest.json +213 -149
  283. package/opencode/arcs/prompts/arcs-docs.txt +53 -47
  284. package/opencode/arcs/prompts/arcs-flash.txt +190 -0
  285. package/opencode/arcs/prompts/arcs-orchestrate-caveman.txt +116 -412
  286. package/opencode/arcs/prompts/arcs-orchestrate.txt +114 -331
  287. package/opencode/arcs/prompts/code-reviewer.txt +37 -98
  288. package/opencode/arcs/prompts/devil-advocate.txt +44 -115
  289. package/opencode/arcs/prompts/graph-explorer.txt +31 -179
  290. package/opencode/arcs/prompts/software-engineer.txt +24 -6
  291. package/opencode/arcs/prompts/tech-architect.txt +28 -12
  292. package/opencode/arcs/skills/brainstorming/SKILL.md +65 -105
  293. package/opencode/arcs/skills/brainstorming/scripts/server.js +37 -10
  294. package/opencode/arcs/skills/brainstorming/scripts/start-server.sh +20 -3
  295. package/opencode/arcs/skills/brainstorming/scripts/stop-server.sh +25 -6
  296. package/opencode/arcs/skills/brainstorming/visual-companion.md +3 -10
  297. package/opencode/arcs/skills/deep-pr-review/SKILL.md +5 -5
  298. package/opencode/arcs/skills/deep-pr-review/review-template.md +1 -1
  299. package/opencode/arcs/skills/enriching-codegraph-proposals/SKILL.md +17 -18
  300. package/opencode/arcs/skills/executing-plans/SKILL.md +26 -234
  301. package/opencode/arcs/skills/implementation/SKILL.md +61 -0
  302. package/opencode/arcs/skills/init-project/SKILL.md +16 -15
  303. package/opencode/arcs/skills/install-claude-code-hook/SKILL.md +143 -0
  304. package/opencode/arcs/skills/systematic-debugging/SKILL.md +16 -15
  305. package/opencode/arcs/skills/test-driven-development/SKILL.md +1 -1
  306. package/opencode/arcs/skills/to-diagram/SKILL.md +10 -29
  307. package/opencode/arcs/skills/writing-knowledge/SKILL.md +7 -6
  308. package/opencode/arcs/skills/writing-plans/SKILL.md +80 -130
  309. package/opencode/arcs/skills/writing-plans/plan-document-reviewer-prompt.md +38 -30
  310. package/package.json +14 -6
  311. package/scripts/build-opencode-bundle.mjs +23 -11
  312. package/scripts/claude-code-session-hook.mjs +125 -0
  313. package/scripts/deploy-claudecode-bundle.mjs +185 -132
  314. package/scripts/deploy-opencode-bundle.mjs +207 -6
  315. package/scripts/lib/bundle-helpers.mjs +29 -3
  316. package/scripts/lint-bundle.mjs +123 -3
  317. package/skills/explore-dag.md +5 -3
  318. package/skills/init-project.md +27 -26
  319. package/skills/orchestrate.md +29 -13
  320. package/skills/update-docs.md +8 -13
  321. package/opencode/arcs/prompts/docs-researcher.txt +0 -79
  322. package/opencode/arcs/prompts/oncall-ops.txt +0 -85
  323. package/opencode/arcs/skills/brainstorming/spec-document-reviewer-prompt.md +0 -56
  324. package/opencode/arcs/skills/code-agent/SKILL.md +0 -63
  325. package/opencode/arcs/skills/executing-plans/code-quality-reviewer-prompt.md +0 -57
  326. package/opencode/arcs/skills/executing-plans/implementer-prompt.md +0 -152
  327. package/opencode/arcs/skills/executing-plans/spec-reviewer-prompt.md +0 -91
  328. package/opencode/arcs/skills/quick-dev/SKILL.md +0 -52
  329. package/opencode/arcs/skills/requesting-code-review/SKILL.md +0 -59
  330. package/opencode/arcs/skills/requesting-code-review/code-reviewer.md +0 -139
  331. package/opencode/arcs/skills/the-ladder/SKILL.md +0 -54
@@ -41,11 +41,12 @@ function pruneUndeclaredFiles(rootPath, allowedFiles) {
41
41
  let defaultOutputRootCurrent = defaultOutputRoot;
42
42
 
43
43
  /**
44
- * Generates the ARCS Orchestrator and ARCS Caveman prompt .txt files into
45
- * <outputRoot>/prompts/. The TypeScript modules src/cli/arcs-orchestrate.ts
46
- * and src/cli/arcs-orchestrate-caveman.ts remain the canonical source; these
47
- * .txt files are committed mirrors so the bundle is self-describing alongside
48
- * the static sub-agent prompts.
44
+ * Generates the ARCS Orchestrator, ARCS Caveman, and ARCS Flash prompt .txt
45
+ * files into <outputRoot>/prompts/. The TypeScript modules
46
+ * src/cli/arcs-orchestrate.ts, src/cli/arcs-orchestrate-caveman.ts, and
47
+ * src/cli/arcs-flash.ts remain the canonical source; these .txt files are
48
+ * committed mirrors so the bundle is self-describing alongside the static
49
+ * sub-agent prompts.
49
50
  *
50
51
  * Requires `tsc` to have run first (dist/cli/arcs-orchestrate.js must exist).
51
52
  * package.json's build:opencode-bundle chains `tsc` before this script.
@@ -53,19 +54,28 @@ let defaultOutputRootCurrent = defaultOutputRoot;
53
54
  async function generateOrchestratorPrompts(outputRoot) {
54
55
  const orchestrateModulePath = resolve(repoRoot, "dist/cli/arcs-orchestrate.js");
55
56
  const cavemanModulePath = resolve(repoRoot, "dist/cli/arcs-orchestrate-caveman.js");
57
+ const flashModulePath = resolve(repoRoot, "dist/cli/arcs-flash.js");
56
58
 
57
- if (!existsSync(orchestrateModulePath) || !existsSync(cavemanModulePath)) {
59
+ if (
60
+ !existsSync(orchestrateModulePath) ||
61
+ !existsSync(cavemanModulePath) ||
62
+ !existsSync(flashModulePath)
63
+ ) {
58
64
  throw new Error(
59
65
  `Compiled orchestrator modules missing. Run \`npm run build\` before bundle build.\n` +
60
66
  ` Expected: ${orchestrateModulePath}\n` +
61
- ` Expected: ${cavemanModulePath}`, );
67
+ ` Expected: ${cavemanModulePath}\n` +
68
+ ` Expected: ${flashModulePath}`,
69
+ );
62
70
  }
63
71
 
64
72
  const orchestrateModule = await import(pathToFileURL(orchestrateModulePath).href);
65
73
  const cavemanModule = await import(pathToFileURL(cavemanModulePath).href);
74
+ const flashModule = await import(pathToFileURL(flashModulePath).href);
66
75
 
67
76
  const orchestrateText = orchestrateModule.ORCHESTRATE_PROMPT_TEXT;
68
77
  const cavemanText = cavemanModule.ORCHESTRATE_CAVEMAN_PROMPT_TEXT;
78
+ const flashText = flashModule.FLASH_PROMPT_TEXT;
69
79
 
70
80
  if (typeof orchestrateText !== "string" || orchestrateText.length === 0) {
71
81
  throw new Error("ORCHESTRATE_PROMPT_TEXT not exported as non-empty string");
@@ -73,12 +83,16 @@ async function generateOrchestratorPrompts(outputRoot) {
73
83
  if (typeof cavemanText !== "string" || cavemanText.length === 0) {
74
84
  throw new Error("ORCHESTRATE_CAVEMAN_PROMPT_TEXT not exported as non-empty string");
75
85
  }
86
+ if (typeof flashText !== "string" || flashText.length === 0) {
87
+ throw new Error("FLASH_PROMPT_TEXT not exported as non-empty string");
88
+ }
76
89
 
77
90
  const promptsDir = resolve(outputRoot, "prompts");
78
91
  mkdirSync(promptsDir, { recursive: true });
79
92
 
80
93
  const orchestratePath = resolve(promptsDir, "arcs-orchestrate.txt");
81
94
  const cavemanPath = resolve(promptsDir, "arcs-orchestrate-caveman.txt");
95
+ const flashPath = resolve(promptsDir, "arcs-flash.txt");
82
96
 
83
97
  // Banner prepended to every generated prompt file. Uses HTML comment syntax
84
98
  // so it's invisible when rendered as markdown but obvious to anyone opening
@@ -102,6 +116,7 @@ async function generateOrchestratorPrompts(outputRoot) {
102
116
  `${banner("src/cli/arcs-orchestrate-caveman.ts")}${cavemanText}\n`,
103
117
  "utf-8",
104
118
  );
119
+ writeFileSync(flashPath, `${banner("src/cli/arcs-flash.ts")}${flashText}\n`, "utf-8");
105
120
  }
106
121
 
107
122
  async function main() {
@@ -140,11 +155,8 @@ async function main() {
140
155
  ]);
141
156
 
142
157
  mkdirSync(outputRoot, { recursive: true });
143
- pruneUndeclaredFiles(outputRoot, allowedOutputFiles);
144
-
145
- // Generate orchestrator prompt mirrors after prune so they always end up
146
- // on disk fresh from the canonical TS sources.
147
158
  await generateOrchestratorPrompts(outputRoot);
159
+ pruneUndeclaredFiles(outputRoot, allowedOutputFiles);
148
160
  }
149
161
 
150
162
  try {
@@ -0,0 +1,125 @@
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
+ * HARD RULE: this script never blocks the session. Any failure — ARCS not
11
+ * running, token rejected, timeout, malformed JSON — is swallowed, nothing is
12
+ * printed, and the exit code stays 0. Exit code 2 (the "block" signal) is never
13
+ * produced. A broken bridge must be invisible, never an obstacle to the user's
14
+ * actual Claude Code session.
15
+ *
16
+ * Config comes from the environment, assigned inline in the settings.json
17
+ * command string:
18
+ * ARCS_HOOK_TOKEN per-project token (required)
19
+ * ARCS_HOOK_SLUG ARCS project slug (required)
20
+ * ARCS_HOOK_URL ARCS web server URL (default http://127.0.0.1:4173)
21
+ */
22
+
23
+ const DEFAULT_URL = "http://127.0.0.1:4173";
24
+ /** Short by design: a hung ARCS server must not stall prompt submission. */
25
+ const TIMEOUT_MS = 1500;
26
+ const EVENTS = new Set(["SessionStart", "UserPromptSubmit", "SessionEnd", "Stop"]);
27
+
28
+ /** Never rejects: an unreadable stdin yields "" and the run turns into a no-op. */
29
+ function readStdin() {
30
+ return new Promise((resolveStdin) => {
31
+ let raw = "";
32
+ let settled = false;
33
+ const finish = () => {
34
+ if (settled) return;
35
+ settled = true;
36
+ clearTimeout(timer);
37
+ process.stdin.destroy();
38
+ resolveStdin(raw);
39
+ };
40
+ const timer = setTimeout(finish, TIMEOUT_MS);
41
+
42
+ process.stdin.setEncoding("utf-8");
43
+ process.stdin.on("data", (chunk) => {
44
+ raw += chunk;
45
+ });
46
+ process.stdin.on("end", finish);
47
+ process.stdin.on("error", finish);
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Labelled and separated so the agent can tell queued out-of-band instructions
53
+ * from the prompt the user just typed.
54
+ */
55
+ function formatQueued(messages) {
56
+ const body = messages.map((m, i) => `[${i + 1}] ${String(m).trim()}`).join("\n\n");
57
+ return `Messages queued from the ARCS web UI, delivered at this checkpoint:\n\n${body}`;
58
+ }
59
+
60
+ async function main() {
61
+ const raw = await readStdin();
62
+ if (!raw.trim()) return;
63
+
64
+ const event = JSON.parse(raw);
65
+ const eventName = event?.hook_event_name;
66
+ const sessionId = event?.session_id;
67
+ if (!EVENTS.has(eventName) || typeof sessionId !== "string" || !sessionId) return;
68
+
69
+ const token = process.env.ARCS_HOOK_TOKEN;
70
+ const slug = process.env.ARCS_HOOK_SLUG;
71
+ if (!token || !slug) return;
72
+ const baseUrl = (process.env.ARCS_HOOK_URL || DEFAULT_URL).replace(/\/+$/, "");
73
+
74
+ const response = await fetch(`${baseUrl}/api/hook/${encodeURIComponent(slug)}/event`, {
75
+ method: "POST",
76
+ headers: {
77
+ "content-type": "application/json",
78
+ authorization: `Bearer ${token}`,
79
+ },
80
+ body: JSON.stringify({
81
+ hook_event_name: eventName,
82
+ session_id: sessionId,
83
+ ...(typeof event.cwd === "string" && { cwd: event.cwd }),
84
+ ...(typeof event.source === "string" && { source: event.source }),
85
+ ...(typeof event.reason === "string" && { reason: event.reason }),
86
+ ...(typeof event.transcript_path === "string" && { transcript_path: event.transcript_path }),
87
+ }),
88
+ signal: AbortSignal.timeout(TIMEOUT_MS),
89
+ });
90
+ if (!response.ok) return;
91
+
92
+ // Only UserPromptSubmit can inject context; the other events are pure
93
+ // notifications and answer with empty stdout.
94
+ if (eventName !== "UserPromptSubmit") return;
95
+
96
+ const envelope = await response.json();
97
+ const messages = envelope?.data?.queuedMessages;
98
+ if (!Array.isArray(messages) || messages.length === 0) return;
99
+
100
+ process.stdout.write(
101
+ JSON.stringify({
102
+ hookSpecificOutput: {
103
+ hookEventName: "UserPromptSubmit",
104
+ additionalContext: formatQueued(messages),
105
+ },
106
+ }),
107
+ );
108
+ }
109
+
110
+ // Belt and braces around the hard rule: even a bug in this file (or a stray
111
+ // async rejection) must not surface as a non-zero exit for the user.
112
+ process.on("uncaughtException", () => {
113
+ process.exitCode = 0;
114
+ });
115
+ process.on("unhandledRejection", () => {
116
+ process.exitCode = 0;
117
+ });
118
+
119
+ // No process.exit(): letting the event loop drain guarantees stdout is flushed
120
+ // before the process ends, and the default exit code is already 0.
121
+ main()
122
+ .catch(() => {})
123
+ .finally(() => {
124
+ process.exitCode = 0;
125
+ });
@@ -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,8 @@
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 through the
13
+ // explicit DEFAULT_AGENT_PRECEDENCE list (default: "arcs-orchestrate")
12
14
  //
13
15
  // Env vars:
14
16
  // DEPLOY_BUNDLE_ROOT — override bundle root (default: opencode/arcs)
@@ -20,6 +22,7 @@
20
22
  // Outputs JSON to stdout: DeployResult
21
23
  // Exit code: 0 on success, 1 on error.
22
24
 
25
+ import { createHash } from "node:crypto";
23
26
  import {
24
27
  existsSync,
25
28
  mkdirSync,
@@ -32,7 +35,13 @@ import {
32
35
  import { homedir } from "node:os";
33
36
  import { dirname, relative, resolve } from "node:path";
34
37
  import { fileURLToPath } from "node:url";
35
- import { wireCodegraphMcp, wireRtk } from "./lib/bundle-helpers.mjs";
38
+ import {
39
+ isActiveAgentForMode,
40
+ isRetiredAgentForMode,
41
+ validateRetirementReplacements,
42
+ wireCodegraphMcp,
43
+ wireRtk,
44
+ } from "./lib/bundle-helpers.mjs";
36
45
 
37
46
  const scriptDir = dirname(fileURLToPath(import.meta.url));
38
47
  const repoRoot = resolve(scriptDir, "..");
@@ -67,9 +76,30 @@ const dryRun = process.env.DEPLOY_DRY_RUN !== "false";
67
76
 
68
77
  const destination = scope === "project" ? projectRoot : configRoot;
69
78
 
70
- const DEFAULT_AGENT = "arcs-orchestrate";
71
79
  const SKILL_PREFIX = "arcs-";
72
80
 
81
+ function isPromptPath(value) {
82
+ if (typeof value !== "string" || value.includes("\\")) return false;
83
+ const segments = value.split("/");
84
+ return (
85
+ segments.length >= 2 &&
86
+ segments[0] === "prompts" &&
87
+ segments.slice(1).every((segment) => segment !== "" && segment !== "." && segment !== "..") &&
88
+ segments.at(-1).endsWith(".txt")
89
+ );
90
+ }
91
+
92
+ function resolveBundlePromptPath(value) {
93
+ if (!isPromptPath(value)) throw new Error(`Invalid bundle prompt path: ${value}`);
94
+ const promptsRoot = resolve(bundleRoot, "prompts");
95
+ const resolvedPath = resolve(promptsRoot, ...value.split("/").slice(1));
96
+ const relativePath = relative(promptsRoot, resolvedPath);
97
+ if (relativePath.split(/[\\/]/).includes("..")) {
98
+ throw new Error(`Bundle prompt path escapes prompts/: ${value}`);
99
+ }
100
+ return resolvedPath;
101
+ }
102
+
73
103
  // ---------------------------------------------------------------------------
74
104
  // Model tier configuration
75
105
  // ---------------------------------------------------------------------------
@@ -81,102 +111,80 @@ const tierModels = {
81
111
  light: process.env.DEPLOY_MODEL_LIGHT || "inherit",
82
112
  };
83
113
 
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
- };
114
+ function readAgentRegistry() {
115
+ const manifestPath = resolve(bundleRoot, "manifest.json");
116
+ if (!existsSync(manifestPath)) throw new Error(`Agent registry not found at ${manifestPath}`);
117
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
118
+ if (!Array.isArray(manifest.agents))
119
+ throw new Error("Invalid agent registry: agents must be an array");
120
+
121
+ const ids = new Set();
122
+ const sources = new Set();
123
+ const destinations = new Set();
124
+ for (const agent of manifest.agents) {
125
+ const valid =
126
+ agent &&
127
+ typeof agent.id === "string" &&
128
+ /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(agent.id) &&
129
+ ["active", "retired"].includes(agent.status) &&
130
+ ["primary", "subagent"].includes(agent.kind) &&
131
+ ["heavy", "standard", "light"].includes(agent.tier) &&
132
+ Array.isArray(agent.modes) &&
133
+ agent.modes.length > 0 &&
134
+ agent.modes.every((mode) => ["opencode", "claudecode"].includes(mode)) &&
135
+ isPromptPath(agent.source) &&
136
+ isPromptPath(agent.destination) &&
137
+ typeof agent.description === "string" &&
138
+ agent.description.length > 0 &&
139
+ agent.permissions &&
140
+ ["allow", "deny"].includes(agent.permissions.edit) &&
141
+ ["allow", "deny"].includes(agent.permissions.bash) &&
142
+ ["allow", "deny"].includes(agent.permissions.webfetch) &&
143
+ ["allow", "deny"].includes(agent.permissions.mcp) &&
144
+ ["allow", "deny"].includes(agent.permissions.task);
145
+ if (!valid) throw new Error(`Invalid agent registry record: ${JSON.stringify(agent)}`);
146
+ if (ids.has(agent.id)) throw new Error(`Duplicate agent registry id: ${agent.id}`);
147
+ if (sources.has(agent.source))
148
+ throw new Error(`Duplicate agent registry source: ${agent.source}`);
149
+ if (destinations.has(agent.destination))
150
+ throw new Error(`Duplicate agent registry destination: ${agent.destination}`);
151
+ ids.add(agent.id);
152
+ sources.add(agent.source);
153
+ destinations.add(agent.destination);
154
+ }
155
+ validateRetirementReplacements(manifest.agents);
156
+ return manifest.agents;
157
+ }
97
158
 
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
- };
159
+ function claudeTools(agent) {
160
+ const tools = [];
161
+ if (agent.permissions.task === "allow") tools.push("Task");
162
+ tools.push("Read");
163
+ if (agent.permissions.edit === "allow") tools.push("Write", "Edit");
164
+ tools.push("Glob", "Grep");
165
+ if (agent.permissions.bash === "allow") tools.push("Bash");
166
+ return tools.join(", ");
167
+ }
175
168
 
176
169
  function ensureParentDir(filePath) {
177
170
  mkdirSync(dirname(filePath), { recursive: true });
178
171
  }
179
172
 
173
+ function sha256(content) {
174
+ return createHash("sha256").update(content).digest("hex");
175
+ }
176
+
177
+ function readInstalledManifest() {
178
+ const manifestPath = resolve(destination, configRelativePath(".arcs-bundle.json"));
179
+ if (!existsSync(manifestPath)) return null;
180
+ try {
181
+ const value = JSON.parse(readFileSync(manifestPath, "utf-8"));
182
+ return value?.bundleId === "arcs-claudecode-bundle" ? value : null;
183
+ } catch {
184
+ return null;
185
+ }
186
+ }
187
+
180
188
  function configRelativePath(suffix) {
181
189
  return scope === "project" ? `.claude/${suffix}` : suffix;
182
190
  }
@@ -204,26 +212,23 @@ function buildAgentSources() {
204
212
  throw new Error(`Prompts directory not found at ${promptsDir}`);
205
213
  }
206
214
 
207
- const promptFiles = readdirSync(promptsDir).filter((f) => f.endsWith(".txt"));
208
- const sources = [];
209
-
215
+ const registry = readAgentRegistry();
216
+ const registeredSources = new Set(registry.map((agent) => agent.source));
217
+ const promptFiles = readdirSync(promptsDir).filter((file) => file.endsWith(".txt"));
210
218
  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");
219
+ const source = `prompts/${file}`;
220
+ if (!registeredSources.has(source)) throw new Error(`Unregistered prompt file: ${source}`);
221
+ }
214
222
 
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
- };
223
+ const sources = [];
224
224
 
225
- const tier = agentTierMap[stem] || "standard";
226
- const model = tierModels[tier];
225
+ for (const agent of registry.filter((record) => isActiveAgentForMode(record, "claudecode"))) {
226
+ const stem = agent.id;
227
+ const sourcePath = resolveBundlePromptPath(agent.source);
228
+ if (!existsSync(sourcePath))
229
+ throw new Error(`Registered agent prompt not found: ${agent.source}`);
230
+ const promptContent = readFileSync(sourcePath, "utf-8");
231
+ const model = tierModels[agent.tier];
227
232
 
228
233
  // Claude Code requires `name` to be a kebab-case identifier (lowercase
229
234
  // letters + hyphens). The filename stem already satisfies this and is
@@ -231,17 +236,12 @@ function buildAgentSources() {
231
236
  // `description`. The default-agent setting (DEFAULT_AGENT) references this
232
237
  // same stem, so it resolves. Display names with spaces/parens/apostrophes
233
238
  // (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
239
  const compiledContent = [
240
240
  "---",
241
241
  `name: ${stem}`,
242
- `description: ${meta.description}`,
242
+ `description: ${agent.description}`,
243
243
  `model: ${model}`,
244
- `tools: ${toolsCsv}`,
244
+ `tools: ${claudeTools(agent)}`,
245
245
  "---",
246
246
  "",
247
247
  promptContent,
@@ -289,7 +289,29 @@ function buildSkillSources() {
289
289
  // 3. settings.json merge — set default agent
290
290
  // ---------------------------------------------------------------------------
291
291
 
292
+ // Which primary becomes the deployed default is an explicit, ordered policy —
293
+ // never "whichever active primary happens to come first in manifest.json".
294
+ // Registry array order must not be able to promote an agent: a new primary
295
+ // (e.g. the speed-optimized arcs-flash) becomes eligible only by being listed
296
+ // here, and only at the rank it is listed at. Earlier entries always win, so a
297
+ // lower-ranked primary is a fallback, never a silent replacement.
298
+ const DEFAULT_AGENT_PRECEDENCE = ["arcs-orchestrate", "arcs-orchestrate-caveman", "arcs-flash"];
299
+
300
+ function selectDefaultAgent(registry) {
301
+ for (const id of DEFAULT_AGENT_PRECEDENCE) {
302
+ const agent = registry.find((record) => record.id === id);
303
+ if (agent && agent.kind === "primary" && isActiveAgentForMode(agent, "claudecode")) {
304
+ return agent;
305
+ }
306
+ }
307
+ throw new Error(
308
+ `No active Claude Code primary agent in default precedence: ${DEFAULT_AGENT_PRECEDENCE.join(", ")}`,
309
+ );
310
+ }
311
+
292
312
  function planSettingsUpdate() {
313
+ const defaultAgent = selectDefaultAgent(readAgentRegistry());
314
+
293
315
  const settingsConfigRelative = configRelativePath("settings.json");
294
316
  const settingsAbsolute = resolve(destination, settingsConfigRelative);
295
317
 
@@ -308,7 +330,7 @@ function planSettingsUpdate() {
308
330
  }
309
331
  }
310
332
 
311
- const merged = { ...parsed, agent: DEFAULT_AGENT };
333
+ const merged = { ...parsed, agent: defaultAgent.id };
312
334
  const serialized = `${JSON.stringify(merged, null, 2)}\n`;
313
335
 
314
336
  let status;
@@ -328,6 +350,8 @@ function planSettingsUpdate() {
328
350
  // ---------------------------------------------------------------------------
329
351
 
330
352
  function main() {
353
+ const registry = readAgentRegistry();
354
+ const previousManifest = readInstalledManifest();
331
355
  const agentSources = buildAgentSources();
332
356
  const skillSources = buildSkillSources();
333
357
  const settingsPlan = planSettingsUpdate();
@@ -375,20 +399,6 @@ function main() {
375
399
  // Orphans
376
400
  const filesRemoved = [];
377
401
 
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
402
  // Skill orphans — only `arcs-*/` directories that aren't in current source.
393
403
  // The prefix gives us a safe namespace; foreign user skills are never touched.
394
404
  const skillsTargetDir = resolve(destination, configRelativePath("skills"));
@@ -405,6 +415,22 @@ function main() {
405
415
  }
406
416
  }
407
417
 
418
+ const retiredById = new Map(
419
+ registry
420
+ .filter((agent) => isRetiredAgentForMode(agent, "claudecode"))
421
+ .map((agent) => [agent.id, agent]),
422
+ );
423
+ for (const ownership of previousManifest?.agents ?? []) {
424
+ const retired = retiredById.get(ownership.id);
425
+ if (!retired) continue;
426
+ const expectedDestination = configRelativePath(`agents/${retired.id}.md`);
427
+ if (ownership.promptDestination !== expectedDestination) continue;
428
+ const installedPath = resolve(destination, ownership.promptDestination);
429
+ if (existsSync(installedPath) && sha256(readFileSync(installedPath)) === ownership.sourceHash) {
430
+ filesRemoved.push(ownership.promptDestination);
431
+ }
432
+ }
433
+
408
434
  // Pass 2: Write if not dry-run
409
435
  if (!dryRun) {
410
436
  for (const { compiledContent, configRelative } of agentSources) {
@@ -432,6 +458,33 @@ function main() {
432
458
  rmSync(abs, { recursive: isDir, force: true });
433
459
  }
434
460
  }
461
+
462
+ const installedManifestPath = resolve(destination, configRelativePath(".arcs-bundle.json"));
463
+ ensureParentDir(installedManifestPath);
464
+ writeFileSync(
465
+ installedManifestPath,
466
+ `${JSON.stringify(
467
+ {
468
+ bundleId: "arcs-claudecode-bundle",
469
+ installMode: `claudecode-${scope}`,
470
+ sourceBundleVersion: "deploy-script",
471
+ sourceBundleHash: sha256(readFileSync(resolve(bundleRoot, "manifest.json"))),
472
+ installedAt: new Date().toISOString(),
473
+ // Persisted so a later `arcs init` can reuse the previous tier
474
+ // selection instead of re-prompting for it.
475
+ tierModels,
476
+ ownedPaths: [],
477
+ agents: agentSources.map((agent) => ({
478
+ id: agent.stem,
479
+ promptDestination: agent.configRelative,
480
+ sourceHash: sha256(agent.compiledContent),
481
+ })),
482
+ },
483
+ null,
484
+ 2,
485
+ )}\n`,
486
+ "utf-8",
487
+ );
435
488
  }
436
489
 
437
490
  // Best-effort: wire the codegraph MCP server. Skipped on dry-run; never fatal.