Skip to content

Fix copied-prefix Codex subagent accounting#2228

Merged
steipete merged 6 commits into
steipete:mainfrom
hhh2210:codex/fix-subagent-copied-prefix-accounting
Jul 16, 2026
Merged

Fix copied-prefix Codex subagent accounting#2228
steipete merged 6 commits into
steipete:mainfrom
hhh2210:codex/fix-subagent-copied-prefix-accounting

Conversation

@hhh2210

@hhh2210 hhh2210 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Distinguish restarted subagent counters from rollouts that copy an ancestor prefix.
  • Find the leaf-owned suffix from Codex's local turn marker, then reuse the existing totals reducer for that suffix.
  • Keep real parent dependencies only where accounting still depends on parent totals.
  • Preserve fast-path/Foundation parity, cold/warm cache parity, and the parser-hash invalidation contract.

The regression is an abstraction error, not a missing special case. source.subagent describes lineage provenance. It does not guarantee that the file owns an independent cumulative counter.

User-visible failure

The currently installed CodexBar build on the affected machine attributed 591M Jul 16 tokens to Unknown model and displayed 1.3B tokens for the day:

codex-clipboard-99697265-f03b-453a-8cf3-6d083659f3c2.png

The screenshot is symptom evidence. The quantitative comparison below uses the same frozen 2,012-file corpus and isolated empty caches for both revisions.

Scanner Jul 16 tokens Jul 16 Unknown
origin/main (6d71af30) 4,086,288,236 886,306,282
this patch (67862278) 231,475,556 0

Cold, warm, and forced scans on the patch produced identical report values. Jul 16 resolves to 223,869,513 gpt-5.6-sol tokens plus 7,606,043 codex-auto-review tokens. The 30-day result is 3,799,232,783 tokens / $2,765.5475077; it still contains 307,441,975 historical Unknown tokens, so this PR does not claim to complete #2037.

The bisect and representative-file arithmetic are in the #2208 regression report. #2208 fixed the real reset-only shape from #2193, but generalized that fixture into an unconditional source.subagent rule. That bypasses the parent resolver, so #2118 cannot invalidate or repair the resulting attribution.

Design

The scanner keeps its existing metadata probe and one full streaming pass; this PR does not add a second full raw-JSON pass. For explicit subagent rollouts it buffers compact parsed observations for one file, not raw JSON, then classifies the rollout before replaying events through the existing totals reducer.

The classifier uses these invariants:

  1. The first session_meta owns leaf identity. Later metadata may enrich missing fields for the same concrete leaf ID, but cannot replace it.
  2. An embedded different metadata ID proves that the rollout contains a copied ancestor prefix.
  3. After the final embedded ancestor, the first adjacent turn_context + inter_agent_communication_metadata(trigger_turn: true) pair opens the leaf-owned suffix.
  4. The suffix baseline is the last cumulative total before that marker, not the ancestor metadata position.
  5. A copied rollout is treated as a restarted counter only with strong reset evidence: the first suffix total equals last and is below the pre-marker baseline.

The fourth rule matters in the real corpus. Of 197 copied-prefix files with a usable local boundary, 191 contain 10,197 cumulative token rows between the final ancestor metadata and the first valid marker. Cutting at metadata would discard valid baseline evolution.

Shape Accounting Parent cache dependency
reset-only subagent full independent counter none
copied prefix with local marker marker-owned suffix none
copied prefix without marker inherited parent baseline required
ordinary fork existing inherited baseline required

The final cache audit found 208 forked entries: 197 marker-owned suffixes, 10 independent counters, and one inherited dependency. No forked entry lacked a dependency mode, and no unexpected lineage-only entry was produced.

There is an explicit source comment against restoring either blanket rule. source.subagent must not be treated as synonymous with “independent counter” or “inherited counter.”

Cache compatibility

This keeps the cache contract proposed in #1042 and landed separately by the maintainer as 5aded294 with co-author credit:

  • parser/attribution changes rotate the generated producer hash (3c42ef1a44c90442 here);
  • codex-vN changes only for an incompatible stored schema or cache layout.

If a parent changes across both snapshot-read attempts, the resolver's dependency key remains nil. The child cache therefore cannot be reused on the next refresh, preserving #2118's unstable-parent invalidation contract.

No codex-v10 bump is needed. This is exactly the kind of parser semantic change the producer hash is meant to invalidate automatically.

Validation

  • make check after rebasing onto origin/main: passed; SwiftFormat and SwiftLint report zero violations.
  • 121 scanner/classifier/cache/performance tests: passed, including all 94 CostUsageScannerBreakdownTests, existing Ultra-mode Terra and Sol sessions can overcount forked context #2037 regression fixtures, fast/Foundation parser parity, late lineage metadata, cold/warm/force cache behavior, unstable-parent invalidation, and reset-only preservation.
  • Release scan, same frozen corpus and isolated caches:
    • origin/main cold: 5.84s / 298.2 MiB and 6.04s / 299.2 MiB;
    • cold: 5.29s / 111.4 MiB and 4.59s / 111.9 MiB;
    • warm: 0.19s / 81.1 MiB;
    • versus a separately built origin/main release harness using the same corpus and cache isolation, average wall time is about 16.8% lower and peak RSS about 62.6% lower. This small local A/B is directional evidence only, not a general performance claim. The result is consistent with reduced copied-prefix row materialization, but that cause was not profiler-proven.

make test is not fully green on this machine because ClaudeOAuthCredentialsStoreCLIStorageOwnershipTests deterministically fails 7/8 tests on clean origin/main at 6d71af30 with the same eight assertions. The branch reproduces that unrelated baseline exactly; no scanner or cache test fails.

Fixes #2108.

Refs #2037, #2118, #2193, and #2208.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Codex local usage accounting for forked/subagent rollouts that copy an ancestor prefix by classifying rollout shape and, when possible, attributing only the leaf-owned suffix instead of treating source.subagent as synonymous with an independent cumulative counter. It also updates cache dependency handling so fork lineage can be recorded without forcing parent-baseline cache invalidation when the child no longer depends on parent totals.

Changes:

  • Add a subagent rollout shape classifier (embedded ancestor detection + local marker boundary + reset-evidence handling) and integrate it into the Codex JSONL scanner.
  • Record “lineage-only” cache dependency mode for forked sessions that do not depend on parent totals, and skip parent dependency validation for those entries.
  • Add focused unit + integration tests covering copied-prefix + marker-owned suffix behavior, fast/Foundation parity, and cache mode persistence.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift Extends regression coverage to assert cold/warm/force parity and lineage-only cache dependency mode.
Tests/CodexBarTests/CodexSubagentRolloutShapeTests.swift New unit tests for the rollout shape classifier invariants and boundary detection.
Tests/CodexBarTests/CodexSubagentAccountingIntegrationTests.swift New integration tests verifying inherited-baseline vs owned-suffix behavior and cache mode persistence (fast + fallback parser).
Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CacheHelpers.swift Stores and validates fork dependency keys with a lineage-only mode that bypasses parent dependency checks.
Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift Buffers subagent fast lines, classifies copied-prefix vs independent semantics, and replays events through the existing reducer using the correct baseline/boundary.
Sources/CodexBarCore/Vendored/CostUsage/CodexSubagentRolloutShape.swift New classifier implementation for distinguishing independent counters vs copied prefixes and locating leaf-owned suffixes.
Sources/CodexBarCore/Generated/CodexParserHash.generated.swift Updates producer hash to invalidate stale Codex caches after semantic parser changes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CacheHelpers.swift Outdated
Comment thread Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 16, 2026
@clawsweeper

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed July 16, 2026, 5:18 PM ET / 21:18 UTC.

Summary
The PR classifies Codex subagent rollouts as restarted counters or copied ancestor prefixes, accounts only the locally owned suffix where appropriate, and updates parent-cache dependency handling and regression coverage.

Reproducibility: yes. for the reported pre-hardening revision: the frozen 2,012-file corpus shows the then-current main producing 4.086B July 16 tokens and 886M Unknown tokens, versus 231M and zero Unknown on 6786227. The same live comparison has not yet been shown for current head cc5a205.

Review metrics: 3 noteworthy metrics.

  • Diff surface: 9 files; 1,361 added, 52 removed. The patch remains within the Codex scanner subsystem but materially changes classification, parsing, and cache paths.
  • Focused validation: 121 tests reported passing. The reported suite covers classifier, scanner, cache, parser-parity, invalidation, and performance-sensitive behavior.
  • Proof revision gap: 2 semantic commits after measured SHA. The published corpus comparison targets 6786227, before the current maintainer-hardening commits.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #2108
Summary: This PR is the candidate fix for the real copied-prefix corpus report; the broader Ultra accounting issue remains only partially addressed.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦐 gold shrimp
Patch quality: 🦞 diamond lobster
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Rerun the frozen-corpus cold, warm, and forced comparisons on cc5a205 and post redacted output.
  • Let the queued macOS and Linux checks complete against the exact merge result.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The corpus evidence is strong but was captured on 6786227, before the current head's two semantic hardening commits; rerun it on cc5a205, redact private corpus details, and update the PR body to trigger review, or ask a maintainer to comment @clawsweeper re-review.

Risk before merge

  • [P1] The latest two semantic hardening commits have not been demonstrated against the frozen real corpus used for the posted before-and-after totals.
  • [P1] An upstream Codex rollout shape not represented by the focused tests or corpus could still be misclassified and cause material token under- or over-counting.
  • [P1] The exact-head macOS and Linux build/test checks were incomplete in the supplied context, and the recorded PR base trails the reported current main SHA.

Maintainer options:

  1. Refresh exact-head corpus proof (recommended)
    Rerun the documented cold, warm, and forced scans on cc5a205 and merge only if they preserve the corrected model attribution and totals.
  2. Request broader rollout evidence
    Pause for another independent copied-prefix corpus only if maintainers believe the existing 2,012-file dataset does not adequately represent supported Codex rollout shapes.

Next step before merge

  • [P1] No automated code repair is indicated; the contributor must refresh real-corpus proof for the current head, followed by ordinary exact-head merge review.

Security
Cleared: The diff is confined to local JSONL parsing, cache semantics, generated parser identity, and tests, with no new dependency, secret, permission, download, or code-execution surface.

Review details

Best possible solution:

Retain the hardened shape classifier and parser-hash invalidation, rerun the same isolated frozen-corpus scan on cc5a205, then merge after exact-head checks pass and continue the broader historical Unknown-token investigation separately.

Do we have a high-confidence way to reproduce the issue?

Yes for the reported pre-hardening revision: the frozen 2,012-file corpus shows the then-current main producing 4.086B July 16 tokens and 886M Unknown tokens, versus 231M and zero Unknown on 6786227. The same live comparison has not yet been shown for current head cc5a205.

Is this the best way to solve the issue?

Yes. Deriving counter semantics from embedded lineage and a local turn marker, then replaying the owned range through the existing totals reducer, is narrower and safer than restoring either blanket subagent rule.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 6ffdfeba6c6e.

Label changes

Label changes:

  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦞 diamond lobster.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The corpus evidence is strong but was captured on 6786227, before the current head's two semantic hardening commits; rerun it on cc5a205, redact private corpus details, and update the PR body to trigger review, or ask a maintainer to comment @clawsweeper re-review.
  • remove proof: sufficient: Current real behavior proof status is insufficient, not sufficient.
  • remove rating: 🦞 diamond lobster: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: 📣 needs proof.

Label justifications:

  • P1: The reproduced regression can inflate a real user's daily Codex accounting from hundreds of millions to billions of tokens, making a core cost workflow urgently unreliable.
  • merge-risk: 🚨 other: The merge changes ownership semantics for cumulative token counters, so an unmodeled rollout shape could materially misstate usage despite green focused tests.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦞 diamond lobster.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The corpus evidence is strong but was captured on 6786227, before the current head's two semantic hardening commits; rerun it on cc5a205, redact private corpus details, and update the PR body to trigger review, or ask a maintainer to comment @clawsweeper re-review.
Evidence reviewed

What I checked:

Likely related people:

  • steipete: Authored the two latest hardening commits affecting the scanner and conservative parsing behavior on this branch. (role: recent area contributor; confidence: high; commits: 97c9ca57153f, cc5a205affbf; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift, Sources/CodexBarCore/Vendored/CostUsage/CodexSubagentRolloutShape.swift)
  • harjothkhara: Authored the merged restarted-subagent accounting change whose reset-only behavior this PR preserves while narrowing its blanket subagent rule. (role: introduced adjacent behavior; confidence: high; commits: 8489602f84ca; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift, Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift)
  • xx205: Authored the merged parent-cache dependency work whose stable-snapshot invalidation contract this PR retains. (role: introduced adjacent behavior; confidence: high; commits: 2acf34cdf860; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner+CacheHelpers.swift, Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-16T17:36:38.024Z sha 97c9ca5 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-16T18:17:09.553Z sha 97c9ca5 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-16T18:58:46.524Z sha 97c9ca5 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 16, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 16, 2026
steipete added 2 commits July 16, 2026 23:45
…pied-prefix-accounting

# Conflicts:
#	Sources/CodexBarCore/Generated/CodexParserHash.generated.swift
@steipete
steipete merged commit a1fad48 into steipete:main Jul 16, 2026
7 checks passed
@steipete

Copy link
Copy Markdown
Owner

Merged as a1fad485d6686138f7742931735e1a305705435a after maintainer hardening and exact-head verification.

Local verification on head 25bbf59129350a3296ba78c1863fb283d60e4a6c:

  • swift test --filter CodexSubagentAccountingIntegrationTests — 8/8 passed.
  • swift test --filter CodexSubagentRolloutShapeTests — 12/12 passed.
  • swift test --filter CostUsageScannerBreakdownTests — 92/92 passed.
  • make check — parser hash current, SwiftFormat clean, SwiftLint reported 0 violations.
  • Final autoreview — clean, no accepted/actionable findings (confidence 0.90). An earlier review finding about oversized truncated turn-context boundary validation was accepted and fixed in 25bbf5912, with invalid-timestamp and nested-type regression coverage.

CI run https://github.com/steipete/CodexBar/actions/runs/29540917080 completed green on the exact head: lint, changes, Linux x64, Linux arm64, both macOS test shards, and lint-build-test. GitGuardian also passed. PR state was CLEAN and MERGEABLE immediately before merge.

Maintainer commits: 97c9ca571, cc5a205af, merge-main resolution f7a737bea, and final hardening 25bbf5912.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P1 Urgent regression or broken agent/channel workflow affecting real users now. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex real fork corpus: 5,427 replayed parent events across rewritten timestamps

3 participants