refactor(sandbox-policy): remove capability family registries

This commit is contained in:
Tianyi Cui
2026-07-31 13:28:02 +08:00
parent e6407477a7
commit e088cfa59d
112 changed files with 260 additions and 403 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 packages/fs/fs-sandbox/README.md
README.md: a376f2c23dca9f0895525fa274a1ae0545823f63
README.zh.md: 4fa2deecb7d10124da8b7920997196b816457fcc
README.md: bce22feac8b6b4a31abc0cbfddd39681ad437062
README.zh.md: 0bb0190f5a0506f2d10f82a5f03370b977472aee

View File

@@ -26,7 +26,7 @@ A denial is a structured `FsError` (`FS_SANDBOX_DENIED`, carrying the effective
#### What the model sees
This backend contributes the write/edit family to the owner-rendered `sandbox:policy` section. Indirectly, `dsh-tool-fs` renders its `FS_SANDBOX_DENIED` refusals as the `[sandbox: file access denied under <mode> mode]` marker plus the same-turn escalation hint.
The policy owner contributes capability-neutral `sandbox:policy` context. Indirectly, `dsh-tool-fs` renders this backend's `FS_SANDBOX_DENIED` refusals as the `[sandbox: file access denied under <mode> mode]` marker plus the same-turn escalation hint.
#### Token effect
@@ -34,7 +34,7 @@ The current-policy clause adds a small fixed prefix while this backend is mounte
#### KV Cache effect
A standing-policy or family-composition change updates the owner-rendered request prefix; operation results remain append-only.
A standing-policy change updates the owner-rendered request prefix; operation results remain append-only.
## Known Limitations and Deferred Work

View File

@@ -26,7 +26,7 @@
#### 模型看到的内容
该后端会向归属方渲染的 `sandbox:policy` 段落贡献 write/edit 家族。作为间接影响,`dsh-tool-fs` 会把本后端的 `FS_SANDBOX_DENIED` 拒绝渲染为 `[sandbox: file access denied under <mode> mode]` 标记和同轮次升级提示。
策略归属方会贡献与具体能力无关的 `sandbox:policy` 上下文。作为间接影响,`dsh-tool-fs` 会把本后端的 `FS_SANDBOX_DENIED` 拒绝渲染为 `[sandbox: file access denied under <mode> mode]` 标记和同轮次升级提示。
#### Token 影响
@@ -34,7 +34,7 @@
#### KV Cache 影响
常驻策略或家族组合发生变化时,归属方渲染的请求前缀会更新;操作结果保持仅追加。
常驻策略发生变化时,归属方渲染的请求前缀会更新;操作结果保持仅追加。
## 已知限制与暂缓事项

View File

@@ -44,7 +44,7 @@ import { isPathUnder } from './containment.ts'
* Plugin config: the local backend's knobs, verbatim (only `cwd`, the resolve
* base for relative paths). The sandbox default (mode + `workspace-write`
* fallback root) is NOT here — `ctx.sandboxPolicy` resolves each calling
* session for both enforcing families.
* session for every enforcing capability.
*/
export type Config = LocalConfig
@@ -63,7 +63,6 @@ export class SandboxedFileSystem extends LocalFileSystem {
constructor(ctx: Context, config: Config) {
super(ctx, config)
this.defaultMode = ctx.sandboxPolicy.defaultMode
ctx.sandboxPolicy.registerEnforcedFamily('filesystem')
}
/** The deployment default mode — the capability fact the tool layer reads to advertise escalation. */

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 packages/fs/tool-fs/README.md
README.md: eae4fca7fcb7416a139e17a2ec356b4445ba4fc3
README.zh.md: 8005fc63851ea2373ecd225358694d02cbe9a6ec
README.md: d8d75e251d6b565b402d97eed7bc8b135708e7c5
README.zh.md: 515320ee85219a55904702dfde1777f53f047cd3

View File

@@ -2,7 +2,7 @@
English | [中文](README.zh.md)
The **model-facing filesystem tools** — `read`, `write`, `edit` — and their **executor**. This is the consumer layer of the filesystem stack: it owns tool names, JSON schemas, argument validation, prompt sections, **read windowing**, and result formatting. It reads/writes/edits through the `ctx.fs` provider seam ([`@deepseek-ai/dsh-fs`](../fs)) **directly**. The freshness/observation policy is contributed by a separate plugin ([`@deepseek-ai/dsh-fs-policy`](../fs-policy)) through the `fs/*` event gate; the tool is not method-coupled to it. Under a confining provider, the shared sandbox-policy service is required for per-session execution and the tool registers that filesystem mutations expose escalation.
The **model-facing filesystem tools** — `read`, `write`, `edit` — and their **executor**. This is the consumer layer of the filesystem stack: it owns tool names, JSON schemas, argument validation, prompt sections, **read windowing**, and result formatting. It reads/writes/edits through the `ctx.fs` provider seam ([`@deepseek-ai/dsh-fs`](../fs)) **directly**. The freshness/observation policy is contributed by a separate plugin ([`@deepseek-ai/dsh-fs-policy`](../fs-policy)) through the `fs/*` event gate; the tool is not method-coupled to it. Under a confining provider, the shared sandbox-policy service is required for per-session execution and the tool exposes escalation for filesystem mutations.
```ts ignore-check
// Default deployment: a ctx.fs provider, the policy plugin, then the tools.
@@ -46,7 +46,7 @@ The tools do **not** inject a policy service or inspect any cache. Each tool res
The tool passes `exec` (the tool-execution context) as the opaque `actor` on every dispatch. The default thunks return `undefined` (the unconstrained bare provider). When `@deepseek-ai/dsh-fs-policy` is loaded it occupies the single decision slot — returning `createIfAbsent`/`replaceIfVersion`/`{ version }` or throwing `FS_NOT_OBSERVED` — and records on `fs/observed`. Backend errors (`FsError`) and a thrown `FS_NOT_OBSERVED` flow through `ToolRegistry.execute()` and become `isError` tool results with their `{ name, code }` attached.
When `ctx.fs.sandboxMode` reports confinement, write/edit advertise `sandbox_permissions` and `justification`, resolve approved retries through `ctx.approval`, and register `filesystem` as escalatable with `ctx.sandboxPolicy`. The policy owner therefore adds anti-refusal context only while the real mutation tools offer that path.
When `ctx.fs.sandboxMode` reports confinement, write/edit advertise `sandbox_permissions` and `justification` and resolve approved retries through `ctx.approval`. The policy owner contributes capability-neutral standing policy; the tool results retain operation-specific denial and retry guidance.
## `fs/observed` is fire-and-forget

View File

@@ -2,7 +2,7 @@
[English](README.md) | 中文
**面向模型的文件系统工具**(`read`、`write`、`edit`)及其**执行器**。这是文件系统栈的消费方层:拥有工具名称、JSON Schema、参数校验、提示词段、**读取窗口逻辑**和结果格式化。它**直接**通过 `ctx.fs` 提供方 seam([`@deepseek-ai/dsh-fs`](../fs))读取/写入/编辑。新鲜度/观察策略由独立插件([`@deepseek-ai/dsh-fs-policy`](../fs-policy))通过 `fs/*` 事件门禁贡献;工具不与其方法耦合。使用施加沙箱限制的提供方时,逐会话执行需要共享沙箱策略服务,工具还会登记文件系统变更具备升权路径。
**面向模型的文件系统工具**(`read`、`write`、`edit`)及其**执行器**。这是文件系统栈的消费方层:拥有工具名称、JSON Schema、参数校验、提示词段、**读取窗口逻辑**和结果格式化。它**直接**通过 `ctx.fs` 提供方 seam([`@deepseek-ai/dsh-fs`](../fs))读取/写入/编辑。新鲜度/观察策略由独立插件([`@deepseek-ai/dsh-fs-policy`](../fs-policy))通过 `fs/*` 事件门禁贡献;工具不与其方法耦合。使用施加沙箱限制的提供方时,逐会话执行需要共享沙箱策略服务,工具还会为文件系统变更提供升权路径。
```ts ignore-check
// Default deployment: a ctx.fs provider, the policy plugin, then the tools.
@@ -46,7 +46,7 @@ await ctx.plugin(ToolFs) // this package — re
工具在每次分派中把 `exec`(工具执行上下文)作为不透明 `actor` 传入。默认 thunk 返回 `undefined`(不受约束的裸提供方)。加载 `@deepseek-ai/dsh-fs-policy` 后,它会占用单个决策槽:返回 `createIfAbsent`/`replaceIfVersion`/`{ version }` 或抛出 `FS_NOT_OBSERVED`,并在 `fs/observed` 时记录。后端错误(`FsError`)和抛出的 `FS_NOT_OBSERVED` 会流经 `ToolRegistry.execute()`,变成 `isError` 工具结果,并附带 `{ name, code }`。
当 `ctx.fs.sandboxMode` 表明提供方施加沙箱限制时,write/edit 会公开 `sandbox_permissions` 与 `justification`,通过 `ctx.approval` 解析经批准的重试,并将 `filesystem` 家族注册到 `ctx.sandboxPolicy`,标记为可升权。因此,策略归属方只会在实际变更工具提供该路径时添加反预防性拒绝上下文。
当 `ctx.fs.sandboxMode` 表明提供方施加沙箱限制时,write/edit 会公开 `sandbox_permissions` 与 `justification`,并通过 `ctx.approval` 解析经批准的重试。策略归属方会贡献与具体能力无关的常驻策略;工具结果仍保留操作特定的拒绝与重试引导。
## `fs/observed` 发后即忘

View File

@@ -67,7 +67,6 @@ export function apply(ctx: Context, config: Config): void {
// per-call policy resolution, and denial-marker mapping, all keyed off whether
// the mounted ctx.fs confines (ctx.fs.sandboxMode).
const sandbox = new FsSandboxSurface(ctx)
if (sandbox.escalationModes.length > 0) ctx.get('sandboxPolicy')?.registerEscalatableFamily('filesystem')
applyWriteTool(ctx, sandbox)
applyEditTool(ctx, sandbox)
}