Parent
方案基线
jinjunnn/alpha-code#724 的 CLOSE_DECIDE §9 第 2 条 + §6 的 E1–E7 表。本票正文逐字取自该基线,未新增任何 AC 或准入条件。
依赖
jinjunnn/alpha-code#1128(CODE#1)先落地 —— 本票执行的是它提供的同一个 resolver,不自建第二套。
负责(基线原文)
V1 catalog + E1–E6;E7/internal 排除 ratchet;dynamic inventory/API;stale/direct call 运行时重读。
边界(基线原文)
session/tools.ts、session/llm/request.ts、tool/code-mode.ts、session/llm.ts、session/prompt.ts 及窄测。
Out of scope(基线原文)
不切 V1↔V2、不替换现有 ability/sovereignty 闸。
退出条件(基线原文)
disabled 双闸、ask-before-hook/side-effect、enabled 保留能力闸;bin/check 绿。
已实测的用户可观察缺陷(本票落地即应消失)
jinjunnn/alpha-code#1121(P1)—— #725 双咽喉取证量到,判据全部驱动生产入口 SessionTools.resolve() 返回对象的 .execute(),副作用用真实计数(不是「抛没抛异常」):
| 判据 |
identity 规则 |
期望 |
实测 |
| B3 |
builtin::write = deny |
拒绝,文件不落盘 |
文件真的写出来了 |
| B10 |
builtin::write = ask |
先请求批准 |
不问,直接落盘 |
| B2 |
plugin:probe:default = deny |
拒绝,marker 不落盘 |
插件工具照跑 |
用户可达路径已用真 opencode.json + 真 Config + 真 Agent.Service 量到 —— v1/config/permission.ts:18-36 的 InputObject 接受任意键,所以用户写得出这条规则,而它在执行面无声无效。
最要紧的一句:用户把某个内置/插件/宿主工具设成「询问」,它照跑不误、不弹窗。
#725 同时量到的对照(说明缺口精确在哪)
- 咽喉 A(模型目录)=
LLMRequestPrep.prepare() 返回的 tools —— 真绿。四来源 identity deny 都真把工具拿掉且只拿掉它自己;摘掉 permission/index.ts:300-304 的 identity hard-deny 分支 ⇒ A1–A4 当场翻红。
- 咽喉 B(执行)=
SessionTools.resolve() 返回对象的 .execute() —— 只对 MCP 成立。摘掉 session/tools.ts:437-442 的 ctx.ask({permission: canonicalToolIdentity(...)}) ⇒ B1/B5/B7/B8 当场翻红,全部 A 判据不动。
⇒ 缺口 = builtin / plugin / 宿主 MCP-resource 工具完全不接 identity 轴。
⚠️ #1121 不要单独打补丁。 基线 §10 明写「不另造第二个审批引擎 / 第二张 identity 映射」;症状级修复会撞上这条。
基线 §6 里已点名、本票必须逐个处理的接缝
| 接缝 |
基线要求 |
E4 Code Mode child(tool/code-mode.ts:136-190) |
子工具不走 register wrapper;在 hook(:143-147)之前用同一 resolver/ask,disabled child 也不进 child catalog(:211-215) |
E5 workflow executor(session/llm.ts:127-163) |
preapproved 列表只收 effective enabled,ask/disabled 均不得预批;executor 仍二次重读 |
E6 direct subtask(session/prompt.ts:263-397) |
绕过 SessionTools;在 plugin hook、subsession/Task execute 副作用前单独用相同 resolver。现有 :284-288 只完成 deny,不足以实现 ask |
E7 attachment ingestion(prompt.ts:830-849) |
明确排除,保留 ask:()=>Effect.void 并以 #731 I6 负向测试锁死 |
| internal sentinel |
host::StructuredOutput 与 _noop 按窄例外锁死,不进 Settings |
#725 的记录:E4 / E6 / E7 本轮只有源码级确认,没在运行期量到(E4 因探针把 experimentalCodeMode 钉成 false;E6 要起整回合;E7 的「显式排除」今天没有锁死断言)。本票落地后由 VERIFY 补运行期证据。
复杂度
M(基线已定方案,接缝逐个指名到 file:line)。
Parent
方案基线
jinjunnn/alpha-code#724的 CLOSE_DECIDE §9 第 2 条 + §6 的 E1–E7 表。本票正文逐字取自该基线,未新增任何 AC 或准入条件。依赖
jinjunnn/alpha-code#1128(CODE#1)先落地 —— 本票执行的是它提供的同一个 resolver,不自建第二套。负责(基线原文)
V1 catalog + E1–E6;E7/internal 排除 ratchet;dynamic inventory/API;stale/direct call 运行时重读。
边界(基线原文)
session/tools.ts、session/llm/request.ts、tool/code-mode.ts、session/llm.ts、session/prompt.ts及窄测。Out of scope(基线原文)
不切 V1↔V2、不替换现有 ability/sovereignty 闸。
退出条件(基线原文)
disabled 双闸、ask-before-hook/side-effect、enabled 保留能力闸;
bin/check绿。已实测的用户可观察缺陷(本票落地即应消失)
jinjunnn/alpha-code#1121(P1)——#725双咽喉取证量到,判据全部驱动生产入口SessionTools.resolve()返回对象的.execute(),副作用用真实计数(不是「抛没抛异常」):builtin::write=denybuiltin::write=askplugin:probe:default=deny用户可达路径已用真
opencode.json+ 真Config+ 真Agent.Service量到 ——v1/config/permission.ts:18-36的 InputObject 接受任意键,所以用户写得出这条规则,而它在执行面无声无效。最要紧的一句:用户把某个内置/插件/宿主工具设成「询问」,它照跑不误、不弹窗。
#725同时量到的对照(说明缺口精确在哪)LLMRequestPrep.prepare()返回的tools—— 真绿。四来源 identitydeny都真把工具拿掉且只拿掉它自己;摘掉permission/index.ts:300-304的 identity hard-deny 分支 ⇒ A1–A4 当场翻红。SessionTools.resolve()返回对象的.execute()—— 只对 MCP 成立。摘掉session/tools.ts:437-442的ctx.ask({permission: canonicalToolIdentity(...)})⇒ B1/B5/B7/B8 当场翻红,全部 A 判据不动。⇒ 缺口 = builtin / plugin / 宿主 MCP-resource 工具完全不接 identity 轴。
#1121不要单独打补丁。 基线 §10 明写「不另造第二个审批引擎 / 第二张 identity 映射」;症状级修复会撞上这条。基线 §6 里已点名、本票必须逐个处理的接缝
tool/code-mode.ts:136-190):143-147)之前用同一 resolver/ask,disabled child 也不进 child catalog(:211-215)session/llm.ts:127-163)session/prompt.ts:263-397):284-288只完成 deny,不足以实现 askprompt.ts:830-849)ask:()=>Effect.void并以#731I6 负向测试锁死host::StructuredOutput与_noop按窄例外锁死,不进 Settings#725的记录:E4 / E6 / E7 本轮只有源码级确认,没在运行期量到(E4 因探针把experimentalCodeMode钉成 false;E6 要起整回合;E7 的「显式排除」今天没有锁死断言)。本票落地后由 VERIFY 补运行期证据。复杂度
M(基线已定方案,接缝逐个指名到
file:line)。