@robota-sdk/agent-framework 3.0.0-beta.100

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 ADDED
@@ -0,0 +1,2924 @@
1
+ # @robota-sdk/agent-framework
2
+
3
+ ## 3.0.0-beta.100
4
+ ### Patch Changes
5
+
6
+ - @robota-sdk/agent-core@3.0.0-beta.100
7
+ - @robota-sdk/agent-executor@3.0.0-beta.100
8
+ - @robota-sdk/agent-file-authority@3.0.0-beta.100
9
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.100
10
+ - @robota-sdk/agent-interface-command@3.0.0-beta.100
11
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.100
12
+ - @robota-sdk/agent-interface-session@3.0.0-beta.100
13
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.100
14
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.100
15
+ - @robota-sdk/agent-roundtable@3.0.0-beta.100
16
+ - @robota-sdk/agent-session@3.0.0-beta.100
17
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.100
18
+ - @robota-sdk/agent-tools@3.0.0-beta.100
19
+
20
+ ## 3.0.0-beta.99
21
+ ### Patch Changes
22
+
23
+ - @robota-sdk/agent-core@3.0.0-beta.99
24
+ - @robota-sdk/agent-executor@3.0.0-beta.99
25
+ - @robota-sdk/agent-file-authority@3.0.0-beta.99
26
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.99
27
+ - @robota-sdk/agent-interface-command@3.0.0-beta.99
28
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.99
29
+ - @robota-sdk/agent-interface-session@3.0.0-beta.99
30
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.99
31
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.99
32
+ - @robota-sdk/agent-roundtable@3.0.0-beta.99
33
+ - @robota-sdk/agent-session@3.0.0-beta.99
34
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.99
35
+ - @robota-sdk/agent-tools@3.0.0-beta.99
36
+
37
+ ## 3.0.0-beta.98
38
+ ### Patch Changes
39
+
40
+ - @robota-sdk/agent-core@3.0.0-beta.98
41
+ - @robota-sdk/agent-executor@3.0.0-beta.98
42
+ - @robota-sdk/agent-file-authority@3.0.0-beta.98
43
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.98
44
+ - @robota-sdk/agent-interface-command@3.0.0-beta.98
45
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.98
46
+ - @robota-sdk/agent-interface-session@3.0.0-beta.98
47
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.98
48
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.98
49
+ - @robota-sdk/agent-roundtable@3.0.0-beta.98
50
+ - @robota-sdk/agent-session@3.0.0-beta.98
51
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.98
52
+ - @robota-sdk/agent-tools@3.0.0-beta.98
53
+
54
+ ## 3.0.0-beta.97
55
+ ### Patch Changes
56
+
57
+ - 7911a7d: Preserve pending execution discovery and input admission in atomic Session conversation snapshots.
58
+ Strict synchronous checkpoints now gate waiting, settlement and abandonment acknowledgment; failed saves
59
+ require checkpoint repair without repeating execution. Restore before framework queue and autonomous
60
+ input admission, and refuse unresolved conversation copies. Read v1/v2 session envelopes and write v2;
61
+ older readers preserve v2 as unsupported, so coordinate reader versions when rolling back.
62
+ - Updated dependencies [e5a4254]
63
+ - Updated dependencies [c207a31]
64
+ - Updated dependencies [9b4f63b]
65
+ - Updated dependencies [43df9c0]
66
+ - Updated dependencies [c59acd3]
67
+ - Updated dependencies [7911a7d]
68
+ - Updated dependencies [23a30cd]
69
+ - @robota-sdk/agent-tools@3.0.0-beta.97
70
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.97
71
+ - @robota-sdk/agent-core@3.0.0-beta.97
72
+ - @robota-sdk/agent-session@3.0.0-beta.97
73
+ - @robota-sdk/agent-roundtable@3.0.0-beta.97
74
+ - @robota-sdk/agent-interface-session@3.0.0-beta.97
75
+ - @robota-sdk/agent-executor@3.0.0-beta.97
76
+ - @robota-sdk/agent-interface-command@3.0.0-beta.97
77
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.97
78
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.97
79
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.97
80
+ - @robota-sdk/agent-file-authority@3.0.0-beta.97
81
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.97
82
+
83
+ ## 3.0.0-beta.96
84
+ ### Patch Changes
85
+
86
+ - @robota-sdk/agent-core@3.0.0-beta.96
87
+ - @robota-sdk/agent-executor@3.0.0-beta.96
88
+ - @robota-sdk/agent-file-authority@3.0.0-beta.96
89
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.96
90
+ - @robota-sdk/agent-interface-command@3.0.0-beta.96
91
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.96
92
+ - @robota-sdk/agent-interface-session@3.0.0-beta.96
93
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.96
94
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.96
95
+ - @robota-sdk/agent-roundtable@3.0.0-beta.96
96
+ - @robota-sdk/agent-session@3.0.0-beta.96
97
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.96
98
+ - @robota-sdk/agent-tools@3.0.0-beta.96
99
+
100
+ ## 3.0.0-beta.95
101
+ ### Minor Changes
102
+
103
+ - 115e104: **A command's caller can cancel what a skill command starts, including while the skill is prepared.**
104
+
105
+ `ISessionCommands.executeCommand` takes an optional trailing `{ signal }`. For a skill command it
106
+ reaches the turn the skill submits or the fork it runs, and the work before them: a cancel stops the
107
+ skill's activation before or after its shell expressions (once they start, all of them run to the
108
+ end), refuses a turn not yet started and interrupts one that is, and stops a fork. A command cancelled this way
109
+ rejects with the signal's reason whichever step the cancel reached, and a cancelled fork is not
110
+ recorded as an error. Before, a cancel that landed before the skill submitted its turn found nothing
111
+ for `abort()` to stop, and the turn then ran; a fork skill run as a command ignored the cancel. A
112
+ command that starts neither a turn nor a fork ignores the signal; every existing call keeps its shape.
113
+
114
+ A fork skill now receives the signal of whatever runs it, so a fork the model starts inside a turn
115
+ stops when that turn is aborted instead of running on.
116
+
117
+ `robota acp` hands each `/command` prompt's signal to the command, so `session/cancel` stops a skill
118
+ command's turn or fork even when it lands before the turn has started.
119
+ - 04719a9: **A permission request names the tool call it is about.**
120
+
121
+ `IPermissionRequestEvent` gains an optional `executionId`: the same id the call's `tool_start` and
122
+ `tool_end` carry, so a surface can hold one row from the request to the call's end. The session's
123
+ permission path carries the call's id from the tool wrapper to the prompt (`IPermissionAskContext.executionId`)
124
+ and the framework's prompt registry stamps it on the event, so it reaches every client that receives
125
+ the event, the WebSocket and HTTP `permission_request` frames included. It is present whenever the
126
+ session reports that call (its own, or an in-process background agent's) and absent for a
127
+ child-process agent's forwarded request.
128
+
129
+ The ACP agent transport keys its permission rows by that id: the request's `toolCallId` is the
130
+ call's execution id, its start and end address the same row, a denial the session decides on its
131
+ own while the editor's dialog is open closes that one row, and two same-named calls each follow
132
+ their own row whatever order the editor answers in. A request that names no call gets a row that
133
+ closes with the answer, and is closed at the end of the turn if no answer came. The name-ordered
134
+ matching is gone.
135
+ - 04a6de4: **Reasoning text a provider streams now reaches the editor as an ACP `agent_thought_chunk`, through a new `thinking_delta` session event.**
136
+
137
+ `IChatOptions.onThinkingDelta`, `IRunOptions.onThinkingDelta` and `IResumeExecutionOptions.onThinkingDelta`
138
+ (typed `TThinkingDeltaCallback`) carry reasoning text from a provider through the run, and the session
139
+ options (`ISessionOptions.onThinkingDelta`, `ICreateSessionOptions.onThinkingDelta`) hand it to the
140
+ session's owner. `InteractiveSession` emits it as `thinking_delta(delta)`, beside `text_delta`. The
141
+ text is never part of the reply: it is not appended to the conversation, not streamed through
142
+ `onTextDelta`, and the core adds no record of its own for it (no text-delta log entry, no
143
+ `provider_stream_raw_delta`); a provider's own native payload capture and response metadata keep
144
+ what the provider sent, as before. A reasoning delta counts as provider activity for the idle
145
+ timeout whether or not anyone listens to it, so a model that is only thinking is not cut off. The
146
+ existing `thinking(isThinking)` event is unchanged and remains the busy indicator. Where a provider
147
+ sends no reasoning text, nothing is emitted and nothing new is switched on.
148
+
149
+ `@robota-sdk/agent-interface-session` is a major change because a new session event name makes an
150
+ exhaustive map over the event names stop compiling until it classifies the event.
151
+
152
+ `@robota-sdk/agent-transport-acp` sends each non-empty `thinking_delta` to the editor as an
153
+ `agent_thought_chunk`, in order with the message chunks, so `robota acp` shows the model's reasoning
154
+ in the editor. A turn that streamed only thoughts still shows its result text, because only reply
155
+ text marks a turn as streamed. The WebSocket wire, the HTTP stream, headless stream-json, `query()`
156
+ and the terminal UI do not carry the new event in this change (`@robota-sdk/agent-transport` and
157
+ `@robota-sdk/agent-ui-terminal` classify it as non-surface). A forked skill and an in-process subagent
158
+ pass their reply text up but not their reasoning.
159
+
160
+ Two providers already receive reasoning text and now report it. `@robota-sdk/agent-provider-openai`
161
+ passes `response.reasoning_summary_text.delta` events of a streamed Responses call to
162
+ `onThinkingDelta`; the API sends them only when the provider profile asks for a reasoning summary, and
163
+ no request option changed; a summary streamed in several parts, and the summary of a later reasoning
164
+ item, each start on a new paragraph (`\n\n`) so the parts do not run together.
165
+ `@robota-sdk/agent-provider-openai-compatible` reports the text of Gemma's thought channel, which the
166
+ provider already removed from the reply, as it streams across chunk boundaries, with each later
167
+ channel of one reply on a new paragraph; the reply text is unchanged. No other provider reports
168
+ reasoning, and Anthropic thinking is not enabled. A model fallback chain still moves to the next model when only reasoning had streamed.
169
+
170
+ The scripted test provider (`@robota-sdk/agent-core/testing`) accepts an optional `thinking` string on
171
+ a turn and delivers it through `onThinkingDelta` before the turn's text; the scripted session harness
172
+ collects `thinking_delta` and now keeps a scripted tool-call turn's `usage`, which it used to drop.
173
+ - 0ba247b: A tool result can now carry a view its source declared (an MCP app), and a surface can invoke a
174
+ runtime tool through the session's permission gate with a prompt. This is the contract and wiring
175
+ layer: nothing produces a view yet, and the GUI does not yet host one.
176
+
177
+ - `agent-core` — `IToolResult.view` carries an `IToolAppView` (source, `ui://` resource, mime type,
178
+ HTML, structured content, callable tools, the call's input). `view` is now a typed key of
179
+ `IToolResult`, so an extension that already used a `view` key with another type must rename it.
180
+ The view is display data: it never enters model context or the size that decides a spill, and a
181
+ result replaced by its reference keeps it.
182
+ - `agent-interface-session` — `invokeRuntimeTool` takes `permissionInteraction` (`'interactive'` or
183
+ the default `'deny'`), a `driverId` (a host that attributes prompts names it as the requester) and
184
+ an `executionId` its events carry. A finished model call's `tool_end` names its view with
185
+ `IToolState.appView` (`viewId`, source, resource), and the new
186
+ `ISessionToolAppViews.readToolAppView(viewId)` reads the document. A permission handler may take
187
+ `{ signal }`, and aborting it withdraws the prompt.
188
+ - `agent-session` — a direct call asks a person only when its caller says so, and the handler is
189
+ given the call's own signal; the tool end event carries the view, never in the logged result data.
190
+ - `agent-framework` — the view of a model's call is kept under a `viewId` the session mints, in a
191
+ bounded per-session store (16 views, 4 MiB each, 16 MiB in all, measured on the whole serialized
192
+ view), and read on demand, so the document never rides `tool_end` to every surface, never enters
193
+ the recorded history, and a repeated provider tool-call id cannot overwrite another turn's view.
194
+ A malformed view is dropped. A direct call keeps and names no view, recognised by the id it was
195
+ started with. A submission or agent wakeup that arrives while a direct call holds the session is
196
+ queued behind it, as during a turn, instead of refused. A direct call acting for a driver
197
+ attributes its permission prompt and tool events to that driver, and aborting its signal withdraws
198
+ an open prompt from every surface.
199
+ - `agent-transport` — a driving connection sends `call-app-tool` (answered by `app_tool_result`) and
200
+ `read-app-view` (answered by `app_view`). A call names its view and reaches only the tools that
201
+ view's source declared; a call or read that decodes but cannot be served answers `protocol_error`
202
+ echoing the `requestId`, while an observer's attempt is refused like any non-read. A call still
203
+ waiting on its prompt is cancelled when its connection goes away (for the resume bridge, when the
204
+ bridge is disposed). `maxFrameBytes` bounds an app answer to what a carrier's channel carries;
205
+ the WebRTC carrier uses a history page's worth. `IProtocolSession` now includes the runtime-tool
206
+ and app-view roles.
207
+ - `agent-ui-web` — the two new server messages are recorded as not rendered until the app-view host
208
+ consumes them.
209
+
210
+ An implementation of `IInteractiveSession` or `IProtocolSession` outside this repository must add
211
+ `readToolAppView` (and, for `IProtocolSession`, `listRuntimeTools` and `invokeRuntimeTool`); the
212
+ members are required so a host cannot silently lack them.
213
+
214
+ ### Patch Changes
215
+
216
+ - 60f3965: **`robota mcp serve --ask-client` puts a caller's permission and ask prompts to the calling MCP client through elicitation instead of failing them.**
217
+
218
+ `@robota-sdk/agent-transport-mcp`: `createMcpTransport`, `createMcpHttpHost`,
219
+ `createMcpRemoteHttpHost` and `createAgentMcpServer` take `askClient`. Off by default, every prompt
220
+ is a tool error as before. On, and when the client declared form-mode elicitation, a permission or
221
+ ask prompt raised by that client's own call is put to it: a permission offers allow once or deny
222
+ only, never a remembered grant; an ask becomes a form (choice, multiple choice, free text); a masked
223
+ ask is never sent; deny, decline, cancel, a client error or an answer naming nothing offered keeps
224
+ today's outcome. stdio asks during the call. The HTTP hosts keep no session state, so they ask only
225
+ a client on the 2026-07-28 revision, through input-required rounds whose `requestState` is a
226
+ single-use random token naming one parked call; a 2025-era HTTP client keeps the tool error.
227
+ A call listens for prompts only while its own work drives the session, so a submission waiting
228
+ in the queue never holds another caller's prompt that it cannot answer.
229
+ Breaking for hand-written sessions: `IMcpTransportSession` now also requires `ISessionEvents`
230
+ (`on`/`off`), `ISessionPromptResolution` (`resolvePermission`/`resolveAsk`) and
231
+ `ISessionDriverAttribution` (`getActiveDriverId`), which `InteractiveSession` and the published
232
+ test double already implement.
233
+
234
+ `@robota-sdk/agent-interface-session` / `@robota-sdk/agent-session` / `@robota-sdk/agent-framework`:
235
+ `ISessionRuntimeTools.invokeRuntimeTool` (and `Session.invokeRuntimeTool`) accept
236
+ `options.permissionInteraction` and `options.driverId`. A direct call still denies a decision that
237
+ would need a person, and finds no one to ask a question, unless its caller passes
238
+ `permissionInteraction: 'interactive'`; then it asks the session's permission handler and its
239
+ tools get the session's ask port. `InteractiveSession` makes `driverId` the active driver while
240
+ the direct call runs, so a prompt the call raises carries it as `requesterDriverId`. With
241
+ `askClient` on, an MCP call runs under its own `mcp:<n>` driver id; a submission made that way is
242
+ attributed to it rather than to the owner.
243
+
244
+ `@robota-sdk/agent-transport`: exports `permissionSummaryArgument`, the argument a person recognises
245
+ a tool call by (`filePath` for the built-in file tools), for every transport that puts a permission
246
+ request to a person in its own wire form.
247
+
248
+ `@robota-sdk/agent-cli`: `mcp serve --ask-client` turns this on for whichever carrier the run serves.
249
+ - 02053ec: Leave unregistered DeepSeek model costs unknown instead of applying unrelated legacy model prices.
250
+ - Updated dependencies [60f3965]
251
+ - Updated dependencies [115e104]
252
+ - Updated dependencies [04719a9]
253
+ - Updated dependencies [04a6de4]
254
+ - Updated dependencies [0ba247b]
255
+ - Updated dependencies [02053ec]
256
+ - @robota-sdk/agent-interface-session@3.0.0-beta.95
257
+ - @robota-sdk/agent-session@3.0.0-beta.95
258
+ - @robota-sdk/agent-core@3.0.0-beta.95
259
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.95
260
+ - @robota-sdk/agent-executor@3.0.0-beta.95
261
+ - @robota-sdk/agent-interface-command@3.0.0-beta.95
262
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.95
263
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.95
264
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.95
265
+ - @robota-sdk/agent-tools@3.0.0-beta.95
266
+ - @robota-sdk/agent-file-authority@3.0.0-beta.95
267
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.95
268
+ - @robota-sdk/agent-roundtable@3.0.0-beta.95
269
+
270
+ ## 3.0.0-beta.94
271
+ ### Minor Changes
272
+
273
+ - e706b43: Live telemetry can name its spans with the OpenTelemetry GenAI semantic conventions. Set
274
+ `PRODUCT_TELEMETRY_SEMCONV` to `gen_ai` to export `invoke_agent`, `chat {model}` (client) and
275
+ `execute_tool {tool}` spans with `gen_ai.*` attributes, keeping Robota-only facts as `agent.*`; or to
276
+ `gen_ai/dup` to emit both attribute sets while dashboards move. The default, `agent`, exports exactly
277
+ the spans it did before. An unknown value, or the setting while neither traces nor metrics are exported,
278
+ refuses startup. Console traces under a GenAI mode print the same projected spans.
279
+
280
+ The live prompt trace now carries each tool body's name (the session's tool-body observation includes it
281
+ and the framework's live projection passes a label-safe name through); it reaches spans only under a
282
+ GenAI mode and is never written to session history.
283
+
284
+ ### Patch Changes
285
+
286
+ - e079992: The Korean memory cues and sensitive-term words of the default automatic-memory policy now load from a locale data file (`src/memory/locales/ko.json`) instead of being written into the source. Matching behavior is unchanged.
287
+ - Updated dependencies [8fdd44c]
288
+ - Updated dependencies [e706b43]
289
+ - Updated dependencies [fef3a50]
290
+ - @robota-sdk/agent-tools@3.0.0-beta.94
291
+ - @robota-sdk/agent-session@3.0.0-beta.94
292
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.94
293
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.94
294
+ - @robota-sdk/agent-interface-session@3.0.0-beta.94
295
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.94
296
+ - @robota-sdk/agent-core@3.0.0-beta.94
297
+ - @robota-sdk/agent-executor@3.0.0-beta.94
298
+ - @robota-sdk/agent-file-authority@3.0.0-beta.94
299
+ - @robota-sdk/agent-interface-command@3.0.0-beta.94
300
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.94
301
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.94
302
+ - @robota-sdk/agent-roundtable@3.0.0-beta.94
303
+
304
+ ## 3.0.0-beta.93
305
+ ### Patch Changes
306
+
307
+ - Release the integrated provider credential isolation and consumer runtime and interaction composition updates.
308
+ - Updated dependencies
309
+ - @robota-sdk/agent-core@3.0.0-beta.93
310
+ - @robota-sdk/agent-executor@3.0.0-beta.93
311
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.93
312
+ - @robota-sdk/agent-interface-command@3.0.0-beta.93
313
+ - @robota-sdk/agent-interface-session@3.0.0-beta.93
314
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.93
315
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.93
316
+ - @robota-sdk/agent-session@3.0.0-beta.93
317
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.93
318
+ - @robota-sdk/agent-tools@3.0.0-beta.93
319
+ - @robota-sdk/agent-file-authority@3.0.0-beta.93
320
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.93
321
+ - @robota-sdk/agent-roundtable@3.0.0-beta.93
322
+
323
+ ## 3.0.0-beta.92
324
+ ### Patch Changes
325
+
326
+ - Local OpenAI-compatible servers can be set up without saving a placeholder API key. Explicit credentials and environment references remain effective for authenticated servers and connection tests. Optional credentials are managed through the user-only provider edit command.
327
+ - Updated dependencies
328
+ - @robota-sdk/agent-core@3.0.0-beta.92
329
+ - @robota-sdk/agent-executor@3.0.0-beta.92
330
+ - @robota-sdk/agent-interface-command@3.0.0-beta.92
331
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.92
332
+ - @robota-sdk/agent-interface-session@3.0.0-beta.92
333
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.92
334
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.92
335
+ - @robota-sdk/agent-session@3.0.0-beta.92
336
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.92
337
+ - @robota-sdk/agent-tools@3.0.0-beta.92
338
+ - @robota-sdk/agent-file-authority@3.0.0-beta.92
339
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.92
340
+ - @robota-sdk/agent-roundtable@3.0.0-beta.92
341
+
342
+ ## 3.0.0-beta.91
343
+ ### Patch Changes
344
+
345
+ - bad976f: Persist turn and tool intent before effects, restore interrupted calls with unknown outcomes, reap owned foreground shell groups after owner death, and prune proven dead peer announcements.
346
+ - Updated dependencies [bad976f]
347
+ - @robota-sdk/agent-session@3.0.0-beta.91
348
+ - @robota-sdk/agent-tools@3.0.0-beta.91
349
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.91
350
+ - @robota-sdk/agent-core@3.0.0-beta.91
351
+ - @robota-sdk/agent-executor@3.0.0-beta.91
352
+ - @robota-sdk/agent-file-authority@3.0.0-beta.91
353
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.91
354
+ - @robota-sdk/agent-interface-command@3.0.0-beta.91
355
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.91
356
+ - @robota-sdk/agent-interface-session@3.0.0-beta.91
357
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.91
358
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.91
359
+ - @robota-sdk/agent-roundtable@3.0.0-beta.91
360
+
361
+ ## 3.0.0-beta.90
362
+ ### Minor Changes
363
+
364
+ - 7116367: Credentials the runtime holds for itself no longer reach the commands it runs.
365
+
366
+ - `agent-cli` — once a workspace's settings are admitted, every variable a provider profile or
367
+ definition names as its credential (`$ENV:` references, and defaults such as `OPENAI_API_KEY`)
368
+ leaves the process environment, so tools, hooks, background shells, a skill's `!` commands and
369
+ the environment an MCP header helper inherits no longer carry it, a hosted worker's broker token
370
+ included (a variable an MCP definition references explicitly still resolves); the provider keeps
371
+ authenticating from the startup snapshot. A user or managed settings layer can let
372
+ commands see one with `"commandEnvAllow": ["NAME"]`; project settings cannot. With the OS sandbox
373
+ on, confined commands can no longer read `settings.json`, `credentials/`, `mcp-credentials/` or
374
+ `remote-host-identity.json` under the user state directory. **Behavior change:** a command that
375
+ relied on inheriting a provider key now needs the opt-in, and a host embedding `startCli` finds
376
+ those variables gone from its own `process.env` afterwards — a later in-process call must pass them
377
+ in its `environment`.
378
+ - `agent-framework` — the settings schema gains `commandEnvAllow`; `checkSettingsDocument` and
379
+ `buildProviderProfilesSnapshot` take an optional environment map to resolve `$ENV:` references
380
+ against instead of the live process environment.
381
+ - `agent-command` — provider startup checks credentials against the host's environment snapshot.
382
+ - `agent-tools` — `OsSandboxClient` takes `hiddenPaths`, always hidden from confined commands and
383
+ not changeable by sandbox settings.
384
+ - `agent-subagent-runner` — a child-process subagent removes its provider credential variable from
385
+ its own environment once its provider is built, unless the start payload says the owner opted it in
386
+ (`keepProviderCredential`).
387
+ - `dag-node-instant-node` — prompt nodes accept an env resolver (`createPromptBackedNodeDefinition`'s
388
+ third argument, `rehydrateInstantNode`'s `resolveEnv`) for their `$ENV:` credential default.
389
+ - `agent-command-workflows` — `/workflows create` and `/workflows run` resolve prompt-node credentials
390
+ from the host's environment snapshot.
391
+ - 5bb675a: Provider commands check a profile's `$ENV:` or default credential against the host's environment snapshot, so `/provider switch`, `/provider test`, `/provider add`, `/provider edit` and a cross-profile `/model` keep working while the runtime withholds its own credentials from `process.env`.
392
+
393
+ - `IProviderCommandModuleOptions` takes an optional `env`, and `createDefaultCommandModules` takes `providerEnvironment`. The CLI passes its startup snapshot.
394
+ - The git that isolated subagents run, and so the repository's hooks, now get the command environment instead of the full snapshot.
395
+
396
+ ### Patch Changes
397
+
398
+ - Updated dependencies [7116367]
399
+ - @robota-sdk/agent-tools@3.0.0-beta.90
400
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.90
401
+ - @robota-sdk/agent-core@3.0.0-beta.90
402
+ - @robota-sdk/agent-executor@3.0.0-beta.90
403
+ - @robota-sdk/agent-file-authority@3.0.0-beta.90
404
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.90
405
+ - @robota-sdk/agent-interface-command@3.0.0-beta.90
406
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.90
407
+ - @robota-sdk/agent-interface-session@3.0.0-beta.90
408
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.90
409
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.90
410
+ - @robota-sdk/agent-roundtable@3.0.0-beta.90
411
+ - @robota-sdk/agent-session@3.0.0-beta.90
412
+
413
+ ## 3.0.0-beta.89
414
+ ### Patch Changes
415
+
416
+ - @robota-sdk/agent-core@3.0.0-beta.89
417
+ - @robota-sdk/agent-executor@3.0.0-beta.89
418
+ - @robota-sdk/agent-file-authority@3.0.0-beta.89
419
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.89
420
+ - @robota-sdk/agent-interface-command@3.0.0-beta.89
421
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.89
422
+ - @robota-sdk/agent-interface-session@3.0.0-beta.89
423
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.89
424
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.89
425
+ - @robota-sdk/agent-roundtable@3.0.0-beta.89
426
+ - @robota-sdk/agent-session@3.0.0-beta.89
427
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.89
428
+ - @robota-sdk/agent-tools@3.0.0-beta.89
429
+
430
+ ## 3.0.0-beta.88
431
+
432
+ ### Patch Changes
433
+
434
+ - Updated dependencies [d994f60]
435
+ - @robota-sdk/agent-tools@3.0.0-beta.88
436
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.88
437
+ - @robota-sdk/agent-core@3.0.0-beta.88
438
+ - @robota-sdk/agent-executor@3.0.0-beta.88
439
+ - @robota-sdk/agent-file-authority@3.0.0-beta.88
440
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.88
441
+ - @robota-sdk/agent-interface-command@3.0.0-beta.88
442
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.88
443
+ - @robota-sdk/agent-interface-session@3.0.0-beta.88
444
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.88
445
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.88
446
+ - @robota-sdk/agent-roundtable@3.0.0-beta.88
447
+ - @robota-sdk/agent-session@3.0.0-beta.88
448
+
449
+ ## 3.0.0-beta.87
450
+
451
+ ### Minor Changes
452
+
453
+ - 7d9cc66: Keep host-declared inline human controls reachable during active turns. Plugin disable and uninstall can withdraw future dispatch without changing model invocation or host command policy.
454
+ - 7d9cc66: Expose declarative contribution descriptors for installed bundles and resolved MCP sources,
455
+ including source generations, host capability requirements and compatibility diagnostics.
456
+ Revalidate MCP approval, source identity and workspace trust before new dispatch, preserving
457
+ outcomes of calls already started and refusing retained tools after shutdown.
458
+ - 7d9cc66: Preserve an explicitly supplied host tool scheduling policy through session assembly and CLI presentation modes, retaining permission admission and conservative handling of undeclared resources.
459
+
460
+ ### Patch Changes
461
+
462
+ - Release the migrated Robota product with its public SDK namespace, robota command, compatible SDK exports, internal product configuration, and verified CLI startup and delivery corrections.
463
+ - 7d9cc66: Load declared JSON and inline bundle MCP configurations with selected-source containment, ordered whole-server replacement and file provenance. Route packaged servers through normal CLI/app MCP startup with namespaced identities, existing trust/approval/authority gates, disable overlays and value-free compatibility diagnostics.
464
+ - 7d9cc66: Load external name-only plugin manifests without inventing optional metadata. Select the recorded
465
+ installed source instead of the lexically last cached directory, refusing invalid, missing or
466
+ ambiguous revisions. Check the installed identity as well as the manifest name for disablement.
467
+ - 7d9cc66: Add user-only project memory topic correction and forgetting, prevent automatic restoration after restart, refresh retained startup context, and reconcile semantic recall with current durable source content.
468
+ - 7d9cc66: Allow consumer eval metrics to require a perfect outcome independently of aggregate scores, and reject interrupted runs as successful evaluations.
469
+ - 7d9cc66: Add explicit MCP Skills selection, bounded supervisor access and persistent host content consent.
470
+ Users can inspect verified instructions, approve the exact content fingerprint and withdraw consent;
471
+ models can discover metadata only. Consent stays separate from server admission and model-turn activation.
472
+ - 7d9cc66: Route discovered MCP Skills through the shared skill command runtime with lazy verified content, source-bound invocation names, current user consent and execution-owned activation cleanup. Keep remote shell expressions inert and defer queued user skill reads until their own turn executes.
473
+ - 7d9cc66: Restore actual interactive tool observations, identities and outcomes from persisted event history.
474
+ Show denied calls as failed in live and restored GUI conversation views.
475
+ - 7d9cc66: Retain registered tool source attribution in observations and preserve ordered outcome receipts independently of conversation summaries.
476
+ - 7d9cc66: Expose verified skill supporting resources only within their owning turn or fork, using the current host consent and manifest.
477
+ - 7d9cc66: Retain mixed tool observations alongside structured results through live session events and history
478
+ display. The shared app renderer previews inline raster images and keeps resource URIs inert, with
479
+ explicit diagnostics for unsupported media instead of silently dropping it.
480
+ - 7d9cc66: Observe scheduler queue intervals separately from pre-dispatch admission, permission and tool work.
481
+ Preserve valid duration totals when live trace detail is bounded, reporting invalid evidence explicitly
482
+ through content-free console and OTLP traces without altering dispatch, recovery or settlement.
483
+ - Updated dependencies
484
+ - Updated dependencies [66af868]
485
+ - Updated dependencies [7d9cc66]
486
+ - Updated dependencies [7d9cc66]
487
+ - Updated dependencies [7d9cc66]
488
+ - Updated dependencies [7d9cc66]
489
+ - Updated dependencies [7d9cc66]
490
+ - Updated dependencies [7d9cc66]
491
+ - Updated dependencies [7d9cc66]
492
+ - Updated dependencies [7d9cc66]
493
+ - Updated dependencies [7d9cc66]
494
+ - Updated dependencies [7d9cc66]
495
+ - Updated dependencies [7d9cc66]
496
+ - @robota-sdk/agent-core@3.0.0-beta.87
497
+ - @robota-sdk/agent-executor@3.0.0-beta.87
498
+ - @robota-sdk/agent-file-authority@3.0.0-beta.87
499
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.87
500
+ - @robota-sdk/agent-interface-command@3.0.0-beta.87
501
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.87
502
+ - @robota-sdk/agent-interface-session@3.0.0-beta.87
503
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.87
504
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.87
505
+ - @robota-sdk/agent-roundtable@3.0.0-beta.87
506
+ - @robota-sdk/agent-session@3.0.0-beta.87
507
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.87
508
+ - @robota-sdk/agent-tools@3.0.0-beta.87
509
+
510
+ ## 3.0.0-beta.86
511
+
512
+ ### Patch Changes
513
+
514
+ - @robota-sdk/agent-core@3.0.0-beta.86
515
+ - @robota-sdk/agent-executor@3.0.0-beta.86
516
+ - @robota-sdk/agent-file-authority@3.0.0-beta.86
517
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.86
518
+ - @robota-sdk/agent-interface-command@3.0.0-beta.86
519
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.86
520
+ - @robota-sdk/agent-interface-session@3.0.0-beta.86
521
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.86
522
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.86
523
+ - @robota-sdk/agent-roundtable@3.0.0-beta.86
524
+ - @robota-sdk/agent-session@3.0.0-beta.86
525
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.86
526
+ - @robota-sdk/agent-tools@3.0.0-beta.86
527
+
528
+ ## 3.0.0-beta.85
529
+
530
+ ### Minor Changes
531
+
532
+ - 193a0bc: `${CLAUDE_SKILL_DIR}` in a skill expands to the absolute folder its `SKILL.md` is in; it used to expand to an empty string. A skill's `` !`command` `` gets `CLAUDE_SKILL_DIR` and `CLAUDE_SESSION_ID` in its environment, so the shell expands them there too (`TShellExecFn` takes an optional `env`). Skills from host folders and a trusted project carry the folder, and bundle-plugin skills and commands record theirs. `ICommand` gains `skillDirectory`, and `IContributionSource` an optional `locate()` that names the absolute path of a root-relative one.
533
+ - 54e2848: `createQuery()` takes `model`, `allowedTools` and `deniedTools`, and the query function has `shutdown()`.
534
+
535
+ - `model` picks the model, so a query works with any provider without a settings file; before, it always asked for Anthropic's default model.
536
+ - `allowedTools` lets named tools (your own `additionalTools`, say) run in the `default` mode without a `permissionHandler`; `deniedTools` are never offered to the model.
537
+ - Calls on one query function run one at a time and each resolves with its own reply. Before, concurrent calls all resolved with the first turn's reply.
538
+ - `await query.shutdown()` ends the query's session; a call still running or waiting rejects, and so does every later one.
539
+
540
+ ### Patch Changes
541
+
542
+ - 4e11579: `runGroupChat` runs on the Roundtable core.
543
+
544
+ `runGroupChat`'s own `while` loop is replaced by a facade over `@robota-sdk/agent-roundtable`'s
545
+ `Roundtable`: one step id becomes one participant, the caller's `selectNextStep` policy is adapted
546
+ into a `TurnSelector`, and the core runs the only turn loop. The public contract
547
+ (`IGroupChatOrchestrationSpec`, `SelectNextStep`, `IGroupChatOrchestratorDeps`,
548
+ `IOrchestrationRunResult`) is unchanged, and so is the behavior it describes: the first speaker,
549
+ threaded whole-transcript prompts, the `maxTurns` bound and its error message and check order, empty
550
+ steps, the STARTED/STEP_STARTED/STEP_COMPLETED/COMPLETED/FAILED event sequence, per-step usage, and
551
+ the original error object thrown on failure — including for inputs the old loop tolerated only
552
+ because it never validated them, such as a non-finite or extremely large `maxTurns` or a step with no
553
+ usable model id.
554
+
555
+ A few differences are deliberate and small: the selector now receives a freshly built history array
556
+ on every call rather than a reference into a mutated one; a duplicate step id keeps only its last
557
+ definition and an empty step id can never be reached (both were already-unreachable edge cases in
558
+ the old loop); and a non-integer `maxTurns` is rounded up for the core's own internal turn ceiling,
559
+ though the selector's own bound check still compares the caller's exact value first. Reported step
560
+ usage comes back as a plain-data copy (same values; undefined-valued keys omitted), and a reading that
561
+ cannot be stored as finite JSON, such as one containing `NaN`, is left out of the step result instead
562
+ of failing the run. Each call keeps a small in-memory operation log for its conversation; it is bounded
563
+ per call and negligible at the default `maxTurns` (the step count).
564
+
565
+ - 3c1967f: Reloading plugins updates the live session's skill routing and model skill catalogue together
566
+ with command completion. Disabled plugins stop being executable after reload, and unreadable
567
+ settings clear the plugin skill snapshot. Hook changes require a new session.
568
+ - 5684612: A bundle plugin skill can use `${CLAUDE_PLUGIN_ROOT}`: it expands to the plugin's folder in the
569
+ skill's body, and `` !`command` `` preprocessing gets it in the environment, as plugin hooks already
570
+ did. Every skill's commands now get `CLAUDE_PLUGIN_ROOT` set (empty outside a plugin), so a value the
571
+ host process carries never stands in for it. A session also loads project plugins, skills and hooks
572
+ alike, only from a folder inside the trusted workspace; trust granted to one repository does not
573
+ extend to a plugin folder elsewhere.
574
+ - 6ee8725: A user settings file that does not parse no longer reads as "no plugin is disabled". Plugin settings
575
+ now refuse to read it: no plugin loads (skills, commands, hooks and themes alike), a plugin command
576
+ such as `/plugin enable` fails instead of rewriting the whole settings file with the plugin keys
577
+ alone, and `robota doctor` reports the plugin check as failed while still inspecting each installed
578
+ plugin. The CLI already refuses to start with such a file; this covers a session started later in
579
+ the same process.
580
+ - 6072e9a: Bundle plugin skills and commands now run. They were listed in the command menu, but typing one
581
+ answered "Unknown command", and the model could neither see nor activate them: the session's skill
582
+ router and the prompt's skill list read only the host's skill roots. A session now also loads the
583
+ skills and commands of the bundle plugins it may load, once, behind the same gates as plugin hooks
584
+ (not in a bare session, project plugins only in a trusted workspace, disabled plugins skipped). A
585
+ session's own skill of the same name wins, then the first plugin to name it.
586
+ - 2e07cad: A subagent and a fork-context skill now start in the permission mode their parent is in at that
587
+ moment. The runtime used to hand them the mode it was built with, so after a switch to `plan` a
588
+ subagent the model started, or a skill it ran in a fork, still ran in the earlier mode and could
589
+ edit. `IInProcessSubagentRunnerDeps` gains the optional `getParentPermissionMode`, which the session
590
+ wires to its live mode; the in-process and child-process runners read it at spawn and fall back to
591
+ `permissionMode` when it is absent.
592
+
593
+ In plan mode the model can no longer run `/workflows create` or `/workflows build`: both save to
594
+ the project, and `create` also runs the workflow. The user can still run them by hand.
595
+
596
+ - Updated dependencies [190f78f]
597
+ - Updated dependencies [41cca13]
598
+ - Updated dependencies [193a0bc]
599
+ - Updated dependencies [ada3841]
600
+ - Updated dependencies [5093a30]
601
+ - Updated dependencies [94b2c87]
602
+ - Updated dependencies [10597b2]
603
+ - Updated dependencies [3ab2eca]
604
+ - @robota-sdk/agent-roundtable@3.0.0-beta.85
605
+ - @robota-sdk/agent-core@3.0.0-beta.85
606
+ - @robota-sdk/agent-interface-command@3.0.0-beta.85
607
+ - @robota-sdk/agent-session@3.0.0-beta.85
608
+ - @robota-sdk/agent-executor@3.0.0-beta.85
609
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.85
610
+ - @robota-sdk/agent-interface-session@3.0.0-beta.85
611
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.85
612
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.85
613
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.85
614
+ - @robota-sdk/agent-tools@3.0.0-beta.85
615
+ - @robota-sdk/agent-file-authority@3.0.0-beta.85
616
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.85
617
+
618
+ ## 3.0.0-beta.84
619
+
620
+ ### Minor Changes
621
+
622
+ - e8d70ac: A first run finds a provider, instead of a dead end. `robota --serve` (and the daemon it starts) no
623
+ longer refuses when no provider is configured: it starts in setup mode, and the GUI's conversation area
624
+ shows a "Connect a model provider to start" panel with a "Set up provider" button in place of the
625
+ composer. Answering it configures and swaps in the first provider live, with no restart. A startup
626
+ failure now says why — `robota daemon start --json` and the desktop app's fatal screen report the
627
+ child's own reason instead of a generic "readiness channel closed", and the fatal screen gets a Try
628
+ again button. `trust status --json` and the desktop trust dialog list only sources whose state trust
629
+ would actually change, instead of naming one this platform could not determine; the dialog shows one
630
+ sentence and a collapsed Details section. `robota --serve --open` in an untrusted folder now asks at
631
+ the terminal (trust it, start Restricted, or quit) when someone is there to ask, instead of refusing
632
+ outright.
633
+
634
+ ### Patch Changes
635
+
636
+ - Updated dependencies [c7f213c]
637
+ - Updated dependencies [9f46375]
638
+ - Updated dependencies [9f46375]
639
+ - Updated dependencies [e8d70ac]
640
+ - Updated dependencies [9c6a8db]
641
+ - Updated dependencies [9c6a8db]
642
+ - Updated dependencies [9c6a8db]
643
+ - Updated dependencies [9c6a8db]
644
+ - Updated dependencies [9c6a8db]
645
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.84
646
+ - @robota-sdk/agent-core@3.0.0-beta.84
647
+ - @robota-sdk/agent-session@3.0.0-beta.84
648
+ - @robota-sdk/agent-interface-session@3.0.0-beta.84
649
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.84
650
+ - @robota-sdk/agent-tools@3.0.0-beta.84
651
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.84
652
+ - @robota-sdk/agent-interface-command@3.0.0-beta.84
653
+ - @robota-sdk/agent-executor@3.0.0-beta.84
654
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.84
655
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.84
656
+ - @robota-sdk/agent-file-authority@3.0.0-beta.84
657
+
658
+ ## 3.0.0-beta.83
659
+
660
+ ### Major Changes
661
+
662
+ - 6ae3f28: A served runtime can list its workspace's sessions, start a new one and switch to another without the
663
+ process or any client connection restarting. The GUI shows them in a sessions sidebar.
664
+
665
+ - `agent-interface-session` is **`major`** for two reasons:
666
+ - It adds `ISessionListing`, `ISessionDirectory` and `ISessionSwitchedEvent`.
667
+ - `IInteractiveSessionEvents` gains a required `session_switched` event. An exhaustive map over the
668
+ event names stops compiling until it classifies the new event.
669
+ - `agent-transport` is **`major`** for the same kind of reason:
670
+ - It adds the wire messages `list-sessions` → `sessions`/`sessions_error`, `new-session`,
671
+ `switch-session`, and the broadcast `session_switched`.
672
+ - It adds a `sessionDirectory` handler option. A refusal to switch comes back as a
673
+ `protocol_error` carrying the reason.
674
+ - An exhaustive map over message types must add the new variants.
675
+ - `agent-transport-ws` passes a configured `sessionDirectory` to every connection.
676
+ - `agent-framework` is **`major` because `IRuntimeHostHandle.session` is now a `SessionSlot`**, not the
677
+ `InteractiveSession`, and `bindTransports` receives the slot.
678
+ - The slot is an `IInteractiveSession` that forwards to the current session. Members outside that
679
+ interface are read through `host.session.current`, which changes on a switch.
680
+ - Adds `InteractiveSession.whenInitialized()`.
681
+ - Exports `listUnreadableSessions`.
682
+ - `agent-ui-web` is **`major`**:
683
+ - `IWsSessionState` gains session listing state and actions.
684
+ - It adds a `SessionSidebar`.
685
+ - `/resume` opens the sidebar.
686
+ - `agent-cli`: `robota --serve` provides the session directory, and refuses a switch that would lose
687
+ work in progress. External-event grants belong to the run: a switch reopens them on the new session,
688
+ as the TUI already does.
689
+ - External-event grant history (spent tokens, rate windows, revocations) belongs to the run. The new
690
+ option `externalEventGrantHistory` (from `createExternalEventGrantHistory()`) is shared by every
691
+ session that a served runtime or the TUI builds. A session switch therefore replays no spent token
692
+ and resets no rate limit. The TUI previously had this gap when it switched sessions.
693
+
694
+ ### Minor Changes
695
+
696
+ - 724fabb: External-event grants are given at start, carried exactly to a background session, listed without their
697
+ principal, and revoked by the owner.
698
+
699
+ - `agent-framework` (breaking) — `openExternalEventSource` and `ExternalEventIngress.open` take only
700
+ `{ grant, audit? }`: the session builds each grant's verifier from `grant.verifier` with the
701
+ `externalEventVerifierFactory` its host passed when the session was built (without one, no grant opens), and an
702
+ open that supplies a verifier or a factory is refused. `IExternalEventSource.revoke()` stops the grant's queued and running turns,
703
+ refuses its later events as `grant-revoked`, and keeps the label from being opened again. A submission the
704
+ session refuses is `shutting-down` only while it shuts down, and `session-unavailable` otherwise. New command
705
+ host adapter `externalEvents` (`ICommandExternalEventsAdapter`).
706
+ - `agent-ui-terminal` — forwards `externalEventVerifierFactory` from the render options to the session.
707
+ - `agent-interface-transport` — `TExternalEventRefusal` gains `session-unavailable`.
708
+ - `agent-command` — `/events` lists the session's grants (label, principal kind, state, counts) and
709
+ `/events revoke <grant-id>` withdraws one. User-only.
710
+ - `agent-cli` — a grant file (`grantId`, `issuer`, `resource` ending in `/events/<grantId>`, exactly one of
711
+ `subject` or `client`, `scopes`, optional `algorithms` and `rate`) is validated before anything starts, with a
712
+ reason that names the grant and no configured value. `robota --external-event-grant <file>` (TUI) and
713
+ `robota session start --background --external-event-grant <file>` open every grant or fail the start; a
714
+ background session receives its grants through a private file, opens them before it reports ready, and the
715
+ launcher refuses a readiness that names other grants. `robota session events list <id> [--json]` and
716
+ `robota session events revoke <id> <grant-id>` work over the generation-bound control socket, and
717
+ `robota session list --format json` shows each grant's counts. The retired `--external-event-allow` now points
718
+ at `--external-event-grant`.
719
+
720
+ - bfe8ed5: An external event is admitted only by a bearer access token the session verifies itself, and its sender is the
721
+ grant that token matched, never a name in the event.
722
+
723
+ - `agent-interface-transport` — `IExternalEventGrant` (a label, an access-token verifier configuration that pins
724
+ exactly one subject or client, the `message` kind, optional turn-rate windows), `IExternalEventDelivery` (the
725
+ token and the event as a carrier received them), the closed `TExternalEventRefusal` set, `TExternalEventAdmission`
726
+ and the content-free `TExternalEventAuditRecord`.
727
+ - `agent-framework` (breaking) — `ExternalEventIngress.open` and `InteractiveSession.openExternalEventSource` take
728
+ `{ grant, verifier, audit? }` instead of `{ id, allowedSenders, authenticate }`, and `receive` takes
729
+ `{ token, event }`. A delivery is refused with a stable word when the token is missing or the verifier refuses
730
+ it, when the token was already spent on an event (`jti`), when the event is malformed or oversize, or when the
731
+ grant is over its rate; nothing refused reaches the queue. An admitted event is attributed
732
+ `external:<grant>:<conversation>`, a payload display name appears in the envelope only as `claimed-name`, and the
733
+ receipt (`TExternalEventReceipt`) answers at acceptance with the turn id. Every refusal and settlement is
734
+ reported to the `audit` sink without content, conversation, name or token. `IAuthenticatedExternalEvent` and
735
+ `IExternalEventReceipt` are removed.
736
+ - `agent-cli` (breaking) — `--external-event-allow` is refused with the reason: a sender name relayed by an MCP
737
+ server does not prove who sent an event.
738
+
739
+ - 4f49d14: The device mesh can be turned on, and `/peers`, `/handoff` and `/devices` reach the user's other devices.
740
+
741
+ - New user setting `transports.mesh.enabled` (default `false`). When it is `true`, an interactive
742
+ session opens the device mesh at startup and closes it on exit. Only the user settings count; a
743
+ project's settings cannot turn it on. Print and serve runs never open it, and a device without an
744
+ identity is told to run `/devices init`. Only one session of a device opens it at a time; another
745
+ session on the same device says so in `/devices` and links nothing.
746
+ - By default a linked device may send messages, files and sessions. Each file and each session still
747
+ waits for the operator's yes on this machine's terminal; with no terminal the answer is no.
748
+ Delegating, observing and driving stay off unless `transports.mesh.options.capabilities` lists
749
+ them.
750
+ - A message from a linked device arrives like one from a session on this host: a peer turn with no
751
+ authority, attributed to the device the handshake proved, under the same rate limit and
752
+ conversation limits.
753
+ - `/peers` lists linked devices beside the sessions on this host; `/peers send` and
754
+ `/peers send-file` take a device id. `/handoff` lists linked devices and pushes the session to one.
755
+ Files arrive in the usual place aside, and sessions are saved without starting.
756
+ - `/devices` shows whether the mesh is on, how this device finds the others, and which are linked.
757
+ - The mesh uses the relay at `transports.webrtc.options.relayUrl` when one is set. Without one it
758
+ finds devices on the local network and over the public ways in `transports.mesh.options`.
759
+ - `/peers`, `/handoff` and `/devices` stay user-only. Their descriptions tell the model they cover
760
+ linked devices.
761
+ - `agent-framework`: the `/peers` port can list linked devices (`listDevices`, `ILinkedDeviceSummary`).
762
+ - `agent-command`: the `/devices` port can report the mesh (`meshStatus`, `IDevicesMeshStatus`).
763
+
764
+ - 7b72344: Every client can offer the session's commands and skills and show its status. The GUI uses them as a
765
+ desktop-style composer.
766
+
767
+ - `agent-interface-session` is **`major` because `IInteractiveSession` gains required members**:
768
+ `ISessionCommands.listSkills()` and a `statusRead` capability, `getStatusSnapshot()`. The snapshot
769
+ holds session, model, permission mode, effort, context and goal. An external implementation stops
770
+ compiling until it adds both.
771
+ - `agent-transport` is **`major` for the same reason on `IProtocolSession`**. It also gains the wire
772
+ messages `get-commands` → `commands` and `get-status` → `session_status`. Both are reads that the
773
+ observe role may send.
774
+ - `agent-interface-command` gains `ICommandSkillListEntry`, moved from `agent-framework`, which
775
+ re-exports it unchanged.
776
+ - `agent-ui-web` is **`major` because its state changes shape**:
777
+ - A command's outcome and a finished turn's tool calls are now conversation entries: `messages` is
778
+ `TConversationEntry[]`.
779
+ - The `uiIntentNotices` list, `dismissUiIntentNotice`, `applyUiIntentEvent`,
780
+ `removeUiIntentNotice` and `IUiIntentNotice` are removed. An intent now answers with an info
781
+ line in the conversation.
782
+ - Session notices keep only `session-error` and `protocol-error`.
783
+ - The state gains `commandCatalog` and `sessionStatus`.
784
+ - `agent-command` registers `/theme` and `/keybindings` even without a terminal. They then answer
785
+ that they belong to the Robota terminal, instead of being unknown.
786
+ - `agent-framework`:
787
+ - `InteractiveSession.getStatusSnapshot()`.
788
+ - The main-thread row previews the last chat message instead of the last record's type.
789
+ - `agent-cli` serves the full GUI web app, renamed from `agent-cli-web` to `agent-gui-web`, on
790
+ `robota --serve --open`.
791
+
792
+ - 9721162: A trusted workspace saves its sessions on macOS and other hosts without Linux's project-write guarantee.
793
+
794
+ - **`agent-framework`:** `supportsWorkspaceProjectMutation(platform?)` tells a host in advance whether project writes can be proven to stay under the trusted root. The project writer uses the same answer, so the two cannot disagree.
795
+ - **`agent-cli`:**
796
+ - Where project writes cannot be proven safe, a trusted workspace keeps its sessions in the user session store (`$PRODUCT_USER_STATE_DIR/sessions`). They are listed for that workspace by their working directory, so `/resume`, the sessions sidebar, `--continue` and `robota session list` find them. Nothing is written under the project root.
797
+ - Before this, every save in a trusted git workspace on macOS was refused, and those surfaces listed nothing.
798
+ - Linux keeps trusted sessions in the project, as before.
799
+ - `robota session list`, `robota usage` and `robota session analyze` report such sessions as user sessions, never as project sessions.
800
+
801
+ - 57f57f5: A daemon keeps several sessions live, and each client is bound to its own: one client's switch moves
802
+ only that client.
803
+
804
+ - `agent-interface-session`: `ISessionBinder`/`ISessionBinding`, the session-change refusal codes with
805
+ `isSessionChangeRefusal`, and listing rows that may say `live` and `clients`.
806
+ - `agent-framework`: `SessionPool` and `SessionChangeRefusal`.
807
+ - `agent-transport` (**major**): a new server frame, `session_change_failed`, which an exhaustive
808
+ consumer must handle. A refused `new-session` or `switch-session` now answers with it, carrying a
809
+ `code`, instead of `protocol_error`; both requests take an optional `requestId` that it echoes.
810
+ - `agent-transport-ws`: the `sessionBinder` option binds each connection to its own session and
811
+ releases the binding when the connection closes.
812
+ - `agent-cli`: `robota --serve` and the daemon keep up to four sessions live. Each WebSocket client and
813
+ attached terminal is bound to its own session; leaving a busy session is no longer refused, and only
814
+ the last driver of a session with a pending prompt is kept from leaving it. Grants and the supervised
815
+ name stay on the runtime's first session, and its reported activity covers every live session.
816
+ - `agent-ui-web`: a refused new or switch shows the host's reason as a notice (an older host's
817
+ `protocol_error` still does); the session sidebar marks live sessions and counts the other clients
818
+ on each; after a reconnect to a host that keeps sessions live, the GUI returns to the session it was on.
819
+ - `agent-ui-terminal`: an attached terminal shows why a switch was refused, and the picker's switch
820
+ stays pending until the host answers; the session picker marks live sessions and their clients.
821
+
822
+ - ba822c1: An attached client reads a workspace entry's detail, stops a waiting self-paced loop, completes
823
+ subcommands, and sees status changes another client made.
824
+
825
+ - `agent-interface-session` (major): `IInteractiveSession` gains the required roles
826
+ `ISessionExecutionDetail` and `ISessionSelfPacedLoopControl` (`TWaitingLoopStopOutcome`), and the
827
+ exhaustively mapped event map gains `status_changed`.
828
+ - `agent-transport` (major): `IProtocolSession` gains both roles; the wire unions gain
829
+ `read-execution-detail`, `stop-waiting-loop`, `execution_detail`, `execution_detail_error` and
830
+ `waiting_loop_stop`; `status_changed` is pushed as `session_status`; `isObserverMessageType` is
831
+ exported from the root and `./client`.
832
+ - `agent-interface-command` (minor): `ICommandListEntry` gains optional `argumentHint` and
833
+ `subcommands` (`ICommandSubcommandEntry`).
834
+ - `agent-cli` (minor):
835
+ - `robota session attach` and an attach from `robota session view` open the full terminal UI,
836
+ the one `robota --attach` opens, in drive mode or, with `--observe`, read-only. The reduced
837
+ attached view is gone.
838
+ - A served runtime names each of its sessions after the session's first real turn.
839
+ - `agent-framework` (minor):
840
+ - `InteractiveSession` gains `stopWaitingSelfPacedLoop(reason?)`: it stops the one waiting loop,
841
+ or stops none and names `/loop stop` when several wait. `SessionSlot` forwards it and
842
+ `readExecutionWorkspaceDetail`.
843
+ - The session emits `status_changed` when its mode, model, effort, goal or name changes, after a
844
+ command, a turn, a rename or a goal or plan transition.
845
+ - A new option `autoName: true` makes the session name itself once, after its first turn, with its
846
+ current provider; it keeps a name it already has and lets a rename made meanwhile win. Off by
847
+ default.
848
+ - The command catalog carries each command's `argumentHint` and `subcommands`.
849
+ - `agent-ui-terminal` (major):
850
+ - The full terminal UI attached to a host's session reads a workspace entry's detail, sends input
851
+ to a background task, stops a waiting self-paced loop on Esc, and completes subcommands.
852
+ - `renderAttachedApp` takes `mode: 'drive' | 'observe'` (default `'drive'`) and `announce`. In
853
+ observe mode the terminal sends only what an observer may send, refuses prompts, host commands,
854
+ abort and loop stop with a read-only notice, still runs `/exit` and its own commands, and its
855
+ status bar says it is observing. `ITuiChannelSnapshot` gains `readOnly`.
856
+ - The in-process terminal no longer names sessions; it builds its session with `autoName: true`.
857
+ `ITuiInteractionChannelOptions.onAutoNamed` is removed.
858
+
859
+ - 9721162: The command catalog says who runs a command, and which surfaces can run it.
860
+
861
+ - **`agent-interface-command` (major).**
862
+ - Adds `TCommandRunner` (`'runtime' | 'client'`) and `TCommandSurface` (`'terminal' | 'gui'`).
863
+ - `ICommand` gains optional `runner` and `surfaces`.
864
+ - `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'`.
865
+ - **`agent-framework` (minor).**
866
+ - `ISystemCommand` gains optional `runner` and `surfaces`, and the command listing carries both.
867
+ - An undeclared runner resolves to `'runtime'`.
868
+ - `SessionTerminalHandoffGate` is exported for a terminal client that hands its own terminal to a command.
869
+ - **`agent-command` (minor).**
870
+ - `/shell`, `/editor`, `/theme` and `/keybindings` declare `runner: 'client'` and `surfaces: ['terminal']`.
871
+ - `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.
872
+ - **`agent-ui-web` (minor).** The `/` menu marks a command that runs in the terminal with a "terminal" badge.
873
+
874
+ - 6e6b06b: A wire client can now render the whole session the way the in-process terminal UI does: the full
875
+ history, the context window as it changes, when the history changes, and where each turn came from.
876
+
877
+ - `agent-interface-session` is **`major`**: `ISessionConversationRead` gains a required
878
+ `getFullHistory()`. Any implementation of it, or of `IInteractiveSession`, must add it.
879
+ - `agent-transport` is **`major`**:
880
+ - It adds `get-history { fromIndex? }` → `history { startIndex, total, entries }`. The history
881
+ crosses one bounded page at a time (at most 256 KiB of entries; a single larger entry is sent
882
+ alone), from `fromIndex` (default 0), so no reply grows with the session. The client asks for
883
+ the next page after the previous one arrived. Entries are `IWireHistoryEntry`: a history entry
884
+ with an ISO 8601 `timestamp`. An observer may send it.
885
+ - `complete` and `interrupted` carry the turn's result without the session's history
886
+ (`TWireExecutionResult`); a client reads the history with `get-history`.
887
+ - It adds `get-prompts`: the host sends the permission and ask prompts still open as the
888
+ `permission_request` / `ask_request` frames that asked them, for a client that attached later.
889
+ An observer may not send it.
890
+ - `pending` gains an optional `pendingCount`: a host sends it when it knows how many prompts are
891
+ queued, and a client that gets none counts the prompt it shows. The host sends `pending` in
892
+ reply to a `submit` once it has taken the prompt, so a prompt queued behind a running turn shows
893
+ as queued.
894
+ - `command` takes an optional `requestId`, which the host echoes on the command's
895
+ `command_result` or `protocol_error`.
896
+ - The session's `context_update` is pushed as the `context` frame that `get-context` answers with.
897
+ - `compact`, `skill_activation` and `memory_event` push the new `history_changed`; the client
898
+ reads the history again.
899
+ - `turn_source` is pushed as the new `turn_source` frame.
900
+ - An exhaustive map over `TClientMessage` or `TServerMessage` types must add the new variants,
901
+ and `IProtocolSession` now requires `getFullHistory()`.
902
+ - `agent-transport-http` is **`major`** only because `IHttpTransportSession` includes the conversation
903
+ read role, so a session handed to it must now provide `getFullHistory()`.
904
+ - `agent-framework`: `SessionSlot` forwards `getFullHistory()` to the current session.
905
+ - `agent-ui-web` receives the new frames and does not render them.
906
+
907
+ - caaab20: `/rewind` works again. Every session the CLI builds for a trusted workspace captures edit
908
+ checkpoints; before, none did, and `/rewind` failed everywhere with "Edit checkpoints require
909
+ project authority."
910
+
911
+ - `agent-cli` (patch): a trusted workspace composes an edit checkpoint store for the terminal UI, a
912
+ print run, a served runtime and each session a daemon keeps live. Every session gets its own
913
+ 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
914
+ stays inside the project (every platform but Linux), none is composed: a checkpoint could be
915
+ neither saved nor restored there.
916
+ - `agent-command` (patch): where a session has no checkpoints, `/rewind` says why: a restricted
917
+ workspace is told to run `robota trust --yes` and restart Robota, and a host that cannot write
918
+ the project safely says so. `/rewind list` reports this as a failed command instead of throwing.
919
+ - `agent-framework` (minor): a checkpoint operation on a session without a store throws
920
+ `EditCheckpointsUnavailableError`, whose `reason` is `host-cannot-write-project`,
921
+ `restricted-workspace` or `no-checkpoint-store`. It is a `WorkspaceAuthorityRequiredError`, as
922
+ before, named `EditCheckpointsUnavailableError`. `HeadlessInteractionChannel` takes an
923
+ `editCheckpointStore` option.
924
+ - `agent-ui-terminal` (minor): `renderApp` takes `createEditCheckpointStore` in place of
925
+ `editCheckpointStore`, and builds each session its own store, since a session switch can build the
926
+ next session before the old one's turn ends. `TuiInteractionChannel` keeps `editCheckpointStore`:
927
+ a channel runs one session.
928
+
929
+ - f01868f: `sandbox.autoAllowBashIfSandboxed` takes effect. The CLI confined shell commands in the OS sandbox,
930
+ but no session learned about the sandbox, so a confined command still asked for approval in the
931
+ terminal UI, a served runtime and MCP serve, and a print run with no one to approve it refused it.
932
+
933
+ - `agent-cli` (patch): a served session, and each session a daemon keeps live, receives the sandbox
934
+ the shell tools run under.
935
+ - `agent-framework` (minor): `HeadlessInteractionChannel` takes a `sandboxClient` option and hands it
936
+ to the session.
937
+ - `agent-ui-terminal` (minor): `renderApp` and `TuiInteractionChannel` take a `sandboxClient` option
938
+ and hand it to each session they build.
939
+
940
+ - e8779c9: A subagent consults the sandbox its shell tools run under, as its parent does. With
941
+ `autoAllowBashIfSandboxed` on, a confined command the subagent's gate leaves to the mode now runs
942
+ without a prompt. Before, a `context: fork` skill asked for approval, and a print run refused it.
943
+ An Agent-tool subagent in `auto` mode sent a command allowed by a broad rule like `Bash(npm *)` to
944
+ its classifier instead. A background policy's ceiling is still checked first: nothing outside it
945
+ runs.
946
+
947
+ - `agent-framework` (minor): `createSubagentSession` takes a `commandSandbox` option. The fork and the
948
+ in-process runner derive it from the parent's sandbox, the instance their inherited tools run
949
+ under. `sandboxApprovalFor` is exported.
950
+ - `agent-subagent-runner` (minor): `ISubagentWorkerComposition` takes an optional `createSandbox`. The
951
+ worker builds that sandbox once and hands the same instance to `createTools` and to the session.
952
+ - `agent-cli` (patch): Robota's worker composition builds the OS sandbox through `createSandbox`, so
953
+ a child-process subagent approves what its parent approves.
954
+
955
+ ### Patch Changes
956
+
957
+ - 3c81769: A supervised session accepts attach connections on its control socket.
958
+
959
+ - A terminal of the same user sends `{"command":"attach","id","generation","mode":"drive"|"observe","protocol":1}`.
960
+ The session compares the generation with its own. It refuses another generation, an unknown mode or
961
+ protocol, or a fifth concurrent attach. Otherwise it answers `{"status":"attached","driverId":"attach:<n>"}`
962
+ and carries the ordinary session protocol as newline-delimited JSON on the same connection.
963
+ - The driver id is assigned by the session and a client-sent one is ignored. Turns submitted from an
964
+ attached terminal are attributed to it and counted under the new `attach` usage surface.
965
+ - `drive` sends prompts and answers the session's questions under the usual co-drive rules. `observe`
966
+ is read-only and never counts as a surface that can answer, so an unattended session still denies
967
+ its prompts at once.
968
+ - Detaching or crashing ends only that connection: a turn in progress keeps running, a prompt no other
969
+ surface can answer is denied, and the session returns to its unattached posture. A reader that falls
970
+ 1 MiB behind is disconnected, and an oversize frame closes only its own connection. Stopping the
971
+ session ends attached connections with it.
972
+ - Commands from an attached terminal carry the remote origin, so pairing, revoking and reading the
973
+ pairing link stay refused. An attached terminal is never an operator approver; supervised sessions
974
+ keep refusing mesh connections that need one.
975
+ - A client may send its first frames in the same write as the handshake; only the handshake line
976
+ itself is held to the control endpoint's line limit.
977
+ - `agent-framework`: the surface a turn was submitted on now reaches its usage observation. It was
978
+ dropped before, so remote-control turns were counted as `unknown`.
979
+ - The terminal client (`robota session attach`) and the view keys come separately.
980
+
981
+ - 997f2fb: A revoked or closed external-event grant checks the token before it answers, so only a caller holding a valid
982
+ token for that grant learns it was revoked; anyone else gets exactly the refusal a live grant gives. The TUI keeps
983
+ revoked grants open-and-revoked on each session it binds so their tokens are still checked. The per-grant counters
984
+ now also count the refusals the HTTP endpoint decides itself (a missing token, an oversize body).
985
+ - e689c8e: Follow-ups to connection approval and `/handoff`.
986
+
987
+ - `agent-transport-webrtc-web` — the browser remote client says `Waiting for the host to approve this connection…`
988
+ (`awaiting-approval`) after pairing, and `Connected` only once the host's session answers. A host that closes the
989
+ channel instead is shown as `refused` and is not retried, since a retry would only ask the operator again; a
990
+ first connection lost before the host answered is `failed`. Reconnect attempts count until the host admits a
991
+ connection, so a link that keeps dropping while approval is pending gives up instead of asking again and again.
992
+ - `agent-core`, `agent-session`, `agent-framework` — a turn that did not come from the operator stores its
993
+ `turnSource` (`peer`, `external`, `agent-wakeup`) beside `driverId` on the user message and in the display
994
+ history (`IRunOptions.turnSource`), so a session handed off keeps where each turn came from.
995
+ - `agent-cli` — a `/handoff` resent after a lost confirmation reports what stays behind as it is now, not as it was
996
+ at the first attempt, and after refusing to resend a session that changed, the hand-off status shows that refusal
997
+ instead of the earlier lost confirmation.
998
+
999
+ - 4241fc5: Device mesh follow-ups.
1000
+
1001
+ - A device with no identity is pointed to `/devices add` on one of the user's devices and `/devices join`
1002
+ here, as well as to `/devices init`. The message says that `init` is for the first device only,
1003
+ because it creates a separate identity that can never link to the user's other devices. The `/devices`
1004
+ description and the `init` subcommand say the same.
1005
+ - An identity created mid-session (`/devices init`, or a successful `/devices join`) opens the mesh
1006
+ without a restart when `transports.mesh.enabled` is on.
1007
+ - If a session stalls for longer than the mesh lock's stale window (for example while the machine
1008
+ sleeps), another session can take the mesh over. The stalled session now notices this on its next
1009
+ lock refresh, closes its own mesh, and says why. Two sessions no longer run it together.
1010
+ `holdExclusiveFileLock` has a new `onLost` option for this.
1011
+ - `/peers` and `/handoff` still list and reach linked mesh devices when local same-host peer discovery
1012
+ fails. `/peers` says why sessions on this host are not listed. `ICommandLocalPeersAdapter` has a new
1013
+ optional `localDiscoveryOff` field for this.
1014
+ - `agent-transport-webrtc`: when lists become newer on a node (reissued, revoked, or adopted from a
1015
+ peer), the node sends them over every admitted connection instead of waiting for the next handshake.
1016
+ Reissues, revocations and enrolments in the CLI take effect this way at once. A receiver adopts a
1017
+ pushed list only if it is newer, issued by this user's signing key, and verifies. The push does not
1018
+ depend on the peer's capabilities, and it never reaches the application's message handlers.
1019
+
1020
+ - 7d77ce4: `/goal` turns no longer show the goal loop's instruction to the model as a user message. Each surface
1021
+ shows `Goal: <objective> (iteration n of max)`, and the session's auto-generated name comes from that
1022
+ line. The goal's `report_goal_status` and the self-paced loop's `report_loop_decision` are
1023
+ classified as inspections, so they neither ask for permission every turn in `default` mode nor get
1024
+ refused in `plan` mode, where a goal could never finish.
1025
+ - 57280bf: Every published package now declares `"engines": { "node": ">=22.12.0" }`. Before, 27 of the 38
1026
+ packages declared no floor (`agent-core`, `agent-tools` and every provider among them),
1027
+ `agent-session` and `agent-file-authority` declared `>=20.19.0`, and the other nine declared
1028
+ `>=22.0.0`, so a consumer on Node 20 saw at most a warning from a transitive dependency.
1029
+
1030
+ Why 22.12: `agent-cli` and `agent-ui-terminal` need Node 22 through `ink` 7, and the CommonJS entries
1031
+ of `agent-tools` and its dependents, `agent-transport`/`node` and its dependents, and
1032
+ `agent-ui-terminal` `require()` ESM-only dependencies (`p-limit`, `jose`, `chalk`), which Node 22
1033
+ supports unflagged only from 22.12. `engines` is advisory unless the consumer enables `engine-strict`.
1034
+
1035
+ No code changes: `tsdown` now reads `node22.12.0` as its build target from the field.
1036
+
1037
+ - 18c0d5c: Every published package now exports `./package.json`, so `require('<package>/package.json')` and
1038
+ `import('<package>/package.json', { with: { type: 'json' } })` work instead of failing with
1039
+ `ERR_PACKAGE_PATH_NOT_EXPORTED`, and each tarball now ships the package's `CHANGELOG.md`.
1040
+ - 5a0ee96: Workspace trust no longer drops on its own. A grant was keyed by the repository config file and the
1041
+ volume's device number, so `git push -u`, a branch rename or delete, `git remote add`, or macOS
1042
+ renumbering a volume left a trusted workspace untrusted. Where the filesystem records a birth time
1043
+ (APFS, ext4, NTFS, …), the key is now the git directory's own inode and birth time, which hold through
1044
+ all of these while a repository recreated at the same path still does not inherit the grant; elsewhere
1045
+ the stricter config-based key stays. Granting or revoking also retires a trusted record left for the
1046
+ same worktree under an earlier key, so it no longer counts as a second trusted repository; it is
1047
+ marked revoked rather than deleted, so a repository that returns to that path never regains a
1048
+ generation an approval (such as a project MCP server's) was recorded against.
1049
+
1050
+ Grants made before this change are keyed the old way: run `robota trust --yes` once more in each
1051
+ workspace. A workspace revoked before shows as untrusted until it is trusted or revoked again.
1052
+
1053
+ - Updated dependencies [3c81769]
1054
+ - Updated dependencies [724fabb]
1055
+ - Updated dependencies [bfe8ed5]
1056
+ - Updated dependencies [e689c8e]
1057
+ - Updated dependencies [7b72344]
1058
+ - Updated dependencies [6ae3f28]
1059
+ - Updated dependencies [be0e53c]
1060
+ - Updated dependencies [57f57f5]
1061
+ - Updated dependencies [ba822c1]
1062
+ - Updated dependencies [9721162]
1063
+ - Updated dependencies [6e6b06b]
1064
+ - Updated dependencies [8bd5fac]
1065
+ - Updated dependencies [57280bf]
1066
+ - Updated dependencies [5033dd9]
1067
+ - Updated dependencies [18c0d5c]
1068
+ - Updated dependencies [dbd888d]
1069
+ - Updated dependencies [1887e54]
1070
+ - Updated dependencies [0368058]
1071
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.83
1072
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.83
1073
+ - @robota-sdk/agent-core@3.0.0-beta.83
1074
+ - @robota-sdk/agent-session@3.0.0-beta.83
1075
+ - @robota-sdk/agent-interface-session@3.0.0-beta.83
1076
+ - @robota-sdk/agent-interface-command@3.0.0-beta.83
1077
+ - @robota-sdk/agent-executor@3.0.0-beta.83
1078
+ - @robota-sdk/agent-file-authority@3.0.0-beta.83
1079
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.83
1080
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.83
1081
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.83
1082
+ - @robota-sdk/agent-tools@3.0.0-beta.83
1083
+
1084
+ ## 3.0.0-beta.82
1085
+
1086
+ ### Minor Changes
1087
+
1088
+ - c7f9203: Connected sessions can send each other files.
1089
+
1090
+ - `/peers send-file <session-id> <path>` sends a copy of any file the operator can read to another
1091
+ live session on this host.
1092
+ - The model sends a file only through the `peer_send_file` tool. Every call asks the user, showing
1093
+ the path, size, hash and destination; no permission mode, rule or remembered consent answers it.
1094
+ The tool reaches only files inside the workspace whose path does not look like it holds secrets
1095
+ (`.env*`, `~/.ssh`, keys and credentials), and it does not exist in a turn a peer's message started.
1096
+ - The receiving operator approves every file. A received file is kept as an inert copy (mode 0600)
1097
+ under `$PRODUCT_USER_STATE_DIR/peer-files/<sender>/`. It is never run and never placed in the model's context.
1098
+ The conversation is told only its name, size and sha256. A name that leaves that directory is
1099
+ refused, a symbolic link is never written through, and nothing is overwritten.
1100
+ - Transfers travel on a channel of their own (a separate connection on this host, a separate data
1101
+ channel between devices), in chunks the receiver paces, up to 32 MiB, and are kept only when the
1102
+ whole content matches the offered sha256. A transfer that ends early is discarded; there is no
1103
+ resume.
1104
+
1105
+ **API**
1106
+
1107
+ - `agent-interface-session-mobility`: the `file` capability, which asks the operator for every
1108
+ request; `ConnectionAuthority.authorizeFile`; `IFileOffer` and `IFileFrameChannel`.
1109
+ - `agent-transport/node`: `sendFileOverChannel` and `receiveFileOverChannel`, the carrier over any
1110
+ `IFileFrameChannel`; `DEFAULT_MAX_FILE_BYTES`.
1111
+ - `agent-transport-webrtc`: `IDeviceMeshLink.openFileChannel` and `onFileChannel`.
1112
+ - `agent-remote-pairing`: `file` joins `DEVICE_CAPABILITIES`. A device certificate that names it is
1113
+ refused as malformed by an earlier version.
1114
+ - `agent-core`: `IToolPermissionProfile.notInPeerTurn` withholds a tool from a turn a peer's message
1115
+ started.
1116
+ - `agent-framework`: `ICommandLocalPeersAdapter.prepareFile`.
1117
+
1118
+ ### Patch Changes
1119
+
1120
+ - Updated dependencies [c7f9203]
1121
+ - Updated dependencies [004fe7f]
1122
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.82
1123
+ - @robota-sdk/agent-core@3.0.0-beta.82
1124
+ - @robota-sdk/agent-session@3.0.0-beta.82
1125
+ - @robota-sdk/agent-executor@3.0.0-beta.82
1126
+ - @robota-sdk/agent-interface-command@3.0.0-beta.82
1127
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.82
1128
+ - @robota-sdk/agent-interface-session@3.0.0-beta.82
1129
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.82
1130
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.82
1131
+ - @robota-sdk/agent-tools@3.0.0-beta.82
1132
+ - @robota-sdk/agent-file-authority@3.0.0-beta.82
1133
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.82
1134
+
1135
+ ## 3.0.0-beta.81
1136
+
1137
+ ### Major Changes
1138
+
1139
+ - 9843fe6: Sign in to a remote MCP server from inside a session, and use its tools without restarting.
1140
+
1141
+ - **`/mcp login <server> [--no-browser]`** runs the same per-server OAuth sign-in as
1142
+ `robota mcp login` (discovery checks, PKCE, `state`, RFC 9207 `iss`, RFC 8707 resource, the
1143
+ loopback listener, the lock-guarded store). It opens the browser through the argv opener; with
1144
+ `--no-browser`, or when no browser can be opened, it shows the authorization URL and asks for the
1145
+ redirect URL in the session's own prompt (masked), held to the same rules as a pasted redirect in
1146
+ the terminal. A failed, refused, timed-out or cancelled sign-in changes nothing and is reported by
1147
+ a fixed reason only. `/mcp login <server> --client-secret` is refused: a secret is never typed into
1148
+ a session, and `robota mcp login <server> --client-secret` is named instead (also after a failed
1149
+ token exchange for a pre-registered client). `/mcp` stays user-only (`modelInvocable: false`).
1150
+ - **Connected in the same session:** after a sign-in, a server that could not connect for want of
1151
+ one goes through the normal admission (approval, fingerprint, trust) and connects, and its tools
1152
+ are offered from the next message; a server that was already connected is admitted again and
1153
+ reconnects, and its authenticator drops what it held and reads the new credential. A tool left out
1154
+ because the session already has its name is reported, and only tools actually added get
1155
+ provenance. In browser mode the authorization URL is shown in the session prompt before the
1156
+ browser opens, where the user can also choose to paste the redirect instead or cancel.
1157
+ - **`runMCPOAuthLogin`** takes `readRedirectWhenBrowserFails`: when `openBrowser` rejects, the
1158
+ loopback listener stops and the pasted redirect is read instead, for the same redirect URI. The
1159
+ loopback listener's time limit now runs from its first `wait()` — once the authorization page is
1160
+ handed over — so time spent at a prompt before the browser opens does not count against it.
1161
+ - **`Session.addTools`** (and `ICommandSessionTools.addTools`) offers tools that became usable
1162
+ mid-session, through the same permission gate and — via `ISessionOptions.wrapAddedTools`, which
1163
+ `createSession` sets — the same edit-checkpoint and reversible-execution wraps as the assembled
1164
+ tools. A name the session already has is left out, never replaced. Calls are serialized, and tools
1165
+ added while a turn runs are applied when the next turn starts, so a turn's rounds all see one
1166
+ tool list and the prompt cache misses once, at that boundary.
1167
+ - **Breaking (`agent-framework`, major):** `addTools` is a new required member of the
1168
+ `ICommandSessionTools` role port (and so of `ICommandSessionRuntime`). A host that implements the
1169
+ port itself must add it; one that passes an `agent-session` `Session` already has it.
1170
+ - **`ICommandMCPActivationAdapter.oauthLogin`** (`ICommandMCPOAuthLoginRequest`,
1171
+ `ICommandMCPOAuthLoginResult`, `ICommandMCPOAuthRedirectPrompt`) is the port behind it.
1172
+ - The sign-in notice and `/mcp status` now suggest `/mcp login <server>` in a session and
1173
+ `robota mcp login <server>` in a terminal; the server's name is shown only when it is safe to paste
1174
+ into any shell, otherwise `<server>`.
1175
+
1176
+ ### Minor Changes
1177
+
1178
+ - 3038eb7: A message from another session is instant messaging: text from an untrusted third party that
1179
+ carries no authority. What the model does with it is decided by the session's ordinary permissions —
1180
+ rules, permission mode and remembered consent — exactly like the session's own work. The per-origin
1181
+ peer policy is gone.
1182
+
1183
+ **BREAKING**
1184
+
1185
+ - `agent-core`: `IPermissionEvaluationContext.peerTurn` is now a boolean. It decides only whether a
1186
+ `repliesToPeer` tool exists; every other call in a peer turn is decided as in any turn. Removed:
1187
+ `isToolAvailableInPeerTurn`, `isSecretPath`, `IPeerTurnAuthority`, `TPeerReach` (now exported by
1188
+ `agent-interface-session-mobility`) and `IToolPermissionProfile.workspacePaths`.
1189
+ - `agent-tools`: `Read` and `Glob` no longer declare `workspacePaths`.
1190
+ - `agent-session`: `ISessionRunOptions.peerReach` is replaced by `peerTurn?: boolean`, and
1191
+ `ISessionOptions.allowPeerChanges` is removed. An ask in a peer turn is answered like any other:
1192
+ a consent the operator remembered answers it, and an "always allow" given there is remembered.
1193
+ - `agent-interface-session`: `IPeerTurnContext` no longer has `reach`; it carries only the reply
1194
+ route.
1195
+ - `agent-interface-session-mobility`: `peerReachOf` is removed; `TPeerReach` moves here. A delegated
1196
+ turn carries no reach.
1197
+ - `agent-framework`: the `peers.allowChanges` setting is removed (an existing value is ignored). A
1198
+ peer turn is offered the ordinary tools, plus `peer_reply`.
1199
+
1200
+ **Changes**
1201
+
1202
+ - `agent-framework`: the per-turn statement tells the model the message is an opinion from an
1203
+ untrusted third party, not its owner's instruction, and that it decides for itself whether and how
1204
+ to act. A message still expands no `@path` and attaches no context reference, and its requests
1205
+ still carry no provider-hosted tool, since no permission step can decide one. The session takes
1206
+ at most 6 messages a minute and 30 an hour from each sender for a turn; a message over the limit
1207
+ is refused with a reason the sender receives. A prompt answer given in the name of a `peer:` or `external:`
1208
+ driver is ignored. External-event turns keep their tool-less baseline.
1209
+ - `agent-cli`: incoming peer turns carry only their reply route.
1210
+
1211
+ - 02b7452: A reply to a peer session is decided by the permission system like any call that sends something
1212
+ off this machine, and it goes only to the sender that was admitted.
1213
+
1214
+ - `agent-core` — a tool declaring `repliesToPeer` is still refused outside a peer turn; inside one it
1215
+ is decided by the ordinary steps: deny, ask and allow rules, then the mode. It declares no risk
1216
+ class, so it asks by default, is refused in plan mode and proceeds under bypass. `IPeerTurnAuthority`
1217
+ no longer has `toolUsed`.
1218
+ - `agent-session` — an "always allow" answer to the reply is remembered and answers later replies,
1219
+ as for any tool; other asks in a peer turn still need a fresh approval each time.
1220
+ - `agent-framework` — `peer_reply` asks the operator by default, showing the full text and the peer
1221
+ it goes to; `permissions.allow`/`deny` rules naming `peer_reply` apply. `PeerMessageIngress`
1222
+ refuses a message whose origin names a sender other than the admitted one, or whose admission names
1223
+ no sender, and submits the turn with the admitted identity.
1224
+ - `agent-cli` — a local peer message is taken as coming from the session it names only when that
1225
+ session confirms, at its own socket, that it is sending exactly that message to this receiver.
1226
+ The reply target, the driver id and the operator's notices come from the confirmed sender. A
1227
+ session on an earlier version cannot confirm, so its messages are refused; both sessions need this
1228
+ version to message each other.
1229
+
1230
+ - 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 `$PRODUCT_USER_STATE_DIR/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.
1231
+
1232
+ The remote-control host identity key moves into the store. The old `$PRODUCT_USER_STATE_DIR/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.
1233
+
1234
+ - 18b52cc: Built-in commands are offered to the model deliberately, each described for the model, and never
1235
+ with a trust, credential or permission-widening action.
1236
+
1237
+ - `agent-interface-command` — `ICommand` gains `modelDescription?` (what the model is told, beside the
1238
+ short `/help` line), and `modelInvocable` on a subcommand entry now narrows what the model may run.
1239
+ - `agent-framework` — `ISystemCommand` gains `modelDescription?` and `modelRequiresPermission?`.
1240
+ Once any subcommand of a model-invocable command declares `modelInvocable`, the model may run only
1241
+ the bare command and the subcommands declared `true`; everything else, including an alias or an
1242
+ undeclared subcommand, is refused before the command runs. The model-facing descriptor lists only
1243
+ that subset. A model-requested monitor's command is now decided by the shell tool's gate (its
1244
+ Bash/Shell rules, the mode and the prompt) and a refusal rejects with the new
1245
+ `MonitorCommandRefusedError`. The `scriptedSession` test harness accepts `permissions` patterns.
1246
+ - `agent-session` — `Session.checkToolPermission(toolName, toolArgs)` decides an action that has a
1247
+ tool's effect by another route: that tool's PreToolUse hooks, then the gate's rules, mode,
1248
+ remembered consent and prompt — never the command sandbox's auto-approval, since the action does
1249
+ not run inside the sandbox.
1250
+ - `agent-framework` also: `ICommandMCPActivationAdapter.userActionSurface?` tells `/mcp` whether the
1251
+ user can type a session command, so the model's status names the terminal sign-in otherwise.
1252
+ - `agent-command` — `/context` (bare and `list`), `/cost` (the report, not `budget`) and `/mcp`
1253
+ (`status` only, without a prompt) are now model-invocable; `/memory approve` and `/memory reject`
1254
+ are now user-only; the model's `/monitor` is decided by the shell gate rather than by consent to
1255
+ the command's name. Every model-invocable command carries a model-facing description. The model's
1256
+ `/mcp status` shows only safe names, states and the command to suggest, and a caller that does not
1257
+ identify itself gets that view. `/context list` accounts only for turns still in context. New
1258
+ `mcpUserActionNotice`, `mcpUserActionCommand` and `mcpUnavailableServersNotice` build the fixed
1259
+ notices.
1260
+ - `agent-command-workflows` — `/workflows` carries a model-facing description.
1261
+ - `agent-mcp` — `createDiscoveredTool` accepts `authFailureNotice`: a call the server refuses for
1262
+ authentication returns that host text instead of the generic failure.
1263
+ - `agent-cli` — an MCP server that did not start because the user must approve it, trust the
1264
+ workspace or sign in is named to the model at the start of an interactive session with the
1265
+ command to suggest, and a
1266
+ signed-in OAuth server that refuses a call tells the model to suggest `/mcp login <server>` — or, in print and serve runs, the terminal
1267
+ `robota mcp login <server>`.
1268
+
1269
+ A command whose bare form is a complete action declares `runsBare`, so choosing `/cost` or `/mcp`
1270
+ from the autocomplete menu still runs it even though they now declare subcommands.
1271
+
1272
+ ### Patch Changes
1273
+
1274
+ - 007fd90: Authority per connection: pairing stays with the local operator, and driving needs the operator's yes.
1275
+
1276
+ - `agent-interface-session-mobility` — `ConnectionAuthority` decides what one connection may do.
1277
+ `presence` and `message` are allowed; `delegate` and `handoff` ask the receiving operator for every
1278
+ request; `observe` and `drive` ask once per connection. With no `IOperatorApprover` the answer is
1279
+ no. `authorizeDelegation` turns an approved task into a peer turn from where admission placed the
1280
+ peer, ignoring anything else on the request, so the receiver's policy decides what it may do.
1281
+ - `agent-transport-webrtc` — `connectionApproval` asks the operator before a connection reaches the
1282
+ session, after every proof has run. Frames the peer sends meanwhile are held (bounded) and delivered
1283
+ only after a yes. A channel that closes first withdraws the question (the approval context carries
1284
+ an `AbortSignal`), and a later answer admits nothing. A first-pairing device is pinned for
1285
+ reconnect only once it is admitted.
1286
+ - `agent-command` — `/remote-control enable` and `revoke` from a connected surface are refused, and
1287
+ `status` never shows a connected surface the pairing link.
1288
+ - `agent-framework` — the `remote-control-enable` host action runs only for the operator's own
1289
+ command, whichever command asked for it.
1290
+ - `agent-cli` — every remote-control connection, a returning trusted device included, is put to the
1291
+ operator on the host terminal; without an interactive terminal it is refused.
1292
+
1293
+ - Updated dependencies [3038eb7]
1294
+ - Updated dependencies [02b7452]
1295
+ - Updated dependencies [ec5e477]
1296
+ - Updated dependencies [b2e0afe]
1297
+ - Updated dependencies [007fd90]
1298
+ - Updated dependencies [18b52cc]
1299
+ - Updated dependencies [9843fe6]
1300
+ - @robota-sdk/agent-core@3.0.0-beta.81
1301
+ - @robota-sdk/agent-tools@3.0.0-beta.81
1302
+ - @robota-sdk/agent-session@3.0.0-beta.81
1303
+ - @robota-sdk/agent-interface-session@3.0.0-beta.81
1304
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.81
1305
+ - @robota-sdk/agent-interface-command@3.0.0-beta.81
1306
+ - @robota-sdk/agent-executor@3.0.0-beta.81
1307
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.81
1308
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.81
1309
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.81
1310
+ - @robota-sdk/agent-file-authority@3.0.0-beta.81
1311
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.81
1312
+
1313
+ ## 3.0.0-beta.80
1314
+
1315
+ ### Major Changes
1316
+
1317
+ - 9c19c50: `/fork [name] [--same-dir]` copies the live conversation into a background session.
1318
+
1319
+ The session writes a copy of its own record under a fresh id — messages, system prompt, tool schemas
1320
+ and full history, and deliberately not the sandbox snapshot, goal, plan or branch — then spawns a
1321
+ background job carrying only `resumeSessionId`. The child restores that record itself, so no
1322
+ conversation crosses the child-process boundary and the worker start payload's key set is unchanged.
1323
+ The background panel gains an `attach` control that switches the terminal onto the forked session; it
1324
+ is a view switch, never a merge, and a missing record or a terminal task is refused with the task's
1325
+ own status.
1326
+
1327
+ **`@robota-sdk/agent-framework` is `major` for one reason: `ICommandHostSessionAccess` gains a
1328
+ required member.** `forkSession({ name? })` is not optional, so an external implementation of that
1329
+ role port stops compiling until it adds the method. Every other change in this set is additive:
1330
+
1331
+ - `agent-interface-execution` — `TExecutionControl` gains `'attach'`.
1332
+ - `agent-interface-command` — `TCommandUiIntent` gains `{ type: 'switch-session'; sessionId }`.
1333
+ - `agent-subagent-runner` — `ISubagentWorkerComposition` gains the optional `openSessionStore`, and
1334
+ the worker resumes a record when the job names one. A composition that registers no store and
1335
+ receives no `resumeSessionId` behaves exactly as before.
1336
+ - `agent-framework` also gains the fork-record builder, `SessionTurnMemory`, and
1337
+ `IAgentBackgroundTaskRequest.resumeSessionId?`; `loadSessionRecord` now returns
1338
+ `restoredSystemPrompt`, which makes a record field that was written and never read take effect on
1339
+ restore.
1340
+ - `agent-executor`, `agent-command`, `agent-transport-tui`, `agent-cli` — the spawn input, the
1341
+ `/fork` module and the attach control that carry it to the surface.
1342
+
1343
+ - 818f0c8: `createSession` and `ICreateSessionResult` are no longer exported from the package root.
1344
+
1345
+ **Migration — `createSession`.** Use `InteractiveSession`, or `createAgentRuntime().createSession(IHeadlessSessionOptions)`, or `createQuery()`. It was the low-level assembly seam, not the intended session entry point; the session-creation route is unchanged for consumers already using one of those three.
1346
+
1347
+ **Migration — `ICreateSessionResult`: there is none, and that is stated rather than glossed.** The package's `exports` map exposes only `.` and `./testing`, so the assembly barrel that still declares the type is unreachable from outside the package. A released consumer importing this type has no replacement path and must stop referring to it. What it _named_ is largely still reachable — its `session` field is a `Session`, which `@robota-sdk/agent-session` exports and which `InteractiveSession.getSession()` returns — so the loss is the aggregate type itself, not the things it described. This is the break the `major` bump declares.
1348
+
1349
+ **Impact on published consumers differs between the two symbols, and the earlier draft of this note got it wrong.** Resolved against the published `3.0.0-beta.79` `dist/node/index.d.ts` (466 exported names), not against the source barrel:
1350
+
1351
+ - `createSession` is **absent** from the published surface. It was root-exported on 2026-08-16, after the 2026-07-06 release, so no released consumer can be calling it.
1352
+ - `ICreateSessionResult` **is published** — root-exported since 2026-06-14 and present at the release commit. Removing it is a genuine break to the published type surface, which is what the `major` bump declares.
1353
+
1354
+ Neither fact is the reason for the removal. `.agents/project-structure.md` § Forward-Provisioned Surface Rule bans consumer-count reasoning about a public surface at any count. The reason is that the surface does not fit the design — `ICreateSessionOptions` is a 60-field internal projection target, and the 2026-03-26 SDK scope redesign already decided this factory is internal. The published-surface facts are recorded so a consumer can tell which removal can affect them, not to justify either.
1355
+
1356
+ `ICreateSessionOptions` remains exported: four packages read indexed-access types off it as the option SSOT, and it is this package's own type.
1357
+
1358
+ Closes issue #2270's export half. Its no-opt-out half stays open against issue #2238 — this change does **not** make the unconditional executor seeding safe, and the SPEC deliberately declines to reinstate that argument even though the un-export makes it literally true again.
1359
+
1360
+ - 9368d00: Advisor escalation: the main model can consult a second model at the decision points it chooses.
1361
+
1362
+ With an advisor configured (`--advisor <profile>[:<model>]`, or the `advisorModel` setting that
1363
+ `/advisor` saves; the flag wins), the session gets an `Advisor({ question? })` tool. The advisor reads
1364
+ the whole conversation — system prompt, messages, tool calls and results — serialized into one prompt
1365
+ and sent with `toolChoice: 'none'`, truncated from the front to fit its window with the system prompt
1366
+ kept, and declines when even that does not fit. Its answer comes back framed as guidance to verify;
1367
+ an empty or refusing answer reads as declined. Calls are limited to two per turn and a fixed number
1368
+ per session, parallel calls in one round share those limits, and a repeated question in the same
1369
+ turn returns the earlier answer. A request that was sent counts even when the provider failed (the
1370
+ decline is reported by class, never by its text); only a call declined before sending gives its slot
1371
+ back.
1372
+
1373
+ Advisor usage, including in-process subagents', is recorded where each turn's usage is recorded —
1374
+ the persisted session history, under the advisor's own provider and model — so `/cost`, usage reports
1375
+ and resumed sessions include it. `/cost` now totals that history and prices each part on its own
1376
+ model, showing "mixed" when more than one model was priced.
1377
+
1378
+ `/advisor <model>` and `/advisor off` change only where calls go, never the tool list, so the main
1379
+ model's prompt cache is not invalidated mid-session; the tool is added only when a session starts
1380
+ with an advisor. Sending history to a destination (provider type and endpoint host) the main model
1381
+ does not already use needs a one-time consent per destination, kept in the user settings file; a
1382
+ refusal is remembered for the session. The organization's `allowedProviders` applies, and
1383
+ `PRODUCT_DISABLE_ADVISOR=1` turns it off completely. In-process subagents inherit the advisor, bound
1384
+ to their own conversation; child-process subagents do not get it.
1385
+
1386
+ **`@robota-sdk/agent-framework` is `major` for one reason: `ICommandHostSessionAccess` gains a
1387
+ required member,** `getSessionUsage()`, the session's persisted usage records. An external
1388
+ implementation of that role port stops compiling until it adds the method. The rest is additive.
1389
+
1390
+ - `agent-session` — `formatConversationEntries`, the one text rendering of a conversation, now used
1391
+ by compaction too. It keeps tool calls and results, marks a user message a peer session sent
1392
+ (`user [from "peer:<id>"]`), and JSON-encodes every message onto one line so no content can forge
1393
+ another entry; compaction previously flattened all of this. `Session.getProvider()` returns the
1394
+ provider the session currently uses.
1395
+ - `agent-framework` — `AdvisorController`, `createAdvisorTool`, the advisor spec helpers, provider
1396
+ destinations (`describeProviderDestination`, `rememberProviderDestination`), `getSessionUsage` and
1397
+ `ISessionUsageRecord`, the `onUsageRecorded` session option, and the optional `advisor` command
1398
+ host adapter. Session assembly binds a host-supplied Advisor tool to the session holding it.
1399
+ - `agent-command` — the `/advisor` command module; `/cost` reads the session's persisted usage.
1400
+ - `agent-cli` — the `--advisor` flag, `advisorModel` setting, per-destination consent store and kill
1401
+ switch.
1402
+ - `agent-ui-terminal` — a usage line from another source (the advisor, a background task) names that
1403
+ source and leaves out the context window it does not have.
1404
+ - `agent-session-analytics` — personal usage counts an advisor call's tokens and cost toward its
1405
+ turn without counting it as a turn.
1406
+
1407
+ - f336838: One permission evaluation order for every caller. The interactive session, background tasks and
1408
+ subagents used to run two different resolvers, so the same call could be decided differently
1409
+ depending on who made it. They now share `evaluatePermission`, and a background policy only adds a
1410
+ ceiling, an ask-everything flag and the task's own lists to it:
1411
+
1412
+ deny → caller ceiling → unevaluable deny (ask) → never-auto-approve set (ask) → ask-everything →
1413
+ bypassPermissions → allow → mode.
1414
+
1415
+ - **`ask` rules.** `permissions.ask` patterns always ask, in every mode including
1416
+ `bypassPermissions`. They are matched per command like a deny rule, and are validated at
1417
+ construction alongside `allow` and `deny`.
1418
+ - **Never auto-approved, bypass included:** removing a critical path with `rm`/`rmdir` (the root, a
1419
+ top-level directory, home, the working directory or a parent), and a modify-class write into
1420
+ `.git`, `.Robota`, `.claude`, `.agents`, `.mcp.json`, `.gitconfig`, `.npmrc` or a shell rc file.
1421
+ Files inside an isolated worktree (`$PRODUCT_PROJECT_STATE_DIR/worktrees/<name>/…`) are ordinary files. With no
1422
+ approver attached, an ask is a denial.
1423
+ - **A ceiling is checked before bypass and before any ask.** A subagent's `inherit-allowlist` ceiling
1424
+ is now the parent's _effective_ rules, read live at spawn: settings, preset lists and command
1425
+ auto-allows. It used to be the raw settings file. An unevaluable deny under a policy now asks,
1426
+ like everywhere else, where it used to deny outright; with no approver it is still a denial.
1427
+ - **Settings layers union `permissions.allow`**, as they already did `deny`. A checked-in project
1428
+ file no longer silently discards the user's allow list.
1429
+ - **Print mode, `createQuery()` and headless sessions default to `default` mode**, not
1430
+ `bypassPermissions`. They have no approver, so a call that would ask is denied. Pass
1431
+ `--permission-mode` / `permissionMode: 'bypassPermissions'` explicitly for unattended runs.
1432
+
1433
+ **Breaking:**
1434
+ - `@robota-sdk/agent-core` removes `resolvePermissionByPolicy` and `TPermissionPolicyDecision` in
1435
+ favour of `projectPermissionPolicy` plus `evaluatePermission`'s new `context` argument.
1436
+ - `@robota-sdk/agent-framework` changes the settings merge rule for `permissions.allow`, and the
1437
+ default permission mode of `createQuery()` and headless sessions.
1438
+
1439
+ - 807d161: **BREAKING — ARCH-010: the execution root is a required contract field, and the containment guard now fails closed.**
1440
+
1441
+ The file-tool containment guard was fail-open: with no root configured it answered "allowed". A tool
1442
+ built with no `cwd` therefore had no boundary — measured, a `Read` constructed that way returned the
1443
+ contents of `/etc/hostname` — and the child-process subagent worker called `createDefaultTools()` with
1444
+ no argument at all, so subagents got exactly that. Three independent auditors found three different
1445
+ symptoms of this one missing field.
1446
+
1447
+ **Removed — seven context-free tool singletons.** `readTool`, `writeTool`, `editTool`, `globTool`,
1448
+ `grepTool`, `shellTool`, `bashTool` are gone from `@robota-sdk/agent-tools`. A module-level instance is
1449
+ bound at import time and can carry no containment root, so after the guard was inverted they could only
1450
+ refuse everything.
1451
+
1452
+ Migrate to the factory of the same name, passing the directory the tool is allowed to work in:
1453
+
1454
+ ```ts
1455
+ // before
1456
+ import { readTool, globTool } from '@robota-sdk/agent-tools';
1457
+ const tools = [readTool, globTool];
1458
+
1459
+ // after
1460
+ import { createReadTool, createGlobTool } from '@robota-sdk/agent-tools';
1461
+ const cwd = process.cwd(); // or the workspace this agent is scoped to
1462
+ const tools = [createReadTool({ cwd }), createGlobTool({ cwd })];
1463
+ ```
1464
+
1465
+ `webFetchTool`, `webSearchTool` and `askUserQuestionTool` are unchanged — they touch no filesystem, so
1466
+ there is no root to contain them by.
1467
+
1468
+ **`cwd` is now REQUIRED** on `ISandboxToolOptions`, `IContainedBuiltinToolOptions` (and everything
1469
+ extending them), `ICreateDefaultToolsOptions`, `ISessionOptions` and `ISubagentOptions`. The `= {}`
1470
+ default parameter was removed from every builtin factory — that default was the mechanism by which
1471
+ "forgot the root" was legal. `new Session({...})` without `cwd` no longer compiles, and also throws at
1472
+ construction, because a required field is only required to a TypeScript caller.
1473
+
1474
+ **`Session` no longer reads `process.cwd()`.** It uses the root it was given, and `getCwd()` exposes it
1475
+ so a fork or subagent asks the session instead of re-deriving a root that can disagree with it.
1476
+
1477
+ **Behavioural change even for callers that already passed a root**: a tool that somehow reaches the
1478
+ guard with no root now REFUSES with an explicit error ("no containment root is configured … this is an
1479
+ assembly bug, not a path problem") instead of allowing the access.
1480
+
1481
+ - e82215f: **ARCH-011: replace the ambiguous transport lifecycle stub with executable conformance.**
1482
+
1483
+ `ITransportAdapter` now requires a frozen `service | runner` lifecycle descriptor. `start()` resolves
1484
+ at the concrete transport's documented readiness boundary; start before attach and repeated active
1485
+ start reject a stable lifecycle error, repeated stop is safe, and stopped adapters can reattach and
1486
+ restart.
1487
+
1488
+ Runner adapters launch separately and expose a typed terminal outcome through
1489
+ `waitForCompletion()`. The registry accepts base adapters, rejects duplicate names, keeps
1490
+ configuration as an optional capability, returns complete ordered records whose pending slots become
1491
+ registry-owned `abandoned` outcomes on stop/rollback, and exposes a real-runner-only first-failure
1492
+ wait. It serializes startup/stop, rejects active restart before mutation, and reverses partial startup
1493
+ from the currently failing adapter with typed safe rollback details. Runtime host and serve mode
1494
+ propagate real nonzero runner results without treating normal shutdown abandonment as failure.
1495
+
1496
+ HTTP, MCP, both WebSocket adapters, WebRTC, and headless invoke one shared public conformance kit.
1497
+ The former `TuiTransport` export is removed because it ignored the attached session; use `renderApp`
1498
+ or `TuiInteractionChannel`, which honestly own their session lifecycle.
1499
+
1500
+ - 52b7346: **BREAKING — ARCH-012: three `IInteractiveSession` members become required, and the conformant test double moves.**
1501
+
1502
+ `isInitialized`, `getPendingCount` and `getActiveDriverId` were OPTIONAL. A consumer reading
1503
+ `session.getActiveDriverId?.() ?? undefined` received the same `undefined` for two unrelated
1504
+ situations — the host attributes turns and none is active, and the host cannot attribute turns at all
1505
+ — with no error, no log, and nothing to tell them apart. The second loses every co-drive attribution
1506
+ silently.
1507
+
1508
+ **Any implementation of `IInteractiveSession` must now provide all three.** `null` from
1509
+ `getActiveDriverId()` means exactly one thing: nobody is driving.
1510
+
1511
+ ```ts
1512
+ // before — a host could simply omit these
1513
+ class MySession implements IInteractiveSession {
1514
+ submit(/* … */) {
1515
+ /* … */
1516
+ }
1517
+ }
1518
+
1519
+ // after
1520
+ class MySession implements IInteractiveSession {
1521
+ readonly isInitialized = true;
1522
+ getPendingCount(): number {
1523
+ return this.queue.length;
1524
+ }
1525
+ getActiveDriverId(): TDriverId | null {
1526
+ return this.activeDriver ?? null;
1527
+ }
1528
+ submit(/* … */) {
1529
+ /* … */
1530
+ }
1531
+ }
1532
+ ```
1533
+
1534
+ **`createTestInteractiveSession` moved** from `@robota-sdk/agent-framework` (its `./testing` subpath)
1535
+ to `@robota-sdk/agent-interface-transport/testing`, beside the contract it doubles. It is **not**
1536
+ re-exported from the old location: pass-through re-exports of another package's symbols are banned in
1537
+ this repo, and the old export had no in-repo consumers — every transport package sits below
1538
+ `agent-framework` and could never import it, which is why 41 hand-rolled partials existed instead.
1539
+
1540
+ ```ts
1541
+ // before
1542
+ import { createTestInteractiveSession } from '@robota-sdk/agent-framework/testing';
1543
+ // after
1544
+ import { createTestInteractiveSession } from '@robota-sdk/agent-interface-transport/testing';
1545
+ ```
1546
+
1547
+ - 2ebff01: Remove the obsolete session-level permission and ask callback options and the stale
1548
+ `permission-resolved` display event. Prompt requests now settle exclusively through the canonical
1549
+ request events and session resolution methods, while leaf adapters fail closed when callbacks reject.
1550
+ - 2d3b2c0: Remove pass-through exports for agent-core environment-reference helpers and agent-session session-id
1551
+ guards. Import `formatEnvReference`, `hasUsableSecretReference`, `isEnvReference`, and
1552
+ `resolveEnvReference` from `@robota-sdk/agent-core`, and import `assertSafeSessionId` and
1553
+ `isSafeSessionId` from `@robota-sdk/agent-session`.
1554
+ - 2d3b2c0: ARCH-024 replaces framework knowledge of command-owner ids with optional, owner-declared semantic
1555
+ roles. `ISystemCommand` can declare `skillActivation`, `contextReduction`, or `subagentSpawn`;
1556
+ `SystemCommandExecutor` exposes the selected role projection and rejects duplicate owners with the
1557
+ typed `DuplicateSystemCommandSemanticRoleError`, atomically across construction, registration, and
1558
+ replacement.
1559
+
1560
+ This is a beta-line breaking contract correction: unannotated commands named `skills`, `compact`, or
1561
+ `agent` no longer receive special framework behavior. `@robota-sdk/agent-command` now declares the
1562
+ roles on its shipped skills, compact, and agent commands.
1563
+
1564
+ - 3a8876b: ARCH-029: decompose the command host into role ports
1565
+
1566
+ `ICommandHostContext`, `ICommandSessionRuntime` and `IAgentJobHostContext` are now empty `extends`
1567
+ aggregates over 26 named role ports, so a command declares only the capability it uses. A role port
1568
+ is a supertype of the aggregate, so narrowing a declared parameter still satisfies
1569
+ `ISystemCommand.execute` by contravariance.
1570
+
1571
+ All 79 members are preserved (46 + 18 + 15) with the declaration kind unchanged, so implementors and
1572
+ callers stay source-compatible.
1573
+
1574
+ **Breaking:** every role-port member is now required except the adapter bag, whose contents are
1575
+ genuinely variational. 38 members went from optional to required. A host that previously omitted a
1576
+ member must now provide one — including `validateCurrentSessionReplayLog`, which was an override
1577
+ with a framework-computed default and no implementor. `createTestCommandHost`,
1578
+ `createTestAgentJobHost` and `createTestSessionRuntime` are published from
1579
+ `@robota-sdk/agent-framework/testing` as conformant, cast-free doubles for exactly this.
1580
+
1581
+ Also removed: the `clearConversationHistory` fallback that reached past the host into
1582
+ `getSession().clearHistory()`. Those were never the same operation — the host path also broadcasts
1583
+ `history_cleared` to every attached surface, so a fallback clear left other surfaces still showing
1584
+ the transcript.
1585
+
1586
+ - 4772067: **BREAKING — ARCH-031: the subagent seam is derived from its transport SSOT instead of copied.**
1587
+
1588
+ One field family — what a subagent job IS — was declared three times as independent shapes and carried
1589
+ between them by six hand-written object literals that nothing checked for totality. A field added to
1590
+ either side had to be hand-copied at every hop, and a miss compiled clean as a silent no-op. TYPE-003
1591
+ named this cause and derived one hop; the next two changes each dropped a field at a hop it had skipped
1592
+ (CORE-025's permission policy, and ANALYTICS-001's `usage`, dropped in the very commit that added it).
1593
+
1594
+ ```ts
1595
+ // now, in @robota-sdk/agent-interface-transport
1596
+ export type ISubagentSpawnRequest = Omit<IAgentBackgroundTaskRequest, 'kind'>;
1597
+ export type ISubagentJobResult = Omit<IBackgroundTaskResult, 'kind' | 'exitCode' | 'signalCode'>;
1598
+ ```
1599
+
1600
+ All four projections collapse to spreads. `parentTaskId` and `providerProfile` now reach the runner
1601
+ because they exist on the source, not because someone remembered them.
1602
+
1603
+ **Per package, classified against each barrel:**
1604
+
1605
+ - **`agent-executor` (major)** — the barrel loses `ISubagentSpawnRequest` and `ISubagentJobResult` (they
1606
+ moved to their owner; re-publishing them here would be a pass-through re-export). `ISubagentJobStart`
1607
+ and `ISubagentJobHandle` rename `jobId` → `taskId`, `ISubagentJobStart` gains `worktree?`, and
1608
+ `ISubagentWorktreePrepareRequest` renames `jobId` → `taskId`.
1609
+ - **`agent-framework` (major)** — the barrel loses eleven type-only re-exports of `agent-executor`-owned
1610
+ types. They carried zero runtime values, so they bought none of the assembly convenience a runtime
1611
+ facade exists for, while making one field family look like it had three owners. Separately,
1612
+ `ISpawnAgentTaskRequest.permissionPolicy` goes optional → **required**.
1613
+ - **`agent-subagent-runner` (major)** — `ISubagentWorkerStartPayload` renames `jobId` → `taskId` and gains
1614
+ `worktree?`. This package is not in the item's declared `area:`; the audit that caught it is the reason
1615
+ it is here.
1616
+ - **`agent-interface-transport` (minor)** — two new barrel exports; nothing removed or renamed.
1617
+ - **`agent-core` (minor)** — **two** new barrel exports. `DEFAULT_BACKGROUND_PERMISSION_POLICY` is the
1618
+ intended one; collapsing the hand-listed permissions block to `export *` also surfaced
1619
+ `clearRegisteredToolArgumentKeys`, which the old list had omitted. It is documented as public rather
1620
+ than re-narrowed — a barrel that cannot fall out of step with its owner is the point of the collapse.
1621
+ Nothing was removed: all nine previously-listed permission types remain on the barrel.
1622
+ - **`agent-cli` (patch)** — migrated as the only in-repo implementer of `ISubagentWorktreeAdapter`; no
1623
+ barrel change.
1624
+
1625
+ **`permissionPolicy` is now required at the spawn boundary**, and its default is one exported constant
1626
+ owned by the permission SSOT. It was previously applied as `?? 'inherit-allowlist'` in the middle of a
1627
+ projection, in **two** packages independently, with nothing keeping them equal — a security-relevant value
1628
+ whose default was declared twice. Every spawn site now states its own policy.
1629
+
1630
+ **The worktree identity moved to the runner envelope.** It is runner-produced — the worktree does not
1631
+ exist when a caller builds a request — so it rides on `ISubagentJobStart.worktree` and crosses the IPC
1632
+ boundary there. The runner no longer also rewrites `request.cwd`, which had given ARCH-010's execution-root
1633
+ rule two carriers that could disagree. `branchName` **relocated rather than being deleted**: it has no
1634
+ reader in this repository today, and for a library that is not a reason to drop a legitimate contract.
1635
+
1636
+ **Renames are consistent across the SPI** (`type` → `agentType`, `jobId` → `taskId`) rather than applied to
1637
+ one shape, which would have left two names for one identifier in a single file. The IPC validator's
1638
+ string-literal keys are now typed against the contract, so the next rename is a compile error instead of a
1639
+ runtime rejection of every start payload.
1640
+
1641
+ - 7b85767: ARCH-035 — the default tool set becomes a composition leaf.
1642
+
1643
+ **New package: `@robota-sdk/agent-tool-defaults`.** It owns `createDefaultTools` and
1644
+ `ICreateDefaultToolsOptions`, including the adapter gating that adds `CodebaseRetrieval` when a
1645
+ `retrievalAdapter` is supplied and the Computer tools when a `computerDriver` is.
1646
+
1647
+ **Breaking for `@robota-sdk/agent-framework`:** `createDefaultTools` and `ICreateDefaultToolsOptions`
1648
+ are no longer exported from it. Import them from `@robota-sdk/agent-tool-defaults`. The packages are
1649
+ pre-release and this repo keeps no compatibility shims, so they are moved rather than deprecated.
1650
+
1651
+ **Also breaking:** the internal `createSession` assembly factory is now `async`. This does NOT affect
1652
+ `IAgentRuntime.createSession`, which stays synchronous — it does not call that factory, and a
1653
+ verification scenario now asserts that explicitly, because propagating async through it would break
1654
+ every consumer that builds a session without supplying `defaultTools`.
1655
+
1656
+ **Zero-config behaviour is unchanged**, deliberately. `createQuery` and the headless runtime have no
1657
+ `defaultTools` seam, so a session built without one still receives the built-in tool tier —
1658
+ `agent-framework` reaches the new leaf through a dynamic `import()`. An earlier revision of this work
1659
+ proposed deleting the tier outright and was rejected on measurement: two published surfaces cannot
1660
+ express the alternative, and the failure mode was a silently toolless agent behind a green typecheck.
1661
+
1662
+ **Why the move matters.** `agent-subagent-runner` legitimately depends on `agent-framework`, so while
1663
+ the aggregator sat on that barrel a neutral runner could compose the product's tool surface with only
1664
+ a scan in the way. It has no manifest edge to the new leaf, so that import does not resolve there at
1665
+ all — the guarantee is carried by the type system now, mirroring what `@robota-sdk/agent-provider-defaults`
1666
+ already does on the provider axis.
1667
+
1668
+ `@robota-sdk/pack-coding` is a patch: it consumes the leaf instead of rebuilding the same list by
1669
+ hand. Its contributed tool surface is unchanged — verified from the published tarballs.
1670
+
1671
+ - 64ba748: **BREAKING — ARCH-042: project filesystem access is now an explicit, host-issued authority instead of an ambient consequence of `cwd`.**
1672
+
1673
+ `@robota-sdk/agent-framework` adds `WorkspaceTrustService` and the opaque
1674
+ `IWorkspaceProjectAuthority`, plus bounded reader, settings-writer, state-storage, and mutation
1675
+ facets. Public session, settings, context, checkpoint, memory, contribution, query, and replay
1676
+ contracts consume those facets. A caller that does not supply `projectAccess` is deliberately
1677
+ restricted to user-owned host state and receives no project filesystem capability.
1678
+
1679
+ The framework removes or renames ambient Node/project exports. Migrate `checkSettingsFile` to
1680
+ `checkNodeHostSettingsFile`, `readMergedProviderSettingsFromPaths` to
1681
+ `readMergedProviderSettingsFromSources`, `resolveProviderSettingsWriteTargetPath` to
1682
+ `resolveProviderSettingsWriteTarget`, `FileSystemMemoryStore` / `createFileSystemMemoryStore` to
1683
+ `WorkspaceMemoryStore` / `createWorkspaceMemoryStore`, and `PluginSettingsStore` to
1684
+ `NodeHostPluginSettingsStore`. Host-only git helpers now carry the `FromNodeHost` suffix.
1685
+ `projectPaths`, `resolveSettingsPathForScope`, and `getProviderSettingsPaths` are removed; project
1686
+ consumers must use the authority facets rather than recover absolute paths.
1687
+
1688
+ `@robota-sdk/agent-session` renames the Node filesystem implementation `SessionStore` to
1689
+ `NodeSessionStore` and adds explicit session-log/external-payload source and sink ports. Session
1690
+ replay no longer resolves external payload files from an ambient directory.
1691
+
1692
+ `@robota-sdk/agent-interface-transport` changes `ISkillExecutionPort.loadCommands(cwd, home?)` to
1693
+ the authority-bound `loadCommands()` and removes the optional absolute-path leak
1694
+ `IInteractiveSessionStore.getFilePath`. `@robota-sdk/agent-command` consequently replaces the
1695
+ `cwd` option of `createSkillsCommandModule` with required `contributionSources`; default command
1696
+ composition accepts explicit contribution sources and discovers no project skills when none are
1697
+ provided.
1698
+
1699
+ `@robota-sdk/agent-cli`, `@robota-sdk/agent-transport`, and
1700
+ `@robota-sdk/agent-transport-tui` thread the trusted-or-restricted project decision through every
1701
+ session surface. Embedded callers that need project settings, state, context, skills, checkpoints,
1702
+ or mutation must mint access through `WorkspaceTrustService` and pass the returned
1703
+ `projectAccess` (and a separately approved mutation/settings facet where required). Omitting it is
1704
+ still type-compatible but is behaviorally breaking: the surface now fails closed instead of
1705
+ reading or writing the current directory.
1706
+
1707
+ - fe48835: Honor skill model selection in forked child sessions. Skill metadata that specifies a model now requires `context: fork` instead of silently ignoring the model during ordinary execution. Startup errors for configured hooks without executors now identify their settings and enabled plugin sources.
1708
+ - 1e40b5b: Move handoff source/destination orchestration and its contract from agent-framework to the session-mobility owner. Import `HandoffSource`, `HandoffDestination`, and their option types from `@robota-sdk/agent-interface-session-mobility`. Mobility now applies offer and authority decisions directly, while the CLI supplies wire effects and the session-record decoder. A successful offer no longer returns a mutable authority transaction.
1709
+ - 8865acf: The framework now defaults to neutral model-facing identifiers: projected command tools use
1710
+ `command_` and attached file content uses `<file_references>`. This changes the default output of
1711
+ `MODEL_COMMAND_TOOL_PREFIX`, `createProviderSafeModelCommandToolName`,
1712
+ `createModelCommandToolProjection`, and `buildPromptWithFileReferences` for SDK consumers.
1713
+
1714
+ To preserve the previous identifiers, pass `modelCommandToolPrefix: 'robota_command_'` and
1715
+ `promptFileReferenceTag: 'PRODUCT_file_references'` in session options, or pass those values to
1716
+ the projection and prompt-format helpers. The Robota product profile supplies both values, so
1717
+ the Robota CLI keeps its existing model tool names and prompt enclosure.
1718
+
1719
+ - 5134b3b: **BREAKING — RUNTIME-003 P2: `submit` hands back the submission's identity, so an answer belongs to
1720
+ the caller who asked for it.**
1721
+
1722
+ `submit` returned nothing, so a caller that needed to know when ITS turn ended had only the
1723
+ session-global `complete` / `interrupted` / `error` events — which say that A turn ended and never
1724
+ which one. The MCP adapter did exactly that, and the result was measurable: a session runs one turn
1725
+ at a time and queues the rest, so two concurrent `submit` calls did not run concurrently. The second
1726
+ waited and then took the RUNNING turn's response as its own answer. Both callers were told about one
1727
+ turn; neither was told which.
1728
+
1729
+ `submit` now returns an `ITurnHandle` — `{ turnId, completed }`. The id is minted when the submission
1730
+ is ACCEPTED and kept if it waits in the queue, so one submission is one identity from end to end.
1731
+
1732
+ `completed` always settles, and that is the part that took the work. A queued submission is not
1733
+ promised a turn: the co-drive queue coalesces a same-driver input into the one behind it, drops at
1734
+ capacity, and discards everything when cleared. A handle that settled only for submissions that ran
1735
+ would leave the rest waiting forever — a worse failure than the ambiguity it replaces — so each of
1736
+ those rejects with a typed `TurnNotRunError` naming which happened (`coalesced`, `dropped`,
1737
+ `cancelled` — shutdown clears the queue through the same path, so it reports as cancelled).
1738
+
1739
+ **Migration.** A caller that ignores the return value is unaffected: `await session.submit(...)`
1740
+ still means what it did, and the direct path still resolves only when the turn is over. An
1741
+ IMPLEMENTER of `IInteractiveSession` must now return a handle:
1742
+
1743
+ ```ts
1744
+ // before
1745
+ async submit(input: string): Promise<void> {
1746
+ await runTurn(input);
1747
+ }
1748
+
1749
+ // after
1750
+ async submit(input: string): Promise<ITurnHandle> {
1751
+ const turnId = crypto.randomUUID();
1752
+ return { turnId, completed: runTurn(input) };
1753
+ }
1754
+ ```
1755
+
1756
+ `createTestInteractiveSession` already returns a conforming handle, so a double built on it needs no
1757
+ change.
1758
+
1759
+ One thing this deliberately does NOT do: DAG run advancement (P3) stays with DAG-001.
1760
+
1761
+ An earlier draft of this note claimed the HTTP route's documented TOCTOU had been measured and was
1762
+ not reachable. That was wrong, and it is corrected here rather than left for a reader to trip over.
1763
+ The probe behind it used a `submit` stub with no suspension point, so it could not exhibit the race
1764
+ it was written to rule out; the real `submit` opens with `await ensureInitialized()`. The race is
1765
+ real and is fixed in its own change (#1656), where the route CLAIMS the turn instead of asking
1766
+ whether one is running.
1767
+
1768
+ - 1f57e7f: **BREAKING — RUNTIME-006: align the exported concrete `InteractiveSession.submit` options with the
1769
+ transport-owned `IInteractiveSession` contract.**
1770
+
1771
+ The concrete class no longer exposes framework-internal turn metadata through its fourth argument;
1772
+ public callers may pass only `ISubmitOptions` (`driverId`). New public and internal submissions
1773
+ always mint a fresh turn identity. An already accepted queued submission now resumes through a
1774
+ private required-identity path instead of re-entering public `submit`, so runtime extra properties
1775
+ cannot select or reuse another turn's identity.
1776
+
1777
+ Queued entries, execution, and every settle/fail/refuse operation now require `turnId`. The former
1778
+ undefined no-op guards and the alternate settler lookup seam are removed, preserving the contract
1779
+ that every accepted handle settles for its own turn or typed refusal.
1780
+
1781
+ - db5c439: Framework query, runtime, interactive, and headless session creation now pass through one validated `SessionRecipe` constructor seam. Standard interactive options require provider and working directory; wrapping a host-owned session remains an explicit recipe mode, and test doubles use the package's `/testing` entry.
1782
+ - 4a01a87: Use the shared strict frontmatter decoder for skill, command, bundle plugin, and agent discovery. Reject malformed authority metadata with source diagnostics, preserve plugin invocation restrictions, and reject invalid agent limits before registration.
1783
+
1784
+ Remove the permissive public `parseFrontmatter` export as a breaking API change. Discovery sources now own validation; no compatibility parser is retained. The test-session harness accepts explicit project authority for trusted contribution fixtures.
1785
+
1786
+ - 242a644: Require versioned, event-decoded session replay logs. Reject unknown, malformed, and unsupported
1787
+ entries instead of dropping them or inventing message fields. Replay-only session loads and lists
1788
+ report damaged logs explicitly. Legacy unversioned JSONL is not accepted; snapshot encoding remains
1789
+ unchanged. Persisted logs now use schema version 1, and all replay entry points share the session-owned
1790
+ decoder and preserve sidecar integrity failures.
1791
+
1792
+ ### Minor Changes
1793
+
1794
+ - d4189b9: The rest of the per-server MCP OAuth lifecycle: signing in to a server without a local browser,
1795
+ signing out of it with token revocation, and each server's sign-in state in `/mcp`.
1796
+
1797
+ - **`robota mcp login <name> --no-browser`** prints the authorization URL and reads the redirect URL
1798
+ the user pastes back (not echoed). `runMCPOAuthLogin` takes `readRedirect` for this; nothing
1799
+ listens on the redirect URI then. The pasted URL is held to the loopback listener's rules through
1800
+ `createPastedRedirectAcceptor`: it must be the registered redirect URI (same origin and path, no
1801
+ user info), carry the sign-in's `state` (compared in constant time), and is accepted once; an
1802
+ error redirect is `authorization-denied` without its `error_description`, and the RFC 9207 `iss`
1803
+ check applies as before. `openBrowser` now also receives the redirect URI. `readRedirect` gets a
1804
+ signal that aborts on cancel or at `callbackTimeoutMs` (5 minutes by default, as for the loopback
1805
+ listener); a paste longer than the prompt accepts fails as `redirect-too-long`.
1806
+ - **Signing out** (`runMCPOAuthLogout`; `robota mcp logout <name>`; `/mcp logout <serverId>`):
1807
+ deletes the stored credential under the refresh lock, then revokes the refresh token and the
1808
+ access token (RFC 7009) when the stored issuer advertises `revocation_endpoint`. Revocation is a
1809
+ POST through the egress policy that never follows a redirect and is byte-bounded; it authenticates
1810
+ the client by `revocation_endpoint_auth_methods_supported` when advertised, otherwise the way its
1811
+ refresh does. The local delete always happens. Each token's outcome is reported in `tokens`, and
1812
+ overall as `revoked`, `partial`, `unsupported`, `failed` or `not-attempted`, with fixed reasons
1813
+ only (new: `revocation-failed`, and `token-type-not-revocable` for RFC 7009
1814
+ `unsupported_token_type`). `/mcp logout` also makes the session's authenticator drop the token it
1815
+ holds (`IMCPOAuthAuthenticator.forget`).
1816
+ - **Sign-in state:** `readMCPOAuthCredentialState` answers `signed-in`, `expired-refreshable`,
1817
+ `sign-in-required` or `signed-out` — never anything token-derived. `/mcp` shows it for every
1818
+ OAuth server; a server this session was told needs a sign-in reads `sign-in-required`.
1819
+ `ICommandMCPActivationAdapter` gains optional `oauthStatus` and `oauthLogout`
1820
+ (`ICommandMCPOAuthStatus`, `ICommandMCPOAuthLogoutResult`).
1821
+ - **No in-session sign-in:** signing in stays `robota mcp login <server>` in a terminal, since it
1822
+ needs the terminal (browser, pasted redirect, hidden secret prompt) a running session owns. `/mcp`
1823
+ names that command for a server that needs a sign-in, as does the session's sign-in notice; the
1824
+ server name is shown there only when it is safe to paste into any shell — a plain token not
1825
+ starting with `-` or `=` — and is otherwise replaced by `<server>` (`shellArgumentForDisplay` in
1826
+ `agent-core`; nothing is quoted, since quoting rules differ between shells). Server names in OAuth
1827
+ notices have control and format characters escaped.
1828
+ - **Refresh hardening:** on `invalid_grant`, the store is read again under the lock; a refresh token
1829
+ another holder rotated in meanwhile is kept (and used when still valid) instead of being deleted.
1830
+ The expiry skew is capped at half the token's lifetime, so a short-lived token is not refreshed on
1831
+ every request; credentials now record `issuedAt` for this.
1832
+
1833
+ - 4078a72: Model fallback chain. `--fallback-model a,b` (or the `fallbackModel` settings array; the flag wins) names up to three models a turn moves to when its model is overloaded, unavailable or failing on the server. An entry is a provider profile, `profile:model`, a bare model on the primary's provider, or `default`. The move happens only before any output has streamed, lasts for the current turn, and is shown as a system note; entries that cannot be built are passed over and entries outside the organization's `allowedProviders` are dropped with a notice. `FallbackProvider` in agent-framework implements it over the session's provider; `IChatOptions` gains `executionId`, `onModelFallback` and `preserveContextWindow`, `IAIProvider` gains optional `resolveModelRoute`, and the execution loop emits a `provider_fallback` event and attributes requests, call observations, committed replies, the response cache and usage to the model that answered. A turn that ran on more than one model records per-model `modelShares` on its usage observation, which personal usage reports split by model and provider. A `/provider` switch keeps the chain, read again for the new primary.
1834
+ - af2f2ad: `/cd <directory>` continues the conversation in another directory.
1835
+
1836
+ - **A move is a new session in the target directory.** In the TUI, Robota saves a copy of the
1837
+ conversation where the target's session store will find it, ends the current run through its
1838
+ normal end-of-life flow, and starts again in the target directory resuming that copy. The target's
1839
+ settings, trust decision, tools, skills and `AGENTS.md` apply, exactly as if Robota had been
1840
+ launched there. The process boundary makes the move atomic, so no tool call can straddle it.
1841
+ - **The system prompt is kept as recorded**, so a provider's prompt cache survives. One appended
1842
+ `<workspace-move>` message tells the model the new directory, and which project instructions now
1843
+ apply.
1844
+ - **Refused** while a turn is running or a background task is still running, for a missing directory
1845
+ or the current one, and for a target a `Cd(...)` deny rule names.
1846
+ - **Access never widens:** a restricted session stays restricted after a move, and a trusted session
1847
+ takes the target's own trust decision.
1848
+ - New contracts: the `workspace-move` host action, `ICommandWorkspaceAdapter` /
1849
+ `IWorkspaceMoveRequest`, `InteractiveSession.moveWorkspace`, and the `workspaceMovedFrom` session
1850
+ option. The CLI's `--moved-from` and `--restricted-workspace` flags are internal.
1851
+
1852
+ - 34e50f0: A new permission mode, `auto`, lets a model classifier approve or block what would otherwise prompt.
1853
+
1854
+ - **What it decides:**
1855
+ - Reads and in-workspace edits run as in `acceptEdits`.
1856
+ - Commands and other calls the mode leaves open go to the classifier, a side call to the
1857
+ session's own model. It sees the call, the working directory and the git remotes, never the
1858
+ conversation.
1859
+ - A block reaches the model with its reason, so it can take another route.
1860
+ - **What still reaches a person, or is refused:**
1861
+ - Deny rules and background ceilings apply first.
1862
+ - `ask` rules, critical removals and protected paths ask a person.
1863
+ - After 3 refusals in a row (blocks, or no usable verdict), or 20 blocks in the session, the
1864
+ mode asks a person until one approves.
1865
+ With no one to ask, the call is denied.
1866
+ - **Allow rules:** in `auto` mode, allow rules that approve any command are set aside while the
1867
+ mode is on. Examples are `Bash(*)`, an interpreter (`Bash(python *)`), a package runner
1868
+ (`Bash(npm run *)`, `Bash(pnpm exec *)`), `Agent`, `ExecuteCommand` or `Computer`. Narrow
1869
+ rules still apply.
1870
+ - **Retry:** `/permissions` lists classifier blocks. `/permissions retry <n>` lets that exact call
1871
+ run once, unjudged, when the model tries it again.
1872
+ - **Turning it on and off:**
1873
+ - `--permission-mode auto`, `/mode auto` or `/permissions auto`.
1874
+ - An organization turns it off with `disableAutoMode` in the org policy.
1875
+ - **New contracts:**
1876
+ - `TPermissionMode` gains `'auto'`.
1877
+ - `allowRulesForAutoMode` and `isBroadExecutionAllowRule`.
1878
+ - `IPermissionClassifier` and `AutoModeGate`.
1879
+ - The `permissionClassifier` session option.
1880
+ - `Session.retryPermissionDenial`, and `retryDenial` on the permission-mode adapter.
1881
+ - The `'classifier'` denial reason.
1882
+ - `createModelPermissionClassifier`.
1883
+ - The `disableAutoMode` option on `createSession` and `IOrgPolicy`.
1884
+
1885
+ - 722e88a: Shell commands can run in an OS-level sandbox: bubblewrap on Linux and WSL2, Seatbelt on macOS.
1886
+
1887
+ - **Confinement:** covers the command and every process it starts.
1888
+ - Writes are limited to the working directory, the temporary directories and
1889
+ `sandbox.filesystem.allowWrite`.
1890
+ - Agent, git-hook, MCP and shell configuration inside the workspace stays read-only.
1891
+ - `sandbox.filesystem.denyRead` hides paths from the command.
1892
+ - The network is on or off (`sandbox.network.enabled`).
1893
+ - **Modes:** `/sandbox` switches between `auto-allow`, `regular` and `off` for the next command and
1894
+ saves the choice.
1895
+ - In `auto-allow` (`sandbox.autoAllowBashIfSandboxed`), a confined command runs without a prompt
1896
+ in `default` and `acceptEdits`.
1897
+ - Deny rules, ask rules, critical removals and plan mode still apply first.
1898
+ - **Exclusions:** `sandbox.excludedCommands` run unconfined, through the ordinary permission path.
1899
+ - **When the sandbox cannot run:** a missing or unusable backend is reported at startup, in
1900
+ `robota doctor` and in `/sandbox`, and commands then run unconfined.
1901
+ `sandbox.failIfUnavailable` refuses to start instead.
1902
+ - **New contracts:**
1903
+ - `OsSandboxClient`, `detectOsSandbox`, `bubblewrapArguments`, `seatbeltProfile`.
1904
+ - `ISandboxClient.wrapCommand` and `autoApproves`.
1905
+ - `IPermissionEvaluationContext.sandboxAutoApproved`.
1906
+ - The `commandSandbox` session option.
1907
+ - The `sandbox` settings key and the `sandbox` command host adapter.
1908
+
1909
+ - a5cc36e: `/permissions` shows the rules the session enforces and the calls it refused.
1910
+
1911
+ - **Rules by source:** each allow, deny and ask rule the gate reads is listed under the settings file
1912
+ that declares it. Rules added by a CLI flag, a preset or a command are listed under "this session".
1913
+ A rule a settings file declares but the session does not enforce is not shown.
1914
+ - **Recent denials:** the latest refused calls, most recent first, with the reason: a rule or the
1915
+ mode, the user declining, or no one available to approve.
1916
+ - New contracts: `Session.getRecentPermissionDenials()`, `PermissionEnforcer.getRecentDenials()`,
1917
+ `IPermissionDenial`, the `permissionRules` host adapter (`createSettingsPermissionRulesAdapter`),
1918
+ and `getPermissionRules` / `listRecentDenials` on `ICommandPermissionModeAdapter`. Settings
1919
+ provenance now covers `permissions.ask`.
1920
+
1921
+ - b70fa3d: `robota --safe-mode` starts a session with every customization off, to rule one out in one run.
1922
+
1923
+ - **Off:** project and user instruction files, skills, custom commands, agent definitions, output
1924
+ styles, external presets, plugins, hooks from every settings layer, and MCP servers.
1925
+ - **Unchanged:** provider, model, built-in tools and permissions work as usual. Nothing on disk
1926
+ changes.
1927
+ - **Project access:** the project starts Restricted whatever its trust decision, so safe mode also
1928
+ runs in print and serve mode.
1929
+ - **Notice:** a line at startup says that safe mode is on.
1930
+ - **Embedders:** `startCli({ safeMode: true })` does the same as the flag.
1931
+ - **New framework option:** `skipConfiguredHooks` on interactive and headless sessions, also
1932
+ carried by the TUI and serve session options.
1933
+
1934
+ - 2711ec6: One broken skill or agent file no longer stops the session.
1935
+
1936
+ Skill, command and agent definitions are shared with other hosts through `.claude`, and those hosts
1937
+ define fields of their own. The frontmatter decoder now validates only the fields Robota owns and
1938
+ ignores the rest (nested `metadata` entries included); a malformed value of an owned field is still
1939
+ refused. A refused file is skipped with a single warning and still claims its name, so a
1940
+ lower-priority definition cannot stand in for it. An empty `argument-hint` reads as no hint. When
1941
+ initialization does fail, the session reports the cause to readiness probes instead of "not
1942
+ initialized", so the terminal shows the reason at once rather than a 15-second timeout.
1943
+
1944
+ The terminal also stops printing type names for message-less telemetry records, keeps its own notices
1945
+ in place across a history sync so the following answer is not skipped, and CLI diagnostics print
1946
+ their context instead of `[object Object]`, through the console so Ink renders them above the frame.
1947
+
1948
+ - 4dd45cc: `/peers` shows how each other local session's workspace relates to this one's: `same worktree`,
1949
+ `same repo`, `different repo`, or `workspace unknown`.
1950
+
1951
+ A session now publishes a workspace claim with its rendezvous entry — the root commits reachable
1952
+ from HEAD, a SHA-256 of its normalized `origin` URL (never the URL itself), and the real path of its
1953
+ worktree — and re-reads it as it runs, so a first commit or a checkout does not leave it stale. The
1954
+ reader does not take the claim as written: it reads git at the claimed path itself, and a claim whose
1955
+ contents disagree is shown as `workspace claim mismatched, not believed` and relates to nothing. Those
1956
+ git reads are local-only and asynchronous, run only for the view that shows the relation (and for
1957
+ the sender of an incoming peer message), and are cached per announcement. The relation also reaches
1958
+ the peer-turn origin, computed by the receiver; a relation the sender put on the wire is discarded,
1959
+ and the admission never carries it.
1960
+
1961
+ The relation is display and routing information only and is never an authorization input.
1962
+
1963
+ Additive: `agent-interface-session-mobility` exports `TWorkspaceRelation` and gains the optional
1964
+ `IPeerOrigin.workspaceRelation`; `agent-framework`'s `ILocalPeerSummary` gains the optional
1965
+ `workspaceRelation` and `workspaceClaim`, and `ICommandLocalPeersAdapter` the optional
1966
+ `listWithWorkspace()`.
1967
+
1968
+ - 4c5148e: ARCH-005 Stage S2 — `robota` is now expressed as an `IProductProfile` and assembled by `assembleProduct`;
1969
+ the hand-wired composition root in `agent-cli` is gone.
1970
+
1971
+ - **`@robota-sdk/agent-product`** — provider construction returns IN-KERNEL. `assembleProduct` builds the
1972
+ provider from `providerDefinitions` + the shell's already-resolved `providerSettings` via agent-core's
1973
+ pure `createProviderFromConfig`; `provider` is now an OPTIONAL injected override. Both are optional, so a
1974
+ Mode A profile can carry only `providerDefinitions`. The fold stays pure and IO-free — every
1975
+ settings/env/file read still happens in the shell. Adds `IAssembledProduct.buildRuntimeOptions`, the pure
1976
+ overlay `buildRuntime` delegates through, and `IAssembledProduct.providerDefinitions`.
1977
+ **Breaking for pre-release consumers:** `IProductProfile.providerDefinitions` is now required and
1978
+ `IProductProfile.provider` / `IAssembledProduct.provider` are now optional.
1979
+ - **`@robota-sdk/agent-framework`** — a scoped, additive session seam: `agentDefinitions` on
1980
+ `TInteractiveSessionOptions` / `ICreateSessionOptions`, composed into the built-in agent tier ahead of
1981
+ `BUILT_IN_AGENTS`, so capability-pack subagents actually reach the runtime. Precedence: discovered
1982
+ project/user definitions > injected > built-in. `AgentDefinitionLoader` now dedupes within that tier
1983
+ (first wins). Absent ⇒ unchanged behavior.
1984
+ - **`@robota-sdk/agent-transport` / `@robota-sdk/agent-transport-tui`** — forward the optional
1985
+ `agentDefinitions` through the headless and TUI channels so every Robota surface carries the seam.
1986
+ - **`@robota-sdk/agent-cli`** — `robota`'s identity (branding, provider surface, presets,
1987
+ `packs: [codingPack]`, base command modules, injected transports/runners/subagent factory) is declared as
1988
+ data in a product profile and folded by `assembleProduct`. The coding command modules (`/shell`,
1989
+ `/editor`) now come from `pack-coding` rather than the base set, so the pack is load-bearing. What remains
1990
+ in the CLI is product-shell only: arg parsing, settings/file IO, terminal notices, first-run/init/
1991
+ `--configure`, memory + session-resume UX, and print/serve/TUI mode dispatch.
1992
+
1993
+ End-user `robota` behavior is unchanged in substance — the assembled command-module set, provider surface,
1994
+ tool set, subagent roster, and preset resolution all match the pre-change assembly — with one accepted
1995
+ cosmetic delta: `/shell` and `/editor` now appear at the END of `/help` output and of the slash-command
1996
+ autocomplete popup rather than mid-list, because they arrive from `pack-coding` and both surfaces render in
1997
+ module-insertion order. Same commands, same behavior, different position.
1998
+
1999
+ - 37af5dc: ARCH-006 + ARCH-007 — the capability-pack TOOL axis reaches parity with the command and subagent axes,
2000
+ and `robota` consumes the composition kernel's RUNTIME SEAM instead of only its materials.
2001
+
2002
+ - **`@robota-sdk/agent-framework` (ARCH-006)** — the default tool set is no longer hard-coded.
2003
+ `createSession` accepts `defaultTools`, which REPLACES the `createDefaultTools()` tier (`[]` suppresses
2004
+ it entirely) — the tool-axis mirror of NEUT-003's `builtInAgents` seam for subagents. The assembled
2005
+ list `defaultTools ⊕ additionalTools ⊕ goalTool` is now **deduplicated by tool name, first occurrence
2006
+ wins**, the same rule `AgentDefinitionLoader` applies within the subagent built-in tier. So a
2007
+ contributed tool with a NEW name is additive, a contributed tool that mirrors a framework default is
2008
+ deduped rather than listed twice, and a product can hand its whole tool surface to its capability
2009
+ packs. A name collision keeps the framework default and drops the contribution: the default tier is
2010
+ built WITH the session context (`cwd` supplies `agent-tools`' working-directory path guard, plus the
2011
+ sandbox client and retrieval adapter) and an already-constructed contribution carries none of it, so
2012
+ replacement is expressible only through the explicit `defaultTools` seam — never as a side effect of a
2013
+ collision. The edit-checkpoint wrap now covers the assembled set, so a pack-contributed `Write`/`Edit`
2014
+ is checkpointed too. Option threaded through `ICreateSessionOptions` / `IInitOptions` /
2015
+ `IInteractiveSessionStandardOptions`. Absent `defaultTools` and absent a duplicate name, every existing
2016
+ path is byte-identical.
2017
+ - **`@robota-sdk/agent-product` (ARCH-007)** — `buildRuntimeOptions` no longer overwrites a
2018
+ caller-supplied `commandModules`. A shell that has already narrowed the merged `base ⊕ packs` superset
2019
+ (as `robota` does with its preset's enabled/disabled delta) keeps that selection; the assembled set is
2020
+ overlaid only when the caller left it unset — the same rule `permissionMode` already followed.
2021
+ - **`@robota-sdk/agent-cli` (ARCH-007)** — `startCli` now routes through
2022
+ `product.buildRuntimeOptions(...)`. The shell resolves its own session inputs and the kernel lays the
2023
+ product-owned materials on top: the packs' tools (`additionalTools`), the packs' subagents
2024
+ (`agentDefinitions`), and the default preset's permission posture when `--permission-mode` left it
2025
+ unset. The hand-threaded `product.subagents` path and the three per-surface
2026
+ `args.permissionMode ?? resolvedPreset.permissionMode` expressions are gone — every surface binds to
2027
+ the one kernel result.
2028
+
2029
+ End-user `robota` behavior is unchanged: the assembled command-module set, provider surface, tool set,
2030
+ subagent roster, preset resolution, and permission posture all match the pre-change assembly.
2031
+
2032
+ - 2ebff01: Emit the complete persisted checkpoint and branch lifecycle, forward plan, context-refresh, and
2033
+ branch events through protocol transports, and render deterministic bounded notices in the TUI.
2034
+ Transport-owned delivery failures now enter the owning carrier cleanup lifecycle without reversing
2035
+ an already-committed session operation.
2036
+ - b078afa: Forward the runtime-owned session store into headless sessions by default while preserving explicit
2037
+ per-session override and disable semantics.
2038
+ - 0f98419: ARCH-037 — published-contract hygiene.
2039
+
2040
+ **Breaking for anyone importing these from `@robota-sdk/agent-interface-transport`** — hence `major`,
2041
+ matching ARCH-031's precedent for a barrel that loses names (a `minor` would file the removal under
2042
+ "Minor Changes" and a beta consumer scanning for breaking changes would meet it as a `TS2305` after
2043
+ upgrading instead). The package is
2044
+ pre-release and the repo keeps no compatibility shims, so the names are removed rather than deprecated;
2045
+ both are re-exports of types `@robota-sdk/agent-core` owns and still exports under the same names.
2046
+
2047
+ - `IActionRequest` — import from `@robota-sdk/agent-core`.
2048
+ - `TBackgroundPermissionPolicy` — import from `@robota-sdk/agent-core`.
2049
+
2050
+ `TActionResponse` deliberately STAYS. It is the one path by which `agent-transport-gui` and
2051
+ `agent-transport-protocol` can name the type: neither may depend on `agent-core`, and `agent-core` is
2052
+ the bottom layer, so the type cannot move down either. It is now a named exception carrying that
2053
+ reasoning in the source.
2054
+
2055
+ **Added** to `@robota-sdk/agent-framework`: `ICreateDefaultToolsOptions`. `createDefaultTools` was
2056
+ exported without it, so a consumer could call the function but could not name what it must pass —
2057
+ they had to reverse-engineer the shape or cast into it. A new `barrel-parameter-types` harness floor
2058
+ now fails on that shape rather than leaving it to review.
2059
+
2060
+ `@robota-sdk/agent-executor` is a patch only: it now sources `TBackgroundPermissionPolicy` from
2061
+ `@robota-sdk/agent-core` (which it already depends on) instead of through the interface package. Its
2062
+ own published surface is unchanged.
2063
+
2064
+ - d312755: Provider DIP Stage D (ARCH-PROVIDER-005): invert the skill node's dependency on the
2065
+ agent-framework assembly. New `ISkillExecutionPort` contract in
2066
+ `@robota-sdk/agent-interface-transport`; `@robota-sdk/agent-framework` exports
2067
+ `createSkillExecutionPort()`; `@robota-sdk/dag-node-skill` now requires an injected
2068
+ `skillPort` (via `ISkillNodeDefinitionOptions.skillPort`) and no longer depends on
2069
+ `agent-framework`. The concrete port is injected at the `dag-nodes-default` composition
2070
+ root. Closes ARL-11 (skill-half).
2071
+
2072
+ BREAKING (@robota-sdk/dag-node-skill): `SkillNodeDefinition`/`SkillResolverRuntime` now
2073
+ require an injected `skillPort`; the no-arg `createSkillNodeDefinition()` factory is removed.
2074
+
2075
+ - 1e3f91a: CMD-004 Phase 2 Stage E (breaking, beta line): the legacy `TCommandEffect` union and
2076
+ `ICommandResult.effects` are DELETED. Commands emit the split contract directly —
2077
+ `hostActions` (session-executed via `ICommandHostAdapters`; works headless and remote) and
2078
+ `uiIntents` (requester-routed `ui_intent` session events with UI-neutral `show-*` names).
2079
+ Final carriers for the former notification effects: `session_renamed` and the new
2080
+ `history_cleared` are BROADCAST session events (forwarded to every WS surface, folded by the
2081
+ TUI transcript/title and the GUI reducer's new `sessionName`/transcript-reset state);
2082
+ `session-execution-started` rides `result.data.sessionExecution`; the plugin-registry refresh
2083
+ rides `result.data.pluginRegistryReloaded`. A mechanical grep floor
2084
+ (`command-effect-grep-floor.test.ts`) keeps `tui-requested`/`TCommandEffect`/`effects:` out of
2085
+ every `packages/*/src` production tree.
2086
+ - 4b76cfa: NEUT-005 (wave 2): restore an actionable context-capacity hint at the surface tier, neutrally. The zero-dependency `agent-core` layer emits a product-neutral hard-capacity notice and exposes the `IAgentConfig.contextCapacityHint` seam (wave 1). This wave wires that seam end-to-end without baking product vocabulary into a neutral library:
2087
+
2088
+ - `agent-session`: `ISessionOptions.contextCapacityHint` is forwarded into the agent configuration factory, making the core seam reachable from the consuming layer.
2089
+ - `agent-framework`: new `deriveContextCapacityHint(commandModules)` derives the concrete remediation wording from the surface's OWN registered command set (names a registered `compact` command → `"Run /compact and retry."`; `undefined` when none, leaving the neutral core default). It is applied automatically in interactive session assembly across the TUI, print, and `--serve` surfaces.
2090
+ - `agent-cli`: the default command set registers `/compact`, so end users regain the actionable hint.
2091
+ - `agent-interface-transport`: reworded the `'allow-project'` permission comment so it no longer hardcodes a storage path (the location is owned by the consuming layer), matching the `agent-session` twin.
2092
+
2093
+ - d9bd9ec: Framework neutrality batch (NEUT-001/003/004/007): `planSelfHostingVerification` now requires injected
2094
+ command templates (repo-process literals evicted from the library); built-in agent set, subagent prompt
2095
+ suffix, and self-verification content are injectable; `claudeMd` renamed to `projectNotesMd` (breaking,
2096
+ beta line); `.agents/tasks` context injection is now opt-in via `taskContext` settings and the unused
2097
+ `updateTaskFileStatus` write API was removed; memory candidate-extractor trigger/vocabulary policy is
2098
+ constructor-injectable with the previous bilingual/dev set as the documented default; session-name
2099
+ sanitizer is Unicode-aware (non-Latin titles preserved).
2100
+ - 90e7a10: The default background observer warning code and exported `OBSERVER_FAILURE_WARNING_CODE` value
2101
+ change from `PRODUCT_BACKGROUND_OBSERVER_FAILURE` to `BACKGROUND_OBSERVER_FAILURE`. Hosts matching
2102
+ the old warning code should match the new neutral code or provide `observerFailureWarningCode` in
2103
+ their background manager or session options. The Robota CLI supplies its existing code explicitly
2104
+ across print, goal, serve, MCP, and TUI sessions.
2105
+ - fcb0da3: PAYLOAD-2153: make external-payload replay stable across Linux, macOS, and Windows.
2106
+
2107
+ - Add the domain-free `@robota-sdk/agent-file-authority` leaf with bounded, root-relative reads over retained native handles and a typed, path-safe refusal taxonomy.
2108
+ - Route session replay and framework project reads through the shared authority while preserving their existing domain-specific budgets, integrity checks, and error mappings.
2109
+ - Expose the canonical safe session-id predicate through the framework facade so CLI exact-session lookup stays within the SDK package boundary.
2110
+ - Package the pinned native bridge in clean-installed Node CLI archives and exact-host standalone Bun binaries, refusing unsupported or mismatched targets before artifact mutation.
2111
+
2112
+ - 9665c6e: Make the permission and "ask the user" flows transport-neutral (REMOTE-007 / B4-2a). A session now
2113
+ emits `permission_request` / `ask_request` / `prompt_resolved` events and exposes
2114
+ `resolvePermission` / `resolveAsk`, so any attached surface — local TUI, a WS/WebRTC driver, or a web
2115
+ UI — can render and answer the SAME prompt (local == remote). The framework builds event-emitting
2116
+ default handlers bound to the session emitter (id-keyed parking, fail-closed on zero listeners / on
2117
+ detach / backstop, teardown drain on abort/cancelQueue/shutdown), replacing the injected
2118
+ askHandler/permissionHandler at their source. `getUserInteraction()` is gated on the `ask_request`
2119
+ listener count so the headless "no-human ⇒ proceed" contract is preserved. The WS protocol carries the
2120
+ new events + `permission-response` / `ask-response` verbs, and WebRTC gets them for free via the shared
2121
+ handler. No `/remote-control` enable path is added.
2122
+ - 44393be: Add the `/remote-control` enable path (REMOTE-008 Stage B4-2b) — turn on P2P remote control locally, get
2123
+ a QR + link, and a paired device co-drives the SAME live session over pairing-gated WebRTC. The command
2124
+ is a declarative trigger returning `remote-control-enable-requested`/`-stop-requested` effects (SSOT
2125
+ agent-interface-transport) and reads state via a new `ICommandHostAdapters.remoteControl.getStatus()`;
2126
+ the TUI dispatches the effects to injected callbacks; all transport construction lives at the agent-cli
2127
+ composition root (`WsSignalingClient` + pairing-gated `WebRtcTransport`, relay URL from
2128
+ `transports.webrtc.options.relayUrl`, QR/link rendered into history). Fail-closed: no relay configured ⇒
2129
+ does nothing; pairing mismatch/timeout ⇒ the session is never exposed. Consumes REMOTE-007 so a paired
2130
+ remote owner answers their own permission/ask prompts over the WebRTC channel.
2131
+ - c7fa299: REMOTE-003 + REMOTE-006 (merged — net behavior; the interim deny-by-default gate never appeared in a
2132
+ published version): commands now carry an invocation source. A `'remote'` value is added to the command
2133
+ invocation source (SSOT relocated to `@robota-sdk/agent-interface-transport`, re-exported by
2134
+ `agent-framework`) and an optional `source` is threaded into
2135
+ `IInteractiveSession.executeCommand(name, args, source?)` (defaults to `'user'`, so all local callers are
2136
+ unchanged). The shared `createWsHandler` tags transport-origin commands `'remote'`. Policy: local == remote
2137
+ (owner principle) — pairing is the sole trust boundary, so a transport-origin command runs exactly as a
2138
+ locally-typed one under the universal permission system (permission modes + PermissionEnforcer + the
2139
+ ask/approval handler); `createDefaultRemoteCommandPolicy()` allows by default. The `IRemoteCommandPolicy`
2140
+ seam remains as an OPTIONAL, user-configured restriction, and the genuinely-remote WebRTC path stays
2141
+ pairing-gated.
2142
+ - fde558e: Forward organization policy through TUI, print, and goal sessions so blocked commands are enforced consistently. Preserve print/goal preset generation, language, prompt-seed, and structured-response options through the headless channel, and guard declared session-capability projections against silent field loss.
2143
+ - 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 }`.
2144
+
2145
+ ### Patch Changes
2146
+
2147
+ - 5307f8a: Discriminate `IBackgroundTaskResult` by kind, the same way `TBackgroundTaskRequest` already is:
2148
+ `exitCode`/`signalCode` exist only on the `process` member and `usage` only on the `agent` member,
2149
+ instead of being optional-and-unreachable on every kind. `IBackgroundTaskResult<K>` narrows to the
2150
+ kind-specific member; called with no type argument it is still the full union, which is what
2151
+ `IBackgroundTaskState.result` continues to hold (that field stays undiscriminated — a later change).
2152
+ `ISubagentJobResult` is now derived as `Omit<IBackgroundTaskResult<'agent'>, 'kind'>` rather than a
2153
+ hand-maintained `Omit<IBackgroundTaskResult, 'kind' | 'exitCode' | 'signalCode'>`.
2154
+
2155
+ `IBackgroundTaskHandle` gains the same kind parameter as `IBackgroundTaskStart`: a runner declared
2156
+ for kind `K` resolves its handle's `result` to `IBackgroundTaskResult<K>`, so a caller that starts a
2157
+ known-kind runner gets a correctly-narrowed result with no cast, and reading a cross-kind field on it
2158
+ is a compile error. Consumers reading `state.result` through the generic (kind-erased) manager or
2159
+ task-state path are unaffected in behavior, but a `.exitCode`/`.signalCode`/`.usage` read there must
2160
+ now narrow on the result's own `kind` first, since the fallback default keeps `IBackgroundTaskResult`
2161
+ as the full union rather than the previously flat, always-present shape.
2162
+
2163
+ `agent-session`'s session-record decoder now rejects a persisted result carrying a field outside its
2164
+ own kind (e.g. an `'agent'` result with `exitCode`) as corrupt, reported at that field's own path —
2165
+ the same corruption-reporting style the taskId/kind identity check already uses.
2166
+
2167
+ **Breaking for `@robota-sdk/agent-interface-execution` and `@robota-sdk/agent-executor`**: code that
2168
+ read `exitCode`/`signalCode`/`usage` off an unnarrowed `IBackgroundTaskResult`, or that implemented
2169
+ `IBackgroundTaskHandle`/a custom runner without specifying its kind parameter, needs to narrow on
2170
+ `result.kind` (or specify the kind parameter) before those fields are visible again.
2171
+
2172
+ - b462ee7: Discriminate `IBackgroundTaskState` by kind, the same way `TBackgroundTaskRequest` and (as of the
2173
+ prior change) `TBackgroundTaskResult` already are. Fields only one runner ever produces now live
2174
+ only on that kind's member instead of being optional-and-cross-kind-reachable on every kind:
2175
+
2176
+ - `agent`-only: `agentType`, `isolation`, `resumeSessionId`, `promptPreview`, and the
2177
+ worktree-isolation fields (`worktreePath`, `branchName`, `worktreeStatus`, `worktreeNextAction`,
2178
+ `worktreeBaseRevision`, `parentWorktreeStatus`).
2179
+ - `scheduled`-only: `schedule`, `nextFireAt`.
2180
+ - Every kind except `agent`: `commandPreview` (a process command, an MCP tool-invocation summary, or
2181
+ a schedule's shell command / wake instruction).
2182
+ - `state.result` is now `IBackgroundTaskResult<K>` — correlated with `state.kind`, not the free
2183
+ full-result union.
2184
+
2185
+ `pid`, `logPath`, and `transcriptPath` stay on the shared base rather than becoming agent- or
2186
+ process-exclusive: the runner handle SPI already reports them for whichever runner's process
2187
+ happens to produce them, and a subagent run via the worktree/child-process runner carries a `pid`
2188
+ exactly as a `process`-kind task does. `timeoutReason` also stays base — session restore sets
2189
+ `'stale_worker'` on any non-terminal, non-rearmable task regardless of kind, not only agent ones.
2190
+
2191
+ `IBackgroundTaskState<K>` narrows to the kind-specific member; called with no type argument it is
2192
+ still the full union. The session-record decoder (`agent-session`) now rejects a persisted task
2193
+ state carrying a field outside its own kind as corrupt, reported at that field's own path, the same
2194
+ way it already rejects a `state.result` whose kind disagrees with `state.kind`.
2195
+
2196
+ **Breaking for `@robota-sdk/agent-interface-execution` and `@robota-sdk/agent-executor`**: code that
2197
+ read a kind-specific field (e.g. `state.agentType`, `state.schedule`, `state.commandPreview`) off an
2198
+ unnarrowed `IBackgroundTaskState` needs to narrow on `state.kind` first, since the fallback default
2199
+ no longer carries every field on every kind. `agent-session`, `agent-framework`, and `agent-command`
2200
+ land the corresponding narrowing at every read site the type change touched; no runtime behavior
2201
+ changes there beyond the state decoder's new corruption checks.
2202
+
2203
+ - 08a9bd6: The CLI update-check cache is now written owner-only (`0600`) into an owner-only directory (`0700`), instead of inheriting the process umask.
2204
+
2205
+ SEC-020 made every writer into the CLI's own store owner-only and scoped this one file out as "not a session record", which left it the only file the product created there at `0644` under a permissive umask. The store directory is the confidentiality boundary and the file modes are the layer beneath it — an exception in that layer is only invisible while the layer above it holds.
2206
+
2207
+ The write now goes through `writeOwnerOnlyFile`, which creates the parent owner-only and sets the mode at creation rather than tightening afterwards, so the file never exists readable. A cache an older version left at `0644` is repaired at its next write.
2208
+
2209
+ `getUserUpdateCheckCachePath`, `readUpdateCheckCache`, `writeUpdateCheckCache` and `IUpdateCheckCache` moved to an internal `update-check-cache` module. **They are exported from the package root under the same names, so no import changes.**
2210
+
2211
+ - 267af5f: The execution containment seam states where tools run.
2212
+
2213
+ - **`ISandboxClient.filesystem`** (`'shared' | 'separate'`, absent means `separate`).
2214
+ - With a **separate** filesystem (E2B, in-memory), every file tool goes through the sandbox, and
2215
+ `Glob`/`Grep`, which can only read the host, are withheld. Previously a remote sandbox still
2216
+ offered host-reading search tools beside sandbox-writing edit tools.
2217
+ - With a **shared** filesystem (OS-level confinement over the host's files), file tools stay on
2218
+ the host under the path guard, and only commands go through the sandbox.
2219
+ - **`describeExecutionContainment` / `routesFilesThroughSandbox`** name the containment (`host`,
2220
+ `sandbox-shared`, `sandbox-separate`) instead of inferring it from an absent value.
2221
+ - **`robota doctor` reports `execution.containment`.** Robota composes no sandbox today, so the
2222
+ doctor says shell commands run unconfined on the host and the permission rules are the only
2223
+ boundary. The CLI composition and the doctor read the same value.
2224
+ - **The `Agent` and `BackgroundProcess` tools no longer fall back to `process.cwd()`** when they
2225
+ were built without an execution root. They report an assembly error instead, as the file tools
2226
+ already did (ARCH-010).
2227
+
2228
+ - baa6863: **ARCH-025: `SubagentManager.wait()` carries `usage`, and `IScheduleEditPatch` becomes nameable.**
2229
+
2230
+ Two declared contract fields were unreachable by the projections meant to carry them.
2231
+
2232
+ `wait()` returned `{ jobId, output, metadata }` and dropped `usage`, though `ISubagentJobResult.usage` is
2233
+ declared (ANALYTICS-001) and populated end to end. The field was born dropped: the commit that added
2234
+ `usage` to `toBackgroundResult` never touched `wait()` two hundred lines above. It now uses the same
2235
+ conditional spread, so the two directions of the hop read identically.
2236
+
2237
+ This is a **contract repair, not a user-visible one** — worth stating because an earlier draft of this work
2238
+ claimed otherwise. `/cost` is fed by the `background_task_completed` event path and already worked;
2239
+ `wait()` feeds `IOrchestrationStepResult.usage`, which nothing currently reads. Forward-provisioned
2240
+ surfaces carry the same quality bar, which is why it is fixed rather than deferred.
2241
+
2242
+ `IScheduleEditPatch` is the parameter type of the public `IBackgroundTaskManager.editScheduledTask` and
2243
+ `IBackgroundTaskHandle.editSchedule`, but it was on neither barrel, so a consumer of those methods could
2244
+ not name its own parameter type. It is now exported (**new export → minor**), and both structural
2245
+ re-declarations in `agent-framework` are gone — `IAgentJobHostContext.editSchedule`, the interface every
2246
+ command module programs against, and the class method implementing it.
2247
+
2248
+ ```ts
2249
+ // before — the caller could not name the type it had to pass
2250
+ editSchedule(
2251
+ taskId: string,
2252
+ patch: { cronExpression?: string; agentInstruction?: string; command?: string },
2253
+ ): Promise<void>;
2254
+
2255
+ // after
2256
+ import type { IScheduleEditPatch } from '@robota-sdk/agent-executor';
2257
+ editSchedule(taskId: string, patch: IScheduleEditPatch): Promise<void>;
2258
+ ```
2259
+
2260
+ Not a surface change for `agent-framework`: TypeScript is structural, so every existing implementer and
2261
+ caller satisfies the named type unchanged.
2262
+
2263
+ **Deliberately not in this change.** `providerProfile` is a dead contract field whose disposition belongs
2264
+ with the seam, and the seam itself — one field family declared three times and carried by hand-written
2265
+ literals nothing checks for totality — is filed as **ARCH-031** (issue #1747) after a `FOUNDATIONAL`
2266
+ finding-depth verdict. ARCH-031's derivation will subsume the `wait()` repair rather than undo it.
2267
+
2268
+ - 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).
2269
+ - bed26ea: Fix: an in-flight autonomous `goal` is no longer lost on session resume. `fromSessionRecord` was a hand-enumerated field whitelist that omitted `goal` (while the write path persisted it), so the goal silently vanished on load. The read path is now a structural mirror of the write path (`{ ...session }`), so every persisted field — including `goal` — round-trips, and a future field cannot be dropped by omission (ARL-08 / DATA-006). `ISessionRecord` gains an opaque `goal?: unknown` for contract honesty.
2270
+ - 07b627f: A local peer can now be answered, and what its turn may do depends on where it runs.
2271
+
2272
+ - `agent-core`: the permission evaluator takes a peer turn's authority as one more input
2273
+ (`IPermissionEvaluationContext.peerTurn`), decided after the deny list and ceiling and before
2274
+ bypass and allow rules. A peer on another host uses no tool. A peer on the same host may use an
2275
+ inspect-class tool that declares `workspacePaths`, only when every named location resolves inside
2276
+ the workspace and is not a credential (`isSecretPath`); write and execute tools are refused unless
2277
+ enabled, and then every use asks. A tool declaring `repliesToPeer` exists only in a peer turn and
2278
+ asks once the turn used another tool. New: `isToolAvailableInPeerTurn`, `TPeerReach`,
2279
+ `IPeerTurnAuthority`. `IRunOptions.withholdHostedTools` leaves a provider's hosted tools out of a
2280
+ run's requests (`nativeWebTools` with `false` withholds a hosted tool for one call).
2281
+ - `agent-tools`: `Read` and `Glob` declare the arguments that say where they look. `Grep` does not:
2282
+ it reads files it was never named, so a peer turn does not get it.
2283
+ - `agent-session`: `ISessionRunOptions.peerReach` makes a run a peer turn for the permission policy;
2284
+ every ask in it needs a fresh approval, and its requests carry no provider-hosted tool. `ISessionOptions.allowPeerChanges` enables write and execute
2285
+ tools for same-host peer turns.
2286
+ - `agent-interface-session`: `ISubmitOptions.peer` (`IPeerTurnContext`) carries a peer turn's reach,
2287
+ the message it answers and the session a reply goes to.
2288
+ - `agent-interface-session-mobility`: `IPeerMessage.inReplyTo` threads a conversation;
2289
+ `peerReachOf(admission)` maps admission to a reach.
2290
+ - `agent-framework`: a peer turn is offered what its origin allows, and a new `peer_reply` tool
2291
+ answers the peer that sent the message, threaded to it. The setting `peers.allowChanges` enables
2292
+ write and execute tools for same-host peer turns.
2293
+ - `agent-ui-terminal`: a permission prompt in a peer turn names the requesting peer.
2294
+ - `agent-cli`: incoming peer turns carry their reach and reply route; a conversation is limited in
2295
+ depth and in how often this session answers it, and a reply over a limit is not sent and the
2296
+ operator is told.
2297
+ - `agent-provider-anthropic`, `agent-provider-openai-compatible` (Qwen): a request whose
2298
+ `nativeWebTools` sets a hosted tool to `false` is sent without it.
2299
+
2300
+ - d0de5b2: A peer session's message now reaches the model as a peer's, and a peer turn runs on the external
2301
+ baseline.
2302
+
2303
+ - `agent-core` marks every user message whose driver id starts with `peer:` as
2304
+ `<peer_message from="…">…</peer_message>` in the outgoing request — both the round and the forced
2305
+ summary — while the stored history keeps the text as sent. Wrapper-shaped text in user and tool
2306
+ messages is escaped, and an id that is not a plain identifier is printed as `peer:unverified`.
2307
+ New exports: `peerDriverOf`, `printablePeerDriver`.
2308
+ - `agent-session`'s conversation transcript (compaction, advisor) labels a peer message with the same
2309
+ printable id, so no rendering echoes a sender-chosen id that is not a plain identifier.
2310
+ - `agent-framework` runs a `peer` turn like an `external` one — no tools (`toolChoice: 'none'`), no
2311
+ `@path` expansion, no context references — and adds a per-turn system statement that the message
2312
+ came from another session and carries no authority. A `peer` turn must carry a `peer:` driver id.
2313
+
2314
+ - dd444c1: Bind interactive prompt, fork-skill, and foreground-command execution cleanup to an opaque
2315
+ controller-owned claim so stale cleanup cannot release another active operation or drain its queued
2316
+ input.
2317
+ - 833afe1: Remove the remaining polynomial-ReDoS backtracking (SEC-003, CodeQL `js/polynomial-redos`) and stop the DTLS fingerprint binding to SDP free text.
2318
+
2319
+ **`extractDtlsFingerprint` (agent-remote-pairing) — remote-reachable, pre-authentication.** Unlike the rest of this class, the SDP it parses arrives over the signaling relay, which the pairing design treats as untrusted, and it is parsed _before_ the channel-binding confirmation — on the browser peer, before `setRemoteDescription` too. Unanchored, `a=fingerprint:\S+\s+…` restarted from every offset in a non-space run: 5.0 s on a 400 KB SDP. It is now anchored to the start of an SDP line (`/^…/m`), which is linear and also stops the extractor from returning a value smuggled into another line's free text (`s=`, `i=`, an unrelated attribute) — text no DTLS stack reads, and which a relay controls. **Behaviour change:** a mid-line `a=fingerprint:` is no longer recognised. Every SDP a WebRTC stack emits puts the attribute at the start of its own line, so no real SDP is affected. A session-level line can still shadow a media-level one; that residual is recorded in the SEC-003 backlog.
2320
+
2321
+ **Trailing-run trims (agent-framework, agent-cli, agent-tools).** `replace(/-+$/, '')`-shaped regexes have no start anchor, so the engine retried the run from every offset inside it and each retry rescanned to the end — 3.0 s at 100 K characters, ~50 s at 400 K. The memory topic sanitiser, the provider profile-name sanitiser, the model-command tool-name projection, the npm registry URL builder, the git-worktree path-segment sanitiser and the sandbox-root normaliser now use linear index scans (`trimEdgeChars` / `trimTrailingChars` in agent-framework, local helpers elsewhere), proven equivalent to the regexes they replace over every string of the relevant alphabet up to 12 characters.
2322
+
2323
+ **Whitespace-ambiguity parsers (agent-framework).** The skill and agent-definition frontmatter list splitters used `/\s*,\s*/`, whose whitespace run overlapped nothing after it on a failed comma — 12.6 s on a 200 K run. They now split on `','`; the padding was already removed by the `.trim()` that follows, so the parsed lists are unchanged. The `.git` `gitdir:` pointer and the task-file open-item matcher used `\s*(.+)$` / `\s+(.+)$`, where `\s` and `.` both match a space; the capture is now pinned to start non-space, which accepts exactly the same inputs (verified exhaustively) and removes 14.5 s and 15.4 s worst cases.
2324
+
2325
+ **`WebFetch` HTML-to-text (agent-tools) — carried no CodeQL alert.** Found by sweeping for the same shapes rather than the flagged lines, and the only quadratic here whose input is a live response body from an arbitrary URL. `<[^>]+>`, `<script[\s\S]*?</script>` and `<style…>` each restarted from every opener that had no terminator: 12.6 s on 200 KB of `<`, and the 5 MB the fetch allows would have taken hours. All three are now single-pass scans, verified character-for-character identical to the regexes over ~800 K generated inputs.
2326
+
2327
+ Apart from the `extractDtlsFingerprint` anchoring noted above, no behaviour changes: every fix accepts the same inputs and produces the same values, and each ships an equivalence test pinning that.
2328
+
2329
+ - 7863b16: Create settings files owner-only (SEC-003, CodeQL `js/insecure-temporary-file`).
2330
+
2331
+ `writeSettings` persists `provider.apiKey` verbatim when a profile is configured without
2332
+ `--api-key-env` — the CLI even warns that the key is "stored as plain text in settings" — but the
2333
+ file was created with the process umask (measured `0644`/`0664`), leaving that credential readable
2334
+ by every user on the host. It is now created `0600`.
2335
+
2336
+ This is a permissions change only — file locations, names, formats, and APIs are unchanged. `mode`
2337
+ applies at creation, so a settings file that already exists keeps whatever mode it has; only newly
2338
+ created settings files are affected.
2339
+
2340
+ - 9814afc: Type-SSOT convergence (TYPE-003; re-audit CONTRACT-002/003/011/012 + RUNTIME-47 + STRUCT-04). Behavior is unchanged — this is a type-level refactor. `ITokenUsage` (agent-core) is confirmed as the usage-triple SSOT: `ISessionUsageTotals` and `IBackgroundTaskUsage` become aliases, and every inline `{ promptTokens; completionTokens; totalTokens }` copy (service/orchestration/executor/remote-client shapes) now references the SSOT (structurally identical → patch). The subagent-job contracts derive from the background-task SSOT — `TSubagentJobStatus = Exclude<TBackgroundTaskStatus, 'paused'>`, mode alias, and a `Pick`-projection `ISubagentJobState` — with a compile-enforced parity test so a drifting hand copy can no longer exist. `@robota-sdk/agent-session` is minor because the public `ISessionRecord` type is now the typed `IInteractiveSessionRecord` alias (previously a relaxed `unknown[]` mirror): runtime behavior of `SessionStore` is identical, but downstream code that assigned loose payloads to the record's fields may need explicit casts at its own trust boundary (the framework store facade's `as unknown as` cast bridge is deleted). agent-session's duplicate `@robota-sdk/agent-core` deps/devDeps declaration is also removed (STRUCT-04).
2341
+ - Updated dependencies [9c19c50]
2342
+ - Updated dependencies [7b6234c]
2343
+ - Updated dependencies [5307f8a]
2344
+ - Updated dependencies [b462ee7]
2345
+ - Updated dependencies [37b4bd7]
2346
+ - Updated dependencies [4eea54b]
2347
+ - Updated dependencies [30e5e50]
2348
+ - Updated dependencies [bb4696a]
2349
+ - Updated dependencies [2345c0b]
2350
+ - Updated dependencies [118fe0e]
2351
+ - Updated dependencies [240777e]
2352
+ - Updated dependencies [718bdf5]
2353
+ - Updated dependencies [50d2c9f]
2354
+ - Updated dependencies [1698be4]
2355
+ - Updated dependencies [a5961c9]
2356
+ - Updated dependencies [9368d00]
2357
+ - Updated dependencies [d4189b9]
2358
+ - Updated dependencies [9edae52]
2359
+ - Updated dependencies [4078a72]
2360
+ - Updated dependencies [4c73a0b]
2361
+ - Updated dependencies [af2f2ad]
2362
+ - Updated dependencies [267af5f]
2363
+ - Updated dependencies [196a900]
2364
+ - Updated dependencies [f336838]
2365
+ - Updated dependencies [34e50f0]
2366
+ - Updated dependencies [722e88a]
2367
+ - Updated dependencies [a5cc36e]
2368
+ - Updated dependencies [d23c848]
2369
+ - Updated dependencies [4dd45cc]
2370
+ - Updated dependencies [807d161]
2371
+ - Updated dependencies [fec722f]
2372
+ - Updated dependencies [e82215f]
2373
+ - Updated dependencies [52b7346]
2374
+ - Updated dependencies [9db63ee]
2375
+ - Updated dependencies [b078afa]
2376
+ - Updated dependencies [b078afa]
2377
+ - Updated dependencies [2ebff01]
2378
+ - Updated dependencies [2ebff01]
2379
+ - Updated dependencies [9db63ee]
2380
+ - Updated dependencies [2ebff01]
2381
+ - Updated dependencies [baa6863]
2382
+ - Updated dependencies [2d3b2c0]
2383
+ - Updated dependencies [4772067]
2384
+ - Updated dependencies [7b85767]
2385
+ - Updated dependencies [0f98419]
2386
+ - Updated dependencies [64ba748]
2387
+ - Updated dependencies [9fbab1b]
2388
+ - Updated dependencies [d312755]
2389
+ - Updated dependencies [a009f5b]
2390
+ - Updated dependencies [61db70f]
2391
+ - Updated dependencies [db80aba]
2392
+ - Updated dependencies [1e3f91a]
2393
+ - Updated dependencies [4f3c075]
2394
+ - Updated dependencies [475e085]
2395
+ - Updated dependencies [6085cad]
2396
+ - Updated dependencies [e477440]
2397
+ - Updated dependencies [9dcb5da]
2398
+ - Updated dependencies [a95ca85]
2399
+ - Updated dependencies [b6d14ce]
2400
+ - Updated dependencies [0382a51]
2401
+ - Updated dependencies [93d061d]
2402
+ - Updated dependencies [39554a1]
2403
+ - Updated dependencies [d28430a]
2404
+ - Updated dependencies [bed26ea]
2405
+ - Updated dependencies [1e40b5b]
2406
+ - Updated dependencies [7669851]
2407
+ - Updated dependencies [c6c56a6]
2408
+ - Updated dependencies [4b76cfa]
2409
+ - Updated dependencies [90e7a10]
2410
+ - Updated dependencies [fcb0da3]
2411
+ - Updated dependencies [07b627f]
2412
+ - Updated dependencies [d0de5b2]
2413
+ - Updated dependencies [9665c6e]
2414
+ - Updated dependencies [44393be]
2415
+ - Updated dependencies [c7fa299]
2416
+ - Updated dependencies [5134b3b]
2417
+ - Updated dependencies [ebd40a0]
2418
+ - Updated dependencies [833afe1]
2419
+ - Updated dependencies [d6b9404]
2420
+ - Updated dependencies [5c5ff23]
2421
+ - Updated dependencies [9814afc]
2422
+ - Updated dependencies [242a644]
2423
+ - @robota-sdk/agent-interface-execution@3.0.0-beta.80
2424
+ - @robota-sdk/agent-interface-command@3.0.0-beta.80
2425
+ - @robota-sdk/agent-executor@3.0.0-beta.80
2426
+ - @robota-sdk/agent-core@3.0.0-beta.80
2427
+ - @robota-sdk/agent-session@3.0.0-beta.80
2428
+ - @robota-sdk/agent-interface-session@3.0.0-beta.80
2429
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.80
2430
+ - @robota-sdk/agent-tools@3.0.0-beta.80
2431
+ - @robota-sdk/agent-interface-session-mobility@3.0.0-beta.80
2432
+ - @robota-sdk/agent-interface-analytics@3.0.0-beta.80
2433
+ - @robota-sdk/agent-tool-defaults@3.0.0-beta.80
2434
+ - @robota-sdk/agent-file-authority@3.0.0-beta.80
2435
+
2436
+ ## 3.0.0-beta.79
2437
+
2438
+ ### Patch Changes
2439
+
2440
+ - @robota-sdk/agent-core@3.0.0-beta.79
2441
+ - @robota-sdk/agent-executor@3.0.0-beta.79
2442
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.79
2443
+ - @robota-sdk/agent-session@3.0.0-beta.79
2444
+ - @robota-sdk/agent-tools@3.0.0-beta.79
2445
+
2446
+ ## 3.0.0-beta.78
2447
+
2448
+ ### Patch Changes
2449
+
2450
+ - Updated dependencies [6f308d1]
2451
+ - @robota-sdk/agent-core@3.0.0-beta.78
2452
+ - @robota-sdk/agent-executor@3.0.0-beta.78
2453
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.78
2454
+ - @robota-sdk/agent-session@3.0.0-beta.78
2455
+ - @robota-sdk/agent-tools@3.0.0-beta.78
2456
+
2457
+ ## 3.0.0-beta.77
2458
+
2459
+ ### Patch Changes
2460
+
2461
+ - Updated dependencies
2462
+ - @robota-sdk/agent-core@3.0.0-beta.77
2463
+ - @robota-sdk/agent-executor@3.0.0-beta.77
2464
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.77
2465
+ - @robota-sdk/agent-session@3.0.0-beta.77
2466
+ - @robota-sdk/agent-tools@3.0.0-beta.77
2467
+
2468
+ ## 3.0.0-beta.76
2469
+
2470
+ ### Patch Changes
2471
+
2472
+ - c0a6287: Relocate session feature logic out of the CLI shell and the transport (DQ-AUDIT-004):
2473
+
2474
+ - Extract session-log timing analysis into the new `@robota-sdk/agent-session-analytics` package (pure analysis over canonical session records — no duplicate types, no file I/O). `agent-cli`'s `session analyze` command shrinks to thin wiring and loads records via the new `createUserSessionStore()` / existing `createProjectSessionStore()` framework facades.
2475
+ - Move LLM-based session auto-naming (`generateSessionName`) from `agent-transport/tui` into `agent-framework` (session-lifecycle owner); the TUI transport now invokes it through the framework.
2476
+
2477
+ - 9df3a88: Split the consolidated `@robota-sdk/agent-transport` package into per-concern transport packages (DQ-AUDIT-005) so unrelated heavy dependencies (React/Ink, ws, Hono, MCP SDK) no longer share one publishable unit and are not dragged into non-TUI consumers' graphs:
2478
+
2479
+ - `@robota-sdk/agent-transport` — lean core: headless adapter + `TransportRegistry` + scripted-provider testing fixtures (no external runtime deps).
2480
+ - `@robota-sdk/agent-transport-tui` — React + Ink terminal UI.
2481
+ - `@robota-sdk/agent-transport-ws` — WebSocket transport + protocol (`agent-web-ui` now depends only on this for WS types).
2482
+ - `@robota-sdk/agent-transport-http` — Hono HTTP transport.
2483
+ - `@robota-sdk/agent-transport-mcp` — MCP server transport.
2484
+
2485
+ The default transport-registry wiring (pre-registering `WsTransport`) moves to the CLI composition root, removing the core→ws edge.
2486
+
2487
+ - 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).
2488
+ - Updated dependencies
2489
+ - Updated dependencies
2490
+ - Updated dependencies
2491
+ - Updated dependencies [576af62]
2492
+ - @robota-sdk/agent-core@3.0.0-beta.76
2493
+ - @robota-sdk/agent-session@3.0.0-beta.76
2494
+ - @robota-sdk/agent-executor@3.0.0-beta.76
2495
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.76
2496
+ - @robota-sdk/agent-tools@3.0.0-beta.76
2497
+
2498
+ ## 3.0.0-beta.75
2499
+
2500
+ ### Patch Changes
2501
+
2502
+ - Agent preset system + live preset switching + context/history correctness fixes.
2503
+
2504
+ - **Preset system (PRESET-001~017):** new `@robota-sdk/agent-preset` package layering framework
2505
+ assembly options into named, selectable profiles (`default`, `autonomous-builder`, `careful-reviewer`,
2506
+ `neutral-executor`) plus user-authored external presets loaded from `$PRODUCT_USER_STATE_DIR/presets/*.json`.
2507
+ - **Live preset switching:** `/preset` command (list + active marker + switch) and a TUI active-preset
2508
+ display. Switching live re-applies permission posture, model/effort, persona, command-module
2509
+ selection, parallel-subagents gating, and a self-verification system-prompt section via the single
2510
+ `applyPresetToSession` engine.
2511
+ - **CTX-001:** the TUI Context display + session auto-compact now use the accurate provider-based token
2512
+ estimate (system prompt + tool schemas included) instead of a crude history-only char heuristic.
2513
+ - **HIST-001:** conversation history is now append-only — removed the silent 100-message count cap that
2514
+ could drop early context; context size is managed solely by size-based compaction.
2515
+
2516
+ - Updated dependencies
2517
+ - @robota-sdk/agent-core@3.0.0-beta.75
2518
+ - @robota-sdk/agent-session@3.0.0-beta.75
2519
+ - @robota-sdk/agent-executor@3.0.0-beta.75
2520
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.75
2521
+ - @robota-sdk/agent-tools@3.0.0-beta.75
2522
+
2523
+ ## 3.0.0-beta.74
2524
+
2525
+ ### Patch Changes
2526
+
2527
+ - Architecture conformance release: doc-vs-code audit (INFRA-002), conformance skill system + GATE-CONFORMANCE blocking scan (INFRA-003), canonical-doc drift cleanup (INFRA-004~~011, BEHAVIOR-004), and the interface-type SSOT extraction to `@robota-sdk/agent-interface-transport` with a mechanically-enforced interface-import rule across packages and apps (DATA-001, INFRA-012~~014). Harness process lessons baked into skills (INFRA-015).
2528
+ - @robota-sdk/agent-core@3.0.0-beta.74
2529
+ - @robota-sdk/agent-executor@3.0.0-beta.74
2530
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.74
2531
+ - @robota-sdk/agent-session@3.0.0-beta.74
2532
+ - @robota-sdk/agent-tools@3.0.0-beta.74
2533
+
2534
+ ## 3.0.0-beta.73
2535
+
2536
+ ### Patch Changes
2537
+
2538
+ - @robota-sdk/agent-core@3.0.0-beta.73
2539
+ - @robota-sdk/agent-executor@3.0.0-beta.73
2540
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.73
2541
+ - @robota-sdk/agent-session@3.0.0-beta.73
2542
+ - @robota-sdk/agent-tools@3.0.0-beta.73
2543
+
2544
+ ## 3.0.0-beta.72
2545
+
2546
+ ### Patch Changes
2547
+
2548
+ - Emit context_update event after session restore so TUI status bar reflects correct context usage immediately on /resume.
2549
+ - @robota-sdk/agent-core@3.0.0-beta.72
2550
+ - @robota-sdk/agent-executor@3.0.0-beta.72
2551
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.72
2552
+ - @robota-sdk/agent-session@3.0.0-beta.72
2553
+ - @robota-sdk/agent-tools@3.0.0-beta.72
2554
+
2555
+ ## 3.0.0-beta.71
2556
+
2557
+ ### Patch Changes
2558
+
2559
+ - fix(context): unify token estimation to single SSOT — status bar and /context list now use the same serialized JSON estimate
2560
+ - Updated dependencies
2561
+ - @robota-sdk/agent-core@3.0.0-beta.71
2562
+ - @robota-sdk/agent-executor@3.0.0-beta.71
2563
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.71
2564
+ - @robota-sdk/agent-session@3.0.0-beta.71
2565
+ - @robota-sdk/agent-tools@3.0.0-beta.71
2566
+
2567
+ ## 3.0.0-beta.70
2568
+
2569
+ ### Patch Changes
2570
+
2571
+ - CLI UX fixes: /context list full LLM context breakdown (CLI-B10), logo resize fix (CLI-B03), token estimates in context list (CLI-B04)
2572
+ - @robota-sdk/agent-core@3.0.0-beta.70
2573
+ - @robota-sdk/agent-executor@3.0.0-beta.70
2574
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.70
2575
+ - @robota-sdk/agent-session@3.0.0-beta.70
2576
+ - @robota-sdk/agent-tools@3.0.0-beta.70
2577
+
2578
+ ## 3.0.0-beta.69
2579
+
2580
+ ### Patch Changes
2581
+
2582
+ - Fix /context list showing empty despite non-zero context percentage. System context files (AGENTS.md, CLAUDE.md) loaded at session startup now appear in the list with [system, active] label. Prompt execution no longer re-adds them as manual duplicates.
2583
+ - @robota-sdk/agent-core@3.0.0-beta.69
2584
+ - @robota-sdk/agent-executor@3.0.0-beta.69
2585
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.69
2586
+ - @robota-sdk/agent-session@3.0.0-beta.69
2587
+ - @robota-sdk/agent-tools@3.0.0-beta.69
2588
+
2589
+ ## 3.0.0-beta.68
2590
+
2591
+ ### Patch Changes
2592
+
2593
+ - @robota-sdk/agent-core@3.0.0-beta.68
2594
+ - @robota-sdk/agent-executor@3.0.0-beta.68
2595
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.68
2596
+ - @robota-sdk/agent-session@3.0.0-beta.68
2597
+ - @robota-sdk/agent-tools@3.0.0-beta.68
2598
+
2599
+ ## 3.0.0-beta.67
2600
+
2601
+ ### Patch Changes
2602
+
2603
+ - CLIR: agent-cli layer separation, agent-framework interactive session improvements, subagent runner fix, TUI interface README
2604
+ - @robota-sdk/agent-core@3.0.0-beta.67
2605
+ - @robota-sdk/agent-executor@3.0.0-beta.67
2606
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.67
2607
+ - @robota-sdk/agent-session@3.0.0-beta.67
2608
+ - @robota-sdk/agent-tools@3.0.0-beta.67
2609
+
2610
+ ## 3.0.0-beta.66
2611
+
2612
+ ### Patch Changes
2613
+
2614
+ - refactor: CLI-001/002 — agent-cli layer separation and monorepo-wide readability lint rules
2615
+ - CLI-001: Extract startup phases into focused modules; enforce agent-cli layer separation
2616
+ - CLI-002: Apply import/order, consistent-type-imports, explicit-function-return-type, prefer-const, object-shorthand across all packages
2617
+ - Fix stale child-process-subagent-worker entry in agent-cli tsdown.config.ts (build fix)
2618
+ - @robota-sdk/agent-core@3.0.0-beta.66
2619
+ - @robota-sdk/agent-executor@3.0.0-beta.66
2620
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.66
2621
+ - @robota-sdk/agent-session@3.0.0-beta.66
2622
+ - @robota-sdk/agent-tools@3.0.0-beta.66
2623
+
2624
+ ## 3.0.0-beta.65
2625
+
2626
+ ### Patch Changes
2627
+
2628
+ - @robota-sdk/agent-core@3.0.0-beta.65
2629
+ - @robota-sdk/agent-executor@3.0.0-beta.65
2630
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.65
2631
+ - @robota-sdk/agent-session@3.0.0-beta.65
2632
+ - @robota-sdk/agent-tools@3.0.0-beta.65
2633
+
2634
+ ## 3.0.0-beta.64
2635
+
2636
+ ### Minor Changes
2637
+
2638
+ - feat: add displayName and requiresPermission to command interfaces
2639
+ - `ICommand`, `ISystemCommand`, `ICommandListEntry`: add optional `displayName` field for user-friendly labels
2640
+ - `ISystemCommand`: add optional `requiresPermission` field for per-command permission policy declaration
2641
+ - `SystemCommandExecutor`: add `resolveRequiresPermission()` — derives from `safety` when field is undefined
2642
+ - All 24 built-in commands declare explicit `displayName` and `requiresPermission`
2643
+ - TUI autocomplete renders `displayName ?? name`; Tab completion still inserts the technical command ID
2644
+ - `/help` output shows `Display Name (/command-id)` format
2645
+
2646
+ ### Patch Changes
2647
+
2648
+ - @robota-sdk/agent-core@3.0.0-beta.64
2649
+ - @robota-sdk/agent-executor@3.0.0-beta.64
2650
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.64
2651
+ - @robota-sdk/agent-session@3.0.0-beta.64
2652
+ - @robota-sdk/agent-tools@3.0.0-beta.64
2653
+
2654
+ ## 3.0.0-beta.63
2655
+
2656
+ ### Patch Changes
2657
+
2658
+ - @robota-sdk/agent-core@3.0.0-beta.63
2659
+ - @robota-sdk/agent-session@3.0.0-beta.63
2660
+ - @robota-sdk/agent-tools@3.0.0-beta.63
2661
+ - @robota-sdk/agent-interface-transport@3.0.0-beta.63
2662
+ - @robota-sdk/agent-executor@3.0.0-beta.63
2663
+
2664
+ ## 3.0.0-beta.62
2665
+
2666
+ ### Patch Changes
2667
+
2668
+ - Updated dependencies
2669
+ - @robota-sdk/agent-core@3.0.0-beta.62
2670
+ - @robota-sdk/agent-executor@3.0.0-beta.62
2671
+ - @robota-sdk/agent-session@3.0.0-beta.62
2672
+ - @robota-sdk/agent-tools@3.0.0-beta.62
2673
+
2674
+ ## 3.0.0-beta.61
2675
+
2676
+ ### Minor Changes
2677
+
2678
+ - e243fb0: Add provider-neutral sandbox execution ports, E2B-compatible sandbox adapter, and SDK sandbox injection for Bash and core file tools.
2679
+ - 18fcc5b: Add provider-neutral sandbox snapshot hydration for interactive sessions. Snapshot-capable sandbox clients now persist `sandboxSnapshotId` on shutdown and restore it before saved message replay on non-fork resume, while the E2B structural adapter supports both `createSnapshot()`-style checkpoints and pause/resume sandbox references.
2680
+ - 3bde012: Add provider-neutral sandbox workspace manifests and wire `InteractiveSession` to apply them before session creation.
2681
+
2682
+ ### Patch Changes
2683
+
2684
+ - 36eb7a9: Add provider-owned native replay payload hooks, replay validation coverage, and a session log validation command.
2685
+ - cc0223d: Add SDK-owned provider profile name suggestions, create model-derived profile keys during interactive setup, and show the active provider profile identity in the CLI status area.
2686
+ - d97bdf2: Add provider-owned model catalog metadata, route `/model` suggestions through the active provider, and make `cli:dev` resolve the CLI workspace dependency closure through source export conditions.
2687
+ - Updated dependencies [e243fb0]
2688
+ - Updated dependencies [1c0d44c]
2689
+ - Updated dependencies [36eb7a9]
2690
+ - Updated dependencies [18fcc5b]
2691
+ - Updated dependencies [d97bdf2]
2692
+ - Updated dependencies [3bde012]
2693
+ - @robota-sdk/agent-tools@3.0.0-beta.61
2694
+ - @robota-sdk/agent-core@3.0.0-beta.61
2695
+ - @robota-sdk/agent-session@3.0.0-beta.61
2696
+ - @robota-sdk/agent-executor@3.0.0-beta.61
2697
+
2698
+ ## 3.0.0-beta.60
2699
+
2700
+ ### Minor Changes
2701
+
2702
+ - 7439391: Add provider-neutral native web search/fetch capability contracts, explicit unsupported handling for OpenAI-compatible/LM Studio profiles, and local WebFetch/WebSearch permission/documentation alignment.
2703
+
2704
+ ### Patch Changes
2705
+
2706
+ - 41ae788: Restore the CLI thinking indicator and add structured Agent tool batch provenance/count metadata.
2707
+ - Updated dependencies [7439391]
2708
+ - @robota-sdk/agent-core@3.0.0-beta.60
2709
+ - @robota-sdk/agent-session@3.0.0-beta.60
2710
+ - @robota-sdk/agent-executor@3.0.0-beta.60
2711
+ - @robota-sdk/agent-tools@3.0.0-beta.60
2712
+
2713
+ ## 3.0.0-beta.59
2714
+
2715
+ ### Patch Changes
2716
+
2717
+ - Updated dependencies [95721ff]
2718
+ - @robota-sdk/agent-tools@3.0.0-beta.59
2719
+ - @robota-sdk/agent-core@3.0.0-beta.59
2720
+ - @robota-sdk/agent-session@3.0.0-beta.59
2721
+ - @robota-sdk/agent-executor@3.0.0-beta.59
2722
+
2723
+ ## 3.0.0-beta.58
2724
+
2725
+ ### Patch Changes
2726
+
2727
+ - Refresh package docs and Robota.io content for the beta 57 feature set.
2728
+ - Updated dependencies
2729
+ - @robota-sdk/agent-core@3.0.0-beta.58
2730
+ - @robota-sdk/agent-executor@3.0.0-beta.58
2731
+ - @robota-sdk/agent-session@3.0.0-beta.58
2732
+ - @robota-sdk/agent-tools@3.0.0-beta.58
2733
+
2734
+ ## 3.0.0-beta.57
2735
+
2736
+ ### Minor Changes
2737
+
2738
+ - b80e51e: Add SDK-owned automatic project memory capture, approval review, bounded retrieval, and session-log provenance.
2739
+ - 1cfdce9: Add SDK-owned edit checkpointing for Write/Edit tool mutations with `/rewind` list and code restore commands.
2740
+ - f61e2cb: Add Qwen provider-owned Responses API support for built-in web search/fetch tools and pass provider-owned profile options through generic CLI/runtime configuration.
2741
+ - 822a78b: Add self-hosting verification planning and atomic UTF-8 writes for built-in file mutation tools.
2742
+ - 9817f99: Add active task context loading, formatting, and status update helpers for `.agents/tasks/*.md`.
2743
+
2744
+ ### Patch Changes
2745
+
2746
+ - 16c3b6f: Persist and render provider-neutral per-turn usage summaries with pre-send context updates in CLI sessions.
2747
+ - 4eca470: Render command tool output as bounded transcript previews and persist tool result metadata in SDK tool summaries.
2748
+ - 90a2802: Render Edit tool summaries as context-aware diff hunks with structured truncation metadata.
2749
+ - 26a1718: Preserve and render Edit tool diff metadata in persisted CLI tool summaries.
2750
+ - e504d30: Route project memory through the model-visible `/memory` command descriptor instead of hidden automatic prompt injection.
2751
+ - 0e0e533: Remove obsolete automatic memory policy configuration and top-level automatic memory orchestration exports from the SDK public surface.
2752
+ - Updated dependencies [16c3b6f]
2753
+ - Updated dependencies [b80e51e]
2754
+ - Updated dependencies [26a1718]
2755
+ - Updated dependencies [f61e2cb]
2756
+ - Updated dependencies [822a78b]
2757
+ - @robota-sdk/agent-core@3.0.0-beta.57
2758
+ - @robota-sdk/agent-session@3.0.0-beta.57
2759
+ - @robota-sdk/agent-executor@3.0.0-beta.57
2760
+ - @robota-sdk/agent-tools@3.0.0-beta.57
2761
+
2762
+ ## 3.0.0-beta.56
2763
+
2764
+ ### Patch Changes
2765
+
2766
+ - Updated dependencies
2767
+ - @robota-sdk/agent-core@3.0.0-beta.56
2768
+ - @robota-sdk/agent-executor@3.0.0-beta.56
2769
+ - @robota-sdk/agent-session@3.0.0-beta.56
2770
+ - @robota-sdk/agent-tools@3.0.0-beta.56
2771
+
2772
+ ## 3.0.0-beta.55
2773
+
2774
+ ### Patch Changes
2775
+
2776
+ - 38a72bf: fix: resolve ESLint tsconfig parsing errors and improve pnpm CI reliability
2777
+ - Add tsconfig.eslint.json to all packages for per-package ESLint runs
2778
+ - Migrate typecheck from pnpm -r exec tsc to per-package typecheck scripts
2779
+ - Add --if-present to all recursive pnpm run scripts
2780
+ - Fix React type imports, dynamic imports in tests, Express.Multer types
2781
+
2782
+ - Updated dependencies [38a72bf]
2783
+ - @robota-sdk/agent-core@3.0.0-beta.55
2784
+ - @robota-sdk/agent-session@3.0.0-beta.55
2785
+ - @robota-sdk/agent-tools@3.0.0-beta.55
2786
+
2787
+ ## 3.0.0-beta.54
2788
+
2789
+ ### Patch Changes
2790
+
2791
+ - fix: resolve all typecheck errors across packages
2792
+ - Updated dependencies
2793
+ - @robota-sdk/agent-session@3.0.0-beta.54
2794
+ - @robota-sdk/agent-core@3.0.0-beta.54
2795
+ - @robota-sdk/agent-tools@3.0.0-beta.54
2796
+
2797
+ ## 3.0.0-beta.53
2798
+
2799
+ ### Patch Changes
2800
+
2801
+ - refactor: monolith decomposition — all agent-\* files under 300 lines
2802
+ - fix: PR #69 code review — session resume tool messages, type SSOT, fork isolation, settings crash, Notification removal, chat validation
2803
+ - Updated dependencies
2804
+ - Updated dependencies
2805
+ - @robota-sdk/agent-core@3.0.0-beta.53
2806
+ - @robota-sdk/agent-session@3.0.0-beta.53
2807
+ - @robota-sdk/agent-tools@3.0.0-beta.53
2808
+
2809
+ ## 3.0.0-beta.52
2810
+
2811
+ ### Patch Changes
2812
+
2813
+ - @robota-sdk/agent-core@3.0.0-beta.52
2814
+ - @robota-sdk/agent-session@3.0.0-beta.52
2815
+ - @robota-sdk/agent-tools@3.0.0-beta.52
2816
+
2817
+ ## 3.0.0-beta.51
2818
+
2819
+ ### Patch Changes
2820
+
2821
+ - @robota-sdk/agent-core@3.0.0-beta.51
2822
+ - @robota-sdk/agent-session@3.0.0-beta.51
2823
+ - @robota-sdk/agent-tools@3.0.0-beta.51
2824
+
2825
+ ## 3.0.0-beta.50
2826
+
2827
+ ### Patch Changes
2828
+
2829
+ - fix: reinsert repository/homepage/bugs in correct field order
2830
+ - Updated dependencies
2831
+ - @robota-sdk/agent-tools@3.0.0-beta.50
2832
+ - @robota-sdk/agent-core@3.0.0-beta.50
2833
+ - @robota-sdk/agent-session@3.0.0-beta.50
2834
+
2835
+ ## 3.0.0-beta.49
2836
+
2837
+ ### Patch Changes
2838
+
2839
+ - fix: add repository, homepage, bugs metadata to all publishable packages
2840
+ - Updated dependencies
2841
+ - @robota-sdk/agent-tools@3.0.0-beta.49
2842
+ - @robota-sdk/agent-core@3.0.0-beta.49
2843
+ - @robota-sdk/agent-session@3.0.0-beta.49
2844
+
2845
+ ## 3.0.0-beta.48
2846
+
2847
+ ### Patch Changes
2848
+
2849
+ - fix: record individual tool-start/tool-end in history + fix streaming tool display
2850
+ - Individual tool-start/tool-end events recorded as IHistoryEntry for persistence
2851
+ - TuiStateManager.onToolEnd uses findIndex (first match only, not all with same name)
2852
+ - MessageList hides tool-start/tool-end entries (not rendered as System:)
2853
+ - @robota-sdk/agent-core@3.0.0-beta.48
2854
+ - @robota-sdk/agent-session@3.0.0-beta.48
2855
+ - @robota-sdk/agent-tools@3.0.0-beta.48
2856
+
2857
+ ## 3.0.0-beta.47
2858
+
2859
+ ### Minor Changes
2860
+
2861
+ - feat: ITransportAdapter unified interface + headless transport + CLI adapter pattern
2862
+ - ITransportAdapter interface in agent-sdk (name, attach, start, stop)
2863
+ - InteractiveSession.attachTransport(transport) method
2864
+ - createHttpTransport, createWsTransport, createMcpTransport, createHeadlessTransport factories
2865
+ - CLI print mode uses adapter pattern: session.attachTransport(transport)
2866
+ - agent-transport-headless: text/json/stream-json output, stdin pipe, exit codes
2867
+ - --output-format, --system-prompt, --append-system-prompt CLI flags
2868
+
2869
+ ### Patch Changes
2870
+
2871
+ - @robota-sdk/agent-core@3.0.0-beta.47
2872
+ - @robota-sdk/agent-session@3.0.0-beta.47
2873
+ - @robota-sdk/agent-tools@3.0.0-beta.47
2874
+
2875
+ ## 3.0.0-beta.46
2876
+
2877
+ ### Minor Changes
2878
+
2879
+ - feat: session continue/resume — persist, restore, and switch sessions
2880
+ - ISessionRecord.history field (required) for UI timeline restoration
2881
+ - Session.injectMessage() for AI context restoration on resume
2882
+ - InteractiveSession: sessionStore, resumeSessionId, forkSession, getName/setName
2883
+ - CLI: --continue, --resume, --fork-session, --name flags
2884
+ - TUI: /resume (session picker), /rename (session naming)
2885
+ - ListPicker generic component with viewport scrolling
2886
+ - Session name display: input border title, terminal title, StatusBar
2887
+ - Session picker: cwd filtering, date+time, response preview
2888
+ - React key remount for instant session switching
2889
+
2890
+ ### Patch Changes
2891
+
2892
+ - Updated dependencies
2893
+ - @robota-sdk/agent-session@3.0.0-beta.46
2894
+ - @robota-sdk/agent-core@3.0.0-beta.46
2895
+ - @robota-sdk/agent-tools@3.0.0-beta.46
2896
+
2897
+ ## 3.0.0-beta.45
2898
+
2899
+ ### Patch Changes
2900
+
2901
+ - refactor: transports consume InteractiveSession only — commandExecutor param removed
2902
+ - Add InteractiveSession.listCommands() for transport tool discovery
2903
+ - All transports use session.executeCommand() instead of separate commandExecutor
2904
+ - Simplified factory signatures: only InteractiveSession required
2905
+ - @robota-sdk/agent-core@3.0.0-beta.45
2906
+ - @robota-sdk/agent-session@3.0.0-beta.45
2907
+ - @robota-sdk/agent-tools@3.0.0-beta.45
2908
+
2909
+ ## 3.0.0-beta.44
2910
+
2911
+ ### Patch Changes
2912
+
2913
+ - feat: IHistoryEntry universal history architecture + test quality cleanup
2914
+ - IHistoryEntry as universal history type across all 4 packages (core → sessions → sdk → cli)
2915
+ - Tool summary stored as event entry in history (category: 'event', type: 'tool-summary')
2916
+ - TuiStateManager pure TypeScript class for CLI rendering state
2917
+ - MessageList renders IHistoryEntry[] with Tool:/System:/You:/Robota: labels
2918
+ - Display order fixed: Tool → Robota (both streaming and abort)
2919
+ - Remove 25 tautological, duplicate, and hardcoded tests
2920
+
2921
+ - Updated dependencies
2922
+ - @robota-sdk/agent-core@3.0.0-beta.44
2923
+ - @robota-sdk/agent-session@3.0.0-beta.44
2924
+ - @robota-sdk/agent-tools@3.0.0-beta.44