Skip to content

Fix unknown Codex model attribution - #2061

Merged
steipete merged 4 commits into
steipete:mainfrom
hhh2210:codex/fix-unknown-codex-model-attribution
Jul 11, 2026
Merged

Fix unknown Codex model attribution#2061
steipete merged 4 commits into
steipete:mainfrom
hhh2210:codex/fix-unknown-codex-model-attribution

Conversation

@hhh2210

@hhh2210 hhh2210 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Stop assigning model-less Codex token events to gpt-5.
  • Preserve the current turn_context model when available, matching the scanner's established precedence.
  • Trim model evidence and ignore blank strings before falling through to another model field or context.
  • Keep unresolved usage under an unknown key, rendered as Unknown model, without applying GPT-5 pricing.
  • Rebuild the Codex cost cache as codex-v9.json so existing false attribution is removed.

Refs #1013. This is a follow-up to #1014: that patch recovered model state from oversized turn_context rows, while this patch removes the remaining assumption that an unresolved model must be GPT-5.

Evidence

Before

CodexBar briefly showed 211M tokens and $34.90 attributed to gpt-5:

CodexBar cost history showing a false GPT-5 attribution

The underlying Codex data for that day contained no model:"gpt-5" records. The local session JSONL contained 112 gpt-5.6-sol model records and 352 codex-auto-review records; logs_2.sqlite also contained no GPT-5 completion. A later cache refresh removed the GPT-5 row, confirming that this was transient scanner attribution rather than a backend model fallback.

The remaining cause was the scanner's final fallback:

currentModel ?? eventModel ?? "gpt-5"

That fallback turned missing evidence into a specific model and a priced cost. This patch keeps the usage visible but explicitly unattributed. It preserves current turn-context precedence and uses normalized token-event model evidence when context is unavailable.

After: real cache rebuild

The same Jul 11 history after rebuilding with the patched scanner has no GPT-5 row. The resolved usage is attributed to gpt-5.6-sol and codex-auto-review:

CodexBar cost history after rebuilding without the false GPT-5 row

After: unresolved-model path

I also ran the freshly built CodexBarCLI cost against an isolated Codex home containing one model-less token_count event with 55M tokens. This exercises the complete JSONL scanner, cache, pricing, and JSON output path without reading a real account:

{
  "date": "2026-07-11",
  "modelBreakdowns": [
    {
      "modelName": "unknown",
      "totalTokens": 55000000
    }
  ],
  "modelsUsed": ["unknown"],
  "totalTokens": 55000000
}

There is no cost or totalCost field for the unknown breakdown, and no GPT-5 row. The fixture used a redacted project path and no credentials, endpoints, browser data, or Keychain access.

Validation

  • make check
  • DYLD_FRAMEWORK_PATH="$PWD/.build/out/Products/Debug" swift test --filter CostUsageScannerBreakdownTests --filter CostUsageCacheTests (65 tests passed)
  • DYLD_FRAMEWORK_PATH="$PWD/.build/out/Products/Debug" swift test --filter UsageFormatterTests (42 tests passed)

The full sharded suite reached an unrelated order-sensitive Claude test group that failed in the combined run and passed when rerun by itself. The Codex scanner/cache and formatter suites pass cleanly.

Copilot AI review requested due to automatic review settings July 11, 2026 12:10

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 cost attribution when token events lack a model by removing the prior implicit fallback to gpt-5, preferring the model present on each token event over stale turn_context, and ensuring unresolved usage is tracked under an explicit unknown model bucket. It also bumps the Codex cost cache artifact version to invalidate previously mis-attributed cached data.

Changes:

  • Update Codex session scanning to select record.model/modelFromInfo before turn_context, and to fall back to an explicit unknown key instead of gpt-5.
  • Bump Codex cost cache artifact from codex-v8.json to codex-v9.json to force a clean rebuild.
  • Add/update tests and formatting to display the unknown bucket as “Unknown model”.

Reviewed changes

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

Show a summary per file
File Description
Tests/CodexBarTests/UsageFormatterTests.swift Adds coverage for displaying the unknown model bucket as “Unknown model”.
Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift Adds regression tests for missing model handling and model precedence; updates expected Codex cache artifact version.
Tests/CodexBarTests/CostUsageCacheTests.swift Updates expected Codex cache filename to codex-v9.json.
Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift Removes gpt-5 fallback, prefers event model over turn_context, and introduces the unknown model key.
Sources/CodexBarCore/Vendored/CostUsage/CostUsageCache.swift Bumps Codex cache artifact version to 9 (filename changes to codex-v9.json).
Sources/CodexBarCore/UsageFormatter.swift Renders model key unknown as “Unknown model”.
Sources/CodexBarCore/Generated/CodexParserHash.generated.swift Updates generated parser hash value.
CHANGELOG.md Documents the Codex cost attribution fix.

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

else { return }

let model = currentModel ?? record.model ?? "gpt-5"
let model = record.model ?? currentModel ?? Self.codexUnknownModel

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 7373e30. Model candidates are now trimmed and blank strings are treated as missing before event/context precedence is applied. Added regression coverage for a whitespace-only event model falling back to the valid turn context.

?? payload["model"] as? String
?? obj["model"] as? String
let model = currentModel ?? modelFromInfo ?? "gpt-5"
let model = modelFromInfo ?? currentModel ?? Self.codexUnknownModel

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 7373e30. Each candidate field is normalized before the nil-coalescing chain, so a blank model can no longer hide a valid model_name. Added an end-to-end regression test for that exact shape.

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 1:32 PM ET / 17:32 UTC.

Summary
The PR normalizes Codex model evidence, preserves current turn-context attribution, records unresolved token usage as an unpriced unknown model, updates its display name, and invalidates affected cost caches.

Reproducibility: yes. Current main has a concrete model-less token-event path that falls through to GPT-5, and the PR supplies both a real affected-cache rebuild and an isolated end-to-end scanner/CLI reproduction.

Review metrics: 2 noteworthy metrics.

  • Patch scope: 8 files; 148 added, 18 removed. The branch is bounded to attribution logic, cache invalidation, display naming, generated parser state, release context, and focused tests.
  • Cache migration: Codex artifact v8 → v9. Existing locally cached false attribution is discarded rather than surviving the parser correction.

Root-cause cluster
Relationship: same_root_cause
Canonical: #1013
Summary: This PR fixes the remaining invented-model fallback behind the same false Codex cost attribution reported in the canonical issue.

Members:

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

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

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

Next step before merge

  • [P2] No repair-lane work is needed; routine required checks and normal maintainer merge review are the only remaining steps.

Security
Cleared: The diff introduces no dependency, workflow, permission, secret, network, installer, downloaded-artifact, or other supply-chain change.

Review details

Best possible solution:

Merge the focused correction once required checks pass so CodexBar preserves observed model attribution, reports unresolved tokens explicitly, and never assigns fabricated GPT-5 cost.

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

Yes. Current main has a concrete model-less token-event path that falls through to GPT-5, and the PR supplies both a real affected-cache rebuild and an isolated end-to-end scanner/CLI reproduction.

Is this the best way to solve the issue?

Yes. Preserving current turn context, filtering blank evidence, retaining unresolved token counts under an unpriced sentinel, and invalidating stale caches is the narrowest maintainable correction.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 060ffe13012d.

Label changes

Label justifications:

  • P2: The PR fixes materially misleading Codex cost attribution with limited blast radius and no emergency availability, security, or data-loss impact.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (screenshot): The inspected before/after app screenshots show the false GPT-5 row disappearing after a real cache rebuild, and isolated live CLI output demonstrates the unresolved-model path without credentials or Keychain access.
  • proof: sufficient: Contributor real behavior proof is sufficient. The inspected before/after app screenshots show the false GPT-5 row disappearing after a real cache rebuild, and isolated live CLI output demonstrates the unresolved-model path without credentials or Keychain access.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The inspected before/after app screenshots show the false GPT-5 row disappearing after a real cache rebuild, and isolated live CLI output demonstrates the unresolved-model path without credentials or Keychain access.
Evidence reviewed

What I checked:

Likely related people:

  • steipete: Authored the final PR-head attribution-contract test commit and carried the central scanner refactor and recent scanner performance work on current main. (role: recent area contributor; confidence: high; commits: 6f657d82fe09, a8c98859, 917fc722; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift, Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift)
  • hhh2210: Authored the previously merged long-turn-context attribution fix and therefore has established merged history in this exact scanner, cache, and test area beyond proposing this PR. (role: introduced related behavior; confidence: high; commits: 036b49755aef; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift, Sources/CodexBarCore/Vendored/CostUsage/CostUsageCache.swift, Tests/CodexBarTests/CostUsageScannerBreakdownTests.swift)
  • Yuxin-Qiao: Most recently changed bounded Codex session metadata scanning in the same central scanner file on current main. (role: recent adjacent contributor; confidence: medium; commits: 25839282; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.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 (5 earlier review cycles)
  • reviewed 2026-07-11T12:15:33.485Z sha 923e767 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-11T12:41:03.317Z sha 7373e30 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-11T12:46:07.882Z sha 7373e30 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-11T13:40:45.866Z sha 92e7731 :: needs changes before merge. :: [P3] Correct the release note to match final model precedence
  • reviewed 2026-07-11T17:26:40.225Z sha 6f657d8 :: needs maintainer review before merge. :: none

@hhh2210

hhh2210 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Added after-fix proof to the PR body: a real cache rebuild screenshot with the false GPT-5 row removed, plus isolated CodexBarCLI cost output showing 55M model-less tokens under an unpriced unknown bucket. Copilot’s blank-model findings are fixed in 7373e30 with two regression tests.

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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. P2 Normal priority bug or improvement with limited blast radius. labels Jul 11, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jul 11, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 11, 2026
@steipete
steipete merged commit 300ddee into steipete:main Jul 11, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants