feat(modes): per-session sandbox/approval switching — the session log as the store, ACP config options
effective(session) = findLast(the session own knob events)?.value ?? the composition-config default. One log-only event per knob, owned by its domain (bash/sandbox-mode in dsh-bash, approval/policy in dsh-approval), each exporting the same three-piece kit: the event declaration, a pure fold, and THE write path — a switch IS its event; no owner service, no facts map. Restart immunity and multi-session isolation fall out of the log replay by construction. Execution follows the fold on both sides: the bash tool stamps escalation grant > session override > executor default, and the approval seam prepends the never-gate that auto-rejects before any interactive answerer. Visibility is two layers per knob: a per-agent prompt section states the effective value on every request (logged through request/header*, so what-the-model-was-told replays from the log), and an agent/pre-step narrator injects at most one coalesced delta notice with positional attribution (user switch vs operator/config drift). The ACP bridge advertises one capability-gated select per composable knob with currentValue folded per session, validates set_config_option against the closed vocabularies, and anchors idle switches at the next turn prompt-submit under the turn-enclosure contract.
This commit is contained in:
@@ -23,7 +23,7 @@ An approval question was put to the answerer chain — log-only audit (like `hoo
|
||||
|
||||
Types: [CallId](core-data-structures/core.md)
|
||||
|
||||
Source: [`packages/approval/approval/src/index.ts:66`](../packages/approval/approval/src/index.ts)
|
||||
Source: [`packages/approval/approval/src/index.ts:77`](../packages/approval/approval/src/index.ts)
|
||||
|
||||
#### `approval/decided` — log-only
|
||||
|
||||
@@ -33,7 +33,17 @@ The outcome of a prior `approval/asked` (same `id`) — log-only audit. Exactly
|
||||
'approval/decided': { id: ApprovalRequestId; outcome: ApprovalOutcome }
|
||||
```
|
||||
|
||||
Source: [`packages/approval/approval/src/index.ts:77`](../packages/approval/approval/src/index.ts)
|
||||
Source: [`packages/approval/approval/src/index.ts:88`](../packages/approval/approval/src/index.ts)
|
||||
|
||||
#### `approval/policy` — log-only
|
||||
|
||||
The session's approval policy was switched — log-only, durable, replayable, never in the model transcript (the model learns the policy from the prompt section and the narrator's notices). The LAST such event is the session's override (effectiveApprovalPolicy); who asked for it is derivable from position (an event after the log's last `request/header*` was a runtime switch by the user).
|
||||
|
||||
```ts persistence-catalog
|
||||
'approval/policy': { policy: ApprovalPolicy }
|
||||
```
|
||||
|
||||
Source: [`packages/approval/approval/src/index.ts:100`](../packages/approval/approval/src/index.ts)
|
||||
|
||||
### `assistant/*`
|
||||
|
||||
@@ -61,6 +71,18 @@ Types: [ContentBlock](core-data-structures/core.md) · [TokenUsage](core-data-st
|
||||
|
||||
Source: [`packages/core/session/src/types.ts:320`](../packages/core/session/src/types.ts)
|
||||
|
||||
### `bash/*`
|
||||
|
||||
#### `bash/sandbox-mode` — log-only
|
||||
|
||||
The session's sandbox mode was switched — log-only (like `approval/*`; NOT a surface event, carries no `surfaceOp`): durable and replayable, never in the model transcript. The LAST such event is the session's override (effectiveSandboxMode); who asked for it is derivable from position (an event after the log's last `request/header*` was a runtime switch by the user; see the tool layer's narrator).
|
||||
|
||||
```ts persistence-catalog
|
||||
'bash/sandbox-mode': { mode: SandboxMode }
|
||||
```
|
||||
|
||||
Source: [`packages/bash/bash/src/session-mode.ts:31`](../packages/bash/bash/src/session-mode.ts)
|
||||
|
||||
### `compact/*`
|
||||
|
||||
#### `compact/end` — log-only
|
||||
|
||||
Reference in New Issue
Block a user