@phnx-labs/agents-cli 1.22.34 → 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 (493) hide show
  1. package/CHANGELOG.md +672 -2
  2. package/README.md +82 -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 +85 -0
  94. package/dist/commands/share.js +379 -8
  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/codex-policy.d.ts +9 -1
  161. package/dist/lib/codex-policy.js +17 -2
  162. package/dist/lib/commands.d.ts +2 -0
  163. package/dist/lib/commands.js +2 -0
  164. package/dist/lib/computer/sessions-list.d.ts +150 -0
  165. package/dist/lib/computer/sessions-list.js +363 -0
  166. package/dist/lib/config-keys.d.ts +86 -0
  167. package/dist/lib/config-keys.js +193 -0
  168. package/dist/lib/config-machine-keys.d.ts +12 -0
  169. package/dist/lib/config-machine-keys.js +17 -0
  170. package/dist/lib/config-transfer.js +3 -4
  171. package/dist/lib/crabbox/cli.d.ts +2 -2
  172. package/dist/lib/crabbox/cli.js +3 -3
  173. package/dist/lib/daemon-health.d.ts +22 -0
  174. package/dist/lib/daemon-health.js +33 -3
  175. package/dist/lib/daemon-services.d.ts +50 -0
  176. package/dist/lib/daemon-services.js +147 -0
  177. package/dist/lib/daemon-ticks.d.ts +35 -66
  178. package/dist/lib/daemon-ticks.js +77 -159
  179. package/dist/lib/daemon.d.ts +72 -4
  180. package/dist/lib/daemon.js +792 -202
  181. package/dist/lib/deeplink/register.d.ts +49 -0
  182. package/dist/lib/deeplink/register.js +253 -0
  183. package/dist/lib/deeplink/url.d.ts +34 -0
  184. package/dist/lib/deeplink/url.js +78 -0
  185. package/dist/lib/device-config.d.ts +124 -29
  186. package/dist/lib/device-config.js +346 -141
  187. package/dist/lib/devices/config-migration.d.ts +42 -0
  188. package/dist/lib/devices/config-migration.js +203 -0
  189. package/dist/lib/devices/connect.js +14 -7
  190. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  191. package/dist/lib/devices/doctor-findings.js +20 -1
  192. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  193. package/dist/lib/devices/harness-inventory.js +0 -0
  194. package/dist/lib/devices/health.d.ts +1 -1
  195. package/dist/lib/devices/health.js +1 -1
  196. package/dist/lib/devices/pending.d.ts +22 -1
  197. package/dist/lib/devices/pending.js +67 -2
  198. package/dist/lib/devices/registry.d.ts +0 -25
  199. package/dist/lib/devices/registry.js +2 -83
  200. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  201. package/dist/lib/devices/resolve-profile.js +44 -0
  202. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  203. package/dist/lib/devices/rollout-verify.js +193 -0
  204. package/dist/lib/devices/ssh-config.js +10 -6
  205. package/dist/lib/event-families.d.ts +28 -0
  206. package/dist/lib/event-families.js +159 -0
  207. package/dist/lib/event-stream.d.ts +9 -1
  208. package/dist/lib/event-stream.js +26 -9
  209. package/dist/lib/events.d.ts +9 -1
  210. package/dist/lib/events.js +21 -6
  211. package/dist/lib/exec.d.ts +30 -0
  212. package/dist/lib/exec.js +220 -122
  213. package/dist/lib/feed-broadcast.d.ts +25 -0
  214. package/dist/lib/feed-broadcast.js +33 -0
  215. package/dist/lib/feed.d.ts +1 -1
  216. package/dist/lib/feed.js +12 -2
  217. package/dist/lib/fleet/capture.js +15 -0
  218. package/dist/lib/fleet/manifest.js +9 -0
  219. package/dist/lib/fleet/types.d.ts +9 -0
  220. package/dist/lib/fleet-status.js +10 -8
  221. package/dist/lib/git.d.ts +20 -6
  222. package/dist/lib/git.js +121 -17
  223. package/dist/lib/hosts/dispatch.d.ts +8 -3
  224. package/dist/lib/hosts/dispatch.js +29 -3
  225. package/dist/lib/hosts/logs.d.ts +2 -2
  226. package/dist/lib/hosts/logs.js +2 -2
  227. package/dist/lib/hosts/option.js +1 -1
  228. package/dist/lib/hosts/passthrough.d.ts +2 -3
  229. package/dist/lib/hosts/passthrough.js +10 -24
  230. package/dist/lib/hosts/progress.js +2 -2
  231. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  232. package/dist/lib/hosts/providers/devices.js +18 -12
  233. package/dist/lib/hosts/ready.d.ts +5 -1
  234. package/dist/lib/hosts/ready.js +9 -3
  235. package/dist/lib/hosts/reconcile.d.ts +2 -2
  236. package/dist/lib/hosts/reconcile.js +2 -2
  237. package/dist/lib/hosts/registry.js +14 -9
  238. package/dist/lib/hosts/remote-cmd.js +1 -1
  239. package/dist/lib/hosts/remote-os.d.ts +9 -6
  240. package/dist/lib/hosts/remote-os.js +13 -6
  241. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  242. package/dist/lib/hosts/routing-flag.js +41 -0
  243. package/dist/lib/hosts/run-target.js +1 -1
  244. package/dist/lib/hosts/session-index.js +1 -1
  245. package/dist/lib/hosts/tasks.d.ts +6 -6
  246. package/dist/lib/hosts/tasks.js +4 -4
  247. package/dist/lib/hosts/types.js +1 -2
  248. package/dist/lib/installations/resolve.js +2 -8
  249. package/dist/lib/isolation-boundary-report.js +0 -1
  250. package/dist/lib/linear-cache.d.ts +7 -0
  251. package/dist/lib/linear-cache.js +31 -4
  252. package/dist/lib/linear-project-counts.d.ts +1 -1
  253. package/dist/lib/linear-project-counts.js +2 -3
  254. package/dist/lib/linear-projects.js +1 -1
  255. package/dist/lib/loop.d.ts +2 -2
  256. package/dist/lib/loop.js +1 -1
  257. package/dist/lib/mailbox-target.d.ts +1 -1
  258. package/dist/lib/mailbox-target.js +1 -1
  259. package/dist/lib/manifest.js +7 -4
  260. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  261. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  262. package/dist/lib/menubar/snapshot.d.ts +3 -2
  263. package/dist/lib/menubar/snapshot.js +6 -2
  264. package/dist/lib/migrate-fold.d.ts +33 -0
  265. package/dist/lib/migrate-fold.js +130 -0
  266. package/dist/lib/migrate.d.ts +34 -34
  267. package/dist/lib/migrate.js +106 -128
  268. package/dist/lib/model-tier-overrides.d.ts +1 -1
  269. package/dist/lib/model-tier-overrides.js +15 -2
  270. package/dist/lib/monitors/config.d.ts +17 -3
  271. package/dist/lib/monitors/config.js +52 -18
  272. package/dist/lib/monitors/engine.d.ts +32 -1
  273. package/dist/lib/monitors/engine.js +94 -11
  274. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  275. package/dist/lib/monitors/fingerprint.js +100 -0
  276. package/dist/lib/monitors/remote.d.ts +47 -0
  277. package/dist/lib/monitors/remote.js +81 -0
  278. package/dist/lib/monitors/state.d.ts +39 -0
  279. package/dist/lib/monitors/state.js +56 -0
  280. package/dist/lib/onepassword.d.ts +17 -0
  281. package/dist/lib/onepassword.js +52 -22
  282. package/dist/lib/open-url.js +1 -1
  283. package/dist/lib/picker.d.ts +14 -2
  284. package/dist/lib/picker.js +35 -13
  285. package/dist/lib/placement.d.ts +1 -1
  286. package/dist/lib/placement.js +1 -1
  287. package/dist/lib/pr-land-detach.d.ts +32 -0
  288. package/dist/lib/pr-land-detach.js +79 -0
  289. package/dist/lib/profiles-presets.js +13 -0
  290. package/dist/lib/profiles.d.ts +2 -0
  291. package/dist/lib/profiles.js +44 -1
  292. package/dist/lib/project-focus.d.ts +1 -1
  293. package/dist/lib/project-focus.js +1 -1
  294. package/dist/lib/project-key.d.ts +17 -0
  295. package/dist/lib/project-key.js +26 -0
  296. package/dist/lib/project-probe.d.ts +4 -1
  297. package/dist/lib/project-probe.js +5 -4
  298. package/dist/lib/project-resources.js +2 -18
  299. package/dist/lib/project-root.d.ts +16 -0
  300. package/dist/lib/project-root.js +20 -2
  301. package/dist/lib/projects.d.ts +20 -1
  302. package/dist/lib/projects.js +78 -1
  303. package/dist/lib/refresh-coordinator.d.ts +24 -0
  304. package/dist/lib/refresh-coordinator.js +52 -0
  305. package/dist/lib/registry.d.ts +2 -2
  306. package/dist/lib/registry.js +1 -1
  307. package/dist/lib/resource-aliases.d.ts +13 -0
  308. package/dist/lib/resource-aliases.js +26 -0
  309. package/dist/lib/resources/types.d.ts +1 -1
  310. package/dist/lib/resources.d.ts +16 -0
  311. package/dist/lib/resources.js +66 -10
  312. package/dist/lib/rotate.d.ts +3 -4
  313. package/dist/lib/rotate.js +4 -5
  314. package/dist/lib/routine-activation.d.ts +22 -2
  315. package/dist/lib/routine-activation.js +63 -16
  316. package/dist/lib/routine-context.d.ts +9 -2
  317. package/dist/lib/routine-context.js +21 -6
  318. package/dist/lib/routines-project.d.ts +58 -48
  319. package/dist/lib/routines-project.js +190 -159
  320. package/dist/lib/routines.d.ts +41 -6
  321. package/dist/lib/routines.js +92 -34
  322. package/dist/lib/run-defaults.d.ts +5 -0
  323. package/dist/lib/run-defaults.js +11 -1
  324. package/dist/lib/runner.d.ts +10 -8
  325. package/dist/lib/runner.js +122 -39
  326. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  327. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  328. package/dist/lib/secrets/agent.d.ts +10 -3
  329. package/dist/lib/secrets/agent.js +43 -8
  330. package/dist/lib/secrets/bundles.d.ts +1 -0
  331. package/dist/lib/secrets/bundles.js +92 -80
  332. package/dist/lib/secrets/index.js +32 -9
  333. package/dist/lib/secrets/install-helper.d.ts +4 -4
  334. package/dist/lib/secrets/install-helper.js +4 -4
  335. package/dist/lib/secrets/push.d.ts +40 -6
  336. package/dist/lib/secrets/push.js +58 -11
  337. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  338. package/dist/lib/secrets/read-backoff.js +1 -1
  339. package/dist/lib/secrets/remote.d.ts +24 -0
  340. package/dist/lib/secrets/remote.js +54 -4
  341. package/dist/lib/self-update.d.ts +108 -0
  342. package/dist/lib/self-update.js +276 -1
  343. package/dist/lib/session/active.d.ts +89 -5
  344. package/dist/lib/session/active.js +165 -10
  345. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  346. package/dist/lib/session/actor-sidecar.js +2 -1
  347. package/dist/lib/session/db.d.ts +176 -2
  348. package/dist/lib/session/db.js +484 -17
  349. package/dist/lib/session/discover.js +27 -4
  350. package/dist/lib/session/hook-sessions.js +2 -2
  351. package/dist/lib/session/host-link.d.ts +2 -2
  352. package/dist/lib/session/host-link.js +2 -2
  353. package/dist/lib/session/pid-registry.d.ts +21 -0
  354. package/dist/lib/session/pid-registry.js +57 -0
  355. package/dist/lib/session/remote-active.js +15 -1
  356. package/dist/lib/session/remote.js +2 -2
  357. package/dist/lib/session/session-cache.d.ts +14 -7
  358. package/dist/lib/session/session-cache.js +51 -9
  359. package/dist/lib/session/state.d.ts +2 -2
  360. package/dist/lib/session/state.js +1 -1
  361. package/dist/lib/session/sync/config.d.ts +10 -10
  362. package/dist/lib/session/sync/config.js +10 -10
  363. package/dist/lib/session/sync/r2.d.ts +34 -0
  364. package/dist/lib/session/sync/r2.js +123 -0
  365. package/dist/lib/session/throughput.d.ts +1 -1
  366. package/dist/lib/session/throughput.js +1 -1
  367. package/dist/lib/session/types.d.ts +23 -1
  368. package/dist/lib/session/types.js +15 -0
  369. package/dist/lib/session/viewing-in.d.ts +1 -1
  370. package/dist/lib/session/viewing-in.js +1 -1
  371. package/dist/lib/session/watch.d.ts +101 -0
  372. package/dist/lib/session/watch.js +242 -0
  373. package/dist/lib/share/config.d.ts +4 -0
  374. package/dist/lib/share/config.js +1 -0
  375. package/dist/lib/share/delete.d.ts +93 -0
  376. package/dist/lib/share/delete.js +127 -0
  377. package/dist/lib/share/provision.d.ts +38 -0
  378. package/dist/lib/share/provision.js +50 -0
  379. package/dist/lib/share/publish.d.ts +40 -1
  380. package/dist/lib/share/publish.js +116 -3
  381. package/dist/lib/share/worker-template.js +71 -6
  382. package/dist/lib/shims.d.ts +17 -3
  383. package/dist/lib/shims.js +136 -27
  384. package/dist/lib/signin-badge.js +3 -2
  385. package/dist/lib/skills.js +2 -0
  386. package/dist/lib/smart-launch.d.ts +8 -8
  387. package/dist/lib/smart-launch.js +80 -59
  388. package/dist/lib/ssh-exec.d.ts +1 -1
  389. package/dist/lib/ssh-exec.js +1 -1
  390. package/dist/lib/staleness/prune.d.ts +88 -0
  391. package/dist/lib/staleness/prune.js +69 -0
  392. package/dist/lib/staleness/registry.d.ts +1 -1
  393. package/dist/lib/staleness/writers/commands.js +34 -2
  394. package/dist/lib/staleness/writers/hooks.js +16 -0
  395. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  396. package/dist/lib/staleness/writers/skills.js +19 -0
  397. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  398. package/dist/lib/staleness/writers/subagents.js +0 -4
  399. package/dist/lib/staleness/writers/types.d.ts +32 -0
  400. package/dist/lib/startup/command-registry.d.ts +6 -12
  401. package/dist/lib/startup/command-registry.js +14 -31
  402. package/dist/lib/startup/dev-build.d.ts +10 -0
  403. package/dist/lib/startup/dev-build.js +13 -1
  404. package/dist/lib/startup/spellcheck.d.ts +18 -0
  405. package/dist/lib/startup/spellcheck.js +45 -0
  406. package/dist/lib/state.d.ts +36 -9
  407. package/dist/lib/state.js +96 -46
  408. package/dist/lib/subagents-registry.d.ts +0 -7
  409. package/dist/lib/subagents-registry.js +38 -65
  410. package/dist/lib/subagents.d.ts +0 -33
  411. package/dist/lib/subagents.js +0 -75
  412. package/dist/lib/sync-umbrella.js +1 -1
  413. package/dist/lib/teams/agents.d.ts +41 -1
  414. package/dist/lib/teams/agents.js +187 -9
  415. package/dist/lib/teams/api.d.ts +11 -1
  416. package/dist/lib/teams/api.js +11 -2
  417. package/dist/lib/teams/delivery.d.ts +41 -0
  418. package/dist/lib/teams/delivery.js +60 -0
  419. package/dist/lib/teams/registry.d.ts +14 -0
  420. package/dist/lib/teams/registry.js +51 -1
  421. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  422. package/dist/lib/teams/remoteWorktree.js +29 -0
  423. package/dist/lib/teams/scheduler.d.ts +1 -1
  424. package/dist/lib/teams/scheduler.js +1 -1
  425. package/dist/lib/teams/worktree.d.ts +24 -0
  426. package/dist/lib/teams/worktree.js +42 -0
  427. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  428. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  429. package/dist/lib/terminal/engine.d.ts +4 -0
  430. package/dist/lib/terminal/engine.js +8 -2
  431. package/dist/lib/terminal/types.d.ts +21 -2
  432. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  433. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  434. package/dist/lib/tickets/list.d.ts +53 -0
  435. package/dist/lib/tickets/list.js +153 -0
  436. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  437. package/dist/lib/tmux/orphan-reap.js +644 -0
  438. package/dist/lib/tmux/session.d.ts +68 -3
  439. package/dist/lib/tmux/session.js +95 -5
  440. package/dist/lib/triggers/handlers.d.ts +20 -0
  441. package/dist/lib/triggers/handlers.js +6 -1
  442. package/dist/lib/types.d.ts +46 -34
  443. package/dist/lib/usage-fleet.d.ts +32 -0
  444. package/dist/lib/usage-fleet.js +125 -0
  445. package/dist/lib/usage-refresh.d.ts +3 -3
  446. package/dist/lib/usage-refresh.js +19 -16
  447. package/dist/lib/usage.d.ts +51 -47
  448. package/dist/lib/usage.js +145 -153
  449. package/dist/lib/version-duplicates.js +2 -2
  450. package/dist/lib/versions.d.ts +56 -13
  451. package/dist/lib/versions.js +195 -45
  452. package/dist/lib/watchdog/log.d.ts +1 -1
  453. package/dist/lib/watchdog/log.js +3 -3
  454. package/dist/lib/watchdog/rotate.d.ts +6 -6
  455. package/dist/lib/watchdog/rotate.js +6 -6
  456. package/dist/lib/workflows.d.ts +1 -1
  457. package/dist/lib/yaml-io.d.ts +47 -0
  458. package/dist/lib/yaml-io.js +55 -0
  459. package/package.json +2 -1
  460. package/scripts/install-helper.js +2 -2
  461. package/scripts/postinstall.js +23 -20
  462. package/dist/commands/defaults.d.ts +0 -7
  463. package/dist/commands/defaults.js +0 -107
  464. package/dist/commands/export.d.ts +0 -11
  465. package/dist/commands/export.js +0 -215
  466. package/dist/commands/helper.d.ts +0 -12
  467. package/dist/commands/helper.js +0 -87
  468. package/dist/commands/hosts.d.ts +0 -11
  469. package/dist/commands/hosts.js +0 -330
  470. package/dist/commands/lock.d.ts +0 -12
  471. package/dist/commands/lock.js +0 -70
  472. package/dist/commands/pull.d.ts +0 -17
  473. package/dist/commands/pull.js +0 -39
  474. package/dist/commands/push.d.ts +0 -14
  475. package/dist/commands/push.js +0 -30
  476. package/dist/commands/wallet.d.ts +0 -20
  477. package/dist/commands/wallet.js +0 -216
  478. package/dist/commands/worktree.d.ts +0 -19
  479. package/dist/commands/worktree.js +0 -272
  480. package/dist/lib/account-labels.d.ts +0 -24
  481. package/dist/lib/account-labels.js +0 -72
  482. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  483. package/dist/lib/auto-dispatch-linear.js +0 -107
  484. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  485. package/dist/lib/auto-dispatch-provider.js +0 -30
  486. package/dist/lib/auto-dispatch.d.ts +0 -93
  487. package/dist/lib/auto-dispatch.js +0 -128
  488. package/dist/lib/export.d.ts +0 -72
  489. package/dist/lib/export.js +0 -269
  490. package/dist/lib/lock.d.ts +0 -93
  491. package/dist/lib/lock.js +0 -207
  492. package/dist/lib/wallet/index.d.ts +0 -78
  493. package/dist/lib/wallet/index.js +0 -253
@@ -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');
@@ -1,47 +1,24 @@
1
1
  /**
2
- * Project-level routine opt-in, source tracking, and user-layer sync.
2
+ * Project routine discovery, source tracking, and user-layer sync.
3
3
  *
4
- * Project YAML under `<project>/.agents/routines/*.yml` is inspection-only by
5
- * default (a cloned public repo must never auto-fire agent prompts). After an
6
- * explicit opt-in, routines are materialised into `~/.agents/routines/` with
7
- * `source:` provenance so the daemon which only loads user + system layers —
8
- * can fire them. `syncProjectRoutines` refreshes the user-layer copies when
9
- * project YAML changes (also invoked on daemon SIGHUP).
4
+ * Project YAML under `<project>/.agents/routines/*.yml` never fires on its own
5
+ * (a cloned repo must not auto-run agent prompts). A routine has exactly one
6
+ * state enabled or disabled owned by this device's `meta.deviceRoutines`
7
+ * list, never by the project YAML's own `enabled:` field. `agents routines
8
+ * enable <name>` materialises the routine into `~/.agents/routines/` with
9
+ * `source:` provenance (so the daemon, which loads only user + system layers,
10
+ * can see it) and flips the device flag on — one action. `discoverProjectRoutines`
11
+ * surfaces not-yet-materialised routines from the user's registered projects so
12
+ * `list` shows them as disabled. `syncProjectRoutines` refreshes materialised
13
+ * copies from their source YAML (also invoked on daemon SIGHUP).
10
14
  */
11
- import { type JobSource } from './routines.js';
15
+ import { type JobConfig, type JobSource } from './routines.js';
12
16
  /** Expand `~/…` and resolve to an absolute path. */
13
17
  export declare function expandProjectPath(p: string): string;
14
18
  /** Store paths home-relative when under $HOME so they travel across machines. */
15
19
  export declare function displayProjectPath(abs: string): string;
16
- /** Project roots currently opted into daemon firing (absolute paths). */
17
- export declare function listEnabledProjectRoots(): string[];
18
- /** True when this project root is on the opt-in allowlist. */
19
- export declare function isProjectRoutinesEnabled(projectRoot: string): boolean;
20
- /**
21
- * True when the project's own `agents.yaml` opts into project routines:
22
- * `routines: { enable: true }`. This is an additional source of opt-in that
23
- * still requires the project to be present on disk; it does not auto-enable
24
- * every clone — the project must declare it, and `sync` / `enable-project`
25
- * still materialises consent into the user layer.
26
- */
27
- export declare function projectAgentsYamlEnablesRoutines(projectRoot: string): boolean;
28
20
  /** Resolve the project root (parent of `.agents/`) from a cwd, or null. */
29
21
  export declare function resolveProjectRoot(cwd?: string): string | null;
30
- /**
31
- * Opt a project root into daemon firing. Returns true when newly added,
32
- * false when it was already enabled.
33
- */
34
- export declare function enableProjectRoutines(projectRoot: string): boolean;
35
- /**
36
- * Remove a project root from the opt-in allowlist. Optionally deletes the
37
- * user-layer copies that were materialised from it.
38
- */
39
- export declare function disableProjectRoutines(projectRoot: string, opts?: {
40
- removeSynced?: boolean;
41
- }): {
42
- removed: boolean;
43
- deletedJobs: string[];
44
- };
45
22
  /** Git provenance for a project root (best-effort; never throws). */
46
23
  export declare function readProjectGitSource(projectRoot: string): Pick<JobSource, 'repo' | 'branch' | 'commit'>;
47
24
  /** List project routine YAML files (name + absolute path). */
@@ -63,11 +40,15 @@ export interface SyncProjectResult {
63
40
  }>;
64
41
  }
65
42
  /**
66
- * Materialise one project's routines into the user layer.
43
+ * Refresh one project's already-materialised routines from its source YAML.
67
44
  * - Overwrites user copies that already carry matching `source.projectPath`
68
45
  * - Never clobbers a hand-authored user routine (no source / different source)
69
46
  * - Removes user copies from this project whose YAML disappeared
70
- * - Activates materialized routines on this device without mutating definitions
47
+ *
48
+ * Sync NEVER touches the device enable flag: a routine's enabled/disabled state
49
+ * is owned solely by `meta.deviceRoutines` (via `agents routines enable/disable`),
50
+ * never by the project YAML's own `enabled:` field. That is what keeps a cloned
51
+ * repo from auto-firing — refreshing a definition can never turn it on.
71
52
  */
72
53
  export declare function syncProjectRoutines(projectRoot: string): SyncProjectResult;
73
54
  export interface SyncAllResult {
@@ -75,23 +56,52 @@ export interface SyncAllResult {
75
56
  /** Project roots that were listed but missing on disk. */
76
57
  missing: string[];
77
58
  }
59
+ /** Distinct project roots that already have at least one materialised routine. */
60
+ export declare function materialisedProjectRoots(): string[];
78
61
  /**
79
- * Sync every project root on the user allowlist (`meta.routines.projects`),
80
- * plus any explicit `extraRoots`. Project `agents.yaml` `routines.enable`
81
- * alone never opts a path in enable-project is required.
62
+ * Refresh every materialised project routine from its source YAML. The set of
63
+ * roots is derived from what the user has already enabled/materialised (their
64
+ * `source.projectPath`), not from any allowlistenabling a routine is the only
65
+ * thing that brings its project into the refresh set. Also runs on daemon SIGHUP.
82
66
  */
83
67
  export declare function syncAllProjectRoutines(opts?: {
84
68
  extraRoots?: string[];
85
69
  }): SyncAllResult;
70
+ /** A project routine available to enable, not yet materialised on this device. */
71
+ export interface DiscoveredProjectRoutine {
72
+ name: string;
73
+ projectRoot: string;
74
+ file: string;
75
+ /** Display config for `list` (always disabled — enablement is a local act). */
76
+ config: JobConfig;
77
+ }
86
78
  /**
87
- * Discover project routines at cwd for the setup UX. Returns null when no
88
- * project `.agents/routines` dir exists.
79
+ * Project routines from registered projects that are NOT already materialised
80
+ * in the user layer. These surface in `agents routines list` as disabled rows so
81
+ * the single enabled/disabled model is visible, and `enable <name>` resolves a
82
+ * name against them. A routine whose name already exists as a user/system
83
+ * routine is omitted (that materialised copy is the live one).
89
84
  */
90
- export declare function discoverProjectRoutinesAt(cwd?: string): {
85
+ export declare function discoverProjectRoutines(): DiscoveredProjectRoutine[];
86
+ /**
87
+ * Resolve a routine name to a project source for `enable <name>`: first the cwd
88
+ * project, then registered projects. Returns null when the name matches no
89
+ * project routine, or throws-by-return when it is ambiguous across projects.
90
+ */
91
+ export declare function findProjectRoutine(name: string, cwd?: string): {
91
92
  projectRoot: string;
92
- files: Array<{
93
- name: string;
94
- path: string;
95
- }>;
96
- enabled: boolean;
93
+ file: string;
94
+ } | {
95
+ ambiguous: string[];
97
96
  } | null;
97
+ /**
98
+ * Materialise one project routine into the user layer WITHOUT enabling it. The
99
+ * caller (`agents routines enable`) flips the device flag separately, so a
100
+ * materialise can never by itself make a routine fire. Returns the written
101
+ * config, or an error string.
102
+ */
103
+ export declare function materialiseProjectRoutine(projectRoot: string, name: string): {
104
+ job: JobConfig;
105
+ } | {
106
+ error: string;
107
+ };
@@ -1,21 +1,26 @@
1
1
  /**
2
- * Project-level routine opt-in, source tracking, and user-layer sync.
2
+ * Project routine discovery, source tracking, and user-layer sync.
3
3
  *
4
- * Project YAML under `<project>/.agents/routines/*.yml` is inspection-only by
5
- * default (a cloned public repo must never auto-fire agent prompts). After an
6
- * explicit opt-in, routines are materialised into `~/.agents/routines/` with
7
- * `source:` provenance so the daemon which only loads user + system layers —
8
- * can fire them. `syncProjectRoutines` refreshes the user-layer copies when
9
- * project YAML changes (also invoked on daemon SIGHUP).
4
+ * Project YAML under `<project>/.agents/routines/*.yml` never fires on its own
5
+ * (a cloned repo must not auto-run agent prompts). A routine has exactly one
6
+ * state enabled or disabled owned by this device's `meta.deviceRoutines`
7
+ * list, never by the project YAML's own `enabled:` field. `agents routines
8
+ * enable <name>` materialises the routine into `~/.agents/routines/` with
9
+ * `source:` provenance (so the daemon, which loads only user + system layers,
10
+ * can see it) and flips the device flag on — one action. `discoverProjectRoutines`
11
+ * surfaces not-yet-materialised routines from the user's registered projects so
12
+ * `list` shows them as disabled. `syncProjectRoutines` refreshes materialised
13
+ * copies from their source YAML (also invoked on daemon SIGHUP).
10
14
  */
11
15
  import * as fs from 'fs';
12
16
  import * as os from 'os';
13
17
  import * as path from 'path';
14
18
  import * as yaml from 'yaml';
15
19
  import { execFileSync } from 'child_process';
16
- import { getProjectAgentsDir, getProjectRoutinesDir, readMeta, updateMeta, ensureAgentsDir, } from './state.js';
17
- import { readJob, writeJob, setJobEnabled, deleteJob, listJobs, validateJob, } from './routines.js';
20
+ import { getProjectAgentsDir, getProjectRoutinesDir, ensureAgentsDir, } from './state.js';
21
+ import { readJob, writeJob, deleteJob, listJobs, validateJob, } from './routines.js';
18
22
  import { parseOwnerRepoFromRemote } from './registry.js';
23
+ import { listProjectDefs, projectDirsAbs } from './projects.js';
19
24
  import { isSafeSegmentName } from './paths.js';
20
25
  /** Expand `~/…` and resolve to an absolute path. */
21
26
  export function expandProjectPath(p) {
@@ -36,52 +41,6 @@ export function displayProjectPath(abs) {
36
41
  }
37
42
  return resolved;
38
43
  }
39
- /** Project roots currently opted into daemon firing (absolute paths). */
40
- export function listEnabledProjectRoots() {
41
- const meta = readMeta();
42
- const raw = meta.routines?.projects ?? [];
43
- const out = [];
44
- const seen = new Set();
45
- for (const p of raw) {
46
- if (typeof p !== 'string' || p.trim() === '')
47
- continue;
48
- const abs = expandProjectPath(p);
49
- if (seen.has(abs))
50
- continue;
51
- seen.add(abs);
52
- out.push(abs);
53
- }
54
- return out;
55
- }
56
- /** True when this project root is on the opt-in allowlist. */
57
- export function isProjectRoutinesEnabled(projectRoot) {
58
- const abs = expandProjectPath(projectRoot);
59
- return listEnabledProjectRoots().some((p) => p === abs);
60
- }
61
- /**
62
- * True when the project's own `agents.yaml` opts into project routines:
63
- * `routines: { enable: true }`. This is an additional source of opt-in that
64
- * still requires the project to be present on disk; it does not auto-enable
65
- * every clone — the project must declare it, and `sync` / `enable-project`
66
- * still materialises consent into the user layer.
67
- */
68
- export function projectAgentsYamlEnablesRoutines(projectRoot) {
69
- const agentsYaml = path.join(expandProjectPath(projectRoot), 'agents.yaml');
70
- if (!fs.existsSync(agentsYaml))
71
- return false;
72
- try {
73
- const parsed = yaml.parse(fs.readFileSync(agentsYaml, 'utf-8'));
74
- if (!parsed || typeof parsed !== 'object')
75
- return false;
76
- const routines = parsed.routines;
77
- if (!routines || typeof routines !== 'object')
78
- return false;
79
- return routines.enable === true;
80
- }
81
- catch {
82
- return false;
83
- }
84
- }
85
44
  /** Resolve the project root (parent of `.agents/`) from a cwd, or null. */
86
45
  export function resolveProjectRoot(cwd = process.cwd()) {
87
46
  const agentsDir = getProjectAgentsDir(cwd);
@@ -89,63 +48,6 @@ export function resolveProjectRoot(cwd = process.cwd()) {
89
48
  return null;
90
49
  return path.dirname(agentsDir);
91
50
  }
92
- /**
93
- * Opt a project root into daemon firing. Returns true when newly added,
94
- * false when it was already enabled.
95
- */
96
- export function enableProjectRoutines(projectRoot) {
97
- const abs = expandProjectPath(projectRoot);
98
- const stored = displayProjectPath(abs);
99
- let added = false;
100
- updateMeta((meta) => {
101
- const projects = [...(meta.routines?.projects ?? [])];
102
- const already = projects.some((p) => expandProjectPath(p) === abs);
103
- if (already)
104
- return meta;
105
- projects.push(stored);
106
- added = true;
107
- return {
108
- ...meta,
109
- routines: {
110
- ...(meta.routines ?? {}),
111
- projects,
112
- },
113
- };
114
- });
115
- return added;
116
- }
117
- /**
118
- * Remove a project root from the opt-in allowlist. Optionally deletes the
119
- * user-layer copies that were materialised from it.
120
- */
121
- export function disableProjectRoutines(projectRoot, opts = {}) {
122
- const abs = expandProjectPath(projectRoot);
123
- let removed = false;
124
- updateMeta((meta) => {
125
- const projects = meta.routines?.projects ?? [];
126
- const next = projects.filter((p) => expandProjectPath(p) !== abs);
127
- if (next.length === projects.length)
128
- return meta;
129
- removed = true;
130
- return {
131
- ...meta,
132
- routines: {
133
- ...(meta.routines ?? {}),
134
- projects: next,
135
- },
136
- };
137
- });
138
- const deletedJobs = [];
139
- if (opts.removeSynced) {
140
- for (const job of listJobs()) {
141
- if (job.source?.kind === 'project' && expandProjectPath(job.source.projectPath) === abs) {
142
- if (deleteJob(job.name))
143
- deletedJobs.push(job.name);
144
- }
145
- }
146
- }
147
- return { removed, deletedJobs };
148
- }
149
51
  /** Git provenance for a project root (best-effort; never throws). */
150
52
  export function readProjectGitSource(projectRoot) {
151
53
  const abs = expandProjectPath(projectRoot);
@@ -216,11 +118,15 @@ function readProjectJobFile(filePath) {
216
118
  }
217
119
  }
218
120
  /**
219
- * Materialise one project's routines into the user layer.
121
+ * Refresh one project's already-materialised routines from its source YAML.
220
122
  * - Overwrites user copies that already carry matching `source.projectPath`
221
123
  * - Never clobbers a hand-authored user routine (no source / different source)
222
124
  * - Removes user copies from this project whose YAML disappeared
223
- * - Activates materialized routines on this device without mutating definitions
125
+ *
126
+ * Sync NEVER touches the device enable flag: a routine's enabled/disabled state
127
+ * is owned solely by `meta.deviceRoutines` (via `agents routines enable/disable`),
128
+ * never by the project YAML's own `enabled:` field. That is what keeps a cloned
129
+ * repo from auto-firing — refreshing a definition can never turn it on.
224
130
  */
225
131
  export function syncProjectRoutines(projectRoot) {
226
132
  ensureAgentsDir();
@@ -244,37 +150,41 @@ export function syncProjectRoutines(projectRoot) {
244
150
  const seenNames = new Set();
245
151
  for (const file of files) {
246
152
  seenNames.add(file.name);
153
+ // Refresh only routines the user already materialised from THIS project.
154
+ // A project file with no existing user-layer copy is "available, not
155
+ // enabled" — it surfaces via `discoverProjectRoutines` and is materialised
156
+ // by `agents routines enable <name>`, never auto-pulled by a refresh.
157
+ const existing = readJob(file.name);
158
+ if (!existing)
159
+ continue;
160
+ const existingSource = existing.source;
161
+ const fromThisProject = existingSource?.kind === 'project'
162
+ && expandProjectPath(existingSource.projectPath) === abs;
163
+ if (!fromThisProject) {
164
+ result.skipped.push({
165
+ name: file.name,
166
+ reason: existingSource
167
+ ? `user-layer routine already exists from another source (${existingSource.projectPath})`
168
+ : 'user-layer routine already exists (hand-authored); not overwriting without source match',
169
+ });
170
+ continue;
171
+ }
247
172
  const job = readProjectJobFile(file.path);
248
173
  if (!job) {
249
174
  result.errors.push({ name: file.name, error: 'unreadable or invalid YAML' });
250
175
  continue;
251
176
  }
252
- const existing = readJob(file.name);
253
- if (existing) {
254
- const existingSource = existing.source;
255
- const fromThisProject = existingSource?.kind === 'project'
256
- && expandProjectPath(existingSource.projectPath) === abs;
257
- if (!fromThisProject) {
258
- result.skipped.push({
259
- name: file.name,
260
- reason: existingSource
261
- ? `user-layer routine already exists from another source (${existingSource.projectPath})`
262
- : 'user-layer routine already exists (hand-authored); not overwriting without source match',
263
- });
264
- continue;
265
- }
266
- // Preserve user-layer devices pin when project YAML omits it (same overlay
267
- // semantics as listJobs project discovery).
268
- if (job.devices === undefined && existing.devices && existing.devices.length > 0) {
269
- job.devices = existing.devices;
270
- }
271
- // Carry the original creation stamp across. A sync rebuilds the config
272
- // from the PROJECT yaml, which never carries `createdAt`, so without this
273
- // every `agents routines sync` would re-stamp it to now — walking the
274
- // overdue floor forward and hiding real missed fires for project routines.
275
- if (existing.createdAt)
276
- job.createdAt = existing.createdAt;
177
+ // Preserve user-layer devices pin when project YAML omits it (same overlay
178
+ // semantics as listJobs project discovery).
179
+ if (job.devices === undefined && existing.devices && existing.devices.length > 0) {
180
+ job.devices = existing.devices;
277
181
  }
182
+ // Carry the original creation stamp across. A sync rebuilds the config
183
+ // from the PROJECT yaml, which never carries `createdAt`, so without this
184
+ // every `agents routines sync` would re-stamp it to now — walking the
185
+ // overdue floor forward and hiding real missed fires for project routines.
186
+ if (existing.createdAt)
187
+ job.createdAt = existing.createdAt;
278
188
  // Surface repo for list/display when project has a GitHub origin.
279
189
  if (git.repo && !job.repo)
280
190
  job.repo = git.repo;
@@ -286,8 +196,9 @@ export function syncProjectRoutines(projectRoot) {
286
196
  continue;
287
197
  }
288
198
  try {
199
+ // Refresh the definition only. Enablement lives in meta.deviceRoutines and
200
+ // is never derived from the project YAML here.
289
201
  writeJob(job);
290
- setJobEnabled(job.name, job.enabled);
291
202
  result.synced.push(file.name);
292
203
  }
293
204
  catch (err) {
@@ -307,13 +218,23 @@ export function syncProjectRoutines(projectRoot) {
307
218
  }
308
219
  return result;
309
220
  }
221
+ /** Distinct project roots that already have at least one materialised routine. */
222
+ export function materialisedProjectRoots() {
223
+ const roots = new Set();
224
+ for (const job of listJobs()) {
225
+ if (job.source?.kind === 'project')
226
+ roots.add(expandProjectPath(job.source.projectPath));
227
+ }
228
+ return [...roots];
229
+ }
310
230
  /**
311
- * Sync every project root on the user allowlist (`meta.routines.projects`),
312
- * plus any explicit `extraRoots`. Project `agents.yaml` `routines.enable`
313
- * alone never opts a path in enable-project is required.
231
+ * Refresh every materialised project routine from its source YAML. The set of
232
+ * roots is derived from what the user has already enabled/materialised (their
233
+ * `source.projectPath`), not from any allowlistenabling a routine is the only
234
+ * thing that brings its project into the refresh set. Also runs on daemon SIGHUP.
314
235
  */
315
236
  export function syncAllProjectRoutines(opts = {}) {
316
- const roots = new Set(listEnabledProjectRoots());
237
+ const roots = new Set(materialisedProjectRoots());
317
238
  for (const r of opts.extraRoots ?? [])
318
239
  roots.add(expandProjectPath(r));
319
240
  const projects = [];
@@ -328,22 +249,132 @@ export function syncAllProjectRoutines(opts = {}) {
328
249
  return { projects, missing };
329
250
  }
330
251
  /**
331
- * Discover project routines at cwd for the setup UX. Returns null when no
332
- * project `.agents/routines` dir exists.
252
+ * Absolute local checkout roots for every registered project, deduped. This is
253
+ * the discovery universe for project routines: bounded to projects the user
254
+ * registered (`agents projects`), never an arbitrary filesystem scan.
333
255
  */
334
- export function discoverProjectRoutinesAt(cwd = process.cwd()) {
335
- const projectRoot = resolveProjectRoot(cwd);
336
- if (!projectRoot)
337
- return null;
338
- const routinesDir = getProjectRoutinesDir(projectRoot);
339
- if (!routinesDir || !fs.existsSync(routinesDir))
340
- return null;
341
- const files = listProjectRoutineFiles(projectRoot);
342
- if (files.length === 0)
256
+ function registeredProjectRoots() {
257
+ const roots = new Set();
258
+ for (const def of listProjectDefs()) {
259
+ for (const dir of projectDirsAbs(def, { forRemote: false })) {
260
+ if (dir)
261
+ roots.add(path.resolve(dir));
262
+ }
263
+ }
264
+ return [...roots];
265
+ }
266
+ /**
267
+ * Project routines from registered projects that are NOT already materialised
268
+ * in the user layer. These surface in `agents routines list` as disabled rows so
269
+ * the single enabled/disabled model is visible, and `enable <name>` resolves a
270
+ * name against them. A routine whose name already exists as a user/system
271
+ * routine is omitted (that materialised copy is the live one).
272
+ */
273
+ export function discoverProjectRoutines() {
274
+ const materialisedNames = new Set(listJobs().map((j) => j.name));
275
+ const out = [];
276
+ const seen = new Set();
277
+ for (const root of registeredProjectRoots()) {
278
+ const files = listProjectRoutineFiles(root).filter((f) => !materialisedNames.has(f.name) && !seen.has(f.name));
279
+ if (files.length === 0)
280
+ continue;
281
+ const git = readProjectGitSource(root); // once per root, not per routine
282
+ for (const file of files) {
283
+ const job = readProjectJobFile(file.path);
284
+ if (!job)
285
+ continue;
286
+ seen.add(file.name);
287
+ job.name = file.name;
288
+ job.source = {
289
+ kind: 'project',
290
+ projectPath: expandProjectPath(root),
291
+ ...(git.repo ? { repo: git.repo } : {}),
292
+ ...(git.branch ? { branch: git.branch } : {}),
293
+ ...(git.commit ? { commit: git.commit } : {}),
294
+ };
295
+ if (git.repo && !job.repo)
296
+ job.repo = git.repo;
297
+ job.enabled = false; // available, not enabled — never inferred from the repo YAML
298
+ out.push({ name: file.name, projectRoot: expandProjectPath(root), file: file.path, config: job });
299
+ }
300
+ }
301
+ return out;
302
+ }
303
+ /**
304
+ * Resolve a routine name to a project source for `enable <name>`: first the cwd
305
+ * project, then registered projects. Returns null when the name matches no
306
+ * project routine, or throws-by-return when it is ambiguous across projects.
307
+ */
308
+ export function findProjectRoutine(name, cwd = process.cwd()) {
309
+ const cwdRoot = resolveProjectRoot(cwd);
310
+ if (cwdRoot) {
311
+ const match = listProjectRoutineFiles(cwdRoot).find((f) => f.name === name);
312
+ if (match)
313
+ return { projectRoot: expandProjectPath(cwdRoot), file: match.path };
314
+ }
315
+ const hits = [];
316
+ const seenRoots = new Set();
317
+ for (const root of registeredProjectRoots()) {
318
+ const abs = expandProjectPath(root);
319
+ if (seenRoots.has(abs))
320
+ continue;
321
+ seenRoots.add(abs);
322
+ const match = listProjectRoutineFiles(abs).find((f) => f.name === name);
323
+ if (match)
324
+ hits.push({ projectRoot: abs, file: match.path });
325
+ }
326
+ if (hits.length === 0)
343
327
  return null;
344
- return {
345
- projectRoot,
346
- files,
347
- enabled: isProjectRoutinesEnabled(projectRoot) || projectAgentsYamlEnablesRoutines(projectRoot),
328
+ if (hits.length > 1)
329
+ return { ambiguous: hits.map((h) => displayProjectPath(h.projectRoot)) };
330
+ return hits[0];
331
+ }
332
+ /**
333
+ * Materialise one project routine into the user layer WITHOUT enabling it. The
334
+ * caller (`agents routines enable`) flips the device flag separately, so a
335
+ * materialise can never by itself make a routine fire. Returns the written
336
+ * config, or an error string.
337
+ */
338
+ export function materialiseProjectRoutine(projectRoot, name) {
339
+ ensureAgentsDir();
340
+ const abs = expandProjectPath(projectRoot);
341
+ const match = listProjectRoutineFiles(abs).find((f) => f.name === name);
342
+ if (!match)
343
+ return { error: `no routine '${name}' under ${displayProjectPath(abs)}/.agents/routines` };
344
+ const job = readProjectJobFile(match.path);
345
+ if (!job)
346
+ return { error: `routine '${name}' is unreadable or invalid YAML` };
347
+ const existing = readJob(name);
348
+ if (existing) {
349
+ const src = existing.source;
350
+ const fromThisProject = src?.kind === 'project' && expandProjectPath(src.projectPath) === abs;
351
+ if (!fromThisProject) {
352
+ return {
353
+ error: src
354
+ ? `a routine named '${name}' already exists from another source (${src.projectPath})`
355
+ : `a hand-authored routine named '${name}' already exists; rename one before enabling`,
356
+ };
357
+ }
358
+ if (existing.createdAt)
359
+ job.createdAt = existing.createdAt;
360
+ if (job.devices === undefined && existing.devices && existing.devices.length > 0) {
361
+ job.devices = existing.devices;
362
+ }
363
+ }
364
+ const git = readProjectGitSource(abs);
365
+ job.name = name;
366
+ job.source = {
367
+ kind: 'project',
368
+ projectPath: abs,
369
+ ...(git.repo ? { repo: git.repo } : {}),
370
+ ...(git.branch ? { branch: git.branch } : {}),
371
+ ...(git.commit ? { commit: git.commit } : {}),
348
372
  };
373
+ if (git.repo && !job.repo)
374
+ job.repo = git.repo;
375
+ const errors = validateJob(job);
376
+ if (errors.length > 0)
377
+ return { error: errors.join('; ') };
378
+ writeJob(job);
379
+ return { job };
349
380
  }