fix: repair configured plugin installs (#76129)

Summary:
- The PR adds a 2026.5.2 doctor repair pass for actively used configured downloadable plugins, prefers ClawHub ... pm fallback, records installed plugin state, extends upgrade-survivor coverage, and updates docs/changelog.
- Reproducibility: yes. Static inspection of current main and the PR head gives a high-confidence reproduction ... d-plugin install pass, while the PR tests the new repair-only path, success stamping, and warning behavior.

ClawSweeper fixups:
- Included follow-up commit: test: cover configured plugin install update path
- Included follow-up commit: test: isolate channel option metadata cache
- Included follow-up commit: fix: keep configured plugin repair scoped

Validation:
- ClawSweeper review passed for head d3519ce42c.
- Required merge gates passed before the squash merge.

Prepared head SHA: d3519ce42c
Review: https://github.com/openclaw/openclaw/pull/76129#issuecomment-4364120658

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
Peter Steinberger
2026-05-02 16:49:52 +01:00
committed by GitHub
parent 7b6b6401ce
commit b63d098e8c
22 changed files with 1133 additions and 121 deletions

View File

@@ -1,4 +1,4 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { __testing, resolveCliChannelOptions } from "./channel-options.js";
import { __testing as startupMetadataTesting } from "./startup-metadata.js";
@@ -22,12 +22,17 @@ vi.mock("../channels/ids.js", () => ({
}));
describe("resolveCliChannelOptions", () => {
afterEach(() => {
beforeEach(() => {
__testing.resetPrecomputedChannelOptionsForTests();
startupMetadataTesting.clearStartupMetadataCache();
vi.clearAllMocks();
});
afterEach(() => {
__testing.resetPrecomputedChannelOptionsForTests();
delete process.env.OPENCLAW_PLUGIN_CATALOG_PATHS;
});
it("uses precomputed startup metadata when available", async () => {
readFileSyncMock.mockReturnValue(
JSON.stringify({ channelOptions: ["cached", "quietchat", "cached"] }),
@@ -49,6 +54,5 @@ describe("resolveCliChannelOptions", () => {
readFileSyncMock.mockReturnValue(JSON.stringify({ channelOptions: ["cached", "quietchat"] }));
expect(resolveCliChannelOptions()).toEqual(["cached", "quietchat"]);
delete process.env.OPENCLAW_PLUGIN_CATALOG_PATHS;
});
});