@phnx-labs/agents-cli 1.22.117 → 1.22.119

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 (271) hide show
  1. package/CHANGELOG.md +301 -0
  2. package/dist/bootstrap.js +4 -11
  3. package/dist/commands/accounts.js +7 -4
  4. package/dist/commands/browser.d.ts +52 -70
  5. package/dist/commands/browser.js +192 -3562
  6. package/dist/commands/daemon.d.ts +39 -2
  7. package/dist/commands/daemon.js +72 -73
  8. package/dist/commands/events.js +1 -1
  9. package/dist/commands/exec.js +53 -1
  10. package/dist/commands/projects.js +92 -7
  11. package/dist/commands/repo.js +13 -49
  12. package/dist/commands/route.js +5 -5
  13. package/dist/commands/routines.js +39 -12
  14. package/dist/commands/sessions-render.d.ts +1 -1
  15. package/dist/commands/sessions-render.js +0 -1
  16. package/dist/commands/sessions.test-fixture.d.ts +0 -1
  17. package/dist/commands/sessions.test-fixture.js +0 -37
  18. package/dist/commands/setup-browser.d.ts +17 -12
  19. package/dist/commands/setup-browser.js +52 -87
  20. package/dist/commands/setup-preferences.d.ts +0 -17
  21. package/dist/commands/setup-preferences.js +18 -49
  22. package/dist/commands/setup.js +9 -9
  23. package/dist/commands/ssh.js +10 -1
  24. package/dist/commands/sync.js +6 -44
  25. package/dist/commands/teams.js +0 -1
  26. package/dist/commands/update.d.ts +19 -0
  27. package/dist/commands/update.js +34 -6
  28. package/dist/commands/view.d.ts +12 -1
  29. package/dist/commands/view.js +47 -2
  30. package/dist/index.js +107 -26
  31. package/dist/lib/account-capabilities.js +0 -2
  32. package/dist/lib/account-catalog.d.ts +38 -0
  33. package/dist/lib/account-catalog.js +110 -26
  34. package/dist/lib/account-provider-registry.js +1 -1
  35. package/dist/lib/account-registry.d.ts +1 -1
  36. package/dist/lib/account-registry.js +36 -2
  37. package/dist/lib/accounting/rotate.js +22 -8
  38. package/dist/lib/accounting/usage-ingest.d.ts +6 -1
  39. package/dist/lib/accounting/usage-ingest.js +115 -45
  40. package/dist/lib/accounting/usage-sync.d.ts +134 -31
  41. package/dist/lib/accounting/usage-sync.js +227 -66
  42. package/dist/lib/accounting/usage.d.ts +16 -3
  43. package/dist/lib/accounting/usage.js +26 -8
  44. package/dist/lib/accounts/add.d.ts +3 -1
  45. package/dist/lib/accounts/add.js +24 -13
  46. package/dist/lib/accounts/slots.d.ts +8 -0
  47. package/dist/lib/accounts/slots.js +17 -0
  48. package/dist/lib/add-dir.js +0 -1
  49. package/dist/lib/agent-cli-commands.js +0 -1
  50. package/dist/lib/agent-spec/agents.d.ts +6 -7
  51. package/dist/lib/agent-spec/agents.js +7 -60
  52. package/dist/lib/auth-health.d.ts +69 -1
  53. package/dist/lib/auth-health.js +133 -4
  54. package/dist/lib/browser/context.d.ts +82 -0
  55. package/dist/lib/browser/context.js +88 -0
  56. package/dist/lib/browser/paths.d.ts +25 -0
  57. package/dist/lib/browser/paths.js +51 -0
  58. package/dist/lib/browser/record.d.ts +38 -0
  59. package/dist/lib/browser/record.js +57 -0
  60. package/dist/lib/browser/sessions-list.js +1 -2
  61. package/dist/lib/browser-client.d.ts +158 -0
  62. package/dist/lib/browser-client.js +234 -0
  63. package/dist/lib/channels/owner-sink.d.ts +1 -18
  64. package/dist/lib/channels/owner-sink.js +29 -82
  65. package/dist/lib/channels/providers/rush.d.ts +7 -7
  66. package/dist/lib/channels/providers/rush.js +127 -57
  67. package/dist/lib/claude-account-token.d.ts +7 -1
  68. package/dist/lib/claude-account-token.js +26 -4
  69. package/dist/lib/claude-statusline.d.ts +1 -1
  70. package/dist/lib/claude-statusline.js +15 -3
  71. package/dist/lib/commands.js +1 -1
  72. package/dist/lib/crabbox/lease.js +1 -1
  73. package/dist/lib/crabbox/runtimes.js +1 -3
  74. package/dist/lib/daemon/account-state-daemon-service.js +1 -0
  75. package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
  76. package/dist/lib/daemon/auth-sync-service.js +37 -43
  77. package/dist/lib/daemon/daemon.d.ts +25 -14
  78. package/dist/lib/daemon/daemon.js +92 -154
  79. package/dist/lib/daemon/runner.d.ts +2 -2
  80. package/dist/lib/daemon/runner.js +32 -9
  81. package/dist/lib/daemon/self-update-service.d.ts +35 -34
  82. package/dist/lib/daemon/self-update-service.js +40 -36
  83. package/dist/lib/daemon/service.d.ts +12 -8
  84. package/dist/lib/daemon/supervisor.d.ts +65 -54
  85. package/dist/lib/daemon/supervisor.js +136 -171
  86. package/dist/lib/daemon/testdata/process-view-start.js +5 -2
  87. package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
  88. package/dist/lib/daemon/usage-sync-service.js +46 -78
  89. package/dist/lib/daemon-health.d.ts +22 -5
  90. package/dist/lib/daemon-health.js +47 -3
  91. package/dist/lib/daemon-services.d.ts +1 -1
  92. package/dist/lib/daemon-services.js +0 -10
  93. package/dist/lib/daemon-ticks.js +4 -2
  94. package/dist/lib/devices/doctor-findings.js +8 -11
  95. package/dist/lib/devices/harness-inventory.js +14 -5
  96. package/dist/lib/exec-account-home.js +5 -0
  97. package/dist/lib/exec.js +10 -13
  98. package/dist/lib/feed/events.js +0 -1
  99. package/dist/lib/feed/tool-activity.js +5 -2
  100. package/dist/lib/fleet-shared-state.d.ts +45 -0
  101. package/dist/lib/fleet-shared-state.js +78 -9
  102. package/dist/lib/fs-atomic.js +25 -0
  103. package/dist/lib/github/pr-mergeable.d.ts +4 -2
  104. package/dist/lib/github/pr-mergeable.js +5 -3
  105. package/dist/lib/github/project-prs.d.ts +58 -3
  106. package/dist/lib/github/project-prs.js +205 -7
  107. package/dist/lib/harness/adapters/cursor.js +14 -4
  108. package/dist/lib/harness-auth-capabilities.d.ts +4 -3
  109. package/dist/lib/harness-auth-capabilities.js +1 -2
  110. package/dist/lib/helper-versions.js +1 -1
  111. package/dist/lib/hooks/cache.d.ts +7 -0
  112. package/dist/lib/hooks/cache.js +27 -2
  113. package/dist/lib/hooks/install.js +7 -1
  114. package/dist/lib/hosts/ready.d.ts +38 -8
  115. package/dist/lib/hosts/ready.js +62 -14
  116. package/dist/lib/installations/active-check.d.ts +27 -0
  117. package/dist/lib/installations/active-check.js +61 -0
  118. package/dist/lib/installations/migrate.js +6 -3
  119. package/dist/lib/installations/shims.d.ts +1 -1
  120. package/dist/lib/installations/shims.js +32 -12
  121. package/dist/lib/installations/store.d.ts +9 -0
  122. package/dist/lib/installations/store.js +24 -0
  123. package/dist/lib/installations/update.js +21 -15
  124. package/dist/lib/installations/versions.js +15 -3
  125. package/dist/lib/manifest.js +1 -1
  126. package/dist/lib/models.js +0 -2
  127. package/dist/lib/open-url.js +28 -54
  128. package/dist/lib/profiles.js +0 -2
  129. package/dist/lib/projects.d.ts +16 -0
  130. package/dist/lib/projects.js +31 -0
  131. package/dist/lib/refresh.js +1 -1
  132. package/dist/lib/routine-readiness.d.ts +35 -0
  133. package/dist/lib/routine-readiness.js +74 -16
  134. package/dist/lib/rules/compile.js +6 -0
  135. package/dist/lib/sandbox.js +0 -2
  136. package/dist/lib/secrets-policy.d.ts +89 -11
  137. package/dist/lib/secrets-policy.js +175 -28
  138. package/dist/lib/session/active.d.ts +17 -6
  139. package/dist/lib/session/active.js +105 -49
  140. package/dist/lib/session/db.d.ts +1 -1
  141. package/dist/lib/session/db.js +65 -18
  142. package/dist/lib/session/discover.js +1 -283
  143. package/dist/lib/session/mirror.d.ts +4 -3
  144. package/dist/lib/session/mirror.js +4 -3
  145. package/dist/lib/session/parse.d.ts +0 -2
  146. package/dist/lib/session/parse.js +1 -138
  147. package/dist/lib/session/pid-registry.d.ts +6 -3
  148. package/dist/lib/session/pid-registry.js +18 -8
  149. package/dist/lib/session/remote/watch.d.ts +1 -1
  150. package/dist/lib/session/remote/watch.js +7 -3
  151. package/dist/lib/session/throughput.d.ts +1 -3
  152. package/dist/lib/session/throughput.js +0 -20
  153. package/dist/lib/session/types.d.ts +2 -2
  154. package/dist/lib/session/types.js +2 -2
  155. package/dist/lib/sessions-client.d.ts +60 -1
  156. package/dist/lib/sessions-client.js +227 -4
  157. package/dist/lib/setup-tool-status.js +5 -10
  158. package/dist/lib/signin-badge.d.ts +3 -2
  159. package/dist/lib/signin-badge.js +6 -3
  160. package/dist/lib/smart-launch.js +4 -1
  161. package/dist/lib/staleness/detectors/commands.d.ts +1 -1
  162. package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
  163. package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
  164. package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
  165. package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
  166. package/dist/lib/staleness/detectors/rules.d.ts +1 -1
  167. package/dist/lib/staleness/detectors/skills.d.ts +1 -1
  168. package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
  169. package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
  170. package/dist/lib/staleness/writers/commands.d.ts +1 -1
  171. package/dist/lib/staleness/writers/hooks.d.ts +1 -1
  172. package/dist/lib/staleness/writers/mcp.d.ts +1 -1
  173. package/dist/lib/staleness/writers/permissions.d.ts +1 -1
  174. package/dist/lib/staleness/writers/plugins.d.ts +1 -1
  175. package/dist/lib/staleness/writers/rules.d.ts +1 -1
  176. package/dist/lib/staleness/writers/skills.d.ts +1 -1
  177. package/dist/lib/staleness/writers/sources.js +5 -0
  178. package/dist/lib/staleness/writers/subagents.d.ts +1 -1
  179. package/dist/lib/staleness/writers/workflows.d.ts +1 -1
  180. package/dist/lib/state.d.ts +6 -4
  181. package/dist/lib/state.js +7 -17
  182. package/dist/lib/teams/parsers.d.ts +1 -1
  183. package/dist/lib/teams/parsers.js +1 -136
  184. package/dist/lib/teams/placement-probe.js +50 -15
  185. package/dist/lib/teams/scheduler.d.ts +7 -0
  186. package/dist/lib/types.d.ts +16 -1
  187. package/dist/lib/types.js +1 -1
  188. package/dist/lib/view-types.d.ts +32 -0
  189. package/dist/lib/watchdog/read.js +0 -1
  190. package/dist/lib/watchdog/rotate.js +1 -2
  191. package/dist/lib/watchdog/runner.js +2 -2
  192. package/dist/lib/watchdog/watchdog.d.ts +1 -1
  193. package/dist/lib/watchdog/watchdogTail.js +0 -31
  194. package/package.json +1 -1
  195. package/scripts/postinstall.js +8 -8
  196. package/dist/browser.d.ts +0 -2
  197. package/dist/browser.js +0 -17
  198. package/dist/commands/browser-picker.d.ts +0 -18
  199. package/dist/commands/browser-picker.js +0 -97
  200. package/dist/lib/browser/arc-discovery.d.ts +0 -52
  201. package/dist/lib/browser/arc-discovery.js +0 -197
  202. package/dist/lib/browser/arc-dom.d.ts +0 -14
  203. package/dist/lib/browser/arc-dom.js +0 -121
  204. package/dist/lib/browser/caller-identity.d.ts +0 -40
  205. package/dist/lib/browser/caller-identity.js +0 -175
  206. package/dist/lib/browser/cdp.d.ts +0 -51
  207. package/dist/lib/browser/cdp.js +0 -254
  208. package/dist/lib/browser/chrome.d.ts +0 -141
  209. package/dist/lib/browser/chrome.js +0 -704
  210. package/dist/lib/browser/chromium-discovery.d.ts +0 -28
  211. package/dist/lib/browser/chromium-discovery.js +0 -96
  212. package/dist/lib/browser/devices.d.ts +0 -34
  213. package/dist/lib/browser/devices.js +0 -61
  214. package/dist/lib/browser/domain-skills.d.ts +0 -71
  215. package/dist/lib/browser/domain-skills.js +0 -195
  216. package/dist/lib/browser/drivers/arc.d.ts +0 -40
  217. package/dist/lib/browser/drivers/arc.js +0 -276
  218. package/dist/lib/browser/drivers/firefox.d.ts +0 -99
  219. package/dist/lib/browser/drivers/firefox.js +0 -377
  220. package/dist/lib/browser/drivers/local.d.ts +0 -55
  221. package/dist/lib/browser/drivers/local.js +0 -266
  222. package/dist/lib/browser/drivers/ssh.d.ts +0 -120
  223. package/dist/lib/browser/drivers/ssh.js +0 -467
  224. package/dist/lib/browser/editor.d.ts +0 -3
  225. package/dist/lib/browser/editor.js +0 -50
  226. package/dist/lib/browser/ffmpeg.d.ts +0 -12
  227. package/dist/lib/browser/ffmpeg.js +0 -184
  228. package/dist/lib/browser/firefox-discovery.d.ts +0 -69
  229. package/dist/lib/browser/firefox-discovery.js +0 -162
  230. package/dist/lib/browser/har.d.ts +0 -85
  231. package/dist/lib/browser/har.js +0 -77
  232. package/dist/lib/browser/hygiene.d.ts +0 -97
  233. package/dist/lib/browser/hygiene.js +0 -153
  234. package/dist/lib/browser/index.d.ts +0 -5
  235. package/dist/lib/browser/index.js +0 -5
  236. package/dist/lib/browser/input.d.ts +0 -7
  237. package/dist/lib/browser/input.js +0 -92
  238. package/dist/lib/browser/ipc.d.ts +0 -204
  239. package/dist/lib/browser/ipc.js +0 -1453
  240. package/dist/lib/browser/login-detection.d.ts +0 -87
  241. package/dist/lib/browser/login-detection.js +0 -274
  242. package/dist/lib/browser/profiles.d.ts +0 -422
  243. package/dist/lib/browser/profiles.js +0 -1157
  244. package/dist/lib/browser/refs.d.ts +0 -89
  245. package/dist/lib/browser/refs.js +0 -191
  246. package/dist/lib/browser/registry.d.ts +0 -70
  247. package/dist/lib/browser/registry.js +0 -252
  248. package/dist/lib/browser/remote-control.d.ts +0 -59
  249. package/dist/lib/browser/remote-control.js +0 -85
  250. package/dist/lib/browser/resolve-target.d.ts +0 -66
  251. package/dist/lib/browser/resolve-target.js +0 -264
  252. package/dist/lib/browser/runtime-state.d.ts +0 -291
  253. package/dist/lib/browser/runtime-state.js +0 -584
  254. package/dist/lib/browser/secret-ref.d.ts +0 -10
  255. package/dist/lib/browser/secret-ref.js +0 -14
  256. package/dist/lib/browser/service.d.ts +0 -812
  257. package/dist/lib/browser/service.js +0 -4693
  258. package/dist/lib/browser/stream.d.ts +0 -17
  259. package/dist/lib/browser/stream.js +0 -72
  260. package/dist/lib/browser/task-index.d.ts +0 -78
  261. package/dist/lib/browser/task-index.js +0 -199
  262. package/dist/lib/browser/types.d.ts +0 -647
  263. package/dist/lib/browser/types.js +0 -61
  264. package/dist/lib/browser/upload.d.ts +0 -29
  265. package/dist/lib/browser/upload.js +0 -298
  266. package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
  267. package/dist/lib/daemon/browser-ipc-service.js +0 -46
  268. package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
  269. package/dist/lib/daemon/browser-task-reap-service.js +0 -26
  270. package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
  271. package/dist/lib/fleet-shared-repo-sync.js +0 -490
@@ -12,8 +12,29 @@
12
12
  * `agents sessions`, and resolving it would recurse (the 1.22.85 secrets
13
13
  * fork bomb with the names swapped — agi-cli#3532).
14
14
  */
15
+ import { spawnSync } from 'node:child_process';
15
16
  import { findInPath } from './agent-spec/agents.js';
17
+ import { compareVersions } from './agent-spec/primitives.js';
18
+ import { stripRoutingFlags } from './hosts/remote-cmd.js';
16
19
  const INSTALL_HINT = 'npm i -g @phnx-labs/sessions-cli';
20
+ /**
21
+ * First `sessions` release that implements the metadata filters and sort
22
+ * (`-p/--project`, `--since`, `--until`, `--sort`, the `@version` agent suffix,
23
+ * and the harness shorthands). An older binary would treat these as FTS tokens,
24
+ * so a box with `sessions` < this floor keeps them on the in-repo engine (which
25
+ * implements the same filters) rather than mis-routing to a binary that can't.
26
+ */
27
+ const SESSIONS_FILTERS_MIN_VERSION = '0.2.0';
28
+ /**
29
+ * First `sessions` release that implements the point-to-one remote read flag
30
+ * `--host <target>` (SSH to ONE box, run `sessions … --local`, stream JSON back).
31
+ * An older binary would treat `--host` as an FTS token, so a box with `sessions`
32
+ * below this floor keeps a `--host` query on the in-repo engine (which resolves
33
+ * `--device` against the fleet) rather than mis-routing it. Kept separate from the
34
+ * filter floor above even though 0.2.1 ≥ 0.2.0 — a 0.2.0 binary supports the
35
+ * filters but NOT `--host`, so the two gates are checked independently.
36
+ */
37
+ const SESSIONS_HOST_MIN_VERSION = '0.2.1';
17
38
  export class SessionsClientError extends Error {
18
39
  code;
19
40
  constructor(code, message) {
@@ -52,6 +73,83 @@ const READ_FLAGS = new Set([
52
73
  '--local',
53
74
  '--no-interactive',
54
75
  ]);
76
+ /**
77
+ * Boolean harness-shorthand flags added in 0.2.0 (`--claude` = `--agent claude`).
78
+ * Recognized as read flags only when the resolved binary supports filters.
79
+ */
80
+ const FILTER_BOOL_FLAGS = new Set([
81
+ '--claude',
82
+ '--codex',
83
+ '--kimi',
84
+ '--antigravity',
85
+ '--grok',
86
+ '--opencode',
87
+ ]);
88
+ /**
89
+ * Value-taking filter flags added in 0.2.0 (each consumes the next argv token,
90
+ * or is written `--flag=value`). `--agent`/`--limit` are NOT here — they are the
91
+ * 0.1.x base set handled unconditionally below.
92
+ */
93
+ const FILTER_VALUE_FLAGS = new Set([
94
+ '--project',
95
+ '--since',
96
+ '--until',
97
+ '--sort',
98
+ ]);
99
+ /** True if any 0.2.0-only filter flag is present — one case that needs the version probe. */
100
+ export function usesFilterFlags(args) {
101
+ return args.some((arg) => {
102
+ if (arg === '-p' || arg === '-a')
103
+ return true;
104
+ if (FILTER_BOOL_FLAGS.has(arg))
105
+ return true;
106
+ for (const vf of FILTER_VALUE_FLAGS) {
107
+ if (arg === vf || arg.startsWith(`${vf}=`))
108
+ return true;
109
+ }
110
+ return false;
111
+ });
112
+ }
113
+ /**
114
+ * True if the 0.2.1 point-to-one remote read flag `--host <value>` (or `--host=value`)
115
+ * is present — the other case that needs the version probe, gated on its own floor.
116
+ */
117
+ export function usesHostFlag(args) {
118
+ return args.some((arg) => arg === '--host' || arg.startsWith('--host='));
119
+ }
120
+ let cachedProbedVersion;
121
+ /**
122
+ * Probe `sessions --version` ONCE per process (cached), returning the parsed
123
+ * version string, or `null` when the probe fails or the output is unparseable.
124
+ * The single cache is what keeps the filter and host gates to one spawn between
125
+ * them, however many `sessionsBinSupports*` calls a query makes.
126
+ */
127
+ function probeSessionsVersion(bin) {
128
+ if (cachedProbedVersion !== undefined)
129
+ return cachedProbedVersion;
130
+ const { command, prefix } = invocation(bin);
131
+ const res = spawnSync(command, [...prefix, '--version'], { encoding: 'utf8', timeout: 3000 });
132
+ const version = (res.stdout ?? '').trim();
133
+ cachedProbedVersion = !res.error && /^\d+\.\d+\.\d+/.test(version) ? version : null;
134
+ return cachedProbedVersion;
135
+ }
136
+ /**
137
+ * Whether the resolved `sessions` binary is at or above `minVersion`. A probe
138
+ * failure or an unparseable version reads as unsupported — the safe direction
139
+ * (in-repo engine handles it), never a mis-route to an old binary.
140
+ */
141
+ export function sessionsBinSupports(bin, minVersion) {
142
+ const version = probeSessionsVersion(bin);
143
+ return version !== null && compareVersions(version, minVersion) >= 0;
144
+ }
145
+ /** Whether the resolved `sessions` binary is new enough for the 0.2.0 filters. */
146
+ export function sessionsBinSupportsFilters(bin) {
147
+ return sessionsBinSupports(bin, SESSIONS_FILTERS_MIN_VERSION);
148
+ }
149
+ /** Whether the resolved `sessions` binary is new enough for the 0.2.1 `--host` flag. */
150
+ export function sessionsBinSupportsHost(bin) {
151
+ return sessionsBinSupports(bin, SESSIONS_HOST_MIN_VERSION);
152
+ }
55
153
  const ENGINE_VERBS = new Set([
56
154
  'resume',
57
155
  'detach',
@@ -76,19 +174,45 @@ const ENGINE_VERBS = new Set([
76
174
  'migrations',
77
175
  'export',
78
176
  ]);
79
- export function isReadQuery(args) {
177
+ export function isReadQuery(args, opts = {}) {
80
178
  if (args.length === 0)
81
179
  return false;
180
+ // Base (0.1.x) value flags, always recognized; the 0.2.0 filter value flags
181
+ // join them only when the binary supports filters, and the 0.2.1 `--host`
182
+ // value flag only when the binary supports it (its own, higher floor).
183
+ const valueFlags = new Set(['--limit', '--agent']);
184
+ const boolFlags = new Set(READ_FLAGS);
185
+ if (opts.filters) {
186
+ for (const vf of FILTER_VALUE_FLAGS)
187
+ valueFlags.add(vf);
188
+ for (const bf of FILTER_BOOL_FLAGS)
189
+ boolFlags.add(bf);
190
+ }
191
+ if (opts.host)
192
+ valueFlags.add('--host');
82
193
  for (let i = 0; i < args.length; i++) {
83
194
  const arg = args[i];
84
- if (arg === '--limit' || arg === '--agent') {
195
+ // `-a` (agent) and `-p` (project) are 0.2.0 short flags that take a value.
196
+ if (opts.filters && (arg === '-a' || arg === '-p')) {
85
197
  i += 1;
86
198
  continue;
87
199
  }
88
- if (arg.startsWith('--limit=') || arg.startsWith('--agent='))
200
+ let matchedValue = false;
201
+ for (const vf of valueFlags) {
202
+ if (arg === vf) {
203
+ i += 1;
204
+ matchedValue = true;
205
+ break;
206
+ }
207
+ if (arg.startsWith(`${vf}=`)) {
208
+ matchedValue = true;
209
+ break;
210
+ }
211
+ }
212
+ if (matchedValue)
89
213
  continue;
90
214
  if (arg.startsWith('-')) {
91
- if (!READ_FLAGS.has(arg))
215
+ if (!boolFlags.has(arg))
92
216
  return false;
93
217
  continue;
94
218
  }
@@ -97,8 +221,107 @@ export function isReadQuery(args) {
97
221
  }
98
222
  return true;
99
223
  }
224
+ /**
225
+ * Scan an argv for the `sessions` `--device`/`-D` flag, which commander defines
226
+ * as VARIADIC (`-D, --device <target...>`) — so it can appear more than once and
227
+ * a space-form value greedily consumes following bare tokens as extra devices.
228
+ * Returns how many times it occurs, the FIRST value, and the index of the last
229
+ * argv token that value occupies (the flag token itself for the `=`/glued forms,
230
+ * the following value token for the space form). Pure; no imports.
231
+ */
232
+ function scanDeviceFlag(args) {
233
+ let count = 0;
234
+ let value;
235
+ let valueEndIndex;
236
+ for (let i = 0; i < args.length; i++) {
237
+ const a = args[i];
238
+ let matched = false;
239
+ let v;
240
+ let endIdx = i;
241
+ if (a === '--device' || a === '-D') {
242
+ matched = true;
243
+ v = args[i + 1];
244
+ endIdx = i + 1;
245
+ }
246
+ else if (a.startsWith('--device=')) {
247
+ matched = true;
248
+ v = a.slice('--device='.length);
249
+ }
250
+ else if (a.startsWith('-D=')) {
251
+ matched = true;
252
+ v = a.slice(3);
253
+ }
254
+ else if (/^-D.+/.test(a)) {
255
+ matched = true;
256
+ v = a.slice(2);
257
+ }
258
+ if (matched) {
259
+ count += 1;
260
+ if (count === 1) {
261
+ value = v;
262
+ valueEndIndex = endIdx;
263
+ }
264
+ }
265
+ }
266
+ return { count, value, valueEndIndex };
267
+ }
268
+ /**
269
+ * Plan the rewrite of a `sessions` READ query that names EXACTLY ONE device via
270
+ * `--device <name>` (and no explicit `--host`) into the standalone's
271
+ * point-to-one remote read: the caller resolves the device to an ssh target and
272
+ * appends `--host ssh://<target>` to `readArgs`, forwarding it to the LOCAL
273
+ * standalone (which owns the ssh hop). This is the local-orchestration collapse
274
+ * (secrets-cli model): `sessions` owns the remote read, replacing the in-repo
275
+ * `--device` peer fan-out — WHEN it is safe (the caller gates on the LOCAL
276
+ * standalone supporting `--host`, >=0.2.1, and falls through to the in-repo
277
+ * fan-out if the PEER lacks the standalone).
278
+ *
279
+ * `sessions --host` is point-to-one, so ONLY a single unambiguous device may
280
+ * collapse; a multi-device query MUST stay on the in-repo fan-out, which parses
281
+ * commander's variadic `--device` correctly. Returns null (→ in-repo path,
282
+ * unchanged) when the query is not a single-device read:
283
+ * - no `--device`/`-D`, or a missing/flag-shaped value;
284
+ * - `--device`/`-D` appears more than once (`--device box --device mac-mini`);
285
+ * - the value is a fan-out sentinel `all`/`fleet` (case-insensitive);
286
+ * - a bare token immediately follows the value (`--device box mac-mini`) —
287
+ * commander's variadic would take it as a second device, so this is
288
+ * multi-device too;
289
+ * - an explicit `--host` is already on the argv — it wins, matching `secrets`'
290
+ * `rewriteDeviceToHost`, so we never add a second `--host`;
291
+ * - the remaining query (with `--device` stripped) is not a read — a lifecycle
292
+ * `--device` (resume/watch/inject/focus/…) keeps its in-repo/`runOnPeer`
293
+ * behavior exactly.
294
+ *
295
+ * Pure and argv-only: fleet resolution (device → ssh target, via
296
+ * `resolveRemoteDevice`) and the version gate live in the caller so this is unit
297
+ * testable with real inputs. `filters` mirrors the caller's version gate for the
298
+ * 0.2.0 filter flags (the `--device` token is not a filter flag, so it is
299
+ * computed identically on the original argv and on `readArgs`).
300
+ */
301
+ export function planDeviceHostRead(args, opts = {}) {
302
+ const { count, value, valueEndIndex } = scanDeviceFlag(args);
303
+ // Exactly one occurrence, with a real (non-flag) value — else fall through.
304
+ if (count !== 1)
305
+ return null;
306
+ if (value === undefined || value === '' || value.startsWith('-'))
307
+ return null;
308
+ if (usesHostFlag(args))
309
+ return null;
310
+ const lower = value.toLowerCase();
311
+ if (lower === 'all' || lower === 'fleet')
312
+ return null;
313
+ // A bare token after the value is a second variadic device (multi-device).
314
+ const next = valueEndIndex !== undefined ? args[valueEndIndex + 1] : undefined;
315
+ if (next !== undefined && !next.startsWith('-'))
316
+ return null;
317
+ const readArgs = stripRoutingFlags(args, [{ long: 'device', short: 'D', takesValue: true }]);
318
+ if (!isReadQuery(readArgs, { filters: opts.filters }))
319
+ return null;
320
+ return { device: value, readArgs };
321
+ }
100
322
  /** Test seam: drop the memoized bin so PATH fixtures can re-resolve. */
101
323
  export function _resetSessionsClientForTest() {
102
324
  cachedBin = undefined;
325
+ cachedProbedVersion = undefined;
103
326
  }
104
327
  export const SESSIONS_INSTALL_HINT = INSTALL_HINT;
@@ -5,7 +5,7 @@ import { getCacheDir, getDeviceMetaPath, getHelpersDir, getUserAgentsDir } from
5
5
  import { atomicWriteJsonSync, withFileLockAsync } from './fs-atomic.js';
6
6
  import { probeCapture } from './probe.js';
7
7
  import { invocation, isStandaloneComputer } from './computer-client.js';
8
- import { getSocketPath as browserSocketPath } from './browser/ipc.js';
8
+ import { isStandaloneBrowser } from './browser-client.js';
9
9
  export const SETUP_TOOLS = ['browser', 'computer', 'secrets', 'term'];
10
10
  export function toolSetupCacheDir(options = {}) {
11
11
  return path.join(options.cacheDir ?? getCacheDir(), 'setup-tools');
@@ -15,8 +15,9 @@ function cachePath(tool, options) {
15
15
  }
16
16
  function setupInputs(tool) {
17
17
  const inputs = [path.join(getUserAgentsDir(), 'agents.yaml'), getDeviceMetaPath()];
18
+ // browser-cli's IPC socket (integration contract §4). computer's is the helper socket.
18
19
  if (tool === 'browser')
19
- inputs.push(browserSocketPath());
20
+ inputs.push(path.join(getHelpersDir(), 'browser', 'browser.sock'));
20
21
  if (tool === 'computer')
21
22
  inputs.push(process.env.COMPUTER_HELPER_SOCKET || path.join(getHelpersDir(), 'computer.sock'));
22
23
  return inputs;
@@ -39,14 +40,8 @@ function binaryMetadata(tool) {
39
40
  const accept = (candidate) => {
40
41
  if (tool === 'computer')
41
42
  return isStandaloneComputer(candidate);
42
- if (tool === 'browser') {
43
- try {
44
- return !fs.realpathSync(candidate).endsWith(path.join('dist', 'browser.js'));
45
- }
46
- catch {
47
- return false;
48
- }
49
- }
43
+ if (tool === 'browser')
44
+ return isStandaloneBrowser(candidate);
50
45
  return true;
51
46
  };
52
47
  let executable = explicit ? (accept(explicit) ? explicit : null) : findInPath(tool, { accept });
@@ -37,8 +37,9 @@ export declare function loginSubcommand(agent: AgentId): string | null;
37
37
  * personal device; this box is provisioned from the durable credential).
38
38
  * - Unnamed legacy homes use the same version-targeted command shape as
39
39
  * doctor, so the hint never logs a different/default home in by accident.
40
- * - `unverified` emits nothing: the probe could not confirm state (e.g. a
41
- * worker whose token lacks the usage scope), so there is nothing to repair.
40
+ * - `unverified` / `no_evidence` emit nothing: the probe could not confirm state
41
+ * (codex/grok have no probe endpoint; a worker's token lacks the usage scope),
42
+ * so there is nothing to repair.
42
43
  */
43
44
  export declare function fixFor(input: {
44
45
  agent: AgentId;
@@ -66,12 +66,15 @@ export function loginSubcommand(agent) {
66
66
  * personal device; this box is provisioned from the durable credential).
67
67
  * - Unnamed legacy homes use the same version-targeted command shape as
68
68
  * doctor, so the hint never logs a different/default home in by accident.
69
- * - `unverified` emits nothing: the probe could not confirm state (e.g. a
70
- * worker whose token lacks the usage scope), so there is nothing to repair.
69
+ * - `unverified` / `no_evidence` emit nothing: the probe could not confirm state
70
+ * (codex/grok have no probe endpoint; a worker's token lacks the usage scope),
71
+ * so there is nothing to repair.
71
72
  */
72
73
  export function fixFor(input) {
73
74
  const { agent, verdict } = input;
74
- if (verdict === 'live' || verdict === 'rate_limited' || verdict === 'unverified' || verdict === 'ready')
75
+ // `no_evidence` (credential present, nothing probed/run here yet) is benign like
76
+ // `unverified` — there is nothing to repair (PHNX-4116).
77
+ if (verdict === 'live' || verdict === 'rate_limited' || verdict === 'unverified' || verdict === 'no_evidence' || verdict === 'ready')
75
78
  return null;
76
79
  if (input.provisioning === 'per-device' || verdict === 'per-device') {
77
80
  return loginHint(agent);
@@ -98,7 +98,10 @@ export function formatNoHealthyDeviceError(pool, signals, agent) {
98
98
  reason = signal.headroom === 'loaded'
99
99
  ? 'overloaded'
100
100
  : signal.installed !== true || signal.signedIn !== true
101
- ? 'no ready harness account'
101
+ // Surface the box's OWN reason (`runReady.reason`, e.g. "all
102
+ // signed_out") when it gave one, rather than a bare "no ready harness
103
+ // account" that leaves the operator guessing (PHNX-4116).
104
+ ? `no ready harness account${signal.reason ? ` (${signal.reason})` : ''}`
102
105
  : 'ineligible';
103
106
  }
104
107
  else if (signal?.timedOut) {
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const commandsDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const commandsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const hooksDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const hooksDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const mcpDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const mcpDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const permissionsDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const permissionsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const pluginsDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const pluginsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const rulesDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const rulesDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,4 +1,4 @@
1
1
  import type { ResourceDetector } from './types.js';
2
2
  /** Exported for unit tests (RUSH-2320 #2). Production callers: list() below. */
3
3
  export declare function skillDirsMatch(src: string, dest: string): boolean;
4
- export declare const skillsDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
4
+ export declare const skillsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const subagentsDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const subagentsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceDetector } from './types.js';
2
- export declare const workflowsDetectors: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
2
+ export declare const workflowsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const commandsWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const commandsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const hooksWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const hooksWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const mcpWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const mcpWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const permissionsWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const permissionsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const pluginsWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const pluginsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -3,4 +3,4 @@ export interface RulesSelection {
3
3
  /** Preset name to compose. Empty string falls through to `"default"` in the composer. */
4
4
  preset: string;
5
5
  }
6
- export declare const rulesWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<RulesSelection>>>;
6
+ export declare const rulesWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<RulesSelection>>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const skillsWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const skillsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -11,6 +11,7 @@ import * as fs from 'fs';
11
11
  import * as path from 'path';
12
12
  import { getUserAgentsDir, getAgentsDir, getEnabledExtraRepos, getCommandsDir, getSkillsDir, getHooksDir } from '../../state.js';
13
13
  import { isSafeSegmentName, safeJoin } from '../../paths.js';
14
+ import { AGENTS } from '../../agents.js';
14
15
  /** Trusted source bases for content-like kinds. Project layer excluded. */
15
16
  function trustedSourceBases() {
16
17
  return [
@@ -57,6 +58,10 @@ function pluginSupportsAgent(manifest, agent) {
57
58
  /** Every `plugins/<plugin>/skills` dir across trusted source bases, filtered to an optional plugin/agent scope. */
58
59
  export function pluginSkillDirs(options = {}) {
59
60
  const dirs = [];
61
+ // A harness that loads plugin skills natively gets no flattened copy and no
62
+ // plugin credit for a top-level skills/<name>: that copy is an orphan there.
63
+ if (options.agent && AGENTS[options.agent]?.nativePluginSkills)
64
+ return dirs;
60
65
  for (const base of trustedSourceBases()) {
61
66
  const pluginsDir = path.join(base.dir, 'plugins');
62
67
  let entries;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const subagentsWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const subagentsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -1,2 +1,2 @@
1
1
  import type { ResourceWriter } from './types.js';
2
- export declare const workflowsWriters: Partial<Record<"claude" | "codex" | "gemini" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
2
+ export declare const workflowsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
@@ -427,8 +427,11 @@ export declare function withMetaLock<T>(fn: () => T): T;
427
427
  * never run inside the short, non-heartbeated lockfile window; the user repo
428
428
  * already pushes.
429
429
  *
430
- * Scoped tightly: only called when the central bytes actually changed, and never
431
- * from the daemon (see {@link isDaemonProcess}). A commit failure fails open —
430
+ * Scoped tightly: only called when the central bytes actually changed — from a
431
+ * CLI command and from the daemon alike, since no daemon tick commits the user
432
+ * repo any more (the shared-state exchange moved to SSH, PHNX-4116), so a
433
+ * daemon-side central write would otherwise sit dirty until the next CLI
434
+ * central edit. A commit failure fails open —
432
435
  * a concurrent daemon holding `index.lock`, a mid-rebase repo — leaving
433
436
  * agents.yaml dirty; the next successful central write commits it, and until
434
437
  * then a pull that would collide refuses rather than losing data. A config
@@ -489,8 +492,7 @@ export declare function updateMeta(updates: Partial<Meta> | ((meta: Meta) => Met
489
492
  * A CLI command that actually moved the fleet-shared central agents.yaml commits
490
493
  * it so the tree is never left dirty on that file at rest — the window that
491
494
  * trips `dirtyTreeRefusal` and wedges pulls fleet-wide (PHNX-3968). Gated on a
492
- * real byte change and never run in the daemon, whose publish tick owns central
493
- * commits. See {@link commitCentralConfig}.
495
+ * real byte change. See {@link commitCentralConfig}.
494
496
  */
495
497
  export declare function commitCentralConfigAfterWrite(centralChanged: boolean): void;
496
498
  /** Derive a filesystem-safe local clone path for a package source URL. */
package/dist/lib/state.js CHANGED
@@ -864,17 +864,6 @@ function writeIfChanged(filePath, content) {
864
864
  atomicWriteFileSync(filePath, content);
865
865
  return true;
866
866
  }
867
- /**
868
- * True in the always-on daemon process (launched as `agents __daemon-run`,
869
- * see cli/src/index.ts). The daemon owns central git commits through
870
- * fleet-shared-repo-sync's publish tick, so a central write from inside the
871
- * daemon must NOT also commit here — that would race the publisher's own
872
- * add/commit/rebase/push on the same index. Every ordinary CLI invocation
873
- * returns false and commits its own central edit synchronously.
874
- */
875
- function isDaemonProcess() {
876
- return process.argv[2] === '__daemon-run';
877
- }
878
867
  /**
879
868
  * Commit the central `agents.yaml` in the user repo, synchronously, so a CLI
880
869
  * config mutation never leaves the working tree dirty on that one shared-line
@@ -892,8 +881,11 @@ function isDaemonProcess() {
892
881
  * never run inside the short, non-heartbeated lockfile window; the user repo
893
882
  * already pushes.
894
883
  *
895
- * Scoped tightly: only called when the central bytes actually changed, and never
896
- * from the daemon (see {@link isDaemonProcess}). A commit failure fails open —
884
+ * Scoped tightly: only called when the central bytes actually changed — from a
885
+ * CLI command and from the daemon alike, since no daemon tick commits the user
886
+ * repo any more (the shared-state exchange moved to SSH, PHNX-4116), so a
887
+ * daemon-side central write would otherwise sit dirty until the next CLI
888
+ * central edit. A commit failure fails open —
897
889
  * a concurrent daemon holding `index.lock`, a mid-rebase repo — leaving
898
890
  * agents.yaml dirty; the next successful central write commits it, and until
899
891
  * then a pull that would collide refuses rather than losing data. A config
@@ -1685,13 +1677,11 @@ export function updateMeta(updates) {
1685
1677
  * A CLI command that actually moved the fleet-shared central agents.yaml commits
1686
1678
  * it so the tree is never left dirty on that file at rest — the window that
1687
1679
  * trips `dirtyTreeRefusal` and wedges pulls fleet-wide (PHNX-3968). Gated on a
1688
- * real byte change and never run in the daemon, whose publish tick owns central
1689
- * commits. See {@link commitCentralConfig}.
1680
+ * real byte change. See {@link commitCentralConfig}.
1690
1681
  */
1691
1682
  export function commitCentralConfigAfterWrite(centralChanged) {
1692
- if (centralChanged && !isDaemonProcess()) {
1683
+ if (centralChanged)
1693
1684
  commitCentralConfig(USER_AGENTS_DIR);
1694
- }
1695
1685
  }
1696
1686
  /** Derive a filesystem-safe local clone path for a package source URL. */
1697
1687
  export function getPackageLocalPath(source) {
@@ -1,5 +1,5 @@
1
1
  /** Supported agent CLI types for team spawning. */
2
- export type AgentType = 'codex' | 'gemini' | 'cursor' | 'claude' | 'opencode' | 'grok' | 'antigravity' | 'kimi' | 'droid' | 'warp';
2
+ export type AgentType = 'codex' | 'cursor' | 'claude' | 'opencode' | 'grok' | 'antigravity' | 'kimi' | 'droid' | 'warp';
3
3
  /** Normalize a raw JSON event from any agent type into an array of unified event objects. */
4
4
  export declare function normalizeEvents(agentType: AgentType, raw: any): any[];
5
5
  /** Normalize a raw JSON event, returning only the first unified event (convenience wrapper). */