refactor(mode): modes are collaboration states — drop the access cap; enforcement axes stay independent
Review follow-up (tianyicui): plan mode and the sandbox are orthogonal
AXES, not just orthogonal state — entering plan must not change what the
sandbox enforces, matching Codex's separation of Plan/Default
collaboration presets from sandbox and approval settings.
ModeDefinition.access, the bash/resolve-mode clamp, and both cap-derived
guards are removed; a ModeDefinition is exactly { section }, and a mode
now carries only its guidance section plus the exit_plan_mode review.
The bash seam's resolveMode + waterfall go with their only listener:
dsh-bash and dsh-tool-bash revert to master byte-for-byte, and the
dsh-mode → dsh-bash dependency edge is gone. A deployment that wants
kernel-enforced read-only planning pairs the mode picker with the
independent sandbox-mode option, in either order.
The RFC archives this as the second removed enforcement shape (after
the interim allowlist) with the same restart trigger — effects
self-declaration; the orthogonality FAQ now answers with the two-axis
rule. The plan example demonstrates the axes side by side, and the
re-recorded fixtures pin the guidance-only section.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
Registry (`ctx.bashEnv`) for trusted, per-execution `DSH_*` variables. The namespace is rebuilt for every model bash call: ambient `DSH_*` values are discarded by the executor, then the registry's current snapshot is injected. Built-in shell facts remain owned by the registry itself while plugins can register additional, enumerable facts with effect-scoped disposal.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L109)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L102)
|
||||
|
||||
### ctx.bashEnv.register(contributor)
|
||||
|
||||
@@ -20,7 +20,7 @@ Register one environment contributor. Names and keys are unique; built-in keys a
|
||||
|
||||
**Returns** the disposer that unregisters the contribution.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L130)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L123)
|
||||
|
||||
### ctx.bashEnv.collect(execution)
|
||||
|
||||
@@ -34,7 +34,7 @@ Build the trusted `DSH_*` snapshot for one bash tool execution.
|
||||
|
||||
**Returns** an immutable environment overlay containing built-ins and current contributions.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L172)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L165)
|
||||
|
||||
### ctx.bashEnv.list()
|
||||
|
||||
@@ -46,4 +46,4 @@ Enumerate plugin-contributed variables without executing their resolvers.
|
||||
|
||||
**Returns** declarations sorted by environment variable name.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L204)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/tool-bash/src/index.ts#L197)
|
||||
|
||||
@@ -11,7 +11,7 @@ Implementations must honor these semantics:
|
||||
- BashProcess.readOutput is incremental: consecutive reads never repeat output. Lossy reads report truncation and available spill files.
|
||||
- Disposal kills all running background processes and awaits their exit.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L69)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L49)
|
||||
|
||||
### ctx.bash.sandboxMode
|
||||
|
||||
@@ -21,21 +21,7 @@ get sandboxMode(): SandboxMode | undefined
|
||||
|
||||
The sandbox mode this executor applies by default, or `undefined` when it does not sandbox commands.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L79)
|
||||
|
||||
### ctx.bash.resolveMode(session)
|
||||
|
||||
```ts website-api
|
||||
async resolveMode(session: Session | undefined): Promise<SandboxMode | undefined>
|
||||
```
|
||||
|
||||
Resolve the sandbox mode a call for `session` runs under: the session's standing override (the `bash/sandbox-mode` fold) falling back to this executor's configured default, dispatched through the `bash/resolve-mode` waterfall so policy plugins can narrow the base per call — read-time composition over independent folds, nothing written back to any store. Returns `undefined` — without consulting the waterfall — when this executor never confines (sandboxMode `undefined`): there is no mode to resolve and nothing would honor one. An escalation grant is not this method's business: the tool layer resolves grants separately and stamps them with higher precedence.
|
||||
|
||||
- `session` — the session whose override fold applies; `undefined` for a sessionless caller (the executor default alone seeds the waterfall).
|
||||
|
||||
**Returns** the effective mode for a confining executor; `undefined` for one that never confines.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L100)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L59)
|
||||
|
||||
### ctx.bash.resolve(request)
|
||||
|
||||
@@ -49,7 +35,7 @@ Apply implementation-owned defaults and caps to a request before execution.
|
||||
|
||||
**Returns** the fully-specified spec to hand to `run`/`start`.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L113)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L69)
|
||||
|
||||
### ctx.bash.run(spec)
|
||||
|
||||
@@ -63,7 +49,7 @@ Run a command in the foreground; resolves when it finishes.
|
||||
|
||||
**Returns** the outcome; nonzero exits, timeout kills, and abort kills resolve with a descriptive result rather than reject.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L121)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L77)
|
||||
|
||||
### ctx.bash.start(spec)
|
||||
|
||||
@@ -77,4 +63,4 @@ Start a background process and return its handle immediately.
|
||||
|
||||
**Returns** the live process handle (reads, kill, quiescence promise).
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L128)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L84)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Harness events
|
||||
|
||||
Every event the harness packages declare on the cordis event bus (40 total), grouped by scope. The **mode** is the dispatch semantics (`emit` fire-and-forget, `parallel` awaited, `serial` first-bail, `waterfall` veto-chain — a waterfall listener MUST call `next()` to delegate).
|
||||
Every event the harness packages declare on the cordis event bus (39 total), grouped by scope. The **mode** is the dispatch semantics (`emit` fire-and-forget, `parallel` awaited, `serial` first-bail, `waterfall` veto-chain — a waterfall listener MUST call `next()` to delegate).
|
||||
|
||||
## agent/*
|
||||
|
||||
@@ -229,22 +229,6 @@ Ask composed answerers for one decision. Return an outcome to claim the request
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/ui/user-approval/src/index.ts#L31)
|
||||
|
||||
## bash/*
|
||||
|
||||
### bash/resolve-mode
|
||||
|
||||
**Mode:** `waterfall`
|
||||
|
||||
```ts website-api
|
||||
'bash/resolve-mode'(this: BashExecutor, session: Session | undefined, next: () => Promise<SandboxMode>): Promise<SandboxMode>
|
||||
```
|
||||
|
||||
Waterfall around BashExecutor.resolveMode's base — the session's standing override falling back to the executor's configured default. A policy plugin narrows the resolution per call by clamping `await next()` (a session mode's `access` cap is the shipped example); returning without `next()` replaces the resolution outright. Dispatched only for a confining executor — a never-confining one resolves `undefined` without consulting listeners, so a listener always receives a real base mode from `next()`.
|
||||
|
||||
- `session` — the session the call belongs to (its log carries the override fold and any mode state a listener clamps by); `undefined` for a sessionless caller.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/bash/bash/src/index.ts#L49)
|
||||
|
||||
## fs/*
|
||||
|
||||
### fs/edit-intent
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
`ModesService` — provided by `@deepseek-ai/dsh-mode`.
|
||||
|
||||
`ctx.modes`: the session-mode service. Owns the `mode/set` vocabulary, the pending-intent flush, the boundary narration, and both policy layers (the assemble filter + `mode:policy` section, and the `tools/pre-execute` gate). UIs read mode flips off `session/event`; there is no live mirror.
|
||||
`ctx.modes`: the session-mode service. Owns the `mode/set` vocabulary, the pending-intent flush, the boundary narration, the `mode:policy` section, and the exit tool's visibility rule. UIs read mode flips off `session/event`; there is no live mirror.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L256)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L216)
|
||||
|
||||
### ctx.modes.resolved
|
||||
|
||||
@@ -16,7 +16,7 @@ readonly resolved: ResolvedModes
|
||||
|
||||
Validated definitions (built-in `plan` merged unless overridden).
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L260)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L220)
|
||||
|
||||
### ctx.modes.list()
|
||||
|
||||
@@ -28,7 +28,7 @@ The selectable mode vocabulary: DEFAULT_MODE first, then the configured definiti
|
||||
|
||||
**Returns** Mode names, `default` first.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L485)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L380)
|
||||
|
||||
### ctx.modes.get(agent)
|
||||
|
||||
@@ -42,7 +42,7 @@ The agent's mode state: the folded mode in force (a folded name the config no lo
|
||||
|
||||
**Returns** The current (effective) mode and the pending intent, if any.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L497)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L392)
|
||||
|
||||
### ctx.modes.set(agent, mode)
|
||||
|
||||
@@ -55,4 +55,4 @@ Select the agent's mode. Validates the name against list (loud on unknown; `defa
|
||||
- `agent` — The agent to switch.
|
||||
- `mode` — The target mode name.
|
||||
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L512)
|
||||
[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/mode/mode/src/index.ts#L407)
|
||||
|
||||
Reference in New Issue
Block a user