Skip to content

refactor(permissions): separate tool policy from approval decisions - #2140

Open
new-Beginner wants to merge 3 commits into
vastsa:mainfrom
new-Beginner:refactor/goal-permission-policy-9ba23a
Open

new-Beginner wants to merge 3 commits into
vastsa:mainfrom
new-Beginner:refactor/goal-permission-policy-9ba23a

Conversation

@new-Beginner

@new-Beginner new-Beginner commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary / 概要

按 #1999 的维护者拆分意见,先独立审阅工具权限边界和设计,再审阅持久化 Goal 功能。本 PR 是 A:行为保持的权限基础,不提前启用自主 Goal;原 #1999 保持打开、head 不变。

  • Host 内部 ToolPermissionPolicy::{Agent, Contract} 区分工具可用性、审批和执行权。类型不进入模型参数、IPC/RPC 或持久化数据。
  • 两个生产入口仍从 Host 持久模式选择 legacy 策略:Plan 与旧 Goal 均保持 Contract 硬拒绝。Auto、session grants 和 scratch 例外不能越过它。
  • Ask / Accept edits / Auto、风险分类、外部路径校验、原生 scope grant、插件沙箱和 plan-safe action 执行约束不变。
  • 新 ADR 明确后续 Goal 的激活条件:真实执行模式、当前绑定和生命周期必须先经过 Host 校验;选择 Agent 工具策略不等于授予 Auto 或把 Goal 改名为 Agent。
  • 没有 Goal 表、迁移、自动续跑、启动/恢复入口或 UI。8 个文件,+313 / -42。

建议审阅顺序

  1. permissions/tool_policy.rs:原有 allowlist 与插件例外的唯一实现。
  2. permissions.rs:membership deny 保持在风险、审批、授权缓存和 scratch 之前。
  3. rpc/mod.rs:选择来自 Host,而非调用方声称的模式。
  4. docs/adr/goal-execution-permission-policy.md:独立基础与后续激活的安全条件。

第二份功能分支 feat/goal-runtime-clean-9ba23a 依赖本提交;请先审阅这里的权限设计。这里只建立边界,不主张自主 Goal 已获得设计批准。

Verification / 实际验证

基线 main:078bc3061953a6f50eef0b4151e80207313c5e97。
候选:9320826b68462a500c3897c4ab4c6ff458b7d454。

  • 改前:23 项权限测试和旧 Goal 原生 RPC 硬拒绝测试通过;改后:26 项权限测试及同一 RPC 用户路径通过。
  • 新差分矩阵覆盖 Agent / Plan / Goal / legacy、13 种工具和缺省/空/非空插件 action;另验证 Agent membership 不绕过 Ask 和外部路径审批。
  • 真实隔离 Host:Agent Auto Write 创建文件,Plan/旧 Goal Auto Write 不创建文件;伪造 caller mode 不能选策略。零模型请求。
  • Rust fmt、build、all-target Clippy;Host Runtime TypeScript 构建;架构、policy、差异及脚本 lint 检查通过。Clippy 保留主干 5 条未修改告警。
  • 文档结构 616 页、89 对中英文检查及完整 VitePress 站点构建通过。
  • 未运行完整平台/全仓测试、付费模型、发布安装或 verify:ui:*。新 PR 的远程 checks 以 GitHub 当前 head 为准,不沿用 feat(goal): add durable autonomous goals with attached controls #1999 的绿色状态。

Requirement link / 需求关联

Refs #1995

后续依赖功能 PR:https://github.com/vastsa/PI-Desktop/pull/2141。B 的主 diff 包含本基础提交;请先审核 A,B 提供仅功能提交的对照链接。

Make Host tool membership an explicit internal policy so the Goal
authorization design can be reviewed independently of storage and UI.
Preserve the legacy Plan and Goal deny path until its Host producers
are supplied by the dependent feature.

Keep risk, approval, path and tool-specific execution guards unchanged;
cover the existing policy matrix and native Goal refusal.

Refs vastsa#1995
Keep the policy extraction behavior unchanged while retaining the newer\nsteering and background-job documentation. Point the existing compaction\ncontract test at the extracted allowlist instead of its former module.

Refs vastsa#1995
Validate the existing policy boundary against the current remote base.
@new-Beginner

Copy link
Copy Markdown
Contributor Author

Minimal CI/conflict repair

Head: 253af7c5fddb1187e9ca97ad0930cfe2a8e5428e. GitHub integration candidate: 60d5c091bc0035e00e90d9ed365a301becd7b81e; tree b212e1dea2649e86046793efcc3b17a891333a94.

Cause and exact change

The sole failing test in original CI job 127795077615 was context-compaction.test.mjs, “the hard boundary is enforced by the host, with a model-side escape hatch”. It searched permissions.rs for "new_context", although this PR moved the allowlist into permissions/tool_policy.rs. Change only its source-read path; retain every assertion. Local reproduction: 1 failure / 13 tests before the fix, then 13/13 passing.

Conflict files (2)

  • docs/adr/README.md: keep main's steering ADR and this PR's permission-policy ADR.
  • docs/spec/06-delivery/04-e2e-test-plan.md: keep main's background-job and subsequent DashScope scenarios plus the permission foundation scenario.

The foundation implementation is unchanged: both Plan and legacy Goal still use Contract membership. No Goal lifecycle, schema or UI is activated here. The additional authored source change beyond conflict integration is the one-line test read path.

Verification actually run

  • node --test apps/desktop/test/context-compaction.test.mjs: 13 passed at the final commit.
  • Native permission tests: 26 passed; goal_authorization_reuses_the_durable_contract_mode_hard_deny: 1 passed, using a freshly compiled and identified A test executable.
  • Agent runtime full suite: 1782 passed, 1 existing skip.
  • All TS package builds and desktop typecheck; Electron production build; configured repository lint; architecture, style-token, agent-policy, Pi patch and PR-base guards: passed.
  • cargo fmt --check; cargo clippy -p host-core --all-targets --locked: passed (5 pre-existing warnings, not changed).
  • Documentation structure: 619 pages; locale check: 89 pairs; full VitePress build: passed.
  • PI_HOST_CORE_BINARY=<A-host> node scripts/e2e-goal-permission-policy.mjs: passed at the final commit, actual Agent Write/Plan and legacy Goal denial/caller-mode spoofing, 0 model requests.

No refactor, new capability, permission relaxation, timeout/tolerance increase, assertion removal, dependency downgrade, force-push, or merge to main. Existing published heads remain ancestors. PR #1999 and the primary checkout were not modified. B still depends on A; the repaired A head is an ancestor of B.

Both candidates contain base fb4816bca4e9e01140f6b0b78faee6c7a9561910. GitHub merge-ref trees were fetched and verified equal to the locally tested candidate trees. Explicit test profiles, loopback model fixtures, task caches and evidence were directed to task scratch. No paid provider or daily application instance was used.

Current repaired-head CI (snapshot at posting)

  • Docs checks: success
  • Rust host-core format / lint / test: success
  • Rust host-core Windows / transcript cache E2E: success
  • JS build / typecheck / lint / architecture / test: success
  • Trusted extensions Electron E2E: success
  • Head contains latest base: success

Pending checks are not claimed as passing. This comment does not request automatic merge.

@new-Beginner

Copy link
Copy Markdown
Contributor Author

@Tioit-Wang 回应你在 #1999 原始审阅意见 中提出的「权限变化夹在大改动中,实际上无法独立审阅」问题:这份 A 先把权限设计和行为保持的基础单独交出来。

  • 单独合入 A 不会放开 Goal。 Plan 和旧 Goal 仍选择 Contract 策略,Write/Edit 等原有硬拒绝保留;Auto、会话授权缓存和 scratch 例外不能越过它。
  • 区分的是「工具可用性」「是否需要审批」「当前执行是否有权工作」三个层次。内部策略类型不进入模型参数、IPC/RPC 或数据库;Ask/Accept edits/Auto、外部路径审批和插件沙箱边界不变。这里没有 Goal 存储、迁移、续跑或 UI。
  • 设计记录 已列出替代方案及后续启用条件:自动执行必须由 Host 校验实际执行模式、Goal 绑定及生命周期,不能仅凭输入框模式或调用方声称的 goal 取得权限。
  • 真实的 Goal→Agent 工具策略启用仍在依赖 PR feat(goal): integrate durable goals after permission policy review #2141。 它依赖 B 提供上述可信执行接线,所以 A 只做无行为变化的基础,不能把批准 A 当成已批准 B 的权限行为变化。B 中这部分仍需要你明确审阅;不是将它作为普通重构或存储改动默认带过。

当前 head 253af7c5f 的六项 checks 均通过,权限矩阵和真实 Host 的旧 Goal 拒绝路径也已验证。测试证据用于证明边界,没有替代权限设计审阅;请先审阅这里的设计与拒绝顺序,再审阅 #2141 的实际启用接线。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant