fix(server): opencode by-id existence fallback — stop declaring rebound panes dead at restart - #579
Merged
Merged
Conversation
…ified the archived-refusal premise Stage-2 load-bearing validation (11 verified, 1 falsified): live attach to an archived opencode session succeeds and Session.get has no time_archived filter (v1.18.9), so the by-id existence query drops 'AND time_archived IS NULL' to preserve attach parity. Tests flipped (archived => found/Present), the legacy- schema test repurposed to pin schema robustness, and validation results + accepted limitations (channel-suffixed db filename) recorded in Global Constraints. Ledger: .worktrees/.the-usual-logs/opencode-existence-fallback/ load-bearing-ledger.md
Independent review found Task 4's load-bearing assertion could not pass:
waitForOpencodeDbSession returns only {id, title, directory}, so
childRow.parent_id was always undefined and the premise gate's child
verification would fail for the wrong reason (or, via the old adapt
hedge, be silently dropped and pass vacuously against a ROOT session).
- Extend Task 4 to also modify the harness: queryOpencodeSessionRow now
selects parent_id (additive; existing callers unaffected), declared in
the task's Files list and Step 5 commit command.
- Assertion is now expect(childRow.parent_id).toBe(rootSessionId), marked
LOAD-BEARING; adapt hedge rewritten to forbid weakening it (PRAGMA
table_info fallback for column-name variance; no-parent-column case
routes to the existing recorded-infeasibility branch).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
At restart, the reconcile existence probe answered from the opencode session LISTING, which filters child sessions (parent_id IS NULL) and directory-less rows. A pane rebound via the opencode TUI-plugin signal lane to a child session id (the session the user was actually viewing) therefore read Absent; because the rebind ledger makes ever_bound true, reconcile derived DeadSession{session_not_on_disk} — the "Dead sessions" dialog — even though the row exists on disk. Worse, a pane claiming the superseded root id was chain-corrected to the invisible child terminus, so one child rebind buried BOTH bookmarks.
The Fix
IndexExistenceProbe now falls back to a direct read-only by-id sqlite query (no parent_id filter, no directory filter) when the warm index says Absent for opencode — the exact analog of the existing claude raw-file fallback, keeping the probe in agreement with the attach arm (
opencode --session <id>resolves by id, children included).Load-bearing error semantics: DB open/read failure answers Unknown (reconcile defers and retries), never Absent — so WAL lock contention can't recreate the bug; missing DB file stays Absent.
Performance: Short 250ms busy timeout (not the listing's 5s) since exists() is sync on the reconcile path.
Fallback hits: Feed the monotone observed-set; claude/codex Absent never consult the opencode DB.
Archived sessions: Count as Present — validated against real opencode (attach to archived sessions succeeds).
Migration: No ledger migration needed: the ledger was recording the truth; fixing the reader heals existing affected users on their next reconcile automatically.
Testing
Review Status
Built via the-usual recipe; independent plan review (2 rounds) and delta review (first-round pass, zero blockers) both passed.
Follow-ups (non-blocking)
Generated with Amplifier