From 5ea07a8fca0f7451d22198aa216de9fe4ea94d7a Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 28 Apr 2026 00:45:47 -0700 Subject: [PATCH] docs: rewrite plugin-inspector README --- README.md | 409 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 285 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index 0ed0105..fa51278 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,42 @@ +OpenClaw Plugin Inspector banner + # OpenClaw Plugin Inspector -`@openclaw/plugin-inspector` checks an OpenClaw plugin package before it reaches -users. It is meant to answer practical compatibility questions: +`@openclaw/plugin-inspector` is the offline compatibility checker for OpenClaw +plugin packages and plugin fixture suites. -- Can OpenClaw discover this plugin package and manifest? -- Which SDK imports, hooks, and registration calls does the plugin use? -- Will the plugin still load in clean CI without local OpenClaw internals? -- What report artifacts should CI upload when compatibility breaks? +It answers the questions that matter before a plugin reaches users: -The default check is static, offline, and credential-free. Runtime capture is -available, but it is always explicit because it imports plugin code. +- can OpenClaw discover the package metadata and `openclaw.plugin.json` + manifest? +- which hooks, registration calls, manifest contracts, and SDK imports does the + plugin use? +- does the plugin still look compatible without local OpenClaw internals? +- if CI finds a breakage, which JSON, Markdown, SARIF, JUnit, and summary + artifacts should downstream automation read? +- when a fixture-suite harness such as Crabpot runs many plugins, which findings + are hard breakages, known warnings, live issues, deprecations, or inspector + proof gaps? -## When To Use It - -Use the plugin-root workflow for normal plugin repositories: - -```bash -npx @openclaw/plugin-inspector inspect --no-openclaw -``` - -Use fixture suites only when one repository is intentionally checking many -plugins, such as Crabpot: - -```bash -plugin-inspector report --config crabpot.config.json --out reports -``` - -Most plugin authors should start with `inspect --no-openclaw`, then add -`init --ci --scripts` once the local check makes sense. +The default path is static, offline, and credential-free. Runtime capture exists, +but it is opt-in because it imports plugin code. ## Requirements - Node.js 22 or newer. - A plugin package root with `package.json`. -- An `openclaw.plugin.json` manifest when the plugin uses the manifest contract. +- `openclaw.plugin.json` when the plugin uses the OpenClaw manifest contract. +- No OpenClaw checkout, credentials, network service, or live provider access for + default inspection. -OpenClaw itself is optional. Pass `--no-openclaw` when CI should not compare -against a local OpenClaw checkout. +Pass `--no-openclaw` when CI should not compare against a local OpenClaw +checkout. If an OpenClaw checkout is supplied with `--openclaw `, the +inspector only reads public compatibility surfaces such as compat records, SDK +exports, hook names, manifest fields, and registrar metadata. -## First Check +## Quick Start -From a plugin package directory: +Run this from a plugin package root: ```bash npx @openclaw/plugin-inspector inspect --no-openclaw @@ -60,12 +56,13 @@ The command writes: - `reports/plugin-inspector-report.md` - `reports/plugin-inspector-issues.md` -It exits non-zero when compatibility breakages are found. Warnings and -suggestions stay visible in the reports without necessarily failing the command. +It exits non-zero when hard compatibility breakages are found. Warnings, +suggestions, issue classifications, and logs stay visible in the report without +necessarily failing the command. -## Add It To A Plugin Repo +## Install In A Plugin Repo -Install the package when you want local scripts and repeatable CI: +Install the package when you want repeatable local scripts and CI: ```bash npm install --save-dev @openclaw/plugin-inspector @@ -88,7 +85,7 @@ Then run: npm run plugin:check ``` -Or let the inspector write the starting config, package scripts, and GitHub +The initializer can write the starter config, package scripts, and GitHub Actions workflow: ```bash @@ -96,8 +93,9 @@ npx @openclaw/plugin-inspector init --ci --scripts --dry-run npx @openclaw/plugin-inspector init --ci --scripts ``` -`init` detects `packageManager` and common lockfiles. Override that detection -with `--package-manager npm`, `pnpm`, `yarn`, or `bun`. +`init` detects `packageManager` and common lockfiles. Override that with +`--package-manager npm`, `--package-manager pnpm`, `--package-manager yarn`, or +`--package-manager bun`. Existing files are protected unless you pass `--force`. ## Configuration @@ -106,7 +104,8 @@ Small plugin repos can keep configuration in `package.json`: ```json { "scripts": { - "plugin:check": "plugin-inspector inspect --no-openclaw" + "plugin:check": "plugin-inspector inspect --no-openclaw", + "plugin:ci": "plugin-inspector ci --no-openclaw --runtime --mock-sdk --allow-execute" }, "pluginInspector": { "version": 1, @@ -114,7 +113,10 @@ Small plugin repos can keep configuration in `package.json`: "id": "weather", "priority": "high", "seams": ["dynamic-tool"], - "sourceRoot": "src" + "sourceRoot": "src", + "expect": { + "registrations": ["registerTool"] + } }, "capture": { "mockSdk": true @@ -123,7 +125,7 @@ Small plugin repos can keep configuration in `package.json`: } ``` -Use `plugin-inspector.config.json` when you want a standalone config file: +Use `plugin-inspector.config.json` for a standalone config file: ```json { @@ -146,18 +148,94 @@ Use `plugin-inspector.config.json` when you want a standalone config file: } ``` -Check what the inspector resolved before wiring CI: +Inspect the resolved config before wiring CI: ```bash plugin-inspector config --json ``` -Copy-ready config examples live in: +Copy-ready examples live in: - `examples/plugin-inspector.config.json` - `examples/package-json-plugin-inspector.json` -## CI Setup +## Commands + +| Command | Purpose | +| --- | --- | +| `plugin-inspector` | Default alias for `check`. | +| `plugin-inspector check` | Script-friendly plugin-root check. | +| `plugin-inspector inspect` | Plugin-root check unless `--config` is supplied; with `--config`, runs a fixture report. | +| `plugin-inspector ci` | Compatibility report plus CI summary, SARIF, and JUnit outputs. | +| `plugin-inspector config` | Print resolved plugin-root config as text or JSON. | +| `plugin-inspector init` | Write starter config, scripts, and optional GitHub Actions workflow. | +| `plugin-inspector report` | Run a fixture-suite config with many plugins. | +| `plugin-inspector capture` | Runtime-capture one entrypoint directly. | + +Common options: + +| Option | Meaning | +| --- | --- | +| `--plugin-root ` / `--root ` | Check a plugin somewhere other than the current directory. | +| `--config ` | Read a standalone config file. Required for fixture-suite `report`. | +| `--out ` | Write reports somewhere other than `reports/`. | +| `--openclaw ` | Compare against a local OpenClaw checkout. | +| `--no-openclaw` | Disable OpenClaw checkout comparison. | +| `--runtime` / `--capture` | Add opt-in runtime registration capture. | +| `--no-runtime` / `--no-capture` | Disable runtime capture even when config enables it. | +| `--mock-sdk` / `--sdk mock` | Use generated SDK and external-package mocks for runtime capture. | +| `--real-sdk` / `--sdk real` | Use installed real SDK dependencies instead of mocks. | +| `--allow-execute` | Permit commands that import plugin code. | +| `--json` | Print machine-readable JSON to stdout. | +| `--sarif [path]` | Write SARIF from `check` or `inspect`; `ci` enables this by default. | +| `--junit [path]` | Write JUnit XML from `check` or `inspect`; `ci` enables this by default. | +| `--no-sarif` / `--no-junit` | Disable default `ci` outputs. | + +Run the built-in help for the exact CLI surface: + +```bash +plugin-inspector --help +``` + +## Runtime Capture + +Runtime capture imports plugin entrypoints in an isolated subprocess and records +what `register(api)` does. Use it when static inspection cannot prove the actual +registrations made at runtime. + +```bash +plugin-inspector inspect --no-openclaw --runtime --mock-sdk --allow-execute +``` + +`--allow-execute` is the deliberate safety switch. Without it, modes that import +plugin code fail closed. The older environment guard still works for custom +harnesses: + +```bash +PLUGIN_INSPECTOR_EXECUTE_ISOLATED=1 plugin-inspector inspect --no-openclaw --runtime --mock-sdk +``` + +By default, runtime capture uses generated mocks for `openclaw/plugin-sdk` +subpaths and unresolved external packages discovered in the plugin import graph. +That keeps compatibility CI offline and credential-free. It does not call live +services, launch OpenClaw, run provider SDKs, or emulate service lifecycle side +effects. + +Use `--real-sdk` only when the plugin workspace already has real SDK +dependencies installed and you intentionally want that path. + +Runtime capture writes: + +- `reports/plugin-inspector-runtime-capture.json` +- `reports/plugin-inspector-runtime-capture.md` + +Capture one entrypoint directly: + +```bash +plugin-inspector capture ./dist/index.js --mock-sdk --allow-execute +``` + +## CI `plugin-inspector ci` writes the normal compatibility report plus CI-native summary, SARIF, and JUnit artifacts. @@ -190,7 +268,7 @@ jobs: path: reports/plugin-inspector-* ``` -Generated CI artifacts include: +Generated `ci` artifacts: - `reports/plugin-inspector-report.json` - `reports/plugin-inspector-report.md` @@ -200,83 +278,109 @@ Generated CI artifacts include: - `reports/plugin-inspector.sarif` - `reports/plugin-inspector.junit.xml` -Use `--no-sarif` or `--no-junit` only if your CI surface cannot consume those -formats. - -More examples: +CI examples: - `examples/github-actions-plugin-inspector.yml` - `examples/github-actions-code-scanning.yml` - `examples/gitlab-ci-plugin-inspector.yml` - `examples/circleci-plugin-inspector.yml` -## Runtime Capture +## Report Surfaces -Runtime capture imports plugin entrypoints in an isolated subprocess and records -what `register(api)` does. Use it when static inspection cannot show the actual -registrations your plugin makes at runtime. +The compatibility report is the primary contract. Preserve field names and +finding codes because downstream CI and Crabpot reports may consume them. -```bash -plugin-inspector inspect --no-openclaw --runtime --mock-sdk --allow-execute -``` +Important report sections: -`--allow-execute` is the deliberate safety switch. Without it, modes that import -plugin code fail closed. The older `PLUGIN_INSPECTOR_EXECUTE_ISOLATED=1` -environment guard still works for custom harnesses. - -By default, runtime capture uses generated mocks for `openclaw/plugin-sdk` -subpaths and unresolved external packages discovered in the plugin import graph. -That lets compatibility CI run without OpenClaw installed. - -Use `--real-sdk` only when the plugin workspace already has real SDK -dependencies installed and you intentionally want that path. - -Runtime capture writes: - -- `reports/plugin-inspector-runtime-capture.json` -- `reports/plugin-inspector-runtime-capture.md` - -Capture one entrypoint directly: - -```bash -plugin-inspector capture ./dist/index.js --mock-sdk --allow-execute -``` - -## Command Reference - -| Command | Use it when | +| Field | Meaning | | --- | --- | -| `plugin-inspector inspect` | You are checking one plugin package. | -| `plugin-inspector check` | You need the older script-friendly alias for `inspect`. | -| `plugin-inspector ci` | You want reports plus CI summary, SARIF, and JUnit outputs. | -| `plugin-inspector config` | You want to inspect resolved config before running CI. | -| `plugin-inspector init` | You want starter config, scripts, and CI workflow files. | -| `plugin-inspector report` | You are running a fixture-suite config with many plugins. | -| `plugin-inspector capture` | You want runtime capture for one entrypoint. | +| `status` | `pass` unless hard breakages exist. | +| `summary` | Counts for fixtures, breakages, warnings, suggestions, issues, issue classes, and contract probes. | +| `targetOpenClaw` | Status and public compatibility data read from the optional OpenClaw checkout. | +| `fixtures` | Per-plugin metadata, hooks, registrations, manifest contracts, package data, and SDK imports. | +| `breakages` | Blocking compatibility failures. | +| `warnings` / `suggestions` | Non-blocking compatibility findings. | +| `issues` | Normalized issue rows with severity and class. | +| `contractProbes` | Suggested synthetic probes derived from observed contracts. | +| `logs` | Informational inventory and coverage rows. | +| `decisions` | Maintainer-facing follow-up or compatibility-policy decisions. | -Useful options: +Issue classes currently flow through the reports as live issues, compat gaps, +deprecation warnings, inspector gaps, upstream metadata, and fixture regressions. -| Option | Meaning | -| --- | --- | -| `--plugin-root ` | Check a plugin somewhere other than the current directory. | -| `--config ` | Read a standalone config file. | -| `--out ` | Write reports somewhere other than `reports/`. | -| `--no-openclaw` | Skip comparison against a local OpenClaw checkout. | -| `--runtime` | Add opt-in runtime registration capture. | -| `--mock-sdk` | Use generated SDK and external-package mocks for runtime capture. | -| `--real-sdk` | Use installed real SDK dependencies instead of mocks. | -| `--allow-execute` | Permit commands that import plugin code. | +## CI Policy And Shared Reporting Primitives -Run the built-in help for the complete flag list: +`plugin-inspector` owns the shared CI policy and report rendering primitives. +Fixture-suite harnesses such as Crabpot should call these exports instead of +reimplementing scoring, summaries, Markdown, SARIF, or JUnit handling. -```bash -plugin-inspector --help +The root API exposes grouped helpers: + +```js +import { ci } from "@openclaw/plugin-inspector"; + +const policyReport = ci.buildPolicyReport({ + policy, + compatibilityReport, + executionResults, + strict: false, +}); + +await ci.writePolicyReport(policyReport); ``` -## Embedding In A Harness +CI policy reports default to: -Most plugin repos should use the CLI. Test harnesses can import grouped helpers -from the root package when they need to compose inspector workflows directly: +- `reports/plugin-inspector-ci-policy.json` +- `reports/plugin-inspector-ci-policy.md` + +A policy must use `version: 1` and define: + +- `allowedBlocked` +- `expectedWarnings` +- `thresholds` +- `fixtureSets` + +Policy scoring fails hard breakages, unknown blocked synthetic probes, hard ref +diff regressions, failed execution results, strict live P0 issues, and strict +classified blockers. Non-strict mode keeps classified blocked probes and live P0 +issues visible as warnings. + +CI summary helpers read the known report set from `reports/` and render one +machine-readable and one Markdown rollup: + +- compatibility +- runtime capture +- synthetic probes +- cold import readiness +- workspace plan +- platform probes +- import-loop profile +- execution results +- runtime profile +- ref diff +- profile diff +- CI policy + +## Fixture Suites + +Most plugin authors should use the plugin-root workflow. Use fixture suites when +one repository intentionally checks many plugins or packages, as Crabpot does. + +```bash +plugin-inspector report --config crabpot.config.json --out reports +plugin-inspector report --config crabpot.config.json --out reports --check +plugin-inspector ci --config crabpot.config.json --out reports --no-openclaw +``` + +Fixture-suite configs are loaded through the explicit fixture helpers. That keeps +normal plugin-root configuration simple while still supporting bulk compatibility +harnesses. + +## Public API + +Prefer the CLI for normal plugin repositories. Import the public API when a test +harness needs to compose workflows directly: ```js import { pluginRoot } from "@openclaw/plugin-inspector"; @@ -290,31 +394,88 @@ const { report, paths } = await pluginRoot.runCheck({ console.log(report.status, paths.jsonPath); ``` -The root package groups stable workflows as `pluginRoot`, `fixtureSuites`, -`staticInspection`, `reports`, `contracts`, `ci`, `runtime`, and `synthetic`. -Named exports remain available for existing automation. +Stable grouped facades: -## What The Mock SDK Does +| Facade | Use | +| --- | --- | +| `pluginRoot` | Load config, inspect, run checks, capture entrypoints, or set up a plugin repo. | +| `fixtureSuites` | Load fixture-suite configs, run reports, and build fixture-suite readiness plans. | +| `staticInspection` | Inspect source text or fixture sets without the compatibility report layer. | +| `reports` | Render/write reports and classify issue findings. | +| `contracts` | Build, render, validate, and write contract captures and coverage. | +| `ci` | Build summaries, policy reports, execution results, SARIF, and JUnit outputs. | +| `runtime` | Build runtime profiles, profile diffs, ref diffs, and import-loop profiles. | +| `synthetic` | Build and run synthetic probe plans. | -The mock lane is for compatibility CI, not live service testing. +Named exports remain available for existing automation. Prefer the grouped +facades for new code because they show ownership and keep downstream wrappers +thin. -When `--mock-sdk` is enabled, the inspector generates temporary modules for -`openclaw/plugin-sdk` subpaths and unresolved external packages. The mock SDK -captures registrations; it does not call network services, launch OpenClaw, run -provider SDKs, or emulate service lifecycle side effects. +## Development -Keep live provider/service tests in the plugin repository behind credentials -and explicit opt-in flags. +Repository checks are intentionally small and offline: -## Scope +```bash +npm test +npm run release:contents +npm run check +``` -Default inspection reads manifests, package metadata, and source files, then -reports observed `api.on(...)`, `api.register*`, `define*`, SDK imports, and -manifest contracts. +`npm run check` runs the Node test suite and the package-contents guard. The +contents guard shells through `npm pack --dry-run --json` and verifies the npm +tarball includes package entrypoints, examples, README assets, and no private +`test/`, `scripts/`, or `.github/` paths. -OpenClaw target checkout parsing is limited to public compatibility registries, -SDK package exports, manifest types, hooks, and captured registrar metadata. +Useful release-prep commands: -Cold import capture, synthetic contract probes, runtime capture, and live lanes -are separate opt-in modes. Live lanes must stay credential-gated and should not -run in default CI. +```bash +npm run release:local +npm run release:readiness +npm run release:notes +npm run release:plan +npm run release:crabpot -- --crabpot ../crabpot +``` + +`release:readiness` proves the local package and verifies Crabpot follow-through. +It does not publish. + +Keep this package dependency-light. Do not add runtime dependencies unless they +remove real complexity. Default checks must stay offline and credential-free. + +## Release Notes + +The package publishes from annotated `v*` tags through GitHub Actions. The +release workflow runs the test suite, verifies the npm tarball, publishes the +GitHub release, and publishes the public npm package through npm trusted +publishing. + +Before tagging a release: + +1. Move `CHANGELOG.md` `Unreleased` notes into a versioned section. +2. Update `package.json` to the same version. +3. Update Crabpot's `pluginInspectorRef` to the release commit. +4. Run `npm run release:readiness`. +5. Run the Crabpot plugin-inspector smoke commands printed by + `npm run release:crabpot -- --crabpot ../crabpot`. + +After npm publish, update Crabpot's package pin and run: + +```bash +npm run release:crabpot -- --crabpot ../crabpot --published +``` + +Do not publish npm packages without explicit owner approval. + +## Contribution Notes + +There is no `CONTRIBUTING.md` in this repository. Until one exists, use the repo +scripts above as the local contract and follow these project rules: + +- preserve stable report field names and finding codes; +- prefer public OpenClaw plugin contracts over core internals; +- isolate any OpenClaw source parsing behind explicit helpers; +- keep runtime execution behind `--allow-execute` or + `PLUGIN_INSPECTOR_EXECUTE_ISOLATED=1`; +- when behavior, entrypoints, release metadata, or the npm package version + change, update Crabpot's `@openclaw/plugin-inspector` pin/docs/smoke path and + run the Crabpot plugin-inspector smoke before calling the work done.