Make the router's routing state authoritative instead of sniffed - #630
Draft
GoodForOneFare wants to merge 1 commit into
Draft
Make the router's routing state authoritative instead of sniffed#630GoodForOneFare wants to merge 1 commit into
GoodForOneFare wants to merge 1 commit into
Conversation
GoodForOneFare
force-pushed
the
gordo-stdout-router-reenable
branch
from
August 14, 2026 19:33
bb136f6 to
d9e06ba
Compare
GoodForOneFare
force-pushed
the
gordo-stdout-router-reenable
branch
5 times, most recently
from
August 17, 2026 14:09
812ee3f to
cce3eac
Compare
Disabling restored write while leaving the compatibility marker behind, so marker sniffing could report a routed stream after routing had stopped. That made re-enabling unreliable and let captures silently miss output. Track active streams in a weak identity registry. Enable is additive, disable can target one stream or drain every live route, and with_enabled unwinds only streams activated by its scope. Roll back only newly activated streams if a later activation fails. Have Capture establish that scope itself so partially replaced stdout/stderr globals are routed for the capture without disturbing existing routes. Expose routed? and a read-only routed_streams snapshot while retaining enabled? compatibility. Pin write_without_cli_ui and write_without_routing to the pre-routing write so later wrappers cannot re-enter themselves. Keep ownership with the stream, preflight foreign compatibility markers, and decline rather than stack a second router from another cli-ui copy. Require Writer's original write explicitly, preserve pre-existing singleton writes, and let abandoned caller-owned streams fall out of the weak registry without an explicit disable. Co-authored-by: River <river@shopify.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Assisted-By: devx/c0685ec8-2be2-4abc-9131-691e185f92ae
GoodForOneFare
force-pushed
the
gordo-stdout-router-reenable
branch
from
August 27, 2026 20:25
cce3eac to
63edccc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
StdoutRouter.disablerestored the originalwritemethod but left thewrite_without_cli_uicompatibility method installed. Becauseenabled?inferred routing from that method, the process could reach a contradictory state:enabled?still returnedtrue,enablerefused to route the stream again,Capture#runaccepted the false-positive state and silently captured nothing.Resolving enable/disable only through the current
$stdoutand$stderralso orphaned routes when either global was replaced.with_enabledcompounded the problem by unconditionally disabling on exit, including routes that existed before entering its scope.Fix
Routing state now lives in a weak identity registry rather than being inferred from methods installed on a stream.
routed?(stream)checks the registry,enabled?remains as a compatibility alias, androuted_streamsreturns a read-only snapshot for inspection.enableis additive and per-stream. It routes the current$stdoutand$stderrwithout discarding routes temporarily displaced from those globals.disable(stream)removes one route; no-argumentdisabledrains every live registered route.with_enabledremembers only streams it newly routed and removes only those on exit. If a later stream fails to activate, activation rolls back only streams added by that attempt and preserves pre-existing routes.Captureestablishes the routing it needs.Capture#runexecutes insidewith_enabled, so disabled, half-routed, or partially replaced stdout/stderr globals are routed for the capture and restored afterward instead of raising or letting output escape.ObjectSpace::WeakMap; callers should still pair explicit enable/disable operations, but dropping a transient stream no longer pins it for the process lifetime.write_without_cli_uicloses over the stream's pre-routingwrite.write_without_routinguses the same method when available, so a laterwritewrapper can call either bypass without re-entering itself.Writerrequires the pre-routing method explicitly. This prevents accidentally constructing a Writer around an already-routedwrite, preserves pre-existing singleton wrappers during normal disable, and lets in-flight writes finish after deactivation.capture_iousewith_enabled, avoiding accidental long-lived routes.The earlier role-retagging and exact routing-state restoration layer was removed. Routing is additive and idempotent; scopes need only remember the streams they added, not rewrite the roles or wrappers of existing routes.
Tests
Coverage includes:
$stdout/$stderrreplacement,writewrappers,writerestoration,Validation:
630,20260817, and8675309, with one existing skip,🤖 Generated with LLM assistance
(posted by an LLM bot on behalf of Gord)