feat(opencode): add db doctor and repair commands#32093
Open
pascalandr wants to merge 11 commits into
Open
Conversation
Adds native db doctor and repair flows with JSON output, dry-run and apply modes, safe/aggressive repair planning, backup-before-apply safeguards, transactional preconditions, and targeted DB tests.
Contributor
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
# Conflicts: # packages/opencode/src/cli/cmd/db.ts # packages/opencode/src/index.ts
This was referenced Jun 13, 2026
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.
Issue for this PR
Related issues (does not automatically close): #29908, #31204, #19191, #29581, #31597, #23594, #30157, #14970, #24780.
Type of change
What does this PR do?
Adds native database health commands for local OpenCode SQLite databases:
opencode db doctorandopencode db doctor --jsonopencode db repair --dry-runandopencode db repair --applyThe commands inspect local OpenCode SQLite databases directly, without opening them through the app runtime on diagnostic/dry-run paths. They diagnose/repair rows by comparing persisted data shapes against the invariants required by the OpenCode binary currently running the command.
This is not a generic legacy repair toolbox. The repair contract is:
doctorchecks whether the existing local DB schema and persisted rows conform to the session/message/part specs that this binary expects, without performing migrations.repair --applyonly applies explicitly cataloged row-shape fixes that have deterministic target values and precondition checks.The supported repair catalog is exported from
@opencode-ai/core/database/healthasSUPPORTED_REPAIRSand is included indoctor/repair --dry-runJSON output. Each catalog entry declares the target OpenCode version/invariant, known target migration when applicable, source evidence if known, repair behavior, and safety constraints. The report also includes acompatibilityblock with the current binary version, expected migrations for that binary, applied DB migrations, and observedsession.versiondistribution.Supported repair catalog
This PR currently supports exactly these repair codes:
part_legacy_id_prefix: renamespart_<suffix>IDs toprt_<suffix>only when the target ID does not already exist. This fixes the observed load failure:Expected a string starting with "prt", got "part_..." at [0]["parts"][0]["id"].assistant_message_missing_agent: copies assistantsession_message.data.modetodata.agentwith original-JSON precondition checks.session_agent_missing: fillssession.agentonly when one unambiguous value can be derived from assistant or agent-switched messages.session_model_missing: fillssession.modelonly when one unambiguous model object can be derived from assistant or model-switched messages.session_path_missing: fillssession.pathfrom the same row's non-emptysession.directory.message_assistant_missing_parent: fills missing assistantparentIDfrom the immediately preceding message in the same session.message_user_missing_agent: fills missing useragentonly when one unambiguous agent is derivable.message_user_missing_model: fills missing usermodelonly when one unambiguous model is derivable.part_step_finish_missing_reason: fills missingstep-finish.reasonwithstop.part_compaction_missing_auto: fills missingcompaction.autowithfalse.part_tool_completed_missing_metadata: fills missing completed-toolstate.metadatawith{}.part_tool_completed_missing_title: fills missing completed-toolstate.titlefromdata.toolonly when present.part_tool_completed_missing_time: fills missing completed-toolstate.time.start/endfrom the part row timestamp while preserving any existing start/end value.Versioning model
doctorandrepairvalidate a DB against the schema and persisted data shapes expected by the current binary. They do not require that the DB was previously opened by this exact OpenCode version. A DB that has been opened/migrated by a newer OpenCode may no longer be openable by older OpenCode versions; this tool is therefore about conformity to the current OpenCode binary, not about restoring historical row formats.Creation/source version information remains useful when it is known. It can help target repairs and explain why a row shape exists, especially when a specific SDK/spec change or migration boundary is known. But source versions are evidence, not the primary repair criterion. The primary criterion is whether the row violates a cataloged invariant of the current migrated target.
If an exact first-required OpenCode release, SDK version, or migration is known, the catalog must cite it. If only affected persisted shapes are known, the catalog must say that explicitly and include observed source evidence without pretending to know the exact boundary.
Safety behavior
The diagnostic and dry-run paths avoid creating, opening through the app runtime, migrating, checkpointing, backing up, or writing to the DB.
repair --applyis the only write path; it creates a SQLite snapshot backup first, runs repairs in a transaction, checks row preconditions, and reruns a post-check.Existing
opencode dbquery/path behavior is preserved.How to update this when SDK/session specs change
For each future persisted-shape change that can break migrated sessions:
SUPPORTED_REPAIRSentry describing the target OpenCode version/invariant, known migration or SDK boundary if known, source evidence if known, repair, and safety constraints.doctor,repair --dry-run,repair --apply, and idempotency.repairable: falseand explain why.How did you verify your code works?
From
packages/opencode:From the repo root / pre-push hook:
Compiled Windows CLI smoke tests:
Real local DB dry-run, without applying repairs:
Manual real-user DB repair validation:
After applying repairs to that real local user DB:
This manually validated the tool against a real local user database and confirmed it repaired the targeted damaged session rows that caused session loading failures.
Follow-up
A good follow-up would be to design how this capability should be exposed outside the local CLI, for example through the SDK and/or an API surface. That should be a separate PR because it needs an explicit contract for permissions, dry-run/apply separation, backup reporting, and safety around running repairs from non-interactive clients.
Screenshots / recordings
Not a UI change.
Checklist