CodexBar #2037 Fork 家族重复计数修复:净化 Fixture 与手算 Oracle 的设计与验证
【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar
本文围绕 CodexBar 仓库中针对 issue #2037(Ultra / forked-session token 重复计数)落地的一枚 P0 级黄金数据(golden fixture)——archived-fork-33ce-3869,讲解净化(sanitized)Codex 本地日志如何被塑造成可复现、可断言的叉族(fork family)重复计数测试样本:从ORACLE.md的手算基准、manifest.json的机读契约,到Issue2037ProvenanceFixtureTests与Issue2037ScannerIntegrationTests两层测试如何把“父进程拥有复制前缀(parent-owns-prefix)”的期望固化为回归防线。读完你将掌握该 fixture 的完整算术、净化边界、时间戳改写策略,以及它为何只能作为 P0 证据而不能宣称 #2037 已修复。
问题背景:fork 家族为什么会被重复计费
Codex 会以forked_from_id在多个 JSONL 会话文件之间建立父子关系:子会话文件会重放(re-emit)祖先会话的token_count历史。如果扫描器对每个文件独立累计,同一个 completion 就可能被“每个携带它的文件各收一次费”,这正是 issue #2037 追踪的 inter-file 重复计数问题。仓库中的规范文档 docs/issue-2037-fork-family-provenance-spec.md 将该问题归纳为两层:跨文件的“复制祖先事件”重复,以及 Ultra 形态下文件内交错的单调累计序列。
修复这类问题不能只靠合成数据自证。规范要求“以净化后的真实 fork 语料为设计输入”,并用手算 token/费用 oracle 锁定正确结果。archived-fork-33ce-3869正是从本地~/.codex中一组真实33ce→3869父-子归档会话净化而来的第一枚这样的样本。
fixture 概览:净化规则与文件布局
该 fixture 位于 Tests/CodexBarTests/Fixtures/CostUsage/Issue2037/archived-fork-33ce-3869/,包含三个关键文件:
- ORACLE.md——人工手写的基准说明(本文主体所依据的文档);
- manifest.json——机读清单与 oracle 数值契约;
- codex-home/archived_sessions/parent.jsonl 与 codex-home/archived_sessions/child.jsonl——净化后的两条会话流。
ORACLE.md 明确声明了净化边界:ID、时间戳、路径与模型标签均为合成别名,且 JSONL 中只保留三类记录:
| 记录类型 | 保留字段 |
|---|---|
session_meta | id、forked_from_id、timestamp |
turn_context | model、multi_agent_version(及可选的multi_agent_mode) |
event_msg(type: token_count) | last_token_usage与total_token_usage两个对象,各自仅含cached_input_tokens、input_tokens、output_tokens、reasoning_output_tokens、total_tokens五个整数字段 |
不包含任何消息正文、工具输出、cwd、凭据或 diff。测试 Tests/CodexBarTests/Issue2037ProvenanceFixtureTests.swift 中的assertProvenanceSafeFields会逐一断言每条记录的字段白名单,任何多出/缺失的字段都会导致测试失败——这从机制上保证仓库内永远只出现可安全公开的数据形态。
manifest.json记录了两条文件的角色关系:parent(leafSessionAlias: "parent-session",无父)与child(leafSessionAlias: "child-session",parentSessionAlias: "parent-session"),并通过copiedPrefixes声明“parent 的前 135 行被复制进 child 的前 135 行”。
核心 oracle:复制前缀长度与三种口径的算术
ORACLE.md 给出了本 fixture 最核心的数值事实:最长连续归一化(last_token_usage, total_token_usage)前缀为 N = 135,即父流的 135 个事件全部被复制进子流的前 135 行,子流余下 23 行是其独有工作。
| 流 | Token 行数 | last.total_tokens之和 |
|---|---|---|
| Parent | 135 | 13,432,621 |
| Child | 158 | 15,352,834 |
由此可以推导出三种口径(ORACLE.md 的原文算术):
copied child prefix = 13,432,621 child unique suffix = 15,352,834 - 13,432,621 = 1,920,213 naive parent + child = 13,432,621 + 15,352,834 = 28,785,455 parent-owns-prefix = 13,432,621 + 1,920,213 = 15,352,834 overcount removed = 13,432,621一个重要的单位说明:这里的“单位”是存储的last_token_usage.total_tokens字段,不要试图通过叠加cached_input_tokens来重建它——缓存输入已经包含在 provider 报告的 total 中,此处不可加。manifest.json 中的 oracle 对象完整固化这些数字(naiveLastTokens: 28785455、dedupedLastTokens: 15352834、copiedPrefixLastTokens: 13432621等),并额外记录了copiedPrefixTimestampMismatches: 135。
关键设计决策:为什么时间戳必须被排除在匹配之外
ORACLE.md 特意强调:135 行匹配的复制行在父流与子流中故意使用不同的合成事件时间戳。真实 Codex 在 fork 时会把复制行的时间戳改写为一次紧凑的突发(tight burst),因此:
- 前缀匹配器既不要求也不使用时间戳相等;
- 时间戳不能进入复制候选的指纹(fingerprint)——这是 docs/issue-2037-p0-local-corpus-findings.md 中锁定的本地结论(§10.1:复制时时间戳被改写,排除出指纹匹配;§10.2:复制行是“归一化后字段相等”,而非逐字节相等,实际语料中 0 行是逐字节一致的)。
同样的排除规则适用于文件内序号(ordinal):子日志中插入的新事件会推移序号,因此序号只能作为候选匹配后的 tie-break,不能充当身份。这两个约束后来被吸收进规范的“Identity contract”(docs/issue-2037-fork-family-provenance-spec.md)与“Canonical fingerprint”(同文档 §7):指纹只使用复制稳定(copy-stable)字段,如模型、归一化后的last_token_usage与total_token_usage。
另一项故意设计是事件时间戳使用 UTC 中午:父流落在2030-01-01,子流的复制前缀与独有工作分别落在2030-01-01与2030-01-02。原因是本地语料最初用 UTC 午夜时,本地时区会把父行映射到前一个本地日,导致窄报告窗口内父文件被静默排除。改为中午后,无论哪个本地时区,父行都不会滑出 1 月 1 日–2 日的报告窗口(这一坑在 docs/issue-2037-p0-local-corpus-findings.md 的“Pitfalls”一节有记录)。
ORACLE.md 还确认两条流各自的total_token_usage.total_tokens序列均无下降——说明该样本不涉及 Ultra 交错(intra-file interleaved)形态,是纯粹的跨文件 fork golden。
manifest 契约:从手写文档到可机读断言
manifest.json 把 ORACLE.md 的叙述翻译为测试可直接解码的结构化数据:schemaVersion/redactionVersion、files(别名、相对路径、sourceRole、叶子会话别名、父会话别名)、copiedPrefixes(长度 135)与oracle(全部数值)。加载逻辑在 Tests/CodexBarTests/Issue2037FixtureSupport.swift,其中validate会校验别名唯一性、relativePath必须位于codex-home/且不得包含..、copiedPrefixes引用的别名必须存在且父子不同——坏清单在测试启动时即被拒绝。
同一文件里还定义了SanitizedForkFamilyFixture,提供三个读取原语:
sessionMetadata(named:)——取每个文件第一条session_meta(叶子身份);events(named:)——按行解析event_msg/token_count,产出TokenEvent(timestamp, last, total);jsonObjects(named:)——供字段白名单断言使用。
其中TokenUsage的scannerUnits属性(input + cached + output)体现了另一个关键区分:oracle 用sum(last.total_tokens)计,扫描器按sum(input + cached_input + output)计,二者并不恒等(当total_tokens不含缓存输入时尤其如此),因此集成测试必须比较“scanner units”而非裸 total 字段和。
两层测试验证:从纯算术到端到端扫描
fixture 层:前缀匹配与 oracle 算术
Issue2037ProvenanceFixtureTests.swift 的archived fork fixture preserves the copied normalized prefix and hand oracle验证:
longestCommonNormalizedPrefix(parent, child)实际算出 135,与 manifest 的copiedPrefixLength一致;- 父/子事件数与 ORACLE.md 表格完全吻合(135 / 158);
parentLastTokens、childLastTokens、copiedPrefixLastTokens、naiveLastTokens、dedupedLastTokens逐项等于 manifest oracle;naiveLastTokens > dedupedLastTokens(重复计费确实更贵);timestampMismatches == 135且> 0——证明复制行时间戳全部不同,匹配不依赖时间戳;- 两条流均无
total_token_usage下降。
其中longestCommonNormalizedPrefix的实现(同文件 L151-L156)即 ORACLE.md 所述规则的直译:按文件顺序zip(parent, child),逐对比较fingerprint(last+total全部字段)直到首个不等。
scanner 集成层:loadDailyReport 对比 parent-owns-prefix
Issue2037ScannerIntegrationTests.swift 走完整链路:把 fixture 安装进隔离的CostUsageTestEnvironment(sessions/+archived_sessions/双根),以本地正午的 1 月 1 日–2 日窗口调用CostUsageScanner.loadDailyReport(provider: .codex, …, forceRescan: true),再把报告逐日累加inputTokens + cacheReadTokens + outputTokens,与“父流全部 + 子流跳过前 135 行”的期望 scanner units 比对。
测试注释给出的结论很关键:当前#1164inherited-totals 记账在“父文件存在于窗口内”的前提下,已经匹配 parent-owns-prefix 的 scanner-unit oracle——子流绝对总量被 fork 点的父快照 rebase,复制前缀在子流上贡献约 0,只计 fork 后的增长。因此这条测试是回归锁定(regression lock),而不是新的 ledger 实现。ORACLE.md 的“Scanner note”同样强调这一点:它锁住的是 #1164 路径对该形态的正确性,不覆盖缺父兄弟家族(missing-parent siblings)或文件内交错 Ultra 掉档。
golden 的边界:它证明了什么,不证明什么
ORACLE.md 结尾有两条必须严格遵守的边界声明:
- 这是普通跨文件 fork golden,不是 Ultra/交错 golden——两条流的累计序列都没有下降,无法覆盖 Ultra 报告者描述的“文件内多条单调累计线交错、总量中途掉档”形态;
- 它是P0 证据,不得用来声称 #2037 已修复或关闭。
配套的 docs/issue-2037-p0-local-corpus-findings.md 进一步说明了当前运行时策略:当父文件缺失时,不做基于 token 计数器的破坏性跨文件去重(fail open),因为不同子流在相同序号上可能拥有完全相等的 token 向量——仅凭计数相等就抑制合法事件会静默少计。该文档还列出 #1164 继承记账不覆盖的缺口(缺父兄弟、provisional family 计费所有者、文件内交错、任意深度的真事件键 ledger),以及完整的后续步骤(事件键 ledger、所有权迁移、family closure 先于日期过滤等)。整个仓库的 Issue2037 目录下还有 live-fork-4d90-52bf(第二个父在场 golden,父截断到复制前缀 N=180,锁定了“ordinal 120 处 last 非零但 total 持平”的真实语料怪癖)与 missing-parent-siblings(两个子共享前缀但无父文件)等配套样本,共同构成 #2037 修复推进过程中的证据链。
小结:一份可复算的重复计费基准
archived-fork-33ce-3869的价值在于把“fork 家族重复计数”这一抽象缺陷压缩为一组可手工复算的数字(naive 28,785,455 → parent-owns-prefix 15,352,834,消除 13,432,621 的重复计费),并通过 manifest + 两层测试使其成为持续集成的硬断言。它对实现与评审者的约束同样明确:时间戳和文件序号不得充当跨文件身份;单位必须区分sum(last.total_tokens)与 scanner units;净化语料只能证明它覆盖的形态。在事件键 ledger 与所有权迁移落地之前,它是 #2037 修复路上被反复引用的、不可退让的基准线。
【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考