subagent: seed inherited policy events at creation

The parent implementation introduced sandboxMode and approvalPolicy as generic SessionHeader fields, then propagated those fields through both persistence backends, session-query indexes, collision checks, policy-specific seed-boundary folds, catalogs, and a broad test matrix. That storage plane is unnecessary: Session already accepts a validated constructor seed, and persistence captures that seed when the session is announced before committing its first batch.

Capture each parent override synchronously at delegation, append source-tagged sandbox/mode and approval/policy records after the optional fork prefix, and create the child with that combined seed. Keeping header.seedLength at the original fork-prefix length preserves lineage while ordinary last-event-wins folds make the inherited records outrank stale parent history and remain subordinate to later child switches. Unswitched parents still stamp nothing, so children continue to follow deployment defaults.

Remove the generic header fields and every persistence/query/schema branch built around them. Collapse the inheritance suite from ten leaking scenarios to four owned-context cases covering real filesystem confinement, stale fork precedence, delegation-time capture, and the no-override path. The assembled headless snapshot now asserts the persisted inheritance event directly.

This keeps the security behavior while restoring policy ownership to the existing event log and deleting the speculative durability machinery that the original tests did not exercise.
This commit is contained in:
Tianyi Cui
2026-07-28 21:31:17 +08:00
parent afa38c4b2f
commit cfceb8452b
55 changed files with 415 additions and 1371 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/core-data-structures/persistence.md
persistence.md: 6238182a9d570852bc1ba6e89de90427aa625b99
persistence.zh.md: 414454dd19131a07876620e9c1e3232e155e9ccf
persistence.md: 5a660e17d6f498213564ca7d68dc4d7a615ba1de
persistence.zh.md: b5477cfc8242f9db47c2c6e40bd63f1b3683ace9

View File

@@ -72,30 +72,12 @@ interface SessionHeader {
* resume — a runtime-only depth would reset a resumed child to top-level.
*/
readonly delegationDepth?: number
/**
* The sandbox-mode override inherited from the delegating parent at
* creation (the delegation-inheritance baseline). A neutral string here:
* the policy owner (`dsh-sandbox-policy`) validates it against its closed
* vocabulary on every read, this being a durable boundary. Absent for
* top-level sessions and for children of unswitched parents, which keep
* following the LIVE deployment default. Header-carried (the
* `delegationDepth` precedent) so the baseline is durable from the creation
* moment — no first-turn event survives every crash window, because an
* idle injection can persist a complete turn before any prompt turn opens.
*/
readonly sandboxMode?: string
/**
* The approval-policy override inherited from the delegating parent at
* creation. Same contract as {@link SessionHeader.sandboxMode}; validated
* by `dsh-user-approval` on read.
*/
readonly approvalPolicy?: string
}
```
## `CreateSessionOptions` — seeding and metadata
Creating a `Session` through the store takes a `seed` (replay/fork an existing event log) and `meta` (the storage-level fields the store folds into a `SessionHeader`). The store fills in `version`/`id` and defaults `createdAt`; the caller supplies the validated absolute `cwd`, the `parentSession` lineage, the `seedLength` seed boundary, the `delegationDepth`, the inherited `sandboxMode`/`approvalPolicy` delegation baselines, and — only when reconstructing a persisted session — the original `createdAt` to preserve it.
Creating a `Session` through the store takes a `seed` (replay/fork an existing event log) and `meta` (the storage-level fields the store folds into a `SessionHeader`). The store fills in `version`/`id` and defaults `createdAt`; the caller supplies the validated absolute `cwd`, the `parentSession` lineage, the `seedLength` seed boundary, the `delegationDepth`, and — only when reconstructing a persisted session — the original `createdAt` to preserve it.
```ts type-equiv
/**
@@ -116,8 +98,6 @@ interface CreateSessionOptions {
readonly createdAt?: number
readonly seedLength?: number
readonly delegationDepth?: number
readonly sandboxMode?: string
readonly approvalPolicy?: string
}
}
```

View File

@@ -72,30 +72,12 @@ interface SessionHeader {
* resume — a runtime-only depth would reset a resumed child to top-level.
*/
readonly delegationDepth?: number
/**
* The sandbox-mode override inherited from the delegating parent at
* creation (the delegation-inheritance baseline). A neutral string here:
* the policy owner (`dsh-sandbox-policy`) validates it against its closed
* vocabulary on every read, this being a durable boundary. Absent for
* top-level sessions and for children of unswitched parents, which keep
* following the LIVE deployment default. Header-carried (the
* `delegationDepth` precedent) so the baseline is durable from the creation
* moment — no first-turn event survives every crash window, because an
* idle injection can persist a complete turn before any prompt turn opens.
*/
readonly sandboxMode?: string
/**
* The approval-policy override inherited from the delegating parent at
* creation. Same contract as {@link SessionHeader.sandboxMode}; validated
* by `dsh-user-approval` on read.
*/
readonly approvalPolicy?: string
}
```
## `CreateSessionOptions`seed 与元数据
通过 store 创建 `Session` 时会接收 `seed`(回放/fork 现有事件日志)与 `meta`store 折叠进 `SessionHeader` 的存储层字段。store 填充 `version`/`id` 并为 `createdAt` 提供默认值;调用方提供已校验的绝对 `cwd`、`parentSession` 谱系、`seedLength` 种子边界、`delegationDepth`、继承的 `sandboxMode`/`approvalPolicy` 委派基线,以及——仅在重建已持久化会话时——需要保留的原始 `createdAt`。
通过 store 创建 `Session` 时会接收 `seed`(回放/fork 现有事件日志)与 `meta`store 折叠进 `SessionHeader` 的存储层字段。store 填充 `version`/`id` 并为 `createdAt` 提供默认值;调用方提供已校验的绝对 `cwd`、`parentSession` 谱系、`seedLength` 种子边界、`delegationDepth`,以及——仅在重建已持久化会话时——需要保留的原始 `createdAt`。
```ts type-equiv
/**
@@ -116,8 +98,6 @@ interface CreateSessionOptions {
readonly createdAt?: number
readonly seedLength?: number
readonly delegationDepth?: number
readonly sandboxMode?: string
readonly approvalPolicy?: string
}
}
```