Skip to content

fix(db): index request_cost_ledger for quota and session-tag reads - #19081

Open
HouMinXi wants to merge 2 commits into
cheaper-inference:release/v3.8.54from
HouMinXi:fix/request-cost-ledger-read-indexes
Open

HouMinXi wants to merge 2 commits into
cheaper-inference:release/v3.8.54from
HouMinXi:fix/request-cost-ledger-read-indexes

Conversation

@HouMinXi

@HouMinXi HouMinXi commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A key with a monthly USD cap makes every request run aggregateLedgerThisMonth (via checkKeyQuota) synchronously before it is routed. The query filters request_cost_ledger on (api_key_id, timestamp) and also reads success and amount_usd. The only index for it, idx_rcl_api_key_timestamp(api_key_id, timestamp) from migration 182, does not hold those columns, so SQLite reads every month-to-date row of that key from the table. sumSearchLedgerSpendSince (daily/weekly limits) has the same shape and also reads service_tier.

getCostBySessionTag (GET /api/usage/by-run) joins call_logs.correlation_id to request_cost_ledger.request_id. There is no index on request_id, so the plan walks the whole ledger (SCAN r USING INDEX idx_rcl_timestamp).

Changes

Migration 226_request_cost_ledger_read_indexes.sql, in this order:

  1. drops idx_rcl_api_key_timestamp. 182 is the only place that creates it, so it does not come back on startup;
  2. adds idx_rcl_api_key_ts_cover ON request_cost_ledger(api_key_id, timestamp, success, service_tier, amount_usd). It starts with the old index's two columns, so listLedgerEntries and other lookups that used the old index still get an index;
  3. adds idx_rcl_request_id ON request_cost_ledger(request_id).

The drop comes first so the new indexes reuse the old index's pages. The runner applies the file in one transaction, so no reader sees the table without an index. Every statement uses IF EXISTS / IF NOT EXISTS.

No application code changes. README.md, AGENTS.md, llm.txt and their 66 docs/i18n/<locale>/ mirrors now say 223 migrations instead of 222.

Plans (EXPLAIN QUERY PLAN, database built by the real runner)

read before after
aggregateLedger* SEARCH ... USING INDEX idx_rcl_api_key_timestamp (api_key_id=? AND timestamp>?) SEARCH ... USING COVERING INDEX idx_rcl_api_key_ts_cover (api_key_id=? AND timestamp>?)
sumSearchLedgerSpendSince same as above, table lookups USING COVERING INDEX idx_rcl_api_key_ts_cover
listLedgerEntries USING INDEX idx_rcl_api_key_timestamp USING INDEX idx_rcl_api_key_ts_cover
getCostBySessionTag SCAN r USING INDEX idx_rcl_timestamp SEARCH c USING INDEX idx_cl_session_tag, then SEARCH r USING INDEX idx_rcl_request_id (request_id=?)

Cost

Measured with node:sqlite and the sqlite3 CLI 3.46.1:

  • 500k-row ledger with 36-character UUID key and request ids, as the app writes them (138 MB file): the file grows by 29.1 MB and nothing is left on the freelist. With the earlier order (covering index, then the drop, then idx_rcl_request_id) it grew by 44.9 MB and left 15.7 MB on the freelist.
  • 1.4 GB database (500k ledger rows, 500k call_logs rows): the file grows by 33.3 MB.
  • With short ids (91 MB file) the growth is 18.6 MB, or 30.0 MB with that earlier order.
  • Dropping the old index last is worse. On a 100k-row UUID ledger (25.6 MB file) the growth is 6.4 MB with this order, 8.9 MB with the earlier one and 13.4 MB with the drop last, which leaves the whole old index (7.1 MB) on the freelist.
  • While the migration commits, the WAL briefly grows to 42–73 MB on these databases.

The upgrade also takes the runner's pre-migration VACUUM INTO backup, which scales with the database size (about 1.36 GB for the 1.4 GB database). The index build holds the write lock for its whole transaction (about 7 s on the 1.4 GB database on a loaded machine).

Each ledger insert now updates one more index with a wider key. One row is written per completed request.

Speed

SQL-layer timings, before and after, on a 1.08 GB test database with a 500k-row ledger (median of interleaved runs on a shared machine):

query rows in range before after
monthly SUM, large key 256,654 248.0 ms 17.0 ms
monthly SUM, small key 6,665 4.04 ms 0.31 ms
search spend, 1 week 59,168 59.1 ms 2.78 ms
by-run, real tag (10 rows) — 2744.7 ms 0.027 ms

On a smaller database that fits in the page cache the gains are smaller (about 1.8× to 4.5× for the SUMs). checkKeyQuota and the by-run route were not timed end to end.

Tests

  • tests/unit/request-cost-ledger-index-plans.test.ts (3 tests) runs the application code and checks the EXPLAIN QUERY PLAN of the exact SQL and parameters it executes: the monthly cap check in enforceApiKeyPolicy (one ledger SUM, covering-index seek, still 429 at the cap), sumSearchLedgerSpendSince (right sum, covering-index seek) and getCostBySessionTag (right rows, request_id probe, no SCAN r).
  • tests/unit/db/migration-226-request-cost-ledger-read-indexes.test.ts (3 tests). Each one also checks both new indexes column by column (PRAGMA index_list and index_xinfo: key columns in order, sort order, collation, unique and partial flags):
    • fresh database through the runner: exactly the cover, request_id and timestamp indexes; a second runner pass applies nothing;
    • the 226 SQL executed twice more on a database that already has it: no error, same indexes;
    • upgrade of a database with 2,000 ledger rows (duplicate request_ids included): old index gone, counts and sums unchanged, integrity_check ok, freelist empty.
  • Without the migration file all 6 fail; with it all 6 pass.
  • Mutation run (before this rebase; the SQL statements have not changed since): 37 mutants on the migration, the ledger SQL and the file number; 35 are caught. The two survivors build the same indexes: one creates idx_rcl_request_id before the drop, the other repeats the IF EXISTS / IF NOT EXISTS statements.
  • 117 related test files (ledger, key quota, usage limits, by-run, analytics, migrations), run on this branch and on c84f0551a6: 29 files fail on both because they cannot load better-sqlite3, which is not installed here. Each side also has one other failing test, and it is a different test on each side. On this branch it was R3b in api-key-allow-auto-combos.test.ts, which fails intermittently when run alone (1 of 7 in a later check; earlier runs saw 3 of 3), with or without the migration file. On the base it was a cache hit records no cost in search-provider-reported-cost.test.ts, which passed 3 of 3 times alone on this branch. readme-migration-count-14574.test.ts passes.
  • check:migration-numbering (223 files, no new gap; 026, 055 and 121 are allowlisted), check:db-rules, check:docs-sync, check:docs-counts, check:docs-frontmatter, prettier (on the files it has a parser for; it skips .sql and .txt), eslint, typecheck:core, check:changelog-integrity, check:ai-attribution, check:test-masking, check:test-runner-api, check:file-size, check:tracked-artifacts and check:boundary:ratchet against c84f0551a6 (753 edges, same as the base) pass. check:cycles reports 14 cycles; this PR adds no TypeScript under src/.

Not tested: better-sqlite3 (everything ran on node:sqlite), Postgres or other backends.

Notes

  • Migration number: 226 is the next free number on release/v3.8.53 (c84f0551a6, last file 225_token_ledger_balance_indexes.sql); a gap would fail check:migration-numbering. As of 2026-11-04, open PRs feat(usage): retain cache-write tiers in diagnostics #17307, fix(codex): fence stale credential, quota and catalog writes #18347 and Publish closed usage days into their own summary #18488 also add a 226_ file, and 223–232 are claimed by other open PRs as well. If two 226_ files end up on disk, startup throws Migration version collision detected. If another 226 is applied first, the runner skips this one with a CRITICAL log and the indexes are never built. Whichever PR merges later renumbers. I will check again before this merges and move the file and the test constant with it.
  • Migration counts: check:docs-counts checks README.md, AGENTS.md, llm.txt and the 66 docs/i18n/<locale>/README.md mirrors; check:docs-sync checks the 66 llm.txt mirrors. This PR sets all of them to 223. If another migration PR merges first, I will renumber and update the same files in that rebase.

⚠️ base-red inherited: #18791

checkKeyQuota runs aggregateLedgerThisMonth on every request that has
a key with a cost cap. It filters request_cost_ledger on api_key_id and
timestamp and reads success and amount_usd, so with the (api_key_id,
timestamp) index from migration 182 SQLite still fetched every matching
row from the table. sumSearchLedgerSpendSince has the same shape and
also filters on service_tier. getCostBySessionTag joins the ledger on
request_id, which had no index, so it walked the whole ledger.

Migration 226 replaces idx_rcl_api_key_timestamp with a covering index
on (api_key_id, timestamp, success, service_tier, amount_usd) and adds
idx_rcl_request_id. The covering index has the old one as its prefix,
so lookups that used it keep an index. The old index is dropped first
so the new ones reuse its pages; the runner applies the file in one
transaction.

README.md, AGENTS.md, llm.txt and their 66 docs/i18n mirrors now say
223 migrations, which is what check:docs-counts expects with this file
added.
@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Explain Change →

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

No actionable comments were generated in the recent review.

Summary

Summary by CodeRabbit

  • Performance
    • API-key quota checks, search-spend calculations, and session-tag cost lookups can complete more efficiently as the request-cost ledger grows.
  • Database
    • The update adds indexes to support these lookups. The database may use more storage, and the migration’s backup step can take longer on larger databases.

Migration 226 replaces one request-cost-ledger index and adds two indexes. Tests check the migration and the query plans for quota, search-spend, and session-tag cost reads. Project references update the documented SQLite migration count to 223.

Changes: Request cost ledger read indexes

Layer / File(s) Summary
Define ledger indexes
src/lib/db/migrations/226_request_cost_ledger_read_indexes.sql, changelog.d/fixes/19081-request-cost-ledger-read-indexes.md, AGENTS.md, README.md, llm.txt
Migration 226 drops idx_rcl_api_key_timestamp, creates a covering index on (api_key_id, timestamp, success, service_tier, amount_usd), and adds an index on request_id. The changelog describes the indexed reads and migration characteristics. Project references update the migration count from 222 to 223.
Validate migration upgrades
tests/unit/db/migration-226-request-cost-ledger-read-indexes.test.ts
Tests check the index definitions, repeated migration application, migration-runner behavior, aggregate results, and SQLite integrity after upgrading existing ledger data.
Check ledger read plans
tests/unit/request-cost-ledger-index-plans.test.ts
Tests inspect SQLite query plans for quota, search-spend, and session-tag cost reads. They also check quota responses, search-spend totals, and returned request IDs.

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

Change: Bug fix

Possibly related PRs

Merge Risk: Minimal · up to 65c91

No actionable issue remains from this review; the change is mergeable after normal checks.

Security architecture risk: Low · up to 65c91

The indexes preserve existing ledger data, quota predicates and management-access checks. Remaining uncertainty concerns upgrade resource requirements and concurrent startup against a shared database, rather than a demonstrated new security weakness.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The direct change affects the request-cost ledger in each upgraded SQLite database, including records for all API keys stored there. Its operational exposure is database-wide index construction and ongoing index storage, not additional caller authority. The changelog reports approximately 29 MB of growth for its 500,000-row example and backup time proportional to database size; these figures were not independently measured.

Trust Boundaries and Controls

  • observed — The existing usage handler invokes requireManagementAuth before reading run_id or accessing ledger results. The supplied run identifier is trimmed, bounded to 256 characters and passed as a bound SQL value. The migration changes neither that control sequence nor the lookup's caller reachability.

Resilience and Maintainability Implications

  • inferred — The planning transaction ends before per-file migration execution, whose marker insertion is not conflict-tolerant. Competing migration callers could therefore encounter locking or duplicate-marker failures while transaction rollback protects the index changes. This behavior predates the PR; deployment-level migration serialization remains unknown and is not treated as an introduced security finding.

Hardening Proposals

  • proposed — For deployments sharing a SQLite file, use a single migration owner during upgrade and reserve disk and maintenance time for the backup and index construction. This is an operational precaution, not evidence of a verified vulnerability.
Pre-merge checks: Passed 6 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Description check Warning The description follows the repository template closely. It has a Summary, a Changes section, measured Plans, Cost and Speed tables, a Tests section that lists both added test files and their coverage… 1. Add a Related Issues section. List the closed or related issue numbers, or state that none exist. 2. Add the Target Branch section. Confirm that the base is the active release/v3.8.x branch. Note that the author uses release/v3.8.53, whi…
Passed Passed checks: 6 passed

Check name Status Explanation
Title check Passed The title 'fix(db): index request_cost_ledger for quota and session-tag reads' follows Conventional Commits with type 'fix' and scope 'db'. It matches the main change: migration 226 adds covering and …
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
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.
Tests For Production Code Passed The PR changes production code under src/ by adding src/lib/db/migrations/226_request_cost_ledger_read_indexes.sql. It also adds two targeted test files: `tests/unit/db/migration-226-request-cost-…
No Ai Attribution Passed No AI attribution found. Both reviewed commits have empty trailer fields and human author/committer metadata. Their subjects and bodies contain no Co-Authored-By or AI-generation footer. The PR body…
Full details: Title check

Explanation

The title 'fix(db): index request_cost_ledger for quota and session-tag reads' follows Conventional Commits with type 'fix' and scope 'db'. It matches the main change: migration 226 adds covering and request_id indexes on request_cost_ledger for quota and session-tag reads.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 2 files. (5 skipped: 5 unsupported.)

Full details: Tests For Production Code

Explanation

The PR changes production code under src/ by adding src/lib/db/migrations/226_request_cost_ledger_read_indexes.sql. It also adds two targeted test files: tests/unit/db/migration-226-request-cost-ledger-read-indexes.test.ts validates the migration and index definitions, and tests/unit/request-cost-ledger-index-plans.test.ts checks the affected query plans.

Full details: No Ai Attribution

Explanation

No AI attribution found. Both reviewed commits have empty trailer fields and human author/committer metadata. Their subjects and bodies contain no Co-Authored-By or AI-generation footer. The PR body also contains no AI/bot co-author trailer or Generated with &lt;AI tool&gt; footer. The AI matches in changed documentation refer to the product domain, not attribution.

Full details: Description check

Explanation

The description follows the repository template closely. It has a Summary, a Changes section, measured Plans, Cost and Speed tables, a Tests section that lists both added test files and their coverage, and Notes on the migration number collision risk. The Related Issues section is missing. The Target Branch checklist is also missing, and the author does not say whether the base is the active release/v3.8.x branch. The author does state the base as release/v3.8.53 (c84f055), which is not the template's stated active base. The Validation checklist items are not ticked, and the description does not name the change type. The Reviewer Notes content appears under Cost and Notes rather than under a Reviewer Notes heading. The migration number may collide with other open PRs, which the author flags.

Resolution

  1. Add a Related Issues section. List the closed or related issue numbers, or state that none exist. 2. Add the Target Branch section. Confirm that the base is the active release/v3.8.x branch. Note that the author uses release/v3.8.53, which the template does not list as the active base. Explain the choice or rebase onto the active base. 3. Tick or annotate the Validation checklist. Name the change type (DB). State that npm run lint passed, and state whether the change was reconciled with the current active release base. 4. Confirm that the Tests Added Or Updated section lists every changed test file. The current list covers the two new test files. 5. Move the migration-collision and rebase risks, and the manual validation notes, under a Reviewer Notes heading. 6. Use the template headings exactly: Summary, Related Issues, Target Branch, Validation, Tests Added Or Updated, Coverage Notes, Reviewer Notes.
Finishing Touches

Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info

Run configuration

Commits

Reviewing files that changed from the base of the PR and between c84f055 and 65c91e0.

Files ignored due to path filters: 132

  • docs/i18n/am/README.md is excluded by !docs/i18n/**
  • docs/i18n/am/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ar/README.md is excluded by !docs/i18n/**
  • docs/i18n/ar/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/az/README.md is excluded by !docs/i18n/**
  • docs/i18n/az/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/bg/README.md is excluded by !docs/i18n/**
  • docs/i18n/bg/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/bn/README.md is excluded by !docs/i18n/**
  • docs/i18n/bn/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/bs/README.md is excluded by !docs/i18n/**
  • docs/i18n/bs/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/cs/README.md is excluded by !docs/i18n/**
  • docs/i18n/cs/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/da/README.md is excluded by !docs/i18n/**
  • docs/i18n/da/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/de/README.md is excluded by !docs/i18n/**
  • docs/i18n/de/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/el/README.md is excluded by !docs/i18n/**
  • docs/i18n/el/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/es/README.md is excluded by !docs/i18n/**
  • docs/i18n/es/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/et/README.md is excluded by !docs/i18n/**
  • docs/i18n/et/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/fa/README.md is excluded by !docs/i18n/**
  • docs/i18n/fa/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/fi/README.md is excluded by !docs/i18n/**
  • docs/i18n/fi/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/fr/README.md is excluded by !docs/i18n/**
  • docs/i18n/fr/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ga/README.md is excluded by !docs/i18n/**
  • docs/i18n/ga/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/gu/README.md is excluded by !docs/i18n/**
  • docs/i18n/gu/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ha/README.md is excluded by !docs/i18n/**
  • docs/i18n/ha/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/he/README.md is excluded by !docs/i18n/**
  • docs/i18n/he/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/hi/README.md is excluded by !docs/i18n/**
  • docs/i18n/hi/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/hr/README.md is excluded by !docs/i18n/**
  • docs/i18n/hr/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/hu/README.md is excluded by !docs/i18n/**
  • docs/i18n/hu/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/hy/README.md is excluded by !docs/i18n/**
  • docs/i18n/hy/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/id/README.md is excluded by !docs/i18n/**
  • docs/i18n/id/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ig/README.md is excluded by !docs/i18n/**
  • docs/i18n/ig/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/it/README.md is excluded by !docs/i18n/**
  • docs/i18n/it/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ja/README.md is excluded by !docs/i18n/**
  • docs/i18n/ja/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ka/README.md is excluded by !docs/i18n/**
  • docs/i18n/ka/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/km/README.md is excluded by !docs/i18n/**
  • docs/i18n/km/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/kn/README.md is excluded by !docs/i18n/**
  • docs/i18n/kn/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ko/README.md is excluded by !docs/i18n/**
  • docs/i18n/ko/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/lt/README.md is excluded by !docs/i18n/**
  • docs/i18n/lt/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/lv/README.md is excluded by !docs/i18n/**
  • docs/i18n/lv/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ml/README.md is excluded by !docs/i18n/**
  • docs/i18n/ml/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/mr/README.md is excluded by !docs/i18n/**
  • docs/i18n/mr/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ms/README.md is excluded by !docs/i18n/**
  • docs/i18n/ms/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/mt/README.md is excluded by !docs/i18n/**
  • docs/i18n/mt/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/my/README.md is excluded by !docs/i18n/**
  • docs/i18n/my/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ne/README.md is excluded by !docs/i18n/**
  • docs/i18n/ne/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/nl/README.md is excluded by !docs/i18n/**
  • docs/i18n/nl/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/no/README.md is excluded by !docs/i18n/**
  • docs/i18n/no/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/or/README.md is excluded by !docs/i18n/**
  • docs/i18n/or/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/pa/README.md is excluded by !docs/i18n/**
  • docs/i18n/pa/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/phi/README.md is excluded by !docs/i18n/**
  • docs/i18n/phi/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/pl/README.md is excluded by !docs/i18n/**
  • docs/i18n/pl/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/pt-BR/README.md is excluded by !docs/i18n/**
  • docs/i18n/pt-BR/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/pt/README.md is excluded by !docs/i18n/**
  • docs/i18n/pt/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ro/README.md is excluded by !docs/i18n/**
  • docs/i18n/ro/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ru/README.md is excluded by !docs/i18n/**
  • docs/i18n/ru/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/si/README.md is excluded by !docs/i18n/**
  • docs/i18n/si/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/sk/README.md is excluded by !docs/i18n/**
  • docs/i18n/sk/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/sl/README.md is excluded by !docs/i18n/**
  • docs/i18n/sl/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/sr/README.md is excluded by !docs/i18n/**
  • docs/i18n/sr/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/sv/README.md is excluded by !docs/i18n/**
  • docs/i18n/sv/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/sw/README.md is excluded by !docs/i18n/**
  • docs/i18n/sw/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ta/README.md is excluded by !docs/i18n/**
  • docs/i18n/ta/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/te/README.md is excluded by !docs/i18n/**
  • docs/i18n/te/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/th/README.md is excluded by !docs/i18n/**
  • docs/i18n/th/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/tr/README.md is excluded by !docs/i18n/**
  • docs/i18n/tr/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/uk-UA/README.md is excluded by !docs/i18n/**
  • docs/i18n/uk-UA/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/ur/README.md is excluded by !docs/i18n/**
  • docs/i18n/ur/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/uz/README.md is excluded by !docs/i18n/**
  • docs/i18n/uz/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/vi/README.md is excluded by !docs/i18n/**
  • docs/i18n/vi/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/yo/README.md is excluded by !docs/i18n/**
  • docs/i18n/yo/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/zh-CN/README.md is excluded by !docs/i18n/**
  • docs/i18n/zh-CN/llm.txt is excluded by !docs/i18n/**
  • docs/i18n/zh-TW/README.md is excluded by !docs/i18n/**
  • docs/i18n/zh-TW/llm.txt is excluded by !docs/i18n/**
Files selected for processing: 7

  • AGENTS.md
  • README.md
  • changelog.d/fixes/19081-request-cost-ledger-read-indexes.md
  • llm.txt
  • src/lib/db/migrations/226_request_cost_ledger_read_indexes.sql
  • tests/unit/db/migration-226-request-cost-ledger-read-indexes.test.ts
  • tests/unit/request-cost-ledger-index-plans.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

@diegosouzapw diegosouzapw added the deferred-v3.8.54 Feat PRs held for v3.8.54. Keep open. Do not merge into v3.8.53. label Nov 5, 2026
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.53 to release/v3.8.54 November 5, 2026 22:34
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Re-homed to release/v3.8.54: v3.8.53 entered its release freeze, so the branch now belongs to the release captain and development continues on the next cycle. Nothing is wrong with this PR — it just needed a live base. No action needed from you; CI will re-run against the new base.

This branch has not been deployed

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

Labels

deferred-v3.8.54 Feat PRs held for v3.8.54. Keep open. Do not merge into v3.8.53.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants