Skip to content

Price Claude at Anthropic's list rates on the day they applied: Opus 5.5, Fable 5.1 and Sonnet 5.5 rows, Sonnet 5 at $2 / $10, and 1-hour cache writes - #647

Merged
JasonYeYuhe merged 6 commits into
mainfrom
p156-claude-prices
Oct 6, 2026
Merged

JasonYeYuhe merged 6 commits into
mainfrom
p156-claude-prices

Conversation

@JasonYeYuhe

@JasonYeYuhe JasonYeYuhe commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

What people saw

The two newest Claude models were charged their predecessors' prices. The Mac's Claude table ended at Opus 5, Sonnet 5 and Fable 5, so Claude Opus 5.5 and Claude Fable 5.1 went through the family fallback and borrowed the newest row in their family. Cache hits are most of a Claude Code day, and that is where the borrowed rates were furthest off:

model Anthropic list (input / cache hit / output, per 1M) charged until now
claude-opus-5-5 $4 / $0.20 / $20 $5 / $0.50 / $25 (Opus 5's)
claude-fable-5-1 $10 / $0.25 / $50 $10 / $1 / $50 (Fable 5's)
claude-sonnet-5-5 $2 / $0.20 / $10 $3 / $0.30 / $15 (Sonnet 5's row)
claude-sonnet-5 $2 / $0.20 / $10 $3 / $0.30 / $15

Since #623 those borrowed figures carry "≈", so the first "≈" a Mac showed came from Claude.

Sonnet 5 was charged a rate it never had. It launched at $2 / $10, "introductory" through 2026-08-31, with an increase to $3 / $15 scheduled for 2026-09-01. On 2026-08-10 Anthropic made $2 / $10 the standard price and cancelled the increase. The table held the cancelled $3 / $15 for every day.

Every cache write was charged at the 5-minute rate. Anthropic charges a 5-minute cache write 1.25x input and a 1-hour write 2x. Claude Code splits its writes between the two in every response (usage.cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens), and on this Mac, over the last 45 days, the 1-hour share of the writes was 16% on Opus 5.5, 44% on Fable 5.1, 56% on Opus 5 and 94% on Opus 4.8. The scanner ignored the split.

The 200K long-context tier was computed per token kind. On a tiered row, the scanner charged the first 200K input tokens, the first 200K cache reads, the first 200K writes and even the first 200K output tokens at standard rates, and only the excess of each at the premium. Anthropic's rule is per request: a request whose prompt, cache reads and writes included, is over 200K pays the premium on every token, output included. It was also applied to Sonnet 4.6 forever, although its 1M window has been at standard pricing since 2026-03-13, and never to Opus 4.6, which paid the premium before that date.

What changed

The table (ClaudePricingTable.swift, new, CLIPulseCore, shared with iOS like CodexPricingTable). Every row was read against Anthropic's pricing page, https://platform.claude.com/docs/en/about-claude/pricing, on 2026-10-03, and is written in the page's column order: base input, 5-minute write, 1-hour write, cache hit, output.

  • New rows: claude-opus-5-5 (released 2026-09-22), claude-fable-5-1 (2026-09-01), claude-sonnet-5-5 (2026-09-28), and claude-mythos-5-1 / claude-mythos-5 (Project Glasswing, Fable's prices). Dates are from the API release notes, https://platform.claude.com/docs/en/release-notes/api.
  • claude-sonnet-5 at $2 / $10, cache hits $0.20.
  • Cache hits are 0.1x input, except 0.05x on Opus 5.5 and 0.025x on Fable 5.1 and Mythos 5.1, as the page lists.
  • Every other row is unchanged in its standard prices.

Dated rates. ClaudePricingTable.superseded holds the 200K tier for Opus 4.6 (1M beta from 2026-02-05) and Sonnet 4.6 (from its release on 2026-02-17) until 2026-03-13, when "the 1M token context window is out of beta for Claude Opus 4.6 and Sonnet 4.6, at standard pricing" (release notes). The instant is 00:00 UTC, the convention of CodexPricingTable. The premium rates (Opus 4.6 $10 / $37.50, Sonnet 4.6 / 4.5 / 4 $6 / $22.50, with the caching multipliers on top) come from the page as it stood then: https://web.archive.org/web/20260301150515/https://platform.claude.com/docs/en/about-claude/pricing. The page lists no tier for any current model ("Claude 4.6 and later models ... include the full 1M token context window at standard pricing"). Sonnet 4 and 4.5 keep theirs: their 1M beta was retired on 2026-04-30, after which a request over 200K is an error.

There is no dated rate for Sonnet 5: $2 / $10 is the only rate it ever had.

Each response is priced at its own time, with its 1-hour writes. parseClaudeFile reads the line's instant (the same parse that gave its day) and cache_creation.ephemeral_1h_input_tokens, and Pricing.claudeCostUSD takes both (cacheCreation1hInputTokens:, at:; both default to the old behaviour). The 1-hour share is clamped to the writes it is part of. A log without the split is charged at the 5-minute rate, as before.

The tier is per request. ClaudePricingTable.requestCostUSD puts the whole response on the long-context rates when input + cache reads + cache writes is over 200K. The old per-kind split was written for pricing a day's sum; the scanner prices each response as it reads it. The two places that still price a sum now use aggregateCostUSD, which never takes the tier, so a busy day cannot land on long-context rates: the fallback for a cached day row with no stored cost (entriesFromClaudeCache), and a live session's total (sumClaudeTotals, found by review).

Cache. costUsageCachePricingVersion 6 → 7: every Mac re-reads its Claude logs once, as #624's bump already does, so stored costs move to the new table. Pricing.claudeRatesFingerprint() (every row, every dated rate, and how a fixed list of names resolves) is pinned next to the version in ClaudePricingTableTests, as codexRatesFingerprint() is for Codex, so a future Claude price change without a bump fails the build. Codex is untouched (its fingerprint pin passes unchanged).

Effect on this Mac. A read-only script over this Mac's Claude Code logs for the last 30 days (aggregates only, last line per response, the app's rules approximated) puts the Claude estimate 18% lower under the new table than under the old: Opus 5.5 −41%, Fable 5.1 −25%, Sonnet 5 −30%, while Opus 5 and Opus 4.8 rise about 5% from their 1-hour writes. For the What's New decision on disclosing that Claude estimates rise (#624, mostly in output tokens): with this PR the Claude direction is mixed and depends on the models used, and on this Mac the net is down. So What's New should say that Claude estimates change (some models lower, some higher), not that they rise.

Not in this PR.

  • Fast mode (Opus 5.5 $8 / $40, Opus 5 and 4.8 $10 / $50). No local log shows usage.speed other than standard, and Price Codex at OpenAI's list rates on the day they applied, and mark a borrowed rate with "≈" #623 left Codex's Fast multipliers out too.
  • Data residency (inference_geo, 1.1x) and the Batch API discount: neither applies to Claude Code's interactive requests as logged.
  • The desktop app (cli-pulse-desktop) has its own Claude table and is not changed here.
  • Days the Mac archived before this version keep the costs they were recorded with. The routine read re-prices the days it reads, and those reach the cloud and the iPhone as the Mac uploads them.
  • Vertex-style names (claude-opus-4-5@20251101) still do not normalize; that is unchanged.

How it is tested

  • ClaudePricingTableTests (new, 20 tests)
    • Every row of current, all five columns, against the page; a row added to the table without being listed in the test fails.
    • The caching multipliers on every row and tier: 5-minute 1.25x, 1-hour 2x, cache hit 0.1x except Opus 5.5 (0.05x) and Fable / Mythos 5.1 (0.025x).
    • Only Sonnet 4 and 4.5 keep a tier today, at 2x input and 1.5x output.
    • The dated boundary: the 2026-03-13 00:00 UTC instant, and Opus 4.6 and Sonnet 4.6 one second before it and at it. No date means today's rate; every model with earlier rates has a row today, oldest first.
    • 1-hour writes: $5 / $8 / $6.50 for 1M 5-minute, 1-hour and half-and-half writes on Opus 5.5, clamped to the writes.
    • A sum never takes the tier.
    • Opus 5.5, Fable 5.1, Mythos 5.1 and Sonnet 5.5 resolve to their own rows (not approximate), including anthropic., Bedrock us.anthropic.…-v1:0 and dated spellings.
    • End to end through the scanner: an Opus 5.5 response with split writes costs $1.084 (it was $1.38) and is not approximate; a log without the split is charged 5-minute writes; two 301K-prompt Sonnet 4.6 requests either side of 2026-03-13 cost $0.186 and $0.093; a Fable 5.1 cache row stores $0.25 for 1M cache hits.
    • A response as Claude Code writes it, over several lines with the same ids where the last one counts (added after the 10-07 review): an Opus 5.5 response over three lines, only the last carrying the 1-hour split, costs $1.084, not the $0.904 of its first line's pricing; a two-line Sonnet 4.6 response with a 301K prompt before 2026-03-13 costs $0.231, not today's $0.123; and the same Opus 5.5 response with its first line in one read ($0.704) and the rest in an incremental one costs $1.084. Pending.line no longer has a default, so each place that makes a Pending names the line that prices it, or .alreadyPriced.
    • A cached day row with no stored cost, and a live session whose rows hold none, are priced as sums: 300K Sonnet 4.5 tokens cost $0.90, not $1.80.
    • The fingerprint pin, and a test that a repriced row, a repriced cache hit, a new tier, a new row and a moved dated end each change the fingerprint.
  • ClaudeTieredAndCodexEdgeCostTests: the Claude half rewritten to the per-request rule (300K input pays $1.80, not $1.20; cache reads count toward the threshold; output does not decide it; exactly 200K is standard and one token more moves every token), with the archived page cited.
  • Updated: Claude5PricingTests (Sonnet 5 at $2 / $10; an unknown claude-opus-6 now borrows Opus 5.5 and claude-sonnet-9 Sonnet 5.5; claude-opus-5-1 still takes Opus 5 over Opus 4.8), CodexPricingTableTests (the Claude fallback target and its $4), CostUsageCacheIOTests (version 7).
run where result
filtered swift test (the suites above plus ClaudePricingOpus47Tests, CostUsageScannerAccountingTests, UnpricedCoverageTests, ApproximatePriceCoverageTests, ArchiveTokenBasisTests, CodexTokenAccountingTests) this Mac, acc987fe 218 tests, 0 failures
CLIPulseCore full suite, plain this Mac, acc987fe 4,037 tests, 0 failures (5 skipped)
ClaudePricingTableTests after the review fix this Mac, 831f01a8 18 tests, 0 failures
filtered swift test after the 10-07 review fix (ClaudePricingTableTests, CostUsageScannerAccountingTests, Claude5PricingTests, ClaudeTieredAndCodexEdgeCostTests, CostUsageCacheIOTests, ClaudePricingOpus47Tests) this Mac, 7ff00eab 104 tests, 0 failures; SwiftLint on both changed files, 0 violations
CLIPulseCore full suite, plain this Mac, 7ff00eab 4,041 tests, 0 failures (5 skipped)
gates: no internal docs, duplicate sources, copyright, hardcoded UI strings, personal-info mask, Apple strings parity (1,785 keys x 6, unchanged); SwiftLint on the new files this Mac all pass, 0 violations
CLIPulseCore unit tests CI, 8a5cff14 (Swift CI run 37120631692) plain 4,039 tests, 0 failures (5 skipped), and 0 failures in the Japanese, ROC and Buddhist calendar passes; -DDEVID_BUILD 4,077, 0 failures (7 skipped). All 18 ClaudePricingTableTests ran and passed in all five passes
CLIPulseCore unit tests CI, this head 7ff00eab (Swift CI run 37500794263) plain 4,041 tests, 0 failures (5 skipped), and 0 failures in the Japanese, ROC and Buddhist calendar passes; -DDEVID_BUILD 4,079, 0 failures (7 skipped). Both new tests ran and passed in all five passes. Every build and package job of the full matrix passed

Negative controls (throwaway nc/ branches on CI, deleted after; each mutation has a test that only it trips):

branch mutations failed tests (unit-test job)
nc/p156-claude-prices-a (run 37119510475) Sonnet 5 back to $3 / $15; Opus 5.5 cache hit at 0.1x; the 2026-03-13 date a day late; the tier decided by uncached input only 15 of 4,038: Claude5PricingTests.testPublishedRatesPerMillionTokens and test_publishedRatesPerMillionTokens (Sonnet 5); test_cacheRatesFollowThePagesMultipliers and test_aScannedOpus55ResponseIsChargedItsOwnRates ($1.284) (Opus 5.5); test_theLongContextDateIsTheOneAnthropicPublished (date); test_sonnet_cache_reads_count_toward_the_threshold, test_sonnet_a_prompt_of_exactly_200K_pays_standard_rates and test_aScannedSonnet46RequestPaysTheTierOnlyBeforeMarch13 ($0.093) (tier); the fingerprint pin
nc/p156-claude-prices-b (run 37119524297) the scanner ignores 1-hour writes; the scanner prices without the event time; the fingerprint leaves out dated rates; a cached day's sum priced as one request; the rules version left at 6 6 of 4,038: test_aScannedOpus55ResponseIsChargedItsOwnRates ($0.904); test_aScannedSonnet46RequestPaysTheTierOnlyBeforeMarch13 ($0.093); test_aTableChangeChangesTheClaudeFingerprint; test_aCachedDayRowWithoutAStoredCostIsPricedAsASum ($1.80); testCurrentPricingVersionIsSeven; the pin
nc/p156-claude-prices-c (run 37120002017) a live session's day rows priced as one request; Fable 5.1 cache hit back to $1 5 of 4,039: test_aSessionWhoseRowsHoldNoStoredCostIsPricedAsASum ($1.80); test_cacheRatesFollowThePagesMultipliers, test_claudeCacheRowsCarryTheirResponsesCost ($1.00), test_publishedRatesPerMillionTokens and the pin (Fable 5.1)
nc/p647-fix-a (run 37500820418, after the 10-07 review) the line that replaces an earlier line of a response priced as .alreadyPriced (without its time or 1-hour split), the reviewer's mutation 3 of 4,041: test_aResponseWrittenOverSeveralLinesIsPricedFromItsLastLine ($0.904 for Opus 5.5, $0.123 for Sonnet 4.6) and test_aResponseWhoseLastLinesArriveInALaterReadIsRepricedFromThem ($0.904)
nc/p647-fix-b (run 37500827434) a line that replaces an open row carried from an earlier read keeps that row's priced flag 1 of 4,041: only test_aResponseWhoseLastLinesArriveInALaterReadIsRepricedFromThem ($0.904)
this Mac only the replacing line keeps the earlier line's pricing (line: existing.line) both new tests ($0.904 each); 79 other tests pass

Review. Gemini through agy-review on the diff, with the pricing page, the release notes and the archived page: one finding, fixed in 831f01a8 with a test (NC-C above): sumClaudeTotals, which gives a live session its cost, still priced a cached day row with no stored cost as one request, so a busy session could have landed on the tier. Codex CLI was out of quota.

Second review, 2026-10-07, on this head (8a5cff14): Gemini through agy-review again, on the same four questions (every rate and date against the page, the archived page and the release notes; event time and the 1-hour split on every path of parseClaudeFile, including rows carried from an earlier incremental read; any other place that prices Claude, or text that is now false; whether the tests catch a wrong rate, a lost split, a lost time and a per-kind tier): APPROVE, no findings. Codex CLI was tried again and was out of quota again. A repo-wide search found no other Claude price table (the Companion, the backend and Android carry none) and no user-facing string that names the old rates or the 1.25x write.

Third review, 2026-10-07, on 8a5cff14: APPROVE (non-blocking). Its one medium finding was a test gap: the branch where a later line of a response replaces an earlier one, which prices nearly every real response, had no test of its 1-hour writes or event time. That is fixed in 7ff00eab, with the tests and negative controls above. The low and informational findings are answered in the PR comment of the same day.

🤖 Generated with Claude Code

Copilot AI balanced review requested due to automatic review settings October 3, 2026 11:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

JasonYeYuhe added a commit that referenced this pull request Oct 6, 2026
…st instead of stopping the run

#647 takes 7 for the Claude cache (its price table). Version numbers name
one set of rules across both caches (testClaudeCacheStampedWithTheCodexVersion
IsRejected holds them apart), so the Codex rules of P0-1b move to 8 and the
history says 6 and 7 are Claude's.

The note test read the subagent caveat with `!`. Negative control B removes
the caveat, and the trap there ended the whole CLIPulseCore run, so none of
B's rule-5 expectations after it were ever reported. XCTUnwrap fails the
test and lets the run go on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JasonYeYuhe

Copy link
Copy Markdown
Collaborator Author

Review follow-up (2026-10-07), head 7ff00eab

The 10-07 review approved 8a5cff14 with one medium finding and five low or informational ones. One commit, 7ff00eab, fixes the medium one. The rest are answered below. This PR is not merged.

Fixed: the branch that prices nearly every real response is now tested (medium)

Claude Code writes a response over several lines and the last one counts. So almost every real response is priced in the branch where a later line replaces an earlier one. Before this fix, the end-to-end tests wrote one line per response and never reached that branch. Dropping line: pricing there still compiled and passed every test.

  • Pending.line has no default now. Every place that builds a Pending names the line that prices it. The two places that carry a row already priced say .alreadyPriced. Leaving the argument out is now a compile error.
  • test_aResponseWrittenOverSeveralLinesIsPricedFromItsLastLine, one read:
    • An Opus 5.5 response written over three lines, where only the last line carries the 1-hour split, costs $1.084. Priced from its first line it would be $0.904.
    • A two-line Sonnet 4.6 response with a 301K prompt, dated before 2026-03-13, costs $0.231. At today's rates it would be $0.123.
    • The response counts once, with the output of its last line.
  • test_aResponseWhoseLastLinesArriveInALaterReadIsRepricedFromThem, two reads:
    • The first read sees only the response's first line and charges $0.704. The test also checks that this read leaves the response open.
    • The second read is incremental, picks up the remaining lines, and charges $1.084.

Negative controls. Each mutation changes only the replace branch in parseClaudeFile.

mutation where failed
the replacing line priced as .alreadyPriced, the reviewer's mutation CI nc/p647-fix-a, run 37500820418 3 of 4,041 tests: test_aResponseWrittenOverSeveralLinesIsPricedFromItsLastLine ($0.904 and $0.123) and test_aResponseWhoseLastLinesArriveInALaterReadIsRepricedFromThem ($0.904)
the replacing line keeps the earlier line's pricing (line: existing.line) this Mac both new tests ($0.904 each); 79 other tests pass
a line that replaces an open row carried from an earlier read keeps that row's priced flag CI nc/p647-fix-b, run 37500827434 1 of 4,041 tests: only test_aResponseWhoseLastLinesArriveInALaterReadIsRepricedFromThem. The row is stored without a cost, so the day falls back to pricing its sum with every write at the 5-minute rate, which gives $0.904

Run locally, the first and third mutations failed exactly as on CI. Both nc/ branches are deleted.

CI on 7ff00eab: Swift CI run 37500794263 (full matrix) passed every job. CLIPulseCore ran 4,041 tests with 0 failures and 5 skipped, again under the Japanese, ROC and Buddhist calendars, plus 4,079 with 0 failures under -DDEVID_BUILD. Both new tests passed in all five passes. The push run 37500785984 also passed. CI Gate timed out after 40 minutes waiting for the queued Swift CI run and was re-run once Swift CI finished; attempt 2 passed. All 32 checks are green (2 skipped, as on every push run); the PR is blocked only by REVIEW_REQUIRED and is 0 commits behind main. On this Mac: the full suite ran 4,041 tests with 0 failures, the filtered suites 104 with 0 failures, and SwiftLint found 0 violations.

Not changed in this PR

🤖 Generated with Claude Code

JasonYeYuhe and others added 6 commits October 7, 2026 05:08
…5.5, Fable 5.1 and Sonnet 5.5 rows, Sonnet 5 at $2 / $10, and 1-hour cache writes

The Claude price table stopped at Opus 5, Sonnet 5 and Fable 5. Opus 5.5
borrowed Opus 5's $5 / $25 and $0.50 cache hits (its own: $4 / $20, $0.20),
and Fable 5.1 borrowed Fable 5's $1 cache hits (its own: $0.25). Cache hits
are most of a Claude Code day, so those two were charged about 2.5x and 4x
for most of their tokens, and the "≈" on the cost card came from them.
Sonnet 5 was charged $3 / $15, a scheduled increase Anthropic cancelled
before it happened. Every cache write was charged at the 5-minute rate,
although Claude Code writes much of its cache for an hour (2x input, not
1.25x).

- ClaudePricingTable (new, shared with iOS like CodexPricingTable): every
  row from https://platform.claude.com/docs/en/about-claude/pricing, read
  2026-10-03, in the page's column order (input, 5m write, 1h write, cache
  hit, output). New rows: claude-opus-5-5, claude-fable-5-1,
  claude-sonnet-5-5, claude-mythos-5-1, claude-mythos-5. Sonnet 5 at
  $2 / $10 / $0.20.
- Dated rates: Opus 4.6 and Sonnet 4.6 paid the 200K long-context tier
  until their 1M window went to standard pricing on 2026-03-13 (API release
  notes), so those rows carry the tier in `superseded` until then. The page
  lists no tier for any current model; Sonnet 4 and 4.5 keep theirs.
- The tier is Anthropic's rule (the pricing page as archived on
  2026-03-01): a request whose prompt, cache reads and writes included, is
  over 200K pays the long-context rates on every token. It was split per
  token kind at 200K each, written when a day's sum was priced; responses
  are priced one by one now, and a day's sum (the cache-row fallback) never
  takes the tier.
- The scanner reads usage.cache_creation.ephemeral_1h_input_tokens and
  prices each response at the rate in force at its own time.
- costUsageCachePricingVersion 6 -> 7, so every Mac re-reads its Claude logs
  once. claudeRatesFingerprint() is pinned next to it, as Codex's is.
- Tests: the table row by row against the page, the cache multipliers, the
  dated boundary to the second, 1-hour writes, the whole-request tier, the
  scanner end to end (Opus 5.5 with split writes, Sonnet 4.6 either side of
  03-13, the stored cost), and the fingerprint. Existing expectations that
  named the old fallback targets or the per-kind split are updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A day row's tokens are many responses, so the fallback must not put a busy
day on the 200K long-context tier. 300K Sonnet 4.5 tokens in one cached row
cost $0.90, not the $1.80 of one 300K request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sumClaudeTotals, which gives each active session its cost, priced a cached
day row without a stored cost through claudeCostUSD, which since the
previous commit decides the 200K tier per request. A day row is many
responses, so it would have put a busy session on long-context rates. It
now uses claudeAggregateCostUSD, as entriesFromClaudeCache does. Found by
review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… dating it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… its last line

Claude Code writes a response over several lines with the same ids, and the
last one counts, so nearly every real response is priced in the branch where
a later line replaces an earlier one. The end-to-end tests wrote one line per
response and only reached the first-sighting branch; dropping `line:` from the
replace branch still compiled (Pending.line had a default) and passed every
test.

- Pending.line has no default. Each place that makes a Pending names the line
  that prices it, or `.alreadyPriced` for a row whose cost is already in it.
- test_aResponseWrittenOverSeveralLinesIsPricedFromItsLastLine: an Opus 5.5
  response over three lines, only the last with the 1-hour split, costs
  $1.084; a two-line Sonnet 4.6 response with a 301K prompt before
  2026-03-13 costs $0.231.
- test_aResponseWhoseLastLinesArriveInALaterReadIsRepricedFromThem: the same
  Opus 5.5 response, its first line in one read ($0.704) and the rest in an
  incremental one, costs $1.084.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JasonYeYuhe
JasonYeYuhe merged commit 9375ba6 into main Oct 6, 2026
49 checks passed
@JasonYeYuhe
JasonYeYuhe deleted the p156-claude-prices branch October 6, 2026 20:37
JasonYeYuhe added a commit that referenced this pull request Oct 6, 2026
…st instead of stopping the run

#647 takes 7 for the Claude cache (its price table). Version numbers name
one set of rules across both caches (testClaudeCacheStampedWithTheCodexVersion
IsRejected holds them apart), so the Codex rules of P0-1b move to 8 and the
history says 6 and 7 are Claude's.

The note test read the subagent caveat with `!`. Negative control B removes
the caveat, and the trap there ended the whole CLIPulseCore run, so none of
B's rule-5 expectations after it were ever reported. XCTUnwrap fails the
test and lets the run go on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JasonYeYuhe added a commit that referenced this pull request Oct 6, 2026
…at is still simplified (#652)

* Port two of CodexBar's subagent and fork rules, and say on the Mac what is still simplified

P0-1b. #625 counted subagent and fork rollouts with a deliberately small
subset of CodexBar's rules. Compared with CodexBar's full rules (upstream
3bbf6bc4) on 33 rollouts built from its own fork and subagent tests, run
through both scanners, CLI Pulse matched CodexBar on 8. This ports what was
missing and local to one file; 24 of 33 now match, and every remaining
difference is either deliberate or needs the parent's file.

Ported:

- Rule 4 (CodexTokenAccountant): until a child with a history ordinal counts
  its first tokens, a repeat of the counter it started from, or a copied
  snapshot (a total equal to its own request, at or above that counter),
  adds nothing. From CodexBar's replay checks on the first owned token
  (#3524). Fixed: a forked child that re-reports a larger copied snapshot
  after its boundary counted the whole snapshot as usage.
- Rule 5: a subagent rollout written without a history ordinal (an older
  Codex) is read whole and classified by CodexBar's
  CodexSubagentRolloutShape.classify, ported verbatim under its MIT notice:
  its own history starts at a turn_context followed by a trigger_turn
  inter-agent message (after copied history, or confirmed by its first own
  event), or at an opening total with no request of its own. Events before
  it are copied. Fixed: compact subagents (#2285) and copied-history
  subagents (#2228) counted their parent's history. Such a file is read
  again from the start when it grows. Without such a start, the file counts
  by the other rules as before.

Not ported, and stated in a new line under the Codex note's subagent reason
(six languages): reading a fork's inherited counter from its parent's file.
A fork whose first event repeats its parent's last snapshot, or a subagent
without a history ordinal whose copied history has no turn marker, counts
that request once more. A tripwire test removes the line when the limit
goes. Kept on purpose: #625's reading of a history boundary with no marker
ahead of it (a migrated rollout).

No number changes on the machine this was measured on: the replica before
and after agree on all 171 days of its history (1,083 files), and the Swift
scanner and the replica agree on all 18 days of the 31-day window.

Codex cache rules version 5 -> 7 (6 is the Claude cache's).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Codex cache rules version 8, not 7, and a missing caveat fails its test instead of stopping the run

#647 takes 7 for the Claude cache (its price table). Version numbers name
one set of rules across both caches (testClaudeCacheStampedWithTheCodexVersion
IsRejected holds them apart), so the Codex rules of P0-1b move to 8 and the
history says 6 and 7 are Claude's.

The note test read the subagent caveat with `!`. Negative control B removes
the caveat, and the trap there ended the whole CLIPulseCore run, so none of
B's rule-5 expectations after it were ever reported. XCTUnwrap fails the
test and lets the run go on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* The simplified-rules line names the one request it can count twice, and a resumed read is tested to keep a child's inherited counter

Review of #652 (10-07):

- The line now says "some Codex subagent sessions" and "the last request
  copied in ... can be counted twice", in all six languages (zh: 生成/產生
  wording dropped, 重复计入/重複計入 as on the cached-input line). Not
  "older Codex versions": on the machine measured, the one subagent rollout
  without a history ordinal among 176 was written by Codex 0.153.4, which
  gave its other 57 one. Rule 5's comment says so instead of "older".
- The Usage Dashboard line's tooltip carries the caveat too
  (`dashboardHelp`, tested in zh-Hans).
- The cache round-trip test sets and checks isSubagent, namesForkParent,
  inheritedReference and openingSettled, and an older entry decodes them as
  nil.
- New scanner test: a child with a history ordinal read while only its
  copied history is written, then its replayed snapshot and own request
  appended. Only the own request counts after the resumed read, which
  depends on the persisted inheritedReference.
- The header lists one more difference from upstream: the history ordinal
  is taken from the first session_meta only, not from a later repeat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* zh-Hant: 分叉 for a forked session, as in zh-Hans, and 依簡化規則計算 without the stray 是

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants