Skip to content

Handle OpenCode 2 history database contention consistently - #24826

Open
nwparker wants to merge 1 commit into
nwparker/OpenCode-Native-Chatfrom
nwparker/fix-opencode-vault-source-contention
Open

nwparker wants to merge 1 commit into
nwparker/OpenCode-Native-Chatfrom
nwparker/fix-opencode-vault-source-contention

Conversation

@nwparker

@nwparker nwparker commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​24 0 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​24
Prod 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​12 $\color{#cf222e}{\Huge{\mathbf{−}}}$​24 $\color{#cf222e}{\Huge{\mathbf{−}}}$​12

ELI5

OpenCode 2 history survives a brief database write. When the database stays busy, Vault explains that the database could not be read and retries it on refresh.

What Changed

OpenCode 2 listing and preview reads now use the existing read-only database opener: a 1500 ms busy timeout for native paths and zero for WSL network paths. Errors carry the OpenCode 2 agent and database scope so the existing desktop and mobile notice can describe the unavailable history accurately.

Why

This reuses the policy already used by OpenCode 1 rather than giving the two readers different lock behavior. It tolerates short writes while keeping network paths from waiting on locks they cannot resolve locally.

Linked Issue

Continues the database-opening intent of #15671 and the focused OpenCode Vault work from #10708. This change depends on the native OpenCode core in #24647 and does not settle either original PR's full scope.

Visual Proof

Actual production worker reads use installed OpenCode 2.0.16 history copied into an isolated database. A controlled SQLite writer establishes contention; it is not a currently running CLI writer.

The hidden production encrypted mobile History route at390×812 uses the same genuine retained CLI session: before, V2 appears as a skipped transcript with a raw lock error; after, both OpenCode readers return typed source-writing notices, with zero skipped transcripts. Release and Refresh recover the same session (1→0→1). No synthetic notice amplification was used. The retained before already contains #24772's viewport fix; the after rebuild includes its equivalent copy extraction and this scanner correction. This is macOS rendered web-route proof, not physical phone coverage.

Before: generic OpenCode 2 lock error

After: typed OpenCode 2 source-writing notice

Actual writer lock Before After
Releases after 300 ms No rows; immediate lock error One genuine CLI-created row; no issue
Remains exclusive Immediate generic lock error Typed OpenCode 2 database scope after about 1.6 seconds
Writer released One row One row

Testing

  • I manually tested these changes locally
  • Automated tests added/updated

ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/ai-vault/session-scanner-opencode-sqlite-open.test.ts src/main/ai-vault/session-scanner-opencode2-sqlite.test.ts src/main/ai-vault/session-scanner-opencode-sqlite-paths.test.ts passed 39 distinct tests (24 opener/v2 and 15 related SQLite tests). Native macOS production worker reads covered both real lock cases and recovery; the zero-timeout WSL path is covered by tests, with physical Windows/WSL validation still required.

Review

Only four files change: the canonical opener, its tests, and the two OpenCode 2 readers. The opener preserves read-only access, existing error handling, and the native/WSL boundary.

Agent skill upstream boundary

  • Not applicable; no upstream skill implementation is copied.

Notes

Credit @AmethystLiang for the original OpenCode AI Vault work in #10708 and Brennan Benson for the original #15671 database-opening intent. Cache bounds and scan ownership are separate focused changes.

Checklist

  • This PR is small and focused
  • I explained the user-facing change, mechanism, and reason for the approach
  • Backend before/after behavior is recorded; rendered notice captures accompany the native validation
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and compatibility impact considered
  • Full lint and packaging build are left to CI; focused tests, typecheck, and changed-file gate pass

Reuse the existing readonly OpenCode opener so v2 reads allow brief native writes to finish within 1500 ms and retain the zero-wait WSL share policy. Report v2 listing failures through the existing typed scope notice.

Continues the AI Vault performance work by @AmethystLiang in original PR #10708.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Canonical opener for OpenCode 2 reads — both the v2 list leg and the v2 preview parse now open opencode-next.db through openOpenCodeDatabaseReadonly, dropping their private openReadonlyDatabase (which passed no timeout). They inherit the 1500 ms native / 0 ms WSL busy-timeout split already used by OpenCode 1, and the opener's close-on-pragma-failure guard.
  • Typed issue for the v2 list leg — the catch now calls openCodeDatabaseScanIssue(dbPath, err, 'opencode2'), emitting kind: 'scope' and the OpenCode 2 is writing to … copy. Previously it pushed an unkinded issue, which the panel counts as a skipped transcript.
  • openCodeDatabaseScanIssue accepts 'opencode2' — adds the agent to its union and the OpenCode 2 label; 'opencode'/'zcode' paths untouched.
  • New test — covers a brief v2 lock (recovers, no issues) and a persistent lock (waits inside the busy timeout, returns [], emits the scope issue).

I verified the focused tests (session-scanner-opencode-sqlite-open.test.ts, session-scanner-opencode2-sqlite.test.ts — 24 passed), oxlint on the four changed files, and pnpm tc:node; all clean. The change is a faithful reuse of the existing v1 policy, and the new test genuinely fails against the pre-change default-zero timeout, so it pins the behavior rather than the current state.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant