涉及源码 :
src/parity_audit.py、src/reference_data/archive_surface_snapshot.json、commands_snapshot.json、tools_snapshot.json,src/main.py,tests/test_porting_workspace.py。
1. 要解决什么问题
大型移植里,「我们已经很像原版了」最容易变成 主观口水战 :有人看目录像,有人看 CLI 像,有人坚持行为仍不对。
Parity Audit 做的是:把「像」拆成 若干可计数、可写在 CI 里的维度 ,每次跑 run_parity_audit() 得到同一形状的 ParityAuditResult ,再 to_markdown() 成人类可贴进 PR 的段落------同一代码树 + 同一快照数据 ⇒ 同一数字,从而把争论从「我觉得」推进到「报告显示」。
重要边界 (与 README 一致):这些指标衡量的是 表面与清单维度的对齐倾向 ,不是 runtime 行为等价或法律意义上的「未侵权证明」。
2. 报告长什么样:ParityAuditResult + to_markdown
python
# 73:110:src/parity_audit.py
@dataclass(frozen=True)
class ParityAuditResult:
archive_present: bool
root_file_coverage: tuple[int, int]
directory_coverage: tuple[int, int]
total_file_ratio: tuple[int, int]
command_entry_ratio: tuple[int, int]
tool_entry_ratio: tuple[int, int]
missing_root_targets: tuple[str, ...]
missing_directory_targets: tuple[str, ...]
def to_markdown(self) -> str:
lines = ['# Parity Audit']
if not self.archive_present:
lines.append('Local archive unavailable; parity audit cannot compare against the original snapshot.')
return '\n'.join(lines)
...
五组核心度量(归档存在时才会在 Markdown 里展开):
| 字段 | 含义(分子/分母直觉) |
|---|---|
root_file_coverage |
归档根级 TS/TSX 映射表 中,当前 src/ 顶层 是否出现对应 .py 文件名 |
directory_coverage |
归档顶层 子目录映射表 中,当前 src/ 顶层是否出现对应包名/占位 |
total_file_ratio |
当前 src/ 下 .py 文件总数 vs 参考 JSON 中的 total_ts_like_files |
command_entry_ratio |
commands_snapshot.json 条目数 vs 参考 command_entry_count |
tool_entry_ratio |
tools_snapshot.json 条目数 vs 参考 tool_entry_count |
另有两份 缺失清单 :missing_root_targets、missing_directory_targets,直接给出 还没对齐的期望名,方便开 issue / 拆任务。
3. 「可重复」的数据从哪来
3.1 冻结的参考面:archive_surface_snapshot.json
路径:src/reference_data/archive_surface_snapshot.json。其中除列举根文件、根目录名外,还提供 分母:
python
# 60:62:src/reference_data/archive_surface_snapshot.json
"total_ts_like_files": 1902,
"command_entry_count": 207,
"tool_entry_count": 184
}
学习点 :分母不依赖你本机是否真有 archive/ 目录------它来自 随仓库提交的 JSON 。这样 CI 在无归档环境下仍能比较 「当前 Python 文件数 vs 某次钉死的 TS-like 文件数」 与 「当前快照条目数 vs 钉死的条目数」 (若 to_markdown 未因 archive_present 提前返回,见下节)。
3.2 显式映射表:ARCHIVE_ROOT_FILES / ARCHIVE_DIR_MAPPINGS
根级文件 一对一 期望(TS 名 → 当前 src/ 顶层应存在的 Python 文件名):
python
# 13:31:src/parity_audit.py
ARCHIVE_ROOT_FILES = {
'QueryEngine.ts': 'QueryEngine.py',
'Task.ts': 'task.py',
...
'main.tsx': 'main.py',
...
}
子系统目录 一对一 期望(归档目录名 → 当前 src/ 顶层应有 commands.py 或包名如 assistant):
python
# 34:69:src/parity_audit.py
ARCHIVE_DIR_MAPPINGS = {
'assistant': 'assistant',
...
'native-ts': 'native_ts',
...
}
学习点 :「像不像」里最容易扯皮的一块------根入口与顶层包是否齐 ------被钉死在两个字典里;改期望 = 改表 + 改代码审查,而不是聊天里重新定义。
3.3 本地探测:CURRENT_ROOT 与 ARCHIVE_ROOT
python
# 7:11:src/parity_audit.py
ARCHIVE_ROOT = Path(__file__).resolve().parent.parent / 'archive' / 'claw_code_ts_snapshot' / 'src'
CURRENT_ROOT = Path(__file__).resolve().parent
run_parity_audit 用 CURRENT_ROOT.iterdir() 的 顶层名字 与映射表比对;用 CURRENT_ROOT.rglob('*.py') 统计 全部 Python 文件数。
python
# 121:127:src/parity_audit.py
def run_parity_audit() -> ParityAuditResult:
current_entries = {path.name for path in CURRENT_ROOT.iterdir()}
root_hits = [target for target in ARCHIVE_ROOT_FILES.values() if target in current_entries]
dir_hits = [target for target in ARCHIVE_DIR_MAPPINGS.values() if target in current_entries]
missing_roots = tuple(target for target in ARCHIVE_ROOT_FILES.values() if target not in current_entries)
missing_dirs = tuple(target for target in ARCHIVE_DIR_MAPPINGS.values() if target not in current_entries)
注意 :archive_present 仅检测 ARCHIVE_ROOT.exists(),审计逻辑本身不读取归档内文件列表 ;对比的是 本仓库的 src/ 树 + 参考 JSON + 映射表。
3.4 archive_present 与 Markdown 输出的关系
当 本地无归档目录 时,to_markdown() 提前返回 ,上面那些 分子分母一行都不会打印:
python
# 86:88:src/parity_audit.py
if not self.archive_present:
lines.append('Local archive unavailable; parity audit cannot compare against the original snapshot.')
return '\n'.join(lines)
因此:
- 有归档 :适合贴完整 Parity Audit 段落进 PR。
- 无归档 :CLI 仍执行
run_parity_audit(),但对外报告 刻意缩短------提醒「无法对照本地快照」,避免误以为做过完整对比。
若要在无归档 CI 里 仍断言数字 ,应直接测 ParityAuditResult 字段(见下),不要只解析 Markdown。
4. 命令/工具条目:清单长度 vs 参考分母
python
# 133:135:src/parity_audit.py
total_file_ratio=(current_python_files, int(reference['total_ts_like_files'])),
command_entry_ratio=(_snapshot_count(COMMAND_SNAPSHOT_PATH), int(reference['command_entry_count'])),
tool_entry_ratio=(_snapshot_count(TOOL_SNAPSHOT_PATH), int(reference['tool_entry_count'])),
python
# 117:118:src/parity_audit.py
def _snapshot_count(path: Path) -> int:
return len(json.loads(path.read_text()))
学习点 :命令/工具「像不像」被操作化为 JSON 数组长度与钉死分母的比 。更新镜像清单时,可同时更新 archive_surface_snapshot.json 里的 command_entry_count / tool_entry_count(若归档侧枚举变了),否则会出现 「条目多了但分母旧」 的比值大于 1 的语义------维护者需在评审里约定 是否允许分子大于分母 或 同步 bump 参考值。
5. 如何变成「可重复」:CI 与测试
CLI:
python
# 104:106:src/main.py
if args.command == 'parity-audit':
print(run_parity_audit().to_markdown())
return 0
测试:
test_parity_audit_runs:子进程跑parity-audit,断言输出含Parity Audit(有无归档均过)。test_root_file_coverage_is_complete_when_local_archive_exists:仅当audit.archive_present时,断言根文件全覆盖、目录覆盖 ≥28、命令条目 ≥150、工具条目 ≥100。
python
# 45:51:tests/test_porting_workspace.py
def test_root_file_coverage_is_complete_when_local_archive_exists(self) -> None:
audit = run_parity_audit()
if audit.archive_present:
self.assertEqual(audit.root_file_coverage[0], audit.root_file_coverage[1])
self.assertGreaterEqual(audit.directory_coverage[0], 28)
self.assertGreaterEqual(audit.command_entry_ratio[0], 150)
self.assertGreaterEqual(audit.tool_entry_ratio[0], 100)
可重复报告 在这里体现为:开发者机器上有归档时,门槛测试必须绿 ;无归档时跳过强断言,但 test_command_and_tool_snapshots_are_nontrivial 仍对 PORTED_COMMANDS / PORTED_TOOLS 长度保底。
6. Parity Audit 没有回答什么(避免误用)
- 行为:不跑 TS/Python 双端 E2E,不对比 API 响应体。
- 质量:不衡量测试覆盖率、类型完整度。
- 安全/合规:不是法律或版权结论。
- 归档内容一致性 :不 diff 归档里每个文件与 Python 实现;只认 映射表 + 顶层存在性 + 文件计数 + 快照条目数。
仓库内 PARITY.md(Rust 侧)另有一套 功能差距 叙述,与 Python parity_audit 互补而非重复。
7. 如何把报告用得「更工程」
- PR 模板 :要求贴
python3 -m src.main parity-audit输出(有归档环境时)。 - 趋势 :把
ParityAuditResult五元比例 随时间画线(CI artifact),看移植是否在收敛。 - 扩展维度 :在不动现有字段的前提下,可增加 Rust workspace 指标 、behavioral parity 用例通过数 等,仍通过 dataclass + to_markdown 输出,保持「一次运行、一份报告」。
- 无归档 CI :对
run_parity_audit()的数值做 结构化导出 (JSON),避免依赖被archive_present截断的 Markdown。
8. 小结
- Parity Audit 用 冻结参考 JSON + 显式 TS→Py 映射 + 本地
src/扫描 + 快照条目计数 ,把「像不像」压成 可重复的ParityAuditResult。 to_markdown()提供 人类可读、可贴 PR 的固定格式;archive_present控制是否输出完整指标,体现 数据治理(无归档不强装完整对比)。- 测试 把关键门槛 编码为断言 ,使「像」在 有归档的开发环境 下成为 门禁 而非口头禅。