@phnx-labs/agents-cli 1.22.46 → 1.22.47

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 (167) hide show
  1. package/CHANGELOG.md +279 -0
  2. package/LICENSE +102 -182
  3. package/README.md +31 -18
  4. package/dist/cli/command-registry.d.ts +1 -1
  5. package/dist/cli/command-registry.js +4 -2
  6. package/dist/commands/accounts.js +56 -12
  7. package/dist/commands/auth.js +7 -5
  8. package/dist/commands/browser-sessions-picker.js +9 -7
  9. package/dist/commands/browser.js +266 -15
  10. package/dist/commands/config.js +26 -4
  11. package/dist/commands/cost.d.ts +1 -1
  12. package/dist/commands/detach.d.ts +13 -0
  13. package/dist/commands/detach.js +11 -8
  14. package/dist/commands/exec.js +55 -38
  15. package/dist/commands/feed-watch.d.ts +2 -0
  16. package/dist/commands/feed-watch.js +28 -0
  17. package/dist/commands/feed.js +27 -0
  18. package/dist/commands/feedback.js +3 -19
  19. package/dist/commands/insights.d.ts +1 -1
  20. package/dist/commands/insights.js +2 -2
  21. package/dist/commands/lease.js +3 -3
  22. package/dist/commands/routines.js +1 -1
  23. package/dist/commands/sessions-picker-factory.d.ts +2 -1
  24. package/dist/commands/sessions-picker-factory.js +1 -1
  25. package/dist/commands/sessions-stop.d.ts +24 -0
  26. package/dist/commands/sessions-stop.js +66 -0
  27. package/dist/commands/sessions-trace.d.ts +82 -0
  28. package/dist/commands/sessions-trace.js +387 -0
  29. package/dist/commands/sessions.js +4 -0
  30. package/dist/commands/ssh.d.ts +15 -0
  31. package/dist/commands/ssh.js +194 -16
  32. package/dist/commands/teams.js +34 -2
  33. package/dist/commands/view.d.ts +2 -0
  34. package/dist/commands/view.js +18 -31
  35. package/dist/commands/watchdog.js +9 -14
  36. package/dist/lib/account-capabilities.d.ts +4 -0
  37. package/dist/lib/account-capabilities.js +13 -9
  38. package/dist/lib/account-registry.d.ts +2 -0
  39. package/dist/lib/account-registry.js +30 -2
  40. package/dist/lib/accounting/rotate.d.ts +9 -0
  41. package/dist/lib/accounting/rotate.js +12 -2
  42. package/dist/lib/accounting/usage.d.ts +70 -3
  43. package/dist/lib/accounting/usage.js +235 -63
  44. package/dist/lib/agent-modes.js +29 -1
  45. package/dist/lib/agent-spec/agents.d.ts +4 -3
  46. package/dist/lib/agent-spec/agents.js +14 -6
  47. package/dist/lib/analytics/mix-commands.d.ts +1 -1
  48. package/dist/lib/analytics/mix-commands.js +2 -2
  49. package/dist/lib/auth-health.d.ts +13 -3
  50. package/dist/lib/auth-health.js +50 -8
  51. package/dist/lib/browser/devices.d.ts +19 -0
  52. package/dist/lib/browser/devices.js +23 -0
  53. package/dist/lib/browser/ipc.d.ts +1 -1
  54. package/dist/lib/browser/ipc.js +33 -7
  55. package/dist/lib/browser/profiles.d.ts +106 -1
  56. package/dist/lib/browser/profiles.js +300 -17
  57. package/dist/lib/browser/remote-control.d.ts +26 -2
  58. package/dist/lib/browser/remote-control.js +33 -3
  59. package/dist/lib/browser/runtime-state.d.ts +9 -0
  60. package/dist/lib/browser/runtime-state.js +24 -8
  61. package/dist/lib/browser/service.d.ts +37 -0
  62. package/dist/lib/browser/service.js +78 -20
  63. package/dist/lib/browser/sessions-list.d.ts +1 -3
  64. package/dist/lib/browser/sessions-list.js +3 -16
  65. package/dist/lib/browser/types.d.ts +12 -1
  66. package/dist/lib/codex-policy.d.ts +11 -1
  67. package/dist/lib/codex-policy.js +20 -5
  68. package/dist/lib/config-keys.d.ts +4 -3
  69. package/dist/lib/config-keys.js +17 -7
  70. package/dist/lib/daemon/runner.js +15 -2
  71. package/dist/lib/daemon-ticks.js +2 -2
  72. package/dist/lib/device-config.d.ts +25 -8
  73. package/dist/lib/device-config.js +90 -17
  74. package/dist/lib/devices/config-migration.d.ts +7 -0
  75. package/dist/lib/devices/config-migration.js +67 -3
  76. package/dist/lib/devices/health.d.ts +27 -2
  77. package/dist/lib/devices/health.js +39 -9
  78. package/dist/lib/devices/interactive-host.d.ts +15 -0
  79. package/dist/lib/devices/interactive-host.js +53 -0
  80. package/dist/lib/devices/registry.d.ts +61 -4
  81. package/dist/lib/devices/registry.js +94 -38
  82. package/dist/lib/devices/stats-cache.d.ts +6 -0
  83. package/dist/lib/devices/stats-cache.js +10 -2
  84. package/dist/lib/exec.d.ts +5 -3
  85. package/dist/lib/exec.js +32 -16
  86. package/dist/lib/feed/answer.d.ts +29 -0
  87. package/dist/lib/feed/answer.js +145 -0
  88. package/dist/lib/feed/attention.d.ts +83 -0
  89. package/dist/lib/feed/attention.js +0 -0
  90. package/dist/lib/feed/feed.d.ts +109 -0
  91. package/dist/lib/feed/feed.js +154 -3
  92. package/dist/lib/feed/pr-status.d.ts +14 -0
  93. package/dist/lib/feed/pr-status.js +47 -0
  94. package/dist/lib/feed/watch.d.ts +59 -0
  95. package/dist/lib/feed/watch.js +180 -0
  96. package/dist/lib/fleet/capture.js +6 -0
  97. package/dist/lib/fleet/remote-login.js +8 -3
  98. package/dist/lib/fleet/types.d.ts +17 -0
  99. package/dist/lib/harness/adapter.d.ts +11 -0
  100. package/dist/lib/harness/adapters/claude.js +38 -24
  101. package/dist/lib/harness/adapters/codex.js +2 -4
  102. package/dist/lib/hooks/cache.js +8 -0
  103. package/dist/lib/hooks/match.d.ts +3 -0
  104. package/dist/lib/hooks/match.js +25 -0
  105. package/dist/lib/hosts/passthrough.js +16 -0
  106. package/dist/lib/hosts/registry.js +7 -0
  107. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  108. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  109. package/dist/lib/menubar/install-menubar.d.ts +13 -0
  110. package/dist/lib/menubar/install-menubar.js +26 -2
  111. package/dist/lib/open-url.d.ts +60 -2
  112. package/dist/lib/open-url.js +167 -12
  113. package/dist/lib/refresh-coordinator.d.ts +1 -1
  114. package/dist/lib/refresh-coordinator.js +1 -1
  115. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  116. package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +2 -0
  117. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  118. package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
  119. package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +13 -1
  120. package/dist/lib/session/active.d.ts +67 -0
  121. package/dist/lib/session/active.js +69 -1
  122. package/dist/lib/session/db.js +4 -2
  123. package/dist/lib/session/discover.d.ts +2 -0
  124. package/dist/lib/session/discover.js +12 -6
  125. package/dist/lib/session/prompt.d.ts +35 -0
  126. package/dist/lib/session/prompt.js +56 -0
  127. package/dist/lib/session/remote/watch.d.ts +1 -1
  128. package/dist/lib/session/remote/watch.js +6 -1
  129. package/dist/lib/session/render.js +7 -3
  130. package/dist/lib/session/session-cache.js +5 -1
  131. package/dist/lib/session/trajectory-compare.d.ts +47 -0
  132. package/dist/lib/session/trajectory-compare.js +116 -0
  133. package/dist/lib/session/trajectory-html.d.ts +15 -0
  134. package/dist/lib/session/trajectory-html.js +750 -0
  135. package/dist/lib/session/trajectory-lineage.d.ts +92 -0
  136. package/dist/lib/session/trajectory-lineage.js +195 -0
  137. package/dist/lib/session/trajectory-text.d.ts +37 -0
  138. package/dist/lib/session/trajectory-text.js +277 -0
  139. package/dist/lib/session/trajectory.d.ts +102 -0
  140. package/dist/lib/session/trajectory.js +335 -0
  141. package/dist/lib/startup/command-registry.d.ts +3 -1
  142. package/dist/lib/startup/command-registry.js +5 -2
  143. package/dist/lib/state.d.ts +1 -1
  144. package/dist/lib/state.js +4 -2
  145. package/dist/lib/teams/agents.js +9 -0
  146. package/dist/lib/terminal/inject.d.ts +19 -0
  147. package/dist/lib/terminal/inject.js +19 -9
  148. package/dist/lib/tmux/session.d.ts +46 -13
  149. package/dist/lib/tmux/session.js +173 -27
  150. package/dist/lib/types.d.ts +16 -0
  151. package/dist/lib/usage-backoff.d.ts +2 -1
  152. package/dist/lib/usage-backoff.js +60 -19
  153. package/dist/lib/usage-refresh.d.ts +17 -3
  154. package/dist/lib/usage-refresh.js +57 -11
  155. package/dist/lib/watchdog/log.d.ts +1 -1
  156. package/dist/lib/watchdog/log.js +1 -1
  157. package/dist/lib/watchdog/runner.d.ts +36 -45
  158. package/dist/lib/watchdog/runner.js +150 -119
  159. package/dist/lib/watchdog/service.d.ts +0 -1
  160. package/dist/lib/watchdog/service.js +0 -1
  161. package/dist/lib/watchdog/watchdog-agent.d.ts +38 -0
  162. package/dist/lib/watchdog/watchdog-agent.js +59 -0
  163. package/dist/lib/watchdog/watchdog.d.ts +11 -2
  164. package/dist/lib/watchdog/watchdog.js +37 -104
  165. package/package.json +2 -2
  166. package/dist/commands/usage.d.ts +0 -27
  167. package/dist/commands/usage.js +0 -96
package/CHANGELOG.md CHANGED
@@ -1,5 +1,284 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.22.47
4
+
5
+ - **On your own machine, every Claude run uses your normal login — not the
6
+ worker setup-token (RUSH-2395).** The credential now follows **device role**,
7
+ not run mode. A device marked `config.role: personal` (your interactive box —
8
+ set it with `agents devices role <name> personal`) authenticates every Claude
9
+ run from its per-version login, whether it opens a TUI or is a headless
10
+ one-shot like `agents run claude "fix the bug"`. Before, the choice keyed only
11
+ on whether a prompt was present ("this opens a TUI", not "a human is present"),
12
+ so a headless run on your laptop grabbed the reserved `auth`-bundle setup-token
13
+ and took the session off your login — surfacing as `/status` reporting
14
+ `Auth token: CLAUDE_CODE_OAUTH_TOKEN`. The setup-token stays the credential for
15
+ headless runs on **worker** devices (and unmarked boxes), which have no
16
+ keychain login to defer to. Routines follow the same role gate. Source:
17
+ `apps/cli/src/lib/harness/adapters/claude.ts`,
18
+ `apps/cli/src/lib/exec.ts`, `apps/cli/src/lib/daemon/runner.ts`,
19
+ `apps/cli/src/lib/device-config.ts`.
20
+
21
+ - **A hand-cut release no longer dead-ends on a fresh attestation store or a lost `RELEASE_ATTESTATION_DIR` (RUSH-2970).** Three traps that cost roughly eight failed release attempts across 1.22.43-1.22.46 are fixed at the source. (1) `release-attestation-produce.sh` now seeds `release-manifest.json` from the last published GitHub release before falling back to an empty one — a fresh store had no recorded `computer-mac` inputDigest, so the helper loop read "input changed" and told the operator to run `publish-computer-helper-mac.sh`, which does not write a manifest, so the instruction looped forever on a byte-identical helper. (2) `release-worktree.sh` now exports `RELEASE_ATTESTATION_DIR` to the caller's store when it is unset: the throwaway release worktree resolved its own empty `.release-attestations`, so `require` reported `missing exact attestation key` with `?` for every key component — which reads like a key mismatch rather than a wrong directory. An explicit export still wins. (3) `publish-computer-helper-mac.sh` now sources `headless-sign-context.sh` itself: its own documented invocation (`agents secrets exec apple.com -- ...`) injected the notary creds but left the Developer ID signing keychain locked, so a headless publish died in `codesign` with `errSecInternalComponent` unless the operator knew to source that context first — which nothing said. On a Mac without the release-box pass files it is a no-op. Source: `apps/cli/scripts/{release-attestation-produce,release-worktree,publish-computer-helper-mac}.sh`.
22
+
23
+ - **Session rows show what the agent DID, and dead crash-orphans stop piling up (RUSH-3011).**
24
+ The `agents sessions watch --json` row (which the AGI EXT Fleet reads) now carries a
25
+ **recap** so a row reads as the agent's work, not its stale first prompt: `title` follows
26
+ a best-source-wins ladder — a `/rename`/harness `label` (which also holds an agent-generated
27
+ title) → the last agent line → the first-prompt topic — and `recapSource`
28
+ (`'label'|'last'|'prompt'`) names which rung won, so a session that produced work shows an
29
+ agent-derived line. The first
30
+ user turn is cleaned into `userPromptClean`/`userPromptKind` (with `lastAgentLine` exposed)
31
+ so a screenshot path folds to `[image]`, a pasted `$ cmd` to the command, and a `/skill`
32
+ install path to `/<name>` — path noise never shows on the "You" line — and the recap card's
33
+ `Prompt:` line uses the same cleaning. Separately, a crash-leaked `--device` tunnel session
34
+ that is genuinely dead and days-stale (`abandoned` + dead pid) is folded OUT of the
35
+ reconnectable set (`resumable: false`, `recovery: null`), so the "Needs reconnecting" list
36
+ stops ballooning; a live pid (idle-but-unfinished) or a recently-closed session is never
37
+ reaped. Source: `apps/cli/src/lib/session/{prompt,active,render}.ts`,
38
+ `apps/cli/src/lib/session/remote/watch.ts`, `apps/cli/docs/sessions.md`.
39
+
40
+ - **Keep generated session names in `label`, separate from the first-prompt
41
+ `topic` (RUSH-3011).** Claude `ai-title` and `/rename` events now populate the
42
+ canonical name field consumed by fleet clients, and an empty live metadata
43
+ record can no longer erase an existing generated title or launch handle.
44
+ Source: `apps/cli/src/lib/session/discover.ts`,
45
+ `apps/cli/src/lib/session/db.ts`.
46
+
47
+ - fix(teams): observe AgentManager's fire-and-forget init rejection so a lost init race (dir removed mid-mkdir) fails the awaiting caller instead of crashing the process as an unhandled rejection — the flake that failed two fully-green release attestation runs
48
+
49
+ - **Per-account 429 backoff + auth verdicts derived from fresh usage fetches — the last four 'usage unavailable' accounts recover (RUSH-3036).** After the 20-min probe throttle shipped, four of eight Claude accounts still showed `usage unavailable`: the 429 backoff was per-PROVIDER, so the first account to hit its quota in a refresh pass parked `claude` entirely and every account after it in the loop's fixed iteration order was never fetched — the same accounts starved every pass. The backoff is now scoped per account (`usage-backoff.ts` records `claude@<usageKey>.<deadline>`; a provider-wide penalty still parks everyone, and callers with no account identity keep the old behavior). Second, the auth-health probe no longer spends a second request on the same endpoint: a fresh (≤20 min) successful usage snapshot is the same authenticated request with the same shared setup-token, so `probeAuthHealth` derives a `live` verdict from it and only fires a network probe when no fresh evidence exists — roughly halving fleet endpoint load. `agents devices ping --strict` passes `forceLive`, which skips the derivation entirely — its contract stays a genuinely live request that surfaces `revoked` immediately — and derivation additionally requires a local credential (`signedIn`), so a fleet-imported snapshot on an unsigned home never reads as `live`. The auth probes themselves are account-scoped too, so a probe 429 parks only its account. Source: `apps/cli/src/lib/usage-backoff.ts`, `apps/cli/src/lib/accounting/usage.ts` (`UsageOptions.usageScope`), `apps/cli/src/lib/auth-health.ts` (`verdictFromFreshUsage`), `apps/cli/src/lib/usage-refresh.ts`, `apps/cli/src/lib/daemon-ticks.ts`.
50
+
51
+ - **`agents menubar doctor` no longer claims a healthy just-upgraded helper is "running the OLD binary" (RUSH-3038).** The stale-process check compared a pid start time parsed from `ps -o lstart`, which prints whole **seconds**, against the installed bundle's sub-second mtime. `restartMenubarHelperAfterSwap` restarts the helper within the same second as the swap that triggered it, so a correct upgrade always tripped the strict `<`: on zion at 1.22.46 the pid started at `…353000` and the bundle was written at `…353700` — 700 ms apart, one second — and doctor reported the helper stale and told the user their Accessibility grant "may not be trusted", after an upgrade that had already restarted it onto the new binary. The bundle mtime is now truncated to the same whole second before comparing, so a pid that started in the swap's own second reads fresh while a pid a full second or more older is still caught. Source: `apps/cli/src/lib/menubar/install-menubar.ts`.
52
+
53
+ - **`agents run codex --mode auto` stops prompting for approval.** Codex declared only `plan`/`edit`/`skip`, so `--mode auto` silently degraded to `edit` — and `edit` is `approval_policy="on-request"`, which asks before every command the sandbox denies. Every unattended caller that passes `--mode auto` (AGI EXT's agent launches, teams teammates, routines) therefore sat on an approval dialog nobody was there to answer. Codex now has a real `auto`: the `agents-auto` permission profile, identical sandbox to `agents-edit` (workspace, `~/.agents`, the regenerable toolchain cache roots, network on), with `approval_policy="never"` — a sandbox-denied command surfaces to the model as a plain command failure it can work around instead of stopping the run. Autonomy is the approval axis only: `auto` does not widen the sandbox, and `--mode skip` remains the only mode that removes it. Interactive shim launches (a bare `codex` at your own terminal) still pin `edit`, where an approval prompt is the useful outcome. Source: `apps/cli/src/lib/codex-policy.ts`, `apps/cli/src/lib/harness/adapters/codex.ts`, `apps/cli/src/lib/agent-spec/agents.ts`, `apps/cli/src/lib/exec.ts`.
54
+
55
+ - **Hooks can be scoped to a permission mode: new `matches.permission_mode` predicate (RUSH-3050).** A `hooks.yaml` / subrule `hooks.yaml` entry may declare `matches: { permission_mode: plan }` (string or array) so the hook fires only when the harness reports that mode in the hook's stdin JSON (`permission_mode`, or Grok-style `permissionMode`). The predicate is deliberately fail-open on absence: a harness that never reports a mode (Codex, and most others — Claude Code is the one that does) keeps firing the hook, so declaring it never silently disables a hook fleet-wide. Enforced in both the TS reference evaluator (`shouldFire()`) and the generated shim gate, pinned together by the existing conformance suite. Motivating case: the plan-presentation Stop hook fired on every stop in every session and false-positived on ordinary answers that mentioned plans; it can now declare `permission_mode: plan`. Source: `apps/cli/src/lib/types.ts` (`HookMatches`), `apps/cli/src/lib/hooks/match.ts`, `apps/cli/src/lib/hooks/cache.ts`, `apps/cli/docs/hooks.md`.
56
+
57
+ - **New device config key `description` — a one-line, fleet-synced answer to
58
+ "what is this box FOR".** `agents devices config <name> description "gpu box
59
+ — cuda 12.4"` stores a single-line summary in the device's tracked
60
+ `~/.agents/devices/<name>/agents.yaml` under `config.description`, so it
61
+ syncs to every machine via `agents repo push/pull` exactly as `role` does,
62
+ and any box may set it for any device (`shared` visibility). Because it
63
+ will be shown by the device-list renderer it is validated: a newline is rejected outright and
64
+ the value is capped at 80 characters — over-long input fails with a readable
65
+ error naming the cap, never a silent truncation. `notes` is unchanged: it
66
+ stays the appended list of long-form operator scratch, and both key
67
+ descriptions now state the distinction. Source:
68
+ `apps/cli/src/lib/device-config.ts`.
69
+
70
+ - **Dismissing a discovered device is now a fleet-wide fact (RUSH-3062).** The ignore-list lived at `~/.agents/.history/devices/ignored.json` — a gitignored, per-machine path — so a node dismissed on one box kept re-surfacing as an auto-discovery suggestion on every other box. It now lives in the tracked, synced central `~/.agents/agents.yaml` under `fleet.ignored`, a list of `{ name, ignoredAt, ignoredOn }` entries (who dismissed it, when, on which box — the read side for a future `agents devices ignored`). An ignored node is deliberately not a device, so it has no per-device doc; central agents.yaml is the established home (it already carries `fleet.defaults`). Writes go through the existing `updateMeta` path (`withMetaLock` + atomic write), and a malformed `fleet.ignored` block is still a hard error rather than a silently-emptied set. A one-shot migration folds any existing `ignored.json` into `fleet.ignored` (union by name, legacy `updatedAt` kept as `ignoredAt`) and removes the legacy file only after the central write lands; running it twice is a no-op. The `loadIgnored` / `isIgnored` / `addIgnored` / `removeIgnored` signatures are unchanged, so no call site churn. Source: `apps/cli/src/lib/devices/registry.ts`, `apps/cli/src/lib/devices/config-migration.ts`, `apps/cli/src/lib/state.ts`.
71
+
72
+ ---
73
+ type: feat
74
+ ---
75
+
76
+ Collect root-disk capacity in the existing device health probe and cache static hardware specifications for seven days.
77
+
78
+ ---
79
+ type: feat
80
+ ---
81
+
82
+ Put real capacity in the default `agents devices list` — a `spec` cell (cores / total RAM / total disk), a `disk` used column beside load and mem, and the per-device `description` as the tail column (truncated first on narrow terminals, then role; the numbers never truncate). Add `agents devices describe <name> <text>` (task-shaped sugar over the `description` config key) and `agents devices ignored` (dismissed nodes — when, and which machine dismissed them). `devices list --json` gains `description` and disk totals inside `health` (additive only).
83
+
84
+ - **Interactive `agents run` now spawns directly by default (RUSH-3066).** `tmux.enabled` is an explicit per-device opt-in for addressable panes instead of the default wrapper: the wrap's benefit (a unique `%pane` so `agents sessions --active` can tell co-located agents apart, and `agents focus` re-attaching without forking) accrues to the control plane, while the cost — mouse, scrollback and clipboard behavior — is paid by whoever is at the terminal. Turn it back on per device with `agents config set devices.<name>.tmux on`. `--no-tmux` and `--disable-tmux` remain compatible no-ops while wrapping is off.
85
+
86
+ ---
87
+ type: fix
88
+ ---
89
+
90
+ Make opt-in tmux-wrapped runs default to mouse interaction, OSC 52 system clipboard integration, and 20,000 lines of scrollback while preserving the user's tmux configuration.
91
+
92
+ - **BREAKING: the top-level `agents usage` command is removed (RUSH-3079).** It was a second, worse surface for the same data `agents view` already renders — per-account quota/rate-limit usage with the account, version, and auth state beside it — and in practice most harnesses printed `stale` or "does not publish usage data" there. Use `agents view` (optionally `agents view <agent>`, `--refresh` for an explicit collection, `--json` for scripts). The name is retired: `agents usage` fails as an unknown command and never auto-corrects into a live command. The shared usage library behind `agents view` and rotation/backoff is untouched. Source: `apps/cli/src/commands/usage.ts` (deleted), `apps/cli/src/cli/command-registry.ts`, `apps/cli/src/lib/startup/command-registry.ts`.
93
+
94
+ - **Security: the remote browser-control consent gate now covers the whole launch path.**
95
+ `agents browser remote-control off` (the default) was only enforced on the
96
+ `browser start` command, but `navigate`, `click`, `screenshot`, `evaluate` and
97
+ the other page verbs open a browser implicitly when the caller has no live
98
+ task. A `browser navigate --device <box>` therefore opened a browser on a
99
+ machine whose owner never opted in, while `browser start --device <box>` was
100
+ correctly refused. The gate now sits in the daemon at the two points that can
101
+ launch a browser (`BrowserService.start` and the create branch of
102
+ `resolveOrCreateTask`), so every implicit-LAUNCH verb is covered. It does not
103
+ cover *attaching*: a request naming an existing task (`--task`, or the
104
+ single-match-by-caller path) returns before the gate and can drive that task's
105
+ tabs. That is pre-existing and tracked separately — `remote-control off` means
106
+ "no new browser", not "no access". The consent
107
+ marker rides the IPC request rather than the daemon's environment: a daemon
108
+ auto-started by a fleet-remote CLI inherits `AGENTS_FLEET_REMOTE=1`
109
+ permanently, and reading that would have refused every later local drive.
110
+ Source: `src/lib/browser/service.ts`, `src/lib/browser/remote-control.ts`,
111
+ `src/lib/browser/ipc.ts`, `src/lib/browser/types.ts`.
112
+
113
+ - **`agents browser profiles edit` and `profiles scope`.** An existing profile's
114
+ description, endpoints, secrets, viewport, and binary could not be changed
115
+ without deleting and recreating it — `-d/--description` existed only on
116
+ `create`, and `updateProfile()` had no CLI caller at all. `profiles edit <name>`
117
+ reuses `create`'s flag spellings (minus `-b/--browser` and `--fleet`, which key
118
+ the on-disk profile cache and the store) and validates the merged record, so a
119
+ binary edit re-resolves the browser path and a `--target-filter` edit re-checks
120
+ the `--electron` gate. `profiles scope <name> <local|fleet>` moves a profile
121
+ between the synced store and this machine.
122
+ Source: `src/lib/browser/profiles.ts`, `src/commands/browser.ts`.
123
+ - **`profiles doctor` flags a fleet profile with a loopback endpoint.** A
124
+ `--fleet` profile whose endpoint is `cdp://localhost:PORT` is evaluated on the
125
+ machine running the command, so the name resolved to a different browser on
126
+ every box — silently handing an agent a logged-out stranger instead of the
127
+ credentialed profile it asked for. Now a failing `scope` check naming the
128
+ repair. `ssh://` profiles are unaffected: they address a host, so fleet scope is
129
+ correct for them. Source: `src/lib/browser/profiles.ts` (`misfiledFleetProfile`).
130
+ - **Fixed: editing a profile's endpoint could collide with itself.** The local
131
+ port scan `createProfile` runs was never applied on update, and applying it
132
+ naively would have failed every edit against the profile's own stored port.
133
+ Extracted as `assertLocalPortFree(profile, { ignore })` and now used by both.
134
+ Source: `src/lib/browser/profiles.ts`.
135
+
136
+ - **`agents browser profiles rename <from> <to>`.** A profile could not be
137
+ renamed at all: `profiles edit` refuses a name change because the name keys the
138
+ on-disk runtime dir, every endpoint/fork dir derived from it, and the
139
+ `browser.profile` pointer. The only route was delete-and-recreate, which
140
+ silently abandons the browser's `--user-data-dir` — where a profile's logins
141
+ live. On a real agent browser that is gigabytes of session state and every
142
+ account it has ever signed into. `rename` moves the config (staying in whichever
143
+ store it already lives in), moves every cache dir belonging to the old name, and
144
+ repoints both `browser.profile` and `browser.viewer` when either pointed there — a dangling `browser.viewer` sends every artifact back to the OS default handler, which is the exact bug the viewer seam was built to fix. Refuses while the profile is in
145
+ use, because moving a `--user-data-dir` out from under a running browser
146
+ corrupts it; refuses when the name exists in BOTH stores, since rewriting one
147
+ would leave the other listed under the old name with its data already moved
148
+ away; and validates every destination BEFORE moving any of them, so a
149
+ collision on the second endpoint cannot strand the first one's logins under a
150
+ name with no config entry. `os` joins `default` as a name a profile may not
151
+ take — it is the reserved `browser.viewer` value meaning the OS handler. Source: `src/lib/browser/profiles.ts`, `src/commands/browser.ts`.
152
+ - **Profile-name validation is shared between `create` and `rename`.** The shape
153
+ rule lived inline in `profiles create`, so a second caller would have accepted
154
+ names `create` rejects. Now `assertRegistrableProfileName`, which also refuses
155
+ `default` — the reserved alias meaning "this machine's configured profile"
156
+ (RUSH-2709), not a name. Source: `src/lib/browser/profiles.ts`.
157
+
158
+ - **User-facing pages open in your configured browser profile, not the OS
159
+ default.** `agents browser navigate` honoured `browser.profile` and nothing
160
+ else did: `agents fleet login`, `agents devices lease`, `agents feedback`,
161
+ `agents sessions trace --open`, and `agents browser sessions --open` each
162
+ shelled straight to `open`/`xdg-open`, so every one of them landed in whatever
163
+ the OS handler happened to be — on a Mac with Arc set as default, all of them
164
+ opened in Arc while the configured Comet profile sat unused. They now route
165
+ through one seam (`showUrl`/`showFile`), which resolves the viewer once.
166
+ This matters beyond tidiness: the configured profile is where the fleet's
167
+ logins accumulate, so a page opened there is one you are already signed in for,
168
+ and a login it acquires is inherited by every later agent.
169
+ The seam does not auto-start the browser daemon: showing a page is a side
170
+ errand, so blocking it on a cold start would be a surprising stall. Daemon
171
+ already running -> the viewer; not running -> the OS handler.
172
+ Source: `src/lib/open-url.ts`.
173
+ - **New `browser.viewer` config key** (device scope) — a profile name, or `os`
174
+ to keep using the OS default handler. Unset follows `browser.profile`.
175
+ Deliberately distinct from `browser.profile`: one is the profile agents drive,
176
+ the other is the browser that shows you a page. Source: `src/lib/device-config.ts`.
177
+ - **New `show` IPC action** — opens a tab bound to no task, so the abandoned-task
178
+ reaper never closes a page you are reading. That is the whole reason it is not
179
+ `navigate`. Screenshots, PDFs and recordings still go to the OS app, where
180
+ Preview and QuickTime are the better viewer.
181
+ Source: `src/lib/browser/service.ts`, `src/lib/browser/ipc.ts`.
182
+ - **New `agents browser show <url|file>`** — the CLI entry point to that seam, so
183
+ external tools (a renderer's `--open`, a script) can show a page in the
184
+ configured profile instead of shelling to `open`. Use it instead of `navigate`
185
+ for anything a person will read: `navigate` binds a task and the reaper closes
186
+ a task's tabs. `--os-browser` forces the OS handler; `--json` reports where it
187
+ landed. Source: `src/commands/browser.ts`.
188
+
189
+ - **`--device interactive` resolves to the machine the human is at.** `--device
190
+ auto` picks a box by load; this picks the one box someone is actually looking
191
+ at, pinned as `interactive.host`. It resolves in the shared host
192
+ matcher rather than per command, so `browser`, `run`, `sessions` and `secrets`
193
+ inherit it; `teams` and `ssh` resolve it explicitly because they leave the
194
+ fleet passthrough before the matcher runs. A few narrower `--device` surfaces
195
+ do not consult the matcher. None of them mis-routes: most fail loud, and
196
+ `devices harnesses` filters to an empty result. Wiring them up is a follow-up.
197
+ It exists because a skill cannot teach a host name: guidance that says
198
+ "deliver it to <box>" is wrong on every other fleet and stale the moment the
199
+ pin changes, so agents were left inferring the target or skipping the step. A
200
+ fixed token is something documentation can state literally and have be correct
201
+ everywhere.
202
+ When no host is pinned it refuses and names the command that fixes it, rather
203
+ than falling back to the local machine — running on a headless worker with
204
+ nobody watching is the exact failure the sentinel prevents, and it would fail
205
+ invisibly. Source: `src/lib/devices/interactive-host.ts`.
206
+
207
+ - **`agents sessions stop <id>` ends a live agent outright, and a tmux-wrapped agent no longer leaves an orphaned dead session behind (graceful shutdown, #5a/#5b).** Two halves of one gap — a single close should tear down every layer (agent → tmux mux → tab):
208
+ - New verb `agents sessions stop <id>` on the session-lifecycle axis (beside `detach`/`attach`): it stops the interactive process and tears down its tmux/mux session — reusing `detach`'s exact `stopInteractive` teardown (`kill-session` when tmux-hosted, else SIGTERM→SIGKILL the pid) and resolution (remote sessions stopped over SSH, cloud/team refused) — but does NOT resume it headless. Use `detach` to keep an agent working unattended, `stop` when the work is over. AGI EXT calls it when a user genuinely closes an agent tab so the agent + mux shut down instead of lingering idle. Source: `apps/cli/src/commands/sessions-stop.ts`.
209
+ - The tmux-wrap `pane-died` hook is now `session_attached`-aware (`AGENT_HOOK_SCHEMA` v6): with a client attached it `detach-client`s as before (so `resolveAfterAttach` reads the exit status, EXEC-23b unchanged); with **no** client attached it `kill-session`s outright. A wrapped agent that exits unattended — a closed terminal, or a `/exit` after the user detached — previously left a dead `remain-on-exit` husk on the socket until the daemon's periodic reap, showing as an orphaned idle session. Source: `apps/cli/src/lib/tmux/session.ts`, `apps/cli/src/lib/exec.ts`.
210
+
211
+ ---
212
+ type: fix
213
+ ---
214
+
215
+ `agents devices capture` no longer wipes `fleet.ignored` — the captured manifest carries device dismissals forward instead of rebuilding the fleet block without them.
216
+
217
+ ---
218
+ type: feat
219
+ ---
220
+
221
+ Feed attention is now modeled as an explicit lifecycle the CLI reconciles, the foundation for a feed-driven Needs-You surface. `OpenBlock` carries `generation`/`source`/`state`/`sourceCursor` (back-compatible — derived for existing blocks), the answer/continue/clear paths write a resolution tombstone before the block clears so a resolved ask can no longer silently resurrect, and a new pure `reconcileAttention` merges the open-block ledger, session lifecycle, and a CLI-supplied PR signal into one canonical `AttentionItem`.
222
+
223
+ - **Stream and answer the canonical operator feed.** `agents feed watch --json`
224
+ now emits one versioned agents, attention, activity, and scope projection for
225
+ thin clients, including retained peer rows across disconnects. `agents feed
226
+ answer <attention-key>` atomically claims the first answer and routes it over
227
+ the recorded reply rail; concurrent losers return `already_answered` without
228
+ injecting twice. Pull-request attention is refreshed by the CLI on a bounded
229
+ TTL. Source: `apps/cli/src/lib/feed/{watch,answer,pr-status}.ts`.
230
+
231
+ - **`agents auth` help no longer claims plan tiers.** The command's description
232
+ now reads "the account layer behind team spaces" — there are no plan tiers —
233
+ and its help notes state that signing in is optional: every local feature
234
+ works with no account, and team spaces are the one thing an account unlocks.
235
+ READMEs and docs updated to match, and license references now name
236
+ FSL-1.1-Apache-2.0. Source: `apps/cli/src/commands/auth.ts`.
237
+
238
+ - **New hook predicate `matches.permission_mode_not` — gate a hook OFF in one
239
+ mode without enumerating every other one.** The existing `permission_mode` is
240
+ an allowlist, so "run everywhere except plan mode" had to be spelled as a list
241
+ of every other mode — and that list silently stops matching the moment a
242
+ harness adds or renames one, which for a guard means it quietly stops
243
+ guarding. The new predicate names the mode to skip instead, so an unknown mode
244
+ still fires: the failure direction is "ran unnecessarily", never "did not
245
+ run". Same fail-open-on-absence rule as its positive twin (a harness that
246
+ reports no mode keeps firing), reads both `permission_mode` and Grok's
247
+ camelCase `permissionMode`, and ANDs with the positive form when both are
248
+ declared. Motivation, measured from `~/.agents/.cache/perf/perf.db`: nine
249
+ guards fire on **every** `Bash` tool call for a combined 292 ms before the
250
+ command runs, across 285,667 recorded fires of which 284 (0.099%) changed the
251
+ outcome — and four of them (`merge-guard`, `pr-description-reminder`,
252
+ `large-file-add-guard`, `git-require-clean-tree`) cannot fire meaningfully
253
+ during a planning turn. Source: `apps/cli/src/lib/hooks/match.ts`,
254
+ `apps/cli/src/lib/types.ts`, `apps/cli/docs/hooks.md`.
255
+
256
+ - **New versions are licensed FSL-1.1-Apache-2.0.** Use, modification, and redistribution remain free for every user. Offering agents-cli as a competing commercial product or service is barred. Each version converts to Apache-2.0 two years after it is made available. Already-shipped Apache-2.0 versions are unchanged. Source: `LICENSE`, `apps/cli/LICENSE`.
257
+
258
+ ---
259
+ type: fix
260
+ ---
261
+
262
+ AGI Menu no longer re-prompts for Accessibility on dev machines, and the clip-paste hotkey (Cmd-Shift-V) no longer depends on the grant at all. A locally-built (ad-hoc) menu-bar helper now signs under a distinct `com.phnx-labs.agents-menubar.dev` bundle id, so it can never poison the shipped app's Accessibility grant (macOS keys the grant to the bundle id and revokes it when a same-id binary fails the stored Developer-ID code requirement). An ad-hoc build also can no longer overwrite a healthy Developer-ID install when the recorded owner path vanishes. A release now hard-fails if the shipped helper's designated requirement ever drops the pinned bundle id or Developer ID team, since that would silently revoke every user's grant on upgrade. And when the grant is missing, Cmd-Shift-V now silently copies the `host:path` reference to the clipboard (press Cmd-V) instead of re-showing the system permission modal on every paste — auto-type stays on only where Accessibility is already granted.
263
+
264
+ - **A release no longer needs `main` to hold still — publish is decoupled from live `main` (RUSH-2395 audit).** `release.sh` used to squash-merge the release PR into `origin/main` and then refuse to publish unless `main`'s tree byte-matched the attested release tree — so any commit that landed on `main` during the release (or a `CHANGELOG` merge conflict) killed it, forcing a ~15-minute quiet window that a busy fleet rarely offers. It now **tags and publishes the attested release commit itself** — the exact tree CI attested and the tarball was packed from — and merges the version-bump PR **asynchronously, after publish, best-effort**. The published bytes are the attested tree by construction, so `main` can churn freely and the bump-merge can be deferred or hand-resolved without ever wedging the release. The attestation of the release-commit tree remains the sole functional gate; the tag push and publish routing stay lease-gated. The catch-up recovery path (registry behind a `main` already at the target version) is unchanged. Source: `apps/cli/scripts/release.sh`.
265
+
266
+ - **`agents sessions trace` compares two sessions.** Pass exactly two selectors and the same command renders a **compare**: the two sessions' tool sequences aligned by tool name, the first divergence point (where the runs' tool order stops lining up), the steps each session ran that the other never did, and a per-session summary — in the same three renderings (HTML with stacked lanes on a shared time axis, compact text, and `--json` with `layout: 'compare'`). Three or more selectors, or `--tree`, still fail loud — lineage (a parent + its team) lands in a follow-up PR. Source: `apps/cli/src/lib/session/trajectory-compare.ts`, `apps/cli/src/commands/sessions-trace.ts`.
267
+
268
+ - **`agents sessions trace <id> --tree` renders a team's lineage.** The third layout of the trace surface, after the single trajectory and the two-session compare: the selected session and every session it spawned, drawn as a delegation graph. The edges are read from the session index, not inferred — a teammate's `meta.json` `parent_session_id` (`teamOrigin.parentSessionId`), with the team's agreed-on spawner (`groupSessionsByTeam().spawnerSessionId`) filling in for a teammate whose own record names none, bounded to that run's own spawn window so a second run of the same team name never adopts the first run's teammates; the edge carries which record established it. A node is always a real session: an inline `Task`/`Agent` sub-agent is a step inside one transcript and produces no session, so it is never drawn as a node. Each node carries its handle, harness, role, indexed tool count, span, PR number, and a recency class (`active`/`idle`/`stale`) — recency, not a success verdict, because nothing on a session row records whether the work landed. HTML draws a self-contained inline-SVG graph with clickable per-node summaries; `--text` prints an indented tree; `--json` emits `layout: 'lineage'` with a `lineage: { rootId, nodes, edges, teams, unresolvedParentIds }` block plus the root's trajectory. Selecting a child roots the graph at its topmost ancestor, so the whole team is always shown; a referenced parent outside the scanned pool is reported rather than dropped. Source: `apps/cli/src/lib/session/trajectory-lineage.ts`, `apps/cli/src/lib/session/trajectory-html.ts`, `apps/cli/src/lib/session/trajectory-text.ts`, `apps/cli/src/commands/sessions-trace.ts`.
269
+
270
+ - **`agents sessions trace` v2 — a real session debugger, program-aware.** The HTML view is rebuilt from a wall-clock waterfall (which crammed all activity into a sliver on long, idle-gappy sessions) into an **analysis hero** — where the time went, the slowest steps, the command/program mix, and error/idle KPIs — over a **readable, execution-ordered step list** with expandable output and clean idle-gap dividers. Every shell step is labeled by the **effective program** it ran (`git`, `gh`, `agents`, `bun`, `sed`… via the shared `extractShellPrograms` parser; `sudo`/`env`/`agents ssh` unwrapped, bare `cd`/`export` skipped) across **every harness's shell tool** — Claude's `Bash`, Codex's `exec_command`, `run_shell_command`, `shell`, `Execute` — so the mix reads `git 94 · agents 81 · gh 75` instead of "Bash 98%". Process **exit codes** show on failures. The "where the time went" share is now keyed by program in **both** the HTML and `--text` renderers off one model field — a Bash-heavy run reads `git 56% · gh 33% · agents 11%`, never `Bash 100%`. `--text` and the `--json` step model gain additive `program` + `exitCode` fields, and the trajectory's `toolTimeShare` is renamed `programTimeShare` (program-keyed) in the `--json` envelope. Source: `apps/cli/src/lib/session/trajectory.ts`, `trajectory-html.ts`, `trajectory-text.ts`.
271
+
272
+ - **`agents sessions trace` (alias `agents trace`) — visualize a session's trajectory.** A tool-call waterfall over a real time axis (durations, errors, idle stalls, delegations) instead of scrolling the Markdown wall. One `buildTrajectory()` model, rendered three ways and auto-selected by audience: an interactive HTML page on your interactive host for a person, a compact token-bounded text trajectory for an agent (`--text`, `--errors-only`), and the versioned `sessions-trace` JSON envelope (`--json`) for tools. Single-session in this release; multi-session compare and team lineage follow. Redacted by default, self-contained HTML (no CDN). Source: `apps/cli/src/commands/sessions-trace.ts`, `apps/cli/src/lib/session/trajectory.ts`.
273
+
274
+ - **`agents view` stops printing "usage unavailable" for a harness that reports a plan and no meters.** Grok's collector writes a subscription tier with no usage windows (`{plan: 'SuperGrok Heavy', windows: []}`), and the cache deserializer treated "no fresh windows" as "nothing cached" — so `--refresh` rendered `SuperGrok Heavy`, the very next plain `agents view grok` rendered `usage unavailable`, and reading the row also **deleted** it. Both grok accounts were permanently stuck in the wrong state because the daemon's periodic refresh re-wrote a row that the next read destroyed. A cached row that carries a plan now survives with no windows; a row with no windows, no plan, and no refusal is still dropped, so an all-expired snapshot keeps pruning (RUSH-2858) and a meterless row can never read as a 0% bar or an `available` badge — `deriveUsageStatusFromSnapshot` still returns null for zero windows. Routing keeps the same guarantee from the other side: a windowless snapshot no longer counts as verified usage, so a meterless pool still spreads across its accounts instead of pinning to whichever one ran most recently. Source: `apps/cli/src/lib/accounting/usage.ts`, `apps/cli/src/lib/accounting/rotate.ts` (RUSH-3060).
275
+
276
+ ---
277
+ type: feat
278
+ ---
279
+
280
+ The watchdog decider is now an agent, not a heuristic script. Every idle session on the machine (its originating task + transcript tail) is handed to ONE `agents run --mode plan` call per tick, which judges each: idle-but-unfinished → nudge that drives it to finish; idle-and-done or genuinely-needs-human → skip. The deterministic pre-filter (`isLikelyTrulyBlocked`, completion/promise regex) and the per-session LLM spawn are gone — one bounded call per tick, only when something is actually idle. A nudge is booked in the cooldown ledger and logged `nudge` ONLY when delivery is confirmed; tmux/iterm/pty self-confirm, while vscodium's fire-and-forget `--open-url` is recorded `undelivered` until the swarm-ext extension acks the verb, ending the phantom-nudge ledger. `agents watchdog history` gains an `undelivered` row; the `--smart` flag is removed (the agent is always the decider). Defaults stay OFF.
281
+
3
282
  ## 1.22.46
4
283
 
5
284
  - **`agents auth` returns, against Phoenix ID instead of a sibling product's backend (RUSH-2581).** 1.22.45 removed the account layer that authenticated against Rush's `api.prix.dev`. It comes back pointed at **Phoenix ID** (`phnx-labs/phoenix-id`), agents-cli's own account service: `agents auth login` runs a device-code flow whose browser page is Phoenix-branded and Google-only, `agents auth whoami` reports the signed-in account, `agents auth logout` clears **this machine** and nothing else, and the team surface nests as `agents auth space` (`list`/`create`/`members`/`invite`/`role`/`remove`). Everything goes through one new seam, `lib/identity/` — one base URL (`PHOENIX_ID_BASE`), one session file, one HTTP funnel, one error type — replacing the shape that had the backend URL hardcoded in five files and the session token re-read by seven separate functions. agents-cli reads no other product's credentials: there is no `~/.rush/user.yaml` fallback. Source: `apps/cli/src/lib/identity/{client,index}.ts`, `apps/cli/src/commands/auth.ts`.
package/LICENSE CHANGED
@@ -1,185 +1,105 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction, and
10
- distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by the copyright
13
- owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all other entities
16
- that control, are controlled by, or are under common control with that entity.
17
- For the purposes of this definition, "control" means (i) the power, direct or
18
- indirect, to cause the direction or management of such entity, whether by
19
- contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
- outstanding shares, or (iii) beneficial ownership of such entity.
21
-
22
- "You" (or "Your") shall mean an individual or Legal Entity exercising
23
- permissions granted by this License.
24
-
25
- "Source" form shall mean the preferred form for making modifications, including
26
- but not limited to software source code, documentation source, and configuration
27
- files.
28
-
29
- "Object" form shall mean any form resulting from mechanical transformation or
30
- translation of a Source form, including but not limited to compiled object code,
31
- generated documentation, and conversions to other media types.
32
-
33
- "Work" shall mean the work of authorship, whether in Source or Object form,
34
- made available under the License, as indicated by a copyright notice that is
35
- included in or attached to the work (an example is provided in the Appendix
36
- below).
37
-
38
- "Derivative Works" shall mean any work, whether in Source or Object form, that
39
- is based on (or derived from) the Work and for which the editorial revisions,
40
- annotations, elaborations, or other modifications represent, as a whole, an
41
- original work of authorship. For the purposes of this License, Derivative Works
42
- shall not include works that remain separable from, or merely link (or bind by
43
- name) to the interfaces of, the Work and Derivative Works thereof.
44
-
45
- "Contribution" shall mean any work of authorship, including the original
46
- version of the Work and any modifications or additions to that Work or
47
- Derivative Works thereof, that is intentionally submitted to Licensor for
48
- inclusion in the Work by the copyright owner or by an individual or Legal Entity
49
- authorized to submit on behalf of the copyright owner. For the purposes of this
50
- definition, "submitted" means any form of electronic, verbal, or written
51
- communication sent to the Licensor or its representatives, including but not
52
- limited to communication on electronic mailing lists, source code control
53
- systems, and issue tracking systems that are managed by, or on behalf of, the
54
- Licensor for the purpose of discussing and improving the Work, but excluding
55
- communication that is conspicuously marked or otherwise designated in writing by
56
- the copyright owner as "Not a Contribution."
57
-
58
- "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
59
- of whom a Contribution has been received by Licensor and subsequently
60
- incorporated within the Work.
61
-
62
- 2. Grant of Copyright License. Subject to the terms and conditions of this
63
- License, each Contributor hereby grants to You a perpetual, worldwide,
64
- non-exclusive, no-charge, royalty-free, irrevocable copyright license to
65
- reproduce, prepare Derivative Works of, publicly display, publicly perform,
66
- sublicense, and distribute the Work and such Derivative Works in Source or
67
- Object form.
68
-
69
- 3. Grant of Patent License. Subject to the terms and conditions of this License,
70
- each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
71
- no-charge, royalty-free, irrevocable (except as stated in this section) patent
72
- license to make, have made, use, offer to sell, sell, import, and otherwise
73
- transfer the Work, where such license applies only to those patent claims
74
- licensable by such Contributor that are necessarily infringed by their
75
- Contribution(s) alone or by combination of their Contribution(s) with the Work
76
- to which such Contribution(s) was submitted. If You institute patent litigation
77
- against any entity (including a cross-claim or counterclaim in a lawsuit)
78
- alleging that the Work or a Contribution incorporated within the Work
79
- constitutes direct or contributory patent infringement, then any patent licenses
80
- granted to You under this License for that Work shall terminate as of the date
81
- such litigation is filed.
82
-
83
- 4. Redistribution. You may reproduce and distribute copies of the Work or
84
- Derivative Works thereof in any medium, with or without modifications, and in
85
- Source or Object form, provided that You meet the following conditions:
86
-
87
- (a) You must give any other recipients of the Work or Derivative Works a copy of
88
- this License; and
89
-
90
- (b) You must cause any modified files to carry prominent notices stating that
91
- You changed the files; and
92
-
93
- (c) You must retain, in the Source form of any Derivative Works that You
94
- distribute, all copyright, patent, trademark, and attribution notices from the
95
- Source form of the Work, excluding those notices that do not pertain to any part
96
- of the Derivative Works; and
97
-
98
- (d) If the Work includes a "NOTICE" text file as part of its distribution, then
99
- any Derivative Works that You distribute must include a readable copy of the
100
- attribution notices contained within such NOTICE file, excluding those notices
101
- that do not pertain to any part of the Derivative Works, in at least one of the
102
- following places: within a NOTICE text file distributed as part of the
103
- Derivative Works; within the Source form or documentation, if provided along
104
- with the Derivative Works; or, within a display generated by the Derivative
105
- Works, if and wherever such third-party notices normally appear.
106
-
107
- The contents of the NOTICE file are for informational purposes only and do not
108
- modify the License. You may add Your own attribution notices within Derivative
109
- Works that You distribute, alongside or as an addendum to the NOTICE text from
110
- the Work, provided that such additional attribution notices cannot be construed
111
- as modifying the License.
112
-
113
- You may add Your own copyright statement to Your modifications and may provide
114
- additional or different license terms and conditions for use, reproduction, or
115
- distribution of Your modifications, or for any such Derivative Works as a whole,
116
- provided Your use, reproduction, and distribution of the Work otherwise complies
117
- with the conditions stated in this License.
118
-
119
- 5. Submission of Contributions. Unless You explicitly state otherwise, any
120
- Contribution intentionally submitted for inclusion in the Work by You to the
121
- Licensor shall be under the terms and conditions of this License, without any
122
- additional terms or conditions. Notwithstanding the above, nothing herein shall
123
- supersede or modify the terms of any separate license agreement you may have
124
- executed with Licensor regarding such Contributions.
125
-
126
- 6. Trademarks. This License does not grant permission to use the trade names,
127
- trademarks, service marks, or product names of the Licensor, except as required
128
- for reasonable and customary use in describing the origin of the Work and
129
- reproducing the content of the NOTICE file.
130
-
131
- 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
132
- writing, Licensor provides the Work (and each Contributor provides its
133
- Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
134
- KIND, either express or implied, including, without limitation, any warranties or
135
- conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
136
- PARTICULAR PURPOSE. You are solely responsible for determining the
137
- appropriateness of using or redistributing the Work and assume any risks
138
- associated with Your exercise of permissions under this License.
139
-
140
- 8. Limitation of Liability. In no event and under no legal theory, whether in
141
- tort (including negligence), contract, or otherwise, unless required by
142
- applicable law (such as deliberate and grossly negligent acts) or agreed to in
143
- writing, shall any Contributor be liable to You for damages, including any
144
- direct, indirect, special, incidental, or consequential damages of any character
145
- arising as a result of this License or out of the use or inability to use the
146
- Work (including but not limited to damages for loss of goodwill, work stoppage,
147
- computer failure or malfunction, or any and all other commercial damages or
148
- losses), even if such Contributor has been advised of the possibility of such
149
- damages.
150
-
151
- 9. Accepting Warranty or Additional Liability. While redistributing the Work or
152
- Derivative Works thereof, You may choose to offer, and charge a fee for,
153
- acceptance of support, warranty, indemnity, or other liability obligations
154
- and/or rights consistent with this License. However, in accepting such
155
- obligations, You may act only on Your own behalf and on Your sole
156
- responsibility, not on behalf of any other Contributor, and only if You agree to
157
- indemnify, defend, and hold each Contributor harmless for any liability incurred
158
- by, or claims asserted against, such Contributor by reason of your accepting any
159
- such warranty or additional liability.
160
-
161
- END OF TERMS AND CONDITIONS
162
-
163
- APPENDIX: How to apply the Apache License to your work.
164
-
165
- To apply the Apache License to your work, attach the following boilerplate
166
- notice, with the fields enclosed by brackets "[]" replaced with your own
167
- identifying information. (Don't include the brackets!) The text should be
168
- enclosed in the appropriate comment syntax for the file format. We also
169
- recommend that a file or class name and description of purpose be included on
170
- the same "printed page" as the copyright notice for easier identification
171
- within third-party archives.
172
-
173
- Copyright [yyyy] [name of copyright owner]
174
-
175
- Licensed under the Apache License, Version 2.0 (the "License");
176
- you may not use this file except in compliance with the License.
1
+ # Functional Source License, Version 1.1, Apache 2.0 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-Apache-2.0
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Phoenix Horizon, Inc.
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
177
98
  You may obtain a copy of the License at
178
99
 
179
- http://www.apache.org/licenses/LICENSE-2.0
100
+ http://www.apache.org/licenses/LICENSE-2.0
180
101
 
181
- Unless required by applicable law or agreed to in writing, software
182
- distributed under the License is distributed on an "AS IS" BASIS,
183
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
184
- See the License for the specific language governing permissions and
185
- limitations under the License.
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.