Skip to content

stack 1/5: triage the open issue surface and lock the bug plan - #951

Open
lidge-jun wants to merge 6 commits into
devfrom
codex/bug-stack-plan
Open

stack 1/5: triage the open issue surface and lock the bug plan#951
lidge-jun wants to merge 6 commits into
devfrom
codex/bug-stack-plan

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Stack

1/4 — triage and the plan

Base: dev
Next: #908 long-context pricing tiers

Summary

Sorts the open issue surface and locks the implementation order for the bugs nobody had reviewed. Documentation only — no src/ changes in this layer.

What the research round overturned

#907 is not a regeneration. scripts/generate-jawcode-metadata.ts:22-24 reads ../jawcode/packages/ai/src/models.json, and that canonical source carries the same stale Terra/Luna numbers across four provider bundles in a different repository. Regenerating today reproduces the defect exactly. The overlay cannot reach it either — src/usage/cost.ts:139-145 gives a valid nonzero jawcode row precedence, and a nonzero-but-wrong row is never a candidate.

It also surfaced a coupling: PRIORITY_MULTIPLIERS stores Fast pricing as ratios against the base rates, calibrated when the bases were stale. Correcting the bases without recomputing them would fix an overcharge on standard requests and introduce an undercharge on Fast ones, silently.

#875's reopen evidence tested a build 115 commits before the fix. git merge-base proves 0b30283b6 is an ancestor of 5dd965a13 ("fix DeepSeek Responses over Codex WebSocket"), which is on dev. The reproduction was real; it reproduced a defect that has since been fixed. Left open with a re-test request rather than closed on an ancestry argument the reporter cannot check.

#545's standing hypothesis was impossible. The recorded analysis said the prepended OAuth identity block consumed the classifier's 64 output tokens. A system prompt is input; max_tokens caps output. The real defect is a round-trip loss: thinking: {type: "disabled"} becomes reasoning: undefined, which is indistinguishable from omitted — and for Sonnet 5, omitted means adaptive thinking on, with thinking tokens counted against the same 64.

The audit gate

Four rounds, three FAIL. Every blocker was accepted and independently re-verified before amending:

  1. Long context × Fast cannot compose. The plan multiplied both. OpenAI's Fast guide says long context is not supported in Fast mode, so the $7.80 figure described a request that cannot exist. They are mutually exclusive regimes.
  2. -pro aliases are unpriceable today. A runtime probe returns null for all three, so a context-tier row could never be reached — the proposed test would have failed against the real estimator. That is a second real bug this work surfaced.
  3. usesAdaptiveThinking() was the wrong gate. It includes fable: [0,0], and Fable rejects an explicit disable — shipping it would have required breaking a passing test (tests/anthropic-reasoning.test.ts:139) to emit a production 400.
  4. Exclusivity was keyed on an unconfirmed tier, and provenance reaches four estimator call sites, not three.

Two of these would have produced code that passed CI and was wrong.

Verification

  • bun x tsc --noEmit — exit 0
  • bun run privacy:scan — passed
  • full prepush gate green on push

Notes

The later layers touch disjoint files (src/usage/, src/codex/, src/claude/+src/adapters/), so any layer can be retargeted to dev independently without a rebase conflict if you prefer to take them separately.

Summary by CodeRabbit

  • Documentation
    • Added planning documentation for triaging outstanding issues and prioritizing future fixes.
    • Documented upcoming improvements for long-context pricing, cooldown recovery, provider pricing accuracy, and classifier behavior.
    • Recorded investigation findings and retest requirements for DeepSeek connectivity and function-call handling.
    • Clarified issue classifications, compatibility labels, roadmap candidates, and unresolved follow-up items.
    • Added an outcome report summarizing issue dispositions, audit findings, corrected test gaps, and contributor work.

Sixteen bug issues, five of them unowned by any open PR. Records what the
research round overturned: #907 cannot be fixed here because the canonical
price source lives in lidge-jun/jawcode, and #875's reopen evidence tested a
commit 115 before the fix that addresses it.
…ck budget

The standing hypothesis said the prepended OAuth identity consumed the
classifier's 64 output tokens. A system prompt is input; it cannot. The real
loss is that thinking:{type:disabled} translates to reasoning:undefined, which
is indistinguishable from omitted — and omitted means adaptive thinking ON.
The audit caught a real design error: long context and Fast are mutually
exclusive regimes, not composable multipliers — OpenAI's guide says long
context is unsupported in Fast mode, so the $7.80 figure described an
impossible request. Also records that -pro aliases would have been skipped by
a base-id-only registry, that the main account has no WHAM single-flight to
join, and that bounded claims need fairness ordering.
Round 2 of the audit found three more, all provable. Reusing
usesAdaptiveThinking() as the disable gate would have emitted a body Fable
rejects — and required breaking a passing test to do it. The -pro aliases are
unpriceable today (runtime probe returns null), so a tier row alone could never
be reached. And exclusivity must key on the response-confirmed tier, since a
Fast request that exceeded 272k was necessarily downgraded.
…nt four call sites

The test text still said 'any priority request' after the design moved to
response-confirmed priority — implemented literally it would have reinstated
the bug the amendment removed. And provenance has to reach four estimator call
sites, not three: missing the per-provider one would make the dashboard total
disagree with its own breakdown.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds seven planning documents for backlog triage, long-context pricing, cooldown recovery, DeepSeek diagnostics, Jawcode pricing corrections, classifier thinking preservation, and stacked implementation outcomes.

Changes

Bug backlog planning

Layer / File(s) Summary
Scope and disposition planning
devlog/_plan/260803_bug_backlog_stack/000_scope.md, devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md
Defines issue ownership, review phases, proposed labels, maintainer sponsorship, and evidence-only handling.
Long-context pricing plan
devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md
Defines provider/model context tiers, pricing precedence, metadata propagation, and regression tests.
Cooldown recovery plan
devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md
Defines reset-derived cooldown probes, routing claim and settle primitives, snapshot validation, worker coalescing, startup wiring, and test coverage.
Residual and upstream dispositions
devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md, devlog/_plan/260803_bug_backlog_stack/050_jawcode_price_blocker.md
Documents DeepSeek retesting and diagnostic capture requirements, plus upstream Jawcode price corrections and metadata regeneration.
Classifier thinking preservation
devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md
Defines disabled-thinking preservation, a dedicated capability predicate, adapter output, and regression coverage.
Stack outcome report
devlog/_plan/260803_bug_backlog_stack/070_outcome.md
Records stacked layers, issue dispositions, audit findings, corrected assumptions, test changes, and contributor PR decisions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

  • Issue 915: The cooldown recovery plan directly addresses reset-derived cooldown recovery and routing probes.

Possibly related PRs

  • lidge-jun/opencodex#889: This PR documents residual DeepSeek triage for issue #875, while PR #889 implements related provider-wire fixes.
  • lidge-jun/opencodex#924: This PR overlaps with the cooldown recovery plan’s reset-derived eligibility and claim/settle fencing.

Suggested labels: chore

Suggested reviewers: wibias, ingwannu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the PR's main change: triaging open issues and defining the bug implementation plan.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/bug-stack-plan

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 12

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@devlog/_plan/260803_bug_backlog_stack/000_scope.md`:
- Around line 5-7: Update the objective statement in the scope document to align
with the phase map: state that each unowned issue is either implemented in a
later phase or handled through evidence or an upstream disposition, rather than
promising implementation for every unreviewed bug. Preserve the existing
two-deliverable structure and the bottom-up stacked pull-request approach for
defects that do enter implementation.
- Around line 117-123: Update
devlog/_plan/260803_bug_backlog_stack/000_scope.md:117-123 and
devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md:79-83 to
distinguish the stale original reproduction from the unresolved residual: state
that the original reproduction used commit 0b30283b6, 115 commits before the
fix, and that the “no follow-up request” residual remains unverified pending
retest and capture. Preserve the existing upstream disposition for `#907`.
- Around line 108-115: The Phase 1 status is inconsistent between the scope
table and disposition document. Update
devlog/_plan/260803_bug_backlog_stack/000_scope.md lines 108-115 and
devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md lines 5-12
consistently: if the sweep is complete, mark the disposition section completed
with its verification date and issue/comment evidence; otherwise change the
Phase 1 outcome from applied to planned.

In `@devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md`:
- Around line 72-84: Preserve response-tier provenance through the estimator
instead of passing only effectiveServiceTier() from the cost surfaces in
management/shared.ts and usage/summary.ts. Apply Fast pricing only when
responseServiceTier is confirmed as "priority"; requested or configured priority
without that response confirmation must use context pricing. Update the
long-context pricing test to use a request above the threshold with requested or
configured priority and response tier "default", while keeping confirmed Fast
coverage below 272,000 tokens.

In `@devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md`:
- Line 176: Update the paragraph beginning with “#922 touches” so it starts with
“PR `#922` touches” instead, resolving the Markdownlint MD018 error and preserving
the existing statement.
- Around line 13-17: Make the evidence references reproducible in
devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md:13-17 by
recording the exact commit SHA behind origin/dev; at 151-156, verify that
devlog/_plan/260803_cooldown_recovery_probe/000_plan.md exists or update the
reference to its current location; and at 174-181, record PR `#922`’s merge-base
SHA and re-check its touched files before relying on the non-overlap conclusion.

In `@devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md`:
- Line 7: Update the paragraph containing “#875” so the issue identifier is
wrapped in backticks rather than interpreted as a Markdown heading, while
preserving the surrounding text and meaning.

In `@devlog/_plan/260803_bug_backlog_stack/050_jawcode_price_blocker.md`:
- Around line 88-96: Update the planned regression near the usage-cost tests to
cover all four provider bundles: openai, openai-codex, github-copilot, and
opencode-zen. Use table-driven resolver assertions or a generator invariant that
verifies each nonzero row returns the exact expected tuple with source "jawcode"
and status "verified", rather than testing only resolveMatchedPrice("openai",
model).
- Around line 57-71: Update the pricing evidence section beside the model table
to include the canonical official-page URL, retrieval date, and relevant version
or snapshot identifier. Add or link a committed evidence artifact containing the
referenced pricing data so future reviewers can reproduce the verdict=strong_ok
decision and detect later vendor price changes.
- Around line 105-113: Extend the pricing regression tests around the
standard-price case to define the corrected Fast Terra and Luna expected values
and select Fast mode explicitly. Assert every billed dimension affected by
PRIORITY_MULTIPLIERS, including input and output rates, so the tests verify
Terra’s 3.2-based and Luna’s 0.08-based Fast pricing rather than only the base
rates.

In `@devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md`:
- Around line 123-127: Expand the model-ID regression matrix near the existing
Sonnet 5 and Fable cases with explicit canonical, date-pinned, and suffixed
Sonnet 5 variants. Add Opus 4.7 and Opus 4.8 cases asserting that the `"none"`
effort produces no `thinking` field. Ensure the cases cover both predicate
outcomes without widening the predicate itself.
- Around line 129-130: Update the round-trip plan’s Sonnet 5 handling at the
sampling-field sections around the unchanged-fields statement and lines 145-147:
omit or normalize temperature, top_p, and top_k for Sonnet 5 in both thinking
modes, while preserving them for models that support non-default values. Add a
final wire-shape assertion verifying the resulting Sonnet 5 request excludes or
normalizes those fields, without changing max_tokens, stop_sequences, OAuth
identity, terminal mapping, retry behavior, or native passthrough.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ba9deed3-c434-442b-95f5-332bcdc71bc6

📥 Commits

Reviewing files that changed from the base of the PR and between 14b20de and 151da16.

📒 Files selected for processing (7)
  • devlog/_plan/260803_bug_backlog_stack/000_scope.md
  • devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md
  • devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md
  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md
  • devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md
  • devlog/_plan/260803_bug_backlog_stack/050_jawcode_price_blocker.md
  • devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md

Comment on lines +5 to +7
Two deliverables, one unit. First, every open issue carries a disposition its
own content justifies. Second, the bugs that nobody has actually reviewed get
built — as a stacked pull-request chain, bottom-up, one layer per defect.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Align the objective with the phase map.

Lines 5-7 promise that all unreviewed bugs will be built. Lines 114-119 intentionally make #875 and #907 evidence-only, with no implementation phase. State that each unowned issue is either implemented in a later phase or handled through evidence or an upstream disposition.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/000_scope.md` around lines 5 - 7,
Update the objective statement in the scope document to align with the phase
map: state that each unowned issue is either implemented in a later phase or
handled through evidence or an upstream disposition, rather than promising
implementation for every unreviewed bug. Preserve the existing two-deliverable
structure and the bottom-up stacked pull-request approach for defects that do
enter implementation.

Comment on lines +108 to +115
| Phase | Doc | Unit | Outcome |
|---|---|---|---|
| 1 | `010` | Disposition sweep: labels + evidence comments | applied |
| 2 | `020` | #908 long-context pricing tiers | code |
| 3 | `030` | #915 cooldown early-recovery probe | code |
| 4 | `060` | #545 classifier thinking round-trip | code |
| — | `040` | #875 residual — evidence, no code | comment |
| — | `050` | #907 price staleness — evidence, no code | 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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- target files ---'
for f in devlog/_plan/260803_bug_backlog_stack/000_scope.md \
         devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md; do
  printf '\n### %s\n' "$f"
  wc -l "$f"
  sed -n '1,80p' "$f"
  printf '\n--- relevant later sections ---\n'
  sed -n '80,140p' "$f"
done

printf '\n--- phase-1 references and completion markers ---\n'
rg -n -i --glob '!node_modules' \
  '260803_bug_backlog_stack|010_disposition_sweep|disposition sweep|evidence comments|label corrections|verification date|applied|planned' \
  devlog .github 2>/dev/null || true

printf '\n--- repository state summary ---\n'
git status --short
git diff --stat

Repository: lidge-jun/opencodex

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -eu

dir='devlog/_plan/260803_bug_backlog_stack'

printf '%s\n' '--- phase-directory inventory ---'
git ls-files "$dir"

printf '\n%s\n' '--- complete Phase 1 document ---'
nl -ba "$dir/010_disposition_sweep.md" | sed -n '1,100p'

printf '\n%s\n' '--- completion/status wording in the stack documents ---'
rg -n -i \
  'status|state|planned|apply|applied|complete|completed|verification|evidence|date|done|no closures' \
  "$dir"/*.md

printf '\n%s\n' '--- commits that introduced or changed the two documents ---'
git log --oneline --follow -- "$dir/000_scope.md" | head -20
git log --oneline --follow -- "$dir/010_disposition_sweep.md" | head -20

printf '\n%s\n' '--- whether the phase document is the only Phase 1 record ---'
git ls-files | rg '260803_bug_backlog_stack|260725_wibias_pr_issue_disposition' || true

Repository: lidge-jun/opencodex

Length of output: 8890


🏁 Script executed:

#!/bin/bash
set -eu

dir='devlog/_plan/260803_bug_backlog_stack'

printf '%s\n' '--- Phase 1 document with line numbers ---'
sed -n '1,100p' "$dir/010_disposition_sweep.md" | awk '{printf "%4d\t%s\n", NR, $0}'

printf '\n%s\n' '--- document commits and changed paths ---'
git show --no-ext-diff --stat --oneline 71e14191
git show --no-ext-diff --stat --oneline 0d42ebcb
git show --no-ext-diff --format='format:%H%n%ad%n%s' --date=iso-strict 71e14191
git show --no-ext-diff --format='format:%H%n%ad%n%s' --date=iso-strict 0d42ebcb

printf '\n%s\n' '--- Phase 1 execution records outside the plan directory ---'
rg -n -i \
  '#(904|796|695|561|418|919|820|657|656|572|938|893|875|586|806|92|425|414|415|177|178|95|809)|disposition sweep|needs-info|provider-compatibility|maintainer-sponsored' \
  devlog/_fin/260803_bug_backlog_stack devlog/_fin 2>/dev/null | head -200 || true

Repository: lidge-jun/opencodex

Length of output: 50377


Align the Phase 1 completion state.

000_scope.md:108-115 marks Phase 1 as applied, but 010_disposition_sweep.md:11 still says Changes to apply and has no completion date or evidence. If the sweep is complete, rename the section and record the verification date with issue/comment evidence. Otherwise, change the scope outcome to planned.

📍 Affects 2 files
  • devlog/_plan/260803_bug_backlog_stack/000_scope.md#L108-L115 (this comment)
  • devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md#L5-L12
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/000_scope.md` around lines 108 - 115,
The Phase 1 status is inconsistent between the scope table and disposition
document. Update devlog/_plan/260803_bug_backlog_stack/000_scope.md lines
108-115 and devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md lines
5-12 consistently: if the sweep is complete, mark the disposition section
completed with its verification date and issue/comment evidence; otherwise
change the Phase 1 outcome from applied to planned.

Comment on lines +117 to +123
Two issues have no implementation phase on purpose, and each says why in its
own doc rather than being quietly dropped: #875's reopen evidence tested a
commit 115 before the fix, and #907's fix belongs in `lidge-jun/jawcode`.

`#907` is not "unfixable". It is fixable — upstream. Under the current
source-of-truth policy it should not be fixed locally, which is a different and
more honest claim.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- target sections ---'
sed -n '100,135p' devlog/_plan/260803_bug_backlog_stack/000_scope.md
sed -n '65,95p' devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md
printf '%s\n' '--- all `#875` references ---'
rg -n -C 4 '`#875`|875' devlog .github 2>/dev/null | head -n 300
printf '%s\n' '--- relevant filenames ---'
git ls-files | rg '875|260803_bug_backlog_stack|bug_backlog'

Repository: lidge-jun/opencodex

Length of output: 48662


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- 040 residual document ---'
sed -n '1,125p' devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md
printf '%s\n' '--- 040 remaining evidence and disposition ---'
sed -n '125,240p' devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md
printf '%s\n' '--- prior `#875` triage verdict ---'
sed -n '1,85p' devlog/_plan/260802_wt3_provider_wire/020_bug_b_deepseek_service_tier.md
printf '%s\n' '--- current repository evidence for the follow-up path ---'
rg -n -C 5 'no follow-up|follow-up request|residual|commit 115|candidate branch|reopen|`#892`|`#875`' devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md devlog/_plan/260802_wt3_provider_wire/020_bug_b_deepseek_service_tier.md

Repository: lidge-jun/opencodex

Length of output: 20668


🏁 Script executed:

#!/bin/bash
set -e
nl -ba devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md | sed -n '15,38p;78,105p'
nl -ba devlog/_plan/260803_bug_backlog_stack/000_scope.md | sed -n '114,124p'
nl -ba devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md | sed -n '79,84p'

Repository: lidge-jun/opencodex

Length of output: 265


🏁 Script executed:

#!/bin/bash
set -e
awk 'NR>=15 && NR<=38 {printf "%d:%s\n", NR, $0} NR>=78 && NR<=105 {printf "%d:%s\n", NR, $0}' devlog/_plan/260803_bug_backlog_stack/040_deepseek_residual.md
awk 'NR>=114 && NR<=124 {printf "%d:%s\n", NR, $0}' devlog/_plan/260803_bug_backlog_stack/000_scope.md
awk 'NR>=79 && NR<=84 {printf "%d:%s\n", NR, $0}' devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md

Repository: lidge-jun/opencodex

Length of output: 3336


Distinguish stale evidence from the unresolved residual.

040_deepseek_residual.md:85-96 records an unexplained “no follow-up request” residual and requires a retest on a build containing 5dd965a13; it does not document a post-fix reproduction. Update 000_scope.md:117-119 and 010_disposition_sweep.md:81-83 to state that the original reproduction used 0b30283b6, 115 commits before the fix, while the residual remains unverified pending retest and capture.

🧰 Tools
🪛 LanguageTool

[style] ~117-~117: Try using a descriptive adverb here.
Context: ...Two issues have no implementation phase on purpose, and each says why in its own doc rathe...

(ON_PURPOSE_DELIBERATELY)

📍 Affects 2 files
  • devlog/_plan/260803_bug_backlog_stack/000_scope.md#L117-L123 (this comment)
  • devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md#L79-L83
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/000_scope.md` around lines 117 - 123,
Update devlog/_plan/260803_bug_backlog_stack/000_scope.md:117-123 and
devlog/_plan/260803_bug_backlog_stack/010_disposition_sweep.md:79-83 to
distinguish the stale original reproduction from the unresolved residual: state
that the original reproduction used commit 0b30283b6, 115 commits before the
fix, and that the “no follow-up request” residual remains unverified pending
retest and capture. Preserve the existing upstream disposition for `#907`.

Comment on lines +72 to +84
"Confirmed" is load-bearing. `effectiveServiceTier()`
(`src/usage/cost.ts:249-258`) collapses three sources into one scalar with the
precedence `responseServiceTier ?? requestedServiceTier ??
configuredServiceTier`, and the estimator only ever sees the result. OpenAI
documents that a Fast request may be served as `default`, and that the
response's `service_tier` is what identifies the tier actually used — and Fast
does not support long context at all, so a >272k request tagged `priority`
was necessarily *not* served as Fast.

Suppressing the context tier on a merely *requested* priority would therefore
under-bill exactly the request that provoked the downgrade. Exclusivity keys on
`responseServiceTier === "priority"`; a requested-or-configured priority with
no response confirmation takes the context tier.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- plan excerpt ---'
sed -n '1,220p' devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md

printf '%s\n' '--- source symbols and call sites ---'
rg -n -C 5 'effectiveServiceTier|applyPriorityMultiplier|applyContextTier|contextTier|serviceTier' \
  src/usage/cost.ts src/server/management/shared.ts src/usage/summary.ts

Repository: lidge-jun/opencodex

Length of output: 15950


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- cost estimator implementation ---'
sed -n '90,390p' src/usage/cost.ts

printf '%s\n' '--- service-tier types and persistence ---'
rg -n -C 6 'responseServiceTier|requestedServiceTier|configuredServiceTier|serviceTier' \
  src/types.ts src/usage src/server tests/usage-cost.test.ts

printf '%s\n' '--- cited Fast fixture ---'
sed -n '380,435p' tests/usage-cost.test.ts

Repository: lidge-jun/opencodex

Length of output: 49424


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- exact plan line ranges ---'
nl -ba devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md | sed -n '50,90p;160,215p'

printf '%s\n' '--- estimator result types and all call sites ---'
rg -n -C 5 'interface (AttemptCostEstimate|CostEstimate)|type (AttemptCostEstimate|CostEstimate)|estimate(Attempt|Request|Combo)Cost\(' \
  src tests

Repository: lidge-jun/opencodex

Length of output: 16894


🌐 Web query:

OpenAI Fast mode guide long context not supported response service_tier priority default

💡 Result:

As of August 3, 2026, OpenAI's Fast mode (formerly known as Priority processing) provides lower and more consistent latency for supported models [1][2]. Regarding your specific query: 1. Long Context Support: Fast mode is not supported for long context models, fine-tuned models, or embeddings [2][3]. 2. Service Tier and Default Behavior: - You can opt into Fast mode by setting the service_tier parameter to fast or priority in your API requests [2][4]. - If you configure your project settings to default to Fast mode, requests that do not explicitly specify a service_tier will automatically use Fast mode [2][4]. - If your traffic ramps up too quickly, the system may automatically downgrade individual requests from Fast mode to Standard processing [1][2]. When this occurs, the service_tier field in the API response will return default [1][2]. In summary, default in the response indicates a fallback from your requested Fast/Priority tier to the standard service level due to rapid traffic increases, while service_tier: "default" is also the base state when no specific tier is requested and no project-level default has been set [1][5][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- exact plan line ranges ---'
awk 'NR >= 50 && NR <= 90 || NR >= 160 && NR <= 215 { printf "%6d %s\n", NR, $0 }' \
  devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md

printf '%s\n' '--- standalone provenance probe ---'
python3 - <<'PY'
BASE = {"input": 5.0, "output": 30.0, "cacheRead": 0.5, "cacheWrite": 6.25}
FAST = 2.0
CONTEXT = {"input": 2.0, "output": 1.5, "cacheRead": 2.0, "cacheWrite": 2.0}

def effective(response=None, requested=None, configured=None):
    return response or requested or configured

def current_price(response=None, requested=None, configured=None):
    tier = effective(response, requested, configured)
    return "fast", FAST if tier == "priority" else 1.0

def corrected_price(response=None, requested=None, configured=None):
    confirmed_fast = response == "priority"
    return ("fast", FAST) if confirmed_fast else ("long", CONTEXT["input"])

raw_input = 300_000
output = 20_000
short_total = raw_input / 1_000_000 * BASE["input"] + output / 1_000_000 * BASE["output"]
fast_total = short_total * FAST
long_total = raw_input / 1_000_000 * BASE["input"] * CONTEXT["input"] / 2
long_total += output / 1_000_000 * BASE["output"] * CONTEXT["output"] / 1.5

print("requested priority only:", current_price(requested="priority")[0],
      "but required:", corrected_price(requested="priority")[0])
print("configured priority only:", current_price(configured="priority")[0],
      "but required:", corrected_price(configured="priority")[0])
print("response priority:", current_price(response="priority")[0],
      "and required:", corrected_price(response="priority")[0])
print("long request base:", short_total)
print("long request context:", long_total)
print("long request current requested-priority price:", fast_total)
print("underbilling from current requested-priority selection:", long_total - fast_total)
PY

Repository: lidge-jun/opencodex

Length of output: 5766


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
BASE = {"input": 5.0, "output": 30.0, "cacheRead": 0.5, "cacheWrite": 6.25}
FAST = {"input": 2.0, "output": 2.0, "cacheRead": 2.0, "cacheWrite": 2.0}
LONG = {"input": 2.0, "output": 1.5, "cacheRead": 2.0, "cacheWrite": 2.0}

usage = {"input": 300_000, "output": 20_000, "cacheRead": 0, "cacheWrite": 0}

def effective(response=None, requested=None, configured=None):
    return response or requested or configured

def cost(multiplier):
    return sum(
        usage[field] / 1_000_000 * BASE[field] * multiplier[field]
        for field in usage
    )

def current_selection(response=None, requested=None, configured=None):
    return "fast" if effective(response, requested, configured) == "priority" else "context"

def required_selection(response=None, requested=None, configured=None):
    return "fast" if response == "priority" else "context"

for label, fields in [
    ("requested priority only", {"requested": "priority"}),
    ("configured priority only", {"configured": "priority"}),
    ("response priority", {"response": "priority"}),
]:
    print(
        label,
        "current=", current_selection(**fields),
        "required=", required_selection(**fields),
    )

print("context cost=", cost(LONG))
print("fast cost=", cost(FAST))
print("selection error for requested priority=", cost(FAST) - cost(LONG))
PY

Repository: lidge-jun/opencodex

Length of output: 410


Preserve service-tier provenance through the estimator.

effectiveServiceTier() collapses response, requested, and configured tiers. All four cost surfaces pass only that value: src/server/management/shared.ts:127-130, src/usage/summary.ts:289-292, 418-421, and 527-530. Pass responseServiceTier or equivalent provenance into the estimator. Apply Fast pricing only when responseServiceTier === "priority"; otherwise, a long request with requested or configured priority must use context pricing. For the stated Sol rates, this changes 300,000 input plus 20,000 output from $4.20 to $3.90.

The test at 020_long_context_pricing.md:202-204 is inconsistent with the Fast-mode constraint at lines 57-60. Fast mode does not support long context, so test confirmed Fast below 272,000 tokens. Test a request above the threshold with requested or configured priority and a response tier of "default" for the context-tier path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/020_long_context_pricing.md` around
lines 72 - 84, Preserve response-tier provenance through the estimator instead
of passing only effectiveServiceTier() from the cost surfaces in
management/shared.ts and usage/summary.ts. Apply Fast pricing only when
responseServiceTier is confirmed as "priority"; requested or configured priority
without that response confirmation must use context pricing. Update the
long-context pricing test to use a request above the threshold with requested or
configured priority and response tier "default", while keeping confirmed Fast
coverage below 272,000 tokens.

Comment on lines +13 to +17
The chain, verified on `origin/dev`:

1. Cooled accounts are filtered out **before** every strategy runs
(`src/codex/routing.ts:740-768`). All three selectors consume only the
already-filtered list (`:869-905`, `:914-972`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the evidence references reproducible.

The plan depends on mutable branch state, an older plan path, and live PR state. Pin the evidence or verify it during merge.

  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md#L13-L17: record the exact commit SHA behind origin/dev.
  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md#L151-L156: verify the referenced devlog/_plan/260803_cooldown_recovery_probe/000_plan.md exists, or update the reference if the plan moved.
  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md#L174-L181: record the PR #922 merge base and re-check its touched files before relying on the non-overlap decision.
📍 Affects 1 file
  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md#L13-L17 (this comment)
  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md#L151-L156
  • devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md#L174-L181
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md` around lines
13 - 17, Make the evidence references reproducible in
devlog/_plan/260803_bug_backlog_stack/030_cooldown_recovery.md:13-17 by
recording the exact commit SHA behind origin/dev; at 151-156, verify that
devlog/_plan/260803_cooldown_recovery_probe/000_plan.md exists or update the
reference to its current location; and at 174-181, record PR `#922`’s merge-base
SHA and re-check its touched files before relying on the non-overlap conclusion.

Comment on lines +57 to +71
## The correction to the report

The reporter asserted cache writes should be zero. They should not. The
official page publishes a `Short context cache writes` column with nonzero
values for all three models (retrieved 2026-08-03, `verdict=strong_ok`):

| Model | input / cachedInput / cacheWrite / output |
|---|---|
| `gpt-5.6-sol` | 5.00 / 0.50 / 6.25 / 30.00 |
| `gpt-5.6-terra` | 2.00 / 0.20 / 2.50 / 12.00 |
| `gpt-5.6-luna` | 0.20 / 0.02 / 0.25 / 1.20 |

Sol's bundled row is already correct. A regeneration that zeroed cache writes
would replace one wrong number with another — and it would have looked like
progress.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Record the authoritative pricing evidence.

The correction depends on values from “the official page,” but this document includes no source URL, version, snapshot, or committed evidence artifact. Future reviewers cannot reproduce the verdict=strong_ok decision or distinguish a vendor price change from stale documentation.

Add the canonical source reference and retrieval metadata beside this table.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/050_jawcode_price_blocker.md` around
lines 57 - 71, Update the pricing evidence section beside the model table to
include the canonical official-page URL, retrieval date, and relevant version or
snapshot identifier. Add or link a committed evidence artifact containing the
referenced pricing data so future reviewers can reproduce the verdict=strong_ok
decision and detect later vendor price changes.

Comment on lines +88 to +96
Sol unchanged. All four provider bundles need the same correction or they will
contradict each other.

## What lands here afterwards

Regenerate, commit the generated diff without hand-editing, and add a
table-driven regression near `tests/usage-cost.test.ts:153-159` asserting
`resolveMatchedPrice("openai", model)` returns the exact tuple with
`source: "jawcode"` and `status: "verified"` for all three models.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Cover all four Jawcode provider bundles in the regression.

The plan requires corrections for /openai, /openai-codex, /github-copilot, and /opencode-zen, but the proposed test calls resolveMatchedPrice("openai", model) only. That assertion can pass while another bundle retains stale Terra or Luna prices.

Add table-driven assertions for every provider bundle, or add a generator-level invariant that all four nonzero rows contain the expected tuple. Keep the resolver assertion for source: "jawcode" and status: "verified".

🧰 Tools
🪛 LanguageTool

[locale-violation] ~91-~91: In American English, ‘afterward’ is the preferred variant. ‘Afterwards’ is more commonly used in British English and other dialects.
Context: ...tradict each other. ## What lands here afterwards Regenerate, commit the generated diff ...

(AFTERWARDS_US)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/050_jawcode_price_blocker.md` around
lines 88 - 96, Update the planned regression near the usage-cost tests to cover
all four provider bundles: openai, openai-codex, github-copilot, and
opencode-zen. Use table-driven resolver assertions or a generator invariant that
verifies each nonzero row returns the exact expected tuple with source "jawcode"
and status "verified", rather than testing only resolveMatchedPrice("openai",
model).

Comment on lines +105 to +113
`PRIORITY_MULTIPLIERS` (`src/usage/expected-prices.ts:152-156`) stores Fast
pricing as *ratios against the base rates* — Terra `1.6`, Luna `0.4`. Those
ratios were calibrated when the bases were stale.

Correcting the bases therefore breaks Fast estimates for the same two models:
1.6 × 2 = 3.2 against a published Fast Terra of 4, and 0.4 × 0.20 = 0.08
against a published 0.40. The regeneration that fixes #907 must recompute or
replace those multipliers in the same change, or it will fix an overcharge on
standard requests while introducing an undercharge on Fast ones.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Add regression coverage for corrected Fast pricing.

The documented base-rate correction changes the Fast estimates: Terra becomes 1.6 × 2 = 3.2 instead of the published 4, and Luna becomes 0.4 × 0.20 = 0.08 instead of 0.40. The standard-price test at Lines 93-96 will not exercise PRIORITY_MULTIPLIERS.

Define the corrected Fast values and assert them with the actual Fast-mode selector. Cover every billed dimension that the multiplier affects, not only the base input rate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/050_jawcode_price_blocker.md` around
lines 105 - 113, Extend the pricing regression tests around the standard-price
case to define the corrected Fast Terra and Luna expected values and select Fast
mode explicitly. Assert every billed dimension affected by PRIORITY_MULTIPLIERS,
including input and output rates, so the tests verify Terra’s 3.2-based and
Luna’s 0.08-based Fast pricing rather than only the base rates.

Comment on lines +123 to +127
**Pre-write search (DEV-NECESSITY-01).** Reuse was checked first and rejected
on evidence rather than skipped: `usesAdaptiveThinking()` is the only existing
model predicate in this adapter, and it answers a different question. The new
predicate borrows its parsing shape so date-pinned and suffixed ids behave
identically.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Complete the model-ID regression matrix.

Lines 123-127 claim identical behavior for date-pinned and suffixed IDs. Lines 139-147 list only canonical Sonnet 5 and Fable cases. Add explicit canonical, date-pinned, and suffixed Sonnet 5 cases.

Also add Opus 4.7 and Opus 4.8 cases that assert no thinking field is emitted for "none". Omitted thinking is already off for those models. (platform.claude.com)

These cases verify both sides of the new predicate and prevent future gate widening.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md` around
lines 123 - 127, Expand the model-ID regression matrix near the existing Sonnet
5 and Fable cases with explicit canonical, date-pinned, and suffixed Sonnet 5
variants. Add Opus 4.7 and Opus 4.8 cases asserting that the `"none"` effort
produces no `thinking` field. Ensure the cases cover both predicate outcomes
without widening the predicate itself.

Comment on lines +129 to +130
Explicitly unchanged: `max_tokens`, `stop_sequences`, the OAuth identity block,
terminal mapping, retry behavior, native passthrough.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
file='devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md'
printf '%s\n' '--- target context ---'
sed -n '110,160p' "$file"
printf '%s\n' '--- related references ---'
rg -n -i --glob '!node_modules' 'Sonnet 5|sonnet-5|temperature|top[_-]?p|reasoning|native passthrough|sampling' devlog .github src test tests 2>/dev/null | head -n 300

Repository: lidge-jun/opencodex

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- candidate files ---'
git ls-files | rg '(^|/)(anthropic-reasoning|claude-inbound|060_classifier_thinking)\.(test\.)?(ts|md)$|classifier|anthropic'
printf '%s\n' '--- focused references ---'
rg -n -i --glob '*.ts' --glob '*.md' --glob '*.json' \
  'temperature.{0,80}0\.3|topP|top_p|top-k|top_k|Sonnet 5|sonnet-5|native passthrough|round-trip' \
  devlog src tests test 2>/dev/null | head -n 250
printf '%s\n' '--- plan headings and numbered sections ---'
rg -n '^#{1,4}|^[0-9]+\.' devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md

Repository: lidge-jun/opencodex

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- sampling references outside generated metadata ---'
rg -n --glob '!src/generated/**' --glob '!**/*.lock' \
  '\btemperature\b|\btopP\b|\btop_p\b|\btopK\b|\btop_k\b' \
  src tests devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md \
  devlog/_fin/260701_anthropic-reasoning-none-gate \
  2>/dev/null | head -n 300
printf '%s\n' '--- exact relevant test excerpts ---'
for f in tests/anthropic-reasoning.test.ts tests/claude-inbound.test.ts; do
  if test -f "$f"; then
    echo "### $f"
    rg -n -C 8 'sonnet-5|temperature|topP|top_p|reasoning|thinking' "$f" | head -n 240
  fi
done
printf '%s\n' '--- adapter structure ---'
ast-grep outline src/adapters/anthropic.ts
ast-grep outline src/oauth/anthropic.ts

Repository: lidge-jun/opencodex

Length of output: 28157


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- anthropic request construction ---'
sed -n '710,825p' src/adapters/anthropic.ts
printf '%s\n' '--- model capability types and provider config ---'
sed -n '1065,1100p' src/types.ts
sed -n '980,1025p' src/providers/registry.ts
printf '%s\n' '--- plan with line numbers ---'
cat -n devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md | sed -n '1,180p'
printf '%s\n' '--- completed issue notes ---'
cat -n devlog/_fin/260701_anthropic-reasoning-none-gate/00_research.md
cat -n devlog/_fin/260701_anthropic-reasoning-none-gate/20_verification.md

Repository: lidge-jun/opencodex

Length of output: 25788


🌐 Web query:

Anthropic official Sonnet 5 non-default temperature top_p top_k 400 thinking disabled sampling parameters

💡 Result:

For the Claude Sonnet 5 model, Anthropic has introduced a strict constraint regarding sampling parameters: requests that include non-default values for temperature, top_p, or top_k will return a 400 error [1][2]. This policy applies to all requests made to Claude Sonnet 5, regardless of whether thinking mode is enabled or disabled [3]. Consequently, when using this model, you must either omit these parameters from your API request entirely or ensure they are set to their respective default values [1][2]. To guide the model's behavior or output style on Sonnet 5, Anthropic recommends using system-prompt instructions instead of adjusting sampling parameters [1][2]. This change is part of the standard behavior for the Sonnet 5 model class [1].

Citations:


Define Sonnet 5 sampling normalization.

Sonnet 5 returns HTTP 400 for non-default temperature, top_p, or top_k, whether thinking is enabled or disabled. Update lines 129-130 and 145-147 so the round-trip plan omits or normalizes these fields for Sonnet 5. Preserve them only for models that accept them, and add a final wire-shape assertion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/060_classifier_thinking.md` around
lines 129 - 130, Update the round-trip plan’s Sonnet 5 handling at the
sampling-field sections around the unchanged-fields statement and lines 145-147:
omit or normalize temperature, top_p, and top_k for Sonnet 5 in both thinking
modes, while preserving them for models that support non-default values. Add a
final wire-shape assertion verifying the resulting Sonnet 5 request excludes or
normalizes those fields, without changing max_tokens, stop_sequences, OAuth
identity, terminal mapping, retry behavior, or native passthrough.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 151da16c7b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

only for a real non-`none` effort (`src/adapters/anthropic.ts:769-770`), so the
outbound request omits the field. Anthropic documents that for Sonnet 5 an
omitted `thinking` field means *adaptive thinking is on by default*, and that
thinking tokens count against `max_tokens` (retrieved 2026-08-04:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Record the actual documentation retrieval date

This commit was authored and committed on 2026-08-03, so the claim that the Anthropic documentation was retrieved on 2026-08-04 gives the evidence a future, impossible provenance date. Because this evidence justifies the proposed model-specific behavior on an OAuth execution path, replace it with the actual retrieval date (and re-verify the pages if necessary) so reviewers can trust the audit trail.

Useful? React with 👍 / 👎.

Comment on lines +143 to +145
This phase therefore adds provider-scoped base-price rows for the three
aliases alongside their tier rows. That is a real bug of its own surfaced by
this work: `-pro` usage currently shows no cost estimate whatsoever.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Price Fast requests for the -pro aliases

Adding base-price and context-tier rows alone leaves Fast requests for these aliases underpriced: applyPriorityMultiplier() keys PRIORITY_MULTIPLIERS by the logged model, that table contains only the three base GPT-5.6 IDs, and applyOpenAiVirtualModel() deliberately keeps the selected -pro ID in logCtx.model. Therefore an openai-apikey/gpt-5.6-*-pro response confirmed as priority will receive neither the base model's Fast multiplier nor, under the proposed exclusivity rule, the long-context multiplier. Add equivalent priority entries (or a narrowly scoped virtual-ID normalization) and cover a Fast -pro request in the tests.

Useful? React with 👍 / 👎.

Comment on lines +80 to +83
`src/codex/auth-api.ts` — add `runCodexCooldownRecoveryProbes()`, coalesced by
a module-level promise, bounded by the existing `mapWithConcurrency(..., 4,
...)`. Registered on the state sweeper's existing 60s tick
(`src/lib/state-store-sweeper.ts:155-166`) — no new timer. Registration is

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Require explicit security review for the recovery worker

This phase adds an autonomous path in auth-api.ts that obtains pool credentials and sends authenticated WHAM requests, but the plan only mentions a generic account-pool audit gate and never requires the explicit security review mandated for authentication and credential-handling changes. Mark this stack layer as security-review-required before merge, as the classifier phase already does for its OAuth path.

AGENTS.md reference: AGENTS.md:L199-L203

Useful? React with 👍 / 👎.

Comment on lines +175 to +178
`contextTier?: ContextTierName` is added to `AttemptCostEstimate` and
`CostEstimate` so the dashboard can distinguish "long" from "just a bigger
number". A combo result carries it when any attempt does, while each attempt
keeps its own.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include the tiered cost behavior in the public docs

The phase changes user-visible estimated costs and adds contextTier specifically so the dashboard can distinguish long-context pricing, but its implementation and test plan contains no docs-site/ update. Without documenting when the estimator switches the entire request to long-context rates—and how confirmed Fast responses remain exclusive—the dashboard's displayed totals can change substantially with no user-facing explanation; update the relevant dashboard/Codex pricing documentation and keep its translations consistent.

AGENTS.md reference: AGENTS.md:L212-L213

Useful? React with 👍 / 👎.

Comment on lines +93 to +96
Regenerate, commit the generated diff without hand-editing, and add a
table-driven regression near `tests/usage-cost.test.ts:153-159` asserting
`resolveMatchedPrice("openai", model)` returns the exact tuple with
`source: "jawcode"` and `status: "verified"` for all three models.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match the price regression to resolver status

The proposed assertion cannot pass after the upstream price regeneration as described: openai has no jawcodeBundle mapping in the provider registry, so resolveMatchedPrice("openai", model) reaches resolveModelLevelPrice() and returns source: "jawcode" with status: "verified-derived", including for Sol today. Regenerating corrected Terra/Luna rows does not alter that provider mapping. Either assert verified-derived here or explicitly include and justify the mapping change needed to make these results directly verified.

Useful? React with 👍 / 👎.

@lidge-jun

Copy link
Copy Markdown
Owner Author

Stack navigation

  1. stack 1/5: triage the open issue surface and lock the bug plan #951 — triage the open issue surface and lock the bug plan (base dev)
  2. stack 2/5: price long-context requests at the published long rate (#908) #952 — long-context pricing tiers, Cost estimates ignore published long-context pricing tiers (OpenAI >272k, xAI >=200k) #908 (base stack 1/5: triage the open issue surface and lock the bug plan #951)
  3. stack 3/5: carry six contributor bug fixes with authorship intact #953 — carry six contributor bug fixes (base stack 2/5: price long-context requests at the published long rate (#908) #952)

Review and merge bottom-up. Each PR targets the preceding stack branch, so its Files changed view contains only that layer.

The layers touch disjoint files — devlog/, src/usage/, and the carried contributors' paths — so any layer can be retargeted to dev and taken independently without a rebase conflict if you prefer.

Carried in #953, with authorship preserved: #939, #942, #943, #944, #945, #948.

@lidge-jun

Copy link
Copy Markdown
Owner Author

Stack navigation

  1. stack 1/5: triage the open issue surface and lock the bug plan #951 — triage the open issue surface and lock the bug plan (base dev)
  2. stack 2/5: price long-context requests at the published long rate (#908) #952 — long-context pricing tiers, Cost estimates ignore published long-context pricing tiers (OpenAI >272k, xAI >=200k) #908 (base stack 1/5: triage the open issue surface and lock the bug plan #951)
  3. stack 3/5: carry six contributor bug fixes with authorship intact #953 — carry six contributor bug fixes (base stack 2/5: price long-context requests at the published long rate (#908) #952)
  4. stack 4/5: keep an explicit thinking disable through translation (#545) #954 — Claude Desktop classifier thinking round-trip, Claude Desktop 3P Auto Mode classifier retries after 64-token Anthropic OAuth outputs #545 (base stack 3/5: carry six contributor bug fixes with authorship intact #953)

Review and merge bottom-up. Each PR targets the preceding stack branch, so its Files changed view contains only that layer.

The layers touch disjoint files — devlog/, src/usage/, the carried contributors' paths, and src/claude/ + src/adapters/anthropic.ts — so any layer can be retargeted to dev and taken independently without a rebase conflict.

#954 needs human security review per MAINTAINERS.md: it changes request construction on an Anthropic OAuth execution path. It is last in the stack so the first three can land without waiting on that.

Carried in #953, with authorship preserved: #939, #942, #943, #944, #945, #948.

@lidge-jun lidge-jun changed the title stack 1/3: triage the open issue surface and lock the bug plan stack 1/4: triage the open issue surface and lock the bug plan Aug 3, 2026
@lidge-jun

Copy link
Copy Markdown
Owner Author

Stack navigation

  1. stack 1/5: triage the open issue surface and lock the bug plan #951 — triage the open issue surface and lock the bug plan (base dev)
  2. stack 2/5: price long-context requests at the published long rate (#908) #952 — long-context pricing tiers, Cost estimates ignore published long-context pricing tiers (OpenAI >272k, xAI >=200k) #908 (base stack 1/5: triage the open issue surface and lock the bug plan #951)
  3. stack 3/5: carry six contributor bug fixes with authorship intact #953 — carry six contributor bug fixes (base stack 2/5: price long-context requests at the published long rate (#908) #952)
  4. stack 4/5: keep an explicit thinking disable through translation (#545) #954 — Claude Desktop classifier thinking round-trip, Claude Desktop 3P Auto Mode classifier retries after 64-token Anthropic OAuth outputs #545 (base stack 3/5: carry six contributor bug fixes with authorship intact #953)
  5. stack 5/5: probe reset-derived cooldowns without waiting to be selected (#915) #955 — cooldown early-recovery probe, [Bug]: Reset-derived cooldowns can miss early recovery while another pool account remains eligible #915 (base stack 4/5: keep an explicit thinking disable through translation (#545) #954)

Review and merge bottom-up. Each PR targets the preceding stack branch, so its Files changed view contains only that layer.

The layers touch disjoint files — devlog/, src/usage/, the carried contributors' paths, src/claude/ + src/adapters/anthropic.ts, and src/codex/ — so any layer can be retargeted to dev and taken independently without a rebase conflict.

#954 needs human security review per MAINTAINERS.md: it changes request construction on an Anthropic OAuth execution path. #955 sits above it in the chain but is independent of it in code, so if that review blocks, #955 can be retargeted to #953 without conflict.

Carried in #953, with authorship preserved: #939, #942, #943, #944, #945, #948.

@lidge-jun lidge-jun changed the title stack 1/4: triage the open issue surface and lock the bug plan stack 1/5: triage the open issue surface and lock the bug plan Aug 3, 2026
Five layers, sixteen bug issues dispositioned, zero closed on a partial fix.
Twelve adversarial rounds, nine FAIL — including three #915 defects that were
each introduced by fixing the previous one, which is the part worth remembering:
a hand-written allowlist was never the right answer where the domain is an open
string.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@devlog/_plan/260803_bug_backlog_stack/070_outcome.md`:
- Around line 5-6: Update the stack description in 070_outcome.md to say
“five-layer stack” instead of “four-layer stack,” matching the five listed PR
layers (`#951` through `#955`).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ab4e6466-e5af-4eb4-aca9-f801b9d189de

📥 Commits

Reviewing files that changed from the base of the PR and between 151da16 and 133d4dd.

📒 Files selected for processing (1)
  • devlog/_plan/260803_bug_backlog_stack/070_outcome.md

Comment on lines +5 to +6
A four-layer stack off `origin/dev` at `14b20def2`, each layer targeting the
one before it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the stack count.

This text says “four-layer stack,” but the table lists five layers: PRs #951 through #955. The PR objectives also define five layers. Change “four-layer” to “five-layer” to prevent incorrect stack-order documentation.

Proposed fix
-A four-layer stack off `origin/dev` at `14b20def2`, each layer targeting the
+A five-layer stack off `origin/dev` at `14b20def2`, each layer targeting the
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
A four-layer stack off `origin/dev` at `14b20def2`, each layer targeting the
one before it.
A five-layer stack off `origin/dev` at `14b20def2`, each layer targeting the
one before it.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@devlog/_plan/260803_bug_backlog_stack/070_outcome.md` around lines 5 - 6,
Update the stack description in 070_outcome.md to say “five-layer stack” instead
of “four-layer stack,” matching the five listed PR layers (`#951` through `#955`).

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.

1 participant