Skip to content

Expose stale plugin runtime symlink doctor lint findings#98729

Merged
giodl73-repo merged 1 commit into
openclaw:mainfrom
giodl73-repo:doctor-stale-plugin-runtime-symlinks-lint-findings
Jul 3, 2026
Merged

Expose stale plugin runtime symlink doctor lint findings#98729
giodl73-repo merged 1 commit into
openclaw:mainfrom
giodl73-repo:doctor-stale-plugin-runtime-symlinks-lint-findings

Conversation

@giodl73-repo

@giodl73-repo giodl73-repo commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • expose stale global plugin-runtime symlinks as default-disabled core/doctor/stale-plugin-runtime-symlinks lint findings
  • reuse the existing plugin-runtime symlink detector and map stale links to structured warnings
  • keep real unlinking in the existing doctor --fix cleanup path; this PR is lint-only and does not add a structured repair/dry-run hook

Contract / compatibility

  • No public SDK, plugin manifest, config schema, persisted data-model, or plugin contract changes.
  • Default doctor --lint behavior is unchanged; --only core/doctor/stale-plugin-runtime-symlinks and --all can select it.
  • Lint is read-only. Existing repair code remains the owner for removing stale symlinks.

Real behavior proof

Source-harness proof with real temporary directories and directory symlinks showed one core/doctor/stale-plugin-runtime-symlinks warning and confirmed the symlink still existed after detection. Contribution-level proof verifies default lint skips this default-disabled check and explicit --only runs it.

Validation after rebase and symlink test gating

  • node scripts/run-vitest.mjs src/commands/doctor/shared/plugin-runtime-symlinks.test.ts src/flows/doctor-health-contributions.test.ts (65 tests)
  • changed-file oxfmt --check
  • changed-file oxlint --tsconfig config/tsconfig/oxlint.core.json
  • node scripts/plugin-sdk-surface-report.mjs --check
  • git diff --check origin/main...HEAD

Note: the real-symlink tests now gate on directory-symlink filesystem capability, so restricted Windows hosts skip those real filesystem assertions instead of failing with EPERM.

@openclaw-barnacle openclaw-barnacle Bot added the commands Command implementations label Jul 1, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper review

@openclaw-barnacle openclaw-barnacle Bot added size: M maintainer Maintainer-authored PR labels Jul 1, 2026
@clawsweeper

clawsweeper Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper

clawsweeper Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 1:12 PM ET / 17:12 UTC.

Summary
The branch adds a default-disabled Doctor lint check that maps stale plugin-runtime symlinks into structured findings and covers it with symlink and contribution tests.

PR surface: Source +46, Tests +186. Total +232 across 4 files.

Reproducibility: yes. from source: the PR maps existing stale symlink detector output into structured lint findings, and the contribution test covers default skip plus explicit selection. I did not run tests in this read-only review.

Review metrics: 1 noteworthy metric.

  • Doctor lint surface: 1 default-disabled core check added. Maintainers should notice the new selectable check id because it becomes user-visible through doctor --lint --all and explicit --only.

Stored data model
Persistent data-model change detected: migration/backfill/repair: src/commands/doctor/shared/plugin-runtime-symlinks.test.ts, migration/backfill/repair: src/commands/doctor/shared/plugin-runtime-symlinks.ts, migration/backfill/repair: src/flows/doctor-health-contributions.test.ts, migration/backfill/repair: src/flows/doctor-health-contributions.ts, unknown-data-model-change: src/commands/doctor/shared/plugin-runtime-symlinks.test.ts, unknown-data-model-change: src/flows/doctor-health-contributions.test.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Wait for the remaining exact-head CI shard to complete.
  • Have a maintainer explicitly accept the new opt-in Doctor lint check id and warning copy.

Risk before merge

  • [P1] The protected maintainer label means this PR needs explicit maintainer handling before merge or cleanup-close automation.
  • [P1] One exact-head CI shard was still in progress when checked, so merge should wait for required checks to finish.
  • [P1] The PR exposes a new opt-in Doctor lint check id and warning copy through --all and explicit --only, which maintainers should be comfortable making user-visible.

Maintainer options:

  1. Decide the mitigation before merge
    Land the lint-only diagnostic after maintainer approval and green exact-head checks, keeping symlink deletion in the existing doctor --fix cleanup path.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] Protected maintainer label and the new opt-in Doctor lint surface need explicit maintainer review; there is no narrow automated repair to queue.

Security
Cleared: The diff adds bounded local filesystem symlink inspection and tests without new dependencies, workflow changes, package metadata changes, secrets handling, or downloaded code execution.

Review details

Best possible solution:

Land the lint-only diagnostic after maintainer approval and green exact-head checks, keeping symlink deletion in the existing doctor --fix cleanup path.

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

Yes, from source: the PR maps existing stale symlink detector output into structured lint findings, and the contribution test covers default skip plus explicit selection. I did not run tests in this read-only review.

Is this the best way to solve the issue?

Yes. The lint-only shape is the narrow maintainable fix because existing doctor --fix cleanup already owns deletion, and the earlier unreachable structured repair direction was removed after review feedback.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 0ad58848b399.

Label changes

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.

Label justifications:

  • P3: This is a low-risk opt-in Doctor diagnostic and test change, not an urgent runtime regression.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body and latest comments describe after-fix source-harness proof with real temporary directories and directory symlinks plus exact focused validation commands.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and latest comments describe after-fix source-harness proof with real temporary directories and directory symlinks plus exact focused validation commands.
Evidence reviewed

PR surface:

Source +46, Tests +186. Total +232 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 46 0 +46
Tests 2 187 1 +186
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 233 1 +232

What I checked:

  • Repository policy read: Root AGENTS.md was read fully; no scoped AGENTS.md or maintainer notes were found for the touched src/commands/doctor/shared or src/flows paths, so root read-beyond-diff and protected-label guidance applied. (AGENTS.md:1, 0ad58848b399)
  • Current main has the detector but not the lint id: Current main already has collection, note, and removal helpers for stale plugin-runtime symlinks, and an exact search found no core/doctor/stale-plugin-runtime-symlinks check id or health-finding helper. (src/commands/doctor/shared/plugin-runtime-symlinks.ts:56, 0ad58848b399)
  • Existing repair path remains the owner for deletion: Current main removes stale plugin-runtime symlinks from the legacy plugin dependency cleanup sequence used by doctor --fix, which matches the PR's lint-only scope. (src/commands/doctor/shared/plugin-dependency-cleanup.ts:462, 0ad58848b399)
  • Lint selection supports opt-in checks: Current lint runner skips default-disabled checks unless --only or --all selects them, supporting the PR's compatibility claim that default lint output remains unchanged. (src/flows/doctor-lint-flow.ts:38, 0ad58848b399)
  • PR registers the new lint-only contribution: The PR diff adds core/doctor/stale-plugin-runtime-symlinks with defaultEnabled: false, a lazy detector import, and run: async () => {}, so it does not add a new core structured repair path. (src/flows/doctor-health-contributions.ts:1462, 287d2230eed7)
  • PR maps stale symlinks to structured findings: The PR diff adds a mapper and collector that convert existing stale symlink detector results into warning findings with a fix hint that points to openclaw doctor --fix. (src/commands/doctor/shared/plugin-runtime-symlinks.ts:101, 287d2230eed7)

Likely related people:

  • steipete: Authored the commit that added the shared stale plugin-runtime symlink detection/removal helper reused by this PR. (role: introduced adjacent behavior; confidence: high; commits: 8643916094c5; files: src/commands/doctor/shared/plugin-runtime-symlinks.ts, src/flows/doctor-health.ts, src/commands/doctor/shared/plugin-dependency-cleanup.ts)
  • giodl73-repo: Authored the merged adjacent Doctor lint contribution for legacy plugin dependency state in the same registry and tests, beyond only proposing this PR. (role: recent adjacent contributor; confidence: high; commits: 6638a575d39d; files: src/flows/doctor-health-contributions.ts, src/flows/doctor-health-contributions.test.ts, src/commands/doctor/shared/plugin-dependency-cleanup.ts)
  • pgondhi987: Recently hardened legacy plugin dependency cleanup roots near the repair path that still owns stale symlink deletion. (role: adjacent cleanup hardening contributor; confidence: medium; commits: 517f77a68c65, 8a3ffd1e66d4; files: src/commands/doctor/shared/plugin-dependency-cleanup.ts, src/commands/doctor/shared/plugin-dependency-cleanup.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels Jul 1, 2026
@giodl73-repo
giodl73-repo force-pushed the doctor-stale-plugin-runtime-symlinks-lint-findings branch from 2f55e3b to c4d8fee Compare July 2, 2026 01:10
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review current head c4d8fee. Added structured dry-run repair effects for selected stale plugin-runtime symlink cleanup and reran focused proof listed in the PR body.

@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@omarshahine

Copy link
Copy Markdown
Contributor

Codex review finding:

The structured repair path added here is not reachable from the supported Doctor CLI. The contribution registers repairStalePluginRuntimeSymlinkFindings() on core/doctor/stale-plugin-runtime-symlinks, but its run is async () => {} (src/flows/doctor-health-contributions.ts:1345-1365). Because createDoctorHealthContribution only defaults to the structured runner when run is omitted (src/flows/doctor-health-contributions.ts:144-151), this hook is skipped by openclaw doctor --fix. The generic structured fix pass is extension-only (src/flows/doctor-health-contributions.ts:440-453, src/flows/health-check-registry.ts:29-40), and --only is accepted only with --lint (src/cli/program/register.maintenance.ts:42-83), so the PR's claimed doctor --fix --dry-run --only core/doctor/stale-plugin-runtime-symlinks proof is not a real user path.

Best fix: either add a real core structured repair selection path, or make this PR lint-only and remove the dead repair hook/tests/body claim. The existing legacy repair sequence remains the runtime owner for stale symlink cleanup.

@giodl73-repo

Copy link
Copy Markdown
Contributor Author

Addressed Omar's reachability finding by making this PR lint-only again.

What changed:

  • Removed the structured repair() hook from core/doctor/stale-plugin-runtime-symlinks.
  • Removed the unreachable dry-run repair helper/tests and PR-side dry-run behavior from this slice.
  • Kept the existing stale symlink detector and default-disabled lint finding; real symlink removal remains owned by the existing legacy doctor --fix cleanup path.

Validation on 304b4773b4:

  • node scripts/run-vitest.mjs src/flows/doctor-health-contributions.test.ts (57 passed)
  • changed-file pnpm exec oxfmt --check
  • changed-file pnpm exec oxlint
  • node scripts/plugin-sdk-surface-report.mjs --check
  • git diff --check

I also reran src/commands/doctor/shared/plugin-runtime-symlinks.test.ts; on this Windows host it still fails at fs.symlink(..., "dir") with EPERM, so I treated the filesystem-helper test as environment-sensitive rather than a regression from this lint-only correction.

@clawsweeper review

@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 2, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper review final lint-only wording/body synced after Omar fix

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. label Jul 2, 2026
@giodl73-repo
giodl73-repo force-pushed the doctor-stale-plugin-runtime-symlinks-lint-findings branch from 304b477 to 4dd79b7 Compare July 3, 2026 16:36
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review exact head 4dd79b7. Rebased onto current main, kept the PR lint-only after Omar reachability feedback, and gated real directory-symlink tests on filesystem capability to address the Windows EPERM finding. Focused proof and SDK surface check passed.

@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@giodl73-repo
giodl73-repo marked this pull request as ready for review July 3, 2026 16:44
@clawsweeper clawsweeper Bot added status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. labels Jul 3, 2026
@giodl73-repo
giodl73-repo force-pushed the doctor-stale-plugin-runtime-symlinks-lint-findings branch from 4dd79b7 to 287d223 Compare July 3, 2026 17:00
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review exact head 287d223. Fixed the CI no-unnecessary-type-assertion lint finding after marking ready; focused Vitest, changed-file oxfmt, changed-file oxlint with core tsconfig, SDK surface report, and diff-check passed.

@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 3, 2026
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

Maintainer note for ClawSweeper P1s: accepted.

  • Exact-head hosted CI is now clean on 287d2230eed71d84ccd248f9cef77507b88ac312; the remaining cancelled label/auto-response jobs are superseded automation runs, not PR failures.
  • I accept the new opt-in Doctor lint surface: core/doctor/stale-plugin-runtime-symlinks is default-disabled and only user-visible through doctor --lint --all or explicit --only selection.
  • I accept the warning copy and scope. This PR is lint-only; actual symlink deletion remains in the existing legacy doctor --fix cleanup path.

@giodl73-repo
giodl73-repo merged commit 43a7fd3 into openclaw:main Jul 3, 2026
110 of 114 checks passed
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

Merged by head-pinned squash.

Source head: 287d2230eed71d84ccd248f9cef77507b88ac312
Merge commit: 43a7fd3839973756761a871e4d6d2411e5c2adf8

Verification before merge:

  • Focused plugin-runtime-symlink/contribution Vitest passed (65 tests).
  • Changed-file oxfmt passed.
  • Changed-file oxlint with config/tsconfig/oxlint.core.json passed.
  • SDK surface report passed.
  • git diff --check passed.
  • Exact-head hosted checks passed/skipped.

Maintainer note: ClawSweeper's P1 maintainer-acceptance items were accepted above. The local prepare wrapper still fails pnpm check on the npm shrinkwrap guard, and the same failure reproduces on current origin/main, so this was treated as baseline local gate noise rather than PR-caused.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 4, 2026
)

Adds a default-disabled Doctor lint check for stale plugin-runtime symlinks while keeping real deletion in the existing legacy doctor --fix cleanup path.

Verification:
- Focused plugin-runtime-symlink/contribution Vitest passed (65 tests).
- Changed-file oxfmt passed.
- Changed-file oxlint with core tsconfig passed.
- SDK surface report passed.
- git diff --check passed.
- Exact-head hosted checks passed/skipped on 287d223.

Maintainer notes:
- ClawSweeper platinum hermit / ready for maintainer look.
- Accepted the new opt-in lint check id and warning copy on the PR.
- Local prepare wrapper pnpm check still fails on the npm shrinkwrap guard, and the same failure reproduces on current origin/main; treated as baseline local gate noise, not PR-caused.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations maintainer Maintainer-authored PR P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants