Files
ycode/docs/协作/B03-需求.md
T

8.0 KiB
Raw Blame History

B03:完全访问下普通命令仍触发授权

日期:2026-10-21(Asia/Shanghai)。状态:待开发,P1。用户在 YCode 新建对话并预选“允许完全访问”,要求启动 dev,仍反复收到命令授权。当前验收端只读定位,不修改用户会话、策略或产品代码。

1. 真实会话证据

按用户要求,只读检查该条新会话及对应本地 SDK transcript,得到:

  • 会话保存权限为 full-access,对话模式为 craft。
  • 同一真实 SDK 会话记录的权限模式只有 acceptEdits。
  • 初次检查已出现 4 次 Bash 授权;检查期间会话继续运行,最终脱敏快照保留 7 条审批:6 条 Bash、1 条 PowerShell,均已回答。初次分析涉及查找项目目录、读取 memory/配置等命令;不是冻结会话后统计全部生命周期。
  • 快照中的七条持久化请求均为 requestKind: permission,没有 rule,并不是界面明确显示的规则命中记录。
  • 普通的部分命令已执行成功;不能把本例描述成“完全访问字段完全没传”或“所有命令都无法执行”。
  • 原始 callback 的 classifier、decisionReasonType/Code 等字段未持久化,现有记录不足以唯一证明每次具体命中了哪项分支。描述性的 reason 不能代替权限判定来源。

脱敏权限摘要只保留模式、审批数量及种类,没有提交原始会话、SDK transcript、命令、用户路径、凭据或会话标识。不要求另一台电脑取得真实用户数据才能继续开发。

用户当前可见窗口来自 b01-accept-01 检出的 1ed71b6,不是上一轮预览 0fbc161 所在的专用目录。该信息用于辨别窗口,不能用来排除本问题:1ed71b6 到当前 gitea/master@f512a0f 的本问题权限内核/发送/factory 文件没有差异。不要为验证版本而中断用户仍在运行的会话。

2. 代码路径与已证事实

以下针对已知产品代码 0fbc161,权限相关文件与受测旧窗口相同:

  1. src/main/agent/claude/claude-kernel.ts:259 的 permissionModeFor 将 craft+full-access 映射为 SDK acceptEdits。
  2. ensureStarted 把该模式传给 query,setPolicy 也复用此映射;本地 SDK 类型注释明确 acceptEdits 自动接受编辑,不等同于跳过命令权限检查。
  3. canUseTool 的 full-access 自动放行仍受 !mustAskInFullAccess(options) 限制。
  4. mustAskInFullAccess 除真实 matchedAskRule 外,还把 classifier false、subcommandResults、某些 safetyCheck、requiresUserInteraction 和任意非空 decisionReasonCode 都视为必须询问。
  5. 非 matchedAskRule 分支发出的卡片仍标成普通 permission;当前持久记录无法辨别具体 SDK 判定来源,导致“为何完全访问仍询问”难以复盘。

判断:本例是“完全访问与 SDK/宿主命令审批策略不一致”的已证用户问题,不能再作为单纯权限保存或新任务首发字段遗漏处理。过宽的 must-ask 条件具有离线可复现证据;真实回调的具体字段仍未知,不能断言一定都是 subcommandResults。

独立离线反例

脚本直接调用当前真实 ClaudeKernel.canUseTool,固定 craft+full-access,只替换 Electron 与 SDK query;query 被设置成一旦调用立即抛错,没有启动 SDK/CLI、模型或真实命令。

构造的 callback 元数据 宿主 approval 调用次数 最终 requestKind
无附加判定字段 0 无
classifierApprovable:false 1 permission
decisionReasonType:subcommandResults 1 permission
非空 decisionReasonCode 1 permission
明确 matchedAskRule 1 rule-intercept

输出。这些元数据是合成输入,不是用户真实 callback 的还原。脚本退出 0 表示探针执行成功,不表示产品通过验收。approval 夹具选择允许一次,因此最终 behavior 为 allow;问题体现在用户仍需回答一次授权。

重跑:在包含对应产品代码和现有项目依赖的检出中,将脚本复制为 .tmp/full-access-review/policy-repro.mjs,先创建其目录,再执行 node .tmp/full-access-review/policy-repro.mjs。它只写 .tmp 及自己的系统临时目录,不读取真实会话。

3. YC-007:修复完全访问的执行语义

边界:Claude 内核权限模式与 callback、发送/切换策略的必要接线、诊断字段、相关 policy 与真实 SDK/CLI 集成回归。界面标签已经保存为 full-access,不要用只改标签来修复,也不重做模型注册或技能市场。

验收标准

  • AC7.1:新建 craft 会话,首发前选择完全访问;普通目录读取、简单命令、由读取/echo/管道组成的复合命令,在专用测试目录中执行,不再因通用审批分类重复要求授权。覆盖原生 Bash、PowerShell 的第一轮及后续轮次,不能只验证一类命令工具。
  • AC7.2:检查 SDK 模式选择与宿主自动放行整体设计。区分“SDK 未预批准/等待宿主决定”与“确有用户规则要求询问”等不同来源;不要把任意非空原因码或分类器结果一律升级为人工授权。
  • AC7.3:有真实显式询问/拒绝规则时,按既定规则语义处理并展示真实原因;不能编造命中规则。plan/ask 模式限制继续生效,不能因保存偏好为 full-access 而绕过模式限制。
  • AC7.4:对缺失/未知 SDK 判定字段给出明确、经测试的策略,保持本地实际 SDK 类型与真实 callback 一致。不能只拿合成字段测试变绿就宣称完整修复。
  • AC7.5:请求开始前选项、持久化、实际 SDK 模式与宿主策略一致;切换权限、切换模式再返回、客户端重启、内核重建分别覆盖。普通默认权限仍按预期询问,不被本例修复整体放开。
  • AC7.6:把“完全访问下的自动执行”和“本次会话内始终允许”的 grant 生命周期分别验证。不得靠自动写入全工具白名单、篡改用户设置或静默模拟点击允许来修复。
  • AC7.7:增加最小脱敏判定记录:有效宿主权限/agentMode、SDK 模式、toolCall 关联、判定类别/代码、是否真实 matchedAskRule 及最终触发审批分支。不要保存整个请求/环境、敏感命令参数或认证信息;没有数据时明确未知。

采用 SDK bypass 模式还是保留宿主 gate,由开发主对话在真实 SDK 测试后决定。不要仅把 acceptEdits 字符串替换为 bypassPermissions,或直接删除 mustAskInFullAccess,就认为显式规则与模式边界仍正确。

4. 验证与交付

  1. 先复核目标 SDK 版本和真实 callback 字段;已有日志不足时在隔离回环环境补证,不修改用户正在运行的会话。
  2. 真实本地 SDK/CLI+可控 loopback 模型,独立 userData/workspace,发出简单与复合无害命令;记录 approval callback 次数及实际工具结果。普通 full-access 应为 0 次人工审批,默认权限与显式规则场景应有各自明确预期。
  3. 执行 policy 回归、npm run test:alignment、相关发送/会话回归和 npm run build;覆盖默认权限、full-access、plan、ask、切换与重建。新测试须同时覆盖 query 初始权限模式和 canUseTool,不能只测其中一层。
  4. 用户真实会话中出现该问题是已证事实;确切 SDK 判定字段未知仍需记录。没有真实 callback/执行证据时,交付“已实现、待真实 SDK 验证”,不写全量通过。
  5. 创建 docs/协作/B03-交付-01.md 接单、记录完整代码 SHA、逐条 AC、测试与证据,并指明仍未知的规则/原版语义。原版 WorkBuddy 等价性如需取证,仍只允许 REA。

本需求推送后窗口交回开发端。验收端继续只读验证与规划;B01/B02 既有修复不在此处改写为已通过。