SKILL.md 10 KB


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。

# 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

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 精确方法,不扩成整类或整模块,以免纳入时间窗口用例。

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,不依赖外部二进制:

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 时不要重复执行此方法:

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 回写源文件。

PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_router_scripts.TestRouterScriptsBugsAndContracts.test_build_router_package_ssot_sync

缺少资产时保留源码契约和清理保护的验证,将 SSOT 打包项标为“未执行:缺少依赖”。打包成功只证明文件装配与配置投影,不证明目标路由器可运行。

substore

PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_substore_operator

此模块用 Node.js 内置 vm 测试辅助函数,不等于验证真实 Sub-Store HTTP、缓存与端到端选源。

hooks

PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v tests.test_syntax_hook

修改 Hook 时,额外把实际 Write/Edit JSON 输入传给检查器,记录目标文件类型和返回码;不支持的文件、工具或仓库外路径返回 0 只是跳过,不能当作语法检查通过。

分别报告三种证据:注册配置核对、检查器直测、当前会话实际触发。jq 返回 0 不代表查到了目标检查器;配置与直测通过也不代表 Hook 已加载。新增或改变注册时需验证实际触发,并恢复验证用的临时修改、清理探针;未获准验证或未观察到触发时明确标为未验证,提示用户打开 /hooks 或重启后复核,不声称已生效。

完整 discovery

只有静态核实所有测试(包括时间窗口用例)已隔离真实 API、时钟和发布,且具备全部依赖后,另行取得完整 discovery 的执行确认;all 不包含此授权:

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,保留用户原有修改,不清理不属于本次验证的文件。