fix(onboard): match mux-delegated ssh forwards in untracked-forward fallback (#6099) - #6833
Conversation
…allback (NVIDIA#6099) Under `Host *` / `ControlMaster auto` ssh config, the ssh client spawned by `openshell forward start --background` delegates its -L forward to the ControlMaster mux daemon and exits. openshell 0.0.72+ reports this as "ssh exited before local forward listener opened", which the untracked-forward fallback regex did not match, so the live-port probe never ran and onboard timed out and rolled back a healthy sandbox — even though the mux daemon holds the listener and the dashboard serves HTTP 200 throughout. Extend looksLikeUntrackedForward to also match the openshell 0.0.72 diagnostic variants. Confirmation still requires the live-port probe, and the EADDRINUSE conflict check still runs first, so a genuinely failed ssh keeps timing out as before. Verified on a clean macOS 26.5 / Colima host (nemoclaw v0.0.81, openshell 0.0.72): onboard succeeds without ControlMaster, reproduces the NVIDIA#6099 rollback with ControlMaster auto, and the captured failure diagnostic matches the added patterns. Signed-off-by: Tedy Yu <tedyy@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe forward-start diagnostic matcher now recognizes additional mux-delegated SSH errors. Tests cover confirming an untracked forward through a live local port and timing out when that port remains unavailable. ChangesForward diagnostics
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant ForwardStart
participant ForwardList
participant IsPortListening
ForwardStart->>ForwardList: Poll forward registration
ForwardList-->>ForwardStart: Empty
ForwardStart->>IsPortListening: Probe local port
IsPortListening-->>ForwardStart: Live or not live
ForwardStart-->>ForwardStart: Confirm or continue until timeout
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
PR Review Advisor — InformationalAdvisor assessment: Informational / medium confidence Model lanes
Nemotron is a non-blocking second opinion. Its prose, findings, and E2E guidance do not change the primary assessment above and remain in workflow artifacts only. E2E guidanceAdvisory only: coverage and selector recommendations are non-authoritative. E2E / PR Gate independently computes and dispatches trusted jobs without consuming this output. Recommended coverage:
2 optional coverage items · 2 optional selectors · 0 new-test recommendations
This is an automated, non-authoritative review. Findings are inputs to maintainer adjudication. Warnings and optional suggestions do not require a response or follow-up. A human maintainer makes the final merge decision. |
|
Maintainers: this PR trips the fork E2E gate because the diff touches onboarding, selecting the credential-bearing No fork code ran and no secret was exposed (fail-closed state); all other checks are green — cli tests, shards, typecheck, and sandbox image builds. Happy to address any review feedback on the change itself. |
|
Empirical validation of this fix on the same clean macOS 26.5 / Colima reproduction host (v0.0.81 install,
One observation for reviewers: as with the existing #6099 fallback semantics, the confirmed forward remains untracked in |
## Summary Add v0.0.83 release notes to `docs/about/release-notes.mdx` for pre-tag release prep. ## Source Summary - #6773 -> `docs/about/release-notes.mdx`: Shared inference route changes are explicit and fail-safe; status shows recorded route, live route, and drift. - #6875 -> `docs/about/release-notes.mdx`: DGX Station GB300 express setup restored; vLLM storage preflight narrowed. - #6770 -> `docs/about/release-notes.mdx`: Risky Spark vLLM server warning during onboarding. - #6856 -> `docs/about/release-notes.mdx`: Re-onboard reuse preserves tier-default brave/tavily presets. - #6867 -> `docs/about/release-notes.mdx`: Unreachable custom endpoint routed through transport-recovery path. - #6860 -> `docs/about/release-notes.mdx`: Rebuild preflight uses model-aware token field for o-series/GPT-5. - #6845 -> `docs/about/release-notes.mdx`: Corporate CA anchored for image build TLS. - #6833 -> `docs/about/release-notes.mdx`: SSH ControlMaster-delegated forwards recognized in fallback. - #6837 -> `docs/about/release-notes.mdx`: Hermes light skin writes via stdin on macOS. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] 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: - [x] Tests not applicable — justification: doc-only release notes - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed - [ ] Non-success, skipped, or missing CI check accepted by maintainer ## Verification - [x] PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub - [x] Normal pre-commit, commit-msg, and pre-push hooks passed - [x] `npm run docs` passes with 0 errors Signed-off-by: Jessica Yaunches <jyaunches@nvidia.com> Signed-off-by: Jessica Yaunches <jyaunches@nvidia.com>
Summary
nemoclaw onboardstill deletes a healthy sandbox after "forward did not appear in list within 180000ms" in NemoClaw v0.0.81 even previous fix #6116 is merged. One reproducible case is when the host's ssh config appliesControlMaster autoto the sandbox host: the spawned ssh client delegates its-Lforward to the ControlMaster mux daemon and exits, and openshell 0.0.72+ reports that exit asssh exited before local forward listener opened— a diagnostic the untracked-forward fallback regex does not match (due to openshell's recent code change in crates/openshell-cli/src/ssh.rs#419), so the live-port probe never runs. After this change the fallback recognizes the untracked port-forward and confirms the forward via the existing live-port probe instead of rolling back.Related Issue
Fixes #6099
Changes
looksLikeUntrackedForward()insrc/lib/onboard/forward-start.tsto also match the openshell 0.0.72 diagnostic variants (ssh exited before local forward listener opened,local forward listener was not reachable), and document the ControlMaster mux-delegation mechanism. Confirmation still requires the live-port probe, and the EADDRINUSE conflict check still runs first, so a genuinely failed ssh (no listener) keeps timing out exactly as before.ok-port-livefor a mux-delegated forward with a live port, and a negative test proving the same diagnostic without a live port still times out.Type of Change
Quality Gates
Verification
Verifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run check:diffpassed when hooks were skipped or unavailablenpx vitest run --project cli src/lib/onboard/forward-start.test.ts→ 27 passed (24 existing + 3 new)npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result:npm run docsbuilds without warnings (doc changes only)Reproduction evidence
A/B verified on a clean macOS 26.5 / Colima (aarch64) host with nemoclaw v0.0.81 + openshell 0.0.72:
openshell forward list.Host */ControlMaster auto+ControlPersist 600in~/.ssh/config: onboard fails with the exact [macOS][Onboard] nemoclaw onboard deletes the created sandbox after dashboard port-forward "did not appear in list within 180000ms" #6099 signature and deletes the sandbox. Captured mid-failure: the ControlMaster mux daemon (ssh: ~/.ssh/sockets/<user>@sandbox-22 [mux], ppid 1) holds127.0.0.1:18789 LISTEN, the dashboard answers HTTP 200, whileopenshell forward liststays empty — the exact condition the extended fallback now confirms.openshell forward start -d 127.0.0.1:18999 <sandbox>in the same state errors withssh exited before local forward listener opened on 127.0.0.1:18999while the mux picks up the port anyway, confirming the diagnostic text this PR adds to the regex.A complementary root-cause option (out of scope here) is for openshell to spawn its forward ssh with
-o ControlMaster=no -o ControlPath=none, which would also keepforward listtracking accurate under multiplexed ssh configs.🤖 Generated with Claude Code
Signed-off-by: Tedy Yu tedyy@nvidia.com
Summary by CodeRabbit