把 AGENTS.md(545 行)中的项目知识按性质拆开,只留下对代理的要求: - AGENTS.md(176 行)只写规则:读文档指引、提交许可、等待规则、TDD、 测试规则(模块边界/三段结构/功能覆盖优先)、注释规范、目标运行环境、 PowerShell 规则、文档维护规则; - 项目信息新建 docs/ 专题:architecture、node-protocol、workflows、 configuration、operations、testing、decisions; - README 改为项目索引(定位、快速开始、文档导航、目录、工作流、结论摘要); - 修正旧文档错误:README 的"详细约定见 AGENTS.md"与"100% 行覆盖率" (pytest 已移除该门槛);环境变量表补齐 WOV_AUTO_VAD 等 3 项。 新增 scripts/check_doc_links.py 校验相对链接与锚点,当前 14 个文档全部可达。
12 KiB
12 KiB
AGENTS.md — VRSub 协作规则
本文件只写对 AI 编码代理的要求(行为规则、流程约束、执行环境)。 项目信息(架构是什么、有哪些节点、怎么配置)不写在这里,按需阅读:
| 想了解 | 阅读 |
|---|---|
| 项目定位、快速开始、目录结构、文档导航 | README.md |
| 架构、核心机制、北极星不变式、单体化说明 | docs/architecture.md |
| 节点输入输出协议、模型权重解析、长音频、OCR 并发 | docs/node-protocol.md |
| 内置工作流、参数标注约定、切换模型、产物命名 | docs/workflows.md |
| 环境变量全表、启动方式、uv 依赖管理 | docs/configuration.md |
| 批量处理、暂停/继续、孤儿清理、进度日志 | docs/operations.md |
| 测试资产清单、真实模型集成测试 | docs/testing.md |
| 设计决策与踩坑记录(含实验结论) | docs/decisions.md |
| 代码缺陷跟踪与修复验收标准 | docs/代码审查问题跟踪.md |
开工前先做两件事:读 README.md 建立项目认知, 再读 docs/architecture.md 确认不能破坏的硬约束。
提交规则(强制,2026-08)
- 未经用户明确许可,禁止执行
git commit/git push,包括"小步提交"。 - 完成改动后只汇报改动内容与验证结果,等待用户指示;用户明确说出 "提交 / push / 推上去" 等指令时才可执行提交。
- 需要用户确认的场景:新增功能、修复、文档改动、工作流/清单数据改动等 一切涉及 git 写操作的行为。
等待规则(强制,2026-09)
- 单次等待时间不得超过 10 秒。需要长时间运行时,把它放到后台
(
setsid ... &/nohup ... &)写日志,然后每 10 秒轮询一次结果 (for i in $(seq 1 6); do sleep 10; ...; done),而不是用一个长sleep或长timeout把用户的对话阻塞住。 - 反例(禁止):
sleep 600、timeout 1800 uv run pytest——即使命令本身 很快,把 timeout 设成 30 分钟也是错的:它无法预判耗时,只会在出问题时 让用户白等半小时。应当先用 10 秒轮询确认它是否结束。 - 正例:把任务丢后台 →
for i in $(seq 1 N); do sleep 10; <检查是否完成 && break>; done; 耗时任务写日志到data/experiments/...,事后读日志汇报。 - 测试与构建也遵循此规则:已知
uv run pytest全量约 70 秒,用后台+轮询, 不要写timeout 1800。
开发流程:TDD(红-绿-重构)
- 任何新功能/修复必须先写失败测试(红),再实现最小代码让其通过(绿), 最后重构保持整洁;不允许先写实现后补测试。
- 小改动只跑相关测试,避免每次都完整跑全量测试;改动影响面大时才跑全量。
- 测试运行方式与资产说明见 docs/testing.md。
测试规则
模块的边界
「模块」指由独立功能、在程序运行时会真实被使用到的代码块构成的代码上下文:
它可独立运行,也可和其他代码上下文组合运行。
例如 nodes/whisper.py、nodes/llm_filter.py、src/wov_app/batch.py、
src/wov_sdk/models.py 各是一个模块;nodes/subtitle_ocr.py 与其
nodes/adaptive_pool.py 是两个模块(后者可独立使用)。
按模块组织测试代码
- 测试代码必须按模块编写:一个模块对应测试目录下的一个模块目录, 不得把同一模块的测试拆成多个互不相干的平铺文件。
- 单文件过长时,在同一模块目录内拆成多个文件(按行为分组,如
test_rules.py/test_llm_layer.py),而不是拆到模块目录之外。 - 目录布局固定为
tests/<层级>/<模块>/,<层级>对应被测代码位置 (nodes/→tests/nodes/,src/wov_app/→tests/app/,src/wov_sdk/→tests/sdk/),模块目录名即模块名。 - 每个模块目录必须有
__init__.py,保证不同模块目录下的同名测试文件可共存。 - 具体目录示例见 docs/testing.md。
数据 / 测试过程 / 验证结果
- 每个测试必须写成数据 → 测试过程 → 验证结果三段结构:先准备输入数据, 再调用真实生产代码,最后断言输出结果;顺序清晰、一读即懂。
- 测试必须可独立运行:单个测试文件或单个模块目录被单独执行时结果不变。
不依赖全局
conftest.py(不保留全局 conftest),不依赖仓库其他测试的 配置、执行顺序或共享状态。 - 数据与产物目录就是测试代码所在目录:模块专用数据(JSON/期望输出等)
写在测试代码内的常量或模块目录下;视频、音频等无法写进代码的大体积素材,
放同一个模块目录内(如
data/)与其他测试区分,不使用仓库根级中央数据目录。 - 测试过程必须调用真实的生产代码(导入
nodes/、wov_app、wov_sdk的真实实现),我们只构建测试数据、验证输出结果; 不得在测试里重写业务逻辑来模拟被测功能,也不得用伪造结构冒充被测数据。 - 需要磁盘或环境隔离时,由模块自己的 fixture(模块目录下的
conftest.py或测试文件内部)创建临时目录并设置变量,不依赖外部预先存在的配置。
功能覆盖优先,不追求代码覆盖率
- 不追求测试的代码覆盖率 100%,追求功能性代码覆盖率 100%。
- 一个大模块的功能正常,就无须对这个大模块中的辅助函数单独测试: 私有工具函数、内部转换、仅供主流程调用的分支,由主功能用例顺带覆盖即可, 不为了凑行覆盖率给辅助函数补无意义用例。
- 但每个独立功能模块必须被测试覆盖(即上文“模块的边界”中定义的模块), 不得出现“完全无测试的模块”。模块清单与当前覆盖状态见 docs/testing.md。
- 新增独立功能模块时,必须同时补上覆盖其功能的测试,并同步更新上述清单; 只写生产代码不补测试的改动视为未完成。
测试质量与运行
- 测试以保证功能可用为目标,不强制 100% 行覆盖率(pytest 已移除
--cov-fail-under=100门槛);需要查看覆盖率时可手动追加uv run pytest --cov=src --cov=nodes。 - 测试必须使用真实数据:真实音频(合法 WAV/PCM)、真实 JSON/数据库/文件;
禁止用占位字节(如
b"x")或伪造结构冒充被测数据——假数据测试只能凑覆盖率, 无法验证真实行为,视为无意义测试。 - 只允许在 I/O 边界使用 mock/stub:文件系统、网络、子进程、环境变量、时间、 模型推理(重模型不进入单元测试;注入的假模型必须返回结构真实的分段)。
- 真实模型集成测试必须配套:真实 faster-whisper 模型 + 真实音频素材验证 端到端转写,本地缺模型/素材时跳过,有则必须执行(清单见 docs/testing.md)。
- 测试素材必须一次性准备后随模块目录入库(放模块目录内),禁止在测试执行时 现场生成;缺失时跳过而非生成。
- 外部环境状态缺失时应跳过而不是判失败:未配置的密钥、账户余额/配额、
限流、模型/服务不可达、缺失的真实素材都属于环境状态,不是被测代码的行为;
这类用例用
pytest.skip()并说明原因(如pytest.mark.integration用例)。 但代码抛异常、返回结构错误、断言不成立仍必须失败,不得用跳过掩盖回归。 - 测试只保证代码路径被执行,不覆盖端口占用、防火墙、权限等外部环境状态; 端口问题用启动检查、端口检查与 uvicorn 冒烟测试补充。
- 本地出现
WinError 10013/WinError 10048时,先用netstat -ano | findstr :<port>确认是否有残留监听进程。
代码注释规范
- 本仓库所有源码(Python、JavaScript、HTML、CSS、TOML 等支持注释的文件) 必须配有详细中文注释,说明模块/文件职责、核心类与函数的作用以及关键逻辑, 确保后续维护人员无需通读全部实现即可快速理解工作原理。
- 新增或修改代码时,必须同步补充或更新对应注释;不得删除已有注释。
- 测试代码同样必须配有中文注释,说明每条测试验证的行为与覆盖的路径。
- JSON 数据文件(如
manifests/*.json、workflows/*.json)按 JSON 规范不支持 注释,字段语义以src/wov_sdk/models.py的模型注释和 docs/ 文档为准; 修改 JSON 字段时须同步更新文档。
目标运行环境
- 本服务的最终部署目标是 Linux,通常以 Docker/Kubernetes 容器运行。
- 当前 Windows 只作为本地开发环境,不允许在业务代码中写死 Windows 路径、 盘符或 Windows 专用命令。
- 路径处理统一使用
pathlib。 - ffmpeg 在 Linux 上可使用系统包,也允许通过
imageio-ffmpeg使用内置 二进制,节点代码不能假设 ffmpeg 一定在 PATH。 - 测试必须可以在 Windows 和 Linux 上运行;涉及平台分支的代码应同时覆盖 两种路径解析。
Windows / PowerShell 执行规则
- 默认 shell 视为 Windows PowerShell 5.1;不要假设 Bash、zsh 或 PowerShell 7。
必要时先查
$PSVersionTable.PSVersion。 - 禁止把 Bash 语法交给 PowerShell:
python - <<'PY'、cat <<EOF、export、source、rm -rf、Bash 后台&等。 - PowerShell 中
&是调用运算符;URL 或参数含&时整体单引号引用。 - 避免 PowerShell 5.1 下使用 Bash 风格
&&/||;顺序步骤用多行 PowerShell。 - 参数含空格、括号、中文、
&|;><$或引号时默认用单引号。 - 外部程序路径可能有空格时,用
& 'C:\path with spaces\tool.exe' arg1。 - 文件操作优先 PowerShell 原生命令和
-LiteralPath。 - 复杂 Python 不用
python -c;涉及 SQL、JSON、中文、反斜杠、换行或 多层引号时,用仓库脚本或临时.py文件。 - 禁止在 PowerShell 用 Bash here-doc。临时传 Python 源码只允许 PowerShell here-string,且尽量保持 ASCII。
- Python 源码含中文常量时,不通过 PowerShell 管道传给
python -;用 UTF-8 脚本文件、仓库脚本或\uXXXX。 - 搜索文本/文件优先
rg/rg --files。 - 数据库或生产内容写操作前先查询当前数据;写入必须有明确筛选条件,禁止
无条件
DELETE/UPDATE。 - 同一 PowerShell 命令连续失败两次后,停止微调长命令;改短命令、脚本文件、 数组 splatting 或分步验证。
文档维护规则
- 本文件只放对代理的要求。新增项目知识(架构、协议、参数默认值、运维语义、 实验结果)写进 README.md 或 docs/ , 不得写进本文件。
- 新增/移动文档时同步更新 README 的文档导航表与本文件顶部的索引表, 保证链接可达;文档中的相对链接指向真实文件。
- 决策与踩坑("为什么这样做")写 docs/decisions.md, 缺陷跟踪写 docs/代码审查问题跟踪.md, 专题文档只保留结论并链接过去,避免同一内容多处维护。