[rush-daemon][WS2.4][3/9] Route phased requests - #2
Open
mojaza wants to merge 1 commit into
Open
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
The router currently does not robustly validate enabledState values from the wire, which can cause invalid selections to be silently misinterpreted.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds an opt-in WS2.4 routing layer that accepts an integration-resolved phased request and executes it against a warm IOperationGraph, scoping streamed output/events and results to the requesting client while preserving the graph’s long-lived lifecycle.
Changes:
- Introduces
PhasedRequestRouterto validate request identity/shape/selection, reconcile invalidations, apply enabled-states, and run at most one warm iteration with serialization across shared graphs. - Adds a client-scoped event sink + event multiplexer to forward WS1 events and stdout/stderr chunks in-order with backpressure handling and deterministic unsubscribe/cleanup.
- Extends the rush-daemon protocol with typed phased-request contracts, exports new public APIs, and updates docs/API review files + lockfiles.
File summaries
| File | Description |
|---|---|
| libraries/rush-daemon/src/PhasedRequestRouter.ts | New router that serializes phased requests, validates shape/selection, applies enabled states, schedules/executes one warm iteration, and collects client-scoped results. |
| libraries/rush-daemon/src/PhasedRequestEventSink.ts | New _IOperationGraphEventSink that filters to a client’s active closure and performs ordered, backpressured writes for events and log chunks. |
| libraries/rush-daemon/src/PhasedRequestEventMultiplexer.ts | New graph-level multiplexer preserving an integration-owned sink while attaching/detaching a single active request sink. |
| libraries/rush-daemon/src/PhasedRequestClient.ts | New client contract for backpressured event/log chunk writes with abort signaling. |
| libraries/rush-daemon/src/index.ts | Exports IPhasedRequestClient and PhasedRequestRouter. |
| libraries/rush-daemon/src/test/PhasedRequestRouterTestUtilities.ts | Test fixtures for warm OperationGraph routing, runners, and a capturing client. |
| libraries/rush-daemon/src/test/PhasedRequestRouter.test.ts | Coverage for selection/shape validation, invalidation ordering, dependency closure, write ordering/backpressure, abort/disconnect, hook failures, and shared-graph serialization. |
| libraries/rush-daemon/README.md | Documents the new opt-in router boundary and its non-goals/limitations. |
| libraries/rush-daemon/package.json | Adds @rushstack/terminal dependency for new runtime/test usage. |
| libraries/rush-daemon-protocol/src/DaemonPhasedRequest.ts | New phased-request wire contracts (engine shape, selection, per-operation results, request result). |
| libraries/rush-daemon-protocol/src/index.ts | Exports phased-request protocol types. |
| libraries/rush-daemon-protocol/README.md | Notes phased-request contracts as part of the protocol’s capabilities. |
| common/reviews/api/rush-daemon.api.md | API review updates for PhasedRequestRouter and IPhasedRequestClient. |
| common/reviews/api/rush-daemon-protocol.api.md | API review updates for new phased-request protocol types. |
| common/config/subspaces/default/pnpm-lock.yaml | Lockfile updates for added dependency and related snapshot churn. |
| common/config/subspaces/default/repo-state.json | Updates shrinkwrap hash after lockfile changes. |
| common/changes/@rushstack/rush-daemon/mojazayeri-route-phased-requests_2026-08-21-17-24.json | Change entry for @rushstack/rush-daemon (minor). |
| common/changes/@rushstack/rush-daemon-protocol/mojazayeri-phased-request-contracts_2026-08-21-17-24.json | Change entry for @rushstack/rush-daemon-protocol (minor). |
Review details
Files not reviewed (1)
- common/config/subspaces/default/pnpm-lock.yaml: Generated file
- Files reviewed: 17/18 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+325
to
+336
| function addSelectedOperation( | ||
| enabledState: DaemonPhasedOperationEnabledState, | ||
| operation: Operation, | ||
| enabledOperations: Operation[], | ||
| ignoreDependencyOperations: Operation[] | ||
| ): void { | ||
| if (enabledState === true) { | ||
| enabledOperations.push(operation); | ||
| } else { | ||
| ignoreDependencyOperations.push(operation); | ||
| } | ||
| } |
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.
Summary
PhasedRequestRouterover the real warmIWorkspaceSession/IOperationGraphsupplied by the integration boundary from merged [rush-daemon][WS2.3][2/9] Add warm engine component factory microsoft/rushstack#5949.Details
The router validates the request's explicit phase/plugin shape and integration-resolved operation identifiers, reconciles retained workspace invalidations before scheduling, clears and reapplies the requested enabled-state mapping through
IOperationGraph.setEnabledStates, and runs at most one manually scheduled warm iteration. Safe selection expands the requesting client's dependency closure, while missing operations remain disabled.A stable graph-level event multiplexer preserves any integration-owned Rush dual-emit sink while attaching only the active client's selected closure. Raw stdout/stderr chunks and structured WS1 events are forwarded in engine order through serialized async writes, honoring destination backpressure. Client subscriptions detach deterministically after completion, failure, abort, or disconnect, including from operation records retained by the warm graph. Event sequences remain monotonic per client session.
Requests sharing a warm graph are serialized until the later shared-build merging layer. Cancellation and disconnect abort only the current iteration under the existing graph contract; the router never aborts the daemon graph lifetime or closes its runners. Results are scoped to the enabled client closure and retain prior successful outcomes when real graph hooks collapse a repeated warm request to no work.
Limitations
Open microsoft#5895 still lacks a command-independent plugin/phase shape and complete per-iteration runner-lifetime support. This PR therefore begins after an integration has parsed a phased command, supplied the exact warm engine shape, and resolved real graph operation identifiers. It does not duplicate
PhasedScriptAction, construct a fake or empty graph, claim unsupported command/plugin graph construction, or add control-frame command admission. The default executable remains opt-in/dead-code-safe with noapps/rushorrush-liblauncher integration.This layer also does not implement WS2.5 request cwd/env/terminal context, WS2.6 exit-code/warnings policy parity, WS2.7 stdin/raw-mode/PTY behavior, WS2.8 command classification or wait/no-wait wire admission, or WS2.9 concurrent shared-build selection merging.
The Rush dual-emit callback is synchronous, so the router preserves frame order and serializes all destination writes against transport backpressure, but cannot pause an operation producer while an already-emitted chunk awaits the client.
How it was tested
node common/scripts/install-run-rush.js installnode common/scripts/install-run-rush.js test --only @rushstack/rush-daemon-protocol --only @rushstack/rush-daemonOperationGraphcoverage for selection/shape validation, invalidation-before-schedule ordering, dependency closure, exactly one warm iteration, client-only streams/events, ordered async writes, operation failures, cancellation, disconnect/write failure, stale subscription cleanup, scheduling-hook failures, cross-router serialization, monotonic event sequences, and repeated warm no-op retained results.