policy: scope seed-boundary slicing to delegation children

Review fix (ds-review-bot on #623): the unconditional slice regressed the
public SessionStore.fork path — a generic fork child gets seedLength but no
policy baseline, so slicing discarded its seed-carried sandbox/approval
switches and silently widened it to the deployment defaults (a forked
read-only/never parent produced a workspace-write/ask child).

overrideOf now branches on baseline presence: with a header baseline (a
delegation child) the fold covers only own post-seed switches — the
baseline captured from the parent's FULL log subsumes seed history; without
one, the whole log — seeded switches ARE the replayed inherited truth. The
permission preset fold scopes the same way. Red-first: generic-fork
seed-carried override tests in both policy suites.
This commit is contained in:
kingwl
2026-07-26 23:06:15 +08:00
parent b02d3e4c03
commit 99f5fab7bc
17 changed files with 78 additions and 41 deletions

View File

@@ -1862,7 +1862,7 @@ export interface Config {
export type ApprovalPolicy = 'ask' | 'never'
```
Source: [`packages/ui/user-approval/src/index.ts:221`](../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:226`](../packages/ui/user-approval/src/index.ts)
## `@deepseek-ai/dsh-web`

View File

@@ -256,7 +256,7 @@ overrideOf(session: Session): ApprovalPolicy | undefined
Types: [ApprovalOutcome](../core-data-structures/approval.md) · [ApprovalPolicy](../core-data-structures/approval.md) · [ApprovalRequest](../core-data-structures/approval.md) · [Session](../core-data-structures/session.md)
Source: [`packages/ui/user-approval/src/index.ts:236`](../../packages/ui/user-approval/src/index.ts)
Source: [`packages/ui/user-approval/src/index.ts:241`](../../packages/ui/user-approval/src/index.ts)
## `ctx.bash` — `BashExecutor` (abstract seam)
@@ -778,10 +778,11 @@ Owns the deployment's permission presets and their write path. Requires a confin
* override chains execution reads (own post-seed switches, else the
* inherited header baseline, else the composition defaults), so a
* delegated child's inherited knobs derive its real preset. A
* still-matching last OWN selection wins shared-bundle ties (a seed-carried
* selection is stale parent history, subsumed by the baseline); otherwise
* the first table match wins, or {@link CUSTOM_PRESET} when no entry
* matches.
* still-matching last selection wins shared-bundle ties, scoped like the
* knob chains: a delegation child (header baselines present) ignores
* seed-carried selections as stale parent history, while a generic fork
* child keeps them alongside its seed-carried knobs; otherwise the first
* table match wins, or {@link CUSTOM_PRESET} when no entry matches.
* @param session - the session whose preset to derive.
* @returns the effective preset name, or `custom` when nothing matches.
*/