修复: workspace_root 去固定根完整(reload 尊重用户 persistent)
CR-28 审查 🟡 WATCH-1:reload_allowed_dirs 仍无条件 insert workspace_root(pre-existing), 致 commit 声称"用户删白名单后需授权"无法兑现(reload 塞回 persistent)。 修:reload KV 有配时不无条件 insert workspace_root,尊重用户 persistent。 (仅 KV 未配 default_with_root 含 workspace_root,首次免授权行为不变) CR-28 审查回填(✅ PASS,🟡 WATCH-1 已修闭环)。
This commit is contained in:
29
docs/待审查.md
29
docs/待审查.md
@@ -1401,6 +1401,35 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### CR-260619-28 idea source 溯源 + workspace_root 去固定根 + run_command 偏好修复(·commit e4c2e31) — ✅ 已审(PASS·🟡1 WATCH)
|
||||||
|
|
||||||
|
- **结论(2026-06-20·独立 git show e4c2e31 + grep/read 核验 6 文件源码形态 + cargo test 全跑)**: ✅ **PASS** — 🔴0 🟡1 ⚪1
|
||||||
|
- **验证**: `cargo test -p df-ai` 228 passed 0 failed / `cargo test -p devflow idea_source` 14 passed(11 单元 + 3 全链路对抗)/ `cargo check --workspace` EXIT 0 无 warning。
|
||||||
|
- **6 文件 diff 逐一核验**(git show e4c2e31):
|
||||||
|
|
||||||
|
| # | 维度 | 判定 |
|
||||||
|
|---|------|------|
|
||||||
|
| 1 | idea source 保守五条件(idea_source.rs) | ✅ IDEA_SOURCE_AUTO_FILL_ENABLED 开关(:19)+ tool_name=="create_idea"(:65)+ is_source_unfilled 不覆盖(:71)+ message_id Some 非空(:76)+ result.id extract(:84)。5 条件全到位 + best-effort warn 不阻断(:118-122) |
|
||||||
|
| 2 | workspace_root 去固定根(state.rs) | 🟡 部分兑现(见 WATCH-1) |
|
||||||
|
| 3 | run_command 描述收紧(tool_registry.rs) | ✅ 新描述「仅用于命令执行场景:跑测试套件/构建项目/运行二进制」+ 负向引导「读取文件用 read_file/编辑用 patch_file/write_file/列目录用 list_directory/搜索用 search_files——不要用本工具完成」(:1572) |
|
||||||
|
| 4 | ToolDomain::Exec(intent.rs) | ✅ enum 加 Exec(:238)+ Exec.tools()=&["run_command"](:279)+ tool_subset_for Debug 含 Exec(:357)/Code/File/Search 不含 + 对抗测 run_command_only_exposed_for_debug_intent(:878) |
|
||||||
|
| 5 | 注册顺序(tool_registry.rs) | ✅ run_command 从 File 层首位移至末位(:1566-1636),baseline 集合 18+10+1=29 不变(sort 对齐测 :1850-1874) |
|
||||||
|
| 6 | DEBUG_RULES 关键词(intent.rs) | ✅ 运行/执行/构建/测试 0.7 + 跑 0.6(:122-127),中等权重避误抢 Code(编译/重构 1.0) |
|
||||||
|
|
||||||
|
**关键对抗核验(防污染)**:
|
||||||
|
- chat.rs:504 `audit_status`/`result_val` 在 :477 已 binding(match exec_result),:504 引用合法非未定义 ✅
|
||||||
|
- chat.rs:513 `last_assistant_message_id()` 方法存在(context.rs:520,CR-260619-22 已加 4 对抗测)✅
|
||||||
|
- idea_source.rs:108 `update_field(id,"source",val)` 走 IdeaRepo → crud/mod.rs:141 validate_column_name → "source" 在 ideas 白名单(settings.rs:122)✅
|
||||||
|
- low_risk 路径(audit/mod.rs:533)注释自承「create_idea 不会进(Medium→pending)」,代码仍写完成防御/未来级别覆盖 ✅
|
||||||
|
- 集合 baseline 测试 tool_registry.rs:1850 与新注册顺序对齐(注释明确 sort 与顺序无关)✅
|
||||||
|
|
||||||
|
- **🟡 WATCH-1**: **workspace_root 去固定根「动态白名单完整语义」声明部分兑现** — `state.rs:362-365` 删除固定放行成立(diff 核验),但 `reload_allowed_dirs`(:577)仍无条件 `set.insert(workspace_root_path())`(pre-existing 非 e4c2e31 引入)。即用户从 Settings KV 删除工程根后,下次 reload 会强制把工程根塞回 persistent → `is_authorized` 经 persistent 命中照样放行 → 「用户删白名单后需授权」的预期无法兑现。本次只删了 is_authorized 的硬编码,未触及 reload 兜底注入。**非破坏性**(默认行为不变向后兼容),但 commit message「动态白名单完整语义」与实现存在落差。无对应「删除白名单后需授权」的对抗测印证(test_allowed_dirs_workspace_root_authorized:741 用 default_with_root 经 persistent 命中,不覆盖删除场景)。
|
||||||
|
- **⚪ LOW-1**: DEBUG_RULES 5 关键词权重(0.6-0.7)为经验值,无量化校准依据(db 分析 591ff4a0 仅统计偏好率未回归权重调优)。后续可据真实意图误判数据校准。
|
||||||
|
|
||||||
|
- **待修项回流 todo**: **无** 🔴/🟡 项(🟡 WATCH-1 已修:reload_allowed_dirs 删无条件 insert workspace_root,KV 有配尊重用户 persistent,兑现"用户删白名单后工程根需授权"动态白名单完整语义)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 已审归档
|
## 已审归档
|
||||||
|
|
||||||
> 已审 CR 段迁独立文件: [待审查归档/2026-06.md](./07-项目管理/待审查归档/2026-06.md)
|
> 已审 CR 段迁独立文件: [待审查归档/2026-06.md](./07-项目管理/待审查归档/2026-06.md)
|
||||||
|
|||||||
@@ -573,8 +573,9 @@ impl AppState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
// workspace_root 始终在白名单(向后兼容);不重复插入
|
// F-260619-03 收尾:KV 有配时尊重用户 persistent(不无条件塞 workspace_root)。
|
||||||
set.insert(workspace_root_path());
|
// 用户 KV 配置不含 workspace_root → 工程根也需授权(动态白名单完整语义,
|
||||||
|
// 兑现 commit 声称"用户删白名单后需授权")。仅 KV 未配时 default_with_root 含 workspace_root。
|
||||||
for d in dirs {
|
for d in dirs {
|
||||||
let d = d.trim();
|
let d = d.trim();
|
||||||
if d.is_empty() {
|
if d.is_empty() {
|
||||||
|
|||||||
Reference in New Issue
Block a user