claw-code 源码详细分析:Parity Audit——如何用工程对比把「像不像」从口水战变成可重复报告?

涉及源码src/parity_audit.pysrc/reference_data/archive_surface_snapshot.jsoncommands_snapshot.jsontools_snapshot.jsonsrc/main.pytests/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_targetsmissing_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_ROOTARCHIVE_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_auditCURRENT_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. 如何把报告用得「更工程」

  1. PR 模板 :要求贴 python3 -m src.main parity-audit 输出(有归档环境时)。
  2. 趋势 :把 ParityAuditResult 五元比例 随时间画线(CI artifact),看移植是否在收敛。
  3. 扩展维度 :在不动现有字段的前提下,可增加 Rust workspace 指标behavioral parity 用例通过数 等,仍通过 dataclass + to_markdown 输出,保持「一次运行、一份报告」。
  4. 无归档 CI :对 run_parity_audit() 的数值做 结构化导出 (JSON),避免依赖被 archive_present 截断的 Markdown。

8. 小结

  • Parity Audit冻结参考 JSON + 显式 TS→Py 映射 + 本地 src/ 扫描 + 快照条目计数 ,把「像不像」压成 可重复的 ParityAuditResult
  • to_markdown() 提供 人类可读、可贴 PR 的固定格式;archive_present 控制是否输出完整指标,体现 数据治理(无归档不强装完整对比)。
  • 测试 把关键门槛 编码为断言 ,使「像」在 有归档的开发环境 下成为 门禁 而非口头禅。

相关推荐
曲幽2 分钟前
FastAPI + Pydantic 模型终极实战手册:从能跑就行到固若金汤,这些技巧你一定用得上
python·fastapi·web·model·field·pydantic·validator·basemodel
哥不是小萝莉4 分钟前
OpenClaw vs Hermes Agent
ai
基因改造者1 小时前
Hermes Agent 配置指南
人工智能·ai·hermes agent
Java小白笔记2 小时前
OpenClaw 实战方法论
java·开发语言·人工智能·ai·全文检索·ai编程·ai写作
遇见火星2 小时前
OpenAI Codex 使用教程
ai·openai·codex
Irissgwe5 小时前
LangChain快速上手
ai·langchain·llm·ai编程
多年小白6 小时前
谷歌第八代 TPU 来了:性能提升 124%
网络·人工智能·科技·深度学习·ai
Captain_Data7 小时前
AI 12小时设计CPU完整解析:从219字到RISC-V内核的技术突破
人工智能·python·ai·大模型·芯片设计·risc-v
前端摸鱼匠7 小时前
【AI大模型春招面试题27】字节对编码(BPE)的分词过程?如何处理未登录词(OOV)?
人工智能·ai·面试·大模型·求职招聘
多年小白9 小时前
AI 日报 - 2026年4月25日(周六)
网络·人工智能·科技·深度学习·ai