From e9e4b6704cabd82c5437ce3c7345b8f99e33a687 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 28 Apr 2026 13:24:09 -0700 Subject: [PATCH] fix(synthetic): classify kitchen-sink registrars --- CHANGELOG.md | 6 ++ package.json | 2 +- src/synthetic-probes.js | 140 ++++++++++++++++++++++++++++++++++ test/synthetic-probes.test.js | 69 +++++++++++++++++ 4 files changed, 216 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1550e6d..45fb73d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +## 0.3.3 - 2026-04-28 + +### Fixed + +- Classify generated kitchen-sink public registrar coverage in synthetic probe plans so new API-surface fixtures do not fail as unknown execution profiles. + ## 0.3.2 - 2026-04-28 ### Fixed diff --git a/package.json b/package.json index 2faed3e..4f28294 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@openclaw/plugin-inspector", - "version": "0.3.2", + "version": "0.3.3", "private": false, "description": "Offline compatibility inspector for OpenClaw plugins.", "type": "module", diff --git a/src/synthetic-probes.js b/src/synthetic-probes.js index 5b0139a..50914a1 100644 --- a/src/synthetic-probes.js +++ b/src/synthetic-probes.js @@ -16,19 +16,64 @@ export const syntheticRegistrationExecutionProfiles = { callableProperties: ["send", "sendMessage", "receive", "handleMessage"], option: "includeChannelRuntime", }, + registerAgentHarness: { + mode: "metadata-only", + callableProperties: [], + reason: "agent harness factories are captured as registration metadata; agent runtime execution remains isolated opt-in", + }, + registerAgentToolResultMiddleware: { + mode: "metadata-only", + callableProperties: [], + reason: "agent tool-result middleware is captured as registration metadata before tool-result pipeline execution", + }, + registerAutoEnableProbe: { + mode: "metadata-only", + callableProperties: [], + reason: "auto-enable probes are captured as registration metadata before runtime activation checks", + }, registerCli: { mode: "direct", callableProperties: ["handler", "run", "execute"], }, + registerCliBackend: { + mode: "metadata-only", + callableProperties: [], + reason: "CLI backend descriptors are captured as registration metadata before backend process execution", + }, registerCommand: { mode: "direct", callableProperties: ["handler", "run", "execute"], }, + registerCodexAppServerExtensionFactory: { + mode: "metadata-only", + callableProperties: [], + reason: "Codex app server extension factories are captured as registration metadata before host UI execution", + }, + registerCompactionProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "compaction providers are captured as registration metadata before compaction runtime execution", + }, + registerConfigMigration: { + mode: "metadata-only", + callableProperties: [], + reason: "config migrations are captured as registration metadata before mutating stored plugin config", + }, registerContextEngine: { mode: "metadata-only", callableProperties: [], reason: "context engine factories are captured as registration metadata; engine startup remains isolated opt-in", }, + registerDetachedTaskRuntime: { + mode: "metadata-only", + callableProperties: [], + reason: "detached task runtimes are captured as registration metadata before async task execution", + }, + registerGatewayDiscoveryService: { + mode: "metadata-only", + callableProperties: [], + reason: "gateway discovery services are captured as registration metadata before network discovery execution", + }, registerGatewayMethod: { mode: "direct", callableProperties: ["handler", "run", "execute", "invoke"], @@ -46,16 +91,91 @@ export const syntheticRegistrationExecutionProfiles = { callableProperties: [], reason: "legacy hook registrar is captured as metadata; hook handlers are probed through hook events", }, + registerImageGenerationProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "image generation providers are captured as registration metadata before provider runtime execution", + }, registerMemoryPromptSection: { mode: "metadata-only", callableProperties: [], reason: "memory prompt section renderers are captured as metadata before prompt-runtime execution", }, + registerMediaUnderstandingProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "media understanding providers are captured as registration metadata before provider runtime execution", + }, + registerMemoryCapability: { + mode: "metadata-only", + callableProperties: [], + reason: "memory capabilities are captured as registration metadata before memory runtime execution", + }, + registerMemoryCorpusSupplement: { + mode: "metadata-only", + callableProperties: [], + reason: "memory corpus supplements are captured as registration metadata before memory runtime execution", + }, + registerMemoryEmbeddingProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "memory embedding providers are captured as registration metadata before provider runtime execution", + }, + registerMemoryFlushPlan: { + mode: "metadata-only", + callableProperties: [], + reason: "memory flush plans are captured as registration metadata before memory runtime execution", + }, registerMemoryRuntime: { mode: "metadata-only", callableProperties: [], reason: "memory runtime factories are captured as metadata; external memory startup remains isolated opt-in", }, + registerMemoryPromptSupplement: { + mode: "metadata-only", + callableProperties: [], + reason: "memory prompt supplements are captured as registration metadata before prompt-runtime execution", + }, + registerMigrationProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "migration providers are captured as registration metadata before migration runtime execution", + }, + registerMusicGenerationProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "music generation providers are captured as registration metadata before provider runtime execution", + }, + registerNodeHostCommand: { + mode: "metadata-only", + callableProperties: [], + reason: "node host commands are captured as registration metadata before host process execution", + }, + registerProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "provider descriptors are captured as registration metadata before provider runtime execution", + }, + registerRealtimeTranscriptionProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "realtime transcription providers are captured as registration metadata before provider runtime execution", + }, + registerRealtimeVoiceProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "realtime voice providers are captured as registration metadata before provider runtime execution", + }, + registerReload: { + mode: "metadata-only", + callableProperties: [], + reason: "reload handlers are captured as registration metadata before runtime reload execution", + }, + registerSecurityAuditCollector: { + mode: "metadata-only", + callableProperties: [], + reason: "security audit collectors are captured as registration metadata before filesystem or policy scans", + }, registerService: { mode: "lifecycle-opt-in", callableProperties: ["start", "stop", "dispose"], @@ -70,6 +190,26 @@ export const syntheticRegistrationExecutionProfiles = { mode: "direct", callableProperties: ["run", "handler", "execute"], }, + registerTextTransforms: { + mode: "metadata-only", + callableProperties: [], + reason: "text transforms are captured as registration metadata before content mutation execution", + }, + registerVideoGenerationProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "video generation providers are captured as registration metadata before provider runtime execution", + }, + registerWebFetchProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "web fetch providers are captured as registration metadata before provider runtime execution", + }, + registerWebSearchProvider: { + mode: "metadata-only", + callableProperties: [], + reason: "web search providers are captured as registration metadata before provider runtime execution", + }, }; export const defaultSyntheticHookEvents = { diff --git a/test/synthetic-probes.test.js b/test/synthetic-probes.test.js index 5cf0cf8..fa769df 100644 --- a/test/synthetic-probes.test.js +++ b/test/synthetic-probes.test.js @@ -103,6 +103,75 @@ test("synthetic probe plan blocks unclassified registrars", () => { assert.match(validateSyntheticProbePlan(plan).join("\n"), /not been classified/); }); +test("synthetic probe plan classifies generated kitchen-sink registrars", () => { + const kitchenSinkRegistrars = [ + "registerAgentHarness", + "registerAgentToolResultMiddleware", + "registerAutoEnableProbe", + "registerChannel", + "registerCli", + "registerCliBackend", + "registerCodexAppServerExtensionFactory", + "registerCommand", + "registerCompactionProvider", + "registerConfigMigration", + "registerContextEngine", + "registerDetachedTaskRuntime", + "registerGatewayDiscoveryService", + "registerGatewayMethod", + "registerHook", + "registerHttpRoute", + "registerImageGenerationProvider", + "registerInteractiveHandler", + "registerMediaUnderstandingProvider", + "registerMemoryCapability", + "registerMemoryCorpusSupplement", + "registerMemoryEmbeddingProvider", + "registerMemoryFlushPlan", + "registerMemoryPromptSection", + "registerMemoryPromptSupplement", + "registerMemoryRuntime", + "registerMigrationProvider", + "registerMusicGenerationProvider", + "registerNodeHostCommand", + "registerProvider", + "registerRealtimeTranscriptionProvider", + "registerRealtimeVoiceProvider", + "registerReload", + "registerSecurityAuditCollector", + "registerService", + "registerSpeechProvider", + "registerTextTransforms", + "registerTool", + "registerVideoGenerationProvider", + "registerWebFetchProvider", + "registerWebSearchProvider", + ]; + const plan = buildSyntheticProbePlan({ + capture: { + generatedAt: "test", + summary: { fixtureCount: 1 }, + fixtures: [ + { + id: "kitchen-sink", + hooks: [], + registrations: kitchenSinkRegistrars.map((registrar) => ({ + id: `registration.${registrar}:kitchen-sink:index`, + registrar, + ref: "src/generated-registrars.js", + assertions: [`${registrar} is classified`], + syntheticArguments: [{}], + })), + }, + ], + }, + }); + + assert.equal(plan.summary.probeCount, kitchenSinkRegistrars.length); + assert.equal(plan.summary.blockedCount, 0); + assert.deepEqual(validateSyntheticProbePlan(plan), []); +}); + test("synthetic probes invoke retained hook and tool handlers", async () => { const capture = await captureLocalFixture([ "export function register(api) {",