refactor(web): drop the permission RPC pair and turn-anchoring machinery

The session.permissions/setPermission unary pair, the PermissionOption wire
DTO, the client Session wrappers, and the fixture/fake mirrors all leave the
wire: the read side moves to the 'permissions' session projection and the
write side moves to the /permission command in follow-up commits, so the
web protocol gains no permission methods at all.

The pendingSwitches + prompt-submit flush + hasOpenTurn move also goes.
Knob events no longer need turn enclosure: the persistence scanner keeps
standalone events after the last turn/end as part of the preserved prefix
(remove-synthetic-log-only-turns), none of the three knob invariants demand
an open turn, and the setters append bare events. An idle switch commits
immediately; hasOpenTurn stays a user-approval private fold (its audit pair
is the one contract that still requires enclosure).

The old PermissionSelect chip and its mount-time fetch die with the RPCs
(the resident composer broke the mount-once assumption); the projection-fed
replacement lands with the Access seat swap.
This commit is contained in:
imccyu
2026-07-28 21:35:26 +08:00
parent a66d1e335f
commit c6b552e817
36 changed files with 37 additions and 561 deletions
+1 -9
View File
@@ -40,15 +40,7 @@ export type { PendingInteraction, PendingKind, PendingPayloads } from './session
export type {
ProjectionsBaseline, ProjectionValueStore, SessionProjectionMap, UseProjection,
} from './sessions/projection-store.ts'
export type { PermissionOption, SessionId } from '@deepseek-ai/dsh-client-connection/client'
/** The permission select material as the object layer serves it to UI plugins. */
export interface PermissionSelect {
/** Switchable presets plus (when derived) the current-only `custom`. */
options: { value: string; name: string; description?: string }[]
/** The effective current value (`custom` when knobs match no preset). */
currentValue: string
}
export type { SessionId } from '@deepseek-ai/dsh-client-connection/client'
/** Client-side Cordis context after declaration merging. */
export type ClientContext = Context
@@ -248,31 +248,6 @@ export class Session implements ObservableSnapshot<ConversationSnapshot> {
return result
}
/**
* Read the permission select (options + effective current value).
* @returns the select material, or the error branch on failure.
*/
async permissions(): Promise<RpcResult<{ options: { value: string; name: string; description?: string }[]; currentValue: string }>> {
try {
return (await this.api.sessions.permissions({ sessionId: this.sessionId })).result
} catch (error) {
return transportError(error)
}
}
/**
* Switch the permission preset.
* @param value - a preset value advertised by {@link Session.permissions} (never `custom`).
* @returns the confirmed current value, or the error branch on failure.
*/
async setPermission(value: string): Promise<RpcResult<{ currentValue: string }>> {
try {
return (await this.api.sessions.setPermission({ sessionId: this.sessionId, value })).result
} catch (error) {
return transportError(error)
}
}
/** First open: pull the tail page (idempotent — in-flight/already-open returns the existing promise). */
open(): Promise<void> {
if (this.openState === 'open') return Promise.resolve()