Repository navigation
# A persisted auto permission preset makes a session permanently unopenable when the Auto integration is absent ##
#9154
Replies: 2 comments
|
Confirming this from the source at Both ends, locatedWrite end — private apply(session, name, setApproval): void {
const spec = this.resolve(name)
if (name === AUTO_PRESET) this.autoAdmit?.() // optional call: absence is not an error
...
if (current !== name) session.append('permission/preset', { preset: name })Restore end — if (preset === AUTO_PRESET) {
if (this.autoAdmit === undefined)
throw new Error('permission: cannot restore preset "auto" without its active integration')
this.autoAdmit()
}So the asymmetry is exactly as you describe, and it is one line of optional call against one line of throw. Why the failure is so total. The restore path is not called by the opener — it runs from this service's own The write path is not the one a fix would naturally guardThe public method is A public liveness probe already exists
return [...Object.keys(this.presets), ...(this.autoAdmit === undefined ? [] : [AUTO_PRESET])]
The third expected behaviour is reachable today, without rewriting historyYou listed "the session opens with the preset downgraded/flagged" as an alternative to failing at write time, and that one does not need the write end changed. The durable record is a single The ordering supports it, too: Guarding the write and repairing the restore are both worth having; they are not the same fix, and the second one is the one that rescues the sessions that are already in this state. We are prototyping the restore-side half as an out-of-tree plugin (public probe above, no core change) and will follow up here with the result either way — including if it turns out not to carry its weight. |
|
Following up on this thread with the plugin I said I would report back on, since the fix shape here turns out to be reachable from outside the core.
npm install @argszero/cordis-plugin-permission-restore-guard# in a dsh profile's cordis config
- id: permission-restore-guard
name: '@argszero/cordis-plugin-permission-restore-guard'It registers a listener on Ordering is the load-bearing part, and the suite measures it rather than asserting it: a listener registered after the service cannot prevent the throw, because A Evidence, so the claim is checkable rather than interesting: 58 tests against the real Two limits worth stating plainly. It does not re-register the Auto integration and does not restore what Auto did — what a repaired session loses is the Auto admission hook, which is exactly the thing that cannot come back without its integration. And the underlying asymmetry in this report is untouched: the write side still silently succeeds through an optional call while the restore side throws, in a listener whose throw is fatal to the publication. The plugin removes the consequence for sessions it can reach; it does not remove the asymmetry. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
A session whose recorded permission preset is
autocannot be opened at all once theAuto review integration is not live. The host fails to resume the session, disposes it, and
the client marks it
removed— the input bar shows "Session unavailable" and the sessiondisappears from the sidebar. The session data on disk is intact; there is no in-product
way to recover it.
The failure is asymmetric and that asymmetry is the bug:
autosucceeds silently even when no integration is registered(
apply()calls the optionalthis.autoAdmit?.()).(
pinInitialPermission()throws).So a preset that can be written at any time can become unrestorable after a restart, with
no warning and no user-facing remedy.
Affected
@deepseek-ai/dsh-permission-presets@0.1.7-rc.2@deepseek-ai/dsh-api-session-controller(emitsapi-session/removed)@deepseek-ai/dsh-client-ui-conversation(renders the disabled composer)0.2.0-rc.2, Windows 11 x64, bundled runtime0.2.0-rc.2Steps to reproduce
@deepseek-ai/dsh-experimental-auto-reviewis not shipped; the shipped preset table hasonly
workspace-writeanddanger-full-access), write a session's preset asauto.Any third-party preset provider that names its preset
autodoes this — that was thetrigger here (
dsh-auto-approve@0.6.2, whose preset id was later renamed tosandboxed-autoprecisely becauseautobecame reserved).On dsh ≥ 0.1.7 a configured preset cannot be named
auto, but a recordedautoselection is still produced by any integration that registers one.
Expected behavior
Any one of:
autois rejected while no integration is registered (fail at write time, not read time);Actual behavior
resume failed for session "<id>": Error: permission: cannot restore preset "auto" without its active integrationapi-session/removed→ snapshotremoved: true会话不可用/ "Session unavailable";sidebar filters the session out entirely
Root cause (source)
packages/interaction/permission-presets/src/index.ts:publishAgentAvailability/ctx.on('session/disposed', …)inpackages/api/session-controllerthen relay the removal:and the client turns that into a permanently locked composer
(
dsh-client-ui-conversation:const disabled = removed || inert || !live || blocked !== undefined).Impact observed: in one install, 3 of the sessions the user actually works in were
affected (25 sessions total across the store recorded
auto; the rest were archived ordelegated-child sessions that are not listed anyway).
Suggested fix
Pick whichever fits the design intent, but the write side should not be able to create a
state the read side refuses:
apply()should throw (or downgrade + warn) whenname === AUTO_PRESET && this.autoAdmit === undefined, mirroringpinInitialPermission().pinInitialPermission()should not throw for a staleautoidentity; treat it as
custom/the composition default, keep the session openable, andsurface a notice. (The
permission/presetevent is log-only user intent, so the durableidentity is preserved either way.)
out that is not "edit the session log by hand".
Workaround used
Append a superseding
permission/preset(+sandbox/mode) event to the session log,overwriting the
autoselection. This works because the file is a multi-frame zstd containerof JSONL events and the last selection wins — but it requires stopping DSH and hand-editing
the
.zstd, which is not something users should have to do.{"type":"permission/preset","seq":<next>,"time":<ms>,"data":{"preset":"workspace-write"}} {"type":"sandbox/mode","seq":<next+1>,"time":<ms>,"data":{"mode":"workspace-write"}}Related
dsh-auto-approvedocuments this exact failure in its README("a session whose recorded preset is
autofails to open on dsh 0.1.7+ while the officialAuto review is off, with
cannot restore preset "auto" without its active integration.Its data is not lost; it just cannot be opened for now.") — the failure mode is known to
third parties but the docs do not warn about it: the permission-presets subsystem page
only says a stored
autosession "requires the live Auto registration before Agentpublication", without saying the session becomes unopenable.
MissingSessionIDon providers needing a sessionheader), Bug: OpenCode Go requests fail with MissingSessionID #6467, Make web search follow the session's LLM route (and support gateway routing headers) #8512 — this report is a different failure (session lifecycle, not reviewer transport).
All reactions