Doctor: expose extra gateway service findings#84340
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 22, 2026, 3:18 AM ET / 07:18 UTC. Summary PR surface: Source +77, Tests +242. Total +319 across 11 files. Reproducibility: not applicable. this is a PR review for a structured Doctor migration slice, not a bug report with a failing current-main reproduction. Review metrics: 3 noteworthy metrics.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land only after maintainers explicitly accept the lint-default and SDK-context compatibility changes as part of the structured Doctor migration series, keeping legacy gateway cleanup authoritative until a deliberate full switchover. Do we have a high-confidence way to reproduce the issue? Not applicable; this is a PR review for a structured Doctor migration slice, not a bug report with a failing current-main reproduction. Is this the best way to solve the issue? Yes, the implementation follows the merged ordered-contribution migration shape and keeps real gateway cleanup in the existing legacy path; the remaining question is compatibility/product acceptance, not a code defect. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c57fee8239ed. Label changesLabel justifications:
Evidence reviewedPR surface: Source +77, Tests +242. Total +319 across 11 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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 PR egg 🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat. Where did the egg go?
|
6412d3f to
2cd30e3
Compare
5e24059 to
02f5ff9
Compare
02f5ff9 to
51ab30c
Compare
591b40d to
ab2b9dc
Compare
ab2b9dc to
583a243
Compare
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review Updated the branch to signed head This addresses the compatibility finding: non-legacy extra gateway services now produce Validation passed locally: focused gateway/contribution Vitest (82 tests), targeted |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review Pushed a4bcd70 to address the structured gateway-services deep-scan parity finding. Change made:
Validation:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review Updated #84340 at head
Validation on
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review Pushed
Validation on
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Rebased #84340 onto current Validation after rebase:
@clawsweeper please re-review current head. |
|
🦞👀 I queued a lightweight read-only assist pass. It will post a separate answer comment and will not edit the durable ClawSweeper review comment or trigger close, merge, repair, label, or branch changes. Request: please re-review current head. |
|
Added a follow-up cleanup commit Validation for the follow-up cleanup:
@clawsweeper please re-review current head. |
|
🦞👀 I queued a lightweight read-only assist pass. It will post a separate answer comment and will not edit the durable ClawSweeper review comment or trigger close, merge, repair, label, or branch changes. Request: please re-review current head. |
|
ClawSweeper assist: A full current-head correctness review is needed for #84340. I can’t perform that review in assist mode; use Evidence:
Suggested next action: Comment Source: #84340 (comment) |
|
ClawSweeper assist: A full current-head correctness review is needed for #84340. Assist mode can’t perform that review; use Evidence:
Suggested next action: Comment Source: #84340 (comment) |
galiniliev
left a comment
There was a problem hiding this comment.
This PR exposes extra gateway-like services through structured Doctor health findings, threads --deep into lint health checks, and changes default doctor --lint reporting to warning-and-above. That matters because doctor --lint is the automation surface, while the existing mutating gateway-service cleanup path remains in the legacy Doctor contribution.
LOC: +333/-15 (12 files)
By: Gio Della-Libera (@giodl73-repo, acct 2025-09-30) | OpenClaw: 173 PRs, 14 issues, 132 commits/12mo | GitHub: 6177 commits, 206 PRs, 29 issues, 17 reviews/12mo
Findings: No blocking findings.
Bug/behavior: Adds a structured core/doctor/gateway-services/extra check so openclaw doctor --lint can report extra gateway services; legacy services are warning-level and repair-previewable, intentional non-legacy extras are info-level. Also forwards doctor --lint --deep into health checks and changes the default lint threshold from info to warning.
Affected surface: src/commands/doctor-gateway-services.ts, src/commands/doctor-lint.ts, src/flows/doctor-core-checks.ts, src/flows/doctor-health-contributions.ts, src/flows/health-checks.ts, and CLI registration/tests.
Provenance: N/A for a feature/migration slice. Current origin/main defaults runDoctorLintCli() to info in src/commands/doctor-lint.ts and has only core/doctor/gateway-services/platform-notes attached to the Gateway services contribution; it does not expose the new extra-service structured check.
Best-fix verdict: acceptable mitigation / likely best for this migration slice. The implementation keeps real service cleanup in the existing maybeScanExtraGatewayServices() / legacy contribution path while sharing detection and mapping for lint/repair previews, which avoids moving systemd/launchd mutation ownership prematurely.
Alternatives considered:
- Move legacy gateway cleanup fully into the structured repair check now: rejected because
doctor --fixservice mutation policy, prompts, external-service policy, and platform cleanup behavior are still owned by the existing contribution path. - Keep default lint threshold at
infoand special-case intentional extra gateways: rejected as noisier for the automation surface; the branch explicitly tests--severity-min infofor opt-in info visibility. - Put the extra-service check only in standalone lint registration instead of the ordered Doctor contribution map: rejected because current Doctor lint resolves checks through contribution ordering, and this PR keeps the new check attached to
doctor:gateway-services.
Code read: src/commands/doctor-gateway-services.ts, src/daemon/inspect.ts, src/commands/doctor-lint.ts, src/flows/doctor-lint-flow.ts, src/flows/health-checks.ts, src/flows/doctor-core-checks.ts, src/flows/doctor-health-contributions.ts, src/flows/doctor-repair-flow.ts, src/cli/program/register.maintenance.ts, src/plugin-sdk/health.ts, src/plugin-sdk/AGENTS.md, docs/cli/doctor.md, docs/gateway/doctor.md, plus adjacent tests.
Validation:
pnpm docs:listpnpm test src/commands/doctor-gateway-services.test.ts src/commands/doctor-lint.test.ts src/flows/doctor-core-checks.test.ts src/flows/doctor-health-contributions.test.ts src/cli/program/register.maintenance.test.ts --reporter=dot(3 Vitest shards; 121 tests passed)- Live PR checks queried at head
8fb226be72dc33af84aa63fb14d4ae4b68adafab; no non-success/non-skipped/non-neutral check runs were returned.
Remaining uncertainty: I did not run real systemd/launchd/schtasks service discovery or mutating cleanup E2E; this review is based on current detector contracts, focused tests, and the PR’s synthetic service proof. The default lint threshold change remains a maintainer product/compatibility acceptance point rather than a code defect.
|
@clawsweeper review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Updated #84340 at head Change made:
Validation:
@clawsweeper review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Merged via squash.
Thanks @giodl73-repo! |
Summary
doctor:gateway-serviceslegacy run path authoritative for normaldoctor/doctor --fixmutation.This is intentionally the Gateway services slice from the Doctor repair stack. It does not change Gateway startup, provider config, or plugin health behavior.
Stack
Review order: this is the next Doctor structured-repair PR after #84326. The branch itself is rebased on current
main; #86627 has landed and supplies the ordered core Doctor contribution model.Current branch head is signed commit
1818dcab5c5ba0c592b976e45955ac67a3c0d1e5(Keep doctor lint deep internal). The latest commit removesdeepfrom the publicHealthCheckContextSDK contract while keepingdoctor --lint --deepavailable to core Doctor checks. The prior rebased-base cleanup for the unusedsessionStoredestructure remains included so prod type/lint CI passes on current main.Real behavior proof
Behavior or issue addressed:
Extra or legacy Gateway-like services are visible through structured Doctor health checks, while normal mutating service cleanup remains owned by the existing
doctor:gateway-servicesrun path. Intentional non-legacy extra Gateway services are non-failing by default; legacy Gateway services remain warning-level and repairable.Real environment tested:
WSL Ubuntu 24.04, OpenClaw checkout
/root/src/openclaw-84340-proof, prior PR head5d57cbeccc55509c3867bb4c964a0094c6869293, source CLI vianode scripts/run-node.mjs, source harness vianode --import tsx --input-type=module, isolated tempOPENCLAW_STATE_DIR, tempOPENCLAW_CONFIG_PATH, tempHOME, and a synthetic legacy user systemd unit. The branch has since been rebased and updated to8fb226be72dc33af84aa63fb14d4ae4b68adafab; the latest functional Gateway-services behavior is unchanged.Exact steps or command run after this patch:
clawdbot-gateway.serviceunit.extraGatewayServiceToHealthFinding,extraGatewayServiceToRepairEffects, andexitCodeFromFindings.oxlint, targetedoxfmt --check,git diff --check, andpnpm tsgo:core.src/cli/program/register.maintenance.test.ts,src/flows/doctor-core-checks.test.ts,pnpm check:test-types, andpnpm tsgo:core.sessionStoredestructure exposed by currentupstream/main, then reranpnpm tsgo:coresuccessfully.Evidence after fix:
{ "intentional": { "severity": "info", "fixHint": "Run a single gateway per machine unless this extra gateway is intentional.", "defaultLintExit": 0, "repairEffects": [] }, "legacy": { "severity": "warning", "fixHint": "Run openclaw doctor --fix to remove legacy gateway services.", "defaultLintExit": 1, "repairEffects": [ { "kind": "service", "action": "would-remove-legacy-gateway-service", "target": "openclaw-gateway.service", "dryRunSafe": false } ] } }The earlier real CLI proof still applies to the legacy path:
doctor --lint --json --only core/doctor/gateway-services/extrareports the synthetic legacyclawdbot-gateway.serviceas a structured warning with the expected check id, Linux source, target service label, and fix hint.Observed result after fix:
Intentional non-legacy extra Gateway services are visible in structured output without failing default
doctor --lint. Legacy Gateway services remain warning-level, fail default lint, and expose the dry-run cleanup effect.What was not tested:
The proof uses synthetic Gateway service fixtures, not a real installed or running Gateway service. I did not run full
doctor --fixservice cleanup in WSL because the mutating cleanup path can invoke systemd/service-management behavior; the PR intentionally keeps that existing legacy run path authoritative.ClawSweeper and maintainer status
Latest visible ClawSweeper status:
Maintainer findings to accept before merge:
doctor --lintnow reports and failswarning-and-above findings;infofindings require--severity-min info.Severity finding:
warning; they are actionably stale service state with an existingopenclaw doctor --fixcorrection path.info; they are noteworthy but can be left in place indefinitely when intentional.rfcs/needs_refactoring/0002-doctor-health-upgrades.md, records the Doctor warning/info severity bar in the structured health contract.Validation
Current head
8fb226be72dc33af84aa63fb14d4ae4b68adafab:$env:OPENCLAW_VITEST_MAX_WORKERS='1'; node scripts\run-vitest.mjs run src\commands\doctor-gateway-services.test.ts src\commands\doctor-lint.test.ts src\flows\doctor-core-checks.test.ts src\flows\doctor-health-contributions.test.ts src\cli\program\register.maintenance.test.ts --reporter=dot- 121 tests passed across 3 shardspnpm exec oxlint src\cli\program\register.maintenance.test.ts src\cli\program\register.maintenance.ts src\commands\doctor-gateway-services.test.ts src\commands\doctor-gateway-services.ts src\commands\doctor-lint.test.ts src\commands\doctor-lint.ts src\flows\doctor-core-checks.test.ts src\flows\doctor-core-checks.ts src\flows\doctor-health-contributions.test.ts src\flows\doctor-health-contributions.ts src\flows\health-checks.ts src\config\sessions\session-accessor.tspnpm exec oxfmt --check src\cli\program\register.maintenance.test.ts src\cli\program\register.maintenance.ts src\commands\doctor-gateway-services.test.ts src\commands\doctor-gateway-services.ts src\commands\doctor-lint.test.ts src\commands\doctor-lint.ts src\flows\doctor-core-checks.test.ts src\flows\doctor-core-checks.ts src\flows\doctor-health-contributions.test.ts src\flows\doctor-health-contributions.ts src\flows\health-checks.ts src\config\sessions\session-accessor.tspnpm tsgo:corepnpm tsgo:test:srcgit diff --checkFollow-up
1818dcab5c5ba0c592b976e45955ac67a3c0d1e5:OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs run src/commands/doctor-lint.test.ts src/flows/doctor-core-checks.test.ts src/commands/doctor-gateway-services.test.ts src/flows/doctor-health-contributions.test.ts src/cli/program/register.maintenance.test.ts --reporter=dot- 121 tests passed across 3 shardsnode_modules/oxlint/bin/oxlint src/commands/doctor-lint.ts src/commands/doctor-lint.test.ts src/flows/doctor-core-checks.ts src/flows/doctor-core-checks.test.ts src/flows/health-checks.tsnode_modules/oxfmt/bin/oxfmt --check src/commands/doctor-lint.ts src/commands/doctor-lint.test.ts src/flows/doctor-core-checks.ts src/flows/doctor-core-checks.test.ts src/flows/health-checks.tsnode node_modules//native-preview/bin/tsgo.js -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo --declaration false --singleThreaded --checkers 1node node_modules//native-preview/bin/tsgo.js -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src.tsbuildinfo --declaration false --singleThreaded --checkers 1git diff --check