Repository navigation
fix(client): accept legacy config without reconnect loops - #15402
ronak-guliani wants to merge 1 commit into
Conversation
Normalize legacy writing-style strings without changing modern encoding. Classify config schema incompatibility as unsupported and retain that failure through session termination. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused compatibility fix that accepts the legacy settings representation and turns incompatible server-config decoding into a stable unsupported state instead of a reconnect loop. Modern settings encoding, ordinary transport handling, and existing defaults remain unchanged, with targeted tests covering the new paths. Notes:
You can add or adjust custom eligibility rules. Learn more. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (5)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe changes add legacy string decoding for source-control writing-style settings. RPC sessions now classify incompatible server configuration as unsupported and distinguish connection-establishment failures from later socket disconnects. ChangesSettings and connection handling
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant ConfigSubscription
participant RpcSession
participant Supervisor
participant Registry
ConfigSubscription->>RpcSession: Sends initial snapshot or config update
RpcSession->>Supervisor: Reports decode failure as unsupported
Supervisor->>Registry: Reports unsupported environment
Registry->>Registry: Disables environment until compatibility is restored
Suggested reviewers: Merge Risk: ⚪ Minimal · up to The changes are mergeable after normal checks. The available evidence identifies no actionable compatibility or connection-handling failure. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The compatibility change maps legacy values into an existing settings representation without demonstrating new privileges. Incompatible configurations now stop reconnecting. Risk remains low rather than minimal because early-disconnect handling and complete recovery and configuration-provenance paths remain unverified. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 4 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Dismissing prior approval to re-evaluate dc6534f
|
Taking over this one as maintainer for batch ssh-relay-remote-08. The connection runtime has moved since this branch was written, so I will rebuild from current main as two reviewable stack layers: legacy settings decoding, then terminal incompatible-config classification, preserving heartbeat timeout diagnostics. I will credit your original work and close this PR only after the replacement stack is published and compared against your diff. |
|
Thanks @ronak-guliani — this correctly identified the legacy string-valued writing style and the need to let the config subscription retain incompatible-config errors. I rebuilt it against current main because the shared runtime and heartbeat handling have moved, and split the two concerns into the published stack:
I compared your complete original diff against both layers. All intended behavior is retained. The original schema also broadened project writes accidentally; the lower layer preserves that strict boundary. The config-stream approach needed the current heartbeat timeout hook to preserve “stopped responding”; that is in the upper layer. The internal documentation paragraphs were replaced by two short comments at the actual ordering constraints. The original eight cases were replaced by six behavior cases in the existing test files, with existing heartbeat/legacy tests strengthened: 296 passing plus six regressions on main → 302/302 here, scoped lint/format/typechecks passing. Both independent full-stack reviews (Claude Opus 5.5 and GPT-6 Sol) found no actionable issues. Live Chromium verification used the actual client/server with disposable wire frames: legacy bootstrap shows normalized instructions, malformed initial and later configs close their sockets and disable the environment, and modern frames recover after reload. Proof and platform limits are in both replacement descriptions; actual old binaries and native platforms remain unverified. CI is running on the published stack; neither layer is merged. Existing recovery policy still refuses re-enable while unsupported is recorded; recovery uses rediscovery/restart, re-onboarding or the host-update flow. Non-default config consumers and the legacy probe retain pre-existing defect behavior outside this always-on subscription. Those do not block this fix and are recorded on the upper layer. Closing this superseded PR in favor of the linked stack, with credit preserved in both descriptions. |
Problem
An Official 0.0.42 client connected to a Dev 0.0.23 server repeatedly opens only
subscribeServerConfig, then disconnects before readiness. The first real config chunk contains a string-valuedsettings.sourceControlWritingStyle; the newer client requires an object. Its decoder dies withSchemaError, and the supervisor treats that as a transient transport failure, indefinitely retrying.The installed production factory reproduced this failure against an isolated copy of the installed Dev server: one config subscription, a received chunk, failed readiness, and a clean client close with code 1000. A matching Official server succeeds. No live applications, authentication database, or running user server were changed.
Change
Accept legacy writing-style strings in the shared contract: empty/whitespace values become repository conventions, and non-empty instructions become custom mode. Keep modern object encoding and structured settings patches unchanged.
Convert config schema defects into
ConnectionBlockedError(reason="unsupported"). Let the always-on config subscription own readiness and termination, so the disconnect hook cannot mask that failure as transient. The existing registry then disables an incompatible environment rather than automatically retrying. Ordinary transport failures, opening timeouts, heartbeat failures, and unrelated defects retain their existing classifications.This is read compatibility for the identified bootstrap field, not a promise that every RPC or mutation across a nineteen-release gap is compatible. The separate Dev client's brief-disconnect toast and the server's session-inactive logging gap are not claimed fixed.
Scope and approval
Focused obvious-bug exception: a demonstrated config decode regression prevents an otherwise authenticated session from becoming ready. The contract repair and terminal-error classification address that same bootstrap reconnect loop; no new setting, workflow, or server wire rewrite is introduced. Changes are upstream-based because the incompatible production decoder is not in the older fork.
Verification
Tested code:
dc6534f5bc(the commit contains the same code exercised in the browser; the real-socket probe was repeated after committing).cd packages/client-runtime && pnpm test src/rpc/session.test.tsbefore production editscd packages/client-runtime && pnpm test src/rpc/session.test.ts src/connection/supervisor.test.ts src/state/server.test.tscd packages/contracts && pnpm test src/settings.test.tspnpm fmt:checkpnpm lintpnpm typecheckReal legacy server: run the production source
RpcSessionFactoryagainst an isolated installed Dev 0.0.23 server, without rewriting its response. The string config decoded successfully; readiness and probes before/after a 35-second hold passed, heartbeats exchanged ping/pong, exactly one config subscription was opened, and no active-period socket closed. The reproducible probe and revision-bound report are retained as session artifacts, not committed.Real web client: authenticated a worktree-isolated web app and replaced only external config fields as a controlled wire fixture. A legacy instruction string established a connected production session, normalized to custom mode, and rendered unchanged instructions in Source Control settings. A separate malformed
cwd: 42config was recorded as unsupported, disabled the environment through the real registry, and produced only one socket open over a 71-second observation. Removed the fixture, restored compatibility, and verified a normal connected state.The browser fixture does not claim to be a full old-server UI integration; the independent socket experiment uses the actual unmodified legacy server. Captures illustrate current modern-control and legacy-normalization states, not a reconstructed pre-fix Electron screenshot. Pre-authentication socket rejections and an initial IPv4 navigation failure were observed before pairing. There were no application-console errors during authenticated checks, but four environment-descriptor requests were aborted during the scripted reconnect/cleanup phase. The browser pass establishes the asserted production runtime states and rendering, not an entirely error-free network smoke check. A provider-authentication warning was present but unrelated; no provider turn was started.
pnpm test:selfandpnpm pr:mediaare not scripts in this upstream checkout. Attempted media publication using the fork's existing tool:Publication blocked: capture decoding passed, but GitHub attachment upload returned HTTP 404 (exit 1). Verified that no attachment URLs were recorded and no media section was published. Inspected, privacy-cropped screenshots and a 20-second recording remain in local session artifacts; they are not committed. No full server test suite was run, and no unrelated pre-existing fork failures were investigated.
Model: GPT-6.1 Sol. Harness: GitHub Copilot in T3 Code.