mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-26 00:44:41 +00:00
Merge origin/main into feat/copilot-session-store
Resolves the conflicts #946 accumulated while it was in validation. Eight
files conflicted; the session-store accounting is unchanged.
src/daily-cache.ts — version collision. This PR minted 25 when main was at
24; #1056 (`codex-auto-review` pricing) then spent 25 on main. The bump moves
to 26/MIN 26 and daily-cache.v26.json, with main's full comment ladder kept as
the foundation and this PR's paragraph rewritten to name 26 and record the
collision. PENDING_REDERIVE_PROVIDERS and the B1 migration semantics from
b6481c19 carry over intact, retargeted at 26.
src/models.ts, src/parser.ts, src/audit-report.ts, src/models-report.ts —
#1075/#1078 replaced the per-site "reasoning is already inside output" tests
with billableOutputTokens() and REASONING_INCLUDED_IN_OUTPUT. This PR had
added copilot to that case at three sites independently. Union: all three
sites take main's helper call verbatim, and copilot joins claude and codex in
the set — same accounting this PR shipped, now through main's single source of
truth. It also reaches parser.ts activeGeneratedTokens (a fourth site, from
#1079), which is the same correction: a copilot supplementary call carries
reasoning with output 0, so counting it as generated repeats the per-turn
output. The audit legend already said so on this side.
src/providers/copilot.ts — comment-only. #1054's lastEventTimestamp-first
shutdown fallback was derived from this branch, so the code was already
identical on both sides: the `shutdownTimestamp` expression and the
`copilot:<sid>:shutdown:<model>:<n>` key are byte-for-byte main's. Both
rationales are kept (leg-collapse on date, and residual anchoring).
src/session-cache.ts — PROVIDER_PARSE_VERSIONS.copilot takes this PR's
`-session-store-v3` suffix; main's #1051 note about why a fingerprint change
is expensive is kept above it. Codex keeps main's #1092 suffix chain untouched.
src/main.ts — #1067 deleted the unreachable live dailyMap fallback that this
PR had taught behavioral weight. Main's deletion wins; the now-unused
isBehavioralTurn import goes with it.
tests/parser.test.ts — import union.
Also: scripts/upgrade-path/run.mjs NEW_DAILY_CACHE -> daily-cache.v26.json,
CODEBURN_COPILOT_SESSION_STORE_DB added to the #1064 env-isolation CLEARED
list, and the CHANGELOG entry's stale "v21" corrected to v26.
Verified: tsc clean; 3132 tests pass across 223 files; test:locks 26/26;
verify:upgrade PASSED, re-deriving daily-cache.v26.json and holding durable
copilot history across the bump. #1054's regression ("keeps three stampless
shutdown legs as :n keys with lastEventTimestamp") passes on the merged tree.
Real-corpus A/B against origin/main over 2026-07-01..2026-08-22: codex, grok,
kimicode and opencode byte-identical in export, audit and models; claude drifts
only monotonically with run order (a live session writing transcripts, confirmed
by interleaving four runs). This machine has no copilot data, so the copilot
recovery semantics rest on the suites and the upgrade-path corpus.
This commit is contained in:
commit
c30ebecff4
77 changed files with 3352 additions and 497 deletions
|
|
@ -44,6 +44,16 @@ const MANUAL_ENTRIES = {
|
|||
'deepseek-v4-pro': [4.35e-7, 8.7e-7, 0, 3.625e-9],
|
||||
// Mythos 5 launch pricing; not yet in LiteLLM or the models.dev/OpenRouter gap-fill (Fable is).
|
||||
'claude-mythos-5': [10e-6, 50e-6, 12.5e-6, 1e-6],
|
||||
// gpt-5.6-codex / gpt-5.6-codex-max (#1077): not yet in LiteLLM. Every prior
|
||||
// Codex-suffixed id LiteLLM DOES carry bills identically to its bare-model
|
||||
// sibling of the same generation - gpt-5-codex == gpt-5, gpt-5.1-codex ==
|
||||
// gpt-5.1-codex-max == gpt-5.1, gpt-5.2-codex == gpt-5.2, gpt-5.3-codex ==
|
||||
// gpt-5.3 (all four input/output/cache-write/cache-read rates identical,
|
||||
// verified against the live model_prices_and_context_window.json). Mirroring
|
||||
// that pattern onto gpt-5.6 rather than inventing a number: both ids get the
|
||||
// exact gpt-5.6 tuple (Sol-tier: $5/$30 per million, 1.25x cache-write).
|
||||
'gpt-5.6-codex': [5e-6, 3e-5, 6.25e-6, 5e-7],
|
||||
'gpt-5.6-codex-max': [5e-6, 3e-5, 6.25e-6, 5e-7],
|
||||
}
|
||||
|
||||
const snapshot = {}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,26 @@
|
|||
// which is the part the corpus can honestly establish.
|
||||
// dsh did not exist in the published CLI. Reported; required to be absent
|
||||
// in the baseline and present after the upgrade.
|
||||
// codex PRICING changed by design in #1075: reasoning tokens are billed
|
||||
// inside output rather than on top of it, and cache writes are carved out
|
||||
// of the input bucket. Nothing about what was PARSED moved, so codex keeps
|
||||
// the full exact treatment for the call count and every token field; the
|
||||
// cost tolerance is instead replaced with REPRICE_TOLERANCE — the
|
||||
// upgraded cost must be strictly lower than the baseline and within 25%
|
||||
// of it, since #1075 only ever removes a double-count and never raises
|
||||
// cost — and the delta is reported instead. Drop it from this list once a
|
||||
// published CLI carries the fix.
|
||||
const EXACT = ['claude', 'codex', 'gemini', 'kiro', 'cursor']
|
||||
const CHANGED_BY_DESIGN = ['grok']
|
||||
const COST_CHANGED_BY_DESIGN = ['codex']
|
||||
const NEW_IN_THIS_RELEASE = ['dsh']
|
||||
|
||||
const COST_TOLERANCE = 0.005 // 0.5% relative
|
||||
// #1075 only ever LOWERS codex cost (double-counted reasoning removed, cache
|
||||
// writes carved out of the input bucket) and by a bounded amount on any real
|
||||
// corpus; a rise, or a drop past this bound, means something beyond the known
|
||||
// repricing changed.
|
||||
const REPRICE_TOLERANCE = 0.25 // 25% relative
|
||||
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
|
|
@ -95,13 +110,25 @@ for (const name of providers) {
|
|||
if (b.calls !== u.calls) diffs.push(`calls ${b.calls} != ${u.calls}`)
|
||||
for (const f of TOKEN_FIELDS) if (b[f] !== u[f]) diffs.push(`${f} ${b[f]} != ${u[f]}`)
|
||||
const costDrift = relDiff(b.cost, u.cost)
|
||||
if (costDrift > COST_TOLERANCE) diffs.push(`cost ${fmt(b.cost)} != ${fmt(u.cost)} (${(costDrift * 100).toFixed(3)}% > ${(COST_TOLERANCE * 100).toFixed(1)}%)`)
|
||||
let repriced = false
|
||||
if (COST_CHANGED_BY_DESIGN.includes(name)) {
|
||||
if (u.cost > b.cost) diffs.push(`cost ${fmt(b.cost)} -> ${fmt(u.cost)} rose; #1075 should only lower codex cost`)
|
||||
else if (costDrift > REPRICE_TOLERANCE) diffs.push(`cost ${fmt(b.cost)} -> ${fmt(u.cost)} (${(costDrift * 100).toFixed(3)}% > ${(REPRICE_TOLERANCE * 100).toFixed(0)}% expected bound for #1075)`)
|
||||
else {
|
||||
repriced = true
|
||||
notes.push(`${name}: cost ${fmt(b.cost)} -> ${fmt(u.cost)} (${(costDrift * 100).toFixed(3)}%) — repricing expected (#1075); tokens and calls still asserted exactly`)
|
||||
}
|
||||
} else if (costDrift > COST_TOLERANCE) {
|
||||
diffs.push(`cost ${fmt(b.cost)} != ${fmt(u.cost)} (${(costDrift * 100).toFixed(3)}% > ${(COST_TOLERANCE * 100).toFixed(1)}%)`)
|
||||
}
|
||||
if (!EXACT.includes(name)) {
|
||||
notes.push(`${name}: no expectation declared in compare.mjs; ${diffs.length ? diffs.join(', ') : 'identical'}`)
|
||||
verdict = diffs.length ? 'differs (unclassified)' : 'identical'
|
||||
} else if (diffs.length) {
|
||||
failures.push(`${name}: ${diffs.join(', ')}`)
|
||||
verdict = 'DIFFERS'
|
||||
} else if (repriced) {
|
||||
verdict = `repriced (cost ${(costDrift * 100).toFixed(3)}% drift)`
|
||||
} else {
|
||||
verdict = costDrift === 0 ? 'identical' : `identical (cost ${(costDrift * 100).toFixed(3)}% drift)`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const WORK = process.env['UPGRADE_PATH_WORK'] || join(tmpdir(), 'codeburn upgrad
|
|||
const OLD_SESSION_CACHE = 'session-cache.v7.json'
|
||||
const OLD_DAILY_CACHE = 'daily-cache.v17.json'
|
||||
const NEW_SESSION_CACHE_DIR = 'session-cache.v9'
|
||||
const NEW_DAILY_CACHE = 'daily-cache.v25.json'
|
||||
const NEW_DAILY_CACHE = 'daily-cache.v26.json'
|
||||
|
||||
const HOME = join(WORK, 'user home')
|
||||
const PAYLOADS = join(WORK, 'payloads')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue