Skip to content

fix(cli): show working commands for pinned plugin drift#95541

Merged
vincentkoc merged 3 commits into
openclaw:mainfrom
ooiuuii:fix/plugin-drift-exact-pin-hint
Jun 23, 2026
Merged

fix(cli): show working commands for pinned plugin drift#95541
vincentkoc merged 3 commits into
openclaw:mainfrom
ooiuuii:fix/plugin-drift-exact-pin-hint

Conversation

@ooiuuii

@ooiuuii ooiuuii commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes an issue where operators who saw official managed plugin version drift after an upgrade could be given a repair command that did not actually advance exact npm pins.

During a Windows upgrade to 2026.6.10-beta.1, doctor / status --deep reported active official plugins such as brave, discord, qqbot, and whatsapp still on 2026.6.9. The suggested openclaw plugins update <plugin-id> command was not sufficient for those records because their install records were exact npm pins like @openclaw/[email protected]; an id-only update preserves that pin and reports the stale version as up to date.

Why This Change Was Made

This keeps the existing plugin update semantics intact and fixes the operator guidance instead. Plugin drift now resolves the update command for each drift entry: floating installs still use openclaw plugins update <plugin-id>, while exact npm pins use an explicit openclaw plugins update <package>@<gatewayVersion> target derived from the parsed exact npm spec.

Related: #94084 owns the bulk openclaw plugins update --all official-sync path. This PR is intentionally narrower: it makes the per-plugin repair command printed by doctor / gateway status --deep actionable without changing targeted id updates or --all behavior.

Out of scope: changing manual plugins update <id> behavior, unpinning installs automatically, changing bulk update semantics, or changing how version drift is detected.

User Impact

Operators can copy the drift repair command from openclaw doctor or openclaw gateway status --deep and get the plugin onto the gateway version. For the beta upgrade case above, the advice becomes:

openclaw plugins update @openclaw/[email protected] && openclaw gateway restart

instead of an id-only command that can preserve @openclaw/[email protected].

Evidence

Before evidence from the real upgrade:

backup SQLite install records before manual repair:
brave    spec=@openclaw/[email protected]  resolvedVersion=2026.6.9
discord  spec=@openclaw/[email protected]       resolvedVersion=2026.6.9
qqbot    spec=@openclaw/[email protected]         resolvedVersion=2026.6.9
whatsapp spec=@openclaw/[email protected]      resolvedVersion=2026.6.9
codex    spec=@openclaw/[email protected] resolvedVersion=2026.6.10-beta.1

Observed symptom during that upgrade: openclaw plugins update brave, discord, qqbot, and whatsapp each reported the 2026.6.9 install as up to date while the gateway was already on 2026.6.10-beta.1; manually installing @openclaw/<package>@2026.6.10-beta.1 --force --pin repaired the drift.

After-fix real CLI proof from this PR head:

  • Real environment tested: Windows source checkout, PR head 623e3dfcd6, OpenClaw source version 2026.6.9.
  • Setup: temporary OPENCLAW_STATE_DIR and OPENCLAW_CONFIG_PATH; seeded the temporary SQLite installed_plugin_index with a stale exact npm record brave / @openclaw/[email protected].
  • Exact command run after this patch:
node openclaw.mjs gateway status --deep --no-probe
  • Evidence after fix:
Plugin version drift: 1 active official plugin not on gateway 2026.6.9
- brave: 2026.6.8 (npm) -> expected 2026.6.9
Fix: openclaw plugins update @openclaw/[email protected] && openclaw gateway restart.
  • Observed result after fix: the real gateway status --deep CLI path printed an exact package update command derived from the pinned npm spec, not openclaw plugins update brave or the generic <plugin-id> placeholder.
  • What was not tested: full CI and packaged npm release artifacts. doctor shares the same formatter helper and has focused coverage, but the real CLI proof above uses gateway status --deep --no-probe to avoid this machine's unrelated live gateway/device-identity state.

Local validation:

node scripts/run-vitest.mjs src/plugins/plugin-version-drift.test.ts src/commands/doctor-workspace-status.test.ts src/cli/daemon-cli/status.print.test.ts
# 3 shards passed: 21 tests, 17 tests, 11 tests

node scripts/run-oxlint.mjs src\plugins\plugin-version-drift.ts src\plugins\plugin-version-drift.test.ts src\commands\doctor-workspace-status.ts src\commands\doctor-workspace-status.test.ts src\cli\daemon-cli\status.print.ts src\cli\daemon-cli\status.print.test.ts
# exited 0

node_modules\.bin\oxfmt.cmd --check --threads=1 src\plugins\plugin-version-drift.ts src\plugins\plugin-version-drift.test.ts src\commands\doctor-workspace-status.ts src\commands\doctor-workspace-status.test.ts src\cli\daemon-cli\status.print.ts src\cli\daemon-cli\status.print.test.ts
# all matched files use the correct format

git diff --check
# passed

ClawSweeper follow-up addressed:

  • The exact npm command now uses the package parsed from entry.spec after verifying it is an exact npm version.
  • Added regression coverage for inconsistent packageName metadata so the command still targets the pinned spec package.

@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes commands Command implementations size: S labels Jun 21, 2026
@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 21, 2026, 2:32 PM ET / 18:32 UTC.

Summary
The PR adds a plugin drift update-command helper and routes doctor and gateway status drift hints through it so exact npm-pin drift prints package@version update targets.

PR surface: Source +36, Tests +143. Total +179 across 6 files.

Reproducibility: yes. Current main source prints id/generic drift hints, and the documented update contract says id updates preserve exact pins while explicit npm specs change the tracked target.

Review metrics: 1 noteworthy metric.

  • Drift repair command surfaces: 2 changed. Doctor and gateway status both print copy-paste recovery commands, so maintainers should notice the operator guidance before merge.

Stored data model
Persistent data-model change detected: migration/backfill/repair: src/commands/doctor-workspace-status.test.ts, migration/backfill/repair: src/commands/doctor-workspace-status.ts, unknown-data-model-change: src/commands/doctor-workspace-status.test.ts, vector/embedding metadata: src/plugins/plugin-version-drift.test.ts. Migration or upgrade compatibility proof is recorded; maintainers should verify it before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Confirm whether the per-plugin exact-pin recovery hint is the desired guidance alongside the open bulk update path.

Risk before merge

Maintainer options:

  1. Keep Both Recovery Paths
    Land this PR with fix(cli): sync official plugins during update --all #94084 if maintainers want status and doctor to show exact per-plugin fixes while update --all owns bulk convergence.
  2. Use One Bulk Hint
    Pause this PR and make doctor/status recommend the bulk update command after that recovery path lands if maintainers want one operator workflow.
  3. Revise The Hint Shape
    Change the diagnostic text before merge to mention both the exact per-plugin command and the bulk command if that is the approved recovery guidance.

Next step before merge

  • [P2] Maintainer review should choose the approved per-plugin versus bulk upgrade-recovery guidance; there is no narrow automated repair pending.

Security
Cleared: The diff changes CLI diagnostic text and focused tests only; it adds no dependency, workflow, package metadata, secret handling, or new code-execution surface.

Review details

Best possible solution:

Land a maintainer-approved recovery story where doctor/status provide copy-paste-safe exact-pin commands and the bulk updater remains the fleet-wide convergence path, or revise the hints to the single approved workflow.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main source prints id/generic drift hints, and the documented update contract says id updates preserve exact pins while explicit npm specs change the tracked target.

Is this the best way to solve the issue?

Yes for the narrow per-plugin hint path, pending maintainer acceptance of the operator guidance. Deriving the target from the parsed exact install spec is the maintainable fix; the alternative is to use only the bulk update path once that path is approved.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 6fa944e80f22.

Label changes

Label justifications:

  • P2: The PR addresses a bounded CLI recovery bug where official plugin drift diagnostics can give non-working commands for exact npm pins.
  • merge-risk: 🚨 compatibility: The diff changes upgrade recovery guidance for persisted plugin install records, which can affect existing operator workflows.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body provides after-fix terminal output from a real Windows source CLI path with seeded stale exact npm state showing the new exact package command.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides after-fix terminal output from a real Windows source CLI path with seeded stale exact npm state showing the new exact package command.
Evidence reviewed

PR surface:

Source +36, Tests +143. Total +179 across 6 files.

View PR surface stats
Area Files Added Removed Net
Source 3 48 12 +36
Tests 3 146 3 +143
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 6 194 15 +179

What I checked:

  • Repository policy applied: Root AGENTS.md and scoped plugin AGENTS.md were read fully; plugin install records, upgrade recovery, and operator guidance are compatibility-sensitive review surfaces. (AGENTS.md:24, 6fa944e80f22)
  • Current main still has generic gateway status guidance: Current main deep gateway status prints the placeholder command for each drifted plugin, so the proposed change is not obsolete on main. (src/cli/daemon-cli/status.print.ts:487, 6fa944e80f22)
  • Current main doctor guidance uses id or placeholder updates: Current main doctor uses the plugin id for a single drift entry and a placeholder for multiple entries, which is the reported non-working guidance for exact npm pins. (src/commands/doctor-workspace-status.ts:74, 6fa944e80f22)
  • Documented update contract supports the bug claim: The plugin CLI docs say id-based updates reuse recorded specs, including exact pinned versions, while explicit npm specs can switch the tracked target. Public docs: docs/cli/plugins.md. (docs/cli/plugins.md:390, 6fa944e80f22)
  • Update selection supports explicit npm spec repair: Current update selection maps an explicit npm package spec back to the tracked plugin record and records a spec override, while raw plugin ids preserve the tracked spec. (src/cli/plugins-update-selection.ts:23, 6fa944e80f22)
  • PR diff uses parsed exact npm spec package: The PR adds a helper that parses exact npm specs from drift entries and prints package@gatewayVersion update commands in both doctor and gateway status, with regression tests including inconsistent metadata. (src/plugins/plugin-version-drift.ts:26, 623e3dfcd619)

Likely related people:

  • vincentkoc: Current-line blame for plugin drift detection and both doctor/status drift hint outputs points to recent work by Vincent Koc. (role: recent area contributor; confidence: high; commits: 2f3399989893; files: src/plugins/plugin-version-drift.ts, src/commands/doctor-workspace-status.ts, src/cli/daemon-cli/status.print.ts)
  • steipete: History shows Peter Steinberger extracted the plugin install/update command surface that this PR relies on. (role: feature-history contributor; confidence: medium; commits: 5920ea838d51; files: src/cli/plugins-update-command.ts, src/cli/plugins-update-selection.ts)
  • huntharo: Earlier versioned plugin update work touched the update implementation and docs for id-versus-npm-spec behavior. (role: adjacent plugin-update contributor; confidence: medium; commits: 401ffb59f538; files: src/plugins/update.ts, docs/cli/plugins.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 21, 2026
@ooiuuii

ooiuuii commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated for the first review on head 623e3dfcd6:

  • Fixed the command-target finding: exact npm drift commands now use the package parsed from entry.spec, not stale/inconsistent packageName metadata.
  • Added regression coverage for inconsistent packageName metadata.
  • Refreshed the PR body with real after-fix CLI proof from node openclaw.mjs gateway status --deep --no-probe using a temporary state/config and seeded exact npm pin. The output now shows Fix: openclaw plugins update @openclaw/[email protected] && openclaw gateway restart.
  • Re-ran focused validation: drift helper/status/doctor Vitest passed (21/17/11 tests), oxfmt check passed, oxlint exited 0, and git diff --check passed.

Related #94084 remains the bulk plugins update --all sync path; this PR stays scoped to per-plugin drift repair hints.

@clawsweeper

clawsweeper Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 21, 2026
@vincentkoc
vincentkoc force-pushed the fix/plugin-drift-exact-pin-hint branch from 855dd29 to d41b9b5 Compare June 23, 2026 04:22
@vincentkoc
vincentkoc merged commit 2ea0e88 into openclaw:main Jun 23, 2026
91 checks passed
@vincentkoc

Copy link
Copy Markdown
Member

Merged via squash.

Thanks @ooiuuii!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes commands Command implementations merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants