@phnx-labs/agents-cli 1.22.38 → 1.22.40

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 (554) hide show
  1. package/CHANGELOG.md +302 -0
  2. package/README.md +111 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +46 -27
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +260 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.js +206 -94
  13. package/dist/commands/budget.d.ts +7 -6
  14. package/dist/commands/budget.js +8 -7
  15. package/dist/commands/cloud.js +17 -20
  16. package/dist/commands/commands.js +1 -1
  17. package/dist/commands/computer-actions.d.ts +1 -35
  18. package/dist/commands/computer-actions.js +13 -181
  19. package/dist/commands/computer.d.ts +28 -3
  20. package/dist/commands/computer.js +93 -65
  21. package/dist/commands/config.js +47 -4
  22. package/dist/commands/cost.d.ts +2 -1
  23. package/dist/commands/cost.js +7 -6
  24. package/dist/commands/daemon.js +151 -4
  25. package/dist/commands/detach.js +1 -1
  26. package/dist/commands/doctor.js +19 -11
  27. package/dist/commands/events.js +1 -1
  28. package/dist/commands/exec.d.ts +2 -50
  29. package/dist/commands/exec.js +161 -216
  30. package/dist/commands/factory.js +1 -1
  31. package/dist/commands/feed.d.ts +2 -2
  32. package/dist/commands/feed.js +9 -12
  33. package/dist/commands/fleet-capture.js +25 -27
  34. package/dist/commands/focus.d.ts +2 -3
  35. package/dist/commands/focus.js +34 -9
  36. package/dist/commands/go.js +15 -5
  37. package/dist/commands/harness.d.ts +3 -3
  38. package/dist/commands/harness.js +53 -5
  39. package/dist/commands/hooks.js +1 -1
  40. package/dist/commands/import.js +2 -2
  41. package/dist/commands/insights.d.ts +5 -5
  42. package/dist/commands/insights.js +15 -9
  43. package/dist/commands/inspect.d.ts +2 -3
  44. package/dist/commands/inspect.js +4 -16
  45. package/dist/commands/logs.d.ts +2 -2
  46. package/dist/commands/logs.js +9 -9
  47. package/dist/commands/mcp.js +2 -2
  48. package/dist/commands/memory.js +1 -1
  49. package/dist/commands/message.d.ts +1 -1
  50. package/dist/commands/message.js +7 -7
  51. package/dist/commands/mine.d.ts +11 -8
  52. package/dist/commands/mine.js +11 -10
  53. package/dist/commands/models.js +1 -1
  54. package/dist/commands/modes.js +1 -1
  55. package/dist/commands/monitors.js +23 -6
  56. package/dist/commands/output.d.ts +7 -6
  57. package/dist/commands/output.js +11 -10
  58. package/dist/commands/packages.js +4 -4
  59. package/dist/commands/perf.js +1 -1
  60. package/dist/commands/permissions.js +49 -32
  61. package/dist/commands/plugins.d.ts +1 -1
  62. package/dist/commands/plugins.js +3 -3
  63. package/dist/commands/profiles.d.ts +6 -9
  64. package/dist/commands/profiles.js +8 -321
  65. package/dist/commands/projects.d.ts +9 -0
  66. package/dist/commands/projects.js +140 -8
  67. package/dist/commands/prune.js +5 -13
  68. package/dist/commands/refresh-rules.js +1 -1
  69. package/dist/commands/repo.d.ts +5 -7
  70. package/dist/commands/repo.js +34 -18
  71. package/dist/commands/resource-view.js +4 -0
  72. package/dist/commands/resume.d.ts +11 -7
  73. package/dist/commands/resume.js +82 -98
  74. package/dist/commands/route.d.ts +12 -0
  75. package/dist/commands/route.js +261 -0
  76. package/dist/commands/routines.d.ts +2 -3
  77. package/dist/commands/routines.js +120 -145
  78. package/dist/commands/rules.js +1 -1
  79. package/dist/commands/run-account-picker.d.ts +1 -1
  80. package/dist/commands/run-account-picker.js +2 -2
  81. package/dist/commands/run-broadcast.d.ts +21 -0
  82. package/dist/commands/run-broadcast.js +89 -0
  83. package/dist/commands/run-cloud.js +1 -1
  84. package/dist/commands/secrets-vault.d.ts +10 -0
  85. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  86. package/dist/commands/secrets.d.ts +4 -4
  87. package/dist/commands/secrets.js +72 -63
  88. package/dist/commands/sessions-backfill.js +1 -1
  89. package/dist/commands/sessions-browser.d.ts +1 -1
  90. package/dist/commands/sessions-browser.js +9 -5
  91. package/dist/commands/sessions-export.js +2 -2
  92. package/dist/commands/sessions-inject.js +4 -5
  93. package/dist/commands/sessions-migrate.js +16 -27
  94. package/dist/commands/sessions-picker.d.ts +13 -0
  95. package/dist/commands/sessions-picker.js +182 -8
  96. package/dist/commands/sessions-resume.d.ts +7 -3
  97. package/dist/commands/sessions-resume.js +81 -33
  98. package/dist/commands/sessions-stats.js +2 -2
  99. package/dist/commands/sessions.d.ts +75 -68
  100. package/dist/commands/sessions.js +142 -180
  101. package/dist/commands/setup-computer.js +1 -1
  102. package/dist/commands/setup-fleet.js +3 -0
  103. package/dist/commands/setup-mine.d.ts +7 -3
  104. package/dist/commands/setup-mine.js +13 -8
  105. package/dist/commands/setup-secrets.js +2 -2
  106. package/dist/commands/setup-watchdog.js +2 -2
  107. package/dist/commands/setup.js +7 -2
  108. package/dist/commands/share.d.ts +65 -0
  109. package/dist/commands/share.js +253 -20
  110. package/dist/commands/skills.js +3 -3
  111. package/dist/commands/snapshot.d.ts +2 -2
  112. package/dist/commands/snapshot.js +9 -9
  113. package/dist/commands/ssh.d.ts +1 -1
  114. package/dist/commands/ssh.js +318 -48
  115. package/dist/commands/subagents.js +1 -1
  116. package/dist/commands/sync.js +24 -9
  117. package/dist/commands/teams.d.ts +2 -2
  118. package/dist/commands/teams.js +9 -18
  119. package/dist/commands/tmux.js +5 -1
  120. package/dist/commands/trash.js +1 -1
  121. package/dist/commands/usage.d.ts +1 -1
  122. package/dist/commands/usage.js +2 -2
  123. package/dist/commands/utils.d.ts +4 -14
  124. package/dist/commands/utils.js +6 -27
  125. package/dist/commands/versions.js +2 -2
  126. package/dist/commands/view.d.ts +9 -77
  127. package/dist/commands/view.js +23 -8
  128. package/dist/commands/watchdog.js +1 -1
  129. package/dist/commands/webhook.js +11 -25
  130. package/dist/commands/workflows.js +1 -1
  131. package/dist/index.js +1 -1
  132. package/dist/lib/account-capabilities.d.ts +39 -0
  133. package/dist/lib/account-capabilities.js +59 -0
  134. package/dist/lib/account-catalog.js +1 -1
  135. package/dist/lib/account-registry.d.ts +66 -0
  136. package/dist/lib/account-registry.js +151 -5
  137. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  138. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  139. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  140. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  141. package/dist/lib/agent-spec/provider.js +1 -1
  142. package/dist/lib/agents.d.ts +72 -4
  143. package/dist/lib/agents.js +231 -199
  144. package/dist/lib/answer-router.d.ts +2 -2
  145. package/dist/lib/ask-classifier.d.ts +1 -1
  146. package/dist/lib/ask-classifier.js +1 -1
  147. package/dist/lib/audit/log.js +1 -1
  148. package/dist/lib/auth-health.d.ts +1 -1
  149. package/dist/lib/auth-health.js +2 -2
  150. package/dist/lib/brand.js +1 -1
  151. package/dist/lib/browser/caller-identity.d.ts +28 -0
  152. package/dist/lib/browser/caller-identity.js +156 -0
  153. package/dist/lib/browser/cdp.js +1 -1
  154. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  155. package/dist/lib/browser/drivers/ssh.js +2 -2
  156. package/dist/lib/browser/hygiene.d.ts +10 -2
  157. package/dist/lib/browser/hygiene.js +7 -4
  158. package/dist/lib/browser/ipc.d.ts +22 -2
  159. package/dist/lib/browser/ipc.js +185 -21
  160. package/dist/lib/browser/profiles.d.ts +67 -3
  161. package/dist/lib/browser/profiles.js +129 -7
  162. package/dist/lib/browser/remote-control.d.ts +2 -2
  163. package/dist/lib/browser/remote-control.js +3 -3
  164. package/dist/lib/browser/runtime-state.d.ts +79 -0
  165. package/dist/lib/browser/runtime-state.js +119 -1
  166. package/dist/lib/browser/service.d.ts +113 -1
  167. package/dist/lib/browser/service.js +454 -40
  168. package/dist/lib/browser/sessions-list.d.ts +2 -1
  169. package/dist/lib/browser/sessions-list.js +4 -13
  170. package/dist/lib/browser/types.d.ts +18 -0
  171. package/dist/lib/budget/config.js +1 -1
  172. package/dist/lib/budget/ledger.js +1 -1
  173. package/dist/lib/byok-usage.js +1 -1
  174. package/dist/lib/capabilities.js +3 -15
  175. package/dist/lib/catchup.d.ts +1 -1
  176. package/dist/lib/catchup.js +1 -1
  177. package/dist/lib/cloud/dispatch.js +1 -1
  178. package/dist/lib/cloud/host.d.ts +3 -3
  179. package/dist/lib/cloud/host.js +5 -5
  180. package/dist/lib/cloud/rush.d.ts +9 -21
  181. package/dist/lib/cloud/rush.js +33 -120
  182. package/dist/lib/cloud/types.d.ts +2 -2
  183. package/dist/lib/commands.js +3 -13
  184. package/dist/lib/computer/actions.d.ts +36 -0
  185. package/dist/lib/computer/actions.js +162 -0
  186. package/dist/lib/computer/dispatch.d.ts +2 -2
  187. package/dist/lib/computer/dispatch.js +2 -2
  188. package/dist/lib/computer/sessions-list.d.ts +3 -3
  189. package/dist/lib/computer/sessions-list.js +2 -2
  190. package/dist/lib/config-keys.d.ts +12 -3
  191. package/dist/lib/config-keys.js +29 -6
  192. package/dist/lib/config-machine-keys.d.ts +4 -2
  193. package/dist/lib/config-machine-keys.js +6 -2
  194. package/dist/lib/crabbox/lease.js +9 -1
  195. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  196. package/dist/lib/crabbox/runtimes.js +72 -30
  197. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  198. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  199. package/dist/lib/daemon-services.d.ts +1 -1
  200. package/dist/lib/daemon-services.js +5 -0
  201. package/dist/lib/daemon-ticks.d.ts +25 -0
  202. package/dist/lib/daemon-ticks.js +31 -1
  203. package/dist/lib/daemon-webhooks.d.ts +102 -0
  204. package/dist/lib/daemon-webhooks.js +210 -0
  205. package/dist/lib/device-config.d.ts +116 -72
  206. package/dist/lib/device-config.js +366 -132
  207. package/dist/lib/devices/config-migration.d.ts +29 -34
  208. package/dist/lib/devices/config-migration.js +209 -130
  209. package/dist/lib/devices/connect.d.ts +2 -2
  210. package/dist/lib/devices/connect.js +2 -2
  211. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  212. package/dist/lib/devices/discovery-policy.js +101 -0
  213. package/dist/lib/devices/fleet-inventory.js +8 -3
  214. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  215. package/dist/lib/devices/harness-inventory.js +12 -3
  216. package/dist/lib/devices/known-hosts.js +1 -1
  217. package/dist/lib/devices/pool.d.ts +61 -0
  218. package/dist/lib/devices/pool.js +83 -0
  219. package/dist/lib/devices/registry.d.ts +1 -1
  220. package/dist/lib/devices/registry.js +1 -1
  221. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  222. package/dist/lib/devices/resolve-profile.js +2 -2
  223. package/dist/lib/devices/resolve-target.d.ts +1 -1
  224. package/dist/lib/devices/resolve-target.js +4 -4
  225. package/dist/lib/devices/self-host.d.ts +1 -1
  226. package/dist/lib/devices/self-host.js +3 -3
  227. package/dist/lib/devices/ssh-config.d.ts +1 -1
  228. package/dist/lib/devices/stats-cache.js +1 -1
  229. package/dist/lib/devices/sync.d.ts +3 -1
  230. package/dist/lib/devices/sync.js +3 -3
  231. package/dist/lib/doctor-diff.js +4 -4
  232. package/dist/lib/drift-sync.js +2 -2
  233. package/dist/lib/drift.js +2 -2
  234. package/dist/lib/event-families.d.ts +1 -1
  235. package/dist/lib/event-stream.d.ts +1 -1
  236. package/dist/lib/event-stream.js +2 -2
  237. package/dist/lib/events-ingest.js +2 -2
  238. package/dist/lib/exec.d.ts +8 -5
  239. package/dist/lib/exec.js +19 -13
  240. package/dist/lib/factory/snapshot.d.ts +1 -1
  241. package/dist/lib/factory/snapshot.js +1 -1
  242. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  243. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  244. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  245. package/dist/lib/{events.js → feed/events.js} +5 -5
  246. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  247. package/dist/lib/feed-outcome.d.ts +1 -1
  248. package/dist/lib/feed-policy.d.ts +1 -1
  249. package/dist/lib/feed-policy.js +1 -1
  250. package/dist/lib/feed-post.d.ts +1 -1
  251. package/dist/lib/feed-post.js +1 -1
  252. package/dist/lib/feed-ranking.d.ts +1 -1
  253. package/dist/lib/fleet/apply.d.ts +0 -6
  254. package/dist/lib/fleet/apply.js +18 -45
  255. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  256. package/dist/lib/fleet/auth-sync.js +16 -75
  257. package/dist/lib/fleet/capture.js +8 -6
  258. package/dist/lib/fleet/manifest.js +23 -11
  259. package/dist/lib/fleet/types.d.ts +19 -7
  260. package/dist/lib/fleet-cache.d.ts +1 -1
  261. package/dist/lib/fleet-cache.js +1 -1
  262. package/dist/lib/format.d.ts +19 -0
  263. package/dist/lib/format.js +44 -1
  264. package/dist/lib/friction-heuristics.d.ts +1 -1
  265. package/dist/lib/git.d.ts +24 -1
  266. package/dist/lib/git.js +82 -38
  267. package/dist/lib/heal.js +3 -3
  268. package/dist/lib/hooks.d.ts +18 -0
  269. package/dist/lib/hooks.js +113 -1
  270. package/dist/lib/hosts/credentials.d.ts +30 -10
  271. package/dist/lib/hosts/credentials.js +38 -26
  272. package/dist/lib/hosts/dispatch.d.ts +3 -3
  273. package/dist/lib/hosts/dispatch.js +3 -3
  274. package/dist/lib/hosts/option.d.ts +3 -3
  275. package/dist/lib/hosts/option.js +7 -8
  276. package/dist/lib/hosts/passthrough.d.ts +17 -17
  277. package/dist/lib/hosts/passthrough.js +67 -50
  278. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  279. package/dist/lib/hosts/providers/devices.js +1 -1
  280. package/dist/lib/hosts/reconcile.d.ts +1 -1
  281. package/dist/lib/hosts/reconcile.js +1 -1
  282. package/dist/lib/hosts/reconnect.d.ts +1 -1
  283. package/dist/lib/hosts/reconnect.js +2 -2
  284. package/dist/lib/hosts/registry.d.ts +5 -5
  285. package/dist/lib/hosts/registry.js +5 -5
  286. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  287. package/dist/lib/hosts/remote-cmd.js +25 -18
  288. package/dist/lib/hosts/remote-os.d.ts +4 -4
  289. package/dist/lib/hosts/remote-os.js +4 -4
  290. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  291. package/dist/lib/hosts/remote-session-id.js +2 -2
  292. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  293. package/dist/lib/hosts/routing-flag.js +4 -5
  294. package/dist/lib/hosts/run-target.d.ts +4 -4
  295. package/dist/lib/hosts/run-target.js +4 -4
  296. package/dist/lib/hosts/session-index.d.ts +2 -2
  297. package/dist/lib/hosts/session-index.js +1 -1
  298. package/dist/lib/hosts/session-marker.d.ts +1 -1
  299. package/dist/lib/hosts/session-marker.js +1 -1
  300. package/dist/lib/hosts/types.d.ts +2 -2
  301. package/dist/lib/hosts/types.js +2 -2
  302. package/dist/lib/import.js +1 -1
  303. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +49 -1
  304. package/dist/lib/{migrate.js → installations/migrate.js} +265 -38
  305. package/dist/lib/installations/resolve.js +1 -1
  306. package/dist/lib/installations/strategies.js +1 -1
  307. package/dist/lib/installations/update.js +2 -2
  308. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  309. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  310. package/dist/lib/isolation-boundary-report.js +1 -1
  311. package/dist/lib/linear-projects.d.ts +28 -0
  312. package/dist/lib/linear-projects.js +30 -0
  313. package/dist/lib/loop.js +1 -1
  314. package/dist/lib/mailbox-gc.js +1 -1
  315. package/dist/lib/mailbox.js +1 -1
  316. package/dist/lib/mcp-registry.d.ts +62 -0
  317. package/dist/lib/mcp-registry.js +177 -0
  318. package/dist/lib/mcp.d.ts +5 -0
  319. package/dist/lib/mcp.js +124 -307
  320. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  321. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  322. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  323. package/dist/lib/menubar/install-menubar.js +24 -6
  324. package/dist/lib/menubar/snapshot.d.ts +7 -0
  325. package/dist/lib/menubar/snapshot.js +8 -6
  326. package/dist/lib/models.js +1 -1
  327. package/dist/lib/monitors/config.d.ts +12 -0
  328. package/dist/lib/monitors/config.js +3 -0
  329. package/dist/lib/monitors/dispatch.js +26 -5
  330. package/dist/lib/monitors/engine.js +10 -0
  331. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  332. package/dist/lib/monitors/state.d.ts +42 -0
  333. package/dist/lib/monitors/state.js +30 -0
  334. package/dist/lib/notify.d.ts +1 -1
  335. package/dist/lib/observe-aliases.d.ts +2 -2
  336. package/dist/lib/observe-aliases.js +2 -11
  337. package/dist/lib/output/git-output.js +2 -2
  338. package/dist/lib/overdue.d.ts +1 -1
  339. package/dist/lib/overdue.js +1 -1
  340. package/dist/lib/permissions-registry.d.ts +65 -0
  341. package/dist/lib/permissions-registry.js +599 -0
  342. package/dist/lib/permissions.d.ts +24 -13
  343. package/dist/lib/permissions.js +52 -271
  344. package/dist/lib/picker.d.ts +16 -0
  345. package/dist/lib/picker.js +33 -3
  346. package/dist/lib/placement.d.ts +1 -1
  347. package/dist/lib/placement.js +4 -4
  348. package/dist/lib/platform/paths.d.ts +8 -0
  349. package/dist/lib/platform/paths.js +11 -0
  350. package/dist/lib/platform/posixpath.js +3 -3
  351. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  352. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  353. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  354. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  355. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  356. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  357. package/dist/lib/pricing/cost.d.ts +1 -1
  358. package/dist/lib/pricing/cost.js +1 -1
  359. package/dist/lib/profiles-presets.d.ts +1 -1
  360. package/dist/lib/profiles-presets.js +1 -1
  361. package/dist/lib/profiles.js +2 -2
  362. package/dist/lib/project-import.js +4 -1
  363. package/dist/lib/project-launch.d.ts +1 -1
  364. package/dist/lib/project-launch.js +3 -3
  365. package/dist/lib/project-pull.d.ts +128 -0
  366. package/dist/lib/project-pull.js +384 -0
  367. package/dist/lib/project-root.d.ts +2 -2
  368. package/dist/lib/project-root.js +2 -2
  369. package/dist/lib/project-status.js +1 -1
  370. package/dist/lib/projects.d.ts +23 -0
  371. package/dist/lib/projects.js +29 -6
  372. package/dist/lib/refresh.d.ts +12 -1
  373. package/dist/lib/refresh.js +16 -9
  374. package/dist/lib/registry.d.ts +9 -2
  375. package/dist/lib/registry.js +11 -4
  376. package/dist/lib/resources.d.ts +2 -2
  377. package/dist/lib/resources.js +2 -2
  378. package/dist/lib/routers.d.ts +81 -0
  379. package/dist/lib/routers.js +153 -0
  380. package/dist/lib/routine-context.d.ts +1 -0
  381. package/dist/lib/routine-context.js +7 -2
  382. package/dist/lib/routine-notify-owner.d.ts +1 -1
  383. package/dist/lib/routine-notify.d.ts +1 -1
  384. package/dist/lib/routine-notify.js +1 -1
  385. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  386. package/dist/lib/routine-readiness.d.ts +1 -1
  387. package/dist/lib/routine-readiness.js +11 -4
  388. package/dist/lib/routines-placement.d.ts +12 -2
  389. package/dist/lib/routines-placement.js +20 -3
  390. package/dist/lib/routines-project.d.ts +1 -1
  391. package/dist/lib/routines-project.js +1 -1
  392. package/dist/lib/rules/compile.d.ts +1 -0
  393. package/dist/lib/rules/compile.js +10 -2
  394. package/dist/lib/rules/rules.js +1 -1
  395. package/dist/lib/run-notify.js +1 -1
  396. package/dist/lib/runner.d.ts +80 -2
  397. package/dist/lib/runner.js +241 -62
  398. package/dist/lib/sandbox.d.ts +1 -1
  399. package/dist/lib/scheduler.d.ts +1 -1
  400. package/dist/lib/scheduler.js +1 -1
  401. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  402. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  403. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  404. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  405. package/dist/lib/secrets/agent.js +2 -2
  406. package/dist/lib/secrets/audit.js +1 -1
  407. package/dist/lib/secrets/bundles.d.ts +3 -3
  408. package/dist/lib/secrets/bundles.js +7 -7
  409. package/dist/lib/secrets/index.js +1 -1
  410. package/dist/lib/secrets/list-filter.d.ts +1 -1
  411. package/dist/lib/secrets/list-filter.js +2 -2
  412. package/dist/lib/secrets/push.d.ts +1 -1
  413. package/dist/lib/secrets/push.js +10 -12
  414. package/dist/lib/secrets/remote.d.ts +12 -10
  415. package/dist/lib/secrets/remote.js +21 -14
  416. package/dist/lib/secrets/vault.js +2 -2
  417. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  418. package/dist/lib/self-heal/checks/shims.js +1 -1
  419. package/dist/lib/self-update.d.ts +39 -4
  420. package/dist/lib/self-update.js +78 -25
  421. package/dist/lib/serve/control.d.ts +1 -1
  422. package/dist/lib/serve/control.js +4 -4
  423. package/dist/lib/serve/data.d.ts +1 -1
  424. package/dist/lib/serve/data.js +1 -1
  425. package/dist/lib/serve/stream.js +1 -1
  426. package/dist/lib/service-manifest.d.ts +29 -0
  427. package/dist/lib/service-manifest.js +80 -0
  428. package/dist/lib/session/active.d.ts +59 -7
  429. package/dist/lib/session/active.js +158 -17
  430. package/dist/lib/session/bash-command.js +1 -1
  431. package/dist/lib/session/claude-accounts.d.ts +1 -1
  432. package/dist/lib/session/claude-accounts.js +1 -1
  433. package/dist/lib/session/db.d.ts +10 -2
  434. package/dist/lib/session/db.js +25 -6
  435. package/dist/lib/session/discover.d.ts +77 -0
  436. package/dist/lib/session/discover.js +130 -25
  437. package/dist/lib/session/fork.js +1 -1
  438. package/dist/lib/session/inject.d.ts +1 -1
  439. package/dist/lib/session/insights.d.ts +1 -1
  440. package/dist/lib/session/insights.js +1 -1
  441. package/dist/lib/session/live-metadata.d.ts +15 -0
  442. package/dist/lib/session/live-metadata.js +76 -0
  443. package/dist/lib/session/migrate-targets.d.ts +1 -1
  444. package/dist/lib/session/recovery.d.ts +1 -1
  445. package/dist/lib/session/recovery.js +2 -2
  446. package/dist/lib/session/remote-active.d.ts +10 -1
  447. package/dist/lib/session/remote-active.js +8 -3
  448. package/dist/lib/session/remote-bundle.d.ts +1 -1
  449. package/dist/lib/session/remote-bundle.js +2 -2
  450. package/dist/lib/session/remote-list.d.ts +15 -4
  451. package/dist/lib/session/remote-list.js +40 -3
  452. package/dist/lib/session/remote.d.ts +5 -5
  453. package/dist/lib/session/remote.js +13 -17
  454. package/dist/lib/session/resume-command.d.ts +3 -2
  455. package/dist/lib/session/resume-command.js +4 -3
  456. package/dist/lib/session/resume-owner.d.ts +3 -3
  457. package/dist/lib/session/resume-owner.js +3 -3
  458. package/dist/lib/session/session-cache.d.ts +12 -0
  459. package/dist/lib/session/session-cache.js +2 -0
  460. package/dist/lib/session/shell-programs.js +1 -1
  461. package/dist/lib/session/state.js +5 -5
  462. package/dist/lib/session/team-filter.d.ts +1 -1
  463. package/dist/lib/session/team-filter.js +1 -1
  464. package/dist/lib/session/types.d.ts +3 -3
  465. package/dist/lib/session/width.d.ts +2 -2
  466. package/dist/lib/session/width.js +2 -2
  467. package/dist/lib/share/delete.d.ts +21 -0
  468. package/dist/lib/share/delete.js +42 -0
  469. package/dist/lib/share/publish.d.ts +82 -0
  470. package/dist/lib/share/publish.js +170 -18
  471. package/dist/lib/share/worker-template.js +172 -9
  472. package/dist/lib/shims.js +35 -7
  473. package/dist/lib/smart-launch.d.ts +36 -6
  474. package/dist/lib/smart-launch.js +65 -8
  475. package/dist/lib/snapshot.d.ts +4 -4
  476. package/dist/lib/snapshot.js +2 -2
  477. package/dist/lib/ssh-exec.d.ts +1 -1
  478. package/dist/lib/ssh-exec.js +2 -2
  479. package/dist/lib/ssh-tunnel.d.ts +10 -10
  480. package/dist/lib/ssh-tunnel.js +12 -12
  481. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  482. package/dist/lib/staleness/checkers/hooks.js +1 -1
  483. package/dist/lib/staleness/detectors/permissions.js +0 -23
  484. package/dist/lib/staleness/detectors/plugins.js +1 -1
  485. package/dist/lib/staleness/fingerprint.js +1 -1
  486. package/dist/lib/staleness/layers.d.ts +1 -1
  487. package/dist/lib/staleness/layers.js +1 -1
  488. package/dist/lib/staleness/writers/mcp.js +3 -1
  489. package/dist/lib/staleness/writers/plugins.js +1 -1
  490. package/dist/lib/staleness/writers/types.d.ts +8 -0
  491. package/dist/lib/startup/command-registry.d.ts +5 -147
  492. package/dist/lib/startup/command-registry.js +38 -303
  493. package/dist/lib/startup/dev-build.d.ts +0 -21
  494. package/dist/lib/startup/dev-build.js +29 -8
  495. package/dist/lib/state.d.ts +19 -1
  496. package/dist/lib/state.js +120 -51
  497. package/dist/lib/subagents.js +1 -1
  498. package/dist/lib/sync-status.js +1 -1
  499. package/dist/lib/sync-umbrella.d.ts +6 -1
  500. package/dist/lib/sync-umbrella.js +9 -4
  501. package/dist/lib/teams/agents.js +2 -2
  502. package/dist/lib/teams/registry.js +1 -1
  503. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  504. package/dist/lib/terminal/engine.js +1 -1
  505. package/dist/lib/terminal/index.d.ts +4 -0
  506. package/dist/lib/terminal/index.js +3 -0
  507. package/dist/lib/terminal/inject.d.ts +2 -2
  508. package/dist/lib/terminal/inject.js +2 -2
  509. package/dist/lib/terminal/transport.js +1 -1
  510. package/dist/lib/tmux/index.d.ts +1 -1
  511. package/dist/lib/tmux/index.js +1 -1
  512. package/dist/lib/tmux/session.d.ts +21 -5
  513. package/dist/lib/tmux/session.js +76 -22
  514. package/dist/lib/triggers/handlers.d.ts +1 -1
  515. package/dist/lib/triggers/handlers.js +2 -2
  516. package/dist/lib/triggers/webhook.d.ts +36 -2
  517. package/dist/lib/triggers/webhook.js +97 -42
  518. package/dist/lib/types.d.ts +18 -6
  519. package/dist/lib/usage-fleet.d.ts +1 -1
  520. package/dist/lib/usage-fleet.js +1 -1
  521. package/dist/lib/usage-refresh.d.ts +1 -1
  522. package/dist/lib/usage-refresh.js +3 -3
  523. package/dist/lib/version-duplicates.js +2 -2
  524. package/dist/lib/view-types.d.ts +56 -0
  525. package/dist/lib/view-types.js +1 -0
  526. package/dist/lib/watchdog/rotate.d.ts +2 -2
  527. package/dist/lib/watchdog/rotate.js +3 -3
  528. package/dist/lib/watchdog/runner.d.ts +2 -3
  529. package/dist/lib/watchdog/runner.js +3 -4
  530. package/dist/lib/workflows.js +1 -1
  531. package/package.json +2 -1
  532. package/scripts/postinstall.js +2 -2
  533. package/dist/commands/bench.d.ts +0 -2
  534. package/dist/commands/bench.js +0 -101
  535. package/dist/commands/cp.d.ts +0 -84
  536. package/dist/commands/cp.js +0 -231
  537. package/dist/commands/login.d.ts +0 -2
  538. package/dist/lib/resources/commands.d.ts +0 -46
  539. package/dist/lib/resources/commands.js +0 -211
  540. package/dist/lib/resources/hooks.d.ts +0 -16
  541. package/dist/lib/resources/hooks.js +0 -153
  542. package/dist/lib/resources/mcp.d.ts +0 -34
  543. package/dist/lib/resources/mcp.js +0 -250
  544. package/dist/lib/resources/memory.d.ts +0 -15
  545. package/dist/lib/resources/memory.js +0 -46
  546. package/dist/lib/resources/permissions.d.ts +0 -13
  547. package/dist/lib/resources/permissions.js +0 -202
  548. package/dist/lib/resources/rules.d.ts +0 -46
  549. package/dist/lib/resources/rules.js +0 -179
  550. package/dist/lib/resources/skills.d.ts +0 -37
  551. package/dist/lib/resources/skills.js +0 -247
  552. package/dist/lib/resources/subagents.d.ts +0 -46
  553. package/dist/lib/resources/subagents.js +0 -202
  554. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
package/dist/lib/exec.js CHANGED
@@ -10,11 +10,11 @@ import * as fs from 'fs';
10
10
  import * as path from 'path';
11
11
  import { ALL_MODES } from './types.js';
12
12
  import { AGENTS, findInPath } from './agents.js';
13
- import { parseTimeout } from './routines.js';
14
- import { compareVersions, getBinaryPath, getVersionHomePath, isVersionInstalled, listInstalledVersions, resolveVersion } from './versions.js';
13
+ import { parseTimeout } from './scheduling/routines.js';
14
+ import { compareVersions, getBinaryPath, getVersionHomePath, isVersionInstalled, listInstalledVersions, resolveVersion } from './installations/versions.js';
15
15
  import { resolveModel, buildReasoningFlags } from './models.js';
16
16
  import { isTierToken, resolveTier } from './model-tiers.js';
17
- import { createTimer, redactPrompt, redactArgs } from './events.js';
17
+ import { createTimer, redactPrompt, redactArgs } from './feed/events.js';
18
18
  import { sanitizeProcessEnv } from './secrets/bundles.js';
19
19
  import { resolveActor, actorEnv } from './actor.js';
20
20
  import { expandLocalHome } from './project-root.js';
@@ -29,6 +29,8 @@ import { recordRunName } from './session/run-names.js';
29
29
  import { mailboxDir, isValidMailboxId } from './mailbox.js';
30
30
  import { composeWin32CommandLine } from './platform/index.js';
31
31
  import { isTmuxInstalled } from './tmux/binary.js';
32
+ import { isTmuxEnabled } from './device-config.js';
33
+ import { machineId } from './machine-id.js';
32
34
  import { shellQuote } from './ssh-exec.js';
33
35
  import { resolveClaudeSetupToken } from './claude-account-token.js';
34
36
  import { codexEditWritableRoots, codexPolicyArgs } from './codex-policy.js';
@@ -257,10 +259,10 @@ export function parseExecEnv(entries) {
257
259
  * alongside the agent's real session id (terminals/sessions/<pid>.json), so it
258
260
  * is what maps a launch to its exact session even when the hook runs under a
259
261
  * different pid (tmux pane leaf / cmd.exe wrapper) — and, across an SSH hop, what
260
- * lets a `--host` launcher resolve the remote-coined id for agents that never
262
+ * lets a `--device` launcher resolve the remote-coined id for agents that never
261
263
  * accept a forced `--session-id`.
262
264
  *
263
- * ADOPT a caller-supplied `AGENT_LAUNCH_ID` (a `--host` launcher forwards one via
265
+ * ADOPT a caller-supplied `AGENT_LAUNCH_ID` (a `--device` launcher forwards one via
264
266
  * `--env` so it controls the key end-to-end); MINT a fresh one otherwise (every
265
267
  * local run, which passes none). A malformed inbound value is ignored in favour
266
268
  * of a fresh mint — the key must be a real correlation id, never an empty string.
@@ -471,7 +473,7 @@ export function buildExecEnv(options) {
471
473
  // (events.ts::resolveProvenance) reads AGENTS_PARENT_SESSION_ID and stamps it on
472
474
  // every event the child emits. `options.sessionId` is the CHILD's id, so read the
473
475
  // spawner from the live env; guard a same-session resume from naming itself parent.
474
- // Local-spawn scope here; forwarding it across the `--host` SSH hop is Phase 4.
476
+ // Local-spawn scope here; forwarding it across the `--device` SSH hop is Phase 4.
475
477
  const spawnerSessionId = process.env.AGENTS_SESSION_ID || process.env.AGENT_SESSION_ID;
476
478
  if (spawnerSessionId && spawnerSessionId !== options.sessionId) {
477
479
  result.AGENTS_PARENT_SESSION_ID = spawnerSessionId;
@@ -1292,7 +1294,7 @@ export function shouldRecapDeadPane(status, interactive) {
1292
1294
  * Why this is not `status ?? 0`: an interactive run whose tmux server died mid-
1293
1295
  * work landed on exactly those unknown branches and returned 0, so `agents run`
1294
1296
  * printed a failure banner while handing its caller a success code. The same
1295
- * "1 if unknown" rule already governs the `--host` follow path
1297
+ * "1 if unknown" rule already governs the `--device` follow path
1296
1298
  * (`docs/specifications.md` §Agent execution, exit-code table).
1297
1299
  *
1298
1300
  * @param pane What `paneExitStatus` read back for the agent pane.
@@ -1327,12 +1329,13 @@ export function isPaneKnownAliveFromQueryResult(code, stdout) {
1327
1329
  * focus` re-attach a live session without forking it. Pure so the gate is unit-
1328
1330
  * tested independently of the (side-effecting) spawn.
1329
1331
  *
1330
- * All five guards must pass:
1332
+ * All seven guards must pass:
1331
1333
  * - interactive — a headless `-p` run has no TTY to attach; keep bare spawn.
1332
1334
  * - not Windows — no tmux path on win32.
1333
1335
  * - not already in tmux — nesting tmux-in-tmux is pointless and confusing.
1334
1336
  * - not --raw — explicit opt-out.
1335
1337
  * - not AGENTS_NO_TMUX=1 — env opt-out (CI, scripts, the shim passthrough path).
1338
+ * - tmux.enabled — this device's durable opt-out, for a box whose tmux is broken.
1336
1339
  * - tmux installed — otherwise there is nothing to wrap with.
1337
1340
  */
1338
1341
  export function shouldWrapInTmux(ctx) {
@@ -1346,6 +1349,8 @@ export function shouldWrapInTmux(ctx) {
1346
1349
  return false;
1347
1350
  if (ctx.noTmuxEnv)
1348
1351
  return false;
1352
+ if (!ctx.configEnabled)
1353
+ return false;
1349
1354
  if (!ctx.tmuxAvailable)
1350
1355
  return false;
1351
1356
  return true;
@@ -1459,7 +1464,7 @@ async function runInTmux(options, executable, args) {
1459
1464
  const idSeed = (options.sessionId ?? randomUUID()).slice(0, 8);
1460
1465
  const name = slugifyName(`ag-${options.agent}-${idSeed}`);
1461
1466
  const RED = '\x1b[31m', GRAY = '\x1b[90m', OFF = '\x1b[0m';
1462
- const NO_TMUX_TIP = `${GRAY} Tip: re-run with --no-tmux to launch the agent directly and see its full output.${OFF}\n\n`;
1467
+ const NO_TMUX_TIP = `${GRAY} Tip: re-run with --no-tmux to launch the agent directly and see its full output.\n If tmux is broken on this machine, turn the wrap off for good: agents config set devices.${machineId()}.tmux off${OFF}\n\n`;
1463
1468
  // Recap a dead pane's tail into THIS shell's stderr. The pane-died hook
1464
1469
  // detaches the client the instant the agent exits, so a fast failure (a
1465
1470
  // gutted install that dies with ENOENT, a bad flag, a crash on startup) would
@@ -1530,7 +1535,7 @@ async function runInTmux(options, executable, args) {
1530
1535
  // agent finished or was killed. MUST NOT be reported as success: a caller
1531
1536
  // scripting `agents run` would count a run killed mid-work as a clean
1532
1537
  // finish. Tear down so no orphan session is left, say so, and exit non-zero
1533
- // — the same "1 if unknown" rule the `--host` follow path already uses.
1538
+ // — the same "1 if unknown" rule the `--device` follow path already uses.
1534
1539
  await killSession(name, socket).catch(() => { });
1535
1540
  // One computation feeds both the banner and the return value — printing a
1536
1541
  // code the caller does not receive is the same defect in miniature.
@@ -1658,7 +1663,7 @@ async function runInTmux(options, executable, args) {
1658
1663
  return resolveAfterAttach(pane);
1659
1664
  }
1660
1665
  /**
1661
- * Print the run's resolved session id as a one-line stdout sentinel so a `--host`
1666
+ * Print the run's resolved session id as a one-line stdout sentinel so a `--device`
1662
1667
  * launcher can relate the remote-created session back to itself (see the
1663
1668
  * `emitSessionId` option and hosts/session-marker.ts).
1664
1669
  *
@@ -1731,7 +1736,7 @@ async function spawnAgent(options) {
1731
1736
  // That id is the join key that reconciles this launch's pid-registry entry
1732
1737
  // with the hook's authoritative session id even when the hook runs under a
1733
1738
  // different pid (tmux pane leaf / cmd.exe wrapper) — see pid-registry.ts and
1734
- // session/hook-sessions.ts. ADOPT a launch id a `--host` launcher already
1739
+ // session/hook-sessions.ts. ADOPT a launch id a `--device` launcher already
1735
1740
  // forwarded (via `--env AGENT_LAUNCH_ID=…`) so ONE correlation key spans the
1736
1741
  // SSH hop and the launcher can resolve this run's real session id for every
1737
1742
  // agent, not just Claude (RUSH-2034); mint a fresh one for every local run.
@@ -1766,6 +1771,7 @@ async function spawnAgent(options) {
1766
1771
  inTmux: !!process.env.TMUX,
1767
1772
  raw: options.raw === true,
1768
1773
  noTmuxEnv: process.env.AGENTS_NO_TMUX === '1',
1774
+ configEnabled: isTmuxEnabled(),
1769
1775
  tmuxAvailable: isTmuxInstalled(),
1770
1776
  })) {
1771
1777
  timer.mark('startup');
@@ -1913,7 +1919,7 @@ async function spawnAgent(options) {
1913
1919
  // Budget kill resolves with a DISTINCT non-zero exit so CI/headless and
1914
1920
  // teams/cloud can tell a budget termination apart from a normal failure.
1915
1921
  const exitCode = budgetKilled ? BUDGET_KILL_EXIT_CODE : (code ?? 0);
1916
- // Relate the session id back to a `--host` launcher (see the emitSessionId
1922
+ // Relate the session id back to a `--device` launcher (see the emitSessionId
1917
1923
  // doc). Claude's id is the one we forced; every other agent coined its own,
1918
1924
  // which the SessionStart hook recorded under this run's launchId — resolve
1919
1925
  // and print it as a one-line sentinel that rides the followed log home.
@@ -1,5 +1,5 @@
1
1
  import { type ActiveSession } from '../session/active.js';
2
- import { serializeActiveSessionsForJson } from '../../commands/sessions.js';
2
+ import { serializeActiveSessionsForJson } from '../session/active.js';
3
3
  import { readAuthHealthCache, type AuthVerdict } from '../auth-health.js';
4
4
  import { readStatsCache } from '../devices/stats-cache.js';
5
5
  export declare const FACTORY_PROJECTS: readonly [{
@@ -17,7 +17,7 @@ import { execFile as execFileCallback } from 'child_process';
17
17
  import { promisify } from 'util';
18
18
  import * as yaml from 'yaml';
19
19
  import { getActiveSessions } from '../session/active.js';
20
- import { serializeActiveSessionsForJson } from '../../commands/sessions.js';
20
+ import { serializeActiveSessionsForJson } from '../session/active.js';
21
21
  import { readAuthHealthCache } from '../auth-health.js';
22
22
  import { readStatsCache } from '../devices/stats-cache.js';
23
23
  const execFile = promisify(execFileCallback);
@@ -1,4 +1,4 @@
1
- import type { ActorKind } from './actor.js';
1
+ import type { ActorKind } from '../actor.js';
2
2
  import type { EventRecord } from './events.js';
3
3
  /** Recognizable milestone events, ordered first in any activity lane. */
4
4
  export type MilestoneEvent = 'plan.created' | 'pr.opened' | 'pr.merged' | 'worktree.created' | 'worktree.removed' | 'commit.created' | 'pushed' | 'subagent.spawned' | 'artifact.created' | 'task.completed' | 'checklist.created'
@@ -20,14 +20,14 @@
20
20
  import * as fs from 'fs';
21
21
  import * as path from 'path';
22
22
  import * as yaml from 'yaml';
23
- import { stringifyDoc } from './yaml-io.js';
23
+ import { stringifyDoc } from '../yaml-io.js';
24
24
  import chalk from 'chalk';
25
- import { relTime, truncate } from './format.js';
26
- import { getActivityDir, getUserAgentsDir } from './state.js';
27
- import { normalizeHost } from './machine-id.js';
28
- import { projectKeyFromCwd } from './project-key.js';
29
- import { stampProvenance } from './event-provenance.js';
30
- import { pythonToolRegistryLiteral, pythonValueFlagsLiteral, } from './session/bash-command.js';
25
+ import { relTime, truncate } from '../format.js';
26
+ import { getActivityDir, getUserAgentsDir } from '../state.js';
27
+ import { normalizeHost } from '../machine-id.js';
28
+ import { projectKeyFromCwd } from '../project-key.js';
29
+ import { stampProvenance } from '../event-provenance.js';
30
+ import { pythonToolRegistryLiteral, pythonValueFlagsLiteral, } from '../session/bash-command.js';
31
31
  /** The set of milestone events, for tier classification and ordering. */
32
32
  export const MILESTONE_EVENTS = [
33
33
  'plan.created',
@@ -11,9 +11,9 @@
11
11
  * - Permissions: logs dir is 0700, files are 0600 (owner-only)
12
12
  * - Performance tracking: withTiming() wrapper for any async function
13
13
  */
14
- import type { ActorKind } from './actor.js';
14
+ import type { ActorKind } from '../actor.js';
15
15
  export type EventLevel = 'audit' | 'warn' | 'info' | 'debug';
16
- export type EventType = 'agent.run.start' | 'agent.run.end' | 'agent.spawn.start' | 'agent.spawn.end' | 'run.dispatched' | 'daemon.start' | 'daemon.stop' | 'daemon.error' | 'daemon.info' | 'routine.start' | 'routine.end' | 'watchdog.action' | 'version.install' | 'version.switch' | 'version.remove' | 'skill.install' | 'skill.remove' | 'browser.launch' | 'browser.close' | 'browser.navigate' | 'browser.screenshot' | 'computer.action' | 'secrets.get' | 'secrets.unlocked' | 'secrets.create' | 'secrets.import' | 'secrets.export' | 'secrets.view' | 'secrets.lease-denied' | 'secrets.lease-expire' | 'secrets.set' | 'secrets.delete' | 'secrets.rename' | 'cloud.dispatch' | 'cloud.complete' | 'cloud.cancel' | 'cloud.message' | 'teams.create' | 'teams.add' | 'teams.start' | 'teams.complete' | 'teams.disband' | 'hook.fire' | 'hook.complete' | 'hook.error' | 'mcp.add' | 'mcp.remove' | 'mcp.register' | 'resource.sync' | 'rotation.resolved' | 'command.start' | 'command.end' | 'perf.timing' | 'session.start' | 'session.end' | 'webhook.received' | 'webhook.authorized' | 'webhook.rejected' | 'webhook.matched' | 'webhook.fired' | 'webhook.handler.start' | 'webhook.handler.end' | 'plan.created' | 'pr.opened' | 'pr.merged' | 'worktree.created' | 'worktree.removed' | 'commit.created' | 'pushed' | 'subagent.spawned' | 'artifact.created' | 'task.completed' | 'checklist.created' | 'status.posted' | 'file.edited' | 'factory.command' | 'factory.action' | 'factory.uri' | 'factory.launch' | 'friction' | 'error' | 'warn' | 'info' | 'debug';
16
+ export type EventType = 'agent.run.start' | 'agent.run.end' | 'agent.spawn.start' | 'agent.spawn.end' | 'run.dispatched' | 'daemon.start' | 'daemon.stop' | 'daemon.error' | 'daemon.info' | 'routine.start' | 'routine.end' | 'watchdog.action' | 'version.install' | 'version.switch' | 'version.remove' | 'skill.install' | 'skill.remove' | 'browser.launch' | 'browser.close' | 'browser.navigate' | 'browser.screenshot' | 'computer.action' | 'secrets.get' | 'secrets.unlocked' | 'secrets.create' | 'secrets.import' | 'secrets.export' | 'secrets.view' | 'secrets.lease-denied' | 'secrets.lease-expire' | 'secrets.set' | 'secrets.delete' | 'secrets.rename' | 'cloud.dispatch' | 'cloud.complete' | 'cloud.cancel' | 'cloud.message' | 'teams.create' | 'teams.add' | 'teams.start' | 'teams.complete' | 'teams.disband' | 'hook.fire' | 'hook.complete' | 'hook.error' | 'mcp.add' | 'mcp.remove' | 'mcp.register' | 'resource.sync' | 'rotation.resolved' | 'command.start' | 'command.end' | 'perf.timing' | 'session.start' | 'session.end' | 'webhook.received' | 'webhook.authorized' | 'webhook.rejected' | 'webhook.matched' | 'webhook.fired' | 'webhook.failed' | 'webhook.handler.start' | 'webhook.handler.end' | 'plan.created' | 'pr.opened' | 'pr.merged' | 'worktree.created' | 'worktree.removed' | 'commit.created' | 'pushed' | 'subagent.spawned' | 'artifact.created' | 'task.completed' | 'checklist.created' | 'status.posted' | 'file.edited' | 'factory.command' | 'factory.action' | 'factory.uri' | 'factory.launch' | 'friction' | 'error' | 'warn' | 'info' | 'debug';
17
17
  /** Every known event kind. Derived from {@link EVENT_TYPE_TABLE}, never hand-listed. */
18
18
  export declare const EVENT_TYPES: readonly EventType[];
19
19
  /** Runtime guard for an event kind arriving from outside this process. */
@@ -16,14 +16,14 @@ import * as path from 'path';
16
16
  import * as os from 'os';
17
17
  import { createHash } from 'node:crypto';
18
18
  import { gzipSync, gunzipSync } from 'node:zlib';
19
- import { ensureLockTarget, withFileLock } from './fs-atomic.js';
20
- import { getUserAgentsDir } from './state.js';
21
- import { stampProvenance, resetEventProvenanceForTest } from './event-provenance.js';
19
+ import { ensureLockTarget, withFileLock } from '../fs-atomic.js';
20
+ import { getUserAgentsDir } from '../state.js';
21
+ import { stampProvenance, resetEventProvenanceForTest } from '../event-provenance.js';
22
22
  /** Lazy perf warehouse write — avoids a hard cycle at module load. */
23
23
  function recordPerfTiming(payload) {
24
24
  try {
25
25
  // Dynamic import keeps events.ts free of a load-time dependency on perf/db.
26
- void import('./perf/spool.js').then(({ recordSample }) => {
26
+ void import('../perf/spool.js').then(({ recordSample }) => {
27
27
  recordSample({
28
28
  kind: 'perf.timing',
29
29
  label: payload.label,
@@ -128,7 +128,7 @@ const EVENT_TYPE_TABLE = {
128
128
  'perf.timing': true,
129
129
  'session.start': true, 'session.end': true,
130
130
  'webhook.received': true, 'webhook.authorized': true, 'webhook.rejected': true, 'webhook.matched': true,
131
- 'webhook.fired': true, 'webhook.handler.start': true, 'webhook.handler.end': true,
131
+ 'webhook.fired': true, 'webhook.failed': true, 'webhook.handler.start': true, 'webhook.handler.end': true,
132
132
  'plan.created': true, 'pr.opened': true, 'pr.merged': true, 'worktree.created': true,
133
133
  'worktree.removed': true, 'commit.created': true, 'pushed': true, 'subagent.spawned': true,
134
134
  'artifact.created': true, 'task.completed': true, 'checklist.created': true, 'status.posted': true,
@@ -24,10 +24,10 @@
24
24
  import * as fs from 'fs';
25
25
  import * as path from 'path';
26
26
  import * as yaml from 'yaml';
27
- import { stringifyDoc } from './yaml-io.js';
28
- import { getFeedDir, getUserAgentsDir } from './state.js';
29
- import { isAdmin, isHighConsequenceAllowed, isKnownOperator } from './operator.js';
30
- import { projectKeyFromCwd } from './project-key.js';
27
+ import { stringifyDoc } from '../yaml-io.js';
28
+ import { getFeedDir, getUserAgentsDir } from '../state.js';
29
+ import { isAdmin, isHighConsequenceAllowed, isKnownOperator } from '../operator.js';
30
+ import { projectKeyFromCwd } from '../project-key.js';
31
31
  /**
32
32
  * Stable block id for a session. One block per session -- a new question
33
33
  * replaces the previous one (the agent can only ask one question at a time).
@@ -1,4 +1,4 @@
1
- import type { OpenBlock } from './feed.js';
1
+ import type { OpenBlock } from './feed/feed.js';
2
2
  export type OutcomeKind = 'ticket' | 'pr' | 'worktree' | 'unassigned';
3
3
  /** Stable attribution of a block (or agent) to one deliverable. */
4
4
  export interface OutcomeRef {
@@ -1,4 +1,4 @@
1
- import { type OpenBlock, type AnswerRecord } from './feed.js';
1
+ import { type OpenBlock, type AnswerRecord } from './feed/feed.js';
2
2
  export type BlockClass = 'approval' | 'decision';
3
3
  export interface ClassPolicy {
4
4
  timeoutMinutes: number;
@@ -16,7 +16,7 @@ import * as fs from 'fs';
16
16
  import * as path from 'path';
17
17
  import * as yaml from 'yaml';
18
18
  import { getUserAgentsDir } from './state.js';
19
- import { recordAnswer, recordDefaulted, recordMessageReceipt, recordParked, } from './feed.js';
19
+ import { recordAnswer, recordDefaulted, recordMessageReceipt, recordParked, } from './feed/feed.js';
20
20
  import { enqueue, mailboxDir } from './mailbox.js';
21
21
  const POLICY_FILE = 'feed-policy.yaml';
22
22
  const COST_RANK = { low: 0, medium: 1, high: 2 };
@@ -1,4 +1,4 @@
1
- import { type ActivityEvent, type Attachment } from './activity.js';
1
+ import { type ActivityEvent, type Attachment } from './feed/activity.js';
2
2
  import { type PidSessionEntry } from './session/pid-registry.js';
3
3
  /** Soft cap so a runaway agent can't flood the activity lane with essays. */
4
4
  export declare const STATUS_POST_MAX_CHARS = 500;
@@ -16,7 +16,7 @@
16
16
  import * as fs from 'fs';
17
17
  import * as path from 'path';
18
18
  import { spawnSync } from 'child_process';
19
- import { appendActivityEvent, readRecentActivity, } from './activity.js';
19
+ import { appendActivityEvent, readRecentActivity, } from './feed/activity.js';
20
20
  import { resolveProjectNameForCwd, listProjectDefs } from './projects.js';
21
21
  import { getHistoryDir } from './state.js';
22
22
  import { machineId } from './machine-id.js';
@@ -1,4 +1,4 @@
1
- import type { OpenBlock, FeedAskStats } from './feed.js';
1
+ import type { OpenBlock, FeedAskStats } from './feed/feed.js';
2
2
  import type { Classification } from './ask-classifier.js';
3
3
  import type { ActiveSession } from './session/active.js';
4
4
  import type { SessionMeta } from './session/types.js';
@@ -45,12 +45,6 @@ export interface SourceAuth {
45
45
  /** The captured file payloads, keyed by agent. */
46
46
  filesByAgent: Map<string, AuthFilePayload[]>;
47
47
  }
48
- /**
49
- * Can we propagate `agent`'s login to a target on `targetPlatform`? False when
50
- * the agent has no portable file, the source can't provide it (bound / not
51
- * signed in), or the target consumes credentials from its own keychain.
52
- */
53
- export declare function canPushLogin(agent: string, targetPlatform: string | undefined, src: SourceAuth): boolean;
54
48
  export interface DiffContext {
55
49
  /** agents-cli version the source is on — the fleet target version. */
56
50
  targetCliVersion: string;
@@ -13,7 +13,7 @@ import { deviceIdentityArgs, sshTargetFor } from '../devices/connect.js';
13
13
  import { readyProbe, bootstrapAgentsCli } from '../hosts/ready.js';
14
14
  import { buildRemoteAgentsInvocation } from '../hosts/remote-cmd.js';
15
15
  import { sshExec } from '../ssh-exec.js';
16
- import { isPropagatableAgent, hasPortableAuthFiles, isCredentialSafeToPropagate, KEYCHAIN_BOUND_ON_MAC, buildAuthBundle, } from './auth-sync.js';
16
+ import { hasPortableAuthFiles } from './auth-sync.js';
17
17
  /** Strip a version suffix from an agent spec: `claude@latest` -> `claude`. */
18
18
  export function agentIdOf(spec) {
19
19
  return spec.split('@')[0].trim();
@@ -88,20 +88,6 @@ export function parseInstalledVersions(stdout) {
88
88
  return undefined;
89
89
  }
90
90
  }
91
- /**
92
- * Can we propagate `agent`'s login to a target on `targetPlatform`? False when
93
- * the agent has no portable file, the source can't provide it (bound / not
94
- * signed in), or the target consumes credentials from its own keychain.
95
- */
96
- export function canPushLogin(agent, targetPlatform, src) {
97
- if (!isPropagatableAgent(agent))
98
- return false;
99
- if (src.bound.has(agent))
100
- return false;
101
- if (targetPlatform === 'macos' && KEYCHAIN_BOUND_ON_MAC.has(agent))
102
- return false;
103
- return src.available.has(agent);
104
- }
105
91
  /** Pure: desired vs probed -> per-device diff + flat action list. */
106
92
  export function diffFleet(desired, probes, ctx) {
107
93
  const devices = [];
@@ -143,28 +129,24 @@ export function diffFleet(desired, probes, ctx) {
143
129
  rowActions.push({ device: d.device, kind: 'sync-config', detail: `sync config (${d.sync.join(', ')})` });
144
130
  }
145
131
  // login — per agent id, not per spec: `claude@all` names one id many times,
146
- // but login propagates once per agent (its credential is version-shared).
132
+ // but a login is established once per agent (its credential is version-shared).
147
133
  if (d.login === 'sync') {
148
134
  for (const id of [...new Set(d.agents.map(agentIdOf))]) {
149
- if (canPushLogin(id, probe.platform, ctx.sourceAuth)) {
150
- rowActions.push({ device: d.device, kind: 'push-login', agent: id, detail: `propagate ${id} login` });
151
- }
152
- else if (hasPortableAuthFiles(id) && !isCredentialSafeToPropagate(id)) {
153
- // Single-use rotating refresh tokens (e.g. droid/WorkOS) must never be
154
- // copied across boxes the first refresh invalidates every other copy.
155
- // Surface per-machine login guidance instead of silently propagating.
156
- loginBlocked.push(id);
157
- rowActions.push({ device: d.device, kind: 'needs-login', agent: id, detail: `${id} login uses a single-use rotating refresh token — log in on ${d.device} itself` });
158
- }
159
- else if (isPropagatableAgent(id) &&
160
- (ctx.sourceAuth.bound.has(id) || (probe.platform === 'macos' && KEYCHAIN_BOUND_ON_MAC.has(id)))) {
161
- // A login-propagation candidate we still can't push: the source token
162
- // is keychain-bound (unextractable), or the macOS target consumes its
163
- // own keychain. Surface those as manual — don't fake. Agents that were
164
- // never propagation candidates (no portable file), or a source that
165
- // simply isn't signed in, are silently skipped the same on every OS.
135
+ // SING-1b: a native OAuth / session login MUST NOT be copied between
136
+ // devices a rotating token invalidates the fleet on its next refresh
137
+ // (droid/WorkOS collapsed 10 boxes to 1 overnight). `apply` therefore no
138
+ // longer propagates any login; it surfaces per-box login / portable
139
+ // provider-account guidance for every agent that has a login to
140
+ // establish. An agent with no portable login file, or a source that
141
+ // isn't signed in, is silently skipped the same on every OS.
142
+ if (hasPortableAuthFiles(id)) {
166
143
  loginBlocked.push(id);
167
- rowActions.push({ device: d.device, kind: 'needs-login', agent: id, detail: `${id} needs a manual login` });
144
+ rowActions.push({
145
+ device: d.device,
146
+ kind: 'needs-login',
147
+ agent: id,
148
+ detail: `${id}: a native OAuth login can't be copied between devices (SING-1b) — log in on ${d.device} itself, or sync a portable provider account (agents accounts sync)`,
149
+ });
168
150
  }
169
151
  }
170
152
  }
@@ -414,17 +396,8 @@ export function reconcileDevice(row, device, ctx) {
414
396
  steps.push({ kind: 'sync-config', ok: syncOk, detail: `sync config (${row.desired.sync.join(', ') || 'default'})` });
415
397
  ok = ok && syncOk;
416
398
  }
417
- // 4. login propagation one bundle for all pushable agents on this device.
418
- const pushAgents = [...new Set(row.actions.filter((a) => a.kind === 'push-login').map((a) => a.agent))];
419
- if (pushAgents.length > 0) {
420
- const files = [];
421
- for (const agent of pushAgents)
422
- files.push(...(ctx.sourceAuth.filesByAgent.get(agent) ?? []));
423
- const bundle = buildAuthBundle(ctx.source, files);
424
- const r = sshAgents(['apply', '--recv-auth'], JSON.stringify(bundle));
425
- steps.push({ kind: 'push-login', ok: r.code === 0, detail: `propagate login: ${pushAgents.join(', ')}` });
426
- ok = ok && r.code === 0;
427
- }
399
+ // 4. Native login materialization does not exist. Every agent that needs a login is surfaced as
400
+ // `needs-login` (per-box login / portable-account guidance) in the diff above.
428
401
  // 5. secrets provisioning — LAST, and deliberately so. It is the most
429
402
  // sensitive mutation apply performs (credential VALUES crossing to another
430
403
  // machine), so every lower-risk step above is already recorded before we
@@ -1,19 +1,13 @@
1
1
  /**
2
- * Login/token propagation the "one login instead of ~48 OAuth flows" core of
3
- * `agents apply`.
4
- *
5
- * A source machine that is already signed in to a set of harnesses has portable
6
- * credential files on disk (verified per-agent locations below). `snapshotAuth`
7
- * captures those; `materializeAuth` writes them into the corresponding paths on
8
- * a target device. Transport is the caller's job — `apply` streams the bundle
9
- * over the existing (encrypted, authenticated) SSH channel via `sshExec`'s
10
- * stdin `input`, so no app-layer crypto is layered on top of SSH here.
2
+ * Native-login inventory for `agents apply` and `agents fleet login`.
3
+ * Native OAuth/session files are identified only to report device readiness;
4
+ * agents-cli never serializes or materializes them on another device.
11
5
  *
12
6
  * Honest boundary: on macOS, claude and antigravity keep their tokens in the
13
7
  * login keychain, ACL-bound to the harness process — unreadable by us. Those are
14
8
  * classified `bound` and surfaced for a one-time manual login, never faked.
15
9
  */
16
- import type { AuthFilePayload, AuthBundle, AuthSnapshotResult } from './types.js';
10
+ import type { AuthSnapshotResult } from './types.js';
17
11
  /** A portable credential file location, relative to $HOME. */
18
12
  interface AuthFileSpec {
19
13
  rel: string;
@@ -37,10 +31,18 @@ export declare const KEYCHAIN_BOUND_ON_MAC: ReadonlySet<string>;
37
31
  * made. See also `remote-login.ts` and `usage.ts` for the per-machine-login policy.
38
32
  */
39
33
  export declare const SINGLE_USE_ROTATING_REFRESH_AGENTS: ReadonlySet<string>;
40
- /** True when `agent`'s portable credential file(s) are safe to copy between
41
- * machines. Single-use rotating refresh tokens are never safe; keychain-bound
42
- * tokens are handled separately by the caller via {@link KEYCHAIN_BOUND_ON_MAC}. */
43
- export declare function isCredentialSafeToPropagate(agent: string): boolean;
34
+ /**
35
+ * Whether `agent`'s login may be copied between machines by `apply`. Always
36
+ * **false** now (RUSH-2527): every `FLEET_AUTH_FILES` entry is a native,
37
+ * rotating OAuth / session login, and the fleet-auth contract forbids copying any
38
+ * of them between devices (`docs/specifications.md` SING-1b) — not just the
39
+ * single-use-rotating subset (`SINGLE_USE_ROTATING_REFRESH_AGENTS`) that first
40
+ * motivated this gate. `apply` therefore never propagates a login; it surfaces
41
+ * per-box login / portable-account guidance instead. `snapshotAuth` reads no
42
+ * credential file as a result, so a native login never leaves its origin box.
43
+ * The `agent` parameter is retained for the stable call signature.
44
+ */
45
+ export declare function isCredentialSafeToPropagate(_agent: string): boolean;
44
46
  /** True when the agent stores credentials in portable files we can read. This
45
47
  * does NOT mean it is safe to propagate — check {@link isCredentialSafeToPropagate}. */
46
48
  export declare function hasPortableAuthFiles(agent: string): boolean;
@@ -113,25 +115,4 @@ export interface SnapshotOptions {
113
115
  * propagate, not an error.
114
116
  */
115
117
  export declare function snapshotAuth(agents: string[], opts: SnapshotOptions): AuthSnapshotResult;
116
- /** Assemble the plaintext bundle shipped to a target. */
117
- export declare function buildAuthBundle(source: string, files: AuthFilePayload[]): AuthBundle;
118
- export interface MaterializeOptions {
119
- /** Home directory to write credential files into. */
120
- home: string;
121
- }
122
- export interface MaterializeResult {
123
- /** Agent ids that received at least one file. */
124
- written: string[];
125
- /** `rel: reason` for any file that failed. */
126
- errors: string[];
127
- }
128
- /**
129
- * Write a captured auth bundle into a target home. Parent dirs are created; the
130
- * captured POSIX mode is restored (0600 for credentials). Writing through an
131
- * existing symlink lands in the agent's active version home, which is exactly
132
- * what per-version credential carry-forward expects.
133
- */
134
- export declare function materializeAuth(bundle: AuthBundle, opts: MaterializeOptions): MaterializeResult;
135
- /** Parse + validate a bundle received on stdin (the remote `--_recv-auth` path). */
136
- export declare function parseAuthBundle(raw: string): AuthBundle;
137
118
  export {};
@@ -1,13 +1,7 @@
1
1
  /**
2
- * Login/token propagation the "one login instead of ~48 OAuth flows" core of
3
- * `agents apply`.
4
- *
5
- * A source machine that is already signed in to a set of harnesses has portable
6
- * credential files on disk (verified per-agent locations below). `snapshotAuth`
7
- * captures those; `materializeAuth` writes them into the corresponding paths on
8
- * a target device. Transport is the caller's job — `apply` streams the bundle
9
- * over the existing (encrypted, authenticated) SSH channel via `sshExec`'s
10
- * stdin `input`, so no app-layer crypto is layered on top of SSH here.
2
+ * Native-login inventory for `agents apply` and `agents fleet login`.
3
+ * Native OAuth/session files are identified only to report device readiness;
4
+ * agents-cli never serializes or materializes them on another device.
11
5
  *
12
6
  * Honest boundary: on macOS, claude and antigravity keep their tokens in the
13
7
  * login keychain, ACL-bound to the harness process — unreadable by us. Those are
@@ -44,11 +38,19 @@ export const KEYCHAIN_BOUND_ON_MAC = new Set(['claude', 'antigravity']);
44
38
  * made. See also `remote-login.ts` and `usage.ts` for the per-machine-login policy.
45
39
  */
46
40
  export const SINGLE_USE_ROTATING_REFRESH_AGENTS = new Set(['droid']);
47
- /** True when `agent`'s portable credential file(s) are safe to copy between
48
- * machines. Single-use rotating refresh tokens are never safe; keychain-bound
49
- * tokens are handled separately by the caller via {@link KEYCHAIN_BOUND_ON_MAC}. */
50
- export function isCredentialSafeToPropagate(agent) {
51
- return !SINGLE_USE_ROTATING_REFRESH_AGENTS.has(agent);
41
+ /**
42
+ * Whether `agent`'s login may be copied between machines by `apply`. Always
43
+ * **false** now (RUSH-2527): every `FLEET_AUTH_FILES` entry is a native,
44
+ * rotating OAuth / session login, and the fleet-auth contract forbids copying any
45
+ * of them between devices (`docs/specifications.md` SING-1b) — not just the
46
+ * single-use-rotating subset (`SINGLE_USE_ROTATING_REFRESH_AGENTS`) that first
47
+ * motivated this gate. `apply` therefore never propagates a login; it surfaces
48
+ * per-box login / portable-account guidance instead. `snapshotAuth` reads no
49
+ * credential file as a result, so a native login never leaves its origin box.
50
+ * The `agent` parameter is retained for the stable call signature.
51
+ */
52
+ export function isCredentialSafeToPropagate(_agent) {
53
+ return false;
52
54
  }
53
55
  /** True when the agent stores credentials in portable files we can read. This
54
56
  * does NOT mean it is safe to propagate — check {@link isCredentialSafeToPropagate}. */
@@ -185,64 +187,3 @@ export function snapshotAuth(agents, opts) {
185
187
  }
186
188
  return { files, bound };
187
189
  }
188
- /** Assemble the plaintext bundle shipped to a target. */
189
- export function buildAuthBundle(source, files) {
190
- return { v: 1, source, files };
191
- }
192
- /**
193
- * Write a captured auth bundle into a target home. Parent dirs are created; the
194
- * captured POSIX mode is restored (0600 for credentials). Writing through an
195
- * existing symlink lands in the agent's active version home, which is exactly
196
- * what per-version credential carry-forward expects.
197
- */
198
- export function materializeAuth(bundle, opts) {
199
- const written = new Set();
200
- const errors = [];
201
- for (const f of bundle.files) {
202
- const abs = path.join(opts.home, f.rel);
203
- try {
204
- fs.mkdirSync(path.dirname(abs), { recursive: true });
205
- fs.writeFileSync(abs, Buffer.from(f.contentB64, 'base64'));
206
- fs.chmodSync(abs, f.mode || 0o600);
207
- written.add(f.agent);
208
- }
209
- catch (e) {
210
- errors.push(`${f.rel}: ${e.message}`);
211
- }
212
- }
213
- return { written: [...written], errors };
214
- }
215
- /** Parse + validate a bundle received on stdin (the remote `--_recv-auth` path). */
216
- export function parseAuthBundle(raw) {
217
- let doc;
218
- try {
219
- doc = JSON.parse(raw);
220
- }
221
- catch (e) {
222
- throw new Error(`auth bundle is not valid JSON: ${e.message}`);
223
- }
224
- if (typeof doc !== 'object' || doc === null)
225
- throw new Error('auth bundle must be an object.');
226
- const o = doc;
227
- if (o.v !== 1)
228
- throw new Error(`unsupported auth bundle version ${JSON.stringify(o.v)}.`);
229
- if (typeof o.source !== 'string')
230
- throw new Error('auth bundle missing source.');
231
- if (!Array.isArray(o.files))
232
- throw new Error('auth bundle missing files[].');
233
- for (const f of o.files) {
234
- if (typeof f !== 'object' || f === null ||
235
- typeof f.agent !== 'string' ||
236
- typeof f.rel !== 'string' ||
237
- typeof f.contentB64 !== 'string' ||
238
- typeof f.mode !== 'number') {
239
- throw new Error('auth bundle has a malformed file entry.');
240
- }
241
- // Reject path traversal — rel must stay under $HOME.
242
- const rel = f.rel;
243
- if (rel.startsWith('/') || rel.split('/').includes('..')) {
244
- throw new Error(`auth bundle rejected unsafe path: ${rel}`);
245
- }
246
- }
247
- return doc;
248
- }
@@ -28,12 +28,11 @@ export function captureFleet(prev, inputs) {
28
28
  // when the manifest didn't already pin one for that device.
29
29
  //
30
30
  // A device absent from `inputs.devices` drops OUT of the roster — that is the
31
- // intended "live state is the source of truth for WHICH devices exist". But
32
- // `fleet.devices.<name>.config` is also the operator-config store, and a
33
- // capture run from a box whose registry has not seen a peer would silently
34
- // erase that peer's settings. Observed for real: capturing on yosemite-s0
35
- // deleted zion's whole config block from the shared agents.yaml. So carry a
36
- // dropped device's `config:` forward — config only, never its roster fields.
31
+ // intended "live state is the source of truth for WHICH devices exist". A
32
+ // leftover `config:` on an override is the LEGACY #2458 store (folded into
33
+ // per-device docs by migrateDeviceConfigStores). Carry it forward so a
34
+ // capture from a box that has not seen a peer cannot re-strip a not-yet-
35
+ // migrated peer's settings. Config only, never its roster fields.
37
36
  const devices = {};
38
37
  for (const [name, prevOverride] of Object.entries(prevDevices)) {
39
38
  if (inputs.devices.includes(name))
@@ -56,6 +55,9 @@ export function captureFleet(prev, inputs) {
56
55
  defaults: prev?.defaults ?? inputs.defaults ?? {},
57
56
  devices,
58
57
  };
58
+ if (prev?.discovery && Object.keys(prev.discovery).length > 0) {
59
+ manifest.discovery = { ...prev.discovery };
60
+ }
59
61
  const bundles = inputs.secretsBundles ?? prev?.secrets?.bundles;
60
62
  if (bundles && bundles.length > 0)
61
63
  manifest.secrets = { bundles: [...bundles].sort() };