Skip to content

test: add StoreStress harness and contention regression tests - #2766

Merged
steipete merged 1 commit into
mainfrom
review/store-stress
Aug 8, 2026
Merged

test: add StoreStress harness and contention regression tests#2766
steipete merged 1 commit into
mainfrom
review/store-stress

Conversation

@steipete

@steipete steipete commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Salvage outcome

Current main supersedes this PR's original production fix:

This branch was rebuilt on current main; both duplicate production patches were discarded. What remains is independent value:

  • a standalone, non-shipping Scripts/StoreStress package for crash, contention, corpus, WAL, and descriptor testing;
  • a real lock-holder regression crossing SQLite's five-second busy timeout and proving the existing database survives;
  • the observation behind that regression: codexbar cost and other CLI cost surfaces instantiate CostUsageFetcher, so app and CLI processes can each open a writable scanner/store connection.

No changelog entry is needed for test/review tooling.

Crash recovery

Each cycle used its own temp store. The writer was killed with SIGKILL; verification reopened SQLite directly, ran PRAGMA integrity_check, and (for normal writes) checked that committed aggregates exactly formed the expected triangular-number prefix.

Kill point Cycles Marker observed integrity_check=ok Committed-prefix invariant Failures
Mid-write 30 n/a 30/30 30/30 0
Retention + incremental vacuum/checkpoint window 12 12/12 12/12 n/a 0

Concurrency and WAL

One writer and four independent read-only WAL readers ran for 190 seconds. The writer completed 56,009 iterations, 280 retention passes, and 112 budget/vacuum passes with 0 write errors and 0 store rebuilds.

Reader Reads SQLite errors Torn/invariant failures p50 p95 p99 Max
1 9,093,910 0 0 0.015 ms 0.036 ms 0.112 ms 92.685 ms
2 9,072,815 0 0 0.015 ms 0.036 ms 0.112 ms 85.907 ms
3 9,093,841 0 0 0.015 ms 0.036 ms 0.112 ms 85.687 ms
4 9,082,661 0 0 0.015 ms 0.036 ms 0.113 ms 90.990 ms
Total 36,343,227 0 0
WAL/store metric Result
Peak WAL during sustained writes/readers 5,108,832 bytes
Final WAL after 112 budget/vacuum checkpoints 1,054,752 bytes
Final concurrency database 133,382,144 bytes
Open/close descriptor cycles 100
Descriptor count (baseline / peak / final) 4 / 4 / 4

Frozen real-corpus rebuild

~/.codex/sessions was APFS-cloned into a temp directory and made read-only before measurement. The source corpus and ~/Library/Caches/CodexBar were never written. The frozen corpus contained 1,948 JSONL files and 2,371,674,974 logical bytes. The optimized standalone harness wrote only to a separate temp store.

Pass Wall Processed bytes Total bytes Cumulative usage rows Catch-up pending
1 39.72 s 536,870,882 2,371,674,974 34,563 yes
2 17.85 s 1,073,741,794 2,371,674,974 65,857 yes
3 23.39 s 1,610,612,706 2,371,674,974 96,153 yes
4 30.61 s 2,147,483,618 2,371,674,974 141,820 yes
5 29.36 s 2,371,674,974 2,371,674,974 168,550 no

/usr/bin/time -l and immediate unchanged-corpus results:

Run Wall Max RSS Usage rows processed/repriced DB size WAL Catch-up
Cold rebuild 145.48 s 965,787,648 bytes 168,550 / 168,550 107,741,184 bytes checkpointed complete
Immediate unchanged pass 50.02 s 549,339,136 bytes 0 / 0 107,749,376 bytes 0 bytes complete

The second pass confirms zero append/rescan work at corpus scale. Its wall/RSS are not near zero because loading the persisted cache, rediscovering files, and building the report remain nontrivial fixed overhead; the table keeps that distinction explicit.

Verification

  • Root production build: swift build -c release
  • Standalone optimized harness: swift build --package-path Scripts/StoreStress -c release -Xswiftc -enable-testing
  • Focused lock-holder regression: passed in 6.62 s
  • make check: passed, 0 lint violations
  • make test: 822/822 selections passed in 69/69 groups; 0 retries, 0 timeouts
  • Structured autoreview: clean, no accepted/actionable findings

@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: 5729671d59

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +148 to +149
if Self.isTransientContention(error) {
return fallback

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 Abort the cache save after a skipped SQLite write

When a transient lock timeout happens during one component of saveCodexCache, this returns the fallback for that single write, but callers such as persistFile and saveCodexCache ignore the false results and continue with later writes like aggregates and metadata. If the lock clears before those later calls, the store can persist lastScan/window metadata and global aggregates for a scan whose per-file rows or snapshots were skipped, so the UI can read an internally inconsistent cache instead of retrying the whole refresh against the previous committed state.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 session-state 🚨 Merging this PR could lose, corrupt, stale, or mis-associate session or agent state. labels Aug 8, 2026
@clawsweeper

clawsweeper Bot commented Aug 8, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed August 8, 2026, 2:37 PM ET / 18:37 UTC.

ClawSweeper review

What this changes

Adds a separate StoreStress Swift package for SQLite cost-cache crash, contention, WAL, corpus, and descriptor exercises, plus a regression test that verifies a lock timeout preserves the existing database.

Merge readiness

⚠️ Ready for maintainer review - 3 items remain

The rebuilt branch now contains an independent non-shipping stress harness and a focused lock-contention regression test; the earlier production-policy findings do not apply to this head. It is owner-authored, so it remains open for normal maintainer review and CI completion.

Priority: P2
Reviewed head: b333cd1fc3a4e41644b05aabcc53342b15614bbb

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Strong reported runtime evidence and a narrowly scoped test/harness patch support normal merge review; no patch-introduced correctness defect was found.
Proof confidence 🦞 diamond lobster (5/6) Not applicable: This is an owner-authored PR, so the external-contributor proof gate does not apply; the PR body nevertheless records real lock-holder, crash, WAL, and corpus-run results.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: This is an owner-authored PR, so the external-contributor proof gate does not apply; the PR body nevertheless records real lock-holder, crash, WAL, and corpus-run results.
Evidence reviewed 6 items Current store policy: Current main preserves the database for SQLITE_BUSY and SQLITE_LOCKED rather than rebuilding it, matching the behavior exercised by the new regression.
Current save-path limitation: The main save path still ignores individual write return values while continuing with later metadata and aggregate writes; this is pre-existing current-main behavior, not introduced by this test-only PR.
PR scope and regression: The reviewed head adds five files/changes, including a lock-holder regression that establishes SQLITE_BUSY behavior and asserts the database persists with rebuildCount zero.
Findings None None.
Security None None.

How this fits together

CodexBar’s cost scanner persists Codex session-derived usage in a SQLite cache used by both the menu-bar app and CLI cost commands. The store writes scan results and readers consume snapshots, so lock handling must preserve cached history when another connection is writing.

flowchart LR
A[Codex session files] --> B[Cost scanner]
B --> C[SQLite cost cache]
D[CLI cost command] --> C
E[Menu bar app] --> C
C --> F[Usage reports]
G[StoreStress harness] --> C
H[Lock contention test] --> C
Loading

Before merge

  • Resolve merge risk (P1) - The new regression confirms an individual blocked write remains non-destructive, but it does not cover the existing save pipeline’s behavior after a later per-file write is skipped under contention.
  • Resolve merge risk (P1) - The standalone harness intentionally uses writable paths and process-kill scenarios; its README should continue to require disposable cache/store paths when run manually.
  • Complete next step (P2) - Normal owner PR review is the remaining action; there is no narrow patch defect for the repair lane.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Added test tooling 536 added, 0 removed across 5 files; production +0, tests +25 The runtime product path is unchanged; the added surface is a standalone verification harness plus one focused regression.
Reported live stress run 36,343,227 read operations with 0 SQLite or invariant errors The PR body includes substantial after-fix evidence for the harness’s intended concurrency checks.

Merge-risk options

Maintainer options:

  1. Land with the focused regression (recommended)
    Merge after required checks complete, while tracking any whole-save atomicity work separately because this branch does not alter production persistence.
  2. Expand the regression boundary
    Before merging, add a save-pipeline contention case that proves no later metadata or aggregate state is committed after a failed per-file write.

Technical review

Best possible solution:

Keep the production recovery policy from current main, land the focused regression and harness after CI, and separately decide whether the save pipeline should abort its remaining writes after a preserved lock failure.

Do we have a high-confidence way to reproduce the issue?

Yes: the new focused test holds an SQLite write lock beyond the configured busy timeout, then verifies that the blocked write returns false while the existing database survives. The supplied PR body also records a separate lock-holder exercise and sustained WAL-reader run.

Is this the best way to solve the issue?

Yes for the PR’s stated verification goal: a non-shipping harness plus a focused regression is a narrow way to preserve coverage without changing the established recovery policy. It does not resolve the separate current-main question of whether a multi-write cache save should stop after one preserved failure.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 985546901bb9.

Labels

Label justifications:

  • P2: The PR strengthens verification for a normal-priority cost-cache contention boundary without changing shipping behavior.
  • merge-risk: 🚨 session-state: The new tooling and regression concern persisted usage-cache consistency under SQLite contention, which CI alone cannot establish for every real cache state.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: This is an owner-authored PR, so the external-contributor proof gate does not apply; the PR body nevertheless records real lock-holder, crash, WAL, and corpus-run results.

Evidence

What I checked:

  • Current store policy: Current main preserves the database for SQLITE_BUSY and SQLITE_LOCKED rather than rebuilding it, matching the behavior exercised by the new regression. (Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore.swift:144, 985546901bb9)
  • Current save-path limitation: The main save path still ignores individual write return values while continuing with later metadata and aggregate writes; this is pre-existing current-main behavior, not introduced by this test-only PR. (Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift:25, 985546901bb9)
  • PR scope and regression: The reviewed head adds five files/changes, including a lock-holder regression that establishes SQLITE_BUSY behavior and asserts the database persists with rebuildCount zero. (Tests/CodexBarTests/CostUsageStoreTests.swift:1037, b333cd1fc3a4)
  • Feature provenance: The current error classification was introduced by the merged transient-failure fix and is present on main; the PR head is based on the later retention fix and adds tests/harness only. (Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore.swift:170, 5205dd1e003c)
  • Current release boundary: The latest release supplied for review is v0.48.1 at 226085b; the SQLite store work is newer current-main work, so this test tooling has not been established as shipped. (985546901bb9)
  • Read-only inspection constraint: The checkout is a partial clone missing the PR tree blobs needed for a normal local diff, and network resolution failed; the review used the supplied hydrated five-file diff/body plus locally available commit and current-main source.

Likely related people:

  • steipete: Current main history attributes the SQLite cutover, transient-failure policy, and retention fixes to Peter Steinberger; the supplied PR metadata maps the repository owner to steipete. (role: introduced and recently maintained the SQLite cost-store behavior; confidence: high; commits: 56a763ea5a4e, 26fd0bbd7eed, 5205dd1e003c; files: Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore.swift, Sources/CodexBarCore/Vendored/CostUsage/CostUsageStore+CodexCache.swift, Tests/CodexBarTests/CostUsageStoreTests.swift)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Let the queued macOS test shards complete against the rebuilt head.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (2 earlier review cycles)
  • reviewed 2026-08-08T16:21:51.297Z sha 5729671 :: found issues before merge. :: [P2] Abort the enclosing cache save after a skipped write | [P1] Rebase onto the existing non-destructive recovery policy
  • reviewed 2026-08-08T17:03:10.260Z sha 5729671 :: found issues before merge. :: [P1] Keep the full non-destructive error classification | [P2] Abort the cache save after a skipped SQLite write

@steipete
steipete force-pushed the review/store-stress branch from 5729671 to b333cd1 Compare August 8, 2026 18:34
@steipete steipete changed the title fix: don't wipe the SQLite cost store on transient SQLITE_BUSY contention (refs #2760) test: add StoreStress harness and contention regression tests Aug 8, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal priority bug or improvement with limited blast radius. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Aug 8, 2026
@steipete
steipete merged commit e77c453 into main Aug 8, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 session-state 🚨 Merging this PR could lose, corrupt, stale, or mis-associate session or agent state. P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant