Repository navigation
Conversation
e06b740 to
e9e5037
Compare
asto18089
left a comment
There was a problem hiding this comment.
Round-1 fresh review(8 车道全量重审 + 逐条人工复核)
结论:REQUEST CHANGES — 2 BLOCKER + 4 MAJOR。 PR 本身真实有用(S-1 落地、tri-mode 三态 + 审批面 + 规则档 + 底座 #131 集成),无夹带、登记扎实、新测试质量高;但两个 BLOCKER 都打在本 PR 自己的核心安全声明上,必须先修。
前置核验
- 分支已基于最新
origin/main:merge-base =3cec34e2b= 远端 main 头(API 通道确认),无需 rebase。 - 远端头
e9e5037b5树 = 本地 twin 树2b7927c18(字节一致);gitlink41eab46f2== CW#131 当前头(#131 未动,消费关系成立)。 - 本机门禁全绿:
cargo test --locked --lib -- --test-threads=13788/0;前端npm run test+lint绿;cargo check --all-targets --features benchmark-hooks绿;fork-guard.sh --fast268 指纹全过(唯一红 = Layer 0 twin-SHA 化妆红,登记已披露)。head 无 CI check run(仓库 Actions 静默),本地电池即机器验证。 - 审查方式:8 条独立车道(审批面 / 模式状态机 / 规则档 / 发送线+平台 / 前端 / 测试质量 / 文档+登记+夹带审计 / 底座 #131 集成)+ 对每个 B/M 级 finding 的逐行人工复核。8729/3521 规则计数经独立重实现复核为真。
BLOCKER
B1 — 授予/拒绝缓存读路径跨会话泄漏(process 级越权放行)
pending_approvals.rs:160-163:session_granted(grouping_key) / session_denied(approval_key) 只做 contains_key,不带 session 维度;而数据结构本身是 HashMap<key, HashSet<session_id>>(clear_session 也只摘自己的份额)——设计是会话级的,读路径把维度丢了。唯一调用方 forwarder.rs:892-897 明明手里有 session_id(上一行刚 store.mode_state(&session_id))。
后果:同进程内会话 A 点了「本会话允许 cargo build」,会话 B 的同族调用(含 bash -c <任意载荷> 这类 wrapper 兜底 key)直接 ApproveSilently 静默执行,无人出卡;拒绝缓存同样跨会话连坐。与 PR 声明「会话授权/拒绝记忆」直接矛盾,forkguard_approval_surface_grant_and_denial_scoping 测试因同一 API 缺口而咬不到。
修复:两个查询加 session_id 参数,map.get(key).is_some_and(|s| s.contains(sid)),并补跨会话负测试。
B2 — 首次 Plan 写入铸造 Yolo 哨兵,「批准方案≠批准全自动」在主路径上为假
mode_state.rs:385-405:set_mode_in_memory 对新条目 or_insert_with(default_for_new_session)——其 mode 仍是历史 Default::default() 的 Yolo(mode_state.rs:130-134,注释自认「keeps the historical Default mode」);紧接着 pre_plan_mode = Some(entry.mode) 记下的是这个从未真实生效过的 Yolo。claim_pending_plan(mode_state.rs:623-627)accept 时 pre_plan_mode.unwrap_or(Auto) → Yolo,并经 persist_accepted_yolo_mode 持久化。
触发:新建未绑定会话(chip 显示 Auto)→ 首次模式动作点 Plan(GUI 芯片 set_plan_mode_next 即此路径;work 车道默认 plan 的用户在 sessions.js:661-668 物化时也自动走这条路)→ 方案批准 → 会话静默进入持久化全自动驾驶 Yolo。这正是 PR 标题级声明「批准方案≠批准全自动」要消灭的行为。同时测试套件自相矛盾:旧测试 pending_plan_ticket_...(tests.rs:3934,本 PR 未动)把 Yolo 结果钉成预期,新测试 code_session_accepted_yolo_persists...(tests.rs:4870)走 register_pending_plan 铸造路径(resolved default,无 pre_plan_mode)钉 Auto——两个都绿,掩盖了缺陷。
修复:set_mode_in_memory 铸造时用 resolved_default_mode(id)(与全仓其余铸造点一致),或在 mint 当拍用 resolved 值记 pre_plan_mode;同 PR 内对账两处矛盾测试。注:相对 main 非回归(旧版 accept 本就落 Yolo),但对本 PR 的核心新契约是假话,故 BLOCKER。
MAJOR
M1 — 「守卫命中时询问」开关对未物化会话静默空转 + UI 回弹
mode_state.rs:1300-1303:无 mode entry 时 None => return Ok(())——不落 sidecar、不铸条目、不报错。而 composer-controls.jsx:325 恰好在 Auto/Yolo(= 所有从未切过模式的会话,即新会话的默认态)显示这个开关;前端乐观翻转 → 命令 Ok → applyAuthoritativeModeState 用全局默认写回 → 开关弹回,无任何错误提示(interaction.js:465-492)。用户的安全选择被静默丢弃。
修复:铸造 toggle-only 记录(不钉 mode)或显式报错;§9 已知边界未披露此行为。
M2 — Auto→Yolo 芯片切换在双车道都是静默 no-op
ChatView.jsx:2996:if (target !== 'yolo' || !isPlan) return;——!isPlan 分支在双态时代是死代码,tri-mode 加了 Auto 后变成可达的吞没点:Auto 态点 Yolo 什么都不发生。CodexAcpView.jsx:1755-1770 performNativeModeSwitch 三个分支 (plan&&!isPlan)/(yolo&&isPlan)/(auto) 同样漏掉 yolo&&!isPlan。用户从 Auto 回全自动驾驶只有绕道 Plan 一条路;新测试钉了 gate 顺序但恰好没测 auto→yolo。
修复:yolo && !isPlan 走同一确认门 + set_session_mode(sid,'yolo')。
M3 — 「本会话允许」实际只活一个 turn,与声明和 TUI 语义都不符
engine.rs:567-570:emit_chat_terminal(每个 turn 终态都触发)调 clear_session,授予与拒绝一并清空。而 TUI(tui/ui/apply.rs:1311-1312、event_loop.rs:2788-2789)只在换会话/换工作区/session-id 分叉时清,跨 turn 保留;clear_session 的 doc 却声称「语义与 TUI 的 per-session 审批缓存一致」。用户点「本会话允许」,下个 turn 同族调用重新出卡——按钮实为「本 turn 允许」。方向 fail-safe,但声明为假。
修复:把授予/拒绝清扫从 turn 终态挪到会话删除(lib.rs:1405-1409 已有);或将声明/文案改口径为 per-turn。
M4 — work 车道默认值三方契约互相矛盾(draft 显示 Yolo、落地跑 Auto)
mode_state.rs:319-326 后端把未绑定普通会话硬编码 Auto,注释称「frontend applies the work lane's global default at session materialization」;sessions.js:651-668 却只在 laneDefault === "plan" 时套用,注释称「the backend's plain default is always Yolo」——两边注释各指一个不存在的对方。结果:(a) bridge.js:1225-1232 未绑定 draft 兜底显示 YOLO,物化后实际跑 Auto,芯片当着用户面翻转;(b) 用户显式把 work 默认设为 yolo(set_mode_default 仍接受)→ 物化时被静默丢弃。docs/safety-modes.md §6 写的正是后端注释那个承诺。
修复:物化时对 auto/yolo 一并套用 lane 默认(或删掉 work-lane yolo/auto 选项并改文档),同步 draft 兜底与双侧注释。
MINOR(建议同 PR 修或入 §9 披露)
decide_approval先摘登记后校验 decision 字符串(interaction.rs:538vs556-560):非法 decision → 卡没了、engine 悬挂等待。先校验再摘。- 授予缓存写入先于 engine 调用确认(
interaction.rs:547-554):approve_tool_call失败时授予已生效。后置。 - 会话授予命中先于 Plan 防御臂(
pending_approvals.rs:248-256):turn 中切 Plan 后同族调用仍被旧授予静默放行;deny-under-Plan 更严且零成本。 set_plan_mode_next/exit_plan_to_yolo未过ensure_mode_target_session门(interaction.rs:111-138):远程可达,可为任意 id 铸条目 + 落 sidecar(ghost 条目)。_ask_on_guardrail.jsonboot 合并只对已存在条目生效(mode_state.rs:1339-1355):由 persona/mount/pending-plan 写入 toggle 后重启、无 mode 记录 → 显式覆盖被永久忽略。- 会话删除/驱逐不清
_ask_on_guardrail.json(retention.rs:664-730只清另两个 sidecar):死条目累积 + id 复用继承风险。 - 旧二进制对新格式
_session_mode_states.json的第二次写会整体隔离并从空表重建(sidecars.rs:222-280):同PINVOU3_HOME下旧 headless 双写丢失其他会话持久 mode。读路径声明属实,写路径不成立。 - engine 同步失败时 store 已切+已持久化、无事件(
interaction.rs:592-601):远端客户端滞留旧模式直至下次get_mode_state。 - Floor 在 Windows 拼写下保留敏感凭据面(
safety_deny_rules.rs:2028-2041):win_real_home_rules整族进 Floor,C:\Users\me\.ssh\id_rsa直传面在 Yolo 下仍机械拦截(over-block,fail-safe);建议族拆分或登记理由。 safety_deny_rules.rs:118-151v3 posture doc 仍断言「approval 硬连全自动驾驶」「每平台 DangerFullAccess」——S-1 之后两者皆假,审计源文档需更新;session_policy.rs:171-173静态approval_params已无生产调用者,考虑删除。- 测试注:
forkguard_ruleset_profile_floor_count_is_pinneddoc 指docs/fork-modifications.md有 3,521,实际在docs/safety-modes.md;session_mode_write_paths_publish...是源码扫描非行为测试(诚实标注,勿当行为证明);L1 harness 无 Auto/审批卡场景。 - 中间提交卫生:
848697a7c曾把三个权限变更命令注册进 web RPC 而 denylist 在790f90b2d才补上(PR 内已闭、已披露;bisect/单独 cherry-pick 特征提交时边界是开的);dae04fe89提交信息写2b8f19c06,实际登记值是41eab46f2。 - 底座(#131 侧,不阻本 PR):
runtime_threads.rsheadless 审批消费者吞掉approval_force_prompt且只看auto_approve——今天不可达(无人从该车道武装),属未来武装者的潜伏陷阱,建议上游跟进。
已验证为真的关键声明
- S-1 逐轮 posture 线(store 权威、无反转、Plan/Benchmark/无人值守各路径)✅;无人值守恒 Full + 确定性处置(
for_engine_lane全链路:spawn/武装/全局刷新/单会话刷新,源码钉 + 行为钉)✅ - 规则档:Full 8,729 / Floor 3,521 独立重算为真、Floor ⊆ Full、无串改写无 Deny→Ask 改标、热换经
SetPermissionRuleset真达活引擎(Arc 共享、子代理继承)✅;性能无回归(构造点仅 spawn/换档,Yolo 面 -2.5×) - sudo 文案四处平台 + anchor 测试与真实布线一致、旧文案零残留 ✅;
chat:guardrail_denied不带敏感入参 ✅;turn_meta authority 行只含模式/芯片/武装词、无泄漏 ✅ - 审批面机制(登记、去重、remount 回放、denylist 在 RPC 漏斗强制执行、定时优先级保留、13 行真值表)✅;登记(EXPECTED_COMMITS=88 算术、14 指纹逐条实存、MAINTENANCE_BASE 语义、zh/en 镜像、漂移数 525/+93293/−39351 复算一致)✅;夹带审计 60 文件逐 hunk 全部服务于特性或其登记 ✅
- 底座集成:ChangeMode 武装字段、armed/unarmed 双路径无悬挂、13 条新 forkguard 钉实存、ACP/无人值守/子代理 fail-closed ✅
- i18n 三语完整、无 userAgent/Tauri 全局直查、web 白名单不越界、vite 预算提升 486k→492k 有实测依据属正当维护 ✅
- 6 个 stale 测试对账属实(但第 7 个
pending_plan_ticket_...漏对账 = B2 的矛盾钉)
合并门槛
B1、B2 必须修复(含测试对账);M1–M4 修复或明确豁免并改文档/文案。其余 MINOR 建议同 PR 处理或入 §9 已知边界。修复后请重跑:cargo test --locked --lib -- --test-threads=1(关注 sessions/pending_approvals/commands 三簇)+ node --test tests/approval_card_lane.test.mjs tests/code_permission_state.test.mjs + ./scripts/fork-guard.sh --fast。
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed exact head 09393c970793734782bad4b09104bdc36f470cf5 against target 3cec34e2b6b7da8fbb85b70050dae83ff8b4ee10, with the candidate CodeWhale gitlink checked out independently. Head and discussion were rechecked before publication.
Standards
[P2] Return the guardrail-toggle persistence error after rollback. pinvou3-app/src-tauri/src/features/sessions/mode_state.rs:1320–1327 restores both in-memory values when _ask_on_guardrail.json cannot be written, but then returns Ok(()). Consequently both toggle IPC paths report success and broadcast the old selection instead of informing the user about a permissions, read-only-storage or disk failure. Preserve the rollback and propagate the error into the existing frontend failure path. This is an error-reporting defect; no authorization bypass is asserted. AGENTS.md requires complete handling of key errors and insufficient permissions.
Nonblocking: newly added Chinese comments/diagnostics conflict with CONTRIBUTING.md's English requirement.
Spec
[P2] The same failed-write path contradicts the documented persistence behavior. docs/safety-modes.md §3.1 justifies logging-only failure by saying the memory change has already taken effect; the implementation explicitly undoes it. Reconcile implementation/documentation and add a failed-write regression.
[P2] Do not reactivate a terminal approval card on a late IPC rejection. pinvou3-app/src/platform/tauri/bridge/interaction.js:525–528 unconditionally restores the pre-submit active/unresolved state. While that request is pending, chat:done can mark the same card cancelled/resolved and clear the backend pending entry; the delayed approval not found rejection then revives the expired card, whose subsequent clicks can only fail. Preserve a terminal state established during the await rather than applying the stale rollback. This conflicts with the requirement that terminal-turn cards remain unclickable. An actual-source VM probe reproduced active/submitting → cancelled/resolved → active/unresolved with a simulated delayed IPC rejection.
Validation: 53 Node tests passed across approval-card, permission-state and multiagent-normalization suites; architecture guard passed. The VM probe covers frontend scheduling, not full-app or Rust execution. Diff whitespace checking also found one trailing-space line in bridge_domain_protocol.test.mjs:242. Cargo was unavailable; no native Rust, live-provider, author test-count or CI-green claim is made.
Standards: 1 required P2. Spec: 2 required P2, including the same persistence defect (2 distinct required corrections total).
asto18089
left a comment
There was a problem hiding this comment.
Round-2 fresh review(14 评审车道 + 6 证伪复核/闭合核验/机器验证车道)
结论:REQUEST CHANGES — 1 BLOCKER + 5 MAJOR。 PR 的真实价值与工程质量维持 round-1 判断:S-1 落地形态正确(姿态从 mode 拆出为 typed 输入、处置收口纯函数 + 真值表、登记指纹全绿)、零夹带(63 文件逐一归桶全部主题内)、round-1 修复 11/13 闭合且带测试钉。但本轮在全新的 14 条车道上暴露出一批 round-1 未覆盖面:默认档切换把 Web 宿主打入审批黑洞(BLOCKER)、fork 登记文档重钉失同步、以及「truthful / 无数据丢失」级声明在本 PR 自己的交付面上三处失真。
前置核验
- 基点
3cec34e2b(PR 首提交父提交);头09393c970,11 提交 63 文件 +4755/−360;gitlink04c1f7843与fork-guard.sh EXPECTED_HEAD一致,实测候选链 89 提交 / 87 签 / 526 files +93516/-39313 / 269 forkguard 名。 - round-1 修复闭合核验:11/13。B1(读路径带 session 维度 + 跨会话负测试
forkguard_approval_surface_grant_and_denial_scoping)、B2(铸造用resolved_default_mode+ 新旧测试对账)、M1(toggle-only 侧车)、M2(双车道 auto→yolo 同门)、M3(清扫挪会话删除)、M4(三档物化 + draft 兜底)、Minor1-5 全闭合;Minor6 部分(代码已修、无 purge 测试);Minor7 未闭合(写入路径丢失未披露)→ 并入本轮 M4。 - 机器验证(本树实测,全绿):前端
npm run test1443 过 / 0 挂(4 个环境条件跳过)、lint绿;bash scripts/fork-guard.sh --fast全绿无任何红项;python3 scripts/architecture-guard.py绿;cargo check --locked绿(6m46s 冷缓存);定向cargo test --lib -- --test-threads=1:forkguard_ruleset_profile6/0、approval10/0。 - 审查方式:14 条独立车道(意图价值 / 审批面 / 模式状态机 / 规则档 / 发送线平台 / 前端 / i18n 文档 / fork 治理 / 底座 #131 消费 / 夹带审计 / 测试质量 / 安全对抗 / 并发生命周期 / Web 远程宿主)全量重审;随后对全部高严重度候选做第二波证伪式复核(专设推翻车道),4 个候选被推翻或降级(见文末存档),未推翻的才列示于下。20 个 subagent,全部结论读码核实。
BLOCKER
BL1 — Web 宿主默认配置下首个请批调用即静默挂死:默认档切换引入的一级行为回归
- 触发面比"守卫命中"宽得多:未绑定普通会话默认档改 Auto(
features/sessions/mode_state.rs:313-325)=(false, Suggest)(session_policy.rs:271-294);Suggest 姿态下任何请批级工具调用都弹卡(底座authority.rs:555-587→ 转发器pending_approvals.rs:297通配臂 ShowCard)——普通 shell 命令即触发,#5185 carve-out 只放行 git 工作树内文件写,shell 不在内。 - Web 卡链路三处全缺:
platform/web/bridge.js全文件 26 个listen(无一监听chat:approval_required/guardrail_denied/mode_changed,grepapproval零命中;web/bridge/domain-adapter.js:153interaction 域无decideApproval/getPendingApprovals/setSessionMode/setAskOnGuardrail/planStuckGoAuto;relay 侧订阅门(remote_control/manager/mod.rs:2681)对未订阅事件只入 journal 不投递。CodexAcpView 的订阅仅 code 视图挂载期间存在且只放行原生 code 会话——chat 视图普通会话的审批卡在任何 Web 视图都不会出现。 - 挂起表现:turn 指示器永久旋转、无任何提示、无 TTL;唯一自救是用户自己点取消或桌面端有人代答。Yolo 档 + 开关默认 ON 时守卫命中同样落 ShowCard 通配臂,同样挂。
- 相对基线是行为回归:基点未绑定普通会话默认 Yolo=(true, Bypass)(
git show 3cec34e2b核验),基线转发器对非定时会话无条件should_approve = true——基线 Web 会话必能跑完,改后默认配置下第一条 shell 命令即挂。Web 是一级发布面(package.json build:web、三个 web 契约测试、test:webui冒烟、remote-control 文档),且违反仓库自身约定(shared/platform.js:44-45allowlist 注释明文"新桌面专属功能必须保持隐藏直到 Web 适配层显式 opt-in";本 PR 未新增任何 capability,chip 新 UI 在 Web 可见可点却无声失效)。 - 修复方向:桌面管道已全通(4 命令在 access-policy 与 scope 表、3 事件在双端 policy +
RUST_FORWARDED_EVENTS),缺口纯在 Web bridge JS 一层——最小闭环 = 3 个 listen + 5 个方法(可镜像桌面 interaction.js 形态),一个纯前端跟进量级。若产品决定缓做审批面,必须做降级:Web 发起的 turn 守卫/请批命中自动拒绝且chat:guardrail_denied可达、或至少给「等待审批」的 turn 状态提示,并用 capability 门控隐藏 Auto 菜单项/开关/审批按钮(unsupported 显式化)。§9 的「Web 收到但不渲染」披露需同步更正(实际是从不订阅、从不收到)。
MAJOR
M1 — fork 登记单一事实源重钉失同步(4 文件 9 行过期)
125fa92b7 重钉 04c1f7843 时只同步了 fork-modifications / fork-guard / safety-modes,漏掉:THIRD_PARTY_NOTICES.md:10(仍写 41eab46f2)、docs/fork-policy.md:3,11,12,14 与 docs/fork-policy.en.md:3,10,11,13(仍写 41eab46f2/88 提交/86 签/525 files +93293/-39351/268 名)。实测 41eab46f2 口径恰为这些陈旧值(证明是漏同步而非笔误),与 fork-modifications(04c1f7843/89/87/526/+93516/269)和 EXPECTED_HEAD/EXPECTED_COMMITS=89 三向矛盾。AGENTS.md 钦定 fork-policy 为单一事实源——按其行事的审计者会钉错候选并吃到红门禁。头提交自称 "reconcile … fork registers" 但只 reconcile 了一半。修复:补一个 docs 收尾提交同步 5 处数字。
M2 — detached 子代理审批卡被父 turn 终态清死(功能性死锁)
子代理审批确实发到父会话宿主事件流(底座 tools/subagent/mod.rs:15083-15139,id agent:{id}:approval:{boot}:{seq};terminal_chrome_enabled 默认 true → 生产多代理会话 parent_can_prompt=true)。turn-owned 子代理在父 turn 终态被取消 token、卡清掉是对的;但 detached=true 的后台 worker 存活跨父 turn(turn_loop.rs:3672-3686 注释自证),其审批 hold 仍在等待,而 emit_chat_terminal → clear_pending(engine.rs:572)无差别清掉该会话全部登记、前端也把卡就地打为 cancelled(chat-events.js:1113-1120)。此后:卡点击恒报 "approval not found"、get_pending_approvals 不再返回、重挂载无回放——worker 无提示死等,直到用户 agent(action=cancel) 或引擎空闲回收。这是本 PR 新审批面自身的功能性死锁(方向 fail-closed)。修复:终态清扫按 id 形状豁免子代理审批(is_child_approval_id),或底座在子代理审批 resolve/cancel 时发宿主可见事件驱动摘除;补「父 turn 完成时 detached 子代理审批挂起」回归测试。
M3 — chat 车道草稿态 Auto 静默 no-op(同根因波及草稿 Auto→Yolo)
bridge/interaction.js:449-453 setSessionMode 开头 if (!sid) return;,无草稿分支——对照同文件 exitPlanToYolo:328 与 setPlanModeNext 都有 setDraftMode 草稿暂存。物化侧三档就绪(sessions.js:635-645 支持 staged auto)但 pendingDraftMode 没有任何能写进 'auto' 的调用路径。净效果:bound 草稿点 Auto 弹层关闭、无变化无提示;同根因下草稿态点 Yolo 也走 setSessionMode(null,'yolo') 同一死路(tri-mode 把草稿默认改 auto 后新暴露)。绑定草稿的 staged Auto 静默丢失 → 物化落到 lane 全局默认(可能是 Yolo)——用户以为逐项审批、实际全自动,恰是本 PR「chip 不再高估自动化」契约的反面。修复:setSessionMode 补草稿分支(if (!sid) { await setDraftMode(mode); return; }),前端测试补钉(当前草稿 Auto 行为零测试)。
M4 — 降级兼容两条数据丢失链,「无数据丢失」声明对写路径不成立
docs/safety-modes.md:220-222 与 core/mode_state.rs:23-25 声明旧二进制读得 "auto" 时「整体回退 boot cache,单轮陈旧、无数据丢失」——读路径属实,写路径不成立,且还有一条更重的链:
- mode 侧车链:旧二进制(基点仅
{Plan, Yolo},git show 3cec34e2b核验)boot 读失败后,任意一次 mode 写经mutate_json_file解析失败 → 隔离整文件 → 下次写从空表重建只写当前条目(基点sidecars.rs:218-241行为原样存在)→ 其余会话持久 mode 永久丢失。 - settings.json 链(更重):草稿态芯片切 Auto 即把
"auto"写进mode_defaults.work/code_permission.last_mode→ 旧二进制UserPrefs::parse_settings_with_state整份from_value失败 → 整份偏好回落默认(语言/主题/已存模型/服务商配置全部丢失呈现)→ 旧二进制任一设置变更以默认值为基础整份不可逆回写(基点prefs/mod.rs:1018-1027, 1260-1285无解析失败拒写门)。
暴露面需混版本共享 PINVOU3_HOME(回退 tag 与 PINVOU3_HOME 重定位都是受支持流程,现实存在)。声明失实 + 数据丢失双重问题。修复:更正两处声明;评估换新文件名(v2)让旧二进制完全不碰 / mode 默认迁出共享 settings.json 字段;至少在 §9 登记降级风险与恢复方法。本轮 fork-guard --fast 全绿说明门禁不覆盖此面,登记是唯一防线。
M5 — sudo 每轮 reminder 对 Yolo 车道系统性失真 + 同会话矛盾教义
Floor 档零 sudo 规则(safety_deny_rules.rs:2040-2042 明示 sudo 块与 persistence 族归敏感族 Full-only,仅 sudoers 写/visudo 留 Floor),但四平台每轮 reminder(linux_permission.rs:39、macos_permission.rs:19、windows_permission.rs:14、os/unsupported.rs:274)仍宣称「命中 Deny 规则默认直接拒绝 / 开启询问时弹卡」——Auto 档为真(deny face 武装转卡),Yolo 档为假(无规则命中、无卡、Bypass 直通);ON 文案的 systemctl enable/crontab -e 例举在 Yolo 下同样落空(仅 visudo 仍拒)。且同会话静态 instruction_block(super_permission.rs:55)明写「YOLO 模式自动放行」——模型每轮收到两份互斥教义,每轮更新的 reminder 权重更高。四平台 anchor 测试把失真文案钉成了契约。这是本 PR 自己交付物(86ae1eadf「make sudo copy truthful」)的残留半臂:静态块改了、每轮 reminder 没跟上。失真方向偏保守(抑制模型用 sudo)故 MAJOR 而非 BLOCKER。修复:super_permission_turn_reminder 按会话车道分岔(或统一补「Yolo 档本开关不构成机械门」限定),四平台 anchor 同步三态。
MINOR(建议同 PR 修或入 §9 披露)
- docs 两处失实:
safety-modes.md:174-175「本 PR 不改 Web RPC 边界」——实际 denylist 11→14 条、scope 表 +4、access-policy +4;:88武装豁免括号「(Full Access / auto-approve)」漏 Ask/Suggest 档,与 §2 表自相矛盾(armed Ask 下 typed deny 可弹卡获批是有意设计且有测试钉,错的是这句)。 - /etc 凭据销毁与写倒挂:Yolo 下
rm /etc/shadow、truncate -s 0 /etc/sudoers无任何门(武装也无卡),而同文件写tee * /etc/sudoersFloor 硬拒;Floor 内部dd of=/etc/shadow拒 /rm通自相矛盾且被测试有意钉死。超级权限开启 + Yolo 时sudo rm /etc/shadow可达真实 root 破坏。 - 销毁面跨拼写族不一致未登记:Windows Yolo 下
rm ~/.ssh/id_rsa(pwsh 合法拼写)直通而del %userprofile%\…等价物被拒——正是 v3.5 在直传面刚消除的性质在销毁面的跨族残留;docs:190-194「一切拼写保持 Floor」实际仅指 Windows 拼写集合。 - denylist 完整性:
set_plan_mode_next、set_mode_default(不在 scope 表 → 连检查都不经过,可翻全局默认影响未来会话)缺席多代理 Web denylist;aux-前缀早退豁免全部条目(已文档化、影响低)。 - 授权记忆与工作区脱钩:
rebind_workspace_root全程不触pending_approvals,无 cwd operand 的 shell 族 key 不绑根(approval_cache.rs:145-152)——换根后旧授予继续静默放行;与 TUI「换工作区整组清空」先例(tui/ui/apply.rs:2489-2500)及本模块自述镜像语义相悖。 - grouping key 族宽默认化 + 卡片无族宽披露:
rm/curl/scp/dd/chmod塌缩单动词族、git fetch的 flag 注入面(--upload-pack='…'与良性git fetch origin同族);上游 v0.8.37 继承、本 PR 相对基点净收紧,但把它变成新会话默认面且卡片三按钮无任何作用域提示,safety-modes.md:151措辞低估宽度。 - headless agentic 车道游离三态:
pinvou agent run(产品面,CLI 生产带 benchmark-hooks)经硬编码(true, Auto)——恰为底座无人姿态故主守卫面 fail-closed(见证伪存档),但残余armed_full_access_hold(rlm/start_mcp_server)、armed 类型化 ask、hook ask、headless 会话内子代理审批仍可弹卡无人应答,靠 CLI--timeout-secs看门狗兜底为 timeout 报告;for_engine_lane恒 Full 只覆盖 scheduled 车道,存量 Yolo 会话 agentic run 规则档为 Floor;docs/agent-task-cli.md与 §9 均未披露。 - code 车道 turn 终态不清扫审批卡:
code-native-lane.js:671-691只清 tool 卡;残留卡保持 active 可点、每次点击必报 "approval not found"——c84bd8d16「truthful in both lanes」的残留半臂(主车道chat-events.js:1115-1121已闭环)。 - 热换窗口(证伪后收窄):ChangeMode 即时生效、SetPermissionRuleset 只在 turn 间隙应用——窗口仅当轮在飞部分,无「直通」;残余:窗口内只读分类命令免卡逃过 Full 档 deny 面、typed 硬拒面退化为可批准普通卡;反向 Auto→Yolo fail-safe。建议文档登记。
- Floor 产线计数簿记:Windows 实宿主产线 Floor = 3521+613 = 4134(win_real_home_rules 613 条留 Floor),docs 表只写 3521;模块 doc
:248-249「+793 at production」在 v3.5 拆档后已过期(793 = 613+180 横跨两档)。 - i18n/文档小项:en 登记漏两处安全语义(Auto-Review 武装豁免排除、held-call fail-safe 前瞻,zh 正确 en 缺失);守卫拒绝文案双字典(bridge.js 内嵌 vs shared/i18n)en 已现大小写漂移;zh
nativeGuardrailDeniedSession「换参数」窄于实现(换工具同样重请批);读取失败兜底仍st.mode || "yolo"与新默认矛盾。 - 陈旧注释/元数据:
accept_plan的TurnAdmissionMetadata.mode恒序列化"yolo"(engine.rs:217,测试还钉着旧值),accept 实际回 pre-Plan/Auto——桌面 emit + 远程转发短暂发错 mode 后靠chat:mode_changed纠正;bridge.rs:3580-3583, 3969-3973两处两态契约注释停在 S-1 落地前;get_mode_defaultsdoc work→yolo 已变 auto。 - ask 侧车生命周期:boot 无 ghost 清理(
_multi_agent.json装载器有存在性清理,本侧车无);读失败/解析失败静默 return 无日志(姊妹装载器都有eprintln!);retention purge 分支零测试(round-1 Minor6 残留)。 - 前端小竞态:
decideApproval失败回滚用点击时快照无条件回写,可把已终态清扫的卡复活为 active(窄窗口、失败安全);code 车道 Yolo 确认卡不钉目标 sid(确认期间切会话则落到新会话,chat 车道有弃卡防护、双车道不一致);setAskOnGuardrail乐观写不按 sid 归属。 - 提交卫生:
bf5c2d4e4加了必需参数但#[cfg(test)]调用点漏迁,cargo check --all-targets/benchmark-hooks 在该提交树编译失败,直到e9e5037b5才闭合——bisect 落在 bf5c2d4..86ae1ea 任一点踩编译雷;665d61c4a/5d7fa667c/86ae1eadf三提交 fork-guard Layer 0 红(gitlink 消费先于登记,编译依赖所迫、提交信息已披露);665d61c4a42 文件 +2791 巨型提交(可拆「审批面后端」与「tri-mode UI+i18n」两个,后者依赖前者)。
被证伪降级的候选(存档,避免后续轮次重复追查)
- 「decide_approval 零重校验 → Plan 态执行 / 跨过 GuardrailAskOff」:不成立。底座在审批等待结束后、执行前 drain 新 authority 并拒绝跨姿态执行(
turn_loop.rs:5203-5224"An approval wait can outlive a posture switch");Yolo 关 toggle 后 deny face 引擎内即 Block、事件根本不发。宿主层确无重校验,但两个越权结局均不可达,仅剩「在途卡不作废」的 UX 残留(TUI 自身切模式同样不回收在途审批,先例一致)。 - 「热换敏感面直通一轮」:不成立。turn_loop 每批工具规划前/批间/每次执行前应用新 authority,stale 已规划调用直接拒并令模型按新姿态重试;规则集滞留方向安全(Auto→Yolo 时较严 Full 滞留)。
- 「无人值守 agentic 守卫命中弹卡挂死」:主路径不可达。硬编码
ApprovalMode::Auto恰为底座定义的无人姿态,armed deny face / repo-law / sandbox escalation 引擎内 fail-closed 不发事件;残余窄面见 MINOR-7。 - 「web PlanStuck 继续(Auto) 静默变 Yolo」:行为属实但有知情兜底——web 上
needsYoloConfirmation(null)=true,点按钮先弹「切换到 YOLO 模式?」确认卡,不会静默降权;降为能力缺失 + 标签误导(MINOR 级,建议随 BL1 一并处理)。
拆分与优雅
- 零夹带:63 文件逐一归桶全部主题内;
vite.config.mjs预算提升附同基实测与余量说明、协议/路由/性能测试均为姿态改动的必要 ripple、THIRD_PARTY_NOTICES属 gitlink 登记(内容过期问题在 M1)。fork 登记部分不建议拆分(与 gitlink 编译耦合,强拆会让单独树不可编译)。维持单 PR。 - 无重复造轮子:ask-rule 判定、deny 匹配、沙箱校验全走底座 API;三态命名/持久化/审批 UI/规则档全留父仓;底座 #131 候选 placement 恰当(consent-card 教义推广),3 提交演进中 fix 提交(04c1f7843)把 feat/test 两提交的 5 个真实缺陷逐一闭环且配测试。唯一镜像是处置真值表(底座
pub(crate)未导出的不得已),建议 #131 合入后立上游 issue 导出 disposition 判定或随事件携带建议处置。 - 底座消费无误用:
safety_change_mode_op纯函数消除两条武装路径漂移;spawn 期武装先于 entries 发布;「无人值守恒 Full」三发送点有源码钉防 revert;未武装逐字节等同声明逐面核实成立。
建议动作顺序
- BL1:Web bridge 最小闭环(3 listen + 5 方法 + capability 门控隐藏无效控件),或产品决定缓做时实现降级路径(自动拒绝 + 通知可达 / turn 状态提示)并更正 §9 披露;
- M1:docs 收尾提交(fork-policy zh/en 四处 + THIRD_PARTY_NOTICES 一处,同步 04c1f7843/89/87/526/+93516/-39313/269);
- M2:终态清扫豁免子代理审批 id + 回归测试;
- M3:
setSessionMode草稿分支 + 前端钉; - M4:更正「无数据丢失」声明 + v2 文件名/设置字段兼容评估(至少登记降级恢复路径);
- M5:reminder 按车道分岔 + 四平台 anchor 同步;
- MINOR 1-15 酌情同 PR 修(1/2/3/8/12 建议同 PR,其余可入 §9 或后续)。
全提交 DCO;机器验证与 round-1 闭合状态如前置核验所示。round-1 遗留两项(Minor6 测试、Minor7 披露)分别落在 MINOR-13 与 M4。
|
Follow-up to the new peer review, independently checked at unchanged head StandardsThree additional P2 findings are confirmed:
SpecThe same Web and downgrade findings also contradict the usable-workflow and lossless-compatibility claims. Two further P2 defects are confirmed:
Nonblocking P3: the per-turn sudo reminder still promises a mechanical deny/prompt in Yolo although its Floor profile omits the general sudo family. Qualify the copy; this does not establish a permission-opening defect. Validation: actual-source Node VM probes confirmed the missing Web adapter methods/listeners and zero draft writes/IPC calls for sidless mode choices. The detached-worker and old-version write paths were checked in source against the exact candidate and baseline. Earlier same-head Node/architecture receipts remain historical; no Cargo/native Rust, full browser, model execution or peer test-count claim is made. The known trailing-space diff-check finding remains. New findings: Standards 3 P2; Spec 4 P2, with Web and downgrade shared across the axes: 5 distinct additional required corrections, plus 1 nonblocking P3. The original two P2 remain. |
asto18089
left a comment
There was a problem hiding this comment.
Round-2 全新评审(10 车道 @ 09393c970 / 树 dcd7fe5e,2026-11-02,从零重审)
结论:方向与主体实现扎实——0 夹带、登记指纹全过、承诺行为大面匹码、round-1 的两类 blocker 形态在当前头不存在。但本轮找到 6 个 MAJOR(其中 4 个产品级:聊天车道草稿态芯片静默吞没、settings.json 向后兼容破坏、codex 车道两处"truthful in both lanes"承诺未兑现)+ 2 个测试守卫缺口,另有 fork-policy 登记陈旧。合并前需再走一轮修复波。
评审基础设施(本轮实测,非引用)
- base
3cec34e2b= main 最新 tip(API 复核,免 rebase);远端 11 提交链与本地 twin 逐字节同树(父dcd7fe5e,CodeWhalef9dae0480↔ gitlink04c1f7843)。 - 全量电池
cargo test --locked -- --test-threads=1:3794 过 / 0 挂(正文写 3793,差 1 属统计口径);npm test全绿;clippy --lib --bins --no-deps --features dev-tools0 警告;architecture-guard绿。 fork-guard.sh --fast指纹层全绿(88+15 指纹、269 forkguard 名、EXPECTED_COMMITS=89 与rev-list --count一致);唯一红行是本地 twin checkout HEAD 对不上 registered head——树已字节级证明一致,环境性,不成立罪。- 规则计数独立复算(脚本重演组合逻辑):Full=8729 / Floor=3521,与测试钉、docs 精确一致;Floor⊆Full 逐串成立;无规则串改写、无 Deny→Ask 改标。
- 夹带清点:62 个父仓文件 + gitlink 逐一分类,零无关改动。closest-call 逐项核实为直接后果:sudo 文案(旧文案零指纹残留属实)、vite 预算 486k→492k(有分项测量注释)、plan_normalize 窗口 3200→4800(实测锚距 4091,真增长非放松)、l1/memory harness(签名迁移,无新行为)、benchmark-hooks 调用点迁移。
必修(MAJOR)
M1 · 聊天车道草稿态芯片:Auto / Yolo 点击被静默吞没(codex 车道同路径是对的)
setSessionMode(bridge/interaction.js:449-453)以 if (!sid) return; 开头、无草稿兜底;handleModeChipSwitch(ChatView.jsx:2982-3018)把 auto 与过门后的 yolo 都路由给它。场景:未绑定草稿(每个新会话的起点)点 Yolo——chatYoloGateApplies 对无 draftWorkspacePath 的草稿直接不设门(chat-workspace-binding.js:22)→ setSessionMode(null,'yolo') → 无操作、无反馈,首 turn 物化为 Auto;点 Auto 同样吞没;已绑定草稿首次确认后 yolo_confirmed 全局置位,后续 Yolo 点击也全部落进死路径。基线行为里 Plan 起点的 Yolo 点击经 exitPlanToYolo(null) → setDraftMode("yolo") 是通的。同一 PR 里 codex 车道的 performNativeModeSwitch 草稿分支走 stageDraftMode 是对的,两车道行为相反。 同文件 setPlanModeNext(bridge-shared-helpers.js:3970)与 exitPlanToYolo(interaction.js:328)都有 if (!sid) { setDraftMode(...); return; } 模式——新路径没有复用。修法:草稿目标统一路由 setDraftMode(setDraftMode 本就支持 auto/plan/yolo 三值并写 lane 默认)。
M2 · SerializableMode::Auto 进入 settings.json = 旧二进制整文件击穿(持久设置丢失)
本轮把兼容面查全后发现:Auto 加在 core/mode_state.rs 的共享枚举上,prefs::CodePermissionPrefs.last_mode 与 prefs::ModeDefaultPrefs.work/design 都用它。新二进制写入 "auto" 后(触发可达:codex 草稿 stageDraftMode('auto') 写 code_permission.last_mode,CodexAcpView.jsx:1764),旧二进制 serde_json::from_value::<UserPrefs> 对未知变体整体失败 → parse_settings_with_state 回退系统默认(prefs/mod.rs:1045-1057),且 update_transaction 没有解析失败闸门(prefs/mod.rs:1296-1313 直接 save_unlocked())——旧二进制里用户任意一次保存都会把"默认值+本次改动"整体落盘,模型/语言/主题/迁移标记等全部持久丢失。正文的兼容声明("单轮陈旧、无数据丢失")只覆盖了 _session_mode_states.json,没覆盖 settings.json 这第二个持久面。AGENTS.md 要求破坏性配置变更必须有迁移路径。修法:prefs 两个字段的宽容反序列化(未知 mode 字符串 → None)+ 新旧互读回归测试。
M3 · codex 车道审批卡终态不落——66e2728ac 声称 "truthful in both lanes",实际只修了聊天车道
code-native-lane.js:671 的 chat:done 分支只扫 type==='tool',approval 卡不落终态。场景:Auto 会话弹卡后用户 Stop / turn 出错——后端 emit_chat_terminal 已 clear_pending,卡仍可点,之后每次点击都是 "approval not found" 错误横幅、卡永不消散(切会话回来直接蒸发,连终态记录都没有;聊天车道则是落 cancelled 终态)。NATIVE_APPROVAL_STATUS_COPY 连 cancelled 文案都没有。approval_card_lane.test.mjs 只钉了主车道的 sweep,测试面对这条缺口全绿。
M4 · codex Yolo 一次性确认门作用于"确认时刻的 live 会话",不是发起会话
pendingYoloSwitch 只存 { draft }(CodexAcpView.jsx:1141),confirmPendingYoloSwitch(1821)经 performNativeModeSwitch('yolo') 读 live activeId(1781-1790),全程无 sid 捕获、无切走守卫、无 activeId 变化时关门。场景:会话 A 点 Yolo 弹门 → 切到会话 B → 点确认 → exit_plan_to_yolo(B)——B 在从未见过确认门的情况下被武装成 Yolo/Bypass。聊天车道有完整守卫(ChatView.jsx:3055-3060 sid 比对 + 3083-3089 切会话复位),测试也只钉了聊天车道这条。
M5 · decideApproval 失败路径复活刚被终态清扫取消的卡
bridge/interaction.js:512,524-529:previous 在 await 前捕获,catch 无条件恢复。场景:点 Allow 的同时点 Stop——chat:done sweep 先把卡置 resolved:true/cancelled,随后 invoke 以 "approval not found" 失败,catch 把卡改回 resolved:false/active → 已取消的卡复活可点,继续点击每按一次追加一条失败 pill。直接违背"turn 终态未决卡就地落终态不再可点"。修法:catch(与成功路径同理)在恢复前检查 card.resolved 是否已在 await 期间被置位。
M6 · 测试守卫缺口两处(都是安全承诺裸奔)
- forwarder →
approval_surface_decision调用点零测试(forwarder.rs:890-901):真值表测的是纯函数本身;把session_granted/session_denied实参对调(round-1 BLOCKER 的复发形态)或ask/force布尔对调,全仓库无一处变红。至少补一条锚定源码钉(同live_engine_ruleset_sends_route_through_the_engine_lane_profile的做法)。 chat:guardrail_denied不带敏感入参的承诺无任何守卫(forwarder.rs:936-947的 Deny 臂零测试):给 payload 加回input字段,Rust/前端全部测试照样绿。
登记 / 文档(需修,机械性)
- R1
docs/fork-policy.md+.en.md:候选 SHA 仍指41eab46f2(#131 的中间提交,非 head04c1f7843),88 commits / 86 sign-offs / 268 names / 525 files 全是重钉前旧数;缺 twin-commit caveat(fork-modifications 双语都有);"本树 Layer 0+1 绿"的收条在 twin 树上不真。根因可考:fork-policy 只被dae04fe89摸过,1725e7049重钉与4d8199c02reconcile 都漏了它——而它是 self-declared single source of truth。THIRD_PARTY_NOTICES.md同 SHA 陈旧。 - R2 正文提交台账:
f2e08c800不存在于远端链(实际第二个提交是665d61c4a),e9e5037b5(benchmark-hooks 调用点迁移)整条漏记——远端 11 提交,台账 10 条。仓库文件无陈旧 twin/幽灵 SHA(已 grep 证明),仅正文。 - R3
docs/safety-modes.md§3.1 "落盘失败只记日志不打断交互"与代码相反:toggle 落盘失败会回滚内存与镜像(mode_state.rs:1317-1326);同函数两条互斥注释并存,reconcile 提交把陈旧的那条抄进了文档(mode 是 log-only,toggle 不是)。
建议(MINOR,择要)
- 规则面:Linux sudo-ON 每轮 reminder 在 Yolo 下夸大机械门(persistence 全家只在 Full);Windows destroy 面拼写不对称(
Remove-Item ~\.ssh\id_rsaFloor 拒而rm ~/.ssh/id_rsaYolo 静默过——deny-heavy 无洞,但与本 PR"敏感分族按语义不按拼写"的声明在该面自相矛盾);resolved-home 尾斜杠 upload 拼写(/home/me/)Full/Floor 都不盖(destroy 面对同一拼写是盖的,exfil_root_targets先算尾斜杠再 push home 的顺序差)。 - 状态机:旧二进制读含
"auto"的 sidecar 会整表拒绝 + 首次写 quarantine 重建(M2 同族,读路径"无丢失"仅字节意义);从未物化 code 会话 accept 落 Auto 而非 chip 所示 Plan(安全向,正文"accept 回 chip 显示过的默认"只对未绑定普通道成立);ModeDefaultsView文档与bridge.js:255仍写 work→yolo(实际已 work→auto);ask_on_guardrail字段文档与实现相反。 - 引擎线:
ChangeModetry_send 失败时跳过 ruleset 刷新(mode/approval 下次发送自愈,ruleset 停留旧档直到下次刷新;"下次发送自愈"措辞过宽)。 - 前端:
get_mode_state读失败兜底显示 yolo(最坏方向,应 auto,interaction.js:101);web 车道控制可见但死(不渲染已披露,但 access-policy 白名单了命令/事件——藏或实现二选一);旧后端planStuckGoAuto回退到 Yolo 档(标签 Auto 实切 Yolo)。 - CW#131:preview transition 读 installed 而非 planned posture(preview 与 wire hash 可短暂不匹配);首个武装 turn 模型无感知行(恢复会话 re-arm 后无 standing line);sub-agent 武装是 spawn 时快照非 live(方向安全,建议加一句文档)。
- 测试:两个 ruleset composition 钉在默认并行
cargo test --lib下 flake(读$HOME未持ENV_LOCK,本轮实测复现 2 失败;CI--test-threads=1掩盖);first_plan_write...重开断言空真(entry-less fallback 恒 Auto,应改durable_mode_entry);emit_chat_terminal→clear_pending接线无钉;突变探针 3 只单向咬合(seed-false 方向无测试)。
核验为净(要点)
- round-1 两类 blocker 形态在当前头不复现:授予/拒绝缓存每个读点都强制 session 维(
pending_approvals.rs:176-206,键为key→HashSet<session>,双向测试钉);Plan 首写按resolved_default_mode铸条目而非 Yolo 哨兵(回归测试在)。 approval_surface_decision逐臂可达、纯度成立、定序与承诺严格一致(拒绝 > Plan > 授予 > force > 姿态),force 恒弹卡比正文措辞更严(代码与模块文档自洽)。- 无人值守确定性端到端成立:forwarder 先于交互面短路、
for_engine_lane三站点 + spawn 配置推导全 Full、频道序保证武装先于任何 turn op。 - 事件面:
chat:guardrail_denied仅session_id/tool_name/reason稳定键;mode_changed五条路径同漏斗;pending 卡全终态路径clear_pending;会话删除经 purge 钩子摘除 grants/denials/mode/sidecar。 - 跨会话审批内存不可传染(组合键 remove 先于任何写入;重启即清);remount 回放不复活已决卡。
- 性能无回归:Floor 降 Yolo 每调用成本、热换 ms 级同步、登记簿 O(1) 短临界区、无每 turn 重编译。
- i18n 三语全量齐(chat 15 键 + codex native 7 键 + bridge BT 表);无 XSS 面(全部 React 文本节点,400 字符截断);React 无 Tauri 全局直采、依赖方向合规。
处置建议:M1-M6 + R1-R3 修复后我方复审;MINOR 可随后续波次。底座 #131 侧无需改动。
|
Follow-up review of unchanged head Standards[P2] Settle native approval cards when their turn terminates. The new SpecThe same finding violates Validation: I loaded the actual native-lane source and dependencies in Node and exercised approval-required followed by cancellation, error, and ordinary terminal payloads. All three leave the pending card unresolved/active; an already allowed card remains unchanged. The current One new finding per axis, referring to the same P2; the seven previously reported P2 items remain open. |
asto18089
left a comment
There was a problem hiding this comment.
Re-pin wave pushed: ca92bc54f(树 19b1a8809;gitlink → CodeWhale#131 复审修复二头 5c13fc561,fork-guard.sh --fast 本树全绿,行为名实测 273)。
- 登记漂移三件套修复(re-review lane H 的 MAJOR):
THIRD_PARTY_NOTICES.md、docs/fork-policy.md、docs/fork-policy.en.md此前仍写候选41eab46f2(88 提交 / 86 签名 / 268 名 / 525 files +93293/-39351),与同树 gitlink、fork-guard.sh、fork-modifications zh/en(当时04c1f7843/89/87/269/526)矛盾——现全部重钉到5c13fc561并按实测重算:90 提交 / 88 签名 / 273 名 / 526 files +94033/-39383(净 +54650)。 - zh/en parity(lane H minor):en 登记册 (a) 节补齐 Auto-Review 恒拒与 held-call fail-safe 括注(zh 镜像已有);safety-modes.md §8 census 更新为 18 条逐名(复审修复二 4 条均突变验证转红)。
- fork-guard.sh:
EXPECTED_HEAD→5c13fc561、EXPECTED_COMMITS→90、新增 4 条 T2 指纹(发布粘滞 / armed composer 硬拒 / armed Auto-Review 升级 / preview 计划姿态)。
CodeWhale 侧行为变更详见 Pinvou/CodeWhale#131 的 fix-wave 评论。
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed current head ca92bc54ff49fc625de3c5a08b5aaffe1756f6ed against 3cec34e2b6b7da8fbb85b70050dae83ff8b4ee10, including the CodeWhale increment 04c1f7843..5c13fc561. Changes are still required for the previously reported application workflows; the re-pin increment contains no application implementation changes.
Standards
The policy documents, THIRD_PARTY_NOTICES, machine guard and new fingerprints now identify the correct candidate, and my exact-candidate fork-guard.sh --fast passes. This is useful progress on the register finding. It is only partly closed: docs/fork-modifications.en.md:75 and its Chinese counterpart still say the current parent gitlink/EXPECTED_HEAD points to 04c1f7843; their current Layer-0 receipt also says that only an 04c1f7843 checkout is green. The actual registered candidate is 5c13fc561. Align these present-tense assertions while retaining genuine historical receipts. This is the existing register-consistency item, not a new duplicate finding.
The existing required Web approval-workflow and downgrade-persistence compatibility findings remain unchanged. The CodeWhale increment itself yielded no new confirmed production standard violation in this review.
Spec
The seven existing application/spec findings remain: failed guardrail-toggle persistence returns success after rollback; plain-chat late decision failure revives a cancelled card; Web Auto approval lacks its complete interaction workflow; old-binary writes can destroy persisted settings after encountering Auto; a parent terminal clears approvals belonging to a still-running detached worker; chat draft Auto/Yolo selection has no writer; and native approval cards never become non-actionable on turn termination. Details remain in my original review, first follow-up, and native-card follow-up.
I reran the actual-source Node probes on this head: the Web adapter still omits all five interaction methods and all three event listeners; sidless draft Auto/Yolo choices issue zero draft writes; a late rejected chat decision restores an active card after terminal cancellation; and native approval-required followed by terminal events leaves the card active. The foundation's sticky-arming and preview-posture changes do not correct these parent-layer paths. No new production P1/P2 was established in that foundation increment.
Validation
Local fork-guard.sh --fast, architecture guard and the existing approval-card Node test pass. The targeted probes above expose missing behavior despite that test passing. Full diff-check still reports the previously recorded trailing whitespace in bridge_domain_protocol.test.mjs:242. Cargo is unavailable locally: no Rust/native/browser/provider or peer execution totals are claimed.
Current CI is not green: job metadata reports cargo fmt --check, commit-message validation and public-submodule verification failures; the PR-title log confirms unsupported wip type. Some other raw job logs could not be retrieved, so I am not claiming a more specific root cause for those failures. The candidate-window explanation does not replace the public-consumption gate or justify weakening it.
Standards: 3 existing required items, including the partially fixed register. Spec: 7 existing required items; Web and downgrade overlap Standards, giving 8 unique outstanding items. No new required production finding added in this increment.
Round-2 修复波收官(6 MAJOR + R 系 + MINOR 全落,
|
| 评审项 | 处置 |
|---|---|
| M1 聊道草稿芯片吞没 | 草稿三档统一落 setDraftMode(两车道同约);未绑定草稿 Yolo 过同一一次性确认门;setDraftMode 补上双桥公开面 + API 契约 |
| M2 settings.json 击穿 | lane 词表永不写 "auto"——显式 Auto 走 *_auto 伴随旗 + 宽容反序列化 + 视图折回;store/struct 两级回归钉(旧二进制整文件解析不再可破) |
| M3 codex 卡终态不落 | chat:done 清扫未决审批卡落 cancelled + 三语文案(与聊道同约,行为测试钉) |
| M4 codex 门打 live 会话 | 门 entry 捕获发起 sid,确认落点钉回弹门会话(非当前目标不刷本会话控件) |
| M5 复活已取消卡 / 跨面不收敛 | decide 失败恢复让位终态;新增 chat:approval_resolved 收敛广播(后端唯一构造点 + 双白名单 + 双车道幂等处理器 + 协议摘要重算) |
| M6 两处测试裸奔 | forwarder 调用点实参顺序源码钉(grant/denied 对调即红);guardrail_denied 载荷唯一构造点 + 键集钉 |
| R1/R2/R3 + MINOR | fork-policy/notices 重钉随并行 ca92bc54f 收敛(取其 5c13fc561 新数);正文台账修正(幽灵 SHA + 补漏提交);§3.1 落盘语义如实化;sudo reminder 按 Yolo 分档;armed-card 注释纠正;ENV_LOCK 去flake;空真断言改 durable 条目;姿态同步双发独立;回滚镜像精确还原;web/旧后端死控件藏或禁用 |
验证(合并树 = 本波 + 5c13fc561):cargo 电池 --test-threads=1 3800 过 / 0 挂(净增 7 条新回归钉);npm 全量 1431 过 / 0 挂;build:ui/build:web 绿(入口预算 492k→496k,按政策实测 492,003 B);clippy lib+bins dev-tools 0 警告;architecture-guard 绿;fork-guard --fast 全绿(子模块检出于登记头);DCO 全签。
底座侧 5c13fc561(并行推入的复审修复二)恰好闭合了本轮 CW 车道的两条 MINOR(preview 读 planned posture、publish 不回滚武装),与本波无重叠。
asto18089
left a comment
There was a problem hiding this comment.
Round-3 登记重钉批(6b50c78a4,候选 → f972884e5)
随底座复审修复三(CodeWhale#131 推进至 f972884e5,评审 COMMENT 5732557068 / 底座波评论 5732732459)同步重钉登记,并改齐并发 docs 提交(3faee5dd3)遗留的 wave-1 时代陈旧候选表述。
登记重钉(全部实测)
- gitlink 与
EXPECTED_HEAD→f972884e5dc99c16241941c87a094140e5e7600a;EXPECTED_COMMITS90→92(90 带签,新增两提交均带 DCO footer)。 - T2 指纹 19→21(20 测试钉 + 1 文案钉):新增
forkguard_pump_never_auto_approves_a_force_prompt_hold(runtime_threads/tests.rs)、forkguard_a_not_started_turn_neither_consumes_nor_records_the_transition(engine/tests.rs)——两条均在底座突变验证转红后逐字节还原。 - safety-modes §8 census 18→20(复审修复三 2 条 + 逐名补录)。
- drift 重测(
dcd4c200f..f972884e5):526 files, +94377/−39438,净增 54939;forkguard_*行为名 273→275(guard 同口径)。 - zh/en fork-modifications 与 fork-policy parity 同步(92/90、六提交评审史含 clippy
10b28ef5f与复审修复三、260/0 门禁、275 名、21 指纹)。 ./scripts/fork-guard.sh --fast在本树全绿(Layer 0 head 对账 ✓ 92 提交 ✓ 指纹层全过 ✓,实际 275 名)。
陈旧表述改齐(round-3 fresh review F4 及其扩展)
3faee5dd3 只改了 safety-modes,其提交说明中"fork-policy/THIRD_PARTY_NOTICES 重指向被并发重钉取代"并未实际落盘——fork-policy zh/en 仍整段停留在 wave-1 候选(04c1f7843、89 提交/87 签/269 名/+93516/−39313 旧数),THIRD_PARTY_NOTICES 候选行同样未动,fork-modifications 另有 3 处 Layer-0 子句仍写 04c1f7843。本批全部改齐为 f972884e5 现值;历史性 commit 列表中作为评审史的 04c1f7843 提及按原样保留(它们指真实历史提交,非候选指针)。改后全库 grep:候选指针 0 处指向旧 SHA。
底座波回顾(见 CodeWhale#131 波评论)
- F1(MAJOR):runtime pump 丢弃
approval_force_prompt,Full Access 下武装 hold 被静默自动批准 → 绑定字段 + 真人决策路径 + tripwire + 钉。 - F2(MINOR):ChangeMode status 后缀按 carrier 有非实际翻转门控 → 只报真实翻转 + 生产形态断言。
- F3(MINOR):NotStarted 顺序修复无回归钉 → 补
forkguard_a_not_started_turn_neither_consumes_nor_records_the_transition。 - F5(pre-existing):
tools::subagent顺序依赖失败测试在基线f1eb10efc复现,不随本批修复,留独立 follow-up。
门禁
- 本地 clippy 1.99
-D warnings在10b28ef5f与f972884e5报同 5 条预存 lint(PR 之前既有代码,与 CI 工具链口径有漂移),底座波未新增 lint。 - 全量父仓电池在新候选树复跑中,完成后更新 PR 描述对应行。
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed current head 6b50c78a40052d52b8e3ef34253002c9ac87da23 against 3cec34e2b6b7da8fbb85b70050dae83ff8b4ee10, including the six-commit fix wave and exact CodeWhale candidate f972884e5. The application/CLI trees are unchanged from the provisionally tested 3faee5dd3 head.
Confirmed fixes: chat draft Auto/Yolo now reaches its writer and confirmation gate; a late rejected chat decision no longer revives a cancelled card; native terminal events cancel undecided approval cards; current fork policy/notices/register are aligned. The fresh settings.json writer improvement and sudo reminder correction are also acknowledged. The remaining issues below still require changes.
Standards
[P2, new] Update existing CLI consumers of mode defaults for the companion flags. pinvou-cli/crates/cli/src/models.rs:2971-2975 still writes only the legacy mode field, while SessionStore now gives last_mode_auto/work_auto precedence. After selecting Auto in the desktop, pinvou settings set code_permission.last_mode plan succeeds and the CLI getter reports plan, but the retained true companion flag makes a new/restarted code session resolve Auto. Work-default writes and clearing with none have the same inconsistency. Make every reader/writer use the effective-mode contract, clear the companion on legacy choices, and test desktop Auto → CLI choice → reload. This is source-confirmed; I have not executed a native CLI binary.
[P2, existing, partly fixed] Finish the downgrade boundary. Fresh lane-default writes avoid invalidating old whole-settings parsing, but Auto remains in the typed session-mode sidecar. An older reader rejects the whole map; mutation quarantines it and later writes rebuild from an empty map. Preserving quarantine bytes does not preserve active per-session choices or automatically recover them. The section-6 “no data loss” claim still needs an accurate migration/recovery boundary.
[P2, existing] Complete or explicitly reject the Web approval workflow. Hiding/disabling controls does not resolve the changed Auto default: a Web-originated turn can still wait for an approval the Web bridge cannot render or decide. The actual adapter still omits the five approval/mode interaction methods and the three required event listeners. The desktop-only scope disclosure does not cover this regression to an existing Web flow.
Spec
[P2, new] Preserve resolved IDs across delayed pending replay. The new native chat:approval_resolved handler only settles a card already present. If another surface decides after get_pending_approvals captures a snapshot but before CodexAcpView.jsx:2007-2022 applies its reply, the resolution is discarded and the old snapshot then inserts an active card. I executed the actual replay chunk and reducer with a deferred IPC promise: this ordering produces eventChanged:false, followed by an unresolved active card; normal resolution after insertion works. Keep tombstones or an approval replay epoch across the await. The main bridge restore has the same snapshot/dedupe shape. This is a controlled JS ordering reproduction, not a full Tauri transport run.
Two previous P2s remain: guardrail-toggle persistence failure restores the old value but unconditionally returns success, and parent terminal handling still clears approvals belonging to detached workers that remain alive. Correcting rollback mirrors/documentation does not provide failure feedback or repair owner-lifetime cleanup. Web and sidecar compatibility above also remain spec/workflow gaps.
Validation: positive actual-source probes confirmed the three UI fixes; approval-card and permission-state Node tests and architecture guard passed on the byte-identical app tree. Current-candidate fork-guard.sh --fast passes, with 275 registered behavior names. The known diff whitespace issue remains. Current CI is not all green. No local Cargo, native Rust/CLI, browser/provider execution, or author/peer test totals are claimed. The new foundation increment yielded no independently confirmed production P1/P2.
Standards: 3 required items. Spec: 5 required items, overlapping Web and downgrade with Standards: 6 unique P2s remain, including 2 newly identified gaps. Four original P2s are now closed within the reviewed scope.
6b50c78 to
8333ca0
Compare
|
机械修复批已推送(force-with-lease
force push 会清除已有 approvals(CHANGES_REQUESTED 保留)。应用级 8 项 findings 的行为修复由后续批次负责。@JensenChen28 |
asto18089
left a comment
There was a problem hiding this comment.
Round-4 登记复核(随 CodeWhale#131 全新 9-lane 评审)
本地 twin 69b520de1(tree 2d1cc0538a)与远端头 6b50c78a4 逐字节一致;base 3cec34e2b == main 顶端(0 behind),无 rebase 需要。
全部登记数字精确复算 TRUE:./scripts/fork-guard.sh --fast PASS(exit 0);EXPECTED_HEAD/gitlink = f972884e5;rev-list --count dcd4c200f..f972884e5 = 92 与 EXPECTED_COMMITS 一致(fork PR 自述「dcd4c200f 之上第 92 个提交」同口径吻合);21 条新指纹(20 测试钉 + 1 文案钉)全部在本 PR diff 中且 20 个钉名全部存在于 fork 树(零缺失/零孤儿;147 个注册名中 19 个 APP 侧钉在父仓验证存在);drift 526 files +94377/−39438(git diff --shortstat dcd4c200f f972884e5 精确)、行为名 255→275、92 提交/90 DCO(缺签 2 条为基线 #107/#116,PR 6 提交全签)、census §8 = 20 条——全部精确;docs/safety-modes.md 与底库行为逐条一致。子仓 PR 本体走私 CLEAN(零既有断言削弱)。
2 项登记卫生发现(建议本 PR 内修复):
- P2 —
scripts/fork-guard.sh:2头注释与登记自相矛盾:头注释仍是 "89 maintenance commits",同文件EXPECTED_COMMITS=92,而docs/fork-modifications.en.md:341明确声称 "fork-guard.sh header 86→92"。登记陈述对当前树为假——一行修复即可。 - P3 — perf 门放宽未入 body:
pinvou3-app/vite.config.mjs主入口预算 486_000→492_000→496_000(config 内注释载明两次上调依据)与multiagent_plan_normalize.test.mjs结构距离 3200→4800 均未在 PR body 提及。放宽有实测依据、非走私,但 perf 门变更应入 body 供评审明示认可。
CI 备注:两 PR 当前均无任何 check(fork 侧零自动化信号),合并置信完全依赖上述本地复算。
JensenChen28
left a comment
There was a problem hiding this comment.
Follow-up at 8333ca0, including the new registration review. The increment from 6b50c78 consists of Rust formatting and one JS whitespace correction; CodeWhale remains f972884e5dc99c16241941c87a094140e5e7600a.
Standards
No new blocking finding in this mechanical wave. Two nonblocking P3 documentation items are confirmed: fork-guard.sh's header still says 89 maintenance commits although its executable count is correctly 92 and the register claims the header was updated; the PR description should disclose the desktop performance-budget and source-pin window relaxations. The selected margin should also be described accurately rather than calling 496,000 the next thousand above 492,003. These do not invalidate the correct operative gitlink/count/fingerprints.
Spec
The six independently validated P2 items from my preceding review remain unresolved:
- A failed guardrail-setting write rolls back the value but still reports success.
- Web Auto turns can require approvals without a complete Web approval workflow.
- The downgrade fix still leaves session-sidecar choices vulnerable to the older reader/rebuild path.
- Parent terminal cleanup removes approvals still owned by live detached workers.
- CLI default setters/readbacks ignore persisted Auto companion flags, so the next session can contradict the reported default.
- A resolution arriving before deferred pending replay is discarded, allowing replay to recreate an active card.
The earlier resolved UI/register findings remain resolved. This formatting wave repairs none of the six application behaviors; please address them with the corresponding regression coverage.
Validation: independent two-axis increment review, actual approval_card_lane and code_permission_state Node tests passed, architecture and full diff whitespace checks passed, and fork-guard --fast passed with 92 registered commits and 275 behavior names. No local Cargo/native execution or author build measurements are claimed. Local fingerprint success is not a claim that all CI gates are green; the new peer's zero-check statement was not adopted.
Standards: no new blocking findings, two nonblocking documentation follow-ups. Spec: six previously confirmed P2s remain. Requesting changes.
asto18089
left a comment
There was a problem hiding this comment.
Round-4 收官(重钉 + census 两提交 → b436624cb)
随底座复审修复四(CodeWhale#131 b94cc3175)的重钉批与 round-4 评审(COMMENT 5733841785)全部可修项:
| 项 | 处置 |
|---|---|
P2 头部文案 89 vs EXPECTED_COMMITS=92 自相矛盾 |
fork-guard.sh:2 头部 89→96(随本次重钉一并推进),登记的「header 86→92」声明从本批起真正成立;同时修正 fork-policy zh/en 的同族表述 |
| P3 vite 预算 486_000→496_000 与结构距离 3200→4800 未入 body | body 补记 perf 门披露项(config 内注释的两次实测依据一并呈现) |
| 登记 | EXPECTED_HEAD→b94cc3175、EXPECTED_COMMITS=96、T2 指纹 21→23(复审修复四补 forkguard_sync_session_clears_the_recorded_turn_meta_posture、forkguard_an_isolated_turn_neither_consumes_nor_records_the_transition;pump 钉扩展载荷断言不新增钉名)、gitlink→b94cc3175、safety-modes §8 census 20→22、fork-policy/fork-modifications zh+en/THIRD_PARTY_NOTICES 候选数全部改齐(drift 526 files +94761/−39438 净增 55398、277 行为名、96 提交 94 签) |
实测:fork-guard.sh --fast 在重钉树全绿(第 0 层 head 对账绿、277 行为名、指纹层全过);底座 forkguard_ 262/0 + 模块门禁全绿 + 协议 71/0 + fmt 干净。注:作者侧在评审期间并行强推了 rustfmt 重排与 wave-3 重钉(8333ca005),本批按远端新头线性落盘(e7a5b9ad3 重钉 + b436624cb census,census 提交经 Git Data API 推送、树与本地逐字节断言一致)。
|
Processed the remaining round-3 review findings in four commits on top of the round-4 wave ( P2 — CLI consumers of the mode defaults (fixed, P2 — approvals settled across delayed pending replay (fixed, P2 — guardrail-toggle persist failure returned success (fixed, Complementary — round-4 fail-neutral extended to the native lane ( Where the round-4 wave already landed, my parallel drafts were dropped in favor of the pushed direction: the §6 downgrade boundary ( Validation on the merged tree ( @JensenChen28 ready for re-review. |
|
Follow-up on the round-5 wave, independently re-verified at a fresh checkout (worktree at the pushed head, CodeWhale submodule at CI gate repair — Independent re-verification at One residual this wave cannot fix append-only: CI's commit-message gate rejects @JensenChen28 the six P2s from your review at |
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed latest head cdb534fa5b5c6dbff5932d1d51919581624abb7a with exact CodeWhale gitlink b94cc3175a24d21180dfce0ff70512a0f5839a5e, including the four-commit fix wave, its lint followup, and new discussion.
Standards — P2 remains
- Preserve session-sidecar data across downgrade. The old reader still rejects/quarantines the whole typed map when it contains Auto, and subsequent mutations rebuild from empty, losing existing per-session choices. Accurate disclosure in §6 does not implement the repository's data-compatibility requirement; the PR summary's no-data-loss claim also needs correction.
Spec — P2s remain
- Fence failed-decision restoration against terminal cleanup (
pinvou3-app/src-tauri/src/app/commands/interaction.rs:560–578, new). The command removes a pending entry, awaits engine lookup/send, then unconditionallyrecords it on failure. Engine eviction/session purge can clear the registry during that await; the missing-engine/closed-channel branch then recreates an obsolete request after cleanup. A fresh remount snapshot exposes it again, regardless of frontend tombstones. Restore only within the same still-live approval lifecycle and cover cleanup between removal and failure. This is a source-confirmed interleaving, not an executed native race. - Complete or proactively gate unsupported Web Auto work (partially addressed). The translated unsupported/desktop-handoff notice fixes silent waiting. Approval-requiring Auto work can still be accepted from Web and then wait for desktop interaction, without Web decision/replay. Provide the workflow or gate/fallback that unsupported execution path before accepting it; the post-wait notice alone does not complete it.
Closed in source: guardrail persistence now returns its error after rollback; CLI effective getters/paired setters honor and clear Auto companions; known early-resolution events now fence stale replay in both lanes. The actual native replay chunk/reducer probe now suppresses stale insertion and passes the normal-resolution control. Detached-worker terminal cleanup now explicitly denies child requests. Fork header/count and performance disclosure are corrected.
Nonblocking followups: acquire HOME locks before constructing readers; make the chmod-based failure fixture robust to privileged Unix execution; bound tombstones by the actual in-flight snapshot lifetime (the bridge's 512-entry eviction is not itself proof that old snapshots expired). New engineering comments should follow the documented English convention.
Validation: four targeted Node files passed at this head, using a private SHA512-verified exact-lock Acorn package without changing repository dependencies. Architecture/full diff checks passed; unchanged foundation was checked by fork-fast (96 commits/277 behavior names). No local Cargo/native Rust/Windows/full-product execution or author/peer totals are claimed. Earlier-head CI failures are not presented as latest-head results.
|
Round-5 登记重钉批( 随 CodeWhale#131 round-5 全新 11-lane 评审(COMMENT 6576202168)的修复波重钉: |
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed c1fd187d3a7629c3b796e4f850793b5e73e130f8 and exact CodeWhale 1785dae1584f0005ceacbc5153e3a48f010abbaa.
Standards: the register update is consistent: fork-fast passes, with 97 maintenance commits, 279 behavior names and 24 test fingerprints plus the copy fingerprint. The existing P2 downgrade compatibility issue remains: an old reader can quarantine the entire Auto-containing session map and rebuild it on later writes, losing prior per-session choices. Disclosure does not preserve the data. Nonblocking P3: the English consumed-baseline paragraph still says initial + nine followups although eleven commits means ten followups.
Spec: the foundation attribution fix is accepted (also reviewed independently in CodeWhale #131). This increment changes registration/docs/gitlink only; it does not modify the two other remaining P2s:
- Web Auto can accept approval-requiring work, then wait for a desktop decision without a Web decision/replay flow or proactive unsupported-path gate. The handoff notice is a partial correction.
app/commands/interaction.rs:560–578can restore a removed approval after awaited lookup/send failure even if terminal/session cleanup ran in between. Restore only within the same still-live lifecycle; frontend tombstones cannot protect a fresh remount from a newly restored backend entry.
Three unique application P2s remain; previously source-resolved findings stay closed. Full diff whitespace and current fork-fast passed. Existing application Node receipts apply to unchanged source and were not rerun; no Cargo/native Rust, full-product run, or author/peer test totals are claimed.
zhuowp
left a comment
There was a problem hiding this comment.
Reviewed head c1fd187d3a7629c3b796e4f850793b5e73e130f8, tree 1aef5a83be7e9e7e33c02a9d140488f7c03d87fb, against target bf9ad288a6130f348c78be7b59dea0defc4e2597 (merge-base 3cec34e2b6b7da8fbb85b70050dae83ff8b4ee10), personal review request 34843659371, with actual CodeWhale 1785dae1584f0005ceacbc5153e3a48f010abbaa.
Changes are still required:
-
P2 — Give fresh text-tool calls distinct approval identities.
CodeWhale/crates/core/src/tool_parser.rsrestarts its XML call counter on each response, and the live engine fallback preserves those IDs. For two adjacent valid XML fallback responses in one session, the new Auto posture requires approval for ordinary non-readonly shell calls: after the firstxml_tool_1is approved once, a distinct subsequent call receives that ID again, and the actual receipt store rejects the second request before its event or execution. The original parser and receipt modules reproduce the mismatch; a fresh-ID control is accepted. Allocate fresh call/approval incarnations while preserving actual replay identity and receipt validation. This is the real integration failure behind the rejected synthetic second-card scenario. -
P2 — Acknowledge approval acceptance before publishing success.
pinvou3-app/src-tauri/src/app/commands/interaction.rs:582-608treats the engine mailbox send as an accepted decision, then commits session memory and broadcasts resolution. The actual engine validates the request and commits its outcome later. Use an acknowledged disposition for the same approval lifecycle before publishing its successful result; this does not require waiting for tool execution to succeed. -
P2 — Keep failed Continue (Auto) actions retryable.
pinvou3-app/src/platform/tauri/bridge/interaction.js:434-445marks the PlanStuck card handled beforeset_session_mode. If that call rejects, it returns without restoring the card or continuing. The renderer removes its actions, leaving a failed operation marked handled. -
P2 — Scope Web approval-notice deduplication by session.
pinvou3-app/src/platform/web/bridge.js:4018-4031uses a global Set keyed only by approval ID. Different sessions can legitimately produce the same ID; the second then loses its waiting explanation. The actual listener fails this two-session case, while a session-scoped control preserves both notices. -
P2 — Complete or gate unsupported browser Auto work. The unsupported notice repairs silent waiting. An existing browser task can still enter an Auto/Suggest approval wait that its interface cannot decide or replay, requiring a separate desktop. Provide the workflow or explicitly reject/hand off that unsupported execution path. Excluding new browser cards from scope does not by itself complete the existing task flow.
-
P3 — Publish the guardrail setting consistently with persistence.
pinvou3-app/src-tauri/src/features/sessions/mode_state.rs:1356-1407releases the entry/override locks before the sidecar write. Concurrent readers can consume the new value even when that write subsequently fails and rolls back. A deterministic barrier probe observes this transient publication; rollback alone does not retract a consumed posture. -
P3 — Fence pending replay against turn termination. Both lanes cancel cards already present on
chat:done, but an earlier pending snapshot can return afterwards and insert an active expired card. Resolution tombstones fix the separate resolved-before-replay ordering. Apply a terminal/request generation fence to replay in both lanes. -
P3 — Fence failed-decision restoration against cleanup.
pinvou3-app/src-tauri/src/app/commands/interaction.rs:560-580removes pending state, awaits engine lookup/send, and unconditionally restores it on failure. A terminal or purge during that await can therefore be undone by a stale restore. Restore only within the same still-live approval lifecycle. -
P3 — Reconcile overlapping failed arming toggles.
pinvou3-app/src/platform/tauri/bridge/interaction.js:472-488restores each call's captured optimistic value. Two opposite writes that both fail can leave the chip showing enabled while the persisted setting is disabled. The actual bridge probe reproduces this; the sequential control does not. -
P3 — Make the Auto/OFF contract face-specific. The safety-mode table promises silent hard rejection too broadly. Ordinary Suggest typed-Ask, repository-law and sandbox-escalation prompts remain possible without arming. Distinguish those existing prompts from the autonomous guardrail faces converted by the toggle; this is a documentation correction, not an engine-bypass claim.
-
P2 — Correct the downgrade claim in the PR summary. Its statement that old binaries use a boot-cache fallback with one stale turn and no data loss remains inconsistent with the strict old session-sidecar reader and quarantine/rebuild path. The revised section 6 documents the actual boundary; bring the summary into agreement. This finding does not infer a requirement for arbitrary older binaries to understand every new format.
The latest foundation increment correctly separates standing host transitions from per-turn provenance narrowing; no additional defect was established there. The proposed same-session repeated-ID card defect was rejected after checking the actual receipt store: it refuses the repeated request before a second approval event. That protection does not prevent legal ID reuse in different sessions.
Informational census/history leftovers and engineering-language convention remain nonblocking P3 followups: their severity is low, normal operation is unaffected, and their relation to the safety behavior is weak. The substantive findings above do not satisfy all three conditions.
Coverage includes all 461 raw source hunks with actual primary evidence and version inheritance, plus independent checks of complete approval/state paths and high-risk no-finding seams. Coverage closure is not a passing code verdict. Current native Windows evidence includes 24 distinct locked CodeWhale library safety tests, each actually reporting 1 passed/0 failed, and the exact parent library/benchmark-hooks compile. These were verified from raw logs; author suite totals were not adopted. Controlled original-module and fault probes support the findings, but do not establish mounted Tauri/provider, full product/CLI tests, combined-runtime or installer acceptance. Required CI, public dependency consumption and branch-protection gates remain separate and must not be bypassed.
Current-head merge evidence also remains red: required-gate failed, the public-submodule gate reports maintenance f1eb10efc versus gitlink 1785dae15, and commit-message validation rejects 742ca6a0dc8b for a 51-character description against the 50-character limit. Frontend and Rust-lint success do not replace the skipped Rust/native/CLI behavior jobs or waive those required failures.
The final target's three CI files were also checked independently, including all 13 changed hunks and the actual hosted callers. Its bounded safe fixtures and explicitly equivalent inherited repair tests support that integration assessment; no combined native runtime or successful merge-group run is claimed.
Expose the tri-mode controls over the app command surface and align the privileged-copy faces with the real semantics. - decide_approval, get_pending_approvals, set_session_mode, set_ask_on_guardrail and set_plan_mode_next commands behind existence gates and the shared publish sequence; workspace rebind clears per-session approval memory at the bind commit - the mode default preference and its mirrored views under the prefs lock; connectors and marketplace propagate the hot-refresh result to their command callers - Linux, macOS, Windows and unsupported sudo reminders state the three-state semantics instead of the old default-deny wording; integration harness fixtures follow the new shapes Signed-off-by: asto18089 <asto18089@126.com>
Drive the tri-mode face on both desktop lanes with truthful state transitions. - mode chips and drafts land on the lane default, every Yolo entry passes the one-shot confirm gate with generation fencing, and failed toggles converge by rereading the authority instead of writing local guesses - ApprovalCard gains allow / allow-this-session / deny with full-input disclosure, terminal tombstones across replays and fail-neutral handling of malformed echoes; PlanStuckCard keeps its Auto option latched - three-language copy for chips, cards, notices and hints; the main entry budget takes its next thousand-step to 494,000 B for the added surfaces Signed-off-by: asto18089 <asto18089@126.com>
Mirror the tri-mode contract on the web lane and bound its send admission. - posture gates on sends, accept-plan and edit turns with per-session deduplicated notices; direct sends join the per-session admission owner and the FIFO queue, requeue on busy, and resume the missed drain after the receipt - approval requests surface as deduplicated notices, replay honors the terminal fence, and unsupported capabilities say so instead of staying silent - the access-policy denylist gains the decision and mode write commands; the relay webui smoke follows the live first-turn wire with bounded waits Signed-off-by: asto18089 <asto18089@126.com>
Honor the tri-mode companion flags on CLI settings round trips: the effective-mode contract reads and writes the auto companion flag and the ask-on-guardrail default alongside the plan vocabulary, keeping settings.json free of the "auto" literal; contract tests pin both directions. Signed-off-by: asto18089 <asto18089@126.com>
Add docs/safety-modes.md and its English twin: the posture table, the approval surface ordering, the Full/Floor profiles with the recomputed census (Full 8,763, Floor 3,555), the persistence and old-writer interop boundaries, and the residual limitations ledger. Signed-off-by: asto18089 <asto18089@126.com>
Update fork-modifications and the fork-guard register for the merged CodeWhale#131 head this PR consumes, with the current fingerprint and drift census. Signed-off-by: asto18089 <asto18089@126.com>
|
[2026-11-12 重建] 2026-11-10 的 round-20 收官评论(pullrequestreview-5838280164)正文是一个未展开的文件引用( 2026-11-10 round-20 修复波:从零 8 车道评审(评论 5827044662 @
(2026-11-12 起:原 205 提交链已重组为 7 个功能区提交,最终树逐字节一致;本波内容并入 PR 正文的「行为要点 / 验证 / 评审历史」。) |
链与正文整理(2026-11-12)评审期累积的 205 个提交重组为 7 个功能区提交(时序累积的 86KB 正文由结构化正文替代:行为要点 / 提交表 / 验证 / 披露台账 / 21 轮评审历史索引)。最终树与 round-21 修复确认的头
|
zhuowp
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES on 70539297d790781fbc32a054d1f1f771a6adf681, against actual target/merge-base b7a814bc8b90987fff4443fc265fb36e3a435749. The unchanged CodeWhale consumption is 11cba403dc6bd6ca5c4dca55042785b03449ac8e.
Four P2 defects remain: an invalidated ordinary-chat YOLO entry can dispatch after A→B→A navigation; the new aux Plan pin prevents its sole scoped parent-history MCP reader; mode changes report success after failed live ruleset delivery; and coldspawn publication can miss a concurrent persisted guardrail-toggle update. Inline comments identify the actual conditions and recovery limits. These are product findings independent of CI.
Coverage is closed for all 97 changed paths / 790 hunks, including deleted/replaced source, complete affected bodies and capability chains. I accepted the five authenticated current first reviewers’ exact source witnesses with explicit semantic qualifications, independently read the candidate and high-risk boundary chains, and fully read/adjudicated all 205 attributed online bodies. Historical approvals, author pass counts and mechanical hash coverage were not correctness votes.
The older captured-turn mode replay is real, but no current requirement establishes retroactive revocation of a turn already reserved with captured posture; it is not a blocker. Watcher first-message recursion shielding also does not establish the scheduled/windowless unattended safety contract for every background API. Documented compatibility/crash boundaries remain secondary limitations.
Validation includes J’s exact-source extracted JavaScript ordering probe with a generation-check negative control, plus qualified original pure/VM and 20-file Node evidence (164 reporter outcomes, not end-to-end flows; two deliberate negative failures restored). No full native/app/model/MCP, Cargo or production Vite build pass is claimed. CI failures are excluded per the requested review scope. Source review is complete; merge approval is withheld pending the four fixes, and this review does not certify release readiness.
| /// failures itself (boot-log discipline keeps session ids off stderr). | ||
| fn pin_aux_mode_from_parent(&self, aux_id: &str, parent_id: &str) { | ||
| let aux_mode = match self.mode_state(parent_id).mode { | ||
| SerializableMode::Auto => SerializableMode::Plan, |
There was a problem hiding this comment.
[P2] Keep the scoped parent-history reader usable after pinning aux mode. Under the normal Auto default this now durably assigns Plan to the auxiliary conversation (Plan parents also assign Plan). Its healthy configured tool surface contains only mcp_session-reader_read_session, but the unchanged consumed child classifies that MCP tool as read_only=false and rejects non-readonly MCP calls in Plan before execution/approval. The auxiliary UI has no independent mode control, so its advertised ability to fetch parent history is unavailable, including on reuse/restart. The target had no such mode pin. Preserve this narrowly scoped read capability without weakening the general Plan gate.
There was a problem hiding this comment.
Confirmed and boundary-dispositioned. The defect is real: the consumed engine's McpToolAdapter::capabilities() classifies every MCP tool outside is_mcp_read_helper as [Network, RequiresApproval] (no ReadOnly), so the pinned Plan posture rejects mcp_session-reader_read_session before execution/approval and the aux lane's advertised parent-history fetch is dead.
The classification lives in the CONSUMED child (pinned gitlink 11cba403d, unchanged by this PR); neither host-side lever can preserve the capability within your own constraints:
- Session rulesets are deny-only (safety_deny_rules composes deny families); they cannot carve an allow exception into the child's capability gate, so weakening nothing is impossible from the host.
- The pin itself cannot move: the web face refuses Auto (the original reason for the Plan substitution), and Auto/Yolo both weaken or break a constraint you also require (Yolo aux on the approval-less web face is strictly worse).
So the durable fix is the child-side classification change — the fork-owned session-reader read tool belongs in the child's read-helper classification (or the adapter honoring MCP readOnlyHint annotations) — which is a CodeWhale PR by the fork boundary, to be consumed at the next pin advance. I have recorded the residual on the pin itself (pin_aux_mode_from_parentdoc) so it is not mistaken for a bug and "fixed" piecemeal host-side. Leaving this thread unresolved for your adjudication of the boundary call; if you read the child change as in-scope for this PR after all, tell me and I will carry the candidate.
The pre-spawn posture arming reads the persisted mode state before the spawned engine exists, so a concurrent set_ask_on_guardrail could persist a newer flag in that window, find no handle in handle_for, skip the live sync, and report success. The arm then queued the stale snapshot and the insert published the engine with it; ordinary sends carry no ask carrier, so the child preserved the old value across turns. The insert and a fresh re-read of the persisted posture now happen under one entries lock hold, with the reconciled ChangeMode queued before the lock drops: any later handle_for queues its ops after the catch-up, so the spawned engine can never stay on the pre-spawn snapshot. The multiagent spawn-span pin rides the same gap by design. Signed-off-by: asto18089 <asto18089@126.com>
publish_session_mode_change logged a failed live ruleset synchronization and still broadcast chat:mode_changed with a success result — the UI reported the new mode while the live engine kept the previous ruleset, and ordinary sends carry no ruleset replacement, so nothing repaired the discrepancy. The store write has already landed, so the propagated error surfaces as a visible failure against an already-persisted switch: the user can retry the toggle and the retry re-runs the sync against the persisted mode and heals the engine. The broadcast now fires only after the sync succeeded. The v3.5 pin that encoded the old log-and-succeed tradeoff flips with the decision. Signed-off-by: asto18089 <asto18089@126.com>
The aux lane's reader capability (mcp_session-reader_read_session) is classified non-readonly by the consumed engine's MCP adapter — the child's is_mcp_read_helper allowlist does not know the fork's session-reader tools — so the pinned Plan posture rejects its calls before execution/approval and the advertised parent-history fetch is unavailable. The classification lives in the consumed child: host rulesets are deny-only and cannot carve an exception into that capability gate, and the pin itself cannot change without re-breaking one of its two constraints (the web face refuses Auto; weakening the general Plan gate is not an option). The durable fix is the child-side classification change, tracked for the next CodeWhale consumption batch; the residual is now recorded on the pin. Signed-off-by: asto18089 <asto18089@126.com>
The gate re-checked only the session id after its awaits, so an Auto→YOLO action started on A survived an A→B→A navigation: the sid matched again while the session-switch effect had already bumped the dialog generation and discarded the click's lifecycle, and the stale action dispatched setSessionMode(A, yolo). The gate now captures the lifecycle generation before its first await and requires it unchanged at both staleness re-checks — the same lifecycle check the native lane performs by capturing the entry generation before its await. Signed-off-by: asto18089 <asto18089@126.com>
zhuowp
left a comment
There was a problem hiding this comment.
Request changes on 852eeea4ca352ba27364c5905a711648671cef52, reviewed against actual target/merge-base b7a814bc8b90987fff4443fc265fb36e3a435749, with unchanged consumed CodeWhale 11cba403dc6bd6ca5c4dca55042785b03449ac8e.
Two P2 product defects remain: cold/rebuilt engine catch-up refreshes mode without the matching mode-derived ruleset, and the durable auxiliary Plan pin blocks its sole parent-history reader. The inline comments describe the reachable conditions and required corrections.
The prior chat YOLO lifecycle, failed live-sync reporting and missed cold-spawn ask handoff findings are closed in the current source. Current queue, approval lifecycle, workspace publication, persistence and unattended-lane chains were checked independently.
Coverage is complete for all 97 changed paths and 795 cumulative hunks, including original per-hunk source bases, affected bodies, old replacements, current callers/configuration/dependencies, and all 218 exact attributed online entries. Historical approvals, author grades and test counts were not correctness votes.
Validation is source review with qualified original pure/VM evidence; no new tests, native application, browser, model/MCP or release execution is claimed. CI problems are excluded from these product findings. This review does not establish release readiness.
| /// tracked for the next CodeWhale consumption batch. | ||
| fn pin_aux_mode_from_parent(&self, aux_id: &str, parent_id: &str) { | ||
| let aux_mode = match self.mode_state(parent_id).mode { | ||
| SerializableMode::Auto => SerializableMode::Plan, |
There was a problem hiding this comment.
[P2] Preserve the auxiliary parent-history reader under the Plan pin
For the normal enabled Auto/Plan parent population this persists Plan on the auxiliary SID, including healthy legacy reuse. Its advertised parent-history feature depends on its sole tool, mcp_session-reader_read_session, but the unchanged consumed child classifies that MCP tool as non-readonly and rejects it in Plan before execution or approval. The panel has no independent mode control, and reopening or starting a new topic keeps the same Plan assignment. This makes the declared parent-history capability deterministically unavailable; ordinary text Q&A does not replace it. Deliver a compatible scoped-read capability with this pin, without weakening the general Plan gate. The future-child note documents the defect but does not restore the feature.
asto18089
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES on 852eeea4ca352ba27364c5905a711648671cef52,target/merge-base b7a814bc8b(该 head 恰平 main tip,零 rebase 需求,实测 merge-base==tip)。CodeWhale 消耗 pin 11cba403d(本地验证:包含已合并的 #131 merge e2a0e14fd9 及 #133/#134/#135 后续)。
全新 13 分片并行复审 + 本人独立复核 + 3 个突变探针。覆盖 97 文件全量 diff(Rust 宿主 46 文件 / 渲染层 18 / 测试与文档 33)。
P2(1 项,修复波自身的半截修复)
[P2] engine_pool.rs:3034 — c6f30de84e 的 catch-up 只补发 ChangeMode 一半,ruleset 一半仍停留在 pre-spawn 快照;且该排序不变量当前没有任何能变红的测试。
arm_spawned_session_safety_posture(:5396)从 pre-spawn 快照入队 两个 op:safety_change_mode_op + Op::SetPermissionRuleset(mode-derived profile)。catch-up 块(:3034-3040)在同一 entries lock hold 内 fresh re-read 后只重发 ChangeMode,不重发 ruleset。触发:spawn 窗口内并发 set_session_mode(Yolo→Auto)——写侧持久化后 live sync 因 absent-entry 跳过并返回 Ok;spawn 插入后 catch-up 把 posture 修成 Auto,但 ruleset 仍是 Yolo 派生的 Floor(应 SafetyRuleProfile::for_engine_lane(Auto,_) = Full)。结果:Auto 会话的敏感面机械 deny 被削——ask ON 时本应硬拒的敏感操作降级为可批准卡片;ask OFF 时静默放行。divergence 持续到下一次显式 toggle/broadcast/respawn,全程无失败信号。窗口窄(arm→insert 两条 try_send 之间),但这正是 zhuowp round-4 P2 的同类窗口,且提交信息的不变量主张("the spawned engine can never stay on the pre-spawn snapshot")对 ruleset 一半为假。
修复方向:同一 lock hold 内补发 Op::SetPermissionRuleset { ruleset: self.session_scope_ruleset_for_engine(session_id, &engine) }(引擎 lane 形态,与 arm 一致;不可调 refresh_session_permission_ruleset_locked——其 handle_for 会与持有的 entries lock 死锁),并把 live_engine_ruleset_sends_route_through_the_engine_lane_profile 的三处发送点钉扩到第四处。
测试缺口实证(突变 C):把 catch-up 块整体移出 entries lock hold(破坏本修复的承重不变量)后——cargo test -p pinvou3-tauri --lib 全绿 4134 passed; 0 failed; 18 ignored,multiagent_plan_normalize span 钉 51/0 绿(span 只断言代码落在间隙内,对排序不可判红)。对照突变 A/B(见回执)均红:唯独这条 P2 修复无红能力覆盖。安全修复应带能红的钉。
P3(12 项)
- pending_approvals.rs:622 — 优先级阶梯文档与实现相反(代码是对的):实现为 force_prompt 卡片压过 grant cache(
if session_granted && !force_prompt,真值表钉 :1816),与 TUI 底座authority.rs:887一致、fail-safe;但阶梯注释与 PR 正文写“会话授予 > force 弹卡”。改文档,勿改码。 - interaction.rs:748-770 — 被拒的 grant/denial 写入静默丢弃:
remember_grant/remember_denial返回 false(rebind 代际前进)时结果被丢弃,chat:approval_resolved仍向所有面广播 allow_for_session/deny。安全方向(下次重问),但至少记日志或在 payload 打 refused 旗。 - interaction.rs:621-625 — engine-absent 失败臂缺“unknown”广播:另两个失败臂(:668-713)刻意发 resolved-shaped unknown 让所有面渲染为不可判定;此臂(purge 竞态于
handle_with_incarnationawait)只返回 Err,他窗死卡仍呈活跃态。 - safety_deny_rules.rs:2099 — sudo 命令词块在 shed 集:未武装 Yolo 静默放行未枚举的特权变更(
sudo usermod -aG sudo me、sudo nano /etc/shadow),而 Auto/Plan 反而 typed-Deny——更宽的模式拥有更弱的 sudo 门。刻意的+已钉(must_not: "sudo"),但 never-sensible 应含特权提权;建议移入 floor 或在 safety-modes.md 已知边界明示。 - safety_deny_rules.rs:2109 — Windows 侧 Floor/敏感分族按拼写而非语义:
win_native_rules(Floor,2796 条,占 Floor 3555 大头)含逐凭据销毁拼写(del …\.ssh\id_rsa钉保留),语义孪生rm * ~/.ssh/id_rsa却被 shed(钉丢弃)。同一行为 POSIX 静默过、Windows 静默拒,与正文“分族按语义不按拼写”矛盾(保守方向,无安全损失)。 - 正文计数漂移:Floor 实际 3,555(钉
assert_eq!(floor.len(), 3555)与 docs 一致;本人独立重算 destroy 1685+dd 326+catastrophic 261+sudoers 8+root-upload 70+win-native 2796+win-root-upload 39=3555、全量 8763 复核通过);PR 正文写 3,553,请更正。另 Yolo 下逐凭据直传完全缺席(silent pass,armed 与否,safety_deny_rules.rs:1547 自述)——正文表述宜如实标注质量边界。 - store.rs:1203 — aux 钉只继承父模式,ask 种子取全局默认而非父会话有效值:全局默认 OFF + 父 Yolo 已武装 → aux Yolo 静默硬拒而父会话弹卡。方向严格(web aux 面有开关可恢复),建议 pin 时传递父的有效 ask 值。
- web/bridge.js:428 — Auto 拒发文案把用户推向同类陷阱:“Switch the session to Plan or Yolo”——默认武装(
ask_on_guardrail_default=true)下 Yolo 会话同样会 raise web 无法决策的审批卡(child 端 Yolo+armed→卡片)。有webApprovalUnsupported通告、busy 可恢复、可 cancel,无静默悬挂——但文案主动推荐逃逸到同一死角。建议文案如实化,并考虑 web facade 导出setAskOnGuardrail(native lane 已导出)让 web 用户可解除武装。 - connectors.rs:299 — 刷新错误吞掉已算出的 auth-gates 裁决:
refresh_tools_and_broadcast(...).await?; Ok(result?)——refresh 失败时持久化裁决result被丢弃。与传播主题一致,但该裁决是持久态投影:并入错误信息或记日志后返回 verdict。 - 文档+追踪缺口(aux reader residual):8050dc698e 只把 residual 写进 store.rs 源注释;
docs/safety-modes.md§9 已知边界未收(en/zh 双语)。且“tracked for the next CodeWhale consumption batch”目前没有可见追踪工件——截至 2026-11-13 Pinvou/CodeWhale 无任何开放 PR 触及is_mcp_read_helper/session-reader 分类。child 侧分类事实本人已在 pin11cba403d独立复核(crates/tui/src/tools/registry.rs:1455allowlist 仅 5 个 discovery helper,mcp_session-reader_read_session得[Network, RequiresApproval]无 ReadOnly)→ 边界裁决本人同意(host 规则集 deny-only 无法开 allow 豁免;钉不可动:web 拒 Auto、Yolo-on-web 更差),但请挂出 CodeWhale issue/PR 并补 doc §9 条目。 - ChatView.jsx:4548-4555 — 取消处理器不清
chatYoloConfirmError:确认失败→取消→同会话重开卡片显示上一次错误残影。补一行setChatYoloConfirmError('')。 - prefs/mod.rs:897 —
deserialize_lenient_mode静默降级:损坏/未知 lane 默认值读成“从未选择”,无任何日志,与本仓 loader 的“silent skips make defaults undiagnosable”纪律相悖;行为本身正确且有测试。
NIT(不阻塞,捆绑记录)
pending_approvals.rs:85-87 generation 字段文档陈旧(实为 remove_fenced/restore fence 承重件);interaction.rs:744/754 outcome.is_ok() 恒真;pending_approvals.rs:290-303/484-503 生产死测试胶水(remove/list_all_sessions);engine_pool.rs:3034 store.mode_state 在全局 entries lock 下可做 sidecar IO stat(建议 lock 前预热一次 workspace-binding 缓存);forwarder.rs:989 通告先于 deny ack settle(良性);ChatView round-9 确认闩吞一次点击(有记录自愈);ChatView:3160 成功确认后 sid ref 残留(死态);interaction.js:561-583 失败回滚无 epoch 守卫(get_mode_state 重读自愈);interaction.js:505 PlanStuck 闩缺 resolved 检查(当前 UI 不可达);web facade setSessionMode 无 IS_WEB auto 守卫(纵深防御一行);web chat:approval_required 监听器缺 session_id 空值守卫(后端恒发,防御性);CodexAcpView nativeApprovalInputView 与 tool-renderers approvalInputView 字节级孪生(rung-2 可合一);web_aux_chat_admission_gate test 3 与 test 2 逐字节重复;approval_card_lane:247-249 controlFence 自比断言恒真;web_queue_admission_fifo:245 50ms 实时竞态有 CI 抖动风险(:505 的 2000ms 形态更好);commands/tests.rs:3489 副作用断言为不可假阳剧场(真覆盖在源序钉);:3660 魔法窗口 160 偏移脆;:3355/3434 无界尾扫源钉(潜在假红/假绿);sessions/tests.rs 新旧 accept→Auto 断言部分重叠;chat_bound_workspace_logic:31-41 注释措辞断言(行为钉在 approval_card_lane 有补偿);multiagent_plan_normalize span 放宽均有实测记录(跟进代码而非放水,已核实);vite 预算 486k→494k 每步有实测+自记录,web 128k 不变,机制仍 throw——非放水。
zhuowp round-4 四项 P2 的修复裁决(全部实证)
| 发现 | 裁决 |
|---|---|
| Chat YOLO 门 A→B→A 陈旧派发 | 修复正确且完整:genAtGate 前捕获+双复查;全量扫描无同族幸存实例;突变 A(删 gen 条件)→ chat_yolo_gate_session_scope 红,还原后绿 |
| 模式发布吞 live sync 失败 | 修复正确:sync_engine_safety_posture(...).await? 传播;全调用方核对(accept_plan log-only 臂有 wire 姿态论证);突变 B(回退 log-and-succeed)→ session_mode_write_paths_publish_through_the_shared_sequence 红 |
| coldspawn 姿态错过并发 toggle | ChangeMode 半修正确(insert+重读+try_send 单 lock hold;写侧全部先持久化后 sync;无其他插入点);ruleset 半未修=上述 P2;无红能力测试(突变 C 全绿实证) |
| aux Plan 钉杀 session-reader | 事实成立、边界裁决同意(child 分类独立复核如上);残余已记录源内;缺口=doc §9 未收+无 child 侧追踪工件(P3-10) |
四轴结论
- 有用性/根因:成立。tri-mode 全链真实落地(posture 逐轮、registry 隔离键、Full/Floor 热换、降级兼容、单点种子、denylist+读例外)。唯 P2 为修复波自身的半截修复。
- 优雅:良好。纯函数决策核、单漏斗写路径、engine-lane 形态复用;无平行第二系统;死代码胶水有自觉标注。
- 夹带:零夹带。13 分片逐一核对:bridge.rs
locked_env测试专用包装已披露无生产效应;vite 预算上调每步实测记录(本轮自增产物);relay smoke 属强化;CLI companion flags 在范围内;i18n en/ja/zh 三语全齐。 - 缺陷/性能:无逐轮热路径回归;审批面工作按审批计费非按事件;键控状态 512 封顶有逐出;规则组装 ms 级且仅 spawn/换挡/toggle 触发。P2 为安全姿态分叉,非崩溃/数据类。
门与突变回执(本机 arm64,head 852eeea4ca)
cargo test -p pinvou3-tauri --lib:test result: ok. 4134 passed; 0 failed; 18 ignored(228.74s;含 PR 新增测试)cargo fmt --all -- --check:绿node --test --test-concurrency=4:1418 tests,1381 pass,19 fail 全为 env(无 node_modules →Cannot find package react/vite/marked/acorn/postcss/dompurify/domino/@tauri-apps.cli,19 个失败文件逐一归类,无一属于 PR diff;PR 触及的 JS 测试全绿),18 skippedscripts/fork-guard.sh --fast:指纹层全过,301 条 forkguard 名(≥64),exit 0- 突变 A(删 gen 栅栏)→ chat_yolo_gate 钉 红;突变 B(回退传播)→ publish 序列钉 红;突变 C(catch-up 出锁)→ lib 全量绿 + span 钉绿 = P2 修复无红覆盖实锤
CI/required gates 与托管 Windows/原生装配不在本复审主张内。
| last_active_epoch_ms: AtomicU64::new(Self::now_epoch_ms()), | ||
| }, | ||
| ); | ||
| let fresh_state = self.store.mode_state(session_id); |
There was a problem hiding this comment.
[P2] catch-up 只补 ChangeMode,ruleset 半仍停 pre-spawn 快照。 arm(:5396)入队两个 op(ChangeMode + SetPermissionRuleset,mode-derived profile);本块 fresh re-read 后只重发 ChangeMode。并发 set_session_mode(Yolo→Auto) 落在 absent-entry 窗口时:写侧持久化+sync 跳过+返回 Ok,spawn 后 posture 修成 Auto 但 ruleset 仍是 Yolo 派生 Floor(应 Full)——Auto 敏感面机械 deny 被削(ask ON→可批准卡;OFF→静默过),持续到下次 toggle/broadcast。修复:同 lock hold 补发 Op::SetPermissionRuleset { ruleset: self.session_scope_ruleset_for_engine(session_id, &engine) }(勿调 refresh_session_permission_ruleset_locked——handle_for 会死锁于本锁),并扩 live_engine_ruleset_sends_route_through_the_engine_lane_profile 钉到第四发送点。排序不变量当前无红覆盖:突变实测把本块移出 lock 后 lib 4134/0 全绿+span 钉 51/0 绿。
| } | ||
|
|
||
| /// The branch order builds on the TUI `resolve_approval_request_disposition` (authority.rs), with the Plan | ||
| /// defensive arm deliberately stricter: **session denial > Plan hard-deny > session grant > force_prompt card > |
There was a problem hiding this comment.
[P3] 阶梯注释与实现相反(代码对,注释错)。 实现是 force_prompt 压过 grant cache(if session_granted && !force_prompt,真值表钉 :1816 “A force_prompt hold is not served by the cache”),与 TUI 底座 authority.rs:887 一致、fail-safe。按 PR 正文/本注释改码会削弱安全面——改文字:“…> force_prompt 卡(压过授予缓存)> 授予缓存 > 姿态判定”。
| // The grant is recorded on the lossy grouping_key: covers later flag variants (v0.8.37 semantics). | ||
| // It carries the registered card's origin workspace generation: an old success arm resumed after a rebind | ||
| // advanced the generation is refused here in-lock on mismatch, never writing the old directory's decision into new-generation memory (review 5764675531). | ||
| pending_approvals::remember_grant( |
There was a problem hiding this comment.
[P3] 被拒的 grant/denial 写入静默丢弃后仍广播 resolved。 remember_grant/remember_denial 返回 false(rebind 代际前进)时结果丢弃,:765-770 仍广播 allow_for_session/deny——所有窗把卡结算为已授予,下次同族调用重问(安全方向但无信号)。记日志或在 resolved payload 打 refused 旗。
| "decide_approval: approval not found: {approval_id}" | ||
| )); | ||
| }; | ||
| let Some((engine, incarnation)) = pool.handle_with_incarnation(&session_id).await else { |
There was a problem hiding this comment.
[P3] engine-absent 失败臂缺 unknown 广播。 另两臂(:668-713)刻意发 resolved-shaped “unknown” 让所有面渲染不可判定;purge 竞态于 handle_with_incarnation await 时本臂只 Err 返回,他窗死卡仍呈活跃。镜像 unknown 广播。
| /// every host — inert on POSIX, keeps the pinned count host-independent), | ||
| /// and the resolved real-home Windows family ([`win_real_home_rules`]). | ||
| /// | ||
| /// Deliberately NOT here: the sudo command-word block — the sudo product |
There was a problem hiding this comment.
[P3] sudo 命令词块在 shed 集——未武装 Yolo 静默放行未枚举特权变更。 sudo usermod -aG sudo me / sudo nano /etc/shadow 静默过,而 Auto/Plan typed-Deny 同操作:更宽模式拥有更弱 sudo 门(枚举 payload 仍被 Floor 的 rm 族覆盖)。刻意+已钉(must_not: “sudo”),但 never-sensible 应含特权提权——移入 floor_safety_rules 或在 safety-modes.md §9 已知边界明示。
| compactStart: "⏳ Compacting context", compactDone: "✓ Context compacted", compactFail: "⚠️ Compaction failed", compactCancel: "Context compaction canceled", compactAuto: " (auto)", | ||
| toolGuardrailDenied: "Guardrail denied", toolGuardrailDeniedSessionDenied: "this exact operation was denied in this session (a changed request asks again)", toolGuardrailDeniedPlan: "Plan mode is read-only; denied", toolGuardrailDeniedAskOff: "ask-on-guardrail is off; denied outright", | ||
| webApprovalUnsupported: "⚠️ Approval needed — the web UI cannot decide it; the turn waits for a decision in the desktop app", | ||
| webAutoSendBlocked: "⚠️ Send blocked: this session is in Auto mode, which can raise approval cards the web UI cannot decide. Switch the session to Plan or Yolo with the mode chip, or continue in the desktop app.", |
There was a problem hiding this comment.
[P3] Auto 拒发文案把用户推向同类死角。 默认武装(ask_on_guardrail_default=true)下 Yolo 会话同样 raise web 无法决策的审批卡(child 端 Yolo+armed→卡片)。有 webApprovalUnsupported 通告+busy 可恢复+可 cancel,无静默悬挂——但文案推荐逃逸到同一死角。文案如实化(“Yolo 仍可能弹 guardrail 卡,需桌面决策”),并考虑导出 setAskOnGuardrail 到 web facade(native lane 已导出)。
| let result = connector_cli_domain::refresh_connector_auth_gates().await; | ||
| refresh_tools_and_broadcast(&app, pool.inner()).await; | ||
| refresh_tools_and_broadcast(&app, pool.inner()).await?; | ||
| Ok(result?) |
There was a problem hiding this comment.
[P3] 刷新错误吞掉已算出的 auth-gates 裁决。 refresh_tools_and_broadcast(...).await?; Ok(result?) ——refresh 失败时持久化裁决 result 被丢弃换成 refresh 错误。与传播主题一致,但 verdict 是持久态投影:并入错误信息,或记日志后返回 verdict。
| /// parse — a parse failure falls back to system-locale defaults for every | ||
| /// unrelated preference, and the next settings save then durably rewrites | ||
| /// them. Known variants parse normally; anything else reads as None. | ||
| fn deserialize_lenient_mode<'de, D>(deserializer: D) -> Result<Option<SerializableMode>, D::Error> |
There was a problem hiding this comment.
[P3] deserialize_lenient_mode 静默降级。 损坏/未知 lane 默认值读成“从未选择”无任何日志——本仓 loader 纪律是 loud logging。行为正确有测试;补降级日志。
| // (the gate now assigns the caller's action unconditionally on | ||
| // open, but the confirm still captures whatever the shared ref | ||
| // holds at click time). Same invalidation convention as the | ||
| // session-switch effect above. |
There was a problem hiding this comment.
[P3] 取消处理器不清 chatYoloConfirmError。 确认失败→取消→同会话重开卡片重绘上一次错误残影。补 setChatYoloConfirmError('')。
| 停止生成),不是无反馈转圈。完整 Web 审批工作流仍是后续项。 | ||
| - **审批面跨进程重启不保真**:挂起卡与授予/拒绝缓存是进程内存;重启后 turn | ||
| 重新请批(engine 侧审批 id 本就随进程消亡)。这是有意取舍,不是持久化缺陷。 | ||
| - **多智能体引导期的默认解析先于 code 判定注册**:`_multi_agent.json` 的引导 |
There was a problem hiding this comment.
[P3] §9 已知边界未收 aux reader residual。 residual 目前只在 store.rs pin_aux_mode_from_parent 源注释(8050dc698e);本文档 aux/Plan 节读者无从得知“父历史抓取在 Plan 钉下不可用”。补一条(en/zh 双语同步)。另建议挂出 child 侧分类修复的追踪工件——截至 2026-11-13 Pinvou/CodeWhale 无开放 PR 触及 is_mcp_read_helper/session-reader 分类,正文“tracked for the next consumption batch”目前不可见。
JensenChen28
left a comment
There was a problem hiding this comment.
The latest head fixes the stale A→B→A chat YOLO gate and now propagates failed live sync before broadcasting. One P2 remains in the spawn catch-up: the initial arm queues both ChangeMode and a separately derived SetPermissionRuleset, but this catch-up re-reads the mode and queues only ChangeMode. If a mode write lands after the initial arm but while handle_for still sees no published engine, the sync is skipped and this catch-up applies the new mode with the old mode-derived hard-deny ruleset. Please enqueue the matching ruleset in the same ordered catch-up. The existing parent-history reader P2 from zhuowp also remains acknowledged in documentation but not resolved in code; I have left that review/thread untouched.
The pre-spawn arm queues two ops from the snapshot: ChangeMode and SetPermissionRuleset (mode-derived profile). The publication catch-up re-read the fresh posture but only re-sent the ChangeMode half, so a concurrent Yolo->Auto set_session_mode landing in the absent-entry window left the spawned engine running the Auto posture on the Yolo-derived Floor ruleset (Full expected) until the next explicit toggle or broadcast: the Auto sensitive face lost its mechanical deny (an armed ask downgraded hard-deny to an approvable card; an unarmed ask silently passed). The catch-up now re-derives the ruleset through the engine-lane form in the same entries lock hold, mirroring the arm; refresh_session_permission_ruleset_locked stays unusable here (its handle_for would deadlock on the held entries lock). Pins: the lane-form ruleset pin extends to the fourth send site, and a new structural pin holds both reconciled halves inside the lock-hold block — the mutation probe that moved the catch-up outside the lock compiled green against every prior pin (round-5 review receipt), so this ordering was unobserved; both mutations (outside-the-lock, dropped ruleset send) now flip the pins red. Signed-off-by: asto18089 <asto18089@126.com>
Two decide_approval arms were silent where their siblings speak. The grant/denial memory writes return false when a rebind advanced the generation between the card raise and the click; the results were discarded while the resolved broadcast still settled every face as granted — the refusal is now logged so the ask-again outcome is diagnosable. The engine-absent arm restored silently on a refused fence; a purge racing the handle_with_incarnation await left other mounted faces an active-looking dead card, the exact condition the determinate-refusal arm broadcasts for — it now emits the same resolved-shaped "unknown" (a successful restore keeps the card live and stays silent, behavior unchanged). Signed-off-by: asto18089 <asto18089@126.com>
The aux pin inherited the parent's mode but seeded the aux ask toggle from the global default, so a global-OFF default under an armed Yolo parent hard-denied silently in the side panel while the parent raised cards. The pin now seeds the aux entry from the parent's effective armed state through seed_aux_ask_from_parent; an explicit aux override always wins and is never stomped, and the call rides the same confirmed-absent gating as the mode pin. A persist failure degrades to the already-minted global default and self-heals on the next re-pin. Signed-off-by: asto18089 <asto18089@126.com>
The auth-gates verdict was computed, then `?` over the tools/ruleset refresh dropped it on a refresh failure — the persisted-state projection the wrap-up comment promises verbatim was silently replaced by the refresh error. Both signals now survive: the verdict stays the command's answer, and the refresh failure is carried alone when the verdict succeeded or attached when both failed. Signed-off-by: asto18089 <asto18089@126.com>
An unknown lane-default mode value degraded to "never chosen" silently; a hand-edited or newer-binary settings.json reset the default with no signal, unlike every other loader in the file. The degradation now logs (behavior itself unchanged and still tested). Signed-off-by: asto18089 <asto18089@126.com>
Cancelling after a failed confirm left the error state set; re-opening the same session's card repainted the previous attempt's error before any new confirm. The cancel handler clears it alongside the other invalidation points. Signed-off-by: asto18089 <asto18089@126.com>
The Auto send-block copy routed users to Yolo as an escape, but a default-armed Yolo session raises the same web-undecidable approval cards; the copy now states the caveat. The chat:approval_required listener drops a session-less payload before the dedup key instead of poisoning the shared bucket, and the planStuck latches also check the resolved flag (decideApproval's discipline; currently unreachable, defense in depth). Signed-off-by: asto18089 <asto18089@126.com>
Per the round-5 review audit: the web_aux duplicate of the Plan control arm folds into one test; approval_card_lane's controlFence self-comparison and chat_bound's comment-wording assert could never fail and are removed; the mode-target gate probe reads the durable shared mode map (the real mint surface) instead of the aux-only in-memory mirror it could not fail on; the set_mode_default and publish pins cut their windows at the next item so later code cannot fake a green (or false-fail an unrelated eprintln). The cancel dialog pin rides the new error-clear (round-5 fix), and the web wire-surface hash is recomputed for the in-body listener/copy changes (no new command or event surface). Signed-off-by: asto18089 <asto18089@126.com>
Section 9 gains two entries (zh + en): the aux parent-history fetch is unavailable under the Plan pin (consumed-child classification gap, durable fix tracked child-side), and the three known deviations from the "split by semantics" claim — the sudo command-word shed, the absent per-credential upload face, and the Windows spelling asymmetry — all conservative, all pinned, pending a product call. Signed-off-by: asto18089 <asto18089@126.com>
The ladder and the module doc put the session grant ahead of the force_prompt card; the implementation (fail-safe, mirrored from the TUI base) gives a force hold precedence over the grant cache. The wording now matches the code so nobody "fixes" the code to match the prose. Signed-off-by: asto18089 <asto18089@126.com>
|
Round-5 修复波已推: P2(已修 + 突变翻红)
P3 对账
NIT 批(
|
|
更正上一条的一条预告:Pinvou/CodeWhale 仓库禁用了 Issues(REST 410),child 侧分类修复( |
JensenChen28
left a comment
There was a problem hiding this comment.
Reviewed new head c78dc8866e7e191cf1dd52ff481baa39b0e18437 against main b7a814bc8b90987fff4443fc265fb36e3a435749. The earlier spawn catch-up gap is fixed: both mode and ruleset are now recalculated under the publication lock. I still have changes requested for the following issues:
- [P2] Do not log session/approval identifiers —
pinvou3-app/src-tauri/src/app/commands/interaction.rs:774-789writes rawsession_idandapproval_idto stderr when generation-checked grant/denial persistence is refused. These are private session/action identifiers; the nearby aux-seeding code explicitly follows the boot-log rule of keeping session IDs off stderr. Log the refusal without either identifier. - [P2] Preserve an explicit aux toggle and retry failed seeding —
pinvou3-app/src-tauri/src/features/sessions/mode_state.rs:1690-1712checksask_on_guardrail_overridesbefore takingsession_mode_states_io, then writes after acquiring it without rechecking. A concurrent explicit toggle can therefore be overwritten by the inherited seed. Also, if this sidecar write fails,pin_aux_mode_from_parenthas already persisted the aux mode;get_or_create_aux_sessionretries the pin only when the durable mode entry is absent, so the documented “self-heals on the next ... re-pin” path does not run. Please make the check/write atomic and provide a retry path (or correct the claimed guarantee and avoid leaving the aux mode marked initialized). - [P2] Keep all three web locales accurate —
pinvou3-app/src/platform/web/bridge.js:428now correctly warns English users that Yolo can also raise undecidable guardrail cards, but the Japanese and Simplified ChinesewebAutoSendBlockedstrings still recommend switching to Yolo as a workaround. Update those translations too, following the repository’s three-locale UI-copy convention. - [P2] The parent-history reader remains blocked in Plan — this is still the previously reported behavior: the pinned child classifies
mcp_session-reader_read_sessionas non-readonly, so the aux Plan session rejects the parent-history fetch. The new docs disclose that the advertised fetch currently returns nothing but do not make it work. Please keep this outstanding until the child-side classification or an equivalent supported fix lands; do not treat documentation of the failure as resolving it.
The new catch-up sends are also best-effort try_sends (engine_pool.rs:3046-3058). If either send fails on a full engine queue, the operation can still return the engine with the old mode or ruleset while the comment claims both halves are reconciled. Please ensure the catch-up pair is delivered, or surface spawn/acquisition failure rather than treating a failed reconciliation as complete.
CI jobs on this head terminate as failures within seconds and the substantive test jobs are skipped; this provides no validation signal for the changed Rust paths. I did not run local tests.
把安全模式细化为 Plan / Auto / YOLO 三态(S-1 挂起项落地),对齐主流 harness 的分层语义(Claude Code 6-mode、Codex 沙箱/审批分离、Gemini CLI plan<default<yolo 层级、opencode deny-survives-auto):
AppMode::Plan(底座只读归一)(false, Suggest)chat:guardrail_denied通告面为 Yolo 档专属)(true, Bypass)guardrail_ask_off)行为要点
Op::ChangeMode武装底座守卫面(底座 PR fix(prompt): 修复 bundle 技能提示词错误并登记 fork 提示词审查 #131);新会话按ask_on_guardrail_default偏好播种(单点 ctor,显式 sidecar 覆盖恒优先);计划任务/无人值守会话保持确定性 allow/deny 绝不弹卡,且规则档恒为 Full(for_engine_lane——无人值守 Yolo 不丢敏感面机械门)。ApprovalRequired分支按纯函数approval_surface_decision处置,定序为「会话拒绝 > Plan 防御硬拒 > force 弹卡 > 会话授予 > 姿态判定」(round-5 复审更正:force_prompt 卡压过授予缓存——授予臂为session_granted && !force_prompt,代码本就如此,仅表述修正);pending_approvals登记簿 + 按会话隔离的授权/拒绝记忆(授权按 lossy grouping key、拒绝按 exact key,镜像 TUI 语义;跨会话不得互相放行/连坐,跨 turn 存活、随会话删除摘除);decide_approval/get_pending_approvals命令(decision 先校验、缓存在 engine 调用成功后写入);重挂载回放(登记簿按设计进程内存态,跨重启不保真);chat:guardrail_denied拒绝通告不带敏感入参;decide_approval/set_session_mode/set_ask_on_guardrail/set_plan_mode_next/web_access_codex_acp_prompt进入多代理 Web 执行 denylist(get_pending_approvals保持可读)。SafetyRuleProfile{Full, Floor}——Yolo 会话只组装 never-sensible 底线族(Full 8,763 / Floor 3,555,双计数均有测试钉;敏感/底线分族按语义不按拼写);按模式热换 + spawn 期注入;无任何规则串改写、无 Deny→Ask 改标。SerializableMode::Auto降级数据保全——显式 Auto 折叠为"plan"落共享表、以true旗记入_session_auto_modes.json伴随表;旧二进制整表 strict 反序列化成功、其他会话选择不丢,新二进制读路径叠加伴随旗找回 Auto。pre_plan_mode——方案批准回到进 Plan 前的模式(fallback Auto),批准方案≠批准全自动;工作车道未绑定普通会话默认 Auto;辅助对话(aux)无自有模式控制,其模式记录在创建与复用两入口按父会话当期有效档初始化(pre-tri-mode 旧记录按「确认缺席」在复用时补初始化,非破坏性);_ask_on_guardrail.json侧车覆盖尚无 mode 条目的会话的开关写入;set_plan_mode_next/exit_plan_to_yolo与set_session_mode过同一存在性门、走同一条 sync +chat:mode_changed收敛序列(accept_plan由 plan 票据约束,docs §3.1 既定 carve-out)。sendMessageToSession,plan-stuck 补充指令含)与 aux 派发共享同一 per-session admission owner;队列 flush FIFO 唤醒按注册序,被拒队头保持优先,tokenless 等待者唤醒后复查会话队列并重排;accept_plan/editLastTurn持 owner 过栅栏查找;规则档广播受姿态串行门 + 有界发送 + 投递失败 Result 上传;审批恢复与快照发布受 workspace 代栅栏与引擎化身栅栏约束。Authority transition (host): …(底座 fix(prompt): 修复 bundle 技能提示词错误并登记 fork 提示词审查 #131 (b))。chat:mode_changed收敛点、PlanStuckCard Auto 选项、三语 i18n;任何档位进入 Yolo 都过同一条一次性确认门(Auto→Yolo 直达,Plan 退回走exit_plan_to_yolo;确认流带对话/条目代数栅栏),草稿态兜底与后端 resolved 默认一致,守卫开关草稿态禁用。accept_plan、edit_last_turn三入口姿态门 + 按会话去重三语通告;审批请求按审批 id 去重落系统通告(不静默);重放尊重终态栅栏;unsupported 能力明示;relay webui smoke 按活契约重写并有界等待。"auto"字面量。instruction_block括注与 Linux/macOS/Windows/unsupported 每轮 reminder 全部为三态真实语义(anchor 测试同步;旧文案零指纹登记)。提交(7 个,2026-11-12 整理)
a73cd9f6b12f564e6db40ceb94a8d2b846f946d2568db8474d34df1ff60b7f8c67441ae170539297d79011cba403d)链整理说明(2026-11-12):评审期累积的 205 个逐轮修复提交重组为以上 7 个按功能区并组的提交。最终树与最后一轮评审所覆盖的头
4401182e1(tree91bfea5a)逐字节一致——逐提交树断言后经 Git Data API 推送,未改动任何已评审内容;提交消息按仓约定(描述 ≤50、DCO trailer),旧链 27 处 DCO 作者/尾签身份不一致随之消除(本链 7 提交全部 sign-off == author)。评审期 inline 评论引用的旧 SHA 不再指向现存提交,其结论已吸收进本正文与下方评审史。验证(最终树凭据)
树身份:本链 tip tree ==
91bfea5a0a4814ac902a87add8777b751e49f7a5== 最后一轮评审+修复确认的头4401182e1的树(推送脚本逐步断言)。以下凭据均按该树记录。round-20 波全量电池:cargo
--lib --features benchmark-hooks --locked -- --test-threads=14,220 passed / 0 failed / 18 ignored(fmt、clippy-D warnings干净);cargo test全目标 4,134 / 0 / 57;node 1,498 tests / 1,482 passed / 0 failed / 16 skipped(含 FIFO 受理回归);relay unit 88/88;webui smoke 40/40;build:ui493,007 B < 494,000;lint:ui/lint:node/arch-guard/fork-guard fast/commit-msg 校验全绿。round-21 修复波(
4401182e1实测):cargo 全目标 4,134 / 0 / 18 + clippy-D warnings+ fmt 干净;engine_pool 广播投递失败面(Result 上传 + 调用方传播)、web 直发漏排水恢复、codex 门条目代数栅栏三项修复各带变异红臂(swallow→Ok-logging 红、callermap_err摘除红)。突变抽查:历轮累计 40+ 探针(底座武装门、姿态映射、admission 复查、FIFO 唤醒序、代栅栏、boot 幽灵清扫、web 兜底等)全部按预期转红后逐字节还原;逐轮记录见评审史链接的评论。
CI:required gate 因账号 billing 锁定未启动(repo-wide 在案披露);门禁结论以本地实测为准,合并队列在合并树复核。
提交消息:
validate-commit-msg.py --range全链过。run-dev 手动 smoke(6 场景)待模型机执行(本机无 vLLM 端点)。机器可验等价物全绿:Auto 卡→本会话允许(pending_approvals 真值表 + approval_card_lane + forwarder 分支);开关 OFF 拒+通告(truth table + 通告钉);YOLO mkfs 探针卡/静默(底座 deny-face/forced-hold 武装/未武装端到端);Plan accept→回原模式(
pre_plan_modeclaim 测试);轮中翻转→transition 行 + 规则集热换(底座 transition/preview 哈希钉 + publish 序列钉);子代理武装继承(held-call + delegated typed-ask 双镜像钉)。已知边界与披露(均非静默;详见 docs/safety-modes.md §9 与模块文档登记项)
get_pending_approvals回放。set_ask_on_guardrailno-op override 累积。ask_on_guardrail_default无产品 UI(settings.json 手改;机制完整——getter/setter/播种/镜像全钉,如实披露)。get_mode_state失败时姿态门 fail-open;relay smoke 的 tri-mode 面无独立 unit(行为由 FIFO 套件覆盖)。%HOME%、Git Bash${userprofile}寄存拼写)。评审历史(21 轮,2026-10-31 → 2026-11-11)
JensenChen28 于 round-20/21 收官头分别给出 APPROVED(11-10、11-11);zhuowp 的 round-21 三项 P2 已修复并逐项 inline 确认,待其复审。