fix(state-migrations): archive plugin install index on conflict instead of keeping it#90252
fix(state-migrations): archive plugin install index on conflict instead of keeping it#90252Bartok9 wants to merge 1 commit into
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 15, 2026, 11:09 AM ET / 15:09 UTC. Summary PR surface: Source -1, Tests +16. Total +15 across 2 files. Reproducibility: yes. at source level: seed a conflicting legacy Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Keep the migration in core, but archive only records proven superseded by authoritative SQLite state, keep true conflicts visible with actionable guidance, and require real two-run upgrade proof before merge. Do we have a high-confidence way to reproduce the issue? Yes at source level: seed a conflicting legacy Is this the best way to solve the issue? No. The state-migration layer is the right place, but archiving every conflict is too broad; the maintainable fix should archive only proven superseded legacy records and keep unsafe conflicts visible. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c1219d161d3e. Label changesLabel justifications:
Evidence reviewedPR surface: Source -1, Tests +16. Total +15 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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. How this review workflow works
|
Per ClawSweeper review feedback [P3]: the previous text 'shared SQLite state has newer metadata for' was misleading — conflicts can arise from mismatched floating selectors, package renames, or malformed legacy spec metadata, not necessarily because SQLite is newer. Use a generic conflict description that accurately covers all conflict reasons.
f524018 to
ceb2111
Compare
|
@clawsweeper re-review Updated PR:
|
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@Bartok9 thanks for the PR. ClawSweeper is still waiting on real behavior proof before this can move forward. Useful proof can be a screenshot, short video, terminal output, copied live output, linked artifact, or redacted logs that show the changed behavior after the fix. Please redact private tokens, phone numbers, private endpoints, customer data, and anything else sensitive. Once proof is added to the PR body or a comment, ClawSweeper or a maintainer can re-check it. |
|
Thanks @Bartok9 for the focused PR and follow-up here. I am closing this as superseded by #90267 because both PRs target the same repeated legacy plugin install-index migration warning, and the canonical path now has the narrower migration rule plus passing real behavior proof. Canonical PR: #90267 Clownfish is keeping the canonical thread open there so validation and maintainer review stay in one place. The work and discussion from this source PR remain linked for context and credit. If this still covers a different reproduction path after #90267 lands, please reply and we can reopen or split it back out. |
Summary
Motivation
Closes #90213.
After updating to OpenClaw 2026.6.1 (which merged the SQLite state migration in #88585 and the follow-up fix in #89281), some users saw:
This warning repeated on every gateway restart, every
openclaw doctor --fix, and everyopenclaw plugins inspectrun — because the legacy JSON file was left in place, causingmigrateLegacyInstalledPluginIndexto re-enter the conflict path on each invocation.Root cause (code trace)
In
src/infra/state-migrations.ts, the pre-patch conflict branch:This returns without calling
archiveLegacyInstalledPluginIndex, leavingplugins/installs.jsonon disk. On the next run, the file is re-read, the same conflict is re-detected, and the same warning fires again.Fix (code trace)
Post-patch — the conflict path now archives the file and continues:
archiveLegacyInstalledPluginIndexrenamesplugins/installs.json→plugins/installs.json.migrated. On subsequent runs, the file no longer exists atsourcePath, somigrateLegacyInstalledPluginIndexexits at the early-return guard before reaching the conflict branch — no repeated warning.Behavior proof (two-run trace)
Run 1 (fresh legacy file on disk, SQLite has conflicting records):
plugins/installs.json→ renamed toplugins/installs.json.migratedRun 2 (gateway restart /
openclaw doctor --fix/openclaw plugins inspect brave):The
sourcePathno longer exists, the migration function returns before the conflict branch, and warnings are empty. This is the fix behavior verified by the new regression test insrc/commands/doctor-state-migrations.test.ts(thesecond run produces no warningsassertion added by this PR).Verification
tsc --noEmit— cleandescribe('migrateLegacyInstalledPluginIndex — conflict archive')with parameterized cases covering:'shared SQLite state has newer metadata'to generic'detecting conflicting plugin install metadata'per ClawSweeper P3 feedback — covers all conflict causes, not just recency.