Add docs/agent-handoff (backlog, execution state, verification, platform plan, per-task evidence), repo AGENTS.md, and architecture notes updated for the dual-renderer design.
46 lines
4.0 KiB
Markdown
46 lines
4.0 KiB
Markdown
# P0-01 配置路径与测试隔离 — 执行证据
|
||
|
||
日期:2026-09-16(无人值守轮次)
|
||
平台:Windows 11 10.0.26200 x64 · Python 3.10.21(`.venv`)· PyQt6/Qt 6.10.0/6.10.2 · 离屏 `QT_QPA_PLATFORM=offscreen`
|
||
|
||
## 根因(源码确认)
|
||
|
||
1. `core/llm_engine.py` 模块常量 `CONFIG_PATH` + `_load_config()` 不读 `HAOCODE_CONFIG_FILE` → 三个 Qt worker(Agent/Chat/Title)直接读项目内真实配置。
|
||
2. `ui/views/main_window.py:3133`(webview_backend 分支)与 `:5244`(`init_model_popup`)直接 `open(data/config.json)`,绕过环境变量。
|
||
3. `ui/views/bash_panel.py` 有私有的环境变量解析(双入口,非统一)。
|
||
4. `core/db_manager._DEFAULT_DB` 为模块级全局,测试在 import 前重定向的既有模式成立,沿用。
|
||
|
||
## 修复摘要
|
||
|
||
- 新增 `core/config_paths.py`:`config_path()`(`HAOCODE_CONFIG_FILE` 优先、调用时解析)+ `load_config()`(缺失/损坏/非对象 → 可见警告 + 安全空 dict,不抛异常)。
|
||
- `core/llm_engine.py`:删除 `CONFIG_PATH` 常量;`_load_config()` 委托 `load_config()`(保留函数名兼容既有调用方)。
|
||
- `ui/views/main_window.py`:两处直接 open 改走 `core.config_paths.load_config`。
|
||
- `ui/views/bash_panel.py`:`_cfg_path()` 委托统一 `config_path()`,删除私有 `_CFG_PATH` 常量。
|
||
- 新增 `tests/_test_env.py`:`isolate(tag, config)` 统一创建临时配置 + 临时数据库并在 import MainWindow 前完成重定向。
|
||
- 改造 3 个在范围测试使用统一临时环境:`tests/smoke_bash_panel.py`、`tests/test_error_persist.py`、`tests/test_agent_core.py`(provider 用例改读临时配置中的 `testprov`,不再依赖真实配置)。
|
||
- 新增 `tests/test_config_isolation.py`:open/sqlite 拦截器 + 缺失/损坏/非对象回归 + AST 静态扫描。
|
||
|
||
## 定向测试(命令 / 退出码 / 结果)
|
||
|
||
| 命令 | 退出码 | 结果 |
|
||
|---|---|---|
|
||
| `python tests/test_config_isolation.py` | 0 | ALL PASS(14 项断言) |
|
||
| `python tests/test_error_persist.py` | 0 | 39 PASS(与交接基线 39 一致) |
|
||
| `python tests/smoke_bash_panel.py` | 0 | 116 PASS(与交接基线 116 一致) |
|
||
| `python tests/run_tests.py`(test_agent_core.py 的仓库标准运行方式,pytest 由 harness stub) | 0 | 41 passed, 0 failed(与交接基线 41 一致) |
|
||
|
||
注:`python tests/test_agent_core.py` 直接运行在本仓库不可用(文件无独立 runner 且 .venv 不装 pytest,见 requirements.txt 说明),按其设计经 `tests/run_tests.py` 运行;P2-04 聚合入口将统一固化该运行方式。
|
||
|
||
## 完成证据对应
|
||
|
||
- **拦截器证明**:MainWindow 构造 + `save_panel_width` 写回全程,所有 `config.json`(含原子写 `.tmp`)打开路径均位于 `tempfile.gettempdir()/haocode_test_cfgiso_<pid>/`;真实配置路径(仅以字符串比较)从未出现在打开记录中。未读取、未散列真实配置。
|
||
- **临时配置读写**:`llm_engine._load_config()` 读到 `testprov`;`save_panel_width(340)` → `load_panel_width() == 340`,写路径落临时目录。
|
||
- **数据库隔离**:sqlite3.connect 拦截记录中临时库之外零连接/写入。
|
||
- **缺失/损坏/非对象**:三个回归用例均返回 `{}` 且 stdout 含明确警告(`[config] 配置文件缺失/读取/解析失败/不是 JSON 对象`),进程正常退出。
|
||
- **静态扫描**:`core/`、`ui/`、`tools/`、`main.py` 中除 `core/config_paths.py` 外不存在 `config.json` 字符串字面量(AST 级,docstring/注释排除)。
|
||
|
||
## 观察项(未扩范围,留待后续)
|
||
|
||
- `tests/smoke_offscreen.py`、`smoke_mode.py`、`smoke_copy_session.py` 只重定向了数据库、未设置 `HAOCODE_CONFIG_FILE`(不在 P0-01 允许修改清单内)。本轮运行这些套件时在启动环境显式导出临时配置;P2-04 聚合入口将按子进程强制注入临时环境,彻底闭环。
|
||
- `tests/diag_live_agent.py:19`、`tests/tune_model_popup.py:155` 直接引用真实配置路径;二者属 live/tune 人工脚本,默认聚合排除。
|