fix(infra): converge legacy state migrations on archive collisions#102780
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 9, 2026, 8:54 AM ET / 12:54 UTC. Summary PR surface: Source +184, Tests +269. Total +453 across 12 files. Reproducibility: yes. at source and PR-proof level: current main leaves archive collisions as warnings and startup preflight fails on any startup migration warning, while the PR body reports a real-state before/after convergence proof. Review metrics: 3 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land this unified convergence policy after maintainer acceptance and exact-head checks remain green, while keeping true import conflicts warning-blocking. Do we have a high-confidence way to reproduce the issue? Yes at source and PR-proof level: current main leaves archive collisions as warnings and startup preflight fails on any startup migration warning, while the PR body reports a real-state before/after convergence proof. Is this the best way to solve the issue? Yes: current head applies the same convergence behavior to core and shared plugin helpers, keeps real failures as warnings, and downgrades only verified imported Codex residue to notices. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 07a7d596ff6e. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +184, Tests +269. Total +453 across 12 files. View PR surface stats
Acceptance criteria:
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
Review history (1 earlier review cycle)
|
31765e7 to
a00d175
Compare
|
@clawsweeper re-review [P1] Route archive collisions through the shared plugin helper — fixed on head a00d175. Correct catch: On "only verified imported residue becomes non-blocking": the helper is invoked by plugin migrations after their import step, and the non-blocking conversion here is byte-safety based, not trust based — a source is deleted only when its exact bytes already exist in the archive, and otherwise it is preserved under a new archive name. The unresolved-owner Codex sidecar notice similarly fires only after Proof on the new head: |
|
🦞🧹 I asked ClawSweeper to review this item again. |
What Problem This Solves
Fixes #102749. Startup legacy-state migrations never converged when a
.migratedarchive already existed for a still-present legacy source (plugins/installs.json,tasks/runs.sqlitesidecars, plugin-state sidecars, debug-proxy captures, Codex binding sidecars). The migration imported the data but left the source in place with a warning,runDoctorConfigPreflightfails closed on any migration warning, and the prescribed remedy (openclaw doctor --fix) reproduced the same warnings — permanently locking the gateway out of that state dir even though all data was migrated successfully.Release note: gateway startup no longer permanently refuses to start when legacy state migrations leave already-imported files behind.
Why This Change Was Made
The migration result shape conflated "migration failed" with "migration succeeded but left residue", and the startup gate blocked on both. Mixed old/new CLI versions writing the same state dir is enough to trigger the lockout.
User Impact
.migratedarchive it is removed (the data was imported this run and the archive already preserves the snapshot); otherwise it is archived to the first free.migrated.Nname. Both paths are recorded as doctor changes; a second run is silent.noticeschannel (mirroringrunPostCorePluginConvergence) instead of warnings: e.g. Codex binding sidecars whose session owner cannot be resolved are still imported and retained, but no longer block startup.src/commands/doctor-config-preflight.ts) now blocks on real warnings and blockers only; notices are printed underDoctor notices.Evidence
Focused suites (
state-migrations*,doctor-config-preflight.state-migration,doctor-health-contributions,extensions/codex/doctor-contract-api): all pass vianode scripts/run-vitest.mjs.pnpm tsgo:core,pnpm tsgo:core:test,pnpm tsgo:extensions: exit 0. New regression tests cover identical-bytes removal,.migrated.2fallback, second-run silence, notice-vs-warning classification, and the gate passing on notices while still throwing on warnings.Real behavior proof on a copy of the real state dir that reproduced the lockout (legacy
installs.json+installs.json.migrated,runs.sqlitesidecars + archives, 11 unresolved Codex binding sidecars):openclaw gateway runaborts every time withOpenClaw startup migrations did not complete cleanly; refusing to report the gateway ready, andopenclaw doctor --fixcannot clear it (loop documented in [Bug]: startup legacy-state migration never converges when .migrated archive already exists; gateway permanently refuses to start #102749).Doctor notices.