Skip to content

test: repair structural identity oracle normal form - #2153

Merged
KyleAMathews merged 9 commits into
mainfrom
codex/fix-ivm-normal-form
Oct 16, 2026
Merged

KyleAMathews merged 9 commits into
mainfrom
codex/fix-ivm-normal-form

Conversation

@KyleAMathews

@KyleAMathews KyleAMathews commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Why this change

The structural identity oracle rejected two specs that build the same nested array. An explicit array around deep(5, value) equals deep(6, value) after construction. The old model kept the deep tag in its normal form. It therefore disagreed with D2 equality and produced a false failure.

This PR expands deep into repeated array normal forms. It changes the oracle, its replay registration, and its coverage record. It does not change production code.

What the oracle checks

The equal-pair generator uses both spellings of the same array. An adjacent-depth case checks that one missing array level remains unequal.

Collision cases compare symbols with the same description and Map, Set, and object values with similar contents. New cases vary later Map and Set entries and an enumerable array field. The tests check both equalHashValues and structuralIdentity when each call returns.
Fixed cases also vary array subclasses, object prototypes, key order, and hidden symbols.

Both generated properties run fixed and seedless campaigns of 2,000 cases. The replay manifest accepts a seed and shrink path for either property.

Scope

The Set generator wraps its second member so JavaScript keeps both entries. It does not test native Set deduplication.

The RegExp generator uses numeric lastIndex values. Issue #2192 tracks a pre-existing collision for reference-valued lastIndex and its groupBy effect. That defect remains open. The incrementalization oracle owns the separate groupBy path.

Verification

  • Untouched main failed at seed 1158727847, path 255.
  • The focused oracle passes 20 tests. The reduced direct replay passes one case.
  • The old deep model fails after three fixed-seed cases. Removing the equivalent-spelling pair lets that wrong model pass both campaigns.
  • Four representation mutants and two collection-entry mutants fail the intended identity comparisons.
  • The @tanstack/db-ivm typecheck, ESLint, Prettier, and git diff --check pass.

Summary by CodeRabbit

  • Tests
    • Expanded structural-identity coverage for equivalent explicit-array and deep representations, enumerable array fields, symbols, and Maps, Sets, and objects.
    • Added pinned equal and unequal cases, plus seeded test campaigns and replay support for selected properties and cases.
  • Documentation
    • Added oracle review notes covering test scope, replay results, known exclusions, and a remaining issue with frozen RegExps that have object-valued lastIndex.

@changeset-bot

changeset-bot Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 0688c1b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 28a51257-61a2-423a-856a-ca91c3790eca
📥 Commits

Reviewing files that changed from the base of the PR and between abd0405 and 0688c1b.

📒 Files selected for processing: 4
  • docs/contributing/oracle-coverage.md
  • docs/contributing/oracle-reviews/2026-10-14-ivm-structural-identity-normal-form.md
  • packages/db-ivm/tests/structural-identity-oracle.property.test.ts
  • packages/db/tests/oracle-config.ts
🚧 Files skipped from review as they are similar to previous changes: 2
  • docs/contributing/oracle-coverage.md
  • docs/contributing/oracle-reviews/2026-10-14-ivm-structural-identity-normal-form.md

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

📝 Walkthrough

The structural-identity oracle model and property tests now cover additional representations and collision cases. Both property campaigns support configured replay. The oracle registry, replay manifest, and review documentation include the expanded coverage.

Changes: Structural Identity Oracle

Layer / File(s) Summary
Identity model and collision coverage
packages/db-ivm/tests/structural-identity-oracle.property.test.ts, docs/contributing/oracle-coverage.md, docs/contributing/oracle-reviews/*
The test model expands deep nodes into repeated arrays and distinguishes symbols by leaf index. Generated and pinned cases cover enumerable array fields, multi-entry Maps and Sets, representation equivalence, and collisions. The documentation records the review scope, campaign evidence, and excluded inputs.
Replay-aware property campaigns
packages/db-ivm/tests/structural-identity-oracle.property.test.ts, packages/db/tests/oracle-config.ts, packages/db/tests/oracle-replay-manifest.ts
Both properties read replay configuration and run a fixed-seed campaign when no seed is supplied. The registry and manifest map the structural-identity properties to the test file and replay test names.

Priority: ⬇️ Low

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

Change: Other

Sequence Diagram(s)

sequenceDiagram
  participant OracleRunner
  participant OracleReplayManifest
  participant readOracleRunConfig
  participant StructuralIdentityPropertyTests
  OracleRunner->>OracleReplayManifest: Resolve structural-identity property test name
  OracleRunner->>readOracleRunConfig: Read replay configuration
  readOracleRunConfig-->>StructuralIdentityPropertyTests: Provide configured replay selection
  OracleRunner->>StructuralIdentityPropertyTests: Run selected property campaign
Loading
Merge Risk: ⚪ Minimal · up to 0688c

The oracle coverage and replay changes are ready to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
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.
Title check Passed The title is concise, specific, and accurately describes the main change: repairing the structural identity oracle normal form.
Description check Passed The description clearly explains the motivation, oracle changes, scope, verification, and lack of production-code changes. It does not use the template headings or include the checklist and release-im…
Full details: Description check

Explanation

The description clearly explains the motivation, oracle changes, scope, verification, and lack of production-code changes. It does not use the template headings or include the checklist and release-impact checkboxes, but it provides the required change and verification details.

Full details: Docstring Coverage

Explanation

Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 217 kB

ℹ️ View Unchanged
Filename Size
packages/db/dist/esm/client.js 4.22 kB
packages/db/dist/esm/collection-options-brand.js 219 B
packages/db/dist/esm/collection-options.js 258 B
packages/db/dist/esm/collection/change-events.js 1.76 kB
packages/db/dist/esm/collection/changes.js 2.96 kB
packages/db/dist/esm/collection/cleanup-queue.js 901 B
packages/db/dist/esm/collection/config-errors.js 547 B
packages/db/dist/esm/collection/events.js 481 B
packages/db/dist/esm/collection/index.js 5.27 kB
packages/db/dist/esm/collection/indexes.js 2.3 kB
packages/db/dist/esm/collection/lifecycle.js 2.94 kB
packages/db/dist/esm/collection/mutations.js 2.99 kB
packages/db/dist/esm/collection/state.js 7.16 kB
packages/db/dist/esm/collection/subscription.js 8.9 kB
packages/db/dist/esm/collection/sync.js 5.4 kB
packages/db/dist/esm/collection/validate-config.js 1.17 kB
packages/db/dist/esm/deferred.js 207 B
packages/db/dist/esm/error-message.js 642 B
packages/db/dist/esm/errors.js 6.53 kB
packages/db/dist/esm/event-emitter.js 1.06 kB
packages/db/dist/esm/index.js 4.52 kB
packages/db/dist/esm/indexed-db-wrapper.js 1.91 kB
packages/db/dist/esm/indexed-db.js 3.7 kB
packages/db/dist/esm/indexes/auto-index.js 926 B
packages/db/dist/esm/indexes/base-index.js 1.92 kB
packages/db/dist/esm/indexes/basic-index.js 1.93 kB
packages/db/dist/esm/indexes/btree-index.js 1.62 kB
packages/db/dist/esm/indexes/index-registry.js 916 B
packages/db/dist/esm/indexes/reverse-index.js 1.01 kB
packages/db/dist/esm/live-query-adapter.js 338 B
packages/db/dist/esm/live-query-observer.js 4.8 kB
packages/db/dist/esm/live-query-options.js 1.41 kB
packages/db/dist/esm/live-query-window-controller.js 4.27 kB
packages/db/dist/esm/local-only.js 1.08 kB
packages/db/dist/esm/local-storage.js 3.93 kB
packages/db/dist/esm/optimistic-action.js 359 B
packages/db/dist/esm/paced-mutations.js 1.11 kB
packages/db/dist/esm/persisted-readiness.js 195 B
packages/db/dist/esm/proxy.js 3.51 kB
packages/db/dist/esm/query/builder/clone-query.js 849 B
packages/db/dist/esm/query/builder/functions.js 1.56 kB
packages/db/dist/esm/query/builder/index.js 7.48 kB
packages/db/dist/esm/query/builder/query-ir.js 312 B
packages/db/dist/esm/query/builder/ref-proxy-identity.js 292 B
packages/db/dist/esm/query/builder/ref-proxy.js 1.67 kB
packages/db/dist/esm/query/builder/wrapper-identity.js 221 B
packages/db/dist/esm/query/compiler/evaluators.js 2.51 kB
packages/db/dist/esm/query/compiler/expressions.js 603 B
packages/db/dist/esm/query/compiler/group-by.js 4.48 kB
packages/db/dist/esm/query/compiler/index.js 10.3 kB
packages/db/dist/esm/query/compiler/joins.js 3.42 kB
packages/db/dist/esm/query/compiler/lazy-targets.js 1.11 kB
packages/db/dist/esm/query/compiler/order-by.js 2.26 kB
packages/db/dist/esm/query/compiler/parent-routes.js 319 B
packages/db/dist/esm/query/compiler/query-equivalence.js 568 B
packages/db/dist/esm/query/compiler/route-metadata.js 1.24 kB
packages/db/dist/esm/query/compiler/select.js 1.5 kB
packages/db/dist/esm/query/effect.js 5.36 kB
packages/db/dist/esm/query/equality-conjunct.js 486 B
packages/db/dist/esm/query/equality-value-identity.js 735 B
packages/db/dist/esm/query/expression-helpers.js 1.61 kB
packages/db/dist/esm/query/ir-stable-identity.js 4.2 kB
packages/db/dist/esm/query/ir.js 2.2 kB
packages/db/dist/esm/query/join-conditions.js 257 B
packages/db/dist/esm/query/live-query-collection.js 391 B
packages/db/dist/esm/query/live/bucket-facade-adapter.js 3.17 kB
packages/db/dist/esm/query/live/collection-config-builder.js 6.84 kB
packages/db/dist/esm/query/live/collection-registry.js 264 B
packages/db/dist/esm/query/live/collection-subscriber.js 2.28 kB
packages/db/dist/esm/query/live/graph-scheduler.js 305 B
packages/db/dist/esm/query/live/internal.js 145 B
packages/db/dist/esm/query/live/materialized-pipeline.js 2.39 kB
packages/db/dist/esm/query/live/ordered-source-loader.js 5.35 kB
packages/db/dist/esm/query/live/subset-demand-controller.js 1.73 kB
packages/db/dist/esm/query/live/utils.js 1.35 kB
packages/db/dist/esm/query/optimizer.js 2.95 kB
packages/db/dist/esm/query/pooled-live-query.js 4.13 kB
packages/db/dist/esm/query/query-once.js 359 B
packages/db/dist/esm/query/runtime-reference-identity.js 630 B
packages/db/dist/esm/query/subset-dedupe.js 493 B
packages/db/dist/esm/scheduler.js 1.23 kB
packages/db/dist/esm/SortedMap.js 1.6 kB
packages/db/dist/esm/strategies/commit-completion.js 156 B
packages/db/dist/esm/strategies/debounceStrategy.js 658 B
packages/db/dist/esm/strategies/queueStrategy.js 523 B
packages/db/dist/esm/strategies/serial-pacer.js 486 B
packages/db/dist/esm/strategies/throttleStrategy.js 738 B
packages/db/dist/esm/sync-persistence.js 626 B
packages/db/dist/esm/sync-receipt.js 211 B
packages/db/dist/esm/transaction-commit-work.js 351 B
packages/db/dist/esm/transactions.js 4.61 kB
packages/db/dist/esm/utils.js 1.67 kB
packages/db/dist/esm/utils/array-utils.js 270 B
packages/db/dist/esm/utils/browser-polyfills.js 304 B
packages/db/dist/esm/utils/btree.js 3.02 kB
packages/db/dist/esm/utils/callbacks.js 174 B
packages/db/dist/esm/utils/comparison.js 1.94 kB
packages/db/dist/esm/utils/cursor.js 753 B
packages/db/dist/esm/utils/error.js 262 B
packages/db/dist/esm/utils/get-or-create.js 155 B
packages/db/dist/esm/utils/index-optimization.js 2.43 kB
packages/db/dist/esm/utils/source-record.js 140 B
packages/db/dist/esm/utils/type-guards.js 230 B
packages/db/dist/esm/utils/uuid.js 530 B
packages/db/dist/esm/virtual-props.js 413 B
packages/react-db/dist/esm/DbProvider.js 317 B
packages/react-db/dist/esm/development.js 190 B
packages/react-db/dist/esm/HydrationBoundary.js 263 B
packages/react-db/dist/esm/index.js 330 B
packages/react-db/dist/esm/live-query-internals.js 282 B
packages/react-db/dist/esm/source-id-bindings.js 746 B
packages/react-db/dist/esm/useLiveInfiniteQuery.js 2.15 kB
packages/react-db/dist/esm/useLiveQuery.js 3.34 kB
packages/react-db/dist/esm/useLiveQueryEffect.js 504 B
packages/react-db/dist/esm/useLiveSuspenseQuery.js 1.33 kB
packages/react-db/dist/esm/usePacedMutations.js 429 B

compressed-size-action::db-and-react-package-size

@pkg-pr-new

pkg-pr-new Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@2153

@tanstack/browser-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/browser-db-sqlite-persistence@2153

@tanstack/capacitor-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/capacitor-db-sqlite-persistence@2153

@tanstack/cloudflare-durable-objects-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/cloudflare-durable-objects-db-sqlite-persistence@2153

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@2153

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@2153

@tanstack/db-sqlite-persistence-core

npm i https://pkg.pr.new/@tanstack/db-sqlite-persistence-core@2153

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@2153

@tanstack/electron-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/electron-db-sqlite-persistence@2153

@tanstack/expo-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/expo-db-sqlite-persistence@2153

@tanstack/node-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/node-db-sqlite-persistence@2153

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@2153

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@2153

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@2153

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@2153

@tanstack/react-native-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/react-native-db-sqlite-persistence@2153

@tanstack/react-router-with-db

npm i https://pkg.pr.new/@tanstack/react-router-with-db@2153

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@2153

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@2153

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@2153

@tanstack/tauri-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/tauri-db-sqlite-persistence@2153

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@2153

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@2153

commit: 0688c1b

@KyleAMathews
KyleAMathews marked this pull request as ready for review October 14, 2026 09:36
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Incremental update benchmark

Comparing 1356b2f9 (this PR) against 2c83fdc5 (base). Write times are per-write medians over 100 iterations (20 warmup writes). Cold hydrate is one timed first load of each query.

Overall median write time vs base: 1.00× · cold hydrate time: 0.99× (geometric mean of per-case ratios; lower is faster).

Writes: 4 regression(s), 2 improvement(s) (threshold: ±20% and >0.05ms).

Cold hydrate: 1 regression(s), 1 improvement(s) (threshold: ±50% and >5ms).

Per-case flags are noisy on shared runners. Read the geometric means first.

Writes

Query Δ median write time (geomean) Best case Worst case Flags
list: newest 50 open +3.2% -4.1% +36.6% 1 🔴
list + author -0.1% -8.0% +16.2% —
list + comment count -6.3% -24.7% +35.4% 1 🔴 1 🟢
list + 3 recent comments -2.6% -21.0% +75.0% 1 🔴 1 🟢
issue detail + comments +2.1% -9.1% +93.0% 1 🔴

Cold hydrate

Query Δ cold hydrate time (geomean) Best case Worst case Flags
list: newest 50 open -1.9% -41.0% +62.0% —
list + author +1.8% -35.0% +33.8% —
list + comment count -19.6% -81.1% +31.1% 1 🟢
list + 3 recent comments +4.1% -39.3% +233.9% 1 🔴
issue detail + comments +13.4% -10.2% +56.8% —

Each row aggregates the 14.4 scale/index/write-mode configurations of that query; per-configuration tables below.

100 rows/collection | source indexes: none | synced writes — geomean 0.95×, cold 1.00×, 2 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.218ms 0.217ms -0.6% 0.349ms 0.346ms -0.7% 13.014ms 13.380ms +2.8%
list: newest 50 open 0.438ms 0.526ms +20.2% 0.688ms 0.833ms +21.2% 🔴 3.140ms 2.987ms -4.9%
list + author 0.200ms 0.198ms -1.0% 0.329ms 0.333ms +1.3% 8.209ms 9.079ms +10.6%
list + comment count 0.423ms 0.343ms -18.8% 0.683ms 0.534ms -21.8% 12.583ms 12.029ms -4.4%
list + 3 recent comments 0.285ms 0.227ms -20.4% 0.497ms 0.396ms -20.3% 🟢 10.498ms 10.059ms -4.2%
issue detail + comments 0.159ms 0.154ms -2.8% 0.286ms 0.212ms -26.1% 1.388ms 1.442ms +3.9%
100 rows/collection | source indexes: none | optimistic writes — geomean 0.95×, cold 0.91×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.138ms 0.136ms -1.9% 0.226ms 0.205ms -9.6% 1.852ms 1.681ms -9.2%
list: newest 50 open 0.092ms 0.092ms -0.2% 0.166ms 0.176ms +6.6% 2.817ms 1.900ms -32.5%
list + author 0.175ms 0.168ms -4.5% 0.276ms 0.300ms +8.4% 5.076ms 3.300ms -35.0%
list + comment count 0.229ms 0.226ms -1.4% 0.383ms 0.381ms -0.4% 3.623ms 3.486ms -3.8%
list + 3 recent comments 0.167ms 0.132ms -21.0% 0.268ms 0.255ms -4.6% 6.905ms 7.656ms +10.9%
issue detail + comments 0.157ms 0.155ms -0.7% 0.240ms 0.214ms -10.6% 0.978ms 1.340ms +37.1%
100 rows/collection | source indexes: manual | synced writes — geomean 0.99×, cold 0.90×, 1 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.105ms 0.143ms +36.6% 0.152ms 0.238ms +57.1% 2.787ms 3.115ms +11.8%
list: newest 50 open 0.420ms 0.425ms +1.1% 0.647ms 0.725ms +12.1% 1.181ms 1.156ms -2.1%
list + author 0.134ms 0.137ms +1.9% 0.233ms 0.238ms +2.1% 3.044ms 2.523ms -17.1%
list + comment count 0.323ms 0.243ms -24.7% 0.459ms 0.437ms -4.7% 🟢 4.827ms 3.096ms -35.9%
list + 3 recent comments 0.171ms 0.161ms -5.5% 0.303ms 0.210ms -30.8% 4.273ms 4.307ms +0.8%
issue detail + comments 0.125ms 0.120ms -4.0% 0.240ms 0.164ms -31.9% 0.553ms 0.496ms -10.2%
100 rows/collection | source indexes: manual | optimistic writes — geomean 1.00×, cold 1.07×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.105ms 0.105ms -0.4% 0.155ms 0.154ms -0.4% 1.160ms 1.218ms +5.0%
list: newest 50 open 0.085ms 0.084ms -0.9% 0.148ms 0.173ms +16.2% 1.011ms 1.017ms +0.5%
list + author 0.135ms 0.149ms +10.5% 0.183ms 0.251ms +37.4% 2.334ms 2.682ms +14.9%
list + comment count 0.213ms 0.197ms -7.5% 0.329ms 0.327ms -0.8% 4.638ms 4.054ms -12.6%
list + 3 recent comments 0.126ms 0.127ms +0.7% 0.214ms 0.228ms +6.7% 4.772ms 4.658ms -2.4%
issue detail + comments 0.104ms 0.103ms -0.6% 0.148ms 0.168ms +13.4% 0.361ms 0.532ms +47.4%
1,000 rows/collection | source indexes: none | synced writes — geomean 1.26×, cold 1.05×, 2 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.083ms 0.084ms +0.6% 0.172ms 0.170ms -0.8% 9.764ms 7.438ms -23.8%
list: newest 50 open 1.088ms 1.127ms +3.6% 2.001ms 2.102ms +5.0% 6.009ms 5.751ms -4.3%
list + author 0.107ms 0.104ms -2.6% 0.196ms 0.136ms -30.5% 18.359ms 18.592ms +1.3%
list + comment count 0.189ms 0.218ms +15.4% 0.268ms 0.457ms +70.3% 9.517ms 9.300ms -2.3%
list + 3 recent comments 0.124ms 0.217ms +75.0% 0.179ms 0.328ms +83.4% 🔴 9.924ms 11.738ms +18.3%
issue detail + comments 0.099ms 0.191ms +93.0% 0.192ms 0.275ms +42.9% 🔴 1.120ms 1.756ms +56.8%
1,000 rows/collection | source indexes: none | optimistic writes — geomean 0.99×, cold 0.94×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.130ms 0.144ms +10.4% 0.211ms 0.210ms -0.8% 7.789ms 5.789ms -25.7%
list: newest 50 open 0.073ms 0.091ms +24.4% 0.162ms 0.124ms -23.3% 5.057ms 8.195ms +62.0%
list + author 0.135ms 0.124ms -8.0% 0.229ms 0.216ms -5.7% 19.466ms 24.349ms +25.1%
list + comment count 0.199ms 0.166ms -16.8% 0.279ms 0.208ms -25.5% 11.539ms 8.304ms -28.0%
list + 3 recent comments 0.113ms 0.107ms -5.4% 0.174ms 0.146ms -15.7% 15.239ms 9.258ms -39.3%
issue detail + comments 0.104ms 0.096ms -7.8% 0.131ms 0.127ms -2.7% 1.229ms 1.277ms +3.9%
1,000 rows/collection | source indexes: manual | synced writes — geomean 0.95×, cold 0.89×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.077ms 0.077ms +0.4% 0.107ms 0.099ms -7.2% 1.174ms 1.049ms -10.7%
list: newest 50 open 0.317ms 0.318ms +0.4% 0.545ms 0.569ms +4.5% 1.327ms 0.783ms -41.0%
list + author 0.114ms 0.113ms -1.0% 0.216ms 0.213ms -1.4% 1.738ms 1.763ms +1.5%
list + comment count 0.223ms 0.191ms -14.0% 0.296ms 0.233ms -21.4% 2.854ms 2.277ms -20.2%
list + 3 recent comments 0.146ms 0.135ms -7.9% 0.259ms 0.179ms -30.7% 5.670ms 5.363ms -5.4%
issue detail + comments 0.106ms 0.097ms -8.7% 0.136ms 0.125ms -8.3% 0.328ms 0.416ms +27.1%
1,000 rows/collection | source indexes: manual | optimistic writes — geomean 0.96×, cold 1.02×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.090ms 0.089ms -1.4% 0.157ms 0.159ms +1.9% 0.740ms 0.770ms +4.2%
list: newest 50 open 0.072ms 0.072ms +0.5% 0.100ms 0.124ms +24.2% 0.779ms 0.891ms +14.5%
list + author 0.120ms 0.115ms -4.0% 0.209ms 0.149ms -28.5% 2.035ms 1.881ms -7.5%
list + comment count 0.191ms 0.170ms -11.2% 0.226ms 0.211ms -6.5% 2.725ms 2.981ms +9.4%
list + 3 recent comments 0.120ms 0.114ms -5.1% 0.148ms 0.148ms +0.1% 3.593ms 3.399ms -5.4%
issue detail + comments 0.105ms 0.104ms -0.3% 0.143ms 0.184ms +28.7% 0.365ms 0.369ms +1.1%
10,000 rows/collection | source indexes: none | synced writes — geomean 1.06×, cold 1.09×, 1 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.075ms 0.073ms -2.3% 0.102ms 0.102ms +0.1% 69.168ms 67.171ms -2.9%
list: newest 50 open 10.105ms 10.814ms +7.0% 11.036ms 11.474ms +4.0% 65.236ms 72.547ms +11.2%
list + author 0.110ms 0.128ms +16.2% 0.197ms 0.211ms +6.9% 202.597ms 203.311ms +0.4%
list + comment count 0.205ms 0.278ms +35.4% 0.341ms 0.348ms +1.8% 🔴 77.207ms 101.199ms +31.1%
list + 3 recent comments 0.133ms 0.125ms -5.9% 0.233ms 0.193ms -17.2% 76.010ms 83.109ms +9.3%
issue detail + comments 0.100ms 0.091ms -9.1% 0.135ms 0.121ms -10.8% 4.873ms 5.316ms +9.1%
10,000 rows/collection | source indexes: none | optimistic writes — geomean 0.96×, cold 0.98×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.092ms 0.092ms -0.4% 0.158ms 0.161ms +1.5% 63.677ms 62.313ms -2.1%
list: newest 50 open 0.060ms 0.060ms +0.8% 0.093ms 0.097ms +4.0% 64.763ms 66.261ms +2.3%
list + author 0.119ms 0.118ms -1.2% 0.152ms 0.148ms -2.6% 193.809ms 188.287ms -2.8%
list + comment count 0.215ms 0.193ms -10.1% 0.259ms 0.311ms +19.9% 77.675ms 67.693ms -12.9%
list + 3 recent comments 0.113ms 0.106ms -6.5% 0.161ms 0.134ms -16.7% 70.559ms 71.151ms +0.8%
issue detail + comments 0.103ms 0.098ms -5.0% 0.138ms 0.128ms -7.4% 4.841ms 4.936ms +2.0%
10,000 rows/collection | source indexes: manual | synced writes — geomean 0.96×, cold 1.01×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.102ms 0.098ms -4.1% 0.154ms 0.175ms +13.5% 2.160ms 2.284ms +5.8%
list: newest 50 open 0.958ms 0.944ms -1.5% 1.409ms 1.213ms -13.9% 1.809ms 1.760ms -2.7%
list + author 0.105ms 0.100ms -4.8% 0.144ms 0.138ms -4.3% 2.664ms 3.564ms +33.8%
list + comment count 0.220ms 0.214ms -2.7% 0.392ms 0.260ms -33.8% 3.732ms 4.004ms +7.3%
list + 3 recent comments 0.154ms 0.140ms -9.3% 0.196ms 0.227ms +16.0% 7.533ms 4.946ms -34.3%
issue detail + comments 0.113ms 0.113ms +0.6% 0.164ms 0.186ms +13.6% 0.583ms 0.652ms +11.8%
10,000 rows/collection | source indexes: manual | optimistic writes — geomean 0.99×, cold 1.00×, 2 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.103ms 0.101ms -1.8% 0.195ms 0.183ms -6.1% 1.620ms 2.505ms +54.6%
list: newest 50 open 0.080ms 0.077ms -3.5% 0.136ms 0.114ms -16.3% 1.638ms 1.570ms -4.2%
list + author 0.121ms 0.120ms -0.4% 0.149ms 0.154ms +2.9% 2.749ms 3.220ms +17.1%
list + comment count 0.244ms 0.230ms -5.8% 0.286ms 0.275ms -3.9% 18.360ms 3.469ms -81.1% 🟢
list + 3 recent comments 0.130ms 0.137ms +5.9% 0.189ms 0.271ms +43.6% 4.529ms 15.123ms +233.9% 🔴
issue detail + comments 0.114ms 0.113ms -0.6% 0.147ms 0.142ms -3.2% 0.587ms 0.539ms -8.2%

Runner: node v24.8.0, linux 6.17.0-1022-azure, AMD EPYC 7763 64-Core Processor. Timings on shared CI runners are noisy; treat small deltas as indicative only.

@KyleAMathews
KyleAMathews merged commit 7d8f340 into main Oct 16, 2026
39 of 41 checks passed
@KyleAMathews
KyleAMathews deleted the codex/fix-ivm-normal-form branch October 16, 2026 15:39
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