--- name: verify-rotator description: 按改动范围验证 rotator 的语法与隔离测试,检查依赖并报告未验证边界;用于提交前或修改后的主动验证。 disable-model-invocation: true --- # 验证 rotator ## 选择范围 从仓库根目录执行,先说明本次范围和选择理由。 1. `$ARGUMENTS` 接受单个 `python`、`server`、`router`、`substore`、`hooks` 或 `all`。未知值或未支持的组合先澄清,不作为 Shell 命令执行,也不退化为 `all`。 2. 用户只要求计划、解释或整理已有日志时,不执行验证命令。模拟快照、历史日志与本次实测分开标注,不用真实工作区状态替换用户指定的模拟输入。 3. 无参数时读取 `git status --short`、`git diff --stat`、`git diff --cached --stat`,再查看相关未暂存、已暂存差异和未跟踪文件。diff 不包含未跟踪内容,不能仅看 diff 就判定无改动;只读必要文件,不重新扫描全仓。 4. 纯说明文字修改只核对事实、路径和命令,不默认运行单测。无改动且无法从用户请求确定范围时先澄清;明确指定的范围不要求工作区必须有改动。 | 改动位置 | 默认范围 | | --- | --- | | `scripts/domain_updater.py`、`scripts/rotator/`、Python 配置及对应测试 | `python`;涉及 Server CLI/IPC 契约时加 `server`,涉及打包参数投影时加 `router` | | `scripts/server/`、`tests/test_server_mode_lifecycle.py` | `server` | | `scripts/router/`、`configs/config_router.conf`、`build_router_package.sh`、`tests/test_router_scripts.py` | `router` | | `substore/`、`tests/test_substore_operator.py` | `substore` | | `.claude/hooks/`、Hook 设置、`tests/test_syntax_hook.py` | `hooks` | | `tests/test_shell_lifecycle.py` | 根据改动方法选择 `server`、`router` 或两者;打包清理保护属于 `router` | 交叉改动取受影响范围的并集,并对测试去重。新增测试按其覆盖的行为归组,不因文件未出现在表中就静默忽略。 ## 隔离与预检 - 不运行真实 API 更新、cfst 测速、HTTP 服务、真实安装/卸载或当前工作仓库的 Server 调度脚本;不提交、推送或访问 Git 远端。下列测试中已隔离的模拟命令、无远端临时仓库和临时文件可以使用。 - Server 集成测试必须先准备本地模拟 API 和无远端临时仓库,再禁用推送。`GIT_PUSH_ENABLED=0` 不会阻止 `ls-remote` 或 `fetch`。 - 当前 `test_server_mode_adaptive_interval_window` 在模拟 API 配置前执行首次调度,可能访问真实 API,默认不运行。修复需把模拟配置移到首次调度前并固定时钟;验证任务不擅自修测试、删除断言或吞掉失败。 - Python 核心测试包含向回环地址发起请求的故障模拟,不是完全不使用网络。Server 的受控用例使用 `file://` 数据;本地 cfst 用例使用临时 CSV 与 `skip_run=True`。 - `all` 是下列受控组的并集,不是 discovery。执行前静态核查新增/修改测试的模块顶层、包初始化、fixture/helper 和涉及脚本的隔离条件;不要用导入或 discovery 来“仅列出”未经审阅的测试。整模块命令会纳入新增方法,必要时拆成已审阅的精确选择器;不能确认隔离的项列为未验证。 按检查项预检依赖,缺失只阻塞对应项,不自动安装工具或伪造资产。Python 使用 3.9+;核心测试无需 pip 依赖或编译,Sub-Store 验证无需 npm 依赖。 | 检查项 | 主要依赖 | | --- | --- | | Python 测试、Router 三项源码契约、Hook 单测 | Python;Hook 单测 mock 外部检查器,不需要 Node/Bash/jq | | Server 测试 | 按选择器检查 Python、Bash、Git;源码断言不需要启动 Git | | Router/打包 Shell 语法;打包清理保护测试 | sh;清理保护测试另需 Python,不需 cfst/BusyBox | | Sub-Store 语法;Sub-Store 单测 | Node;单测另需 Python | | Hook 注册查询;检查器直测 | 查询需 jq;直测需 Python 及目标文件对应的解释器 | | Router SSOT 打包测试 | Python、sh、打包工具、cfst 实际文件及 BusyBox 文件,见下文 | 缺少 Git 但已明确范围时,不阻塞无关检查;缺少 jq 也不阻塞 Hook 单测。 ## 语法与配置检查 只选涉及范围的命令和已审阅文件,Shell 逐文件检查。Python 示例不覆盖全部测试;按需补充本次涉及的测试文件,不无条件编译 `tests/*.py`。 ```sh # python 范围示例:缓存重定向到 /tmp PYTHONPYCACHEPREFIX=/tmp/pycache python3 -m py_compile scripts/domain_updater.py scripts/rotator/*.py # hooks 范围 PYTHONPYCACHEPREFIX=/tmp/pycache python3 -m py_compile .claude/hooks/check_syntax.py tests/test_syntax_hook.py # 分别用于 server、router、substore 范围;多文件逐一检查 for f in scripts/server/*.sh; do bash -n "$f" || exit 1; done for f in scripts/router/*.sh build_router_package.sh; do sh -n "$f" || exit 1; done node --check substore/operator_template.js # 仅对涉及的配置执行:不请求 API、不测速、不写运行时文件 python3 -B scripts/domain_updater.py --config configs/config.server.json --print-output-settings python3 -B scripts/domain_updater.py --config configs/config.local.json --print-output-settings # Hook 注册查询:还须核对打印的命令确实指向项目检查器 jq -e '.hooks.PostToolUse[] | select(.matcher == "Write|Edit") | .hooks[] | select(.type == "command") | .command' .claude/settings.json ``` 语法检查不执行目标代码,不能代替行为测试。Hook 仅覆盖 Write/Edit 事件,不覆盖通过 Bash 改写文件的操作。 ## 按范围运行测试 ### python ```sh PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_domain_updater tests.test_cfst_local_lifecycle # 单用例示例:无网络与测速,不写仓库运行时文件 python3 -B -m unittest -v tests.test_domain_updater.TestDomainUpdaterP0P1Bugs.test_modular_rotator_package_architecture_and_facade_integrity ``` ### server 以下用例在临时仓库中操作 Git,不执行真实安装。`INVOCATION_ID` 避免调度脚本尝试手动 journald tee。保留三个 Server 精确方法,不扩成整类或整模块,以免纳入时间窗口用例。 ```sh env PYTHONDONTWRITEBYTECODE=1 INVOCATION_ID=local-validation python3 -m unittest -v \ tests.test_shell_lifecycle \ tests.test_server_mode_lifecycle.TestServerModeFullLifecycle.test_server_mode_full_lifecycle_api_fetch_and_git_commit \ tests.test_server_mode_lifecycle.TestServerModeFullLifecycle.test_server_mode_fallback_and_silent_skip \ tests.test_server_mode_lifecycle.TestServerModeFullLifecycle.test_server_mode_rolling_history_prune ``` ### router 以下源码契约只需 Python,不依赖外部二进制: ```sh PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v \ tests.test_router_scripts.TestRouterScriptsBugsAndContracts.test_p1_router_local_update_atomic_file_write \ tests.test_router_scripts.TestRouterScriptsBugsAndContracts.test_p2_router_local_update_filters_zero_speed \ tests.test_router_scripts.TestRouterScriptsBugsAndContracts.test_recheck_correction_router_cfst_params_already_supported ``` 打包清理保护另需 sh;在临时目录触发配置缺失的前置失败,不需打包资产。`all` 已选整个 `tests.test_shell_lifecycle` 时不要重复执行此方法: ```sh PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_shell_lifecycle.TestShellLifecycleP0P1Bugs.test_p0_build_router_package_trap_prematurely_deletes_tmp_dir ``` SSOT 打包用例另需 Python、sh、打包工具和本地资产。检查 `build_router_package.sh` 中 `CFST_SRC_DIR` / `BUSYBOX_SRC` 的当前默认值及环境覆盖,确认 `CFST_SRC_DIR/cfst` 与 `BUSYBOX_SRC` 是实际存在的文件;目录存在不等于二进制存在。不要用 `--help` 探测,该参数会被忽略并继续打包。测试指定临时输出,不直接运行根目录打包命令;`--sync-from-config` 默认只改包内配置,不擅自使用 `--write-back` 回写源文件。 ```sh PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_router_scripts.TestRouterScriptsBugsAndContracts.test_build_router_package_ssot_sync ``` 缺少资产时保留源码契约和清理保护的验证,将 SSOT 打包项标为“未执行:缺少依赖”。打包成功只证明文件装配与配置投影,不证明目标路由器可运行。 ### substore ```sh PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_substore_operator ``` 此模块用 Node.js 内置 `vm` 测试辅助函数,不等于验证真实 Sub-Store HTTP、缓存与端到端选源。 ### hooks ```sh PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_syntax_hook ``` 修改 Hook 时,额外把实际 Write/Edit JSON 输入传给检查器,记录目标文件类型和返回码;不支持的文件、工具或仓库外路径返回 0 只是跳过,不能当作语法检查通过。 分别报告三种证据:注册配置核对、检查器直测、当前会话实际触发。jq 返回 0 不代表查到了目标检查器;配置与直测通过也不代表 Hook 已加载。新增或改变注册时需验证实际触发,并恢复验证用的临时修改、清理探针;未获准验证或未观察到触发时明确标为未验证,提示用户打开 `/hooks` 或重启后复核,不声称已生效。 ### 完整 discovery 只有静态核实所有测试(包括时间窗口用例)已隔离真实 API、时钟和发布,且具备全部依赖后,另行取得完整 discovery 的执行确认;`all` 不包含此授权: ```sh env PYTHONDONTWRITEBYTECODE=1 INVOCATION_ID=local-validation python3 -m unittest discover -s tests -v ``` ## 输出结果 用以下顺序简洁报告,不把计划或缺失证据算作通过: 1. **范围与理由**:所选范围、交叉覆盖和新增测试的纳入/未纳入原因。 2. **实际执行**:命令、退出码、测试运行数量与结果;语法、配置解析和行为测试分别记录。不推断未提供的计数。 3. **失败与未执行**:区分断言失败、加载/运行 ERROR、框架 skip、缺依赖/权限受阻/仅做计划等未执行项;保留失败原因,不自动修复。 4. **验证边界**:受控组不是全套;列明未运行的时间窗口用例(涉及 server/all 时)、Hook 的三种证据状态,以及与目标环境端到端验证的差别。 模拟输入、历史结果与本次实测分开标注。实际执行后检查 `git status --short`,保留用户原有修改,不清理不属于本次验证的文件。