Skip to content

fix(doctor): discover load-path plugin contracts#77477

Merged
jalehman merged 7 commits into
openclaw:mainfrom
jalehman:doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery
May 6, 2026
Merged

fix(doctor): discover load-path plugin contracts#77477
jalehman merged 7 commits into
openclaw:mainfrom
jalehman:doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery

Conversation

@jalehman

@jalehman jalehman commented May 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes OpenClaw doctor so plugin doctor contract sidecars are discovered for explicit filesystem plugins loaded via plugins.load.paths.

This matters for plugins like Lossless Claw during local/checkout-based development: the runtime can load the plugin successfully, but openclaw doctor previously built its doctor-contract registry from the installed/persisted plugin registry without the active config, so load-path plugins were invisible to doctor.

What changed

  • Pass active config into plugin doctor contract discovery so plugins.load.paths plugins are included.
  • Pass active config through doctor warning collection.
  • Extend doctor --fix compatibility migration collection so configured plugin entries, not just channel ids, can contribute plugin doctor normalizers.
  • Add focused coverage for load-path plugin doctor sidecars and non-channel plugin fix paths.

Validation

pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/plugins/doctor-contract-registry.ts src/plugins/doctor-contract-registry.load-paths.test.ts src/channels/plugins/legacy-config.ts src/commands/doctor/shared/legacy-config-issues.ts src/commands/doctor/shared/channel-legacy-config-migrate.ts src/commands/doctor/shared/channel-legacy-config-migrate.test.ts
# Passed

pnpm test src/plugins/doctor-contract-registry.test.ts src/plugins/doctor-contract-registry.load-paths.test.ts src/commands/doctor/shared/channel-legacy-config-migrate.test.ts -- --reporter=verbose
# Passed: 12 tests across 3 files

pnpm build
# Passed

Manual combined-branch validation with Lossless PR #600:

  • pnpm openclaw doctor now shows Lossless warnings for summaryModel and fallbackProviders requiring plugins.entries.lossless-claw.llm.allowModelOverride / allowedModels.
  • A temp-config doctor --fix run adds allowModelOverride: true and the configured allowedModels, without adding allowAgentIdOverride.

Real behavior proof

  • Behavior or issue addressed: openclaw doctor / openclaw doctor --fix now discovers doctor contract sidecars from explicit plugins.load.paths plugins. This lets load-path plugins such as lossless-claw surface legacy config warnings and lets doctor --fix apply plugin-owned normalizers before validation, instead of only considering unresolved channel ids.

  • Real environment tested: Josh’s local OpenClaw checkout on macOS, using the real OpenClaw CLI and real configured Lossless plugin entry. The destructive fix path was tested against a copied temp config so Josh’s real config was not modified.

  • Exact steps or command run after this patch:

    pnpm openclaw doctor | rg -i "lossless|allowModelOverride|allowedModels|summaryModel|fallbackProviders"
    
    OPENCLAW_CONFIG_PATH="$tmp/openclaw.json" pnpm openclaw doctor --fix --non-interactive
    
    node -e '<inspect temp copied config>'
  • Evidence after fix:

    Plain `pnpm openclaw doctor` reported Lossless warnings for `summaryModel` / `fallbackProviders`.
    
    Temp copied-config `doctor --fix --non-interactive` applied the Lossless fix.
    
    Inspecting the copied config after the fix showed:
    - allowModelOverride: true
    - allowedModels includes openai-codex/gpt-5.4-mini
    - allowedModels includes minimax/MiniMax-M2.7
    - allowAgentIdOverride absent
    
  • Observed result after fix: The load-path Lossless doctor contract was discovered from the configured plugin entry, read-only doctor showed the expected Lossless warnings, and doctor --fix --non-interactive updated the copied config with the expected Lossless llm policy.

  • What was not tested: The fix path was intentionally run against a copied temp config, not Josh’s real live config. Full local pnpm test later failed because vitest.unit-fast.config.ts hit the no-output watchdog twice; focused tests, pnpm build, and pnpm check passed.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: line Channel integration: line app: web-ui App: web-ui gateway Gateway runtime extensions: memory-core Extension: memory-core commands Command implementations agents Agent runtime and tooling plugin: file-transfer size: XL maintainer Maintainer-authored PR labels May 4, 2026
@clawsweeper

clawsweeper Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

Summary
The PR passes active OpenClaw config into plugin doctor contract discovery, session owner discovery, and legacy repair paths; adds load-path doctor contract coverage; updates the changelog; and includes small lint/test/export cleanup.

Reproducibility: yes. at source level. Current main omits active config when resolving plugin doctor contracts while manifest discovery depends on config.plugins.load.paths, so a load-path-only plugin can be runtime-visible but doctor-invisible.

Real behavior proof
Sufficient (live_output): The PR body includes after-fix real CLI output for doctor and doctor --fix against a load-path Lossless plugin setup using a copied temp config.

Next step before merge
A narrow PR-branch repair can adjust fallback id selection and add the missing regression test; maintainer review still gates merge because of the protected label.

Security
Cleared: The diff expands existing doctor contract discovery to configured plugin load paths and adds tests/changelog, with no new dependency, CI, package, secret, or artifact-download surface.

Review findings

  • [P2] Exclude handled channels from plugin fallback — src/commands/doctor/shared/channel-legacy-config-migrate.ts:48-50
Review details

Best possible solution:

Keep the active-config pass-through, but compute plugin fallback ids from unresolved channels plus configured non-channel plugin entries and cover a handled bundled channel plus non-channel plugin regression.

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

Yes, at source level. Current main omits active config when resolving plugin doctor contracts while manifest discovery depends on config.plugins.load.paths, so a load-path-only plugin can be runtime-visible but doctor-invisible.

Is this the best way to solve the issue?

No for the current PR head. Passing active config through doctor discovery is the narrow maintainable fix, but fallback id selection should exclude bundled channels already handled by channel doctor normalizers.

Full review comments:

  • [P2] Exclude handled channels from plugin fallback — src/commands/doctor/shared/channel-legacy-config-migrate.ts:48-50
    collectPluginDoctorCompatibilityIds() filters collectRelevantDoctorPluginIds() only against unresolved channel ids. That helper returns configured channels as well as plugins, so a config with a handled bundled channel such as slack plus a non-channel plugin entry sends slack back through applyPluginDoctorCompatibilityMigrations after the bundled normalizer already ran. Build the fallback set from unresolved channels plus configured non-channel plugin entries.
    Confidence: 0.89

Overall correctness: patch is incorrect
Overall confidence: 0.87

Acceptance criteria:

  • pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/plugins/doctor-contract-registry.ts src/plugins/doctor-contract-registry.load-paths.test.ts src/channels/plugins/legacy-config.ts src/channels/plugins/legacy-config.test.ts src/commands/doctor/shared/legacy-config-issues.ts src/commands/doctor/shared/channel-legacy-config-migrate.ts src/commands/doctor/shared/channel-legacy-config-migrate.test.ts src/commands/doctor-session-state-providers.ts src/plugins/plugin-registry-snapshot.test.ts
  • pnpm test src/plugins/doctor-contract-registry.test.ts src/plugins/doctor-contract-registry.load-paths.test.ts src/channels/plugins/legacy-config.test.ts src/commands/doctor/shared/channel-legacy-config-migrate.test.ts -- --reporter=verbose
  • pnpm build

What I checked:

Likely related people:

  • steipete: Recent commits on doctor-contract-registry and doctor session-state repair make this person a strong routing candidate for plugin doctor discovery and session repair behavior. (role: recent maintainer; confidence: high; commits: b17bb63b9eaa, f43a184103b6, 40ffada812b9; files: src/plugins/doctor-contract-registry.ts, src/commands/doctor-session-state-providers.ts)
  • vincentkoc: History shows this person on filtered doctor compatibility, bundled channel compat migration, and channel legacy rule fast paths that the PR modifies. (role: introduced and maintained doctor legacy config paths; confidence: high; commits: 7d54f2a3c2dd, 66e06b50bac3, 5c28cfbf09ee; files: src/commands/doctor/shared/channel-legacy-config-migrate.ts, src/channels/plugins/legacy-config.ts, src/plugins/doctor-contract-registry.ts)
  • gumadeiras: The lazy doctor plugin path work modified doctor-contract-registry shortly before this PR and is directly adjacent to the load-path discovery behavior. (role: adjacent owner; confidence: medium; commits: 66add9fcd96a; files: src/plugins/doctor-contract-registry.ts)

Remaining risk / open question:

  • The PR has the protected maintainer label, so merge and cleanup should remain maintainer-gated even after the narrow repair.
  • This read-only review did not execute the test suite; validation here is source inspection plus the PR body's focused, build, check, and live-output proof.
  • The branch includes unrelated lint/test/export cleanup outside the doctor surface, which maintainers may choose to split before merge.

Codex review notes: model gpt-5.5, reasoning high; reviewed against aed96bb60c7c.

@jalehman

jalehman commented May 4, 2026

Copy link
Copy Markdown
Contributor Author

This was opened with the wrong base. Fixing.

@jalehman jalehman force-pushed the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch from 7c3a220 to 3b6f973 Compare May 4, 2026 19:30
@openclaw-barnacle openclaw-barnacle Bot added size: M and removed docs Improvements or additions to documentation channel: line Channel integration: line app: web-ui App: web-ui gateway Gateway runtime extensions: memory-core Extension: memory-core agents Agent runtime and tooling plugin: file-transfer size: XL labels May 4, 2026
@jalehman jalehman force-pushed the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch 4 times, most recently from c9d09b9 to fd55fe6 Compare May 6, 2026 03:03
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 6, 2026
@jalehman jalehman self-assigned this May 6, 2026
@jalehman jalehman force-pushed the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch from fd55fe6 to c1cc146 Compare May 6, 2026 18:23
@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label May 6, 2026
@jalehman jalehman force-pushed the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch 2 times, most recently from 409bbaf to 244a138 Compare May 6, 2026 18:29
@openclaw-barnacle openclaw-barnacle Bot added the channel: googlechat Channel integration: googlechat label May 6, 2026
@jalehman jalehman force-pushed the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch from 244a138 to 542bfd6 Compare May 6, 2026 18:42
@jalehman jalehman force-pushed the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch from 542bfd6 to d428fd4 Compare May 6, 2026 18:43
@jalehman jalehman merged commit b22c899 into openclaw:main May 6, 2026
90 of 91 checks passed
@jalehman

jalehman commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

Thanks @jalehman!

@jalehman jalehman deleted the doctorfix64294-b7e7c5c1-fix-plugin-doctor-discovery branch May 6, 2026 18:50
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: d428fd4
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
rogerdigital pushed a commit to rogerdigital/openclaw that referenced this pull request May 9, 2026
Merged via squash.

Prepared head SHA: d428fd4
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
lykeion-dev pushed a commit to lykeion-dev/openclaw--rev that referenced this pull request May 14, 2026
Merged via squash.

Prepared head SHA: d428fd4
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Merged via squash.

Prepared head SHA: d428fd4
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
Merged via squash.

Prepared head SHA: d428fd4
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
Merged via squash.

Prepared head SHA: d428fd4
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: googlechat Channel integration: googlechat commands Command implementations maintainer Maintainer-authored PR proof: sufficient ClawSweeper judged the real behavior proof convincing. size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant