agent-embassy 4.4.0 → 4.4.1

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,11 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
6
 
7
+ ## [4.4.1] - 2026-09-06
8
+
9
+ ### Changed
10
+ - Documentation describes the current product; historical scaffolding removed.
11
+
7
12
  ## [4.4.0] - 2026-09-06
8
13
 
9
14
  ### Changed
package/CONTRIBUTING.md CHANGED
@@ -21,7 +21,7 @@ and must never run in CI.
21
21
 
22
22
  ## Core shape
23
23
 
24
- Keep changes inside the v4 architecture:
24
+ Keep changes inside the shipped architecture:
25
25
 
26
26
  - `ledger.ts` owns pure synchronous state transitions;
27
27
  - `owned-state.ts` owns private atomic persistence;
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Embassy
2
2
 
3
- Embassy lets live Claude Code sessions and Codex CLI tasks message one another
3
+ Embassy lets live Claude Code sessions and Codex CLI agents message one another
4
4
  by name, on one Mac or across user-owned Macs reached through SSH. The broker
5
5
  wakes the receiving agent through its native interface; agents do not poll.
6
6
  Claude→Claude, Claude→Codex, Codex→Claude, and Codex→Codex all use the same
@@ -15,15 +15,17 @@ identity, so a rename or replacement never silently retargets queued work.
15
15
 
16
16
  - macOS and Node.js 22 or newer.
17
17
  - Claude Code installed for the Claude sessions you use.
18
- - To receive in Codex, use its managed standalone installation with its App
19
- Server daemon already running under the same macOS login. Embassy discovers
20
- its 20 most recent unarchived root agents automatically, but does not install, start or
21
- update that daemon; merely having a `codex` executable on PATH is
18
+ - To receive in Codex, its managed standalone installation with the App Server
19
+ daemon already running under the same macOS login. Embassy discovers the
20
+ 20 most recent unarchived root agents automatically, but does not install,
21
+ start or update that daemon; merely having a `codex` executable on PATH is
22
22
  insufficient.
23
23
  - A private `nodes.json` when choosing an explicit host name or federating;
24
24
  first single-machine boot creates one from the short hostname.
25
25
  - Key-based, non-interactive SSH between configured machines when federating.
26
26
 
27
+ ## Install
28
+
27
29
  Install one copy with one package manager and verify what the shell resolves:
28
30
 
29
31
  ```sh
@@ -32,94 +34,119 @@ which -a embassy
32
34
  embassy --version
33
35
  ```
34
36
 
35
- The launchd service records the absolute installation path used by
36
- `embassy service install`. After replacing or removing that installation, run
37
- the install command again.
38
-
39
- `embassy service install` starts the per-user launchd agent immediately and
40
- arranges login startup; use the same command to reload broker configuration or
41
- start a stopped installation, and use `embassy service uninstall` to stop and
42
- unload it.
37
+ ## Start the broker
43
38
 
44
- The agent uses launchd's crash-only keepalive policy. A
45
- verified `SIGABRT` crash relaunches it. A clean exit, boot refusal, `SIGTERM`,
46
- or deliberate `kill -9` leaves it stopped; inspect `embassy service status`
47
- and run `embassy service install` deliberately rather than assuming every
48
- signal restarts it.
49
-
50
- ## Quickstart
39
+ ```sh
40
+ embassy service install
41
+ embassy health
42
+ ```
51
43
 
52
- For an explicit host name or federation, create `nodes.json` before starting
53
- the broker. `host` is this machine's name; `nodes` lists directly reachable
54
- Embassy hosts.
44
+ `embassy service install` starts the per-user launchd agent immediately and
45
+ arranges login startup; run the same command again to reload broker
46
+ configuration, to start a stopped installation, or after replacing or removing
47
+ the installation (the service records the absolute installation path). Use
48
+ `embassy service uninstall` to stop and unload it. `embassy serve` is the
49
+ foreground alternative.
50
+
51
+ The agent uses launchd's crash-only keepalive policy. A verified `SIGABRT`
52
+ crash relaunches it. A clean exit, boot refusal, `SIGTERM`, or deliberate
53
+ `kill -9` leaves it stopped; inspect `embassy service status` and run
54
+ `embassy service install` deliberately rather than assuming every signal
55
+ restarts it.
56
+
57
+ `health` means the Embassy control socket and ledger respond. It is not a
58
+ provider readiness proof: it does not show that any Claude session or Codex
59
+ task can receive or answer a message.
60
+
61
+ ### Host name and state directory
62
+
63
+ Every local alias ends in `@host`, where `host` is the value in `nodes.json`.
64
+ On first single-machine boot without that file, Embassy derives a lower-case
65
+ name from the short hostname and atomically writes an empty-node inventory; it
66
+ never rewrites a present file. Read `host` from that file and use it as every
67
+ local `@host` suffix; the examples use `@studio` only because they chose
68
+ `host: studio`.
69
+
70
+ To choose an explicit host name or to federate, create `nodes.json` before
71
+ starting the broker. `host` is this machine's name; `nodes` lists directly
72
+ reachable Embassy hosts:
55
73
 
56
74
  ```json
57
75
  {"version":1,"host":"studio","nodes":[]}
58
76
  ```
59
77
 
60
- `nodes.json` lives inside `EMBASSY_STATE_DIR` when set; otherwise it lives in
78
+ `nodes.json` lives inside `EMBASSY_STATE_DIR` when set; otherwise in
61
79
  `$XDG_STATE_HOME/agent-embassy`, or `~/.local/state/agent-embassy` when
62
- `XDG_STATE_HOME` is unset; every client shell must use the same state-directory
63
- configuration captured by the installed service. Create the private state
64
- directory before saving the example, and set directory mode 0700 and
65
- `nodes.json` mode 0600 before installing the service.
66
-
67
- The file must be owned by the current user, mode 0600, inside the private
68
- mode-0700 state directory. If it is absent on first single-machine boot, Embassy derives a
69
- lower-case name from the short hostname and atomically writes the equivalent
70
- empty-node file. It never rewrites a present inventory.
80
+ `XDG_STATE_HOME` is unset. Create the private state directory first, set it to
81
+ mode 0700 and `nodes.json` to mode 0600, and install the service afterwards.
82
+ Every client shell must use the same state-directory configuration captured by
83
+ the installed service.
71
84
 
72
- Install the supervised broker:
85
+ ## See the agents
73
86
 
74
87
  ```sh
75
- embassy service install
76
- embassy health
88
+ embassy tui # the daily view
89
+ embassy status # one text snapshot
77
90
  ```
78
91
 
79
- Global npm installation includes `skills/embassy-peer` under the
80
- `agent-embassy` package in `npm root -g`; the operator can copy that entire
81
- folder into `~/.codex/skills/` and `~/.claude/skills/`, then ask each agent to
82
- use it, or provide the shown commands directly to the agent's shell tool.
92
+ `embassy tui` is the daily view: an Ink-based terminal client (Node 22+) that
93
+ shows the local broker and each direct host in `nodes.json`, with endpoints
94
+ grouped by state, deliveries newest first, retirements, and action results.
95
+ `embassy status` prints the same snapshot once as text.
83
96
 
84
- Read `host` from the `nodes.json` that first boot created and use it as every
85
- local `@host` suffix; the examples use `@studio` only when you explicitly chose
86
- `host: studio`, not as a universal alias suffix.
97
+ Codex agents appear automatically. Embassy observes the same-user Codex App
98
+ Server daemon and lists its 20 most recent unarchived root agents by their
99
+ current public names; dormant agents remain addressable and wake on delivery.
100
+ Only head agents are endpoints: sub-agents are never discovered or displayed.
101
+ Native task IDs, previews and history never appear in Embassy output. If no
102
+ Codex agent appears, check that the Codex daemon is running under this login;
103
+ Embassy never starts it.
87
104
 
88
- The 20 most recent Codex root agents appear automatically from the same-user App Server daemon. Run
89
- `embassy status` to see their current public names; dormant agents remain
90
- addressable and wake on delivery. Native task IDs, previews and history never
91
- appear in Embassy output.
105
+ Claude sessions are discovered and recorded by exact native identity when a
106
+ Claude caller sends or when a named Claude target is resolved. No helper or
107
+ native advertisement process is installed. To find a Claude session's current
108
+ name, run `embassy refresh` (authorized live discovery) followed by
109
+ `embassy status --json`, or use the exact current name that session supplies.
92
110
 
93
- For a harness without native daemon integration, ask the live Codex CLI task
94
- to execute this fallback registration through its shell tool; an ordinary
111
+ For a harness without native daemon integration, registration is the fallback.
112
+ Ask the live Codex CLI task to run this through its own shell tool; an ordinary
95
113
  terminal lacks that task's inherited identity:
96
114
 
97
115
  ```sh
98
116
  embassy register-codex --alias codex-reviewer@studio
99
117
  ```
100
118
 
101
- Claude sessions are discovered and recorded by exact native identity when a
102
- Claude caller sends or when a named Claude target is resolved. No helper or
103
- native advertisement process is installed.
119
+ The `skills/embassy-peer` folder ships in the `agent-embassy` package under
120
+ `npm root -g`. Copy that entire folder into `~/.codex/skills/` and
121
+ `~/.claude/skills/` and ask each agent to use it, or hand the agent the commands
122
+ shown here directly.
123
+
124
+ ## Message an agent
104
125
 
105
- After `codex-reviewer@studio` appears in status, ask the live Claude Code session
106
- to run `embassy send --to codex-reviewer@studio` with 'Please review the change
107
- and reply using the supplied Embassy hint' on stdin; execute this through the
108
- agent's shell tool, not an unrelated terminal. The sender is inferred from the calling session:
126
+ Ask the live Claude Code session to run `embassy send --to codex-reviewer@studio`
127
+ with the message body on stdin, through the agent's shell tool rather than an
128
+ unrelated terminal. The sender is inferred from the calling session; `send`
129
+ takes exactly one of `--to` or `--conversation` and has no `--from`:
109
130
 
110
131
  ```sh
111
132
  printf '%s\n' 'Please review the change and reply using the supplied Embassy hint' |
112
133
  embassy send --to codex-reviewer@studio
113
134
  ```
114
135
 
115
- The receiving Codex task sees a broker hint such as:
136
+ A successful send returns `result.deliveryToken` and a conversation reference.
137
+ The receipt proves transport, not comprehension: acceptance means the broker
138
+ owns the delivery, not that a model read or understood the body.
139
+
140
+ ## Reply
141
+
142
+ The receiving agent sees a broker hint such as:
116
143
 
117
144
  ```text
118
145
  <embassy-reply-hint conversation="conv_EXACT_REFERENCE" ...>Reply by running `embassy send --conversation conv_EXACT_REFERENCE` with the reply body on stdin.</embassy-reply-hint>
119
146
  ```
120
147
 
121
- It must execute the exact received command to send the reply, because ordinary
122
- Codex final output is not forwarded automatically and `conv_example` is not a
148
+ It must execute the exact received command to send the reply. Ordinary Codex
149
+ final output is not forwarded automatically, and `conv_example` is not a
123
150
  usable reference:
124
151
 
125
152
  ```sh
@@ -127,10 +154,6 @@ printf '%s\n' 'Review complete.' |
127
154
  embassy send --conversation conv_example
128
155
  ```
129
156
 
130
- For a Claude target, find the current Claude target name with an authorized
131
- `embassy refresh` followed by `embassy status --json`, or use the exact current
132
- name supplied by that session.
133
-
134
157
  Conversation references are identity-bound, are not aliases, and may survive a
135
158
  broker restart while their retained ledger row and both exact endpoints remain
136
159
  valid. They stop resolving after retirement, replacement, expiry, eviction, or
@@ -147,6 +170,12 @@ The durable write phases are `queued`, `reserved`, `armed`, `accepted`, and
147
170
  `terminal`. Work known not to have been written may return to the queue. An
148
171
  uncertain armed or accepted write is never replayed.
149
172
 
173
+ Ordinary Codex delivery starts only after an immediate idle observation. A
174
+ competing client can start a turn between that observation and Embassy's
175
+ write; the App Server response cannot distinguish the resulting steer from a
176
+ fresh turn, so the race is undetectable on the wire and the receipt proves
177
+ acceptance and lifetime, not fresh-turn creation.
178
+
150
179
  An exact leading `STEER:` from Claude to Codex targets the active accepted
151
180
  Codex operation at its next safe tool-call boundary. It never interrupts a
152
181
  generation. If that boundary is cleanly unavailable, the message remains in
@@ -155,26 +184,21 @@ the ordinary bounded queue. The global kill switch is
155
184
 
156
185
  See [Delivery semantics](docs/DELIVERY.md) for the phase and receipt contract.
157
186
 
158
- ## Multiple machines
159
-
160
- Install Embassy and run `embassy service install` on both Macs; for `studio`
161
- and `laptop`, use `{"version":1,"host":"studio","nodes":["laptop"]}` on
162
- studio and `{"version":1,"host":"laptop","nodes":["studio"]}` on laptop,
163
- with each peer name matching both the remote inventory's `host` and a working
164
- SSH destination or `~/.ssh/config` Host alias.
187
+ ## Federate
165
188
 
166
- After changing a running broker's inventory, reload it with
167
- `embassy service install`; wait for `codex-reviewer@laptop` to appear from the
168
- Codex daemon on laptop (or use fallback registration), then ask the Claude
169
- session on studio to run
170
- `embassy send --to codex-reviewer@laptop` with the message on stdin.
189
+ Connectivity comes first. Install Embassy and run `embassy service install` on
190
+ both Macs; for `studio` and `laptop`, use
191
+ `{"version":1,"host":"studio","nodes":["laptop"]}` on studio and
192
+ `{"version":1,"host":"laptop","nodes":["studio"]}` on laptop, with each peer
193
+ name matching both the remote inventory's `host` and a working SSH destination
194
+ or `~/.ssh/config` Host alias. After changing a running broker's inventory,
195
+ reload it with `embassy service install`.
171
196
 
172
197
  From studio, verify the remote command environment with
173
198
  `/usr/bin/ssh laptop 'which -a embassy; node --version; embassy --version'`,
174
199
  then verify the corresponding direction from laptop; both remote Node and
175
- Embassy must resolve without an interactive shell or password prompt.
176
-
177
- The local broker launches:
200
+ Embassy must resolve without an interactive shell or password prompt. The local
201
+ broker launches:
178
202
 
179
203
  ```text
180
204
  /usr/bin/ssh <node> embassy peer-stdio
@@ -189,83 +213,83 @@ queue and trusts the peer's source identity, so first contact does not wait
189
213
  for a destination catalog poll. Catalogs are bounded memory-only observations,
190
214
  never routing authority.
191
215
 
216
+ Once `codex-reviewer@laptop` appears from the Codex daemon on laptop (or from
217
+ fallback registration there), the Claude session on studio sends with
218
+ `embassy send --to codex-reviewer@laptop` exactly as it would locally.
219
+
192
220
  `embassy refresh` observes local Claude and Codex sessions and every configured
193
- SSH catalog in parallel. `status` performs no provider or network I/O: it shows the
194
- last per-node catalog rows and observation time, retains the last rows when a
195
- later refresh fails, and labels that node `PEER_TUNNEL_UNAVAILABLE`. At most 128
196
- remote rows are displayed; truncation is explicit. Named and exact sends still
197
- ask the owner directly.
221
+ SSH catalog in parallel. `status` performs no provider or network I/O: it shows
222
+ the last per-node catalog rows and observation time, retains the last rows when
223
+ a later refresh fails, and labels that node `PEER_TUNNEL_UNAVAILABLE`. At most
224
+ 128 remote rows are displayed; truncation is explicit. Named and exact sends
225
+ still ask the owner directly.
226
+
227
+ In `embassy tui`, use `[` / `]` to select a host: the local pane polls every
228
+ second, while independent SSH clients read each remote's
229
+ `embassy status --json` about every five seconds. Each pane reports its own
230
+ broker's health, queue and last operations, not another broker's cached
231
+ catalog, and one hanging host cannot block the other panes. Remote actions run
232
+ the same CLI there over the configured non-interactive SSH; remote retirement
233
+ requires the host plus full endpoint ID confirmation and a fresh supported
234
+ owner snapshot. Disconnected panes are marked stale; an uncertain action is
235
+ never automatically retried. Without an interactive terminal, `tui` prints the
236
+ local status text once and exits without SSH.
237
+
238
+ ## Retire
198
239
 
199
- ## Operations
240
+ ```sh
241
+ embassy retire --alias codex-reviewer@studio
242
+ embassy retire --endpoint <public-id>
243
+ ```
200
244
 
201
- Retain `result.deliveryToken` from the successful send response in your current
202
- session and substitute that exact value for the example; status shows aggregate
203
- route queues and recent delivery metadata but cannot recover a lost delivery
204
- token or distinguish identical sends by token.
245
+ `retire` removes one local endpoint identity and settles all of its
246
+ outstanding work: queued and reserved work is cancelled, armed work becomes
247
+ ambiguous, and accepted work becomes unconfirmed. Remote endpoints must be
248
+ retired on their owning host. If departed sessions share a name, retire one
249
+ exactly with `--endpoint` using its opaque public ID from `result.routes`;
250
+ `--alias` and `--endpoint` are mutually exclusive.
205
251
 
206
- The ellipses (`...` or `…`), `conv_example`, `dlv_example`, and `<public-id>`
207
- are substitutions, not runnable literal values: supply the indicated command
208
- arguments, exact received conversation reference, exact returned delivery
209
- token, or public endpoint ID respectively.
252
+ ## Operations
210
253
 
211
254
  ```sh
212
- embassy status
213
255
  embassy status --json
214
- embassy tui # interactive operator client
215
256
  embassy refresh
216
257
  embassy delivery-status --token dlv_example
217
258
  embassy wait-delivery --token dlv_example
218
- embassy retire --alias codex-reviewer@studio
219
259
  embassy check
220
260
  embassy service status
221
- embassy serve # foreground alternative
222
261
  ```
223
262
 
263
+ `conv_example`, `dlv_example`, and `<public-id>` are substitutions, not
264
+ runnable literal values: supply the exact received conversation reference,
265
+ exact returned delivery token, or public endpoint ID respectively. Retain `result.deliveryToken` from
266
+ the successful send response in your current session; status shows aggregate
267
+ route queues and recent delivery metadata but cannot recover a lost delivery
268
+ token or distinguish identical sends by token.
269
+
224
270
  `status` reports the broker ledger, queue depth, recent message outcomes,
225
271
  retirements, each local route's last native operation, and the last bounded SSH
226
272
  catalog observation. It does not claim that an idle provider is ready.
227
-
228
- Use `delivery-status` to inspect that delivery's phase, pending age or terminal
229
- code; use `status --json` to identify a stranded local route, and retire it with
230
- `retire --alias` using its alias or `retire --endpoint` using its public id from `result.routes`,
231
- understanding that this settles all outstanding work for that endpoint.
232
-
233
- `embassy tui` shows the local broker and each direct host in `nodes.json` in one
234
- terminal. Use `[` / `]` to select a host: local status polls every second, while
235
- independent SSH clients read each remote's `embassy status --json` about every
236
- five seconds. Each pane reports its own broker's health, queue and last
237
- operations—not another broker's cached catalog. One hanging host cannot block
238
- the other panes. No message bodies are displayed.
239
- On-screen keys refresh, check, look up a token or retire on the selected host.
240
- Remote actions run the same CLI there over configured non-interactive SSH;
241
- retirement requires HOST + full endpoint ID confirmation and a fresh supported
242
- owner snapshot. An uncertain action is never automatically retried.
243
- Disconnected views are marked stale; actions are never automatically retried.
244
- Without an interactive terminal, `tui` prints local status text once and exits
245
- without SSH. Unsupported remote response shapes are not guessed; a lazy
246
- `embassy --version` read identifies only that remote CLI, not its broker version.
247
- Deliveries are newest-admitted first, with faults distinguished from successful
248
- delivery. Use 1–4 or Tab to change sections, g/G for first/last row, and Esc to
249
- return from an action result. Token lookup echoes only the token you type;
250
- tokens are not added to the general delivery list. Retirement confirmation
251
- shows the full endpoint identity and the consequences for unsettled work.
252
-
253
273
  Machine output is one closed JSON line shaped as
254
274
  `{"ok":true,"command":"status","result":{...}}`; route rows are therefore at
255
275
  `.result.routes`. A terminal `embassy status` renders the same body for a
256
- person, while `--json` keeps the envelope.
276
+ person, while `--json` keeps the envelope. No message body appears in either.
277
+
278
+ Use `delivery-status` to inspect one delivery's phase, pending age or terminal
279
+ code; `wait-delivery` polls until it is terminal or the bounded wait ends.
257
280
 
258
281
  `check` is a broker-only loopback through the real ledger and coordinator. It
259
282
  proves local control, persistence, routing, and receipt handling without
260
- contacting a live Claude or Codex agent. Healthy means the Embassy control
261
- socket and ledger respond; a passing check exercises only broker loopback, so
262
- neither proves that a Claude session or Codex task can receive or answer a message.
283
+ contacting a live Claude or Codex agent. A passing check exercises only broker
284
+ loopback, so neither `health` nor `check` proves that a Claude session or Codex
285
+ task can receive or answer a message.
263
286
 
264
- `retire` removes one local endpoint identity. Queued and reserved work is
265
- cancelled, armed work becomes ambiguous, and accepted work becomes unconfirmed.
266
- Remote endpoints must be retired on their owning host.
267
- If departed sessions share a name, retire one exactly with
268
- `embassy retire --endpoint <public-id>` using its opaque ID from status.
287
+ In the TUI, on-screen keys refresh, check, look up a token or retire on the
288
+ selected host. Use 1–4 or Tab to change sections, `g`/`G` for the first or last
289
+ row, and Esc to return from an action result. Token lookup echoes only the
290
+ token you type; tokens are not added to the general delivery list. Retirement
291
+ confirmation shows the full endpoint identity and the consequences for
292
+ unsettled work. No message bodies are displayed.
269
293
 
270
294
  ## Safety
271
295
 
@@ -278,36 +302,30 @@ If departed sessions share a name, retire one exactly with
278
302
  - Embassy launches `/usr/bin/ssh` directly without a local shell, in batch mode
279
303
  with forwarding disabled; the remote account must resolve the fixed
280
304
  `embassy peer-stdio` command in its non-interactive SSH environment.
281
- - Healthy means the Embassy control socket and ledger respond; a passing check
282
- exercises only broker loopback, so neither proves that a Claude session or
283
- Codex task can receive or answer a message.
305
+ - Embassy never changes a Codex approval or sandbox policy and never answers
306
+ an approval.
284
307
 
285
308
  See [Security](SECURITY.md), [Configuration](docs/CONFIGURATION.md), and
286
309
  [Architecture](docs/GATEWAY-ARCHITECTURE.md).
287
310
 
288
311
  ## Upgrading to 4.x
289
312
 
290
- Codex discovery reads valid schema 6 forward and writes schema 7, adding only a
291
- private retention marker; existing 4.2.0 endpoints stay retained. No reset is
292
- needed for 4.2.0. Back up `gateway-state.json` before upgrading: 4.2.0 refuses
293
- schema 7, so rollback requires that pre-upgrade backup. Private control changes
294
- 5→6; upgrade CLI and broker together. There is no 3.x migration.
295
-
296
- Before replacing a 3.x installation, use its matching CLI to inspect and
297
- settle or explicitly abandon pending work; stop a launchd broker with
298
- `embassy service uninstall` (or stop the foreground serve process) and confirm
299
- it is stopped with `embassy service status`, back up and move aside only
300
- `gateway-state.json` in that broker's state directory while retaining
301
- `nodes.json`, then install the current discovery-enabled 4.x release and run
302
- `embassy service install`. Current Codex agents are discovered; use fallback
303
- registration only for non-native harnesses.
304
-
305
- All state produced by Embassy 3.x is unsupported by 4.x; preserve the matching
306
- old binary as well as its old state if rollback may be needed, and never run
307
- the old and new brokers together. See the [reset procedure](docs/CONFIGURATION.md#private-state-reset).
308
-
309
- The rollback boundary is the preserved old state plus its matching old binary.
310
- Do not point 4.2.0 at schema-7 state or this release at schema ≤5.
313
+ Upgrade the CLI and broker together; they must come from one installation.
314
+ Private state written by an earlier 4.x release (schema 6) is read forward
315
+ into the current schema 7 with every existing endpoint retained; no reset is
316
+ needed, but back up `gateway-state.json` first, because an earlier 4.x binary
317
+ refuses schema 7 and rollback requires that backup.
318
+
319
+ There is no 3.x migration or converter. Before replacing a 3.x installation,
320
+ use its matching CLI to inspect and settle or explicitly abandon pending work;
321
+ stop the broker with `embassy service uninstall` (or stop the foreground serve
322
+ process) and confirm with `embassy service status`; back up and move aside only
323
+ `gateway-state.json` while retaining `nodes.json`; then install the current
324
+ release and run `embassy service install`. Codex agents are discovered; use
325
+ fallback registration only for non-native harnesses. All 3.x state is
326
+ unsupported: preserve the old binary with its old state if rollback may be
327
+ needed, and never run the old and new brokers together. See the
328
+ [reset procedure](docs/CONFIGURATION.md#private-state-reset).
311
329
 
312
330
  ## Development
313
331
 
package/SECURITY.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## Supported versions
4
4
 
5
- Security fixes are provided for the current release line. Private schema 6 is
6
- read forward into 7; schema ≤5 still requires a reset. Private control peers
7
- must use the same protocol version.
5
+ Security fixes are provided for the current release line. The CLI and broker
6
+ must come from one installation, and federated peers must run the same
7
+ federation protocol.
8
8
 
9
9
  ## Reporting a vulnerability
10
10
 
@@ -200,8 +200,9 @@ commit boundary remain uncertain and are never replayed automatically.
200
200
  Public JSON is a closed projection. It may contain opaque Embassy endpoint IDs,
201
201
  aliases, providers, hosts, queue depths, safe codes, phases/outcomes, ages,
202
202
  recent retirement times, and bounded remote catalog rows and observation times.
203
- Codex rows may additionally contain observed busy, waiting, idle, dormant or unknown state.
204
- The explicit-registration retention marker remains private.
203
+ Codex rows may additionally contain the observed busy, waiting, idle, dormant,
204
+ systemError or unknown state. The explicit-registration retention marker
205
+ remains private.
205
206
  It must never contain native IDs or handles, socket paths, message bodies,
206
207
  delivery/conversation secrets, credentials, exceptions, raw diagnostics, or
207
208
  provider histories. Human output is derived from the same validated shape.
@@ -211,12 +212,13 @@ protocol channel. Operational hints use bounded safe codes and stderr.
211
212
 
212
213
  ## State reset and rollback
213
214
 
214
- Private state writes schema 7 and reads valid schema 6 forward, retaining its
215
- existing rows. Control protocol is 6. Schemas ≤5 and unknown state refuse before
216
- mutation; no 3.x converter or removed-command alias exists. Before upgrading
217
- 4.2.0, stop the broker and back up its state; 4.2.0 refuses schema 7, so rollback
218
- requires that pre-upgrade backup. Upgrading from 3.x still requires inspecting
219
- unsettled work with the old binary and resetting state while keeping `nodes.json`.
215
+ Private state is schema 7; a valid schema-6 document from an earlier 4.x
216
+ release is read forward with its rows retained. Schemas ≤5 and unknown state
217
+ refuse before mutation; there is no 3.x converter or removed-command alias.
218
+ Back up state before upgrading, because an earlier 4.x binary refuses schema
219
+ 7 and rollback requires that pre-upgrade backup. Upgrading from 3.x requires
220
+ inspecting unsettled work with the old binary and resetting state while keeping
221
+ `nodes.json`.
220
222
 
221
223
  Reset invalidates all old routes, receipts, and conversation references. The
222
224
  only rollback is the preserved old binary with its untouched old state. Embassy
@@ -1 +1 @@
1
- export declare const CORE_VERSION = "4.4.0";
1
+ export declare const CORE_VERSION = "4.4.1";
@@ -1,2 +1,2 @@
1
- export const CORE_VERSION = "4.4.0";
1
+ export const CORE_VERSION = "4.4.1";
2
2
  //# sourceMappingURL=core-version.js.map
@@ -123,19 +123,18 @@ the ID is not a command argument or public output. A fallback registration is
123
123
  the same endpoint kind as discovery, and a matching native identity cannot
124
124
  create a duplicate. Each delivery independently attests the current App Server
125
125
  interface and exact task before authorization.
126
- Explicit registration sets a private retention marker, so older roots remain
127
- listed after restart even outside the discovery window. Window aging preserves
128
- automatic rows referenced by pending work, but drops unused automatic rows to
129
- release capacity. No retirement, suppression or settlement occurs. A returning
130
- root keeps its ID while retained/pending; after pruning it receives a fresh ID,
131
- and old receipts never retarget. An unnamed root gets a new generated alias
132
- after pruning. The existing 128-endpoint bound remains.
133
- No discovered/registered badge is exposed.
134
- Explicitly registered rows keep their registered aliases through native scans;
135
- native names drive automatic rows only. A later explicit registration can rename
136
- the retained row without moving its identity or admitted work.
137
- The ellipsis in `--alias ...` is a substitution: use the task's chosen
138
- `codex-` name with this machine's exact `@host` suffix.
126
+ Explicit registration sets a private retention marker, so registered roots
127
+ remain listed after restart even outside the discovery window, and keep their
128
+ registered aliases through native scans; native names drive automatic rows
129
+ only. A later explicit registration can rename the retained row without moving
130
+ its identity or admitted work. Window aging preserves automatic rows referenced
131
+ by pending work but drops unused automatic rows to release capacity, without
132
+ retirement, suppression or settlement. A returning root keeps its ID while
133
+ retained or pending; after pruning it receives a fresh ID (and, if unnamed, a
134
+ new generated alias), and old receipts never retarget. The 128-endpoint bound
135
+ applies to discovered and registered rows alike, and public output carries no
136
+ discovered/registered badge. The ellipsis in `--alias ...` is a substitution:
137
+ use the task's chosen `codex-` name with this machine's exact `@host` suffix.
139
138
 
140
139
  `register-codex --succeeds <old-alias>` atomically retires a predecessor and
141
140
  installs the caller. It never reanchors pending work to a new identity.
@@ -237,11 +236,11 @@ before provider setup, so only one broker can run.
237
236
 
238
237
  ## Private state reset
239
238
 
240
- This release reads valid schema-6 `gateway-state.json` forward, treating every
241
- existing row as retained; new writes use schema 7. The retention marker is the
242
- only added field. Back up state before upgrading 4.2.0; no reset is required,
243
- but 4.2.0 refuses schema 7 and rollback requires the pre-upgrade backup.
244
- There is no 3.x converter. Schema ≤5 or unknown schemas refuse with
239
+ `gateway-state.json` is written as schema 7. A valid schema-6 document from an
240
+ earlier 4.x release is read forward with every existing row retained; no reset
241
+ is required, but back up state before upgrading, because an earlier 4.x binary
242
+ refuses schema 7 and rollback requires the pre-upgrade backup. There is no 3.x
243
+ converter. Schema ≤5 or unknown schemas refuse with
245
244
  `GATEWAY_STATE_SCHEMA_UNSUPPORTED`; malformed accepted schemas refuse with
246
245
  `CORRUPT_GATEWAY_STATE`. Refusal does not mutate the installed file.
247
246
 
@@ -253,20 +252,20 @@ Reset procedure:
253
252
  serve process) and confirm it is stopped with `embassy service status`.
254
253
  3. Back up and move aside only `gateway-state.json` in that broker's state
255
254
  directory. Keep the valid `nodes.json`.
256
- 4. Install the current discovery-enabled 4.x release, then run
257
- `embassy service install`.
258
- 5. The broker creates fresh schema-7 state.
259
- 6. Let current Codex agents be discovered. Use fallback registration only for
260
- non-native harnesses. Claude endpoints are recorded on discovery/use.
255
+ 4. Install the current release, then run `embassy service install`. The
256
+ broker creates fresh schema-7 state.
257
+ 5. Let current Codex agents be discovered. Use fallback registration only for
258
+ non-native harnesses. Claude endpoints are recorded on discovery or use.
261
259
 
262
- All state produced by Embassy 3.x is unsupported by 4.x; preserve the matching
263
- old binary as well as its old state if rollback may be needed, and never run
264
- the old and new brokers together.
260
+ All state produced by Embassy 3.x is unsupported; preserve the matching old
261
+ binary as well as its old state if rollback may be needed, and never run the
262
+ old and new brokers together.
265
263
 
266
264
  A reset abandons unsettled work and invalidates delivery tokens and
267
- conversation references. Rollback means stopping v4 and restoring both the old
268
- binary and its untouched old state. Never hand-edit either schema.
269
- After v4 has accepted work, the old backup does not contain that work. Before
270
- rolling back, inspect and drain or explicitly abandon v4 deliveries, and keep
271
- a separate backup of the v4 state. Restoring v3 is not a rollback of those
272
- delivery effects and must never silently discard unsettled v4 work.
265
+ conversation references. Rollback means stopping the current broker and
266
+ restoring both the old binary and its untouched old state. Never hand-edit
267
+ either schema. Work accepted after the upgrade is absent from the old backup:
268
+ before rolling back, inspect and drain or explicitly abandon those deliveries
269
+ and keep a separate backup of the current state. Restoring the old binary is
270
+ not a rollback of those delivery effects and must never silently discard
271
+ unsettled work.
@@ -8,10 +8,8 @@ pairs are supported. Sending is one `embassy send` command; receiving wakes the
8
8
  target through its native interface. A receipt proves delivery machinery, not
9
9
  model comprehension.
10
10
 
11
- The design optimizes for this steady state and deliberately excludes native
12
- Claude `SendMessage` advertisement helpers, shell-peer mailboxes, automatic
13
- Codex output forwarding, persistent remote mirrors, general activity streams,
14
- and migration compatibility.
11
+ The design optimizes for this steady state; everything it deliberately leaves
12
+ out is listed under [Responsibility exclusions](#responsibility-exclusions).
15
13
 
16
14
  ## Topology
17
15
 
@@ -31,8 +29,8 @@ Claude/Codex CLI
31
29
  remote broker ledger
32
30
  ```
33
31
 
34
- There is one broker per login user and host. The broker owns one schema-7 JSON
35
- document and one private control socket. It does not listen on a network port.
32
+ There is one broker per login user and host. The broker owns one private JSON
33
+ state document and one private control socket. It does not listen on a network port.
36
34
  launchd may supervise the same foreground `serve` entry point.
37
35
 
38
36
  ## Endpoint directory
@@ -139,8 +137,8 @@ guessing. The live host lease is checked before a transaction, before
139
137
  persistence, and immediately before rename.
140
138
 
141
139
  No-op transactions write nothing. Unsupported or corrupt state refuses before
142
- mutation. Valid schema 6 reads forward with all existing rows retained; writes use 7.
143
- The only added field is the private retention marker. Schema ≤5 still needs a reset.
140
+ mutation. A valid schema-6 document from an earlier 4.x release reads forward
141
+ with all existing rows retained; schema ≤5 needs a reset.
144
142
 
145
143
  ## Coordinator
146
144
 
@@ -239,9 +237,8 @@ reset.
239
237
 
240
238
  ## Local control and CLI
241
239
 
242
- The private control protocol is version 6. Each connection carries one bounded
243
- JSON request and one closed JSON response over the expected private Unix
244
- socket. A mutating request whose reply is lost after write reports
240
+ Each private control connection carries one bounded JSON request and one
241
+ closed JSON response over the expected private Unix socket. A mutating request whose reply is lost after write reports
245
242
  `CONTROL_WRITE_OUTCOME_AMBIGUOUS`; the CLI does not retry it.
246
243
 
247
244
  The public CLI is:
@@ -257,8 +254,9 @@ serve service peer-stdio
257
254
  `send` accepts exactly one of `--to` and `--conversation`; it has no `--from`.
258
255
  Human `status` is a rendering of the same closed body-free JSON shape. Its
259
256
  health word describes control/ledger health, local route rows expose their last
260
- native operation, and Codex rows expose busy, waiting, idle, dormant or unknown
261
- status, without parent references or registration-origin labels. The federation section
257
+ native operation, and Codex rows expose busy, waiting, idle, dormant,
258
+ systemError or unknown status, without parent references or
259
+ registration-origin labels. The federation section
262
260
  exposes only the last bounded catalog observation. `health` is a control-path probe. `check` creates temporary
263
261
  private loopback endpoints and uses the real ledger/coordinator/receipt path,
264
262
  then retires them; no provider or model is contacted. It is not a
@@ -283,7 +281,7 @@ Startup order is ownership-sensitive:
283
281
  1. load the private node inventory, or derive a transient first-boot default,
284
282
  and load configuration;
285
283
  2. acquire the fixed host-wide kernel lease;
286
- 3. open and validate schema-7 state without changing the inventory;
284
+ 3. open and validate the private state without changing the inventory;
287
285
  4. atomically install and reload the default inventory when first boot needs
288
286
  one;
289
287
  5. construct native and SSH adapters;
@@ -304,7 +302,7 @@ model interrupt.
304
302
 
305
303
  | Surface | Version | Compatibility policy |
306
304
  |---|---:|---|
307
- | Private state (`gateway-state.json`) | 7 | Reset only; older and unknown schemas refuse without mutation |
305
+ | Private state (`gateway-state.json`) | 7 | A valid schema-6 document is read forward with rows retained; ≤5 and unknown refuse without mutation (reset) |
308
306
  | Private control (CLI ↔ broker) | 6 | CLI and broker must come from one installation |
309
307
  | Federation (`peer-stdio`) | 3 | Exact version and host handshake; no compatibility mode |
310
308
  | Consumed Claude peer protocol | 1 | Incompatible records are rejected in isolation |
@@ -314,10 +312,11 @@ each use boundary. Version or build metadata is never routing authority.
314
312
 
315
313
  ## Responsibility exclusions
316
314
 
317
- The v4 core intentionally has no shell-peer registration/token/mailbox/await
315
+ The core intentionally has no shell-peer registration/token/mailbox/await
318
316
  system, no native Claude advertisement helper, no automatic provider-output
319
317
  reply capture, no persisted remote route mirror, no pair/selection graph, no
320
- dashboard/watch event system, no notice-mode machinery, and no v3 migration
321
- reader. The responsibilities that remain are endpoint identity, bounded
318
+ dashboard/watch event system, no notice-mode machinery, and no old-state
319
+ migration reader. Its responsibilities are endpoint identity, bounded
322
320
  delivery, native wake, exact replies, direct federation, status, retirement,
323
- service supervision, and loopback verification.
321
+ service supervision, and loopback verification. The reasons are recorded in
322
+ the repository's `docs/DECLINED.md`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-embassy",
3
- "version": "4.4.0",
3
+ "version": "4.4.1",
4
4
  "description": "A local gateway for bidirectional messaging between Claude Code sessions and Codex tasks.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -100,4 +100,4 @@ For operator-authorized removal use `embassy retire --alias <local-alias>`. It r
100
100
 
101
101
  When a name collides, operator-authorized `embassy retire --endpoint <public-id>` removes just that local endpoint using its opaque ID from status. Use exactly one of `--alias` or `--endpoint`; never substitute a native session ID. A partial discovery cannot clear a known collision; exact user-supplied UUID addressing remains available until a complete scan proves uniqueness.
102
102
 
103
- There is no shell-peer mailbox, await command, native sending advertisement, automatic output forwarding, reply alias, or unregister-codex command in v4. Do not fall back to removed commands or direct provider sockets; report the precise refusal.
103
+ `embassy --help` lists the whole public CLI; do not fall back to a command that is not listed there or to direct provider sockets; report the precise refusal.