mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:00:42 +00:00
chore(plugins): inventory doctor deprecation compat
This commit is contained in:
@@ -25,12 +25,22 @@ Use this skill for release and publish-time workflow. Keep ordinary development
|
||||
- Before release branching, commit any dirty files in coherent groups, push,
|
||||
pull/rebase, then run `/changelog` on `main` and commit/push/pull that
|
||||
changelog rewrite immediately before creating the release branch.
|
||||
- During release planning, inspect `src/plugins/compat/registry.ts` before
|
||||
branching and again before final publish. For every deprecated or
|
||||
removal-pending compatibility record whose `removeAfter` date is on or before
|
||||
the release date, either remove the compatibility path where safe and
|
||||
validate the affected tests, or write down why removal is blocked and get
|
||||
explicit maintainer approval before shipping the expired compatibility path.
|
||||
- During release planning, inspect both `src/plugins/compat/registry.ts` and
|
||||
`src/commands/doctor/shared/deprecation-compat.ts` before branching and again
|
||||
before final publish. For every deprecated or removal-pending compatibility
|
||||
record whose `removeAfter` date is on or before the release date, either
|
||||
remove the compatibility path where safe and validate the affected tests, or
|
||||
write down why removal is blocked and get explicit maintainer approval before
|
||||
shipping the expired compatibility path.
|
||||
- When removing deprecated runtime/config compatibility, preserve any doctor
|
||||
migration, repair, or hint that is still needed by supported upgrade paths.
|
||||
Doctor-side compatibility should stay tracked in
|
||||
`src/commands/doctor/shared/deprecation-compat.ts` until maintainers confirm
|
||||
the repair is no longer needed.
|
||||
- Revalidate compatibility replacement text during release planning. The
|
||||
recommended replacement can shift as plugin ownership, externalization, and
|
||||
config footprint move, so do not blindly copy stale replacement annotations
|
||||
into release notes.
|
||||
- Do not delete or rewrite beta tags after they leave the machine. If a
|
||||
published or pushed beta needs a fix, commit the fix on the release branch and
|
||||
increment to the next `-beta.N`.
|
||||
@@ -123,12 +133,13 @@ Use this skill for release and publish-time workflow. Keep ordinary development
|
||||
`CHANGELOG.md` version section, not highlights or an excerpt. When creating
|
||||
or editing a release, extract from `## YYYY.M.D` through the line before the
|
||||
next level-2 heading and use that complete block as the release notes.
|
||||
- When preparing release notes, scan `src/plugins/compat/registry.ts` for
|
||||
plugin compatibility records with `warningStarts` or `removeAfter` within 7
|
||||
days after the release date. Add an `Upcoming deprecations` note to the
|
||||
release notes when any exist, including the compatibility code, target date,
|
||||
replacement, and a link to the record's `docsPath` or `/plugins/compatibility`
|
||||
when no more specific deprecation page exists.
|
||||
- When preparing release notes, scan `src/plugins/compat/registry.ts` and
|
||||
`src/commands/doctor/shared/deprecation-compat.ts` for compatibility records
|
||||
with `warningStarts` or `removeAfter` within 7 days after the release date.
|
||||
Add an `Upcoming deprecations` note to the release notes when any exist,
|
||||
including the compatibility code, target date, replacement, and a link to the
|
||||
record's `docsPath` or `/plugins/compatibility` when no more specific
|
||||
deprecation page exists.
|
||||
- When cutting a mac release with a beta GitHub prerelease:
|
||||
- tag `vYYYY.M.D-beta.N` from the release commit
|
||||
- create a prerelease titled `openclaw YYYY.M.D-beta.N`
|
||||
|
||||
@@ -8,6 +8,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
- Plugins/startup: load the default `memory-core` slot during Gateway startup when permitted so active-memory recall can call `memory_search` and `memory_get` without requiring an explicit `plugins.slots.memory` entry, while preserving `plugins.slots.memory: "none"`. Thanks @codex.
|
||||
- Plugins/CLI: prefer native require for compiled bundled plugin JavaScript before jiti so read-only config, status, device, and node commands avoid unnecessary transform overhead on slow hosts. Fixes #62842. Thanks @Effet.
|
||||
- Plugins/compat: inventory doctor-side deprecation migrations separately from runtime plugin compatibility so release sweeps preserve needed repairs while enforcing dated removal windows. Thanks @vincentkoc.
|
||||
- Plugins/compat: add missing dated compatibility records for legacy extension-api, memory registration, provider hook/type aliases, runtime aliases, channel SDK helpers, and approval/test utility shims. Thanks @vincentkoc.
|
||||
- Plugins/CLI: refresh the persisted registry after managed plugin files are removed so ClawHub uninstall cannot leave stale `plugins list` entries. Thanks @codex.
|
||||
- Plugins/CLI: make plugin install and uninstall config writes conflict-aware, clear stale denylist entries on explicit reinstall/removal, and delete managed plugin files only after config/index commit succeeds. Thanks @codex.
|
||||
|
||||
@@ -31,6 +31,18 @@ The registry is the source for maintainer planning and future plugin inspector
|
||||
checks. If a plugin-facing behavior changes, add or update the compatibility
|
||||
record in the same change that adds the adapter.
|
||||
|
||||
Doctor repair and migration compatibility is tracked separately at
|
||||
`src/commands/doctor/shared/deprecation-compat.ts`. Those records cover old
|
||||
config shapes, install-ledger layouts, and repair shims that may need to stay
|
||||
available after the runtime compatibility path is removed.
|
||||
|
||||
Release sweeps should check both registries. Do not delete a doctor migration
|
||||
just because the matching runtime or config compatibility record expired; first
|
||||
verify there is no supported upgrade path that still needs the repair. Also
|
||||
revalidate each replacement annotation during release planning because plugin
|
||||
ownership and config footprint can change as providers and channels move out of
|
||||
core.
|
||||
|
||||
## Plugin inspector package
|
||||
|
||||
The plugin inspector should live outside the core OpenClaw repo as a separate
|
||||
@@ -112,6 +124,10 @@ Current compatibility records include:
|
||||
- persisted plugin registry disable and install-migration env flags while
|
||||
repair flows migrate operators to `openclaw plugins registry --refresh` and
|
||||
`openclaw doctor --fix`
|
||||
- legacy plugin-owned web search, web fetch, and x_search config paths while
|
||||
doctor migrates them to `plugins.entries.<plugin>.config`
|
||||
- legacy `plugins.installs` authored config and bundled plugin load-path
|
||||
aliases while install metadata moves into the state-managed plugin ledger
|
||||
|
||||
New plugin code should prefer the replacement listed in the registry and in the
|
||||
specific migration guide. Existing plugins can keep using a compatibility path
|
||||
|
||||
78
src/commands/doctor/shared/deprecation-compat.test.ts
Normal file
78
src/commands/doctor/shared/deprecation-compat.test.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import fs from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
getDoctorDeprecationCompatRecord,
|
||||
isDoctorDeprecationCompatCode,
|
||||
listDeprecatedDoctorDeprecationCompatRecords,
|
||||
listDoctorDeprecationCompatRecords,
|
||||
} from "./deprecation-compat.js";
|
||||
|
||||
const datePattern = /^\d{4}-\d{2}-\d{2}$/u;
|
||||
|
||||
const requiredDoctorCompatCodes = [
|
||||
"doctor-agent-runtime-embedded-harness",
|
||||
"doctor-plugin-install-config-ledger",
|
||||
"doctor-bundled-plugin-load-paths",
|
||||
"doctor-web-search-plugin-config",
|
||||
"doctor-web-fetch-plugin-config",
|
||||
"doctor-x-search-plugin-config",
|
||||
] as const;
|
||||
|
||||
function parseDate(date: string): Date {
|
||||
return new Date(`${date}T00:00:00Z`);
|
||||
}
|
||||
|
||||
function addUtcMonths(date: Date, months: number): Date {
|
||||
const next = new Date(date);
|
||||
next.setUTCMonth(next.getUTCMonth() + months);
|
||||
return next;
|
||||
}
|
||||
|
||||
describe("doctor deprecation compatibility inventory", () => {
|
||||
it("keeps compatibility codes unique and lookup-safe", () => {
|
||||
const records = listDoctorDeprecationCompatRecords();
|
||||
const codes = records.map((record) => record.code);
|
||||
|
||||
expect(new Set(codes).size).toBe(codes.length);
|
||||
expect(isDoctorDeprecationCompatCode("doctor-web-search-plugin-config")).toBe(true);
|
||||
expect(isDoctorDeprecationCompatCode("missing-code")).toBe(false);
|
||||
expect(getDoctorDeprecationCompatRecord("doctor-web-search-plugin-config").owner).toBe(
|
||||
"provider",
|
||||
);
|
||||
});
|
||||
|
||||
it("tracks the known doctor migrations that protect plugin/config rollout", () => {
|
||||
for (const code of requiredDoctorCompatCodes) {
|
||||
expect(isDoctorDeprecationCompatCode(code), code).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("requires dated deprecation metadata with a three-month maximum window", () => {
|
||||
for (const record of listDeprecatedDoctorDeprecationCompatRecords()) {
|
||||
expect(record.deprecated, record.code).toMatch(datePattern);
|
||||
expect(record.warningStarts, record.code).toMatch(datePattern);
|
||||
expect(record.removeAfter, record.code).toMatch(datePattern);
|
||||
if (!record.warningStarts || !record.removeAfter) {
|
||||
throw new Error(`${record.code} is missing deprecation window dates`);
|
||||
}
|
||||
const maxRemoveAfter = addUtcMonths(parseDate(record.warningStarts), 3);
|
||||
const removeAfter = parseDate(record.removeAfter);
|
||||
expect(removeAfter <= maxRemoveAfter, record.code).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps every record actionable", () => {
|
||||
for (const record of listDoctorDeprecationCompatRecords()) {
|
||||
expect(record.introduced, record.code).toMatch(datePattern);
|
||||
expect(record.source, record.code).toBeTruthy();
|
||||
expect(record.migration, record.code).toBeTruthy();
|
||||
expect(record.replacement, record.code).toBeTruthy();
|
||||
expect(record.docsPath, record.code).toMatch(/^\//u);
|
||||
expect(fs.existsSync(record.migration), `${record.code}: ${record.migration}`).toBe(true);
|
||||
expect(record.tests.length, record.code).toBeGreaterThan(0);
|
||||
for (const testPath of record.tests) {
|
||||
expect(fs.existsSync(testPath), `${record.code}: ${testPath}`).toBe(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
274
src/commands/doctor/shared/deprecation-compat.ts
Normal file
274
src/commands/doctor/shared/deprecation-compat.ts
Normal file
@@ -0,0 +1,274 @@
|
||||
export type DoctorDeprecationCompatStatus = "active" | "deprecated" | "removal-pending" | "removed";
|
||||
|
||||
export type DoctorDeprecationCompatOwner =
|
||||
| "agent-runtime"
|
||||
| "audio"
|
||||
| "browser"
|
||||
| "channel"
|
||||
| "config"
|
||||
| "gateway"
|
||||
| "plugin"
|
||||
| "provider"
|
||||
| "tools"
|
||||
| "tts";
|
||||
|
||||
export type DoctorDeprecationCompatRecord<Code extends string = string> = {
|
||||
code: Code;
|
||||
status: DoctorDeprecationCompatStatus;
|
||||
owner: DoctorDeprecationCompatOwner;
|
||||
introduced: string;
|
||||
deprecated?: string;
|
||||
warningStarts?: string;
|
||||
removeAfter?: string;
|
||||
source: string;
|
||||
migration: string;
|
||||
replacement: string;
|
||||
docsPath: string;
|
||||
tests: readonly string[];
|
||||
notes?: string;
|
||||
};
|
||||
|
||||
const TODAY = "2026-04-26";
|
||||
const MAX_REMOVE_AFTER = "2026-07-26";
|
||||
|
||||
function deprecatedCompatRecord<Code extends string>(
|
||||
record: Omit<
|
||||
DoctorDeprecationCompatRecord<Code>,
|
||||
"deprecated" | "warningStarts" | "removeAfter" | "status"
|
||||
> &
|
||||
Partial<
|
||||
Pick<
|
||||
DoctorDeprecationCompatRecord<Code>,
|
||||
"deprecated" | "removeAfter" | "status" | "warningStarts"
|
||||
>
|
||||
>,
|
||||
): DoctorDeprecationCompatRecord<Code> {
|
||||
return {
|
||||
status: "deprecated",
|
||||
deprecated: TODAY,
|
||||
warningStarts: TODAY,
|
||||
removeAfter: MAX_REMOVE_AFTER,
|
||||
...record,
|
||||
};
|
||||
}
|
||||
|
||||
// Doctor migrations and repair shims can outlive the runtime/config compatibility
|
||||
// path they repair. Release removals must check this inventory before deleting
|
||||
// doctor fixes, and replacement notes should be revalidated against the current
|
||||
// architecture because ownership and config footprint can shift during rollout.
|
||||
export const DOCTOR_DEPRECATION_COMPAT_RECORDS = [
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-agent-runtime-embedded-harness",
|
||||
owner: "agent-runtime",
|
||||
introduced: "2026-04-25",
|
||||
source: "agents.defaults.embeddedHarness; agents.list[].embeddedHarness",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.agents.ts",
|
||||
replacement: "agents.defaults.agentRuntime and agents.list[].agentRuntime",
|
||||
docsPath: "/plugins/sdk-agent-harness",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
notes:
|
||||
"Runtime-policy naming changed during the plugin architecture work; verify replacement wording against current agentRuntime docs before removal.",
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-agent-sandbox-persession",
|
||||
owner: "agent-runtime",
|
||||
introduced: "2026-04-26",
|
||||
source: "agents.defaults.sandbox.perSession; agents.list[].sandbox.perSession",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.agents.ts",
|
||||
replacement: "agents.*.sandbox.scope",
|
||||
docsPath: "/cli/doctor",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-top-level-memory-search",
|
||||
owner: "config",
|
||||
introduced: "2026-04-26",
|
||||
source: "memorySearch",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.agents.ts",
|
||||
replacement: "agents.defaults.memorySearch",
|
||||
docsPath: "/cli/doctor",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-top-level-heartbeat",
|
||||
owner: "config",
|
||||
introduced: "2026-04-26",
|
||||
source: "heartbeat",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.agents.ts",
|
||||
replacement: "agents.defaults.heartbeat and channels.defaults.heartbeat",
|
||||
docsPath: "/automation",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-gateway-bind-host-aliases",
|
||||
owner: "gateway",
|
||||
introduced: "2026-04-26",
|
||||
source: "gateway.bind host aliases such as 0.0.0.0 and localhost",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.gateway.ts",
|
||||
replacement: "gateway.bind.mode values such as lan, loopback, custom, tailnet, and auto",
|
||||
docsPath: "/gateway/configuration",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-audio-transcription-command",
|
||||
owner: "audio",
|
||||
introduced: "2026-04-26",
|
||||
source: "audio.transcription",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.audio.ts",
|
||||
replacement: "tools.media.audio.models",
|
||||
docsPath: "/tools/media-overview",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-channel-thread-binding-ttl",
|
||||
owner: "channel",
|
||||
introduced: "2026-04-26",
|
||||
source: "threadBindings.ttlHours",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.channels.ts",
|
||||
replacement: "threadBindings.idleHours",
|
||||
docsPath: "/channels/channel-routing",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-channel-dm-aliases",
|
||||
owner: "channel",
|
||||
introduced: "2026-04-26",
|
||||
source: "channels.<id>.dm.policy and channels.<id>.dm.allowFrom",
|
||||
migration: "src/config/channel-compat-normalization.ts",
|
||||
replacement: "channels.<id>.dmPolicy and channels.<id>.allowFrom",
|
||||
docsPath: "/channels/channel-routing",
|
||||
tests: ["src/commands/doctor/shared/channel-legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-channel-streaming-aliases",
|
||||
owner: "channel",
|
||||
introduced: "2026-04-26",
|
||||
source: "streamMode, scalar streaming, chunkMode, blockStreaming, draftChunk, nativeStreaming",
|
||||
migration: "src/config/channel-compat-normalization.ts",
|
||||
replacement: "channels.<id>.streaming.*",
|
||||
docsPath: "/channels/channel-routing",
|
||||
tests: ["src/commands/doctor/shared/channel-legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-tts-provider-aliases",
|
||||
owner: "tts",
|
||||
introduced: "2026-04-26",
|
||||
source: "messages.tts.openai/elevenlabs/edge and plugins.entries.voice-call.config.tts aliases",
|
||||
migration: "src/commands/doctor/shared/legacy-config-migrations.runtime.tts.ts",
|
||||
replacement: "messages.tts.providers.<provider> and microsoft instead of edge",
|
||||
docsPath: "/tools/tts",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-plugin-install-config-ledger",
|
||||
owner: "plugin",
|
||||
introduced: "2026-04-25",
|
||||
source: "plugins.installs in authored config",
|
||||
migration: "src/config/plugin-install-config-migration.ts",
|
||||
replacement: "state-managed plugins/installs.json install ledger",
|
||||
docsPath: "/cli/plugins#registry",
|
||||
tests: [
|
||||
"src/config/io.write-config.test.ts",
|
||||
"src/commands/doctor/shared/plugin-registry-migration.test.ts",
|
||||
],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-bundled-plugin-load-paths",
|
||||
owner: "plugin",
|
||||
introduced: "2026-04-25",
|
||||
source: "plugins.load.paths entries that point at bundled plugin source/dist locations",
|
||||
migration: "src/commands/doctor/shared/bundled-plugin-load-paths.ts",
|
||||
replacement: "packaged bundled plugins and the persisted plugin registry",
|
||||
docsPath: "/cli/plugins#registry",
|
||||
tests: ["src/commands/doctor/shared/bundled-plugin-load-paths.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-web-search-plugin-config",
|
||||
owner: "provider",
|
||||
introduced: "2026-04-26",
|
||||
source: "tools.web.search.apiKey and tools.web.search.<provider>",
|
||||
migration: "src/commands/doctor/shared/legacy-web-search-migrate.ts",
|
||||
replacement: "plugins.entries.<plugin>.config.webSearch",
|
||||
docsPath: "/tools/web",
|
||||
tests: ["src/commands/doctor/shared/legacy-web-search-migrate.test.ts"],
|
||||
notes:
|
||||
"Provider/plugin ownership can move as bundled providers externalize; verify the current manifest owner before deleting migration support.",
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-web-fetch-plugin-config",
|
||||
owner: "provider",
|
||||
introduced: "2026-04-26",
|
||||
source: "tools.web.fetch.firecrawl",
|
||||
migration: "src/commands/doctor/shared/legacy-web-fetch-migrate.ts",
|
||||
replacement: "plugins.entries.firecrawl.config.webFetch",
|
||||
docsPath: "/tools/web-fetch",
|
||||
tests: ["src/commands/doctor/shared/legacy-web-fetch-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-x-search-plugin-config",
|
||||
owner: "provider",
|
||||
introduced: "2026-04-26",
|
||||
source: "tools.web.x_search.apiKey",
|
||||
migration: "src/commands/doctor/shared/legacy-x-search-migrate.ts",
|
||||
replacement: "plugins.entries.xai.config.webSearch.apiKey",
|
||||
docsPath: "/tools/grok-search",
|
||||
tests: [
|
||||
"src/commands/doctor/shared/legacy-x-search-migrate.test.ts",
|
||||
"src/commands/doctor/shared/legacy-config-migrate.test.ts",
|
||||
],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-talk-provider-shape",
|
||||
owner: "tts",
|
||||
introduced: "2026-04-26",
|
||||
source: "legacy talk provider scalar fields and provider/provider ids",
|
||||
migration: "src/commands/doctor/shared/legacy-talk-config-normalizer.ts",
|
||||
replacement: "talk.providers.<provider>",
|
||||
docsPath: "/tools/tts",
|
||||
tests: ["src/commands/doctor/shared/legacy-config-migrate.test.ts"],
|
||||
}),
|
||||
deprecatedCompatRecord({
|
||||
code: "doctor-legacy-tools-by-sender",
|
||||
owner: "tools",
|
||||
introduced: "2026-04-26",
|
||||
source: "untyped toolsBySender keys",
|
||||
migration: "src/commands/doctor/shared/legacy-tools-by-sender.ts",
|
||||
replacement: "typed id:, e164:, username:, or name: sender keys",
|
||||
docsPath: "/tools/exec-approvals",
|
||||
tests: ["src/commands/doctor/shared/legacy-tools-by-sender.test.ts"],
|
||||
}),
|
||||
] as const satisfies readonly DoctorDeprecationCompatRecord[];
|
||||
|
||||
export type DoctorDeprecationCompatCode =
|
||||
(typeof DOCTOR_DEPRECATION_COMPAT_RECORDS)[number]["code"];
|
||||
export type KnownDoctorDeprecationCompatRecord =
|
||||
DoctorDeprecationCompatRecord<DoctorDeprecationCompatCode>;
|
||||
|
||||
const doctorDeprecationCompatRecordByCode = new Map<
|
||||
DoctorDeprecationCompatCode,
|
||||
KnownDoctorDeprecationCompatRecord
|
||||
>(DOCTOR_DEPRECATION_COMPAT_RECORDS.map((record) => [record.code, record]));
|
||||
|
||||
export function listDoctorDeprecationCompatRecords(): readonly KnownDoctorDeprecationCompatRecord[] {
|
||||
return DOCTOR_DEPRECATION_COMPAT_RECORDS;
|
||||
}
|
||||
|
||||
export function listDeprecatedDoctorDeprecationCompatRecords(): readonly KnownDoctorDeprecationCompatRecord[] {
|
||||
return DOCTOR_DEPRECATION_COMPAT_RECORDS.filter((record) =>
|
||||
(["deprecated", "removal-pending"] as readonly string[]).includes(record.status),
|
||||
);
|
||||
}
|
||||
|
||||
export function isDoctorDeprecationCompatCode(code: string): code is DoctorDeprecationCompatCode {
|
||||
return doctorDeprecationCompatRecordByCode.has(code as DoctorDeprecationCompatCode);
|
||||
}
|
||||
|
||||
export function getDoctorDeprecationCompatRecord(
|
||||
code: DoctorDeprecationCompatCode,
|
||||
): KnownDoctorDeprecationCompatRecord {
|
||||
const record = doctorDeprecationCompatRecordByCode.get(code);
|
||||
if (!record) {
|
||||
throw new Error(`Unknown doctor deprecation compatibility code: ${code}`);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
@@ -90,6 +90,31 @@ const knownDeprecatedSurfaceMarkers = [
|
||||
file: "src/plugin-sdk/test-utils.ts",
|
||||
marker: "Deprecated compatibility alias",
|
||||
},
|
||||
{
|
||||
code: "plugin-install-config-ledger",
|
||||
file: "src/config/plugin-install-config-migration.ts",
|
||||
marker: "stripShippedPluginInstallConfigRecords",
|
||||
},
|
||||
{
|
||||
code: "bundled-plugin-load-path-aliases",
|
||||
file: "src/commands/doctor/shared/bundled-plugin-load-paths.ts",
|
||||
marker: "plugins.load.paths",
|
||||
},
|
||||
{
|
||||
code: "plugin-owned-web-search-config",
|
||||
file: "src/commands/doctor/shared/legacy-web-search-migrate.ts",
|
||||
marker: "tools.web.search",
|
||||
},
|
||||
{
|
||||
code: "plugin-owned-web-fetch-config",
|
||||
file: "src/commands/doctor/shared/legacy-web-fetch-migrate.ts",
|
||||
marker: "tools.web.fetch.firecrawl",
|
||||
},
|
||||
{
|
||||
code: "plugin-owned-x-search-config",
|
||||
file: "src/commands/doctor/shared/legacy-x-search-migrate.ts",
|
||||
marker: "tools.web.x_search",
|
||||
},
|
||||
] as const;
|
||||
|
||||
function parseDate(date: string): Date {
|
||||
|
||||
@@ -267,6 +267,82 @@ export const PLUGIN_COMPAT_RECORDS = [
|
||||
diagnostics: ["postinstall migration skip", "postinstall migration force deprecation warning"],
|
||||
tests: ["src/commands/doctor/shared/plugin-registry-migration.test.ts"],
|
||||
},
|
||||
{
|
||||
code: "plugin-install-config-ledger",
|
||||
status: "deprecated",
|
||||
owner: "config",
|
||||
introduced: "2026-04-25",
|
||||
deprecated: "2026-04-26",
|
||||
warningStarts: "2026-04-26",
|
||||
removeAfter: "2026-07-26",
|
||||
replacement: "state-managed `plugins/installs.json` install ledger",
|
||||
docsPath: "/cli/plugins#registry",
|
||||
surfaces: ["plugins.installs authored config", "plugin install/update migration"],
|
||||
diagnostics: ["config write migration warning", "doctor registry migration"],
|
||||
tests: [
|
||||
"src/config/io.write-config.test.ts",
|
||||
"src/commands/doctor/shared/plugin-registry-migration.test.ts",
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "bundled-plugin-load-path-aliases",
|
||||
status: "deprecated",
|
||||
owner: "config",
|
||||
introduced: "2026-04-25",
|
||||
deprecated: "2026-04-26",
|
||||
warningStarts: "2026-04-26",
|
||||
removeAfter: "2026-07-26",
|
||||
replacement: "packaged bundled plugins resolved through the persisted plugin registry",
|
||||
docsPath: "/cli/plugins#registry",
|
||||
surfaces: ["plugins.load.paths entries pointing at bundled plugin source/dist paths"],
|
||||
diagnostics: ["doctor bundled plugin load-path warning"],
|
||||
tests: ["src/commands/doctor/shared/bundled-plugin-load-paths.test.ts"],
|
||||
},
|
||||
{
|
||||
code: "plugin-owned-web-search-config",
|
||||
status: "deprecated",
|
||||
owner: "provider",
|
||||
introduced: "2026-04-26",
|
||||
deprecated: "2026-04-26",
|
||||
warningStarts: "2026-04-26",
|
||||
removeAfter: "2026-07-26",
|
||||
replacement: "`plugins.entries.<plugin>.config.webSearch`",
|
||||
docsPath: "/tools/web",
|
||||
surfaces: ["tools.web.search.apiKey", "tools.web.search.<provider>"],
|
||||
diagnostics: ["doctor legacy web-search config migration"],
|
||||
tests: ["src/commands/doctor/shared/legacy-web-search-migrate.test.ts"],
|
||||
},
|
||||
{
|
||||
code: "plugin-owned-web-fetch-config",
|
||||
status: "deprecated",
|
||||
owner: "provider",
|
||||
introduced: "2026-04-26",
|
||||
deprecated: "2026-04-26",
|
||||
warningStarts: "2026-04-26",
|
||||
removeAfter: "2026-07-26",
|
||||
replacement: "`plugins.entries.firecrawl.config.webFetch`",
|
||||
docsPath: "/tools/web-fetch",
|
||||
surfaces: ["tools.web.fetch.firecrawl"],
|
||||
diagnostics: ["doctor legacy web-fetch config migration"],
|
||||
tests: ["src/commands/doctor/shared/legacy-web-fetch-migrate.test.ts"],
|
||||
},
|
||||
{
|
||||
code: "plugin-owned-x-search-config",
|
||||
status: "deprecated",
|
||||
owner: "provider",
|
||||
introduced: "2026-04-26",
|
||||
deprecated: "2026-04-26",
|
||||
warningStarts: "2026-04-26",
|
||||
removeAfter: "2026-07-26",
|
||||
replacement: "`plugins.entries.xai.config.webSearch.apiKey`",
|
||||
docsPath: "/tools/grok-search",
|
||||
surfaces: ["tools.web.x_search.apiKey"],
|
||||
diagnostics: ["doctor legacy x_search config migration"],
|
||||
tests: [
|
||||
"src/commands/doctor/shared/legacy-x-search-migrate.test.ts",
|
||||
LEGACY_CONFIG_MIGRATE_TEST_PATH,
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "plugin-activate-entrypoint-alias",
|
||||
status: "deprecated",
|
||||
|
||||
Reference in New Issue
Block a user