@phnx-labs/agents-cli 1.22.35 → 1.22.37

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 (487) hide show
  1. package/CHANGELOG.md +666 -2
  2. package/README.md +75 -35
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1211 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/attach.js +17 -4
  9. package/dist/commands/audit.d.ts +8 -8
  10. package/dist/commands/audit.js +57 -47
  11. package/dist/commands/browser.js +15 -11
  12. package/dist/commands/cloud.js +1 -1
  13. package/dist/commands/commands.js +0 -11
  14. package/dist/commands/computer-actions.js +33 -0
  15. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  16. package/dist/commands/computer-sessions-picker.js +141 -0
  17. package/dist/commands/computer.d.ts +16 -0
  18. package/dist/commands/computer.js +37 -0
  19. package/dist/commands/config.d.ts +17 -0
  20. package/dist/commands/config.js +401 -0
  21. package/dist/commands/cp.d.ts +84 -0
  22. package/dist/commands/cp.js +231 -0
  23. package/dist/commands/daemon.js +243 -14
  24. package/dist/commands/detach-core.d.ts +1 -1
  25. package/dist/commands/detach-core.js +12 -2
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +64 -5
  28. package/dist/commands/events.d.ts +24 -12
  29. package/dist/commands/events.js +144 -28
  30. package/dist/commands/exec.js +85 -41
  31. package/dist/commands/feed.d.ts +1 -1
  32. package/dist/commands/feed.js +16 -8
  33. package/dist/commands/focus.d.ts +33 -1
  34. package/dist/commands/focus.js +177 -17
  35. package/dist/commands/funnel.d.ts +1 -1
  36. package/dist/commands/go.js +9 -8
  37. package/dist/commands/harness-wizard.d.ts +1 -0
  38. package/dist/commands/harness-wizard.js +18 -20
  39. package/dist/commands/harness.d.ts +2 -0
  40. package/dist/commands/harness.js +59 -26
  41. package/dist/commands/hooks.js +0 -11
  42. package/dist/commands/inspect.d.ts +94 -1
  43. package/dist/commands/inspect.js +866 -40
  44. package/dist/commands/lease.d.ts +4 -4
  45. package/dist/commands/lease.js +6 -6
  46. package/dist/commands/login.js +0 -13
  47. package/dist/commands/logs.d.ts +2 -2
  48. package/dist/commands/logs.js +2 -2
  49. package/dist/commands/mcp.js +7 -2
  50. package/dist/commands/memory.js +7 -2
  51. package/dist/commands/message.d.ts +1 -1
  52. package/dist/commands/message.js +37 -6
  53. package/dist/commands/models.js +4 -0
  54. package/dist/commands/monitors.d.ts +0 -1
  55. package/dist/commands/monitors.js +199 -16
  56. package/dist/commands/open.d.ts +18 -0
  57. package/dist/commands/open.js +57 -0
  58. package/dist/commands/packages.js +2 -107
  59. package/dist/commands/plugins.js +6 -3
  60. package/dist/commands/profiles.d.ts +1 -0
  61. package/dist/commands/profiles.js +16 -160
  62. package/dist/commands/projects.d.ts +28 -0
  63. package/dist/commands/projects.js +125 -5
  64. package/dist/commands/reconnect.js +9 -3
  65. package/dist/commands/repo.js +42 -1
  66. package/dist/commands/resource-view.d.ts +17 -0
  67. package/dist/commands/resource-view.js +36 -14
  68. package/dist/commands/resume.js +9 -2
  69. package/dist/commands/routines.d.ts +0 -2
  70. package/dist/commands/routines.js +473 -289
  71. package/dist/commands/secrets.js +52 -9
  72. package/dist/commands/sessions-export.d.ts +47 -0
  73. package/dist/commands/sessions-export.js +116 -6
  74. package/dist/commands/sessions-import.d.ts +17 -0
  75. package/dist/commands/sessions-import.js +114 -6
  76. package/dist/commands/sessions-migrate.d.ts +27 -0
  77. package/dist/commands/sessions-migrate.js +50 -9
  78. package/dist/commands/sessions-picker.js +23 -4
  79. package/dist/commands/sessions-resume.d.ts +5 -3
  80. package/dist/commands/sessions-resume.js +30 -8
  81. package/dist/commands/sessions-watch.d.ts +2 -0
  82. package/dist/commands/sessions-watch.js +53 -0
  83. package/dist/commands/sessions.d.ts +66 -3
  84. package/dist/commands/sessions.js +298 -47
  85. package/dist/commands/set.d.ts +1 -1
  86. package/dist/commands/set.js +2 -2
  87. package/dist/commands/setup-browser.js +2 -2
  88. package/dist/commands/setup-mine.js +0 -1
  89. package/dist/commands/setup-preferences.js +1 -1
  90. package/dist/commands/setup-share.js +34 -4
  91. package/dist/commands/setup.d.ts +5 -0
  92. package/dist/commands/setup.js +26 -0
  93. package/dist/commands/share.d.ts +67 -0
  94. package/dist/commands/share.js +275 -12
  95. package/dist/commands/skills.js +0 -11
  96. package/dist/commands/snapshot.js +1 -1
  97. package/dist/commands/ssh.d.ts +18 -0
  98. package/dist/commands/ssh.js +549 -210
  99. package/dist/commands/sync.d.ts +5 -0
  100. package/dist/commands/sync.js +212 -32
  101. package/dist/commands/teams.d.ts +13 -0
  102. package/dist/commands/teams.js +187 -30
  103. package/dist/commands/tickets.d.ts +2 -0
  104. package/dist/commands/tickets.js +43 -0
  105. package/dist/commands/update.js +2 -4
  106. package/dist/commands/usage.js +5 -3
  107. package/dist/commands/versions.js +11 -5
  108. package/dist/commands/view.js +15 -7
  109. package/dist/commands/webhook.d.ts +2 -2
  110. package/dist/commands/webhook.js +7 -7
  111. package/dist/index.d.ts +18 -2
  112. package/dist/index.js +53 -1264
  113. package/dist/lib/account-catalog.d.ts +18 -0
  114. package/dist/lib/account-catalog.js +38 -0
  115. package/dist/lib/account-provider-registry.d.ts +18 -0
  116. package/dist/lib/account-provider-registry.js +59 -0
  117. package/dist/lib/account-registry.d.ts +40 -0
  118. package/dist/lib/account-registry.js +239 -0
  119. package/dist/lib/account-schema.d.ts +44 -0
  120. package/dist/lib/account-schema.js +91 -0
  121. package/dist/lib/account-state-service.d.ts +21 -0
  122. package/dist/lib/account-state-service.js +60 -0
  123. package/dist/lib/activity.d.ts +1 -1
  124. package/dist/lib/activity.js +8 -1
  125. package/dist/lib/add-dir.d.ts +80 -0
  126. package/dist/lib/add-dir.js +241 -0
  127. package/dist/lib/agent-cli-commands.d.ts +11 -0
  128. package/dist/lib/agent-cli-commands.js +30 -0
  129. package/dist/lib/agents.js +44 -36
  130. package/dist/lib/answer-router.js +1 -1
  131. package/dist/lib/audit/log.d.ts +10 -27
  132. package/dist/lib/audit/log.js +20 -33
  133. package/dist/lib/auth-health.d.ts +9 -2
  134. package/dist/lib/auth-health.js +42 -9
  135. package/dist/lib/auto-pull-worker.js +7 -3
  136. package/dist/lib/auto-pull.d.ts +44 -3
  137. package/dist/lib/auto-pull.js +88 -5
  138. package/dist/lib/binary-shadow.d.ts +28 -0
  139. package/dist/lib/binary-shadow.js +121 -0
  140. package/dist/lib/brand.js +9 -3
  141. package/dist/lib/browser/ipc.d.ts +30 -0
  142. package/dist/lib/browser/ipc.js +81 -4
  143. package/dist/lib/browser/profiles.d.ts +3 -2
  144. package/dist/lib/browser/profiles.js +65 -22
  145. package/dist/lib/browser/service.d.ts +4 -0
  146. package/dist/lib/browser/service.js +30 -3
  147. package/dist/lib/browser/sessions-list.d.ts +22 -2
  148. package/dist/lib/browser/sessions-list.js +54 -6
  149. package/dist/lib/browser/stream.d.ts +2 -0
  150. package/dist/lib/browser/stream.js +1 -0
  151. package/dist/lib/browser/types.d.ts +19 -0
  152. package/dist/lib/byok-usage.d.ts +9 -2
  153. package/dist/lib/byok-usage.js +133 -31
  154. package/dist/lib/cli-entry.d.ts +11 -0
  155. package/dist/lib/cli-entry.js +46 -0
  156. package/dist/lib/cloud/host.d.ts +1 -1
  157. package/dist/lib/cloud/host.js +2 -2
  158. package/dist/lib/cloud/registry.js +1 -1
  159. package/dist/lib/cloud/types.d.ts +1 -1
  160. package/dist/lib/commands.d.ts +2 -0
  161. package/dist/lib/commands.js +2 -0
  162. package/dist/lib/computer/sessions-list.d.ts +150 -0
  163. package/dist/lib/computer/sessions-list.js +363 -0
  164. package/dist/lib/config-keys.d.ts +86 -0
  165. package/dist/lib/config-keys.js +193 -0
  166. package/dist/lib/config-machine-keys.d.ts +12 -0
  167. package/dist/lib/config-machine-keys.js +17 -0
  168. package/dist/lib/config-transfer.js +3 -4
  169. package/dist/lib/crabbox/cli.d.ts +2 -2
  170. package/dist/lib/crabbox/cli.js +3 -3
  171. package/dist/lib/daemon-health.d.ts +22 -0
  172. package/dist/lib/daemon-health.js +33 -3
  173. package/dist/lib/daemon-services.d.ts +50 -0
  174. package/dist/lib/daemon-services.js +147 -0
  175. package/dist/lib/daemon-ticks.d.ts +35 -66
  176. package/dist/lib/daemon-ticks.js +77 -159
  177. package/dist/lib/daemon.d.ts +72 -4
  178. package/dist/lib/daemon.js +792 -202
  179. package/dist/lib/deeplink/register.d.ts +49 -0
  180. package/dist/lib/deeplink/register.js +253 -0
  181. package/dist/lib/deeplink/url.d.ts +34 -0
  182. package/dist/lib/deeplink/url.js +78 -0
  183. package/dist/lib/device-config.d.ts +124 -29
  184. package/dist/lib/device-config.js +346 -141
  185. package/dist/lib/devices/config-migration.d.ts +42 -0
  186. package/dist/lib/devices/config-migration.js +203 -0
  187. package/dist/lib/devices/connect.js +14 -7
  188. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  189. package/dist/lib/devices/doctor-findings.js +20 -1
  190. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  191. package/dist/lib/devices/harness-inventory.js +0 -0
  192. package/dist/lib/devices/health.d.ts +1 -1
  193. package/dist/lib/devices/health.js +1 -1
  194. package/dist/lib/devices/pending.d.ts +22 -1
  195. package/dist/lib/devices/pending.js +67 -2
  196. package/dist/lib/devices/registry.d.ts +0 -25
  197. package/dist/lib/devices/registry.js +2 -83
  198. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  199. package/dist/lib/devices/resolve-profile.js +44 -0
  200. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  201. package/dist/lib/devices/rollout-verify.js +193 -0
  202. package/dist/lib/devices/ssh-config.js +10 -6
  203. package/dist/lib/event-families.d.ts +28 -0
  204. package/dist/lib/event-families.js +159 -0
  205. package/dist/lib/event-stream.d.ts +9 -1
  206. package/dist/lib/event-stream.js +26 -9
  207. package/dist/lib/events.d.ts +9 -1
  208. package/dist/lib/events.js +21 -6
  209. package/dist/lib/exec.d.ts +30 -0
  210. package/dist/lib/exec.js +219 -121
  211. package/dist/lib/feed-broadcast.d.ts +25 -0
  212. package/dist/lib/feed-broadcast.js +33 -0
  213. package/dist/lib/feed.d.ts +1 -1
  214. package/dist/lib/feed.js +12 -2
  215. package/dist/lib/fleet/capture.js +15 -0
  216. package/dist/lib/fleet/manifest.js +9 -0
  217. package/dist/lib/fleet/types.d.ts +9 -0
  218. package/dist/lib/fleet-status.js +10 -8
  219. package/dist/lib/git.d.ts +20 -6
  220. package/dist/lib/git.js +121 -17
  221. package/dist/lib/hosts/dispatch.d.ts +8 -3
  222. package/dist/lib/hosts/dispatch.js +29 -3
  223. package/dist/lib/hosts/logs.d.ts +2 -2
  224. package/dist/lib/hosts/logs.js +2 -2
  225. package/dist/lib/hosts/option.js +1 -1
  226. package/dist/lib/hosts/passthrough.d.ts +2 -3
  227. package/dist/lib/hosts/passthrough.js +10 -24
  228. package/dist/lib/hosts/progress.js +2 -2
  229. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  230. package/dist/lib/hosts/providers/devices.js +18 -12
  231. package/dist/lib/hosts/ready.d.ts +5 -1
  232. package/dist/lib/hosts/ready.js +9 -3
  233. package/dist/lib/hosts/reconcile.d.ts +2 -2
  234. package/dist/lib/hosts/reconcile.js +2 -2
  235. package/dist/lib/hosts/registry.js +14 -9
  236. package/dist/lib/hosts/remote-cmd.js +1 -1
  237. package/dist/lib/hosts/remote-os.d.ts +9 -6
  238. package/dist/lib/hosts/remote-os.js +13 -6
  239. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  240. package/dist/lib/hosts/routing-flag.js +41 -0
  241. package/dist/lib/hosts/run-target.js +1 -1
  242. package/dist/lib/hosts/session-index.js +1 -1
  243. package/dist/lib/hosts/tasks.d.ts +6 -6
  244. package/dist/lib/hosts/tasks.js +4 -4
  245. package/dist/lib/hosts/types.js +1 -2
  246. package/dist/lib/installations/resolve.js +2 -8
  247. package/dist/lib/isolation-boundary-report.js +0 -1
  248. package/dist/lib/linear-cache.d.ts +7 -0
  249. package/dist/lib/linear-cache.js +31 -4
  250. package/dist/lib/linear-project-counts.d.ts +1 -1
  251. package/dist/lib/linear-project-counts.js +2 -3
  252. package/dist/lib/linear-projects.js +1 -1
  253. package/dist/lib/loop.d.ts +2 -2
  254. package/dist/lib/loop.js +1 -1
  255. package/dist/lib/mailbox-target.d.ts +1 -1
  256. package/dist/lib/mailbox-target.js +1 -1
  257. package/dist/lib/manifest.js +7 -4
  258. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  259. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  260. package/dist/lib/menubar/snapshot.d.ts +3 -2
  261. package/dist/lib/menubar/snapshot.js +6 -2
  262. package/dist/lib/migrate-fold.d.ts +33 -0
  263. package/dist/lib/migrate-fold.js +130 -0
  264. package/dist/lib/migrate.d.ts +34 -34
  265. package/dist/lib/migrate.js +106 -128
  266. package/dist/lib/model-tier-overrides.d.ts +1 -1
  267. package/dist/lib/model-tier-overrides.js +15 -2
  268. package/dist/lib/monitors/config.d.ts +17 -3
  269. package/dist/lib/monitors/config.js +52 -18
  270. package/dist/lib/monitors/engine.d.ts +32 -1
  271. package/dist/lib/monitors/engine.js +94 -11
  272. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  273. package/dist/lib/monitors/fingerprint.js +100 -0
  274. package/dist/lib/monitors/remote.d.ts +47 -0
  275. package/dist/lib/monitors/remote.js +81 -0
  276. package/dist/lib/monitors/state.d.ts +39 -0
  277. package/dist/lib/monitors/state.js +56 -0
  278. package/dist/lib/onepassword.d.ts +17 -0
  279. package/dist/lib/onepassword.js +52 -22
  280. package/dist/lib/open-url.js +1 -1
  281. package/dist/lib/picker.d.ts +14 -2
  282. package/dist/lib/picker.js +35 -13
  283. package/dist/lib/placement.d.ts +1 -1
  284. package/dist/lib/placement.js +1 -1
  285. package/dist/lib/pr-land-detach.d.ts +32 -0
  286. package/dist/lib/pr-land-detach.js +79 -0
  287. package/dist/lib/profiles-presets.js +13 -0
  288. package/dist/lib/profiles.d.ts +2 -0
  289. package/dist/lib/profiles.js +44 -1
  290. package/dist/lib/project-focus.d.ts +1 -1
  291. package/dist/lib/project-focus.js +1 -1
  292. package/dist/lib/project-probe.d.ts +4 -1
  293. package/dist/lib/project-probe.js +5 -4
  294. package/dist/lib/project-resources.js +2 -18
  295. package/dist/lib/project-root.d.ts +16 -0
  296. package/dist/lib/project-root.js +20 -2
  297. package/dist/lib/projects.d.ts +20 -1
  298. package/dist/lib/projects.js +78 -1
  299. package/dist/lib/refresh-coordinator.d.ts +24 -0
  300. package/dist/lib/refresh-coordinator.js +52 -0
  301. package/dist/lib/registry.d.ts +2 -2
  302. package/dist/lib/registry.js +1 -1
  303. package/dist/lib/resource-aliases.d.ts +13 -0
  304. package/dist/lib/resource-aliases.js +26 -0
  305. package/dist/lib/resources/types.d.ts +1 -1
  306. package/dist/lib/resources.d.ts +16 -0
  307. package/dist/lib/resources.js +66 -10
  308. package/dist/lib/rotate.d.ts +3 -4
  309. package/dist/lib/rotate.js +4 -5
  310. package/dist/lib/routine-activation.d.ts +22 -2
  311. package/dist/lib/routine-activation.js +63 -16
  312. package/dist/lib/routine-context.d.ts +9 -2
  313. package/dist/lib/routine-context.js +21 -6
  314. package/dist/lib/routines-project.d.ts +58 -48
  315. package/dist/lib/routines-project.js +190 -159
  316. package/dist/lib/routines.d.ts +41 -6
  317. package/dist/lib/routines.js +92 -34
  318. package/dist/lib/run-defaults.d.ts +5 -0
  319. package/dist/lib/run-defaults.js +11 -1
  320. package/dist/lib/runner.d.ts +10 -8
  321. package/dist/lib/runner.js +122 -39
  322. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  323. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  324. package/dist/lib/secrets/agent.d.ts +10 -3
  325. package/dist/lib/secrets/agent.js +43 -8
  326. package/dist/lib/secrets/bundles.d.ts +1 -0
  327. package/dist/lib/secrets/bundles.js +92 -80
  328. package/dist/lib/secrets/index.js +32 -9
  329. package/dist/lib/secrets/install-helper.d.ts +4 -4
  330. package/dist/lib/secrets/install-helper.js +4 -4
  331. package/dist/lib/secrets/push.d.ts +40 -6
  332. package/dist/lib/secrets/push.js +58 -11
  333. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  334. package/dist/lib/secrets/read-backoff.js +1 -1
  335. package/dist/lib/secrets/remote.d.ts +24 -0
  336. package/dist/lib/secrets/remote.js +54 -4
  337. package/dist/lib/self-update.d.ts +108 -0
  338. package/dist/lib/self-update.js +276 -1
  339. package/dist/lib/session/active.d.ts +89 -5
  340. package/dist/lib/session/active.js +165 -10
  341. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  342. package/dist/lib/session/actor-sidecar.js +2 -1
  343. package/dist/lib/session/db.d.ts +176 -2
  344. package/dist/lib/session/db.js +484 -17
  345. package/dist/lib/session/discover.js +27 -4
  346. package/dist/lib/session/hook-sessions.js +2 -2
  347. package/dist/lib/session/host-link.d.ts +2 -2
  348. package/dist/lib/session/host-link.js +2 -2
  349. package/dist/lib/session/pid-registry.d.ts +21 -0
  350. package/dist/lib/session/pid-registry.js +57 -0
  351. package/dist/lib/session/remote-active.js +15 -1
  352. package/dist/lib/session/remote.js +2 -2
  353. package/dist/lib/session/session-cache.d.ts +14 -7
  354. package/dist/lib/session/session-cache.js +51 -9
  355. package/dist/lib/session/state.d.ts +2 -2
  356. package/dist/lib/session/state.js +1 -1
  357. package/dist/lib/session/sync/config.d.ts +10 -10
  358. package/dist/lib/session/sync/config.js +10 -10
  359. package/dist/lib/session/sync/r2.d.ts +34 -0
  360. package/dist/lib/session/sync/r2.js +123 -0
  361. package/dist/lib/session/throughput.d.ts +1 -1
  362. package/dist/lib/session/throughput.js +1 -1
  363. package/dist/lib/session/types.d.ts +23 -1
  364. package/dist/lib/session/types.js +15 -0
  365. package/dist/lib/session/viewing-in.d.ts +1 -1
  366. package/dist/lib/session/viewing-in.js +1 -1
  367. package/dist/lib/session/watch.d.ts +101 -0
  368. package/dist/lib/session/watch.js +242 -0
  369. package/dist/lib/share/config.d.ts +4 -0
  370. package/dist/lib/share/config.js +1 -0
  371. package/dist/lib/share/provision.d.ts +38 -0
  372. package/dist/lib/share/provision.js +50 -0
  373. package/dist/lib/share/publish.d.ts +40 -1
  374. package/dist/lib/share/publish.js +116 -3
  375. package/dist/lib/share/worker-template.js +71 -6
  376. package/dist/lib/shims.d.ts +17 -3
  377. package/dist/lib/shims.js +98 -26
  378. package/dist/lib/signin-badge.js +3 -2
  379. package/dist/lib/skills.js +2 -0
  380. package/dist/lib/smart-launch.d.ts +8 -8
  381. package/dist/lib/smart-launch.js +80 -59
  382. package/dist/lib/ssh-exec.d.ts +1 -1
  383. package/dist/lib/ssh-exec.js +1 -1
  384. package/dist/lib/staleness/prune.d.ts +88 -0
  385. package/dist/lib/staleness/prune.js +69 -0
  386. package/dist/lib/staleness/registry.d.ts +1 -1
  387. package/dist/lib/staleness/writers/commands.js +34 -2
  388. package/dist/lib/staleness/writers/hooks.js +16 -0
  389. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  390. package/dist/lib/staleness/writers/skills.js +19 -0
  391. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  392. package/dist/lib/staleness/writers/subagents.js +0 -4
  393. package/dist/lib/staleness/writers/types.d.ts +32 -0
  394. package/dist/lib/startup/command-registry.d.ts +6 -12
  395. package/dist/lib/startup/command-registry.js +11 -31
  396. package/dist/lib/startup/dev-build.d.ts +10 -0
  397. package/dist/lib/startup/dev-build.js +13 -1
  398. package/dist/lib/startup/spellcheck.d.ts +18 -0
  399. package/dist/lib/startup/spellcheck.js +45 -0
  400. package/dist/lib/state.d.ts +36 -9
  401. package/dist/lib/state.js +96 -46
  402. package/dist/lib/subagents-registry.d.ts +0 -7
  403. package/dist/lib/subagents-registry.js +38 -65
  404. package/dist/lib/subagents.d.ts +0 -33
  405. package/dist/lib/subagents.js +0 -75
  406. package/dist/lib/sync-umbrella.js +1 -1
  407. package/dist/lib/teams/agents.d.ts +41 -1
  408. package/dist/lib/teams/agents.js +187 -9
  409. package/dist/lib/teams/api.d.ts +11 -1
  410. package/dist/lib/teams/api.js +11 -2
  411. package/dist/lib/teams/delivery.d.ts +41 -0
  412. package/dist/lib/teams/delivery.js +60 -0
  413. package/dist/lib/teams/registry.d.ts +14 -0
  414. package/dist/lib/teams/registry.js +51 -1
  415. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  416. package/dist/lib/teams/remoteWorktree.js +29 -0
  417. package/dist/lib/teams/scheduler.d.ts +1 -1
  418. package/dist/lib/teams/scheduler.js +1 -1
  419. package/dist/lib/teams/worktree.d.ts +24 -0
  420. package/dist/lib/teams/worktree.js +42 -0
  421. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  422. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  423. package/dist/lib/terminal/engine.d.ts +4 -0
  424. package/dist/lib/terminal/engine.js +8 -2
  425. package/dist/lib/terminal/types.d.ts +21 -2
  426. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  427. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  428. package/dist/lib/tickets/list.d.ts +53 -0
  429. package/dist/lib/tickets/list.js +153 -0
  430. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  431. package/dist/lib/tmux/orphan-reap.js +644 -0
  432. package/dist/lib/tmux/session.d.ts +68 -3
  433. package/dist/lib/tmux/session.js +95 -5
  434. package/dist/lib/triggers/handlers.d.ts +20 -0
  435. package/dist/lib/triggers/handlers.js +6 -1
  436. package/dist/lib/types.d.ts +46 -34
  437. package/dist/lib/usage-fleet.d.ts +32 -0
  438. package/dist/lib/usage-fleet.js +125 -0
  439. package/dist/lib/usage-refresh.d.ts +3 -3
  440. package/dist/lib/usage-refresh.js +19 -16
  441. package/dist/lib/usage.d.ts +51 -47
  442. package/dist/lib/usage.js +145 -153
  443. package/dist/lib/version-duplicates.js +2 -2
  444. package/dist/lib/versions.d.ts +56 -13
  445. package/dist/lib/versions.js +195 -45
  446. package/dist/lib/watchdog/log.d.ts +1 -1
  447. package/dist/lib/watchdog/log.js +3 -3
  448. package/dist/lib/watchdog/rotate.d.ts +6 -6
  449. package/dist/lib/watchdog/rotate.js +6 -6
  450. package/dist/lib/workflows.d.ts +1 -1
  451. package/dist/lib/yaml-io.d.ts +47 -0
  452. package/dist/lib/yaml-io.js +55 -0
  453. package/package.json +2 -1
  454. package/scripts/install-helper.js +2 -2
  455. package/scripts/postinstall.js +23 -20
  456. package/dist/commands/defaults.d.ts +0 -7
  457. package/dist/commands/defaults.js +0 -107
  458. package/dist/commands/export.d.ts +0 -11
  459. package/dist/commands/export.js +0 -215
  460. package/dist/commands/helper.d.ts +0 -12
  461. package/dist/commands/helper.js +0 -87
  462. package/dist/commands/hosts.d.ts +0 -11
  463. package/dist/commands/hosts.js +0 -330
  464. package/dist/commands/lock.d.ts +0 -12
  465. package/dist/commands/lock.js +0 -70
  466. package/dist/commands/pull.d.ts +0 -17
  467. package/dist/commands/pull.js +0 -39
  468. package/dist/commands/push.d.ts +0 -14
  469. package/dist/commands/push.js +0 -30
  470. package/dist/commands/wallet.d.ts +0 -20
  471. package/dist/commands/wallet.js +0 -216
  472. package/dist/commands/worktree.d.ts +0 -19
  473. package/dist/commands/worktree.js +0 -272
  474. package/dist/lib/account-labels.d.ts +0 -24
  475. package/dist/lib/account-labels.js +0 -72
  476. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  477. package/dist/lib/auto-dispatch-linear.js +0 -107
  478. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  479. package/dist/lib/auto-dispatch-provider.js +0 -30
  480. package/dist/lib/auto-dispatch.d.ts +0 -93
  481. package/dist/lib/auto-dispatch.js +0 -128
  482. package/dist/lib/export.d.ts +0 -72
  483. package/dist/lib/export.js +0 -269
  484. package/dist/lib/lock.d.ts +0 -93
  485. package/dist/lib/lock.js +0 -207
  486. package/dist/lib/wallet/index.d.ts +0 -78
  487. package/dist/lib/wallet/index.js +0 -253
@@ -272,6 +272,83 @@ export function projectBasePath(def, forRemote) {
272
272
  return undefined;
273
273
  return forRemote ? base : expandLocalHome(base);
274
274
  }
275
+ /**
276
+ * Every directory a project binds, ordered: `primary` first, then each
277
+ * `repos[]` entry that carries a local `path` (joined with its `subpath`).
278
+ * Deduped by resolved path, so a repo row pointing at the primary collapses.
279
+ *
280
+ * The repos[] walk and the dedupe are shared; the three things the two callers
281
+ * genuinely disagree on are parameters rather than guesses, because collapsing
282
+ * them would change one caller's meaning:
283
+ *
284
+ * - **primary** — spawning anchors on the cwd an agent lands in
285
+ * (`defaultPath ?? root`); probing anchors on `root`, so a monorepo
286
+ * subproject still probes its checkout rather than its subdirectory.
287
+ * - **keepMissing** — probing KEEPS a missing directory, because reporting
288
+ * `✗ missing` across the fleet is the whole job. A local spawn drops it: a
289
+ * grant for a path that is not on this box is noise the harness rejects.
290
+ * - **joinSubpath** — a spawn grants the subdirectory the project declares it
291
+ * cares about; a probe wants the repo root, since git status is a
292
+ * whole-checkout question.
293
+ */
294
+ function projectDirList(def, opts) {
295
+ const raw = [
296
+ opts.primary,
297
+ ...(def.repos ?? []).map((r) => {
298
+ if (!r.path)
299
+ return undefined;
300
+ if (!opts.joinSubpath || !r.subpath)
301
+ return r.path;
302
+ return `${r.path.replace(/\/+$/, '')}/${r.subpath.replace(/^\/+/, '')}`;
303
+ }),
304
+ ].filter((p) => typeof p === 'string' && p.length > 0);
305
+ const seen = new Set();
306
+ const out = [];
307
+ for (const p of raw) {
308
+ // Dedupe on the absolute local path so `~/src/x` and an already-expanded
309
+ // `/home/me/src/x` in a hand-edited def collapse to one entry.
310
+ const abs = path.resolve(expandLocalHome(p));
311
+ if (seen.has(abs))
312
+ continue;
313
+ seen.add(abs);
314
+ if (!opts.keepMissing && !fs.existsSync(abs))
315
+ continue;
316
+ out.push(opts.forRemote ? toHomeRelative(abs) : abs);
317
+ }
318
+ return out;
319
+ }
320
+ /**
321
+ * The directories `projects status` probes across the fleet: the repo root plus
322
+ * every bound checkout, home-relative so each host re-roots them, and including
323
+ * directories absent here so a peer can still answer `✗ missing` for them.
324
+ */
325
+ export function projectProbeTargets(def) {
326
+ return projectDirList(def, {
327
+ primary: def.root,
328
+ forRemote: true,
329
+ keepMissing: true,
330
+ joinSubpath: false,
331
+ });
332
+ }
333
+ /**
334
+ * The directories an agent spawned on this project should reach: the cwd first
335
+ * (`resolveDefinedProjectPath`, so cwd behavior is unchanged), then every other
336
+ * bound repo. `forRemote` keeps them `~/…` so the remote shell re-roots them at
337
+ * its own `$HOME`; locally they are absolute and filtered to what exists.
338
+ *
339
+ * Callers pass the resolved primary so a `--project slug@worktree` run grants
340
+ * the sibling repos alongside the worktree it actually landed in.
341
+ */
342
+ export function projectDirsAbs(def, opts) {
343
+ return projectDirList(def, {
344
+ primary: opts.primary ?? projectBasePath(def, opts.forRemote),
345
+ forRemote: opts.forRemote,
346
+ // A remote spawn must not be filtered by THIS box's filesystem: the target
347
+ // host has its own checkouts, and a dir missing here may well be there.
348
+ keepMissing: opts.forRemote,
349
+ joinSubpath: true,
350
+ });
351
+ }
275
352
  function projectRootsAbs(defs) {
276
353
  const out = [];
277
354
  const push = (name, raw) => {
@@ -329,7 +406,7 @@ function isUnder(child, parent) {
329
406
  * with `expandLocalHome` and resolved, so this matches sessions whose cwd shares
330
407
  * this machine's home layout. A session recorded on a different-home machine
331
408
  * (`/Users/x/…` vs `/home/x/…`) will not match until the fleet-wide,
332
- * home-relative variant lands (see the deferred item in docs/11-projects.md).
409
+ * home-relative variant lands (see the deferred item in docs/projects.md).
333
410
  */
334
411
  export function projectNameForCwd(cwd, defs) {
335
412
  if (!cwd)
@@ -0,0 +1,24 @@
1
+ export declare function setRefreshLockRootForTest(root: string | null): string | null;
2
+ export interface RefreshLeaseOptions<T> {
3
+ scope: string;
4
+ key: string;
5
+ /**
6
+ * Re-read the shared result after taking the lease. If another process
7
+ * refreshed it while this caller waited, return that value instead of
8
+ * repeating the provider request.
9
+ */
10
+ readCompleted: () => T | null;
11
+ isCompleted: (value: T) => boolean;
12
+ refresh: () => Promise<T>;
13
+ }
14
+ /**
15
+ * Serialize refresh work across every agents-cli process on this device.
16
+ *
17
+ * In-process promise maps only protect one Node process. Factory, the daemon,
18
+ * `agents view`, and `agents usage` are separate processes, so they need an
19
+ * OS-visible lease. The result is re-read after lock acquisition: a waiter
20
+ * consumes the winner's publication and never calls the provider a second
21
+ * time. `proper-lockfile` supplies heartbeat + stale-owner recovery while an
22
+ * async provider request is in flight.
23
+ */
24
+ export declare function withRefreshLease<T>(options: RefreshLeaseOptions<T>): Promise<T>;
@@ -0,0 +1,52 @@
1
+ import { createHash } from 'node:crypto';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ import lockfile from 'proper-lockfile';
5
+ import { getCacheDir } from './state.js';
6
+ const REFRESH_LOCK_STALE_MS = 2 * 60_000;
7
+ let refreshLockRootOverride = null;
8
+ export function setRefreshLockRootForTest(root) {
9
+ const previous = refreshLockRootOverride;
10
+ refreshLockRootOverride = root;
11
+ return previous;
12
+ }
13
+ function lockTarget(scope, key) {
14
+ const digest = createHash('sha256').update(`${scope}\0${key}`).digest('hex');
15
+ return path.join(refreshLockRootOverride ?? getCacheDir(), 'refresh-locks', scope, `${digest}.lock`);
16
+ }
17
+ /**
18
+ * Serialize refresh work across every agents-cli process on this device.
19
+ *
20
+ * In-process promise maps only protect one Node process. Factory, the daemon,
21
+ * `agents view`, and `agents usage` are separate processes, so they need an
22
+ * OS-visible lease. The result is re-read after lock acquisition: a waiter
23
+ * consumes the winner's publication and never calls the provider a second
24
+ * time. `proper-lockfile` supplies heartbeat + stale-owner recovery while an
25
+ * async provider request is in flight.
26
+ */
27
+ export async function withRefreshLease(options) {
28
+ const target = lockTarget(options.scope, options.key);
29
+ await fs.mkdir(path.dirname(target), { recursive: true });
30
+ try {
31
+ await fs.writeFile(target, '', { flag: 'wx', mode: 0o600 });
32
+ }
33
+ catch (error) {
34
+ if (error?.code !== 'EEXIST')
35
+ throw error;
36
+ }
37
+ const release = await lockfile.lock(target, {
38
+ realpath: false,
39
+ stale: REFRESH_LOCK_STALE_MS,
40
+ update: REFRESH_LOCK_STALE_MS / 4,
41
+ retries: { retries: 240, minTimeout: 25, maxTimeout: 500, factor: 1.2 },
42
+ });
43
+ try {
44
+ const completed = options.readCompleted();
45
+ if (completed !== null && options.isCompleted(completed))
46
+ return completed;
47
+ return await options.refresh();
48
+ }
49
+ finally {
50
+ await release();
51
+ }
52
+ }
@@ -56,7 +56,7 @@ export interface SkillIndexEntry {
56
56
  tags?: string[];
57
57
  author?: string;
58
58
  installs?: number;
59
- /** Lowercase hex sha256 of the skill's SKILL.md written by `agents publish`. */
59
+ /** Lowercase hex sha256 of the skill's SKILL.md supplied by the registry index. */
60
60
  sha256?: string;
61
61
  }
62
62
  /** Raw shape of the skill index document served by Hermes and compatible registries. */
@@ -100,7 +100,7 @@ export declare function parseOwnerRepoFromRemote(remoteUrl: string): string | nu
100
100
  /**
101
101
  * Walk a repo's skills/ and build a flat {@link SkillIndexDocument}. Each entry
102
102
  * carries the sha256 of its SKILL.md so install can verify integrity after
103
- * cloning — this is the artifact `agents publish` commits + pushes.
103
+ * cloning.
104
104
  *
105
105
  * `repoSlug` is the 'owner/repo' the skills are published under, written into
106
106
  * each entry's `repo` field so {@link skillEntryToGitSource} resolves it to
@@ -493,7 +493,7 @@ export function parseOwnerRepoFromRemote(remoteUrl) {
493
493
  /**
494
494
  * Walk a repo's skills/ and build a flat {@link SkillIndexDocument}. Each entry
495
495
  * carries the sha256 of its SKILL.md so install can verify integrity after
496
- * cloning — this is the artifact `agents publish` commits + pushes.
496
+ * cloning.
497
497
  *
498
498
  * `repoSlug` is the 'owner/repo' the skills are published under, written into
499
499
  * each entry's `repo` field so {@link skillEntryToGitSource} resolves it to
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Normalize a resource's frontmatter `aliases:` value into a clean list.
3
+ *
4
+ * A skill (SKILL.md) or command file may declare `aliases:` — alternate names
5
+ * that {@link resolveResource} matches in addition to the canonical file/dir name
6
+ * (the canonical name always wins a collision). The value is a YAML list or a
7
+ * comma/space-separated string, mirroring the command frontmatter `agents:` field.
8
+ *
9
+ * This lives in its own leaf module so `skills.ts` and `commands.ts` (which parse
10
+ * the frontmatter) and `resources.ts` (which resolves by alias) all share one
11
+ * definition without an import cycle.
12
+ */
13
+ export declare function normalizeAliases(raw: unknown): string[];
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Normalize a resource's frontmatter `aliases:` value into a clean list.
3
+ *
4
+ * A skill (SKILL.md) or command file may declare `aliases:` — alternate names
5
+ * that {@link resolveResource} matches in addition to the canonical file/dir name
6
+ * (the canonical name always wins a collision). The value is a YAML list or a
7
+ * comma/space-separated string, mirroring the command frontmatter `agents:` field.
8
+ *
9
+ * This lives in its own leaf module so `skills.ts` and `commands.ts` (which parse
10
+ * the frontmatter) and `resources.ts` (which resolves by alias) all share one
11
+ * definition without an import cycle.
12
+ */
13
+ export function normalizeAliases(raw) {
14
+ const tokens = Array.isArray(raw)
15
+ ? raw
16
+ : typeof raw === 'string'
17
+ ? raw.split(/[,\s]+/)
18
+ : [];
19
+ const out = [];
20
+ for (const token of tokens) {
21
+ const name = String(token).trim();
22
+ if (name && !out.includes(name))
23
+ out.push(name);
24
+ }
25
+ return out;
26
+ }
@@ -9,7 +9,7 @@ import type { AgentId } from '../types.js';
9
9
  export type { AgentId };
10
10
  /** Resource origin. Precedence (highest first): project > user > plugin > system. */
11
11
  export type Layer = 'system' | 'user' | 'project' | 'plugin';
12
- export type ResourceKind = 'command' | 'hook' | 'skill' | 'rule' | 'mcp' | 'permission' | 'subagent' | 'workflow' | 'memory';
12
+ export type ResourceKind = 'command' | 'hook' | 'skill' | 'rule' | 'mcp' | 'permission' | 'subagent' | 'workflow' | 'memory' | 'plugin';
13
13
  /** A resolved resource with its origin layer. */
14
14
  export interface ResolvedItem<T> {
15
15
  name: string;
@@ -32,7 +32,23 @@ export interface ResolvedResource {
32
32
  * repo (or has no commits).
33
33
  */
34
34
  readonly snapshotSha: string | undefined;
35
+ /**
36
+ * Alternate names this resource declares in its frontmatter `aliases:`, which
37
+ * {@link resolveResource} matches in addition to the canonical name. Lazily
38
+ * read from disk on first access and memoized, so listing resources never pays
39
+ * for it unless a caller inspects an alias. `undefined` when the resource
40
+ * declares none (or for a kind that doesn't support aliases — only `skills` and
41
+ * `commands` do), mirroring {@link snapshotSha} so a strict `toEqual` on a
42
+ * ResolvedResource ignores the absent field.
43
+ */
44
+ readonly aliases: string[] | undefined;
35
45
  }
46
+ /**
47
+ * The declared frontmatter `aliases:` of a single resource, or `[]` for a kind
48
+ * that doesn't support aliases. Only `skills` (SKILL.md) and `commands` carry
49
+ * them today. `resourcePath` is the skill directory or the command file.
50
+ */
51
+ export declare function resourceAliases(kind: ResourceKind, resourcePath: string): string[];
36
52
  /**
37
53
  * True when `rawName` (a filename with its extension already stripped) names a
38
54
  * directory doc rather than a resource of `kind`. Exported so every enumerator
@@ -5,8 +5,8 @@
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
7
  import { AGENTS, listInstalledMcpsWithScope } from './agents.js';
8
- import { listInstalledCommandsWithScope } from './commands.js';
9
- import { listInstalledSkillsWithScope } from './skills.js';
8
+ import { listInstalledCommandsWithScope, parseCommandMetadata } from './commands.js';
9
+ import { listInstalledSkillsWithScope, parseSkillMetadata } from './skills.js';
10
10
  import { listOnDiskHooks } from './resource-inventory.js';
11
11
  import { listInstalledInstructionsWithScope } from './rules/rules.js';
12
12
  import { getEffectiveHome } from './versions.js';
@@ -16,13 +16,37 @@ import { isCapable } from './capabilities.js';
16
16
  import { getProjectAgentsDir, getUserAgentsDir, getSystemAgentsDir, getEnabledExtraRepos, } from './state.js';
17
17
  import { isNameActiveInResourceProfile } from './resource-profiles.js';
18
18
  import { resolveSnapshotSha } from './git.js';
19
- /** Build a ResolvedResource with a lazy, memoized `snapshotSha` getter. */
20
- function withProvenance(base) {
19
+ /**
20
+ * The declared frontmatter `aliases:` of a single resource, or `[]` for a kind
21
+ * that doesn't support aliases. Only `skills` (SKILL.md) and `commands` carry
22
+ * them today. `resourcePath` is the skill directory or the command file.
23
+ */
24
+ export function resourceAliases(kind, resourcePath) {
25
+ if (kind === 'skills')
26
+ return parseSkillMetadata(resourcePath)?.aliases ?? [];
27
+ if (kind === 'commands')
28
+ return parseCommandMetadata(resourcePath)?.aliases ?? [];
29
+ return [];
30
+ }
31
+ /** Build a ResolvedResource with lazy, memoized `snapshotSha` and `aliases` getters. */
32
+ function withProvenance(base, kind) {
33
+ let aliasesComputed = false;
34
+ let aliasesCache;
21
35
  return {
22
36
  ...base,
23
37
  get snapshotSha() {
24
38
  return resolveSnapshotSha(base.repoRoot);
25
39
  },
40
+ get aliases() {
41
+ if (!aliasesComputed) {
42
+ const found = resourceAliases(kind, base.path);
43
+ // Undefined (not []) when none, so a strict toEqual on a ResolvedResource
44
+ // ignores it — the same convention snapshotSha uses.
45
+ aliasesCache = found.length > 0 ? found : undefined;
46
+ aliasesComputed = true;
47
+ }
48
+ return aliasesCache;
49
+ },
26
50
  };
27
51
  }
28
52
  function profiledKind(kind) {
@@ -92,7 +116,7 @@ export function resolveResource(kind, name, cwd) {
92
116
  const exactPath = path.join(dir, name);
93
117
  if (fs.existsSync(exactPath)) {
94
118
  if (resourceIsActive(kind, name, source)) {
95
- return withProvenance({ name, path: exactPath, source, repoRoot });
119
+ return withProvenance({ name, path: exactPath, source, repoRoot }, kind);
96
120
  }
97
121
  continue;
98
122
  }
@@ -104,12 +128,44 @@ export function resolveResource(kind, name, cwd) {
104
128
  const withExt = exactPath + ext;
105
129
  if (fs.existsSync(withExt)) {
106
130
  if (resourceIsActive(kind, name, source)) {
107
- return withProvenance({ name, path: withExt, source, repoRoot });
131
+ return withProvenance({ name, path: withExt, source, repoRoot }, kind);
108
132
  }
109
133
  continue;
110
134
  }
111
135
  }
112
136
  }
137
+ // Alias fallback (skills/commands only). A resource may declare `aliases:` in
138
+ // its frontmatter; match `name` against those AFTER every layer's canonical
139
+ // lookup above has missed, so a canonical resource named `name` always wins a
140
+ // collision regardless of layer. Layer precedence still applies among aliases,
141
+ // and entries are sorted so a same-layer alias collision resolves deterministically.
142
+ if (kind === 'skills' || kind === 'commands') {
143
+ for (const [dir, source, repoRoot] of candidates) {
144
+ if (!fs.existsSync(dir))
145
+ continue;
146
+ let entries;
147
+ try {
148
+ entries = fs.readdirSync(dir, { withFileTypes: true });
149
+ }
150
+ catch {
151
+ continue;
152
+ }
153
+ for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
154
+ if (entry.name.startsWith('.'))
155
+ continue;
156
+ const rawName = entry.name.replace(/\.(md|yaml|yml)$/, '');
157
+ if (isDirectoryDoc(kind, rawName))
158
+ continue;
159
+ const resourcePath = path.join(dir, entry.name);
160
+ if (!resourceAliases(kind, resourcePath).includes(name))
161
+ continue;
162
+ if (!resourceIsActive(kind, rawName, source))
163
+ continue;
164
+ // Resolve to the canonical resource (its real name), not the alias.
165
+ return withProvenance({ name: rawName, path: resourcePath, source, repoRoot }, kind);
166
+ }
167
+ }
168
+ }
113
169
  return null;
114
170
  }
115
171
  /**
@@ -190,7 +246,7 @@ export function listResources(kind, cwd) {
190
246
  path: full,
191
247
  source,
192
248
  repoRoot,
193
- }));
249
+ }, kind));
194
250
  continue;
195
251
  }
196
252
  if (!stat.isDirectory() || HOOK_GROUP_SKIP.has(name))
@@ -231,7 +287,7 @@ export function listResources(kind, cwd) {
231
287
  path: path.join(full, script),
232
288
  source,
233
289
  repoRoot,
234
- }));
290
+ }, kind));
235
291
  }
236
292
  }
237
293
  else {
@@ -246,7 +302,7 @@ export function listResources(kind, cwd) {
246
302
  path: full,
247
303
  source,
248
304
  repoRoot,
249
- }));
305
+ }, kind));
250
306
  }
251
307
  }
252
308
  }
@@ -282,7 +338,7 @@ export function listResources(kind, cwd) {
282
338
  path: path.join(dir, entry.name),
283
339
  source,
284
340
  repoRoot,
285
- }));
341
+ }, kind));
286
342
  }
287
343
  }
288
344
  return results;
@@ -106,10 +106,9 @@ export declare function isLaunchableSignedIn(signedIn: boolean, presence: Pick<C
106
106
  /**
107
107
  * How old a usage snapshot may be and still settle a routing DECISION.
108
108
  *
109
- * Deliberately far tighter than the 24h stale-while-revalidate window the
110
- * display paths use (`USAGE_CACHE_SWR_MS`): `agents view` rendering a slightly
111
- * old bar costs nothing, but the router choosing an account from one costs the
112
- * whole run. Measured case — `yosemite-s1` held snapshots 26h to 2.7 days old
109
+ * A display may show an older cached bar, but the router choosing an account
110
+ * from one costs the whole run. Measured case: `yosemite-s1` held snapshots 26
111
+ * hours to 2.7 days old
113
112
  * with a failing refresh, so balanced read `muqsit@getrush.ai` as 48% used and
114
113
  * launched into it while the account was actually at its weekly cap.
115
114
  */
@@ -103,10 +103,9 @@ function isAvailableEligible(candidate) {
103
103
  /**
104
104
  * How old a usage snapshot may be and still settle a routing DECISION.
105
105
  *
106
- * Deliberately far tighter than the 24h stale-while-revalidate window the
107
- * display paths use (`USAGE_CACHE_SWR_MS`): `agents view` rendering a slightly
108
- * old bar costs nothing, but the router choosing an account from one costs the
109
- * whole run. Measured case — `yosemite-s1` held snapshots 26h to 2.7 days old
106
+ * A display may show an older cached bar, but the router choosing an account
107
+ * from one costs the whole run. Measured case: `yosemite-s1` held snapshots 26
108
+ * hours to 2.7 days old
110
109
  * with a failing refresh, so balanced read `muqsit@getrush.ai` as 48% used and
111
110
  * launched into it while the account was actually at its weekly cap.
112
111
  */
@@ -588,7 +587,7 @@ export async function collectRunCandidates(agent) {
588
587
  home,
589
588
  cliVersion: version,
590
589
  info,
591
- })), { readOnly: true });
590
+ })));
592
591
  return rows.map(({ home: _home, info, ...candidate }) => {
593
592
  const usageKey = getUsageLookupKey(info);
594
593
  const usage = usageKey ? usageByKey.get(usageKey) : undefined;
@@ -3,8 +3,6 @@ export declare function normalizeRoutineNames(names: Iterable<string>): string[]
3
3
  export declare function enabledRoutineNames(): string[] | null;
4
4
  export declare function routineEnabledOnThisDevice(name: string): boolean | null;
5
5
  export declare function replaceEnabledRoutines(names: Iterable<string>): string[];
6
- /** Add newly introduced replacements to an already-materialized device manifest. */
7
- export declare function addEnabledRoutinesOnUpgrade(names: Iterable<string>): boolean;
8
6
  /**
9
7
  * Add or remove one routine on this machine. `legacyEnabledNames` seeds the
10
8
  * manifest the first time an upgraded host changes activation, preserving every
@@ -13,4 +11,26 @@ export declare function addEnabledRoutinesOnUpgrade(names: Iterable<string>): bo
13
11
  export declare function setRoutineEnabledOnThisDevice(name: string, enabled: boolean, legacyEnabledNames?: Iterable<string>): string[];
14
12
  /** Read-only fleet view from synced device documents. Never writes a peer file. */
15
13
  export declare function devicesWithRoutineEnabled(name: string): string[];
14
+ /** Which devices enable which routines, read in one pass. */
15
+ export interface RoutineDeviceIndex {
16
+ /** Routine name → the devices whose allowlist names it, sorted. */
17
+ byRoutine: Map<string, string[]>;
18
+ /**
19
+ * True when at least one device document declares a `routines:` list. Until
20
+ * then no routine is "dark" — the fleet simply has not materialized its
21
+ * activation state yet, and saying "will not fire" would be wrong.
22
+ */
23
+ materialized: boolean;
24
+ /** Device files that could not be read, reported instead of thrown. */
25
+ errors: string[];
26
+ }
27
+ /**
28
+ * Build the whole fleet's activation map in one pass over `devices/`.
29
+ *
30
+ * `devicesWithRoutineEnabled` answers this for a single routine and throws on a
31
+ * corrupt peer file — the right contract for a command acting on one routine,
32
+ * the wrong one for a listing, where a single unreadable device document would
33
+ * blank out every row (and re-walking `devices/` per routine is quadratic).
34
+ */
35
+ export declare function routineDeviceIndex(): RoutineDeviceIndex;
16
36
  export declare function currentRoutineDevice(): string;
@@ -26,22 +26,6 @@ export function replaceEnabledRoutines(names) {
26
26
  updateMeta((meta) => ({ ...meta, deviceRoutines: normalized }));
27
27
  return normalized;
28
28
  }
29
- /** Add newly introduced replacements to an already-materialized device manifest. */
30
- export function addEnabledRoutinesOnUpgrade(names) {
31
- const additions = normalizeRoutineNames(names);
32
- let changed = false;
33
- updateMeta((meta) => {
34
- if (!Array.isArray(meta.deviceRoutines))
35
- return meta;
36
- const current = normalizeRoutineNames(meta.deviceRoutines);
37
- const next = normalizeRoutineNames([...current, ...additions]);
38
- if (next.length === current.length && next.every((name, index) => name === current[index]))
39
- return meta;
40
- changed = true;
41
- return { ...meta, deviceRoutines: next };
42
- });
43
- return changed;
44
- }
45
29
  /**
46
30
  * Add or remove one routine on this machine. `legacyEnabledNames` seeds the
47
31
  * manifest the first time an upgraded host changes activation, preserving every
@@ -89,6 +73,69 @@ export function devicesWithRoutineEnabled(name) {
89
73
  }
90
74
  return devices.sort();
91
75
  }
76
+ /**
77
+ * Build the whole fleet's activation map in one pass over `devices/`.
78
+ *
79
+ * `devicesWithRoutineEnabled` answers this for a single routine and throws on a
80
+ * corrupt peer file — the right contract for a command acting on one routine,
81
+ * the wrong one for a listing, where a single unreadable device document would
82
+ * blank out every row (and re-walking `devices/` per routine is quadratic).
83
+ */
84
+ export function routineDeviceIndex() {
85
+ const byRoutine = new Map();
86
+ const errors = [];
87
+ let materialized = false;
88
+ const devicesDir = path.join(getUserAgentsDir(), 'devices');
89
+ if (!fs.existsSync(devicesDir))
90
+ return { byRoutine, materialized, errors };
91
+ let entries;
92
+ try {
93
+ entries = fs.readdirSync(devicesDir, { withFileTypes: true });
94
+ }
95
+ catch (err) {
96
+ return { byRoutine, materialized, errors: [`${devicesDir}: ${err.message}`] };
97
+ }
98
+ for (const entry of entries) {
99
+ if (!entry.isDirectory())
100
+ continue;
101
+ const file = path.join(devicesDir, entry.name, 'agents.yaml');
102
+ if (!fs.existsSync(file))
103
+ continue;
104
+ let parsed;
105
+ try {
106
+ parsed = yaml.parse(fs.readFileSync(file, 'utf-8'));
107
+ }
108
+ catch (err) {
109
+ errors.push(`${file}: ${err.message.split('\n')[0]}`);
110
+ continue;
111
+ }
112
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
113
+ errors.push(`${file}: expected a YAML map`);
114
+ continue;
115
+ }
116
+ const routines = parsed.routines;
117
+ if (routines === undefined)
118
+ continue;
119
+ if (!Array.isArray(routines) || routines.some((routine) => typeof routine !== 'string')) {
120
+ errors.push(`${file}: routines must be a string list`);
121
+ continue;
122
+ }
123
+ materialized = true;
124
+ // Same normalization the writers use (`replaceEnabledRoutines`), so a device
125
+ // that lists a routine twice, or with stray whitespace, cannot make the index
126
+ // disagree with `enabledRoutineNames` about what that device enables.
127
+ for (const name of normalizeRoutineNames(routines)) {
128
+ const devices = byRoutine.get(name);
129
+ if (devices)
130
+ devices.push(entry.name);
131
+ else
132
+ byRoutine.set(name, [entry.name]);
133
+ }
134
+ }
135
+ for (const devices of byRoutine.values())
136
+ devices.sort();
137
+ return { byRoutine, materialized, errors };
138
+ }
92
139
  export function currentRoutineDevice() {
93
140
  return machineId();
94
141
  }
@@ -104,8 +104,15 @@ export interface ResolvedExecutionContext {
104
104
  export declare function expandTargetHome(home: string, p: string): string;
105
105
  /** Rewrite an absolute path under the target home to its portable `~/…` form; pass others through. */
106
106
  export declare function toTargetPortable(home: string, abs: string): string;
107
- /** True for a bare relative path (not absolute, not home-anchored). */
108
- export declare function isBareRelative(p: string): boolean;
107
+ /**
108
+ * True for a bare relative path (not absolute, not home-anchored) ON THE TARGET.
109
+ *
110
+ * `isAbsolute` is evaluated in the TARGET's own path flavour (see
111
+ * {@link targetPath}), not this process's platform — a Windows-shaped absolute
112
+ * cwd (`C:\Users\x\override`) dispatched from a POSIX daemon must still be
113
+ * recognized as absolute, or it is misread as project-relative.
114
+ */
115
+ export declare function isBareRelative(home: string, p: string): boolean;
109
116
  /**
110
117
  * Resolve the working directory a routine's run lands in and verify its
111
118
  * structural + filesystem readiness for the given placement. Pure of global
@@ -70,9 +70,16 @@ export function toTargetPortable(home, abs) {
70
70
  return '~/' + rel.split(tp.sep).join('/');
71
71
  return abs;
72
72
  }
73
- /** True for a bare relative path (not absolute, not home-anchored). */
74
- export function isBareRelative(p) {
75
- return !path.isAbsolute(p) && !p.startsWith('~') && !p.startsWith('$HOME');
73
+ /**
74
+ * True for a bare relative path (not absolute, not home-anchored) ON THE TARGET.
75
+ *
76
+ * `isAbsolute` is evaluated in the TARGET's own path flavour (see
77
+ * {@link targetPath}), not this process's platform — a Windows-shaped absolute
78
+ * cwd (`C:\Users\x\override`) dispatched from a POSIX daemon must still be
79
+ * recognized as absolute, or it is misread as project-relative.
80
+ */
81
+ export function isBareRelative(home, p) {
82
+ return !targetPath(home).isAbsolute(p) && !p.startsWith('~') && !p.startsWith('$HOME');
76
83
  }
77
84
  /**
78
85
  * True when `child` is `base` or strictly beneath it (no `..` escape).
@@ -154,7 +161,7 @@ export function resolveRoutineExecutionContext(input) {
154
161
  if (cwd === undefined) {
155
162
  return finalize(projBase, 'project_path_missing');
156
163
  }
157
- if (isBareRelative(cwd)) {
164
+ if (isBareRelative(targetHome, cwd)) {
158
165
  const baseAbs = expandTargetHome(targetHome, projBase);
159
166
  // Target-side join: `path.resolve` would use this host's separator and,
160
167
  // for a target home this host does not consider absolute, prepend the
@@ -188,8 +195,16 @@ export function resolveRoutineExecutionContext(input) {
188
195
  const abs = expandTargetHome(targetHome, cwd);
189
196
  return finalize(toTargetPortable(targetHome, abs), 'cwd_missing');
190
197
  }
191
- if (path.isAbsolute(cwd)) {
192
- const resolved = path.resolve(cwd);
198
+ // Absolute in EITHER path flavour — a Windows daemon resolving a POSIX
199
+ // target cwd (or the reverse) must not fall through to bare-relative join.
200
+ // Do not `path.resolve` on the local platform: on win32 that rewrites
201
+ // `/home/u/override` to `D:\home\u\override` and falsely flags
202
+ // cwd_not_portable (Windows CI, cross-platform schedule).
203
+ const cwdIsAbsolute = targetPath(targetHome).isAbsolute(cwd) ||
204
+ path.posix.isAbsolute(cwd) ||
205
+ path.win32.isAbsolute(cwd);
206
+ if (cwdIsAbsolute) {
207
+ const resolved = cwd;
193
208
  if (isInside(targetHome, resolved)) {
194
209
  // Normalize an absolute-under-home path to its portable form on save.
195
210
  return finalize(toTargetPortable(targetHome, resolved), 'cwd_missing');