Skip to content

Emit shadow Rush lifecycle events - #5991

Open
Sean Larkin (TheLarkInn) wants to merge 5 commits into
copilot/reporter-r3a-session-sinkfrom
copilot/reporter-r3b-shadow-events
Open

Emit shadow Rush lifecycle events#5991
Sean Larkin (TheLarkInn) wants to merge 5 commits into
copilot/reporter-r3a-session-sinkfrom
copilot/reporter-r3b-shadow-events

Conversation

@TheLarkInn

Copy link
Copy Markdown
Member

Part of #5976

Stack parent: #5988

Summary

  • emit root session and command start/completion/result events through the scoped R3A sink boundary
  • adapt phased operation registration/status into stable project x phase identities and emit registered RUSH_OPERATION_FAILED diagnostics without routing raw chunks
  • correlate legacy AlreadyReportedError failures so catch boundaries do not emit duplicate structured diagnostics
  • feed a privacy-gated TelemetrySubscriber projection into existing Rush telemetry while leaving process exit behavior authoritative
  • add the registered RUSH_COMMAND_FAILED diagnostic for representative uncorrelated command failures

Validation

  • rush install
  • rush build --to @microsoft/rush
  • rush test --only @rushstack/rush-reporter --only @microsoft/rush-lib --only @microsoft/rush
  • rush check
  • rush change --verify

No-output guarantee

Legacy terminal rendering and StreamCollator remain the only visible stdout/stderr owners. The shadow sink emits no terminal text, operation chunks are not routed to reporters, and focused tests compare legacy graph output with and without the reporter adapter.

Non-goals

  • reporter selection, defaults, CLI controls, or automatic activation
  • replacing StreamCollator or emitting the R5 raw operation/output stream
  • removing legacy terminal/logger APIs
  • exhaustive parity, watch/retry, and integration matrices reserved for R3C
  • retargeting or merging this child stack before parent branches advance

@TheLarkInn

Copy link
Copy Markdown
Member Author

Independent R3 review against #5976/RFC phase 3: lifecycle/result ordering, phase-aware operation scope, legacy error correlation, telemetry projection, and no-raw-output behavior are correctly isolated while StreamCollator and process exit remain authoritative. The missing exhaustive parity matrix and logical-cancellation derivation are addressed in child #5992 rather than expanding this slice. Stack-only diff is one commit over #5988; no unresolved review threads are present.

@TheLarkInn

Copy link
Copy Markdown
Member Author

Combined deep review of current head e81d5a2508.

  1. HIGH ReporterOperationEventSink.ts:31-59 drops sharded operations that share project and phase identity. Shard failures can disappear from shadow diagnostics and exit derivation. Map every legacy operation name and aggregate shard status.
  2. LOW RushSession.ts:193-198 adds an envelope privacy gate that bypasses the allowlisted non-public diagnostic projection in Harden reporter telemetry privacy projection #5990. After Harden reporter telemetry privacy projection #5990 is hardened, forward all envelopes to the subscriber and keep one authoritative privacy projection.

@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3b-shadow-events branch from e81d5a2 to 8255a72 Compare August 28, 2026 16:32
@TheLarkInn

Copy link
Copy Markdown
Member Author

Rebased the single R3B commit onto #5988 head 07f17e4c7f and force-pushed 8255a72716.

Fixed sharded-operation-collapse: pre-shard, every shard, and collator now map to one project x phase identity. Status is aggregated per iteration, a shard failure emits one correlated diagnostic, telemetry retains the aggregate failure, and retry/watch registrations keep the same identity. R3B still exposes no raw chunk callback and legacy output remains authoritative. Also memoized reporter close after resolving the parent rebase.

Validation: build through @microsoft/rush; reporter, rush-lib, and apps/rush tests; API Extractor; rush check; rush change --verify --no-fetch; slice is one commit over 07f17e4c7f.

Low follow-on: keep the outer telemetry privacy gate until #5990 reaches shared main. Then remove it and forward all envelopes to the hardened subscriber.

@TheLarkInn

Copy link
Copy Markdown
Member Author

Four-review rerun on 8255a72716 confirms the sharded-operation fix. One MEDIUM issue remains: a failed watch iteration can permanently latch derived exit failure even after the final iteration and command lifecycle succeed. Derived status can disagree with the authoritative final exit.

Required fix: make final command or session completion, or current-iteration outcomes, establish the recovered success result. Add a fail-then-success watch test.

Dismissible low follow-ons: reset group silent state between watch iterations, and remove the outer telemetry privacy gate after #5990 reaches shared ancestry.

@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3b-shadow-events branch from 8255a72 to 2f9ac7d Compare August 28, 2026 17:02
@TheLarkInn

Copy link
Copy Markdown
Member Author

Round two fixed at 2f9ac7d90e.

Derived exit now follows current operation outcomes and authoritative root commandResult, commandCompleted, and sessionCompleted events. A fail-then-success watch sequence now resolves to exit 0, while an active failed iteration still resolves to exit 1. Grouped silence is recomputed after all registrations each iteration, so a group disabled after being active emits no new shadow registration or status.

Validation passed: build through @microsoft/rush; reporter, rush-lib, and apps/rush tests; API Extractor; rush check; rush change --verify --no-fetch; one-commit slice over 07f17e4c7f. The outer telemetry privacy gate remains deferred until #5990 is available in shared ancestry.

@TheLarkInn

Copy link
Copy Markdown
Member Author

Final combined review of 2f9ac7d90e found no critical, high, or medium actionable issue. Sharded aggregation, watch recovery, grouped silence, diagnostics, telemetry status, and derived exit parity are fixed.

One intentional low follow-on remains: remove the outer telemetry privacy gate after #5990 reaches shared ancestry. This head is low-only.

@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3b-shadow-events branch from 52f751f to 58cd2a3 Compare September 3, 2026 18:43
@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3b-shadow-events branch from 58cd2a3 to 14ab214 Compare September 3, 2026 20:01
@TheLarkInn
Sean Larkin (TheLarkInn) force-pushed the copilot/reporter-r3b-shadow-events branch 2 times, most recently from 2a6a582 to 6b2b758 Compare September 3, 2026 20:15
@TheLarkInn

Copy link
Copy Markdown
Member Author

Deep review of current head 3541683 found no critical, high, or medium actionable issues. Failure lifecycle output now matches the normalized process exit, and overlapping pre-iteration cycles remain isolated. Merge remains gated by #5988 and maintainer approval.

@TheLarkInn Sean Larkin (TheLarkInn) left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R3 lifecycle acceptance review against #5976: early failure and finalization outcomes must agree with authoritative native exit behavior.

this._sessionStartTimeMs = performance.now();
this._sessionLifecycleEmitter.emitSessionStarted({
rushVersion: _getRushSessionReporterSourceVersion(this.rushSession)!
});

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Establish the root lifecycle before constructor failures can finalize the reporter. A rush.json/configuration failure is handled in the constructor, where _emitReporterCompletion(1) latches completion and closes the sink before this root emitter exists. executeAsync then returns through _initializationFailed without reaching this block. An exact-head parser reproduction returns false/exits 1 but captures zero events and leaves _getRushSessionDerivedExitStatus at succeeded/0. Errors during unassociated-plugin initialization similarly have no command emitter, so the optional diagnostic call emits nothing. Initialize or buffer the root failure lifecycle before close, use a session-scoped diagnostic when no command exists, and correlate only a diagnostic that was emitted.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed on this owning PR in f439cc6. Root session reporting is available before fallible repository initialization; failures before command selection emit a session-scoped diagnostic and consistent failure completion without changing native fatal behavior. Real malformed-config and early-hook cases failed before the fix and now pass. The owning R3B parser/session/telemetry selection passed 59 cases; downstream reporter-terminal initialization was adapted separately during the stack update. Fresh current-head CI is pending.


// If we make it here, everything went fine, so reset the exit code back to 0
process.exitCode = 0;
this._emitReporterCompletion(0);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Await command-finalization hooks before publishing successful completion. _emitReporterCompletion(0) runs before telemetry.ensureFlushedAsync below. If a public flushTelemetry hook rejects, the base parser returns false and changes process.exitCode to 1, but _reporterCompletionEmitted prevents the outer path from correcting the already-published commandResult/commandCompleted/sessionCompleted. A real delayed rejecting flushTelemetry hook reproduces succeeded:true/exitCode:0 in every final event and derived status, while the actual command exits 1. Defer final success emission until the hook completes and cover the rejection through the failure lifecycle.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed on this owning PR in f439cc6. Successful completion is no longer emitted from the inner execution callback before public telemetry finalization settles. A rejecting real flushTelemetry hook now produces a failure diagnostic and matching final status while preserving the base parser's native false return and nonzero exit behavior. Tests hold the public hook across an event-loop turn and cover both fulfillment and rejection. Fresh current-head CI is pending.

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
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d6318e80-5da9-4858-a147-817e8692f10e
…ilures

Create the root reporting context before repository setup, share correlated failure emission, and publish final completion only after telemetry hooks settle without changing native error handling.

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-r3b-shadow-events branch from f7909be to f439cc6 Compare September 9, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs triage

Development

Successfully merging this pull request may close these issues.

1 participant