@robota-sdk/agent-command 3.0.0-beta.82 → 3.0.0-beta.84

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 (94) hide show
  1. package/CHANGELOG.md +1071 -0
  2. package/README.md +71 -62
  3. package/dist/node/index.cjs +81 -72
  4. package/dist/node/index.d.cts +136 -52
  5. package/dist/node/index.d.cts.map +1 -1
  6. package/dist/node/index.d.ts +136 -52
  7. package/dist/node/index.d.ts.map +1 -1
  8. package/dist/node/index.js +79 -70
  9. package/dist/node/index.js.map +1 -1
  10. package/package.json +16 -10
  11. package/src/agent/__tests__/agent-command.test.ts +62 -0
  12. package/src/agent/agent-command-parser.ts +2 -2
  13. package/src/agent/agent-command.ts +20 -0
  14. package/src/command-module-utils.test.ts +37 -0
  15. package/src/command-module-utils.ts +2 -0
  16. package/src/default/__tests__/__snapshots__/model-exposure.test.ts.snap +2 -2
  17. package/src/default/__tests__/default-command-modules.test.ts +54 -14
  18. package/src/default/__tests__/model-exposure.test.ts +18 -3
  19. package/src/default/__tests__/org-policy-forwarding.test.ts +10 -2
  20. package/src/default/default-command-modules.ts +15 -8
  21. package/src/devices/__tests__/devices-command-module.test.ts +99 -12
  22. package/src/devices/devices-command-module.ts +108 -24
  23. package/src/devices/devices-command-port.ts +62 -1
  24. package/src/devices/index.ts +3 -0
  25. package/src/doctor/doctor-node-deps.ts +6 -7
  26. package/src/editor/editor-command-module.ts +5 -0
  27. package/src/effort/effort-command.test.ts +65 -2
  28. package/src/effort/effort-command.ts +19 -5
  29. package/src/events/__tests__/events-command.test.ts +73 -0
  30. package/src/events/events-command-module.ts +49 -0
  31. package/src/events/events-command.ts +69 -0
  32. package/src/events/index.ts +2 -0
  33. package/src/git/__tests__/fake-git-port.ts +9 -2
  34. package/src/git/__tests__/git-command-module.test.ts +10 -2
  35. package/src/git/git-command-module.ts +3 -4
  36. package/src/git/git-commit.ts +6 -3
  37. package/src/git/index.ts +4 -1
  38. package/src/goal/goal-command.ts +3 -1
  39. package/src/handoff/__tests__/handoff-command-module.test.ts +2 -1
  40. package/src/handoff/handoff-command-module.ts +1 -1
  41. package/src/handoff/handoff-command.ts +2 -2
  42. package/src/help/__tests__/help-command-module.test.ts +3 -0
  43. package/src/help/__tests__/help-command.test.ts +3 -0
  44. package/src/index.ts +14 -0
  45. package/src/keybindings/keybindings-command-module.ts +17 -3
  46. package/src/mcp-activation/__tests__/mcp-activation-command.test.ts +172 -0
  47. package/src/mcp-activation/mcp-activation-command-module.ts +6 -0
  48. package/src/mcp-activation/mcp-activation-command.ts +62 -4
  49. package/src/memory/__tests__/memory-command-module.test.ts +40 -2
  50. package/src/memory/__tests__/memory-command-unavailable.test.ts +63 -0
  51. package/src/memory/memory-command-module.ts +4 -2
  52. package/src/memory/memory-command.ts +42 -2
  53. package/src/mode/__tests__/mode-command-module.test.ts +40 -0
  54. package/src/mode/mode-command.ts +1 -1
  55. package/src/model/__tests__/model-command-module.test.ts +80 -0
  56. package/src/model/__tests__/model-command.test.ts +240 -0
  57. package/src/model/index.ts +6 -0
  58. package/src/model/model-command-module.ts +56 -0
  59. package/src/model/model-command.ts +223 -0
  60. package/src/peers/__tests__/peers-command-module.test.ts +24 -0
  61. package/src/peers/__tests__/peers-command.test.ts +78 -0
  62. package/src/peers/peers-command-module.ts +1 -1
  63. package/src/peers/peers-command.ts +33 -4
  64. package/src/plugin/__tests__/plugin-command-module.test.ts +81 -1
  65. package/src/plugin/plugin-command.ts +47 -4
  66. package/src/provider/__tests__/org-policy.test.ts +4 -0
  67. package/src/provider/__tests__/provider-command-module.test.ts +276 -14
  68. package/src/provider/__tests__/scripted-interaction.ts +12 -2
  69. package/src/provider/provider-command-execution.ts +54 -8
  70. package/src/provider/provider-command-profile-lifecycle.ts +48 -2
  71. package/src/provider/provider-command-profile-operations.ts +14 -0
  72. package/src/provider/provider-command-profile.ts +7 -4
  73. package/src/provider/provider-command-setup.ts +14 -1
  74. package/src/rewind/__tests__/rewind-command-module.test.ts +32 -1
  75. package/src/rewind/rewind-command.ts +23 -2
  76. package/src/schedule/__tests__/loop-command-functional.test.ts +13 -0
  77. package/src/schedule/__tests__/loop-command.test.ts +238 -4
  78. package/src/schedule/__tests__/schedule-redos.test.ts +33 -0
  79. package/src/schedule/loop-command.ts +98 -4
  80. package/src/schedule/schedule-command-module.ts +8 -4
  81. package/src/settings/settings-command-module.ts +2 -2
  82. package/src/shell/shell-command-module.ts +5 -0
  83. package/src/terminal-client/__tests__/terminal-client-commands.test.ts +216 -0
  84. package/src/terminal-client/index.ts +5 -0
  85. package/src/terminal-client/terminal-client-commands.ts +109 -0
  86. package/src/theme/__tests__/theme-command.test.ts +1 -1
  87. package/src/theme/theme-command-module.ts +12 -2
  88. package/src/user-local/__tests__/user-local-command.test.ts +2 -2
  89. package/src/git/__tests__/git-diff.test.ts +0 -125
  90. package/src/git/__tests__/git-process.test.ts +0 -221
  91. package/src/git/__tests__/git-status.test.ts +0 -117
  92. package/src/git/git-diff.ts +0 -129
  93. package/src/git/git-process.ts +0 -169
  94. package/src/git/git-status.ts +0 -134
package/CHANGELOG.md ADDED
@@ -0,0 +1,1071 @@
1
+ # @robota-sdk/agent-command
2
+
3
+ ## 3.0.0-beta.84
4
+
5
+ ### Patch Changes
6
+
7
+ - e8d70ac: A first run finds a provider, instead of a dead end. `robota --serve` (and the daemon it starts) no
8
+ longer refuses when no provider is configured: it starts in setup mode, and the GUI's conversation area
9
+ shows a "Connect a model provider to start" panel with a "Set up provider" button in place of the
10
+ composer. Answering it configures and swaps in the first provider live, with no restart. A startup
11
+ failure now says why — `robota daemon start --json` and the desktop app's fatal screen report the
12
+ child's own reason instead of a generic "readiness channel closed", and the fatal screen gets a Try
13
+ again button. `trust status --json` and the desktop trust dialog list only sources whose state trust
14
+ would actually change, instead of naming one this platform could not determine; the dialog shows one
15
+ sentence and a collapsed Details section. `robota --serve --open` in an untrusted folder now asks at
16
+ the terminal (trust it, start Restricted, or quit) when someone is there to ask, instead of refusing
17
+ outright.
18
+ - Updated dependencies [9f46375]
19
+ - Updated dependencies [e8d70ac]
20
+ - Updated dependencies [9c6a8db]
21
+ - Updated dependencies [9c6a8db]
22
+ - Updated dependencies [9c6a8db]
23
+ - @robota-sdk/agent-core@3.0.0-beta.84
24
+ - @robota-sdk/agent-framework@3.0.0-beta.84
25
+ - @robota-sdk/agent-interface-session@3.0.0-beta.84
26
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.84
27
+ - @robota-sdk/agent-interface-command@3.0.0-beta.84
28
+ - @robota-sdk/agent-preset@3.0.0-beta.84
29
+
30
+ ## 3.0.0-beta.83
31
+
32
+ ### Minor Changes
33
+
34
+ - 724fabb: External-event grants are given at start, carried exactly to a background session, listed without their
35
+ principal, and revoked by the owner.
36
+
37
+ - `agent-framework` (breaking) — `openExternalEventSource` and `ExternalEventIngress.open` take only
38
+ `{ grant, audit? }`: the session builds each grant's verifier from `grant.verifier` with the
39
+ `externalEventVerifierFactory` its host passed when the session was built (without one, no grant opens), and an
40
+ open that supplies a verifier or a factory is refused. `IExternalEventSource.revoke()` stops the grant's queued and running turns,
41
+ refuses its later events as `grant-revoked`, and keeps the label from being opened again. A submission the
42
+ session refuses is `shutting-down` only while it shuts down, and `session-unavailable` otherwise. New command
43
+ host adapter `externalEvents` (`ICommandExternalEventsAdapter`).
44
+ - `agent-ui-terminal` — forwards `externalEventVerifierFactory` from the render options to the session.
45
+ - `agent-interface-transport` — `TExternalEventRefusal` gains `session-unavailable`.
46
+ - `agent-command` — `/events` lists the session's grants (label, principal kind, state, counts) and
47
+ `/events revoke <grant-id>` withdraws one. User-only.
48
+ - `agent-cli` — a grant file (`grantId`, `issuer`, `resource` ending in `/events/<grantId>`, exactly one of
49
+ `subject` or `client`, `scopes`, optional `algorithms` and `rate`) is validated before anything starts, with a
50
+ reason that names the grant and no configured value. `robota --external-event-grant <file>` (TUI) and
51
+ `robota session start --background --external-event-grant <file>` open every grant or fail the start; a
52
+ background session receives its grants through a private file, opens them before it reports ready, and the
53
+ launcher refuses a readiness that names other grants. `robota session events list <id> [--json]` and
54
+ `robota session events revoke <id> <grant-id>` work over the generation-bound control socket, and
55
+ `robota session list --format json` shows each grant's counts. The retired `--external-event-allow` now points
56
+ at `--external-event-grant`.
57
+
58
+ - 28fa8a7: `/devices add` and `/devices join` enrol a new device into your devices.
59
+
60
+ - On a device that holds the signing key, `/devices add` shows a one-time code on the terminal. It
61
+ works once, for five minutes.
62
+ - On the new device, `/devices join [name]` asks for the code on the terminal, creates the device's
63
+ keys, and meets the other device through the signaling relay in
64
+ `transports.webrtc.options.relayUrl`. Both devices need that setting.
65
+ - The new device proves the code over the WebRTC connection's DTLS fingerprints before anything else
66
+ crosses, so a relay in the middle cannot enrol anyone.
67
+ - Both devices then show the same six digits, and both operators compare them and confirm. Someone
68
+ who saw the code cannot choose the digits: the new device commits to its part before it sees the
69
+ existing device's.
70
+ - Only when both operators say yes does the existing device certify the new one and issue a new
71
+ roster. The new device keeps its identity only once the chain it receives verifies.
72
+ - A wrong, expired or already used code is refused. So is a code after a few failed attempts. When
73
+ either operator declines, nothing is issued or kept.
74
+ - The code appears only on the two terminals. It never reaches history, transcripts or the model. A
75
+ code typed as a command argument is refused. Both commands stay user-only and refuse remote
76
+ surfaces.
77
+ - `agent-remote-pairing`: enrollment codes, the enrollment proof, the signed request with its
78
+ commitment, the short authentication string and the frame decoder.
79
+ - `agent-transport-webrtc`: `dialEnrollment` and `listenForEnrollment` provide a data channel bound to
80
+ the negotiated fingerprints.
81
+
82
+ - 4f49d14: The device mesh can be turned on, and `/peers`, `/handoff` and `/devices` reach the user's other devices.
83
+
84
+ - New user setting `transports.mesh.enabled` (default `false`). When it is `true`, an interactive
85
+ session opens the device mesh at startup and closes it on exit. Only the user settings count; a
86
+ project's settings cannot turn it on. Print and serve runs never open it, and a device without an
87
+ identity is told to run `/devices init`. Only one session of a device opens it at a time; another
88
+ session on the same device says so in `/devices` and links nothing.
89
+ - By default a linked device may send messages, files and sessions. Each file and each session still
90
+ waits for the operator's yes on this machine's terminal; with no terminal the answer is no.
91
+ Delegating, observing and driving stay off unless `transports.mesh.options.capabilities` lists
92
+ them.
93
+ - A message from a linked device arrives like one from a session on this host: a peer turn with no
94
+ authority, attributed to the device the handshake proved, under the same rate limit and
95
+ conversation limits.
96
+ - `/peers` lists linked devices beside the sessions on this host; `/peers send` and
97
+ `/peers send-file` take a device id. `/handoff` lists linked devices and pushes the session to one.
98
+ Files arrive in the usual place aside, and sessions are saved without starting.
99
+ - `/devices` shows whether the mesh is on, how this device finds the others, and which are linked.
100
+ - The mesh uses the relay at `transports.webrtc.options.relayUrl` when one is set. Without one it
101
+ finds devices on the local network and over the public ways in `transports.mesh.options`.
102
+ - `/peers`, `/handoff` and `/devices` stay user-only. Their descriptions tell the model they cover
103
+ linked devices.
104
+ - `agent-framework`: the `/peers` port can list linked devices (`listDevices`, `ILinkedDeviceSummary`).
105
+ - `agent-command`: the `/devices` port can report the mesh (`meshStatus`, `IDevicesMeshStatus`).
106
+
107
+ - 7b72344: Every client can offer the session's commands and skills and show its status. The GUI uses them as a
108
+ desktop-style composer.
109
+
110
+ - `agent-interface-session` is **`major` because `IInteractiveSession` gains required members**:
111
+ `ISessionCommands.listSkills()` and a `statusRead` capability, `getStatusSnapshot()`. The snapshot
112
+ holds session, model, permission mode, effort, context and goal. An external implementation stops
113
+ compiling until it adds both.
114
+ - `agent-transport` is **`major` for the same reason on `IProtocolSession`**. It also gains the wire
115
+ messages `get-commands` → `commands` and `get-status` → `session_status`. Both are reads that the
116
+ observe role may send.
117
+ - `agent-interface-command` gains `ICommandSkillListEntry`, moved from `agent-framework`, which
118
+ re-exports it unchanged.
119
+ - `agent-ui-web` is **`major` because its state changes shape**:
120
+ - A command's outcome and a finished turn's tool calls are now conversation entries: `messages` is
121
+ `TConversationEntry[]`.
122
+ - The `uiIntentNotices` list, `dismissUiIntentNotice`, `applyUiIntentEvent`,
123
+ `removeUiIntentNotice` and `IUiIntentNotice` are removed. An intent now answers with an info
124
+ line in the conversation.
125
+ - Session notices keep only `session-error` and `protocol-error`.
126
+ - The state gains `commandCatalog` and `sessionStatus`.
127
+ - `agent-command` registers `/theme` and `/keybindings` even without a terminal. They then answer
128
+ that they belong to the robota terminal, instead of being unknown.
129
+ - `agent-framework`:
130
+ - `InteractiveSession.getStatusSnapshot()`.
131
+ - The main-thread row previews the last chat message instead of the last record's type.
132
+ - `agent-cli` serves the full GUI web app, renamed from `agent-cli-web` to `agent-gui-web`, on
133
+ `robota --serve --open`.
134
+
135
+ - 9721162: The command catalog says who runs a command, and which surfaces can run it.
136
+
137
+ - **`agent-interface-command` (major).**
138
+ - Adds `TCommandRunner` (`'runtime' | 'client'`) and `TCommandSurface` (`'terminal' | 'gui'`).
139
+ - `ICommand` gains optional `runner` and `surfaces`.
140
+ - `ICommandListEntry` gains optional `surfaces` and a **required** `runner`. An implementation of `listCommands()`, or any code that constructs an `ICommandListEntry`, must now emit `runner`; a command that declares none gets `'runtime'`.
141
+ - **`agent-framework` (minor).**
142
+ - `ISystemCommand` gains optional `runner` and `surfaces`, and the command listing carries both.
143
+ - An undeclared runner resolves to `'runtime'`.
144
+ - `SessionTerminalHandoffGate` is exported for a terminal client that hands its own terminal to a command.
145
+ - **`agent-command` (minor).**
146
+ - `/shell`, `/editor`, `/theme` and `/keybindings` declare `runner: 'client'` and `surfaces: ['terminal']`.
147
+ - `createTerminalClientCommands()` builds the same four commands, from the same execute functions, for a terminal client to run itself. The set follows the preset's module selection.
148
+ - **`agent-ui-web` (minor).** The `/` menu marks a command that runs in the terminal with a "terminal" badge.
149
+
150
+ ### Patch Changes
151
+
152
+ - 4241fc5: Device mesh follow-ups.
153
+
154
+ - A device with no identity is pointed to `/devices add` on one of the user's devices and `/devices join`
155
+ here, as well as to `/devices init`. The message says that `init` is for the first device only,
156
+ because it creates a separate identity that can never link to the user's other devices. The `/devices`
157
+ description and the `init` subcommand say the same.
158
+ - An identity created mid-session (`/devices init`, or a successful `/devices join`) opens the mesh
159
+ without a restart when `transports.mesh.enabled` is on.
160
+ - If a session stalls for longer than the mesh lock's stale window (for example while the machine
161
+ sleeps), another session can take the mesh over. The stalled session now notices this on its next
162
+ lock refresh, closes its own mesh, and says why. Two sessions no longer run it together.
163
+ `holdExclusiveFileLock` has a new `onLost` option for this.
164
+ - `/peers` and `/handoff` still list and reach linked mesh devices when local same-host peer discovery
165
+ fails. `/peers` says why sessions on this host are not listed. `ICommandLocalPeersAdapter` has a new
166
+ optional `localDiscoveryOff` field for this.
167
+ - `agent-transport-webrtc`: when lists become newer on a node (reissued, revoked, or adopted from a
168
+ peer), the node sends them over every admitted connection instead of waiting for the next handshake.
169
+ Reissues, revocations and enrolments in the CLI take effect this way at once. A receiver adopts a
170
+ pushed list only if it is newer, issued by this user's signing key, and verifies. The push does not
171
+ depend on the peer's capabilities, and it never reaches the application's message handlers.
172
+
173
+ - 57280bf: Every published package now declares `"engines": { "node": ">=22.12.0" }`. Before, 27 of the 38
174
+ packages declared no floor (`agent-core`, `agent-tools` and every provider among them),
175
+ `agent-session` and `agent-file-authority` declared `>=20.19.0`, and the other nine declared
176
+ `>=22.0.0`, so a consumer on Node 20 saw at most a warning from a transitive dependency.
177
+
178
+ Why 22.12: `agent-cli` and `agent-ui-terminal` need Node 22 through `ink` 7, and the CommonJS entries
179
+ of `agent-tools` and its dependents, `agent-transport`/`node` and its dependents, and
180
+ `agent-ui-terminal` `require()` ESM-only dependencies (`p-limit`, `jose`, `chalk`), which Node 22
181
+ supports unflagged only from 22.12. `engines` is advisory unless the consumer enables `engine-strict`.
182
+
183
+ No code changes: `tsdown` now reads `node22.12.0` as its build target from the field.
184
+
185
+ - 18c0d5c: Every published package now exports `./package.json`, so `require('<package>/package.json')` and
186
+ `import('<package>/package.json', { with: { type: 'json' } })` work instead of failing with
187
+ `ERR_PACKAGE_PATH_NOT_EXPORTED`, and each tarball now ships the package's `CHANGELOG.md`.
188
+ - caaab20: `/rewind` works again. Every session the CLI builds for a trusted workspace captures edit
189
+ checkpoints; before, none did, and `/rewind` failed everywhere with "Edit checkpoints require
190
+ project authority."
191
+
192
+ - `agent-cli` (patch): a trusted workspace composes an edit checkpoint store for the terminal UI, a
193
+ print run, a served runtime and each session a daemon keeps live. Every session gets its own
194
+ store, pooled or switched to in the terminal UI, since two can run turns at the same time. On a host that cannot prove a project write
195
+ stays inside the project (every platform but Linux), none is composed: a checkpoint could be
196
+ neither saved nor restored there.
197
+ - `agent-command` (patch): where a session has no checkpoints, `/rewind` says why: a restricted
198
+ workspace is told to run `robota trust --yes` and restart robota, and a host that cannot write
199
+ the project safely says so. `/rewind list` reports this as a failed command instead of throwing.
200
+ - `agent-framework` (minor): a checkpoint operation on a session without a store throws
201
+ `EditCheckpointsUnavailableError`, whose `reason` is `host-cannot-write-project`,
202
+ `restricted-workspace` or `no-checkpoint-store`. It is a `WorkspaceAuthorityRequiredError`, as
203
+ before, named `EditCheckpointsUnavailableError`. `HeadlessInteractionChannel` takes an
204
+ `editCheckpointStore` option.
205
+ - `agent-ui-terminal` (minor): `renderApp` takes `createEditCheckpointStore` in place of
206
+ `editCheckpointStore`, and builds each session its own store, since a session switch can build the
207
+ next session before the old one's turn ends. `TuiInteractionChannel` keeps `editCheckpointStore`:
208
+ a channel runs one session.
209
+
210
+ - Updated dependencies [3c81769]
211
+ - Updated dependencies [724fabb]
212
+ - Updated dependencies [997f2fb]
213
+ - Updated dependencies [bfe8ed5]
214
+ - Updated dependencies [e689c8e]
215
+ - Updated dependencies [4241fc5]
216
+ - Updated dependencies [4f49d14]
217
+ - Updated dependencies [7b72344]
218
+ - Updated dependencies [6ae3f28]
219
+ - Updated dependencies [9721162]
220
+ - Updated dependencies [be0e53c]
221
+ - Updated dependencies [57f57f5]
222
+ - Updated dependencies [ba822c1]
223
+ - Updated dependencies [9721162]
224
+ - Updated dependencies [6e6b06b]
225
+ - Updated dependencies [7d77ce4]
226
+ - Updated dependencies [8bd5fac]
227
+ - Updated dependencies [57280bf]
228
+ - Updated dependencies [5033dd9]
229
+ - Updated dependencies [18c0d5c]
230
+ - Updated dependencies [dbd888d]
231
+ - Updated dependencies [1887e54]
232
+ - Updated dependencies [caaab20]
233
+ - Updated dependencies [f01868f]
234
+ - Updated dependencies [e8779c9]
235
+ - Updated dependencies [5a0ee96]
236
+ - @robota-sdk/agent-framework@3.0.0-beta.83
237
+ - @robota-sdk/agent-core@3.0.0-beta.83
238
+ - @robota-sdk/agent-interface-session@3.0.0-beta.83
239
+ - @robota-sdk/agent-interface-command@3.0.0-beta.83
240
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.83
241
+ - @robota-sdk/agent-preset@3.0.0-beta.83
242
+
243
+ ## 3.0.0-beta.82
244
+
245
+ ### Minor Changes
246
+
247
+ - c7f9203: Connected sessions can send each other files.
248
+
249
+ - `/peers send-file <session-id> <path>` sends a copy of any file the operator can read to another
250
+ live session on this host.
251
+ - The model sends a file only through the `peer_send_file` tool. Every call asks the user, showing
252
+ the path, size, hash and destination; no permission mode, rule or remembered consent answers it.
253
+ The tool reaches only files inside the workspace whose path does not look like it holds secrets
254
+ (`.env*`, `~/.ssh`, keys and credentials), and it does not exist in a turn a peer's message started.
255
+ - The receiving operator approves every file. A received file is kept as an inert copy (mode 0600)
256
+ under `~/.robota/peer-files/<sender>/`. It is never run and never placed in the model's context.
257
+ The conversation is told only its name, size and sha256. A name that leaves that directory is
258
+ refused, a symbolic link is never written through, and nothing is overwritten.
259
+ - Transfers travel on a channel of their own (a separate connection on this host, a separate data
260
+ channel between devices), in chunks the receiver paces, up to 32 MiB, and are kept only when the
261
+ whole content matches the offered sha256. A transfer that ends early is discarded; there is no
262
+ resume.
263
+
264
+ **API**
265
+
266
+ - `agent-interface-session-mobility`: the `file` capability, which asks the operator for every
267
+ request; `ConnectionAuthority.authorizeFile`; `IFileOffer` and `IFileFrameChannel`.
268
+ - `agent-transport/node`: `sendFileOverChannel` and `receiveFileOverChannel`, the carrier over any
269
+ `IFileFrameChannel`; `DEFAULT_MAX_FILE_BYTES`.
270
+ - `agent-transport-webrtc`: `IDeviceMeshLink.openFileChannel` and `onFileChannel`.
271
+ - `agent-remote-pairing`: `file` joins `DEVICE_CAPABILITIES`. A device certificate that names it is
272
+ refused as malformed by an earlier version.
273
+ - `agent-core`: `IToolPermissionProfile.notInPeerTurn` withholds a tool from a turn a peer's message
274
+ started.
275
+ - `agent-framework`: `ICommandLocalPeersAdapter.prepareFile`.
276
+
277
+ - 004fe7f: `/handoff` moves a session over a real connection.
278
+
279
+ - `/handoff <session-id>` pushes this conversation to another Robota session on this machine. The
280
+ same carrier also runs between two of the user's devices over their mesh connection; no command
281
+ opens that connection yet.
282
+ - A hand-off is push-only: only the operator of the session that holds it starts one. A session or
283
+ device that asks another for its session is refused.
284
+ - The source signs a grant for that one transfer over that one channel with its device key, so a
285
+ hand-off needs the device identity from `/devices init`. The receiving side checks it against the
286
+ sender's certificate, then asks its own operator; without a yes nothing is sent.
287
+ - The session travels on the file-transfer carrier, is kept aside until it matches the manifest, and
288
+ is saved without being started. The operator there resumes it with `robota --resume <id>`.
289
+ - The source gives the session up, and ends, only once the receiving side confirms it saved it.
290
+ Every other outcome leaves the session where it was; if the confirmation is lost, `/handoff` to the
291
+ same session again resends the same transfer, which the receiver settles without saving it twice.
292
+ Peer attribution (`driverId`, `turnSource`)
293
+ travels with it.
294
+ - `/handoff` stays user-only. Its description tells the model to suggest the command to the user.
295
+ - `agent-transport-webrtc`: an admitted mesh link exposes the DTLS fingerprints it is bound to, and
296
+ `judgeHandoffGrant` is exported.
297
+ - `agent-interface-session-mobility`: a hand-off carrier may move the sealed payload whole
298
+ (`sendPayload`), the destination verifies it with `receivePayload`, and the source can report its
299
+ open transfer (`status`) and abandon it for any refusal the destination names.
300
+
301
+ ### Patch Changes
302
+
303
+ - e15e22b: Two of one user's devices can connect to each other over WebRTC, admitted by the device handshake.
304
+
305
+ - `agent-transport-webrtc` — `DeviceMeshNode` keeps one connection per device pair, in either role: the
306
+ device with the lower id offers and the other answers, so concurrent attempts resolve by rule. Both
307
+ roles bind the handshake to the certificate the DTLS layer verified and take one remote description
308
+ with exactly one fingerprint; before admission only handshake frames cross, and a connection counts
309
+ as admitted only once both sides admitted each other. Each connection gets its own DTLS certificate
310
+ (`createDtlsKeys`). A new attempt never displaces an admitted connection until it is admitted
311
+ itself, and attempts per pair are paced. Lists adopted in a handshake, or handed over through
312
+ `refresh`, apply at once, and a device they revoke loses its connection. Signaling runs through
313
+ `IMeshRelay`: `WsMeshRelayClient` for the self-hosted relay's `presence` / `message` frames
314
+ (topics capped per source and relay-wide), `createInMemoryMeshRelayHub` for tests.
315
+ - `agent-remote-pairing` — the pair's two relay inbox topics, one per direction, come from their
316
+ pairwise secret (`derivePairRendezvous(...).relayInbox()`).
317
+ - `agent-cli` — a device holding the signing key reissues its roster and revocation list before they
318
+ expire while an interactive session runs. The host can open this device's mesh endpoint from the
319
+ identity under `~/.robota/devices`, saving newer lists a peer hands over; no command starts it yet.
320
+ - `agent-command` — `/devices add|join` still reports that enrolment is not available yet.
321
+
322
+ - Updated dependencies [c7f9203]
323
+ - @robota-sdk/agent-core@3.0.0-beta.82
324
+ - @robota-sdk/agent-framework@3.0.0-beta.82
325
+ - @robota-sdk/agent-interface-command@3.0.0-beta.82
326
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.82
327
+ - @robota-sdk/agent-interface-session@3.0.0-beta.82
328
+ - @robota-sdk/agent-preset@3.0.0-beta.82
329
+
330
+ ## 3.0.0-beta.81
331
+
332
+ ### Minor Changes
333
+
334
+ - 44fc732: Add `/devices` for this device's identity among the user's devices: `list`, `init` (creates the identity: a recovery phrase, the master-certified signing key, this device's keys and certificate, the first roster and revocation list), `revoke <device-id>` (signing key only, no phrase; confirmed at the terminal) and `recover` (rotates the signing key from the phrase and revokes the old ones). Enrolling another device (`add` / `join`) comes with the device connection.
335
+
336
+ The recovery phrase never enters the session: it is shown once and read with no echo on the controlling terminal (opened apart from the session's input), on the alternate screen that is cleared afterwards, and never reaches prompt history, conversation history, transcripts, traces or the model. Without an interactive terminal the phrase commands refuse. `/devices` is operator-only: never model-invocable and refused from remote surfaces. Private keys live in the host credential store; certificates, roster, revocation lists and sequence marks are kept in owner-only files under `~/.robota/devices`.
337
+
338
+ `agent-remote-pairing` adds `isRecoveryPhraseWord`, so a phrase can be checked one word at a time.
339
+
340
+ - 18b52cc: Built-in commands are offered to the model deliberately, each described for the model, and never
341
+ with a trust, credential or permission-widening action.
342
+
343
+ - `agent-interface-command` — `ICommand` gains `modelDescription?` (what the model is told, beside the
344
+ short `/help` line), and `modelInvocable` on a subcommand entry now narrows what the model may run.
345
+ - `agent-framework` — `ISystemCommand` gains `modelDescription?` and `modelRequiresPermission?`.
346
+ Once any subcommand of a model-invocable command declares `modelInvocable`, the model may run only
347
+ the bare command and the subcommands declared `true`; everything else, including an alias or an
348
+ undeclared subcommand, is refused before the command runs. The model-facing descriptor lists only
349
+ that subset. A model-requested monitor's command is now decided by the shell tool's gate (its
350
+ Bash/Shell rules, the mode and the prompt) and a refusal rejects with the new
351
+ `MonitorCommandRefusedError`. The `scriptedSession` test harness accepts `permissions` patterns.
352
+ - `agent-session` — `Session.checkToolPermission(toolName, toolArgs)` decides an action that has a
353
+ tool's effect by another route: that tool's PreToolUse hooks, then the gate's rules, mode,
354
+ remembered consent and prompt — never the command sandbox's auto-approval, since the action does
355
+ not run inside the sandbox.
356
+ - `agent-framework` also: `ICommandMCPActivationAdapter.userActionSurface?` tells `/mcp` whether the
357
+ user can type a session command, so the model's status names the terminal sign-in otherwise.
358
+ - `agent-command` — `/context` (bare and `list`), `/cost` (the report, not `budget`) and `/mcp`
359
+ (`status` only, without a prompt) are now model-invocable; `/memory approve` and `/memory reject`
360
+ are now user-only; the model's `/monitor` is decided by the shell gate rather than by consent to
361
+ the command's name. Every model-invocable command carries a model-facing description. The model's
362
+ `/mcp status` shows only safe names, states and the command to suggest, and a caller that does not
363
+ identify itself gets that view. `/context list` accounts only for turns still in context. New
364
+ `mcpUserActionNotice`, `mcpUserActionCommand` and `mcpUnavailableServersNotice` build the fixed
365
+ notices.
366
+ - `agent-command-workflows` — `/workflows` carries a model-facing description.
367
+ - `agent-mcp` — `createDiscoveredTool` accepts `authFailureNotice`: a call the server refuses for
368
+ authentication returns that host text instead of the generic failure.
369
+ - `agent-cli` — an MCP server that did not start because the user must approve it, trust the
370
+ workspace or sign in is named to the model at the start of an interactive session with the
371
+ command to suggest, and a
372
+ signed-in OAuth server that refuses a call tells the model to suggest `/mcp login <server>` — or, in print and serve runs, the terminal
373
+ `robota mcp login <server>`.
374
+
375
+ A command whose bare form is a complete action declares `runsBare`, so choosing `/cost` or `/mcp`
376
+ from the autocomplete menu still runs it even though they now declare subcommands.
377
+
378
+ - 9843fe6: Sign in to a remote MCP server from inside a session, and use its tools without restarting.
379
+
380
+ - **`/mcp login <server> [--no-browser]`** runs the same per-server OAuth sign-in as
381
+ `robota mcp login` (discovery checks, PKCE, `state`, RFC 9207 `iss`, RFC 8707 resource, the
382
+ loopback listener, the lock-guarded store). It opens the browser through the argv opener; with
383
+ `--no-browser`, or when no browser can be opened, it shows the authorization URL and asks for the
384
+ redirect URL in the session's own prompt (masked), held to the same rules as a pasted redirect in
385
+ the terminal. A failed, refused, timed-out or cancelled sign-in changes nothing and is reported by
386
+ a fixed reason only. `/mcp login <server> --client-secret` is refused: a secret is never typed into
387
+ a session, and `robota mcp login <server> --client-secret` is named instead (also after a failed
388
+ token exchange for a pre-registered client). `/mcp` stays user-only (`modelInvocable: false`).
389
+ - **Connected in the same session:** after a sign-in, a server that could not connect for want of
390
+ one goes through the normal admission (approval, fingerprint, trust) and connects, and its tools
391
+ are offered from the next message; a server that was already connected is admitted again and
392
+ reconnects, and its authenticator drops what it held and reads the new credential. A tool left out
393
+ because the session already has its name is reported, and only tools actually added get
394
+ provenance. In browser mode the authorization URL is shown in the session prompt before the
395
+ browser opens, where the user can also choose to paste the redirect instead or cancel.
396
+ - **`runMCPOAuthLogin`** takes `readRedirectWhenBrowserFails`: when `openBrowser` rejects, the
397
+ loopback listener stops and the pasted redirect is read instead, for the same redirect URI. The
398
+ loopback listener's time limit now runs from its first `wait()` — once the authorization page is
399
+ handed over — so time spent at a prompt before the browser opens does not count against it.
400
+ - **`Session.addTools`** (and `ICommandSessionTools.addTools`) offers tools that became usable
401
+ mid-session, through the same permission gate and — via `ISessionOptions.wrapAddedTools`, which
402
+ `createSession` sets — the same edit-checkpoint and reversible-execution wraps as the assembled
403
+ tools. A name the session already has is left out, never replaced. Calls are serialized, and tools
404
+ added while a turn runs are applied when the next turn starts, so a turn's rounds all see one
405
+ tool list and the prompt cache misses once, at that boundary.
406
+ - **Breaking (`agent-framework`, major):** `addTools` is a new required member of the
407
+ `ICommandSessionTools` role port (and so of `ICommandSessionRuntime`). A host that implements the
408
+ port itself must add it; one that passes an `agent-session` `Session` already has it.
409
+ - **`ICommandMCPActivationAdapter.oauthLogin`** (`ICommandMCPOAuthLoginRequest`,
410
+ `ICommandMCPOAuthLoginResult`, `ICommandMCPOAuthRedirectPrompt`) is the port behind it.
411
+ - The sign-in notice and `/mcp status` now suggest `/mcp login <server>` in a session and
412
+ `robota mcp login <server>` in a terminal; the server's name is shown only when it is safe to paste
413
+ into any shell, otherwise `<server>`.
414
+
415
+ ### Patch Changes
416
+
417
+ - ec5e477: Add a credential store port (`ICredentialStore` in `agent-core`) and keep the CLI's secrets behind it: the OS keychain through the optional `@napi-rs/keyring` binding (macOS Keychain, Windows Credential Manager, Linux Secret Service), else an owner-only file under `~/.robota/credentials`. The backend is chosen at first use, recorded, and named by `/remote-control status`; a recorded keychain that stops working fails closed instead of degrading to the file.
418
+
419
+ The remote-control host identity key moves into the store. The old `~/.robota/remote-host-identity.json` may have been copied by backups or dotfile sync, so it is not carried over: on the first run after upgrading a new host key is generated, the old file is removed, and the operator is told once that trusted devices must pair again.
420
+
421
+ - 007fd90: Authority per connection: pairing stays with the local operator, and driving needs the operator's yes.
422
+
423
+ - `agent-interface-session-mobility` — `ConnectionAuthority` decides what one connection may do.
424
+ `presence` and `message` are allowed; `delegate` and `handoff` ask the receiving operator for every
425
+ request; `observe` and `drive` ask once per connection. With no `IOperatorApprover` the answer is
426
+ no. `authorizeDelegation` turns an approved task into a peer turn from where admission placed the
427
+ peer, ignoring anything else on the request, so the receiver's policy decides what it may do.
428
+ - `agent-transport-webrtc` — `connectionApproval` asks the operator before a connection reaches the
429
+ session, after every proof has run. Frames the peer sends meanwhile are held (bounded) and delivered
430
+ only after a yes. A channel that closes first withdraws the question (the approval context carries
431
+ an `AbortSignal`), and a later answer admits nothing. A first-pairing device is pinned for
432
+ reconnect only once it is admitted.
433
+ - `agent-command` — `/remote-control enable` and `revoke` from a connected surface are refused, and
434
+ `status` never shows a connected surface the pairing link.
435
+ - `agent-framework` — the `remote-control-enable` host action runs only for the operator's own
436
+ command, whichever command asked for it.
437
+ - `agent-cli` — every remote-control connection, a returning trusted device included, is put to the
438
+ operator on the host terminal; without an interactive terminal it is refused.
439
+
440
+ - Updated dependencies [3038eb7]
441
+ - Updated dependencies [02b7452]
442
+ - Updated dependencies [ec5e477]
443
+ - Updated dependencies [007fd90]
444
+ - Updated dependencies [18b52cc]
445
+ - Updated dependencies [9843fe6]
446
+ - @robota-sdk/agent-core@3.0.0-beta.81
447
+ - @robota-sdk/agent-interface-session@3.0.0-beta.81
448
+ - @robota-sdk/agent-framework@3.0.0-beta.81
449
+ - @robota-sdk/agent-interface-command@3.0.0-beta.81
450
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.81
451
+ - @robota-sdk/agent-preset@3.0.0-beta.81
452
+
453
+ ## 3.0.0-beta.80
454
+
455
+ ### Major Changes
456
+
457
+ - 64ba748: **BREAKING — ARCH-042: project filesystem access is now an explicit, host-issued authority instead of an ambient consequence of `cwd`.**
458
+
459
+ `@robota-sdk/agent-framework` adds `WorkspaceTrustService` and the opaque
460
+ `IWorkspaceProjectAuthority`, plus bounded reader, settings-writer, state-storage, and mutation
461
+ facets. Public session, settings, context, checkpoint, memory, contribution, query, and replay
462
+ contracts consume those facets. A caller that does not supply `projectAccess` is deliberately
463
+ restricted to user-owned host state and receives no project filesystem capability.
464
+
465
+ The framework removes or renames ambient Node/project exports. Migrate `checkSettingsFile` to
466
+ `checkNodeHostSettingsFile`, `readMergedProviderSettingsFromPaths` to
467
+ `readMergedProviderSettingsFromSources`, `resolveProviderSettingsWriteTargetPath` to
468
+ `resolveProviderSettingsWriteTarget`, `FileSystemMemoryStore` / `createFileSystemMemoryStore` to
469
+ `WorkspaceMemoryStore` / `createWorkspaceMemoryStore`, and `PluginSettingsStore` to
470
+ `NodeHostPluginSettingsStore`. Host-only git helpers now carry the `FromNodeHost` suffix.
471
+ `projectPaths`, `resolveSettingsPathForScope`, and `getProviderSettingsPaths` are removed; project
472
+ consumers must use the authority facets rather than recover absolute paths.
473
+
474
+ `@robota-sdk/agent-session` renames the Node filesystem implementation `SessionStore` to
475
+ `NodeSessionStore` and adds explicit session-log/external-payload source and sink ports. Session
476
+ replay no longer resolves external payload files from an ambient directory.
477
+
478
+ `@robota-sdk/agent-interface-transport` changes `ISkillExecutionPort.loadCommands(cwd, home?)` to
479
+ the authority-bound `loadCommands()` and removes the optional absolute-path leak
480
+ `IInteractiveSessionStore.getFilePath`. `@robota-sdk/agent-command` consequently replaces the
481
+ `cwd` option of `createSkillsCommandModule` with required `contributionSources`; default command
482
+ composition accepts explicit contribution sources and discovers no project skills when none are
483
+ provided.
484
+
485
+ `@robota-sdk/agent-cli`, `@robota-sdk/agent-transport`, and
486
+ `@robota-sdk/agent-transport-tui` thread the trusted-or-restricted project decision through every
487
+ session surface. Embedded callers that need project settings, state, context, skills, checkpoints,
488
+ or mutation must mint access through `WorkspaceTrustService` and pass the returned
489
+ `projectAccess` (and a separately approved mutation/settings facet where required). Omitting it is
490
+ still type-compatible but is behaviorally breaking: the surface now fails closed instead of
491
+ reading or writing the current directory.
492
+
493
+ ### Minor Changes
494
+
495
+ - 9c19c50: `/fork [name] [--same-dir]` copies the live conversation into a background session.
496
+
497
+ The session writes a copy of its own record under a fresh id — messages, system prompt, tool schemas
498
+ and full history, and deliberately not the sandbox snapshot, goal, plan or branch — then spawns a
499
+ background job carrying only `resumeSessionId`. The child restores that record itself, so no
500
+ conversation crosses the child-process boundary and the worker start payload's key set is unchanged.
501
+ The background panel gains an `attach` control that switches the terminal onto the forked session; it
502
+ is a view switch, never a merge, and a missing record or a terminal task is refused with the task's
503
+ own status.
504
+
505
+ **`@robota-sdk/agent-framework` is `major` for one reason: `ICommandHostSessionAccess` gains a
506
+ required member.** `forkSession({ name? })` is not optional, so an external implementation of that
507
+ role port stops compiling until it adds the method. Every other change in this set is additive:
508
+
509
+ - `agent-interface-execution` — `TExecutionControl` gains `'attach'`.
510
+ - `agent-interface-command` — `TCommandUiIntent` gains `{ type: 'switch-session'; sessionId }`.
511
+ - `agent-subagent-runner` — `ISubagentWorkerComposition` gains the optional `openSessionStore`, and
512
+ the worker resumes a record when the job names one. A composition that registers no store and
513
+ receives no `resumeSessionId` behaves exactly as before.
514
+ - `agent-framework` also gains the fork-record builder, `SessionTurnMemory`, and
515
+ `IAgentBackgroundTaskRequest.resumeSessionId?`; `loadSessionRecord` now returns
516
+ `restoredSystemPrompt`, which makes a record field that was written and never read take effect on
517
+ restore.
518
+ - `agent-executor`, `agent-command`, `agent-transport-tui`, `agent-cli` — the spawn input, the
519
+ `/fork` module and the attach control that carry it to the surface.
520
+
521
+ - 9368d00: Advisor escalation: the main model can consult a second model at the decision points it chooses.
522
+
523
+ With an advisor configured (`--advisor <profile>[:<model>]`, or the `advisorModel` setting that
524
+ `/advisor` saves; the flag wins), the session gets an `Advisor({ question? })` tool. The advisor reads
525
+ the whole conversation — system prompt, messages, tool calls and results — serialized into one prompt
526
+ and sent with `toolChoice: 'none'`, truncated from the front to fit its window with the system prompt
527
+ kept, and declines when even that does not fit. Its answer comes back framed as guidance to verify;
528
+ an empty or refusing answer reads as declined. Calls are limited to two per turn and a fixed number
529
+ per session, parallel calls in one round share those limits, and a repeated question in the same
530
+ turn returns the earlier answer. A request that was sent counts even when the provider failed (the
531
+ decline is reported by class, never by its text); only a call declined before sending gives its slot
532
+ back.
533
+
534
+ Advisor usage, including in-process subagents', is recorded where each turn's usage is recorded —
535
+ the persisted session history, under the advisor's own provider and model — so `/cost`, usage reports
536
+ and resumed sessions include it. `/cost` now totals that history and prices each part on its own
537
+ model, showing "mixed" when more than one model was priced.
538
+
539
+ `/advisor <model>` and `/advisor off` change only where calls go, never the tool list, so the main
540
+ model's prompt cache is not invalidated mid-session; the tool is added only when a session starts
541
+ with an advisor. Sending history to a destination (provider type and endpoint host) the main model
542
+ does not already use needs a one-time consent per destination, kept in the user settings file; a
543
+ refusal is remembered for the session. The organization's `allowedProviders` applies, and
544
+ `ROBOTA_DISABLE_ADVISOR=1` turns it off completely. In-process subagents inherit the advisor, bound
545
+ to their own conversation; child-process subagents do not get it.
546
+
547
+ **`@robota-sdk/agent-framework` is `major` for one reason: `ICommandHostSessionAccess` gains a
548
+ required member,** `getSessionUsage()`, the session's persisted usage records. An external
549
+ implementation of that role port stops compiling until it adds the method. The rest is additive.
550
+
551
+ - `agent-session` — `formatConversationEntries`, the one text rendering of a conversation, now used
552
+ by compaction too. It keeps tool calls and results, marks a user message a peer session sent
553
+ (`user [from "peer:<id>"]`), and JSON-encodes every message onto one line so no content can forge
554
+ another entry; compaction previously flattened all of this. `Session.getProvider()` returns the
555
+ provider the session currently uses.
556
+ - `agent-framework` — `AdvisorController`, `createAdvisorTool`, the advisor spec helpers, provider
557
+ destinations (`describeProviderDestination`, `rememberProviderDestination`), `getSessionUsage` and
558
+ `ISessionUsageRecord`, the `onUsageRecorded` session option, and the optional `advisor` command
559
+ host adapter. Session assembly binds a host-supplied Advisor tool to the session holding it.
560
+ - `agent-command` — the `/advisor` command module; `/cost` reads the session's persisted usage.
561
+ - `agent-cli` — the `--advisor` flag, `advisorModel` setting, per-destination consent store and kill
562
+ switch.
563
+ - `agent-ui-terminal` — a usage line from another source (the advisor, a background task) names that
564
+ source and leaves out the context window it does not have.
565
+ - `agent-session-analytics` — personal usage counts an advisor call's tokens and cost toward its
566
+ turn without counting it as a turn.
567
+
568
+ - d4189b9: The rest of the per-server MCP OAuth lifecycle: signing in to a server without a local browser,
569
+ signing out of it with token revocation, and each server's sign-in state in `/mcp`.
570
+
571
+ - **`robota mcp login <name> --no-browser`** prints the authorization URL and reads the redirect URL
572
+ the user pastes back (not echoed). `runMCPOAuthLogin` takes `readRedirect` for this; nothing
573
+ listens on the redirect URI then. The pasted URL is held to the loopback listener's rules through
574
+ `createPastedRedirectAcceptor`: it must be the registered redirect URI (same origin and path, no
575
+ user info), carry the sign-in's `state` (compared in constant time), and is accepted once; an
576
+ error redirect is `authorization-denied` without its `error_description`, and the RFC 9207 `iss`
577
+ check applies as before. `openBrowser` now also receives the redirect URI. `readRedirect` gets a
578
+ signal that aborts on cancel or at `callbackTimeoutMs` (5 minutes by default, as for the loopback
579
+ listener); a paste longer than the prompt accepts fails as `redirect-too-long`.
580
+ - **Signing out** (`runMCPOAuthLogout`; `robota mcp logout <name>`; `/mcp logout <serverId>`):
581
+ deletes the stored credential under the refresh lock, then revokes the refresh token and the
582
+ access token (RFC 7009) when the stored issuer advertises `revocation_endpoint`. Revocation is a
583
+ POST through the egress policy that never follows a redirect and is byte-bounded; it authenticates
584
+ the client by `revocation_endpoint_auth_methods_supported` when advertised, otherwise the way its
585
+ refresh does. The local delete always happens. Each token's outcome is reported in `tokens`, and
586
+ overall as `revoked`, `partial`, `unsupported`, `failed` or `not-attempted`, with fixed reasons
587
+ only (new: `revocation-failed`, and `token-type-not-revocable` for RFC 7009
588
+ `unsupported_token_type`). `/mcp logout` also makes the session's authenticator drop the token it
589
+ holds (`IMCPOAuthAuthenticator.forget`).
590
+ - **Sign-in state:** `readMCPOAuthCredentialState` answers `signed-in`, `expired-refreshable`,
591
+ `sign-in-required` or `signed-out` — never anything token-derived. `/mcp` shows it for every
592
+ OAuth server; a server this session was told needs a sign-in reads `sign-in-required`.
593
+ `ICommandMCPActivationAdapter` gains optional `oauthStatus` and `oauthLogout`
594
+ (`ICommandMCPOAuthStatus`, `ICommandMCPOAuthLogoutResult`).
595
+ - **No in-session sign-in:** signing in stays `robota mcp login <server>` in a terminal, since it
596
+ needs the terminal (browser, pasted redirect, hidden secret prompt) a running session owns. `/mcp`
597
+ names that command for a server that needs a sign-in, as does the session's sign-in notice; the
598
+ server name is shown there only when it is safe to paste into any shell — a plain token not
599
+ starting with `-` or `=` — and is otherwise replaced by `<server>` (`shellArgumentForDisplay` in
600
+ `agent-core`; nothing is quoted, since quoting rules differ between shells). Server names in OAuth
601
+ notices have control and format characters escaped.
602
+ - **Refresh hardening:** on `invalid_grant`, the store is read again under the lock; a refresh token
603
+ another holder rotated in meanwhile is kept (and used when still valid) instead of being deleted.
604
+ The expiry skew is capped at half the token's lifetime, so a short-lived token is not refreshed on
605
+ every request; credentials now record `issuedAt` for this.
606
+
607
+ - af2f2ad: `/cd <directory>` continues the conversation in another directory.
608
+
609
+ - **A move is a new session in the target directory.** In the TUI, robota saves a copy of the
610
+ conversation where the target's session store will find it, ends the current run through its
611
+ normal end-of-life flow, and starts again in the target directory resuming that copy. The target's
612
+ settings, trust decision, tools, skills and `AGENTS.md` apply, exactly as if robota had been
613
+ launched there. The process boundary makes the move atomic, so no tool call can straddle it.
614
+ - **The system prompt is kept as recorded**, so a provider's prompt cache survives. One appended
615
+ `<workspace-move>` message tells the model the new directory, and which project instructions now
616
+ apply.
617
+ - **Refused** while a turn is running or a background task is still running, for a missing directory
618
+ or the current one, and for a target a `Cd(...)` deny rule names.
619
+ - **Access never widens:** a restricted session stays restricted after a move, and a trusted session
620
+ takes the target's own trust decision.
621
+ - New contracts: the `workspace-move` host action, `ICommandWorkspaceAdapter` /
622
+ `IWorkspaceMoveRequest`, `InteractiveSession.moveWorkspace`, and the `workspaceMovedFrom` session
623
+ option. The CLI's `--moved-from` and `--restricted-workspace` flags are internal.
624
+
625
+ - 34e50f0: A new permission mode, `auto`, lets a model classifier approve or block what would otherwise prompt.
626
+
627
+ - **What it decides:**
628
+ - Reads and in-workspace edits run as in `acceptEdits`.
629
+ - Commands and other calls the mode leaves open go to the classifier, a side call to the
630
+ session's own model. It sees the call, the working directory and the git remotes, never the
631
+ conversation.
632
+ - A block reaches the model with its reason, so it can take another route.
633
+ - **What still reaches a person, or is refused:**
634
+ - Deny rules and background ceilings apply first.
635
+ - `ask` rules, critical removals and protected paths ask a person.
636
+ - After 3 refusals in a row (blocks, or no usable verdict), or 20 blocks in the session, the
637
+ mode asks a person until one approves.
638
+ With no one to ask, the call is denied.
639
+ - **Allow rules:** in `auto` mode, allow rules that approve any command are set aside while the
640
+ mode is on. Examples are `Bash(*)`, an interpreter (`Bash(python *)`), a package runner
641
+ (`Bash(npm run *)`, `Bash(pnpm exec *)`), `Agent`, `ExecuteCommand` or `Computer`. Narrow
642
+ rules still apply.
643
+ - **Retry:** `/permissions` lists classifier blocks. `/permissions retry <n>` lets that exact call
644
+ run once, unjudged, when the model tries it again.
645
+ - **Turning it on and off:**
646
+ - `--permission-mode auto`, `/mode auto` or `/permissions auto`.
647
+ - An organization turns it off with `disableAutoMode` in the org policy.
648
+ - **New contracts:**
649
+ - `TPermissionMode` gains `'auto'`.
650
+ - `allowRulesForAutoMode` and `isBroadExecutionAllowRule`.
651
+ - `IPermissionClassifier` and `AutoModeGate`.
652
+ - The `permissionClassifier` session option.
653
+ - `Session.retryPermissionDenial`, and `retryDenial` on the permission-mode adapter.
654
+ - The `'classifier'` denial reason.
655
+ - `createModelPermissionClassifier`.
656
+ - The `disableAutoMode` option on `createSession` and `IOrgPolicy`.
657
+
658
+ - 722e88a: Shell commands can run in an OS-level sandbox: bubblewrap on Linux and WSL2, Seatbelt on macOS.
659
+
660
+ - **Confinement:** covers the command and every process it starts.
661
+ - Writes are limited to the working directory, the temporary directories and
662
+ `sandbox.filesystem.allowWrite`.
663
+ - Agent, git-hook, MCP and shell configuration inside the workspace stays read-only.
664
+ - `sandbox.filesystem.denyRead` hides paths from the command.
665
+ - The network is on or off (`sandbox.network.enabled`).
666
+ - **Modes:** `/sandbox` switches between `auto-allow`, `regular` and `off` for the next command and
667
+ saves the choice.
668
+ - In `auto-allow` (`sandbox.autoAllowBashIfSandboxed`), a confined command runs without a prompt
669
+ in `default` and `acceptEdits`.
670
+ - Deny rules, ask rules, critical removals and plan mode still apply first.
671
+ - **Exclusions:** `sandbox.excludedCommands` run unconfined, through the ordinary permission path.
672
+ - **When the sandbox cannot run:** a missing or unusable backend is reported at startup, in
673
+ `robota doctor` and in `/sandbox`, and commands then run unconfined.
674
+ `sandbox.failIfUnavailable` refuses to start instead.
675
+ - **New contracts:**
676
+ - `OsSandboxClient`, `detectOsSandbox`, `bubblewrapArguments`, `seatbeltProfile`.
677
+ - `ISandboxClient.wrapCommand` and `autoApproves`.
678
+ - `IPermissionEvaluationContext.sandboxAutoApproved`.
679
+ - The `commandSandbox` session option.
680
+ - The `sandbox` settings key and the `sandbox` command host adapter.
681
+
682
+ - a5cc36e: `/permissions` shows the rules the session enforces and the calls it refused.
683
+
684
+ - **Rules by source:** each allow, deny and ask rule the gate reads is listed under the settings file
685
+ that declares it. Rules added by a CLI flag, a preset or a command are listed under "this session".
686
+ A rule a settings file declares but the session does not enforce is not shown.
687
+ - **Recent denials:** the latest refused calls, most recent first, with the reason: a rule or the
688
+ mode, the user declining, or no one available to approve.
689
+ - New contracts: `Session.getRecentPermissionDenials()`, `PermissionEnforcer.getRecentDenials()`,
690
+ `IPermissionDenial`, the `permissionRules` host adapter (`createSettingsPermissionRulesAdapter`),
691
+ and `getPermissionRules` / `listRecentDenials` on `ICommandPermissionModeAdapter`. Settings
692
+ provenance now covers `permissions.ask`.
693
+
694
+ - 4dd45cc: `/peers` shows how each other local session's workspace relates to this one's: `same worktree`,
695
+ `same repo`, `different repo`, or `workspace unknown`.
696
+
697
+ A session now publishes a workspace claim with its rendezvous entry — the root commits reachable
698
+ from HEAD, a SHA-256 of its normalized `origin` URL (never the URL itself), and the real path of its
699
+ worktree — and re-reads it as it runs, so a first commit or a checkout does not leave it stale. The
700
+ reader does not take the claim as written: it reads git at the claimed path itself, and a claim whose
701
+ contents disagree is shown as `workspace claim mismatched, not believed` and relates to nothing. Those
702
+ git reads are local-only and asynchronous, run only for the view that shows the relation (and for
703
+ the sender of an incoming peer message), and are cached per announcement. The relation also reaches
704
+ the peer-turn origin, computed by the receiver; a relation the sender put on the wire is discarded,
705
+ and the admission never carries it.
706
+
707
+ The relation is display and routing information only and is never an authorization input.
708
+
709
+ Additive: `agent-interface-session-mobility` exports `TWorkspaceRelation` and gains the optional
710
+ `IPeerOrigin.workspaceRelation`; `agent-framework`'s `ILocalPeerSummary` gains the optional
711
+ `workspaceRelation` and `workspaceClaim`, and `ICommandLocalPeersAdapter` the optional
712
+ `listWithWorkspace()`.
713
+
714
+ - 2d3b2c0: ARCH-024 replaces framework knowledge of command-owner ids with optional, owner-declared semantic
715
+ roles. `ISystemCommand` can declare `skillActivation`, `contextReduction`, or `subagentSpawn`;
716
+ `SystemCommandExecutor` exposes the selected role projection and rejects duplicate owners with the
717
+ typed `DuplicateSystemCommandSemanticRoleError`, atomically across construction, registration, and
718
+ replacement.
719
+
720
+ This is a beta-line breaking contract correction: unannotated commands named `skills`, `compact`, or
721
+ `agent` no longer receive special framework behavior. `@robota-sdk/agent-command` now declares the
722
+ roles on its shipped skills, compact, and agent commands.
723
+
724
+ - 1e3f91a: CMD-004 Phase 2 Stage E (breaking, beta line): the legacy `TCommandEffect` union and
725
+ `ICommandResult.effects` are DELETED. Commands emit the split contract directly —
726
+ `hostActions` (session-executed via `ICommandHostAdapters`; works headless and remote) and
727
+ `uiIntents` (requester-routed `ui_intent` session events with UI-neutral `show-*` names).
728
+ Final carriers for the former notification effects: `session_renamed` and the new
729
+ `history_cleared` are BROADCAST session events (forwarded to every WS surface, folded by the
730
+ TUI transcript/title and the GUI reducer's new `sessionName`/transcript-reset state);
731
+ `session-execution-started` rides `result.data.sessionExecution`; the plugin-registry refresh
732
+ rides `result.data.pluginRegistryReloaded`. A mechanical grep floor
733
+ (`command-effect-grep-floor.test.ts`) keeps `tui-requested`/`TCommandEffect`/`effects:` out of
734
+ every `packages/*/src` production tree.
735
+ - 44393be: Add the `/remote-control` enable path (REMOTE-008 Stage B4-2b) — turn on P2P remote control locally, get
736
+ a QR + link, and a paired device co-drives the SAME live session over pairing-gated WebRTC. The command
737
+ is a declarative trigger returning `remote-control-enable-requested`/`-stop-requested` effects (SSOT
738
+ agent-interface-transport) and reads state via a new `ICommandHostAdapters.remoteControl.getStatus()`;
739
+ the TUI dispatches the effects to injected callbacks; all transport construction lives at the agent-cli
740
+ composition root (`WsSignalingClient` + pairing-gated `WebRtcTransport`, relay URL from
741
+ `transports.webrtc.options.relayUrl`, QR/link rendered into history). Fail-closed: no relay configured ⇒
742
+ does nothing; pairing mismatch/timeout ⇒ the session is never exposed. Consumes REMOTE-007 so a paired
743
+ remote owner answers their own permission/ask prompts over the WebRTC channel.
744
+ - cbee54e: Surface unmatched preset command-module names instead of silently dropping them (INFRA-032). A preset `enabledCommandModules`/`disabledCommandModules` entry that matches no built command module — a short form like `"editor"` instead of `agent-command-editor`, or a typo — is now reported as a non-fatal notice on both the startup `--preset` path (CLI terminal) and the in-session `/preset` path (command result). Detection lives once in agent-framework's new pure `findUnknownModuleNames`, and agent-command's duplicate module filter now delegates to the framework's `selectCommandModules`; `createDefaultCommandModules` returns `{ modules, unknownModuleNames }`.
745
+
746
+ ### Patch Changes
747
+
748
+ - b462ee7: Discriminate `IBackgroundTaskState` by kind, the same way `TBackgroundTaskRequest` and (as of the
749
+ prior change) `TBackgroundTaskResult` already are. Fields only one runner ever produces now live
750
+ only on that kind's member instead of being optional-and-cross-kind-reachable on every kind:
751
+
752
+ - `agent`-only: `agentType`, `isolation`, `resumeSessionId`, `promptPreview`, and the
753
+ worktree-isolation fields (`worktreePath`, `branchName`, `worktreeStatus`, `worktreeNextAction`,
754
+ `worktreeBaseRevision`, `parentWorktreeStatus`).
755
+ - `scheduled`-only: `schedule`, `nextFireAt`.
756
+ - Every kind except `agent`: `commandPreview` (a process command, an MCP tool-invocation summary, or
757
+ a schedule's shell command / wake instruction).
758
+ - `state.result` is now `IBackgroundTaskResult<K>` — correlated with `state.kind`, not the free
759
+ full-result union.
760
+
761
+ `pid`, `logPath`, and `transcriptPath` stay on the shared base rather than becoming agent- or
762
+ process-exclusive: the runner handle SPI already reports them for whichever runner's process
763
+ happens to produce them, and a subagent run via the worktree/child-process runner carries a `pid`
764
+ exactly as a `process`-kind task does. `timeoutReason` also stays base — session restore sets
765
+ `'stale_worker'` on any non-terminal, non-rearmable task regardless of kind, not only agent ones.
766
+
767
+ `IBackgroundTaskState<K>` narrows to the kind-specific member; called with no type argument it is
768
+ still the full union. The session-record decoder (`agent-session`) now rejects a persisted task
769
+ state carrying a field outside its own kind as corrupt, reported at that field's own path, the same
770
+ way it already rejects a `state.result` whose kind disagrees with `state.kind`.
771
+
772
+ **Breaking for `@robota-sdk/agent-interface-execution` and `@robota-sdk/agent-executor`**: code that
773
+ read a kind-specific field (e.g. `state.agentType`, `state.schedule`, `state.commandPreview`) off an
774
+ unnarrowed `IBackgroundTaskState` needs to narrow on `state.kind` first, since the fallback default
775
+ no longer carries every field on every kind. `agent-session`, `agent-framework`, and `agent-command`
776
+ land the corresponding narrowing at every read site the type change touched; no runtime behavior
777
+ changes there beyond the state decoder's new corruption checks.
778
+
779
+ - 3a8876b: ARCH-029: decompose the command host into role ports
780
+
781
+ `ICommandHostContext`, `ICommandSessionRuntime` and `IAgentJobHostContext` are now empty `extends`
782
+ aggregates over 26 named role ports, so a command declares only the capability it uses. A role port
783
+ is a supertype of the aggregate, so narrowing a declared parameter still satisfies
784
+ `ISystemCommand.execute` by contravariance.
785
+
786
+ All 79 members are preserved (46 + 18 + 15) with the declaration kind unchanged, so implementors and
787
+ callers stay source-compatible.
788
+
789
+ **Breaking:** every role-port member is now required except the adapter bag, whose contents are
790
+ genuinely variational. 38 members went from optional to required. A host that previously omitted a
791
+ member must now provide one — including `validateCurrentSessionReplayLog`, which was an override
792
+ with a framework-computed default and no implementor. `createTestCommandHost`,
793
+ `createTestAgentJobHost` and `createTestSessionRuntime` are published from
794
+ `@robota-sdk/agent-framework/testing` as conformant, cast-free doubles for exactly this.
795
+
796
+ Also removed: the `clearConversationHistory` fallback that reached past the host into
797
+ `getSession().clearHistory()`. Those were never the same operation — the host path also broadcasts
798
+ `history_cleared` to every attached surface, so a fallback clear left other surfaces still showing
799
+ the transcript.
800
+
801
+ - 4f3c075: Assemble complete, verified package generations before switching build output; preserve the previous generation on build failure and pack only verified regular-file images. Include copied CLI web assets in affected-build ordering and artifact transfer. Preserve the CLI version in managed build paths. Public runtime contracts remain compatible (patch).
802
+ - d6b9404: Remove polynomial-ReDoS backtracking (SEC-003, CodeQL `js/polynomial-redos`) from three parsers whose input is not repo-controlled.
803
+
804
+ `parseStructuredResponseText` (agent-core) parses raw model output; its fenced-code-block regex used `\s*\n`, and because `\s` also matches a newline the two overlapped, so an unterminated fence containing many blank lines was rejected in O(n^2) — 12.7s for a 400 KB string, now ~1ms. The whitespace run is now restricted to horizontal whitespace, which makes the newline split point unique.
805
+
806
+ `/schedule cron` and `/monitor` (agent-command) are declared `modelInvocable: true`, so their argument string is composed by the model. Both matched the trailing instruction with `\s+(.+)$`; since `.` also matches a space the split point was ambiguous and a non-matching argument cost O(n^2) — ~15s for a 200 KB argument, now <1ms. The instruction is now required to start with a non-space character, which pins the split point without changing which inputs are accepted.
807
+
808
+ No behaviour change: the set of accepted inputs and the parsed values are identical in every case.
809
+
810
+ - Updated dependencies [9c19c50]
811
+ - Updated dependencies [7b6234c]
812
+ - Updated dependencies [5307f8a]
813
+ - Updated dependencies [b462ee7]
814
+ - Updated dependencies [08a9bd6]
815
+ - Updated dependencies [37b4bd7]
816
+ - Updated dependencies [818f0c8]
817
+ - Updated dependencies [4eea54b]
818
+ - Updated dependencies [1698be4]
819
+ - Updated dependencies [9368d00]
820
+ - Updated dependencies [d4189b9]
821
+ - Updated dependencies [9edae52]
822
+ - Updated dependencies [4078a72]
823
+ - Updated dependencies [4c73a0b]
824
+ - Updated dependencies [af2f2ad]
825
+ - Updated dependencies [267af5f]
826
+ - Updated dependencies [196a900]
827
+ - Updated dependencies [f336838]
828
+ - Updated dependencies [34e50f0]
829
+ - Updated dependencies [722e88a]
830
+ - Updated dependencies [a5cc36e]
831
+ - Updated dependencies [d23c848]
832
+ - Updated dependencies [b70fa3d]
833
+ - Updated dependencies [2711ec6]
834
+ - Updated dependencies [4dd45cc]
835
+ - Updated dependencies [378c585]
836
+ - Updated dependencies [4c5148e]
837
+ - Updated dependencies [37af5dc]
838
+ - Updated dependencies [807d161]
839
+ - Updated dependencies [fec722f]
840
+ - Updated dependencies [e82215f]
841
+ - Updated dependencies [52b7346]
842
+ - Updated dependencies [2ebff01]
843
+ - Updated dependencies [2ebff01]
844
+ - Updated dependencies [2d3b2c0]
845
+ - Updated dependencies [b078afa]
846
+ - Updated dependencies [2d3b2c0]
847
+ - Updated dependencies [baa6863]
848
+ - Updated dependencies [2d3b2c0]
849
+ - Updated dependencies [3a8876b]
850
+ - Updated dependencies [4772067]
851
+ - Updated dependencies [7b85767]
852
+ - Updated dependencies [0f98419]
853
+ - Updated dependencies [64ba748]
854
+ - Updated dependencies [9fbab1b]
855
+ - Updated dependencies [d312755]
856
+ - Updated dependencies [a009f5b]
857
+ - Updated dependencies [1e3f91a]
858
+ - Updated dependencies [4f3c075]
859
+ - Updated dependencies [475e085]
860
+ - Updated dependencies [e477440]
861
+ - Updated dependencies [9dcb5da]
862
+ - Updated dependencies [a95ca85]
863
+ - Updated dependencies [b6d14ce]
864
+ - Updated dependencies [0382a51]
865
+ - Updated dependencies [93d061d]
866
+ - Updated dependencies [39554a1]
867
+ - Updated dependencies [d28430a]
868
+ - Updated dependencies [bed26ea]
869
+ - Updated dependencies [fe48835]
870
+ - Updated dependencies [1e40b5b]
871
+ - Updated dependencies [4b76cfa]
872
+ - Updated dependencies [d9bd9ec]
873
+ - Updated dependencies [8865acf]
874
+ - Updated dependencies [90e7a10]
875
+ - Updated dependencies [fcb0da3]
876
+ - Updated dependencies [07b627f]
877
+ - Updated dependencies [d0de5b2]
878
+ - Updated dependencies [9665c6e]
879
+ - Updated dependencies [44393be]
880
+ - Updated dependencies [c7fa299]
881
+ - Updated dependencies [5134b3b]
882
+ - Updated dependencies [dd444c1]
883
+ - Updated dependencies [1f57e7f]
884
+ - Updated dependencies [833afe1]
885
+ - Updated dependencies [d6b9404]
886
+ - Updated dependencies [7863b16]
887
+ - Updated dependencies [fde558e]
888
+ - Updated dependencies [db5c439]
889
+ - Updated dependencies [4a01a87]
890
+ - Updated dependencies [cbee54e]
891
+ - Updated dependencies [9814afc]
892
+ - Updated dependencies [242a644]
893
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.80
894
+ - @robota-sdk/agent-interface-command@3.0.0-beta.80
895
+ - @robota-sdk/agent-framework@3.0.0-beta.80
896
+ - @robota-sdk/agent-core@3.0.0-beta.80
897
+ - @robota-sdk/agent-interface-session@3.0.0-beta.80
898
+ - @robota-sdk/agent-preset@3.0.0-beta.80
899
+
900
+ ## 3.0.0-beta.79
901
+
902
+ ### Patch Changes
903
+
904
+ - @robota-sdk/agent-core@3.0.0-beta.79
905
+ - @robota-sdk/agent-framework@3.0.0-beta.79
906
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.79
907
+ - @robota-sdk/agent-preset@3.0.0-beta.79
908
+
909
+ ## 3.0.0-beta.78
910
+
911
+ ### Patch Changes
912
+
913
+ - Updated dependencies [6f308d1]
914
+ - @robota-sdk/agent-core@3.0.0-beta.78
915
+ - @robota-sdk/agent-framework@3.0.0-beta.78
916
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.78
917
+ - @robota-sdk/agent-preset@3.0.0-beta.78
918
+
919
+ ## 3.0.0-beta.77
920
+
921
+ ### Patch Changes
922
+
923
+ - Updated dependencies
924
+ - @robota-sdk/agent-core@3.0.0-beta.77
925
+ - @robota-sdk/agent-framework@3.0.0-beta.77
926
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.77
927
+ - @robota-sdk/agent-preset@3.0.0-beta.77
928
+
929
+ ## 3.0.0-beta.76
930
+
931
+ ### Patch Changes
932
+
933
+ - DQ-AUDIT-002 — consolidate duplicated domain data onto single owners: one model-pricing SSOT in agent-core (`MODEL_PRICES`/`lookupModelPrice`/`calculateModelCost`/`estimateBlendedCostPer1000`) consumed by agent-command and agent-plugin (drops two embedded/stale price tables); the `len/4` token estimator replaced by core `CONTEXT_ESTIMATE_CHARS_PER_TOKEN`; TUI `TContextState` derived from core `IContextWindowState`; dead pass-through re-exports removed from agent-session.
934
+ - 576af62: Fix `ConfigurationError: Agent must be fully initialized before changing model configuration` when running `/preset` (or any live model re-apply) on a fresh interactive session before the first message. The Robota agent initialized lazily on the first `run()`, but `setModel` requires full initialization. `Session.applyModelOptions` now awaits the new idempotent `Robota.ensureReady()` before `setModel`, and the preset live-switch path (`applyPresetToSession` → `executePresetCommand`) is async end-to-end. Adds a real cold-session regression test (no mocked Robota).
935
+ - Updated dependencies
936
+ - Updated dependencies [c0a6287]
937
+ - Updated dependencies [9df3a88]
938
+ - Updated dependencies
939
+ - Updated dependencies
940
+ - Updated dependencies [576af62]
941
+ - @robota-sdk/agent-core@3.0.0-beta.76
942
+ - @robota-sdk/agent-framework@3.0.0-beta.76
943
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.76
944
+ - @robota-sdk/agent-preset@3.0.0-beta.76
945
+
946
+ ## 3.0.0-beta.75
947
+
948
+ ### Patch Changes
949
+
950
+ - Agent preset system + live preset switching + context/history correctness fixes.
951
+
952
+ - **Preset system (PRESET-001~017):** new `@robota-sdk/agent-preset` package layering framework
953
+ assembly options into named, selectable profiles (`default`, `autonomous-builder`, `careful-reviewer`,
954
+ `neutral-executor`) plus user-authored external presets loaded from `~/.robota/presets/*.json`.
955
+ - **Live preset switching:** `/preset` command (list + active marker + switch) and a TUI active-preset
956
+ display. Switching live re-applies permission posture, model/effort, persona, command-module
957
+ selection, parallel-subagents gating, and a self-verification system-prompt section via the single
958
+ `applyPresetToSession` engine.
959
+ - **CTX-001:** the TUI Context display + session auto-compact now use the accurate provider-based token
960
+ estimate (system prompt + tool schemas included) instead of a crude history-only char heuristic.
961
+ - **HIST-001:** conversation history is now append-only — removed the silent 100-message count cap that
962
+ could drop early context; context size is managed solely by size-based compaction.
963
+
964
+ - Updated dependencies
965
+ - @robota-sdk/agent-preset@3.0.0-beta.75
966
+ - @robota-sdk/agent-framework@3.0.0-beta.75
967
+ - @robota-sdk/agent-core@3.0.0-beta.75
968
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.75
969
+
970
+ ## 3.0.0-beta.74
971
+
972
+ ### Patch Changes
973
+
974
+ - Updated dependencies
975
+ - @robota-sdk/agent-framework@3.0.0-beta.74
976
+ - @robota-sdk/agent-core@3.0.0-beta.74
977
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.74
978
+
979
+ ## 3.0.0-beta.73
980
+
981
+ ### Patch Changes
982
+
983
+ - @robota-sdk/agent-core@3.0.0-beta.73
984
+ - @robota-sdk/agent-framework@3.0.0-beta.73
985
+
986
+ ## 3.0.0-beta.72
987
+
988
+ ### Patch Changes
989
+
990
+ - Updated dependencies
991
+ - @robota-sdk/agent-framework@3.0.0-beta.72
992
+ - @robota-sdk/agent-core@3.0.0-beta.72
993
+
994
+ ## 3.0.0-beta.71
995
+
996
+ ### Patch Changes
997
+
998
+ - fix(context): unify token estimation to single SSOT — status bar and /context list now use the same serialized JSON estimate
999
+ - Updated dependencies
1000
+ - @robota-sdk/agent-core@3.0.0-beta.71
1001
+ - @robota-sdk/agent-framework@3.0.0-beta.71
1002
+
1003
+ ## 3.0.0-beta.70
1004
+
1005
+ ### Patch Changes
1006
+
1007
+ - CLI UX fixes: /context list full LLM context breakdown (CLI-B10), logo resize fix (CLI-B03), token estimates in context list (CLI-B04)
1008
+ - Updated dependencies
1009
+ - @robota-sdk/agent-framework@3.0.0-beta.70
1010
+ - @robota-sdk/agent-core@3.0.0-beta.70
1011
+
1012
+ ## 3.0.0-beta.69
1013
+
1014
+ ### Patch Changes
1015
+
1016
+ - Updated dependencies
1017
+ - @robota-sdk/agent-framework@3.0.0-beta.69
1018
+ - @robota-sdk/agent-core@3.0.0-beta.69
1019
+
1020
+ ## 3.0.0-beta.68
1021
+
1022
+ ### Patch Changes
1023
+
1024
+ - @robota-sdk/agent-core@3.0.0-beta.68
1025
+ - @robota-sdk/agent-framework@3.0.0-beta.68
1026
+
1027
+ ## 3.0.0-beta.67
1028
+
1029
+ ### Patch Changes
1030
+
1031
+ - Updated dependencies
1032
+ - @robota-sdk/agent-framework@3.0.0-beta.67
1033
+ - @robota-sdk/agent-core@3.0.0-beta.67
1034
+
1035
+ ## 3.0.0-beta.66
1036
+
1037
+ ### Patch Changes
1038
+
1039
+ - refactor: CLI-001/002 — agent-cli layer separation and monorepo-wide readability lint rules
1040
+ - CLI-001: Extract startup phases into focused modules; enforce agent-cli layer separation
1041
+ - CLI-002: Apply import/order, consistent-type-imports, explicit-function-return-type, prefer-const, object-shorthand across all packages
1042
+ - Fix stale child-process-subagent-worker entry in agent-cli tsdown.config.ts (build fix)
1043
+
1044
+ - Updated dependencies
1045
+ - @robota-sdk/agent-framework@3.0.0-beta.66
1046
+ - @robota-sdk/agent-core@3.0.0-beta.66
1047
+
1048
+ ## 3.0.0-beta.65
1049
+
1050
+ ### Patch Changes
1051
+
1052
+ - @robota-sdk/agent-core@3.0.0-beta.65
1053
+ - @robota-sdk/agent-framework@3.0.0-beta.65
1054
+
1055
+ ## 3.0.0-beta.64
1056
+
1057
+ ### Minor Changes
1058
+
1059
+ - feat: add displayName and requiresPermission to command interfaces
1060
+ - `ICommand`, `ISystemCommand`, `ICommandListEntry`: add optional `displayName` field for user-friendly labels
1061
+ - `ISystemCommand`: add optional `requiresPermission` field for per-command permission policy declaration
1062
+ - `SystemCommandExecutor`: add `resolveRequiresPermission()` — derives from `safety` when field is undefined
1063
+ - All 24 built-in commands declare explicit `displayName` and `requiresPermission`
1064
+ - TUI autocomplete renders `displayName ?? name`; Tab completion still inserts the technical command ID
1065
+ - `/help` output shows `Display Name (/command-id)` format
1066
+
1067
+ ### Patch Changes
1068
+
1069
+ - Updated dependencies
1070
+ - @robota-sdk/agent-framework@3.0.0-beta.64
1071
+ - @robota-sdk/agent-core@3.0.0-beta.64