Skip to content

refactor(doctor): separate diagnostic orchestration - #5910

Merged
cv merged 8 commits into
mainfrom
codex/refactor-doctor-complexity
Jun 27, 2026
Merged

refactor(doctor): separate diagnostic orchestration#5910
cv merged 8 commits into
mainfrom
codex/refactor-doctor-complexity

Conversation

@cv

@cv cv commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the 114-complexity sandbox doctor command with a narrow orchestration layer and cohesive reporting, messaging, and system-diagnostic modules. doctor.ts shrinks from 884 lines to 531, while a file-scoped Biome ratchet caps every function in the doctor surface at cognitive complexity 10.

Changes

  • isolate doctor report aggregation, text rendering, and JSON rendering in doctor-report.ts
  • extract messaging/runtime-channel diagnostics and host/gateway/local-service diagnostics into focused modules
  • express host, gateway, sandbox, inference, registered-sandbox, tool-scope, and local-service execution as ordered collectors
  • keep doctor --json read-only by probing gateway state without invoking recovery
  • keep registry diagnostics available offline while gating inference-gateway and messaging-runtime sandbox probes on collected reachability
  • validate legacy gateway port mappings against each sandbox's persisted gateway binding
  • add negative tests for missing OpenShell, disconnected gateways, read-only diagnostics, and non-OpenClaw tool-scope gating
  • verify report aggregation/rendering and ensure local inference diagnostics do not mutate provider-health results
  • enforce a cognitive-complexity ceiling of 10 across all doctor modules

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification: the existing doctor helper suites and 12 CLI process scenarios continue to cover end-to-end diagnostics; new focused tests cover the extracted boundaries, report contract, persisted-port matching, and negative orchestration gates.
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: the command reference already defines --json as report-only and mutually exclusive with --fix; this change makes the implementation honor that existing contract.
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: self-review confirmed diagnostic ordering, repair/recovery gating, process exits, and output contracts; the full repository hook and coverage suite passes.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push, or npx prek run --from-ref main --to-ref HEAD passes
  • Targeted tests pass for changed behavior
  • Full npm test passes (broad runtime changes only)
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • New Features
    • Sandbox “doctor” diagnostics now generate a structured, grouped report with colored status labels, optional per-check hints, and a JSON output mode.
    • Added dedicated diagnostics for messaging channels/runtime registry, gateway/container health, local tunnel/service state, and Ollama reachability.
  • Bug Fixes
    • Improved gating so recovery/repairs and certain probes run only when prerequisites are met; JSON runs remain read-only.
    • Messaging runtime registry failures now surface as warnings without hiding related messaging checks.
  • Tests
    • Expanded coverage for report formatting, system checks, and doctor flow gating scenarios.
  • Chores
    • Tightened complexity linting for sandbox doctor action modules.

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv cv self-assigned this Jun 27, 2026
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Splits sandbox doctor reporting, messaging, and system checks into dedicated modules, then rewires doctor.ts to parse intent, gather checks, and render the final report. Tests expand for the new flows, and biome.json adds a complexity override for the doctor files.

Changes

Doctor Report Extraction and Diagnostics Refactor

Layer / File(s) Summary
doctor-report.ts: types, aggregation, and rendering
src/lib/actions/sandbox/doctor-report.ts, src/lib/actions/sandbox/doctor-report.test.ts
Defines DoctorStatus, DoctorCheck, and DoctorReport; computes summary counts and overall status; renders grouped console or JSON output; and verifies report aggregation and rendering behavior.
doctor-messaging.ts: messaging diagnostics
src/lib/actions/sandbox/doctor-messaging.ts
Builds messaging diagnostics for configured channels and runtime registry probing, including enabled or paused channel handling, overlap checks, degraded bridge health, and optional runtime probe results.
doctor-system-checks.ts: gateway and local service checks
src/lib/actions/sandbox/doctor-system-checks.ts
Adds helpers and doctor checks for gateway inspection, sandbox list parsing, readiness inference, cloudflared state, Ollama reachability, and legacy gateway selection, with a gateway port-mapping test.
doctor.ts: intent parsing and check orchestration
src/lib/actions/sandbox/doctor.ts, biome.json
Refactors runSandboxDoctor around intent parsing, host, gateway, sandbox, inference, registered, and tool-scope collectors, then builds and renders the final report through the extracted modules. The Biome override applies the cognitive-complexity rule to the doctor action files.
doctor-flow.test.ts and biome.json
src/lib/actions/sandbox/doctor-flow.test.ts
Expands flow coverage for probe gating and provider-health behavior, and adds assertions around the new orchestration and check gating behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

area: cli, bug-fix

Suggested reviewers

  • cjagwani
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.51% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the main change: refactoring doctor into a separate orchestration layer.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/refactor-doctor-complexity

Comment @coderabbitai help to get the list of available commands.

@github-code-quality

github-code-quality Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the codex/refactor-docto... branch is 96%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main codex/refactor-docto... 0f67897 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the codex/refactor-docto... branch is 68%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main codex/refactor-docto... 0f67897 +/-
src/lib/actions...all/run-plan.ts 80%
src/lib/state/o...oard-session.ts 78%
src/lib/actions...dbox/rebuild.ts 74%
src/lib/state/sandbox.ts 72%
src/lib/shields/index.ts 70%
src/lib/onboard/preflight.ts 69%
src/lib/actions...licy-channel.ts 59%
src/lib/onboard...er-gpu-patch.ts 59%
src/lib/policy/index.ts 52%
src/lib/onboard.ts 20%

Updated June 27, 2026 22:16 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 0 suggestions · 2 test follow-ups
Since last review: 1 prior item resolved · 0 still apply · 0 new items found

Action checklist

  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Add or identify a runtime/integration scenario where plain `doctor` starts with the named gateway missing, `recoverNamedGatewayRuntime()` restores it to healthy, `openshell sandbox list` reports the target sandbox as `Ready`, and the run then performs sandbox-list, inference-gateway, messaging-runtime, and OpenClaw tool-scope probes only after recovery.. The changed unit and flow tests cover the important orchestration and negative trust-boundary behavior. A real runtime path is still useful because `doctor` coordinates Docker, OpenShell gateway lifecycle, sandbox exec, inference gateway probing, messaging runtime diagnostics, local services, and tool-scope checks.
  • PRA-T2 Runtime validation — Add or identify a runtime/integration scenario where `doctor --json` observes the same missing named gateway but does not invoke gateway recovery or any sandbox-exec-based messaging/tool-scope probe, and reports the skipped gateway-dependent checks as non-mutating diagnostics.. The changed unit and flow tests cover the important orchestration and negative trust-boundary behavior. A real runtime path is still useful because `doctor` coordinates Docker, OpenShell gateway lifecycle, sandbox exec, inference gateway probing, messaging runtime diagnostics, local services, and tool-scope checks.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: diagnostics-e2e, messaging-providers-e2e, shields-config-e2e
Optional E2E: sandbox-operations-e2e, inference-routing-e2e, tunnel-lifecycle-e2e

Dispatch hint: diagnostics-e2e,messaging-providers-e2e,shields-config-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • diagnostics-e2e (medium): Closest existing end-to-end diagnostics coverage for a real installed/onboarded sandbox. The PR changes the sandbox doctor diagnostic command and report behavior, so a live diagnostics install/onboard smoke should block merge.
  • messaging-providers-e2e (high): This existing suite directly exercises nemoclaw <sandbox> doctor --json for the Messaging Runtime channel registry check. The PR moves and rewrites that runtime-channel doctor logic.
  • shields-config-e2e (medium): Doctor reports shields posture and mutable OpenClaw config permission state, and doctor --fix can mutate config permissions. Run the live shields/config permission lifecycle suite to guard the security boundary adjacent to this code.

Optional E2E

  • sandbox-operations-e2e (high): Useful adjacent confidence for OpenShell sandbox lifecycle, multi-sandbox state, and gateway recovery paths that doctor now probes and sometimes recovers, but it does not directly assert doctor output.
  • inference-routing-e2e (medium): Doctor route and provider health reporting changed. This suite validates inference routing and credential isolation end-to-end, but it is adjacent rather than direct doctor coverage.
  • tunnel-lifecycle-e2e (medium): Doctor now reports local cloudflared state through the extracted system checks. This is useful if maintainers want confidence in tunnel status interactions, but the PR primarily affects doctor rendering/probes.

New E2E recommendations

  • sandbox doctor diagnostics (high): Existing diagnostics-e2e does not appear to invoke nemoclaw <sandbox> doctor; the only direct doctor E2E found is a messaging-specific doctor --json assertion inside messaging-providers-e2e. Add a focused doctor E2E that validates doctor --json, plain doctor read/write behavior, --json --fix rejection, disconnected gateway skip behavior, local inference gateway subprobe reporting, and config permission --fix on a live OpenClaw sandbox.
    • Suggested test: test/e2e/test-sandbox-doctor.sh / sandbox-doctor-e2e

Dispatch hint

  • Workflow: nightly-e2e.yaml
  • jobs input: diagnostics-e2e,messaging-providers-e2e,shields-config-e2e

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: messaging-providers-vitest
Optional Vitest E2E scenarios: None

Dispatch required Vitest E2E scenarios:

  • gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=messaging-providers-vitest

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required Vitest E2E scenarios

  • messaging-providers-vitest: The PR refactors and changes nemoclaw <sandbox> doctor, including JSON report rendering, gateway reachability gating, inference gateway subprobes, and messaging runtime diagnostics. The wired free-standing live Vitest job messaging-providers-vitest runs test/e2e-scenario/live/messaging-providers.test.ts, which executes doctor --json against a live sandbox and asserts the Runtime channel registry diagnostic.
    • Dispatch: gh workflow run e2e-vitest-scenarios.yaml --ref <pr-head-ref> --field jobs=messaging-providers-vitest

Optional Vitest E2E scenarios

  • None.

Relevant changed files

  • src/lib/actions/sandbox/doctor-messaging.ts
  • src/lib/actions/sandbox/doctor-report.ts
  • src/lib/actions/sandbox/doctor-system-checks.ts
  • src/lib/actions/sandbox/doctor.ts

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Informational

Merge posture: Informational / low confidence
Primary next action: Resolve or justify PRA-1: PR review advisor unavailable.
Open items: 0 required · 1 warning · 0 suggestions · 1 test follow-up
Top item: PR review advisor unavailable

Action checklist

  • PRA-1 Resolve or justify: PR review advisor unavailable
  • PRA-T1 Add or justify test follow-up: Runtime validation

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify correctness Re-run the PR Review Advisor or perform a manual review.
Review findings by urgency: 0 required fixes, 1 item to resolve/justify, 0 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — PR review advisor unavailable

  • Location: not file-specific
  • Category: correctness
  • Problem: The automated advisor could not complete: Could not parse JSON from PR review advisor output; see /home/runner/work/NemoClaw/NemoClaw/artifacts/pr-review-advisor-nemotron-ultra/pr-review-advisor-retry-raw-output.txt
  • Impact: Automated review evidence is incomplete, so human review must cover the changed code manually.
  • Recommended action: Re-run the PR Review Advisor or perform a manual review.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the workflow logs and raw advisor artifact for the execution failure.
  • Missing regression test: No regression test recommendation is available because the advisor did not complete.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the workflow logs and raw advisor artifact for the execution failure.
  • Evidence: Could not parse JSON from PR review advisor output; see /home/runner/work/NemoClaw/NemoClaw/artifacts/pr-review-advisor-nemotron-ultra/pr-review-advisor-retry-raw-output.txt

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

  • None.
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Add or identify targeted runtime/integration validation for the changed behavior; do not report external E2E job pass/fail here.. Runtime/sandbox/infrastructure paths need behavioral runtime validation: biome.json, src/lib/actions/sandbox/doctor-messaging.ts, src/lib/actions/sandbox/doctor-report.ts, src/lib/actions/sandbox/doctor-system-checks.ts, src/lib/actions/sandbox/doctor.ts.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/lib/actions/sandbox/doctor.ts (1)

768-770: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Gate the in-sandbox inference gateway probe on sandbox reachability.

probeSandboxInferenceGatewayHealth executes inside the sandbox, but collectInferenceChecks runs it for local providers even after liveSandboxCheck has marked the sandbox unreachable. Pass sandbox.reachable into inference collection and skip this subprobe when the sandbox is not ready.

Suggested direction
 async function collectInferenceChecks(
   sandboxName: string,
   route: InferenceRoute,
+  sandboxReachable: boolean,
 ): Promise<DoctorCheck[]> {
@@
-  if (isLocalInferenceProvider(route.provider)) {
+  if (sandboxReachable && isLocalInferenceProvider(route.provider)) {
     const gateway = await probeSandboxInferenceGatewayHealth(sandboxName);
-    ...(await collectInferenceChecks(sandboxName, route)),
+    ...(await collectInferenceChecks(sandboxName, route, sandbox.reachable)),

Also applies to: 902-908

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/actions/sandbox/doctor.ts` around lines 768 - 770, Gate the
in-sandbox inference gateway probe on sandbox reachability:
`collectInferenceChecks` currently calls `probeSandboxInferenceGatewayHealth`
for local providers even when `liveSandboxCheck` has already determined the
sandbox is unreachable. Pass `sandbox.reachable` into `collectInferenceChecks`
(and any related inference-check helper) and skip the
`probeSandboxInferenceGatewayHealth` path when the sandbox is not reachable,
while keeping the existing local-provider logic intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/actions/sandbox/doctor-report.ts`:
- Around line 17-24: `DoctorReport.status` is inconsistent with
`buildDoctorReport()` and `renderSummary()`, because the exported type still
permits `"info"` even though it is not produced and is rendered as a generic
fallback. Update the `DoctorReport` type and any related `DoctorStatus` usage in
`doctor-report` so the status contract matches actual behavior, either by
narrowing it to `"ok" | "warn" | "fail"` or by adding explicit `"info"` handling
in `renderSummary()` and the report-building path.

In `@src/lib/actions/sandbox/doctor.ts`:
- Around line 608-610: The gateway probe in collectDoctorChecks still allows
recovery behavior for doctor --json because intent.asJson is dropped before
calling probeOpenShellGateway. Update collectDoctorChecks and
probeOpenShellGateway to accept and forward a read-only/no-recovery flag based
on the JSON intent, and ensure recoverNamedGatewayRuntime is not invoked for
JSON runs so gateway probing remains non-destructive.
- Around line 107-113: The gateway port validation in gatewayPortCheck is using
the process-global GATEWAY_PORT instead of the sandbox’s persisted gateway port,
which can cause false mismatches. Update the Docker port check to use the
sandbox binding-derived port from the same source used to resolve gatewayName,
and keep the expected host port hint aligned with that persisted value. Also
remove the duplicate source of truth in the related occurrences referenced by
the same check so all gateway validation paths compare against the
sandbox-specific port consistently.

---

Nitpick comments:
In `@src/lib/actions/sandbox/doctor.ts`:
- Around line 768-770: Gate the in-sandbox inference gateway probe on sandbox
reachability: `collectInferenceChecks` currently calls
`probeSandboxInferenceGatewayHealth` for local providers even when
`liveSandboxCheck` has already determined the sandbox is unreachable. Pass
`sandbox.reachable` into `collectInferenceChecks` (and any related
inference-check helper) and skip the `probeSandboxInferenceGatewayHealth` path
when the sandbox is not reachable, while keeping the existing local-provider
logic intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 979b5bd2-82ef-4e04-85e5-c15a2e9b8e4e

📥 Commits

Reviewing files that changed from the base of the PR and between 1c27f5b and a726a55.

📒 Files selected for processing (3)
  • biome.json
  • src/lib/actions/sandbox/doctor-report.ts
  • src/lib/actions/sandbox/doctor.ts

Comment thread src/lib/actions/sandbox/doctor-report.ts
Comment thread src/lib/actions/sandbox/doctor.ts Outdated
Comment thread src/lib/actions/sandbox/doctor.ts
Signed-off-by: Carlos Villela <cvillela@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/lib/actions/sandbox/doctor-flow.test.ts (1)

244-246: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert doctor output, not helper wiring.

These cases are pinned to recoverNamedGatewayRuntime, captureOpenshell, and buildToolScopeChecks call patterns instead of the observable runSandboxDoctor result. That makes the tests brittle across equivalent refactors and weakens the migration proof. Prefer asserting the emitted checks / JSON report (for example, no live-sandbox or tool-scope entries, and no repair result) rather than whether private helpers were called or which boolean was passed to them. As per path instructions, "Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions."

Also applies to: 259-260, 286-291, 308-308

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/actions/sandbox/doctor-flow.test.ts` around lines 244 - 246, The
doctor-flow tests are asserting private helper wiring instead of the observable
`runSandboxDoctor` output, making them brittle. Update the affected cases in
`doctor-flow.test.ts` to verify the emitted checks/JSON report from
`runSandboxDoctor` (for example, absence of live-sandbox or tool-scope entries
and no repair result) rather than `recoverNamedGatewayRuntime`,
`captureOpenShell`, or `buildToolScopeChecks` spy calls or their boolean
arguments. Use the public result shape as the assertion target so refactors of
internal helpers do not break the tests.

Source: Path instructions

src/lib/actions/sandbox/doctor-system-checks.ts (1)

190-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bound this legacy gateway fallback with an explicit retirement plan.

This preserves the recorded-driver path and the older platform-detection fallback, but the migration guidance requires retained compatibility paths to name the GitHub retirement work and the observable condition for removing them.

As per path instructions, “Retain an old path only for a demonstrated external/persisted-data contract or a bounded confidence/rollback window… link the retirement issue or PR in GitHub, and state observable exit criteria.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/actions/sandbox/doctor-system-checks.ts` around lines 190 - 198,
Update shouldInspectLegacyGatewayContainer to keep the legacy platform-detection
fallback, but document it with an explicit retirement reference and exit
criteria. Add a comment near the recorded-driver logic and the
isLinuxDockerDriverGatewayEnabled fallback that names the GitHub issue/PR
tracking removal of the legacy gateway path and states the observable condition
for deleting it. Preserve the existing behavior for SandboxEntry.openshellDriver
while making the legacy path clearly time-bounded and tied to the retirement
work.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/actions/sandbox/doctor-messaging.ts`:
- Around line 100-119: channelRuntimeDoctorCheck currently re-reads the sandbox
from registry and swallows registry/loadAgent failures by returning null, which
hides broken agent/config states. Update collectMessagingDoctorChecks and
channelRuntimeDoctorCheck to use the already-available SandboxEntry sb as the
source of truth, and when sandbox resolution or loadAgent fails, return a
warning DoctorCheck instead of omitting the diagnostic. Keep the runtime probe
flow intact for valid agents, and reference channelRuntimeDoctorCheck,
collectMessagingDoctorChecks, and loadAgent when making the change.

---

Nitpick comments:
In `@src/lib/actions/sandbox/doctor-flow.test.ts`:
- Around line 244-246: The doctor-flow tests are asserting private helper wiring
instead of the observable `runSandboxDoctor` output, making them brittle. Update
the affected cases in `doctor-flow.test.ts` to verify the emitted checks/JSON
report from `runSandboxDoctor` (for example, absence of live-sandbox or
tool-scope entries and no repair result) rather than
`recoverNamedGatewayRuntime`, `captureOpenShell`, or `buildToolScopeChecks` spy
calls or their boolean arguments. Use the public result shape as the assertion
target so refactors of internal helpers do not break the tests.

In `@src/lib/actions/sandbox/doctor-system-checks.ts`:
- Around line 190-198: Update shouldInspectLegacyGatewayContainer to keep the
legacy platform-detection fallback, but document it with an explicit retirement
reference and exit criteria. Add a comment near the recorded-driver logic and
the isLinuxDockerDriverGatewayEnabled fallback that names the GitHub issue/PR
tracking removal of the legacy gateway path and states the observable condition
for deleting it. Preserve the existing behavior for SandboxEntry.openshellDriver
while making the legacy path clearly time-bounded and tied to the retirement
work.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ea65b6aa-e09e-4f54-9e2e-edcae770e608

📥 Commits

Reviewing files that changed from the base of the PR and between a726a55 and 935afcb.

📒 Files selected for processing (6)
  • biome.json
  • src/lib/actions/sandbox/doctor-flow.test.ts
  • src/lib/actions/sandbox/doctor-messaging.ts
  • src/lib/actions/sandbox/doctor-report.test.ts
  • src/lib/actions/sandbox/doctor-system-checks.ts
  • src/lib/actions/sandbox/doctor.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/actions/sandbox/doctor.ts

Comment thread src/lib/actions/sandbox/doctor-messaging.ts
cv added 2 commits June 27, 2026 14:29
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/actions/sandbox/doctor-system-checks.test.ts`:
- Around line 20-26: The test for doctor system checks is using branching logic
inside the subprocess mock, which lets the test decide behavior instead of
verifying it linearly. Update the mock in doctor-system-checks.test.ts to return
the two expected subprocess results in a fixed order for the relevant calls, and
remove the conditional handling from the mockImplementation. Keep the assertions
tied to the existing doctor-system-checks flow so the test stays a straight
behavior check without internal branching.
- Line 13: The test cleanup in doctor-system-checks.test.ts is using the
unavailable global require, which can throw inside afterEach and break later
tests. Update the cache invalidation logic to use the existing
createRequire-based requireDist reference instead of require, and keep the cache
deletion scoped to the modulePath resolved via requireDist so the test teardown
remains safe.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: aac754dc-fcae-4c21-a238-a4235ae43397

📥 Commits

Reviewing files that changed from the base of the PR and between 935afcb and 22812b6.

📒 Files selected for processing (5)
  • src/lib/actions/sandbox/doctor-flow.test.ts
  • src/lib/actions/sandbox/doctor-report.ts
  • src/lib/actions/sandbox/doctor-system-checks.test.ts
  • src/lib/actions/sandbox/doctor-system-checks.ts
  • src/lib/actions/sandbox/doctor.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/lib/actions/sandbox/doctor-report.ts
  • src/lib/actions/sandbox/doctor-flow.test.ts
  • src/lib/actions/sandbox/doctor-system-checks.ts
  • src/lib/actions/sandbox/doctor.ts

Comment thread src/lib/actions/sandbox/doctor-system-checks.test.ts Outdated
Comment thread src/lib/actions/sandbox/doctor-system-checks.test.ts Outdated
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

Automated-review follow-up for 58a2e46c8:

  • The earlier report-test blocker is resolved by doctor-report.test.ts: six cases cover empty/info/warn/fail aggregation, schema/counts, JSON output and exit code, preferred/extra group ordering, hints, and text summary rendering.
  • doctor.ts is now the orchestration boundary (884 → 506 lines). Messaging diagnostics (258 lines), report rendering (112 lines), and host/gateway/local-service checks (200 lines) are separate cohesive modules; splitting each remaining collector into another file here would fragment the ordered diagnostic transaction without removing more responsibility.
  • The complexity-10 override is intentional and applies only to these four doctor modules. The full Biome/all-files hook suite passes with it.
  • Messaging and system modules retain existing helper/process coverage; new tests add agent-definition failure visibility and exact persisted gateway-port matching. The 12-case doctor CLI process suite and the exact CI shard (2/5, 1,631 tests with coverage) pass locally.
  • PR fix(messaging): surface telegram config inputs in channels status #5705 overlaps this file. Recommended sequencing is to land this extraction first, then rebase fix(messaging): surface telegram config inputs in channels status #5705 so its messaging change targets doctor-messaging.ts instead of restoring logic to the orchestration module.

cv added 2 commits June 27, 2026 14:45
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

Resolved PRA-1 and PRA-2 in 6424638. The invalid state was a disconnected named gateway or non-ready sandbox followed by sandbox-exec inference and messaging probes. The authoritative boundary is the gateway lifecycle plus live sandbox-list result collected once by collectDoctorChecks; that reachability value is now threaded into both collectors. Registry-only diagnostics still run, while live probes render explicit skipped checks. The flow regression configures ollama-local plus enabled Telegram behind a disconnected named gateway and proves neither sandbox-exec path runs. This is a permanent orchestration invariant rather than a compatibility workaround, so there is no later removal condition.

@cv

cv commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

Resolved GPT advisor PRA-T1 in 0f67897. The new public-flow regression starts plain doctor with a missing named gateway, returns a healthy recovered gateway, and verifies sandbox discovery plus inference, messaging runtime, and tool-scope probes run only after recovery.

@cv

cv commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator Author

Final advisor follow-ups: the positive and negative reachability contracts are covered at the exported runSandboxDoctor flow boundary, including recovery ordering, JSON non-recovery, and proof that sandbox-exec probes stay gated. A live fault-injection test that deliberately removes and recovers a named gateway would expand this refactor into environment-reliability E2E work; the existing process scenarios plus the full self-hosted sandbox, gateway-isolation, port-override, and non-root matrix are green, so PRA-T1/PRA-T2 are justified as unnecessary for this PR. Nemotron reported its own advisor analysis unavailable, but GPT-5.5 completed on the same final head with merge_as_is, CodeRabbit completed, and the manual review plus all CI gates are green.

@cv
cv merged commit 50cb04b into main Jun 27, 2026
41 checks passed
@cv
cv deleted the codex/refactor-doctor-complexity branch June 27, 2026 22:28
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Replaces the 114-complexity sandbox doctor command with a narrow
orchestration layer and cohesive reporting, messaging, and
system-diagnostic modules. `doctor.ts` shrinks from 884 lines to 531,
while a file-scoped Biome ratchet caps every function in the doctor
surface at cognitive complexity 10.

## Changes

- isolate doctor report aggregation, text rendering, and JSON rendering
in `doctor-report.ts`
- extract messaging/runtime-channel diagnostics and
host/gateway/local-service diagnostics into focused modules
- express host, gateway, sandbox, inference, registered-sandbox,
tool-scope, and local-service execution as ordered collectors
- keep `doctor --json` read-only by probing gateway state without
invoking recovery
- keep registry diagnostics available offline while gating
inference-gateway and messaging-runtime sandbox probes on collected
reachability
- validate legacy gateway port mappings against each sandbox's persisted
gateway binding
- add negative tests for missing OpenShell, disconnected gateways,
read-only diagnostics, and non-OpenClaw tool-scope gating
- verify report aggregation/rendering and ensure local inference
diagnostics do not mutate provider-health results
- enforce a cognitive-complexity ceiling of 10 across all doctor modules

## Type of Change

- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Quality Gates

- [x] Tests added or updated for changed behavior
- [x] Existing tests cover changed behavior — justification: the
existing doctor helper suites and 12 CLI process scenarios continue to
cover end-to-end diagnostics; new focused tests cover the extracted
boundaries, report contract, persisted-port matching, and negative
orchestration gates.
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: the command reference already
defines `--json` as report-only and mutually exclusive with `--fix`;
this change makes the implementation honor that existing contract.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: self-review confirmed
diagnostic ordering, repair/recovery gating, process exits, and output
contracts; the full repository hook and coverage suite passes.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [x] Targeted tests pass for changed behavior
- [ ] Full `npm test` passes (broad runtime changes only)
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
Signed-off-by: Carlos Villela <cvillela@nvidia.com>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Sandbox “doctor” diagnostics now generate a structured, grouped report
with colored status labels, optional per-check hints, and a JSON output
mode.
* Added dedicated diagnostics for messaging channels/runtime registry,
gateway/container health, local tunnel/service state, and Ollama
reachability.
* **Bug Fixes**
* Improved gating so recovery/repairs and certain probes run only when
prerequisites are met; JSON runs remain read-only.
* Messaging runtime registry failures now surface as warnings without
hiding related messaging checks.
* **Tests**
* Expanded coverage for report formatting, system checks, and doctor
flow gating scenarios.
* **Chores**
  * Tightened complexity linting for sandbox doctor action modules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@wscurran wscurran added the area: cli Command line interface, flags, terminal UX, or output label Aug 1, 2026
@wscurran wscurran added area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery refactor PR restructures code without intended behavior change labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery refactor PR restructures code without intended behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants