Skip to content

[rush reporter][R6A] Add bootstrap handoff and compatibility adapters - #5993

Merged
Sean Larkin (TheLarkInn) merged 70 commits into
mainfrom
copilot/reporter-r6a-bootstrap-handoff
Sep 11, 2026
Merged

[rush reporter][R6A] Add bootstrap handoff and compatibility adapters#5993
Sean Larkin (TheLarkInn) merged 70 commits into
mainfrom
copilot/reporter-r6a-bootstrap-handoff

Conversation

@TheLarkInn

@TheLarkInn Sean Larkin (TheLarkInn) commented Aug 28, 2026

Copy link
Copy Markdown
Member

Part of #5979.

Stack

graph LR
  M["main: Reporter core merged"] --> R6A["This PR: R6 bootstrap handoff"]
Loading

Base: main. All Reporter core prerequisites, including #5989 and #5988, have landed. The main-relative diff remains exactly 36 R6 paths. Bootstrap replay, compatibility, retention and initialization cleanup compose with the landed canonical unfiltered debug log. Parallel Heft, AI qualification and later follow-up features are not imported.

Merge remains gated on current-head CI and independent approval.

Design choice

Use a minimal prelude in the existing generated install-run-rush path rather than add a reporter-specific script variant. This keeps every existing bootstrap entry point and update mechanism intact, uses the frozen zero-dependency encoder/protocol major from #5986, and gates all changed visible behavior behind an explicit reporter request or the repository experiment.

The prelude parses only early reporter/log-level controls plus the comment-aware useRushReporter experiment. It incrementally builds a 1 MiB bounded NDJSON buffer, chunks external output at 64 KiB, preserves required records, evicts only replaceable activity status, appends the RFC truncation marker, and fails if required output cannot be retained. npm stdout/stderr are captured as ordered framed records with a hard capture ceiling and persistent UTF-8 decoding.

The handoff is written under the OS temp directory with owner-only permissions where supported, an exclusive filename, and a nonce duplicated in private path/nonce environment variables. The frontend creates the authoritative host before version selection, replays then deletes the file, clears the private environment, and sweeps abandoned files using the existing retention policy.

Compatibility behavior

  • No explicit or repository opt-in: the existing bootstrap logger, inherited npm output, and legacy Rush rendering are unchanged.
  • Explicit unsupported reporter/log-level requests fail before loading rush-lib; explicit protocol-major incompatibility fails with an update/use-legacy diagnostic.
  • Implicit environment detection does not enable the pre-major path. Repository opt-in safely falls back to legacy for an older frontend or incompatible handoff, replaying bounded raw fallback output instead of losing it.
  • New frontend + old engine: legacy engine output remains visible on stderr and is bridged as ordered externalOutput events without contaminating machine-reporter stdout.
  • Old frontend + new engine: the engine receives no host sink and retains the existing LegacyFallbackSink/legacy rendering behavior.
  • Direct rush invocation has no handoff and converges on the same authoritative frontend host used by bootstrap invocation.

Current landing qualification (September 11, 2026)

Published 67ac6545cad54d2234d4c723686c09c5a023661a preserves the former R6 head and landed main@130daa8 as its two parents. Normal consumer build/types/lint/API and 392 focused Linux tests passed, including full-debug canonical logs under file/normal, physical-close failures, initialization cleanup and concurrent shutdown. New hosted CI and human approval are still required.

Earlier validation (pre-landing snapshot)

  • node libraries/reporter/scripts/generateBootstrapProtocol.js --check
  • node common/scripts/install-run-rush.js test --only @rushstack/rush-reporter --only @microsoft/rush-lib --only @microsoft/rush
  • Built webpack install-run npm-capture smoke test using cowsay@1.6.0 (ordered stdout/stderr frames, no overflow)
  • node common/scripts/install-run-rush.js check
  • node common/scripts/install-run-rush.js change --verify --no-fetch
  • git diff --check

Focused coverage includes direct/bootstrap startup, replay/deletion, invalid path/nonce, missing/unreadable handoffs, permissions, abandoned cleanup, truncation and required overflow, ordered external output, UTF-8 boundaries, unsupported explicit requests, implicit fallback, and old/new frontend-engine combinations.

Rollback

Revert this single commit. The optional hooks in install-run disappear with the prelude, and the default no-opt-in bootstrap/legacy path remains the unchanged fallback throughout the rollout.

Non-goals

  • R5 operation rendering or replacing StreamCollator
  • Heft child protocol/problem matcher integration
  • agent auto-selection or the Rush 6 default flip
  • removing legacy terminal APIs, rendering, or fallback behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Create the authoritative frontend reporter host before version selection, register global reporter controls, and preserve legacy output unless a non-legacy reporter is explicitly selected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Consume the repository experiment before Rush version selection, keep agent detection out of pre-major defaults, strip frontend-only controls before engine handoff, and preserve legacy verbosity compatibility.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
@TheLarkInn

Sean Larkin (TheLarkInn) commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

Independent /pr-agentmerge review completed against #5979 and RFC sections 4.3, 5.5, and 8.

Fixed in 2b8d8e5ede:

  • unsupported required bootstrap records now fail explicit reporter requests and trigger ordered legacy fallback for repository opt-in;
  • authenticated handoff files are deleted and private environment variables are cleared when frontend selection or reporter initialization fails before replay;
  • both older and newer structured engine protocol-major mismatches now fail explicit requests or receive a LegacyFallbackSink for implicit fallback, rather than an incompatible live manager sink.

Verified the minimal zero-dependency prelude, 1 MiB bounded buffering, 64 KiB UTF-8-safe external-output chunks, required-overflow failure, truncation marker, exclusive nonce/path handoff with owner-only permissions, ordered npm capture, replay/delete/retention cleanup, direct invocation, no-opt-in legacy behavior, and no R5 operation-rendering, Heft, or Rush 6 default-flip scope. The old-engine stderr bridge remains intentional to preserve machine-reporter stdout purity; default/no-opt-in output bypasses it and remains unchanged.

Validation completed: focused @rushstack/rush-reporter, @microsoft/rush, and @microsoft/rush-lib tests/builds; bootstrap generation check; rush check; rush change --verify --no-fetch; and git diff --check.

Stack remains intentionally linear with child auto-merge disabled. Required retarget order after each predecessor merges: #5985 -> retarget #5986 to main -> retarget #5987 to main -> retarget #5989 to main -> retarget #5993 to main. At each step, verify the slice-only diff, full CI, and reviews before advancing. Current external gate: #5985 is mergeable with green checks and auto-merge enabled, but still requires approval; the #5986 Windows Node 26 rerun is still pending. No review threads exist on #5993.

@TheLarkInn

Copy link
Copy Markdown
Member Author

Combined deep review of current head 2b8d8e5ede.

  1. HIGH bootstrap events classify full argv and cwd as public. Omit them or use non-public classified values.
  2. HIGH the old-engine adapter writes captured stdout back to stderr. Restore each stream to itself.
  3. MEDIUM npm install output is captured but not shown live, so long installs appear frozen. Tee while capturing.
  4. MEDIUM bootstrap reporter parsing repeats the pass-through -- bug. Stop scanning at the separator.
  5. MEDIUM rush.json discovery and version resolution occur outside the friendly error handler, producing raw stack traces. Move them inside the guarded path.

Stop reporter control scans at the pass-through separator and add an exactly-once frontend close contract across success, failure, and termination paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Keep reporter controls out of ts-command-line globals, gate incompatible engines before initialization, and enforce bounded signal and close-error behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Preserve unsupported custom reporter values until frontend ownership is unambiguous, and narrow emergency legacy stripping to the reporter selection flag.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Probe reporter ownership without requiring a value, then enforce strict reporter parsing only after frontend ownership is established.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r6a-bootstrap-handoff branch from 2b8d8e5 to c1e13cd Compare August 28, 2026 16:40
@TheLarkInn

Copy link
Copy Markdown
Member Author

Fixed all five bootstrap review findings in c1e13cd.

  • Removed argv and cwd from public bootstrap events and sanitized reporter-mode invocation output.
  • Preserved stdout and stderr separation for old engines, including async output, cleanup, machine-readable stdout, and hard-exit delivery.
  • Teed npm output live to the correct streams while retaining ordered handoff records without duplicate visible replay.
  • Stopped reporter control parsing at standalone -- and preserved pass-through arguments.
  • Moved rush.json discovery and Rush version resolution into the friendly guarded error path.

Validation: deterministic bootstrap generation; reporter build and 299 tests; rush-lib build and 774 tests; Rush frontend build and 62 tests; rush check; stacked rush change --verify; slice-only diff. Rebased the three R6 commits directly onto 62d9e7a. Auto-merge remains disabled. Ready for review.

Preserve the complete R6 side history and acceptance corrections on the qualified main67ca R3A parent. Reconcile startup-envelope version metadata with incoming native-private fields and retain the original side tests plus a public-path regression.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3a-session-sink branch from fe52c2d to 9c40269 Compare September 10, 2026 01:30
Document both the typed event sink and the frontend-assigned sessionId in the cross-version handoff without changing its shape.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Share separated-value recognition with stripping so valueless controls cannot consume legacy flags, and use debug only as the unrequested primary file log-level default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Consume --verbose only for known actions that do not define it and parse repository opt-in value controls only when they are not command-owned. Preserve native aliases, declared custom values, unresolved plugin namespaces, and pass-through arguments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Keep the original R3A producer channel and documentation fix while carrying both frontend-owned value and flag stripping lists from the final foundation parent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Preserve the exact R6 lifecycle, handoff and legacy compatibility contracts while propagating the final command-aware foundation controls and handoff documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Preserve the standalone flag strip list alongside consumed value controls in both real bootstrap compatibility fallback paths. Keep this combined-boundary fix on the corrected review baseline, outside the scoped 6019 follow-up delta.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Preserve the exact published R2B slice and review corrections while reconciling native private members and replacing unbranded parser test objects with real execution paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Share separated-value recognition with stripping so valueless controls cannot consume legacy flags, and use debug only as the unrequested primary file log-level default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Consume --verbose only for known actions that do not define it and parse repository opt-in value controls only when they are not command-owned. Preserve native aliases, declared custom values, unresolved plugin namespaces, and pass-through arguments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Retain the exact scoped producer API and WeakMap-backed plugin facades while preserving native-private parser/plugin members and real launch-boundary coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
Document both the typed event sink and the frontend-assigned sessionId in the cross-version handoff without changing its shape.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3a-session-sink branch from 7abfad2 to 47d4f36 Compare September 10, 2026 20:23
Reconcile the six frontend conflicts with the published R6 content while
inheriting the pinned parent's private build-tooling and publishing changes.
Preserve the original R6 scope and API, serialized lifecycle and cleanup,
and both real bootstrap fallback control-ownership regressions.

The merge retains fa7553d as first parent
and 47d4f36 as second parent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
An error occurred while trying to automatically change base from copilot/reporter-r3a-session-sink to copilot/reporter-r2b-frontend-host-controls September 11, 2026 00:29
Compose R6 initialization cleanup and bootstrap compatibility with the landed core's canonical full-detail log and frontend ownership. Preserve both histories and keep the main-relative change within the published R6 scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Machine-readable stdout can be corrupted or suppressed, and a filesystem path is misclassified as public.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Balanced
Findings: 2 High severity · 1 Medium severity

New issues introduced by this change (3)
Severity Finding
High severity apps/​rush/​src/​RushCommandSelector.ts — When stdout is machine-owned, renderLive is false. adapter.capture() synchronously invokes the… View comment
High severity libraries/​rush-lib/​src/​scripts/​InstallRunRushBootstrap.ts — This stdout decision ignores --output=...://stdout. For example, the supported `--reporter=file… View comment
Medium severity apps/​rush/​src/​RushVersionSelector.ts — This message embeds expectedRushPath, but #reportStartupMessage classifies every emitted event… View comment
What changed in this PR

Adds reporter-aware bootstrap handoff, bounded npm-output capture, cross-version compatibility adapters, and lifecycle cleanup.

Changes:

  • Introduces nonce-protected bootstrap replay and retention cleanup.
  • Bridges legacy engine output into reporter events.
  • Strengthens reporter shutdown and initialization cleanup.
File Description
libraries/​rush-lib/​webpack.config.js Injects the bootstrap Rush version.
libraries/​rush-lib/​src/​utilities/​test/​npmrcUtilities.test.ts Tests privacy metadata handling.
libraries/​rush-lib/​src/​utilities/​npmrcUtilities.ts Adds log privacy classifications.
libraries/​rush-lib/​src/​scripts/​test/​InstallRunScripts.test.ts Tests npm output capture.
libraries/​rush-lib/​src/​scripts/​test/​InstallRunRushBootstrap.test.ts Tests bootstrap handoff behavior.
libraries/​rush-lib/​src/​scripts/​InstallRunRushBootstrap.ts Implements bootstrap buffering and handoff.
libraries/​rush-lib/​src/​scripts/​install-run.ts Captures ordered npm output.
libraries/​rush-lib/​src/​scripts/​install-run-rush.ts Integrates bootstrap initialization.
libraries/​rush-lib/​src/​scripts/​generated/​BootstrapProtocol.ts Adds generated handoff constants.
libraries/​rush-lib/​src/​api/​Rush.ts Exposes reporter protocol compatibility metadata.
libraries/​reporter/​src/​test/​ReporterHost.test.ts Expands replay and cleanup tests.
libraries/​reporter/​src/​test/​PlaintextReporter.test.ts Tests rendered-output suppression.
libraries/​reporter/​src/​test/​Manager.test.ts Tests lifecycle concurrency and delivery.
libraries/​reporter/​src/​test/​Compatibility.test.ts Updates adapter compatibility tests.
libraries/​reporter/​src/​reporters/​PlaintextReporter.ts Avoids duplicate rendered output.
libraries/​reporter/​src/​manager/​ReporterManager.ts Serializes cleanup and protected delivery.
libraries/​reporter/​src/​index.ts Exports legacy fallback output types.
libraries/​reporter/​src/​frontend/​ReporterHost.ts Adds replay fallback and retention cleanup.
libraries/​reporter/​src/​compat/​OldEngineOutputAdapter.ts Records whether output was rendered.
libraries/​reporter/​src/​bootstrap/​BootstrapProtocol.ts Extends generated protocol content.
libraries/​reporter/​README.md Documents cleanup and logging behavior.
common/​reviews/​api/​rush-reporter.api.md Updates the public API report.
common/​changes/​@rushstack/​rush-reporter/​review-r6-shared-close_2026-09-09-14-10.json Records shared-close changes.
common/​changes/​@rushstack/​rush-reporter/​review-r6-cleanup_2026-09-09-13-00.json Records cleanup changes.
common/​changes/​@rushstack/​rush-reporter/​copilot-reporter-r6a-bootstrap-handoff_2026-08-28-04-40.json Records fallback-output changes.
common/​changes/​@microsoft/​rush/​review-r6-cleanup_2026-09-09-13-00.json Records frontend cleanup changes.
common/​changes/​@microsoft/​rush/​review-base-control-composition_2026-09-10.json Records control-stripping compatibility.
common/​changes/​@microsoft/​rush/​copilot-reporter-r6a-bootstrap-handoff_2026-08-28-04-40.json Records bootstrap handoff support.
apps/​rush/​src/​test/​RushReporterHost.test.ts Tests frontend replay and cleanup.
apps/​rush/​src/​test/​RushFrontend.test.ts Tests frontend compatibility metadata.
apps/​rush/​src/​test/​RushCommandSelector.test.ts Tests old-engine output bridging.
apps/​rush/​src/​RushVersionSelector.ts Reports version-selection activity.
apps/​rush/​src/​RushReporterHost.ts Replays handoffs and handles fallback.
apps/​rush/​src/​RushFrontend.ts Passes reporter compatibility state.
apps/​rush/​src/​RushCommandSelector.ts Adapts old and incompatible engines.
apps/​rush/​src/​IRushFrontendLaunchOptions.ts Adds reporter launch metadata.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/rush/src/RushCommandSelector.ts
Comment thread libraries/rush-lib/src/scripts/InstallRunRushBootstrap.ts Outdated
Comment thread apps/rush/src/RushVersionSelector.ts
Preserve machine reporter writes during legacy capture, recognize owned additional stdout outputs during bootstrap without claiming custom parameters, and classify version installation paths as local-sensitive. Keep legacy defaults and canonical full-detail logging unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4747f826-8c83-495d-80df-3d1168662e10
@TheLarkInn
Sean Larkin (TheLarkInn) merged commit b4b4ba7 into main Sep 11, 2026
15 of 16 checks passed
@TheLarkInn
Sean Larkin (TheLarkInn) deleted the copilot/reporter-r6a-bootstrap-handoff branch September 11, 2026 23:26
@github-project-automation github-project-automation Bot moved this from Needs triage to Closed in Bug Triage Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Closed

Development

Successfully merging this pull request may close these issues.

3 participants