Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
224 commits
Select commit Hold shift + click to select a range
8c6b049
Add Rush reporter repository configuration
TheLarkInn Aug 28, 2026
b4f0fc1
Add Rush reporter frontend controls
TheLarkInn Aug 28, 2026
2450d5f
Fix reporter frontend integration
TheLarkInn Aug 28, 2026
c6b0349
Emit shadow Rush lifecycle events
TheLarkInn Aug 28, 2026
b80a277
Add feature-flagged operation event adapter
TheLarkInn Aug 28, 2026
481b4f5
Fix operation reporter stream edge cases
TheLarkInn Aug 28, 2026
cbff953
Harden reporter demo integration
TheLarkInn Aug 28, 2026
8a64282
Harden AI reporter qualification gates
TheLarkInn Aug 28, 2026
0ad2e30
Fix reporter frontend argument and close lifecycle
TheLarkInn Aug 28, 2026
4cb2448
Preserve Rush CLI reporter compatibility
TheLarkInn Aug 28, 2026
00f16e1
Refine reporter flag ownership
TheLarkInn Aug 28, 2026
a5f1f7c
Tolerate value-less custom reporter flags
TheLarkInn Aug 28, 2026
e83fa59
Fix operation stream review findings
TheLarkInn Aug 28, 2026
5aa1d2c
Fix reporter demo review findings
TheLarkInn Aug 28, 2026
965e0db
Fix reporter watch and lock handling
TheLarkInn Aug 28, 2026
ae5c475
Fix overlapping reporter watch cycles
TheLarkInn Aug 28, 2026
5fd4d10
Fix AI fallback privacy gates
TheLarkInn Aug 28, 2026
3250879
Redact secret reporter envelope context
TheLarkInn Aug 28, 2026
f093fbf
Stop execution after parser initialization failure
TheLarkInn Sep 3, 2026
7f47181
Isolate overlapping reporter watch cycles
TheLarkInn Sep 3, 2026
a87994b
Preserve reporter cycles across stream callbacks
TheLarkInn Sep 3, 2026
8431367
Redact secret human reporter messages
TheLarkInn Sep 3, 2026
61a3e54
Force nonzero parser failure exits
TheLarkInn Sep 3, 2026
23de51a
Expose scoped RushSession reporter producers
TheLarkInn Aug 28, 2026
023cf7e
Emit registrations for collapsed iterations
TheLarkInn Sep 3, 2026
04d04cc
Keep operation sink callbacks compatible
TheLarkInn Sep 3, 2026
2139b32
Keep operation stream callbacks compatible
TheLarkInn Sep 3, 2026
745843b
Align reporter completion with failure exit
TheLarkInn Sep 3, 2026
853470e
Complete shadow reporter parity coverage
TheLarkInn Aug 28, 2026
ccd34f3
Forward daemon operation completion events
TheLarkInn Sep 3, 2026
0ef86fa
Finalize machine privacy and zero-work cycles
TheLarkInn Sep 3, 2026
0debf23
Complete collapsed daemon operation cycles
TheLarkInn Sep 3, 2026
6af34ca
Add direct Rush reporter demo path
TheLarkInn Aug 28, 2026
384eab3
Preserve iteration callback compatibility
TheLarkInn Sep 3, 2026
9e90abf
Protect secret logs and callback compatibility
TheLarkInn Sep 3, 2026
6223f0d
Add deterministic AI reporter qualification gates
TheLarkInn Aug 28, 2026
90977fb
Preserve local-sensitive producer identity
TheLarkInn Sep 3, 2026
3b005ee
Isolate reporter configuration test fixtures from shared cleanup
TheLarkInn Sep 7, 2026
7e9a1cd
Add Rush reporter frontend controls
TheLarkInn Aug 28, 2026
43908fe
Fix reporter frontend integration
TheLarkInn Aug 28, 2026
b0056ee
Fix reporter frontend argument and close lifecycle
TheLarkInn Aug 28, 2026
c3dc2c1
Preserve Rush CLI reporter compatibility
TheLarkInn Aug 28, 2026
352aa37
Refine reporter flag ownership
TheLarkInn Aug 28, 2026
034f22d
Tolerate value-less custom reporter flags
TheLarkInn Aug 28, 2026
2c1d786
Stop execution after parser initialization failure
TheLarkInn Sep 3, 2026
c8637e5
Expose scoped RushSession reporter producers
TheLarkInn Aug 28, 2026
32562c8
Emit shadow Rush lifecycle events
TheLarkInn Aug 28, 2026
fde0436
Isolate overlapping reporter watch cycles
TheLarkInn Sep 3, 2026
1bc68af
Keep operation sink callbacks compatible
TheLarkInn Sep 3, 2026
3776ee9
Align reporter completion with failure exit
TheLarkInn Sep 3, 2026
707a019
Complete shadow reporter parity coverage
TheLarkInn Aug 28, 2026
8d665d9
Add feature-flagged operation event adapter
TheLarkInn Aug 28, 2026
3055cfb
Fix operation reporter stream edge cases
TheLarkInn Aug 28, 2026
daec75c
Fix operation stream review findings
TheLarkInn Aug 28, 2026
bf2379e
Preserve reporter cycles across stream callbacks
TheLarkInn Sep 3, 2026
e94c944
Emit registrations for collapsed iterations
TheLarkInn Sep 3, 2026
66110fa
Keep operation stream callbacks compatible
TheLarkInn Sep 3, 2026
4375f9f
Forward daemon operation completion events
TheLarkInn Sep 3, 2026
e38163f
Complete collapsed daemon operation cycles
TheLarkInn Sep 3, 2026
1c2a87f
Add direct Rush reporter demo path
TheLarkInn Aug 28, 2026
7c0fffd
Harden reporter demo integration
TheLarkInn Aug 28, 2026
52c50f8
Force nonzero parser failure exits
TheLarkInn Sep 3, 2026
7fb53ea
Fix reporter demo review findings
TheLarkInn Aug 28, 2026
fbbaae7
Fix reporter watch and lock handling
TheLarkInn Aug 28, 2026
b1eaa85
Fix overlapping reporter watch cycles
TheLarkInn Aug 28, 2026
cce4eb1
Redact secret human reporter messages
TheLarkInn Sep 3, 2026
4293aa3
Finalize machine privacy and zero-work cycles
TheLarkInn Sep 3, 2026
898b55f
Preserve iteration callback compatibility
TheLarkInn Sep 3, 2026
4d141b8
Protect secret logs and callback compatibility
TheLarkInn Sep 3, 2026
30a7814
Sync reporter PR #5999 with its restacked parent
TheLarkInn Sep 7, 2026
5bba19c
Add the missing reporter change note for R2B JSON controls
TheLarkInn Sep 7, 2026
e3bf1e7
Expose scoped RushSession reporter producers
TheLarkInn Aug 28, 2026
ce66517
Emit shadow Rush lifecycle events
TheLarkInn Aug 28, 2026
cd2e907
Isolate overlapping reporter watch cycles
TheLarkInn Sep 3, 2026
a5fd68e
Keep operation sink callbacks compatible
TheLarkInn Sep 3, 2026
b556aec
Align reporter completion with failure exit
TheLarkInn Sep 3, 2026
cc02a14
Complete shadow reporter parity coverage
TheLarkInn Aug 28, 2026
32bf313
Add feature-flagged operation event adapter
TheLarkInn Aug 28, 2026
6ee64ef
Fix operation reporter stream edge cases
TheLarkInn Aug 28, 2026
0ee3e23
Fix operation stream review findings
TheLarkInn Aug 28, 2026
17d5263
Preserve reporter cycles across stream callbacks
TheLarkInn Sep 3, 2026
ccad744
Emit registrations for collapsed iterations
TheLarkInn Sep 3, 2026
5ce23dd
Keep operation stream callbacks compatible
TheLarkInn Sep 3, 2026
f26743e
Forward daemon operation completion events
TheLarkInn Sep 3, 2026
f741114
Complete collapsed daemon operation cycles
TheLarkInn Sep 3, 2026
8e50a42
Add direct Rush reporter demo path
TheLarkInn Aug 28, 2026
8981d22
Harden reporter demo integration
TheLarkInn Aug 28, 2026
09a9fa1
Fix reporter demo review findings
TheLarkInn Aug 28, 2026
306fa70
Fix reporter watch and lock handling
TheLarkInn Aug 28, 2026
fb15ddc
Fix overlapping reporter watch cycles
TheLarkInn Aug 28, 2026
2d80a11
Redact secret human reporter messages
TheLarkInn Sep 3, 2026
41816e7
Finalize machine privacy and zero-work cycles
TheLarkInn Sep 3, 2026
2bc9601
Preserve iteration callback compatibility
TheLarkInn Sep 3, 2026
1c84401
Protect secret logs and callback compatibility
TheLarkInn Sep 3, 2026
2e4a8ca
Sync reporter PR #5999 with parent release metadata
TheLarkInn Sep 7, 2026
07312d4
Add Rush reporter repository configuration
TheLarkInn Aug 28, 2026
a60f284
Isolate reporter configuration test fixtures from shared cleanup
TheLarkInn Sep 7, 2026
1b3fed9
Add Rush reporter frontend controls
TheLarkInn Aug 28, 2026
46d9d40
Fix reporter frontend integration
TheLarkInn Aug 28, 2026
a01d682
Fix reporter frontend argument and close lifecycle
TheLarkInn Aug 28, 2026
29d1087
Preserve Rush CLI reporter compatibility
TheLarkInn Aug 28, 2026
d2508b1
Refine reporter flag ownership
TheLarkInn Aug 28, 2026
0342dee
Tolerate value-less custom reporter flags
TheLarkInn Aug 28, 2026
1aec74f
Stop execution after parser initialization failure
TheLarkInn Sep 3, 2026
583f514
Force nonzero parser failure exits
TheLarkInn Sep 3, 2026
95379c1
Add the missing reporter change note for R2B JSON controls
TheLarkInn Sep 7, 2026
d57e66b
Expose scoped RushSession reporter producers
TheLarkInn Aug 28, 2026
e64ea11
Emit shadow Rush lifecycle events
TheLarkInn Aug 28, 2026
6dcfc56
Isolate overlapping reporter watch cycles
TheLarkInn Sep 3, 2026
21f0f0b
Keep operation sink callbacks compatible
TheLarkInn Sep 3, 2026
f7909be
Align reporter completion with failure exit
TheLarkInn Sep 3, 2026
a575d19
Complete shadow reporter parity coverage
TheLarkInn Aug 28, 2026
220da37
Add feature-flagged operation event adapter
TheLarkInn Aug 28, 2026
a1fa10d
Fix operation reporter stream edge cases
TheLarkInn Aug 28, 2026
87b8f81
Fix operation stream review findings
TheLarkInn Aug 28, 2026
e18f03f
Preserve reporter cycles across stream callbacks
TheLarkInn Sep 3, 2026
8e1e7fd
Emit registrations for collapsed iterations
TheLarkInn Sep 3, 2026
4efd6f5
Keep operation stream callbacks compatible
TheLarkInn Sep 3, 2026
646cb72
Forward daemon operation completion events
TheLarkInn Sep 3, 2026
7aa321f
Complete collapsed daemon operation cycles
TheLarkInn Sep 3, 2026
3cbffdf
Record Reporter operation forwarding release note
TheLarkInn Sep 7, 2026
ec08144
Add direct Rush reporter demo path
TheLarkInn Aug 28, 2026
562fbb0
Harden reporter demo integration
TheLarkInn Aug 28, 2026
1fe6931
Fix reporter demo review findings
TheLarkInn Aug 28, 2026
daa5ddd
Fix reporter watch and lock handling
TheLarkInn Aug 28, 2026
d6ff4f1
Fix overlapping reporter watch cycles
TheLarkInn Aug 28, 2026
aa6d91f
Redact secret human reporter messages
TheLarkInn Sep 3, 2026
7b96732
Finalize machine privacy and zero-work cycles
TheLarkInn Sep 3, 2026
9dab133
Preserve iteration callback compatibility
TheLarkInn Sep 3, 2026
26c2ac0
Protect secret logs and callback compatibility
TheLarkInn Sep 3, 2026
0e2c1f6
Merge aligned Reporter parent into R8A
TheLarkInn Sep 7, 2026
28e30b0
Fix reporter rollback and reserved stream destinations
TheLarkInn Sep 9, 2026
fe52c2d
Expose scoped RushSession reporter producers
TheLarkInn Aug 28, 2026
b930b7b
Emit shadow Rush lifecycle events
TheLarkInn Aug 28, 2026
44bf286
Isolate overlapping reporter watch cycles
TheLarkInn Sep 3, 2026
e588b24
Keep operation sink callbacks compatible
TheLarkInn Sep 3, 2026
603362c
Align reporter completion with failure exit
TheLarkInn Sep 3, 2026
f439cc6
Preserve reporter lifecycle across initialization and finalization fa…
TheLarkInn Sep 9, 2026
2fe0ed0
Complete shadow reporter parity coverage
TheLarkInn Aug 28, 2026
fb5f7c7
Add feature-flagged operation event adapter
TheLarkInn Aug 28, 2026
fba44ed
Fix operation reporter stream edge cases
TheLarkInn Aug 28, 2026
05b3d8f
Fix operation stream review findings
TheLarkInn Aug 28, 2026
5f3a796
Preserve reporter cycles across stream callbacks
TheLarkInn Sep 3, 2026
425945c
Emit registrations for collapsed iterations
TheLarkInn Sep 3, 2026
0563d58
Keep operation stream callbacks compatible
TheLarkInn Sep 3, 2026
c33c2cb
Forward daemon operation completion events
TheLarkInn Sep 3, 2026
a3f0906
Complete collapsed daemon operation cycles
TheLarkInn Sep 3, 2026
3af8aab
Record Reporter operation forwarding release note
TheLarkInn Sep 7, 2026
98f5e24
Add direct Rush reporter demo path
TheLarkInn Aug 28, 2026
f3d4166
Harden reporter demo integration
TheLarkInn Aug 28, 2026
2183cd6
Fix reporter demo review findings
TheLarkInn Aug 28, 2026
050a4d7
Fix reporter watch and lock handling
TheLarkInn Aug 28, 2026
c455b12
Fix overlapping reporter watch cycles
TheLarkInn Aug 28, 2026
14d1927
Redact secret human reporter messages
TheLarkInn Sep 3, 2026
15df6a8
Finalize machine privacy and zero-work cycles
TheLarkInn Sep 3, 2026
f48b6c6
Preserve iteration callback compatibility
TheLarkInn Sep 3, 2026
44b0e57
Protect secret logs and callback compatibility
TheLarkInn Sep 3, 2026
06bc7c5
Adapt foundation regression coverage to restacked R5B
TheLarkInn Sep 9, 2026
4469258
Lift shared human diagnostic formatting onto the R5B slice
TheLarkInn Sep 9, 2026
671f827
Adapt bounded diagnostics and reliable writes to the owning R5B slice
TheLarkInn Sep 9, 2026
68622dd
Merge corrected R5B parent into R8
TheLarkInn Sep 9, 2026
f6e4546
Merge corrected Reporter presentation into R8
TheLarkInn Sep 9, 2026
8bc6c3e
Enforce truthful AI qualification and invocation output budgets
TheLarkInn Sep 9, 2026
26a469f
Redact secret aliases from human diagnostic context
TheLarkInn Sep 9, 2026
feaa0bf
Retain secret-alias privacy in the corrected AI qualification branch
TheLarkInn Sep 9, 2026
f637c70
Coalesce superseded AI start status for native Windows qualification
TheLarkInn Sep 9, 2026
4684f6e
Add Rush reporter repository configuration
TheLarkInn Aug 28, 2026
991a481
Isolate reporter configuration test fixtures from shared cleanup
TheLarkInn Sep 7, 2026
ebbb477
Refresh R2B reporter controls onto native-private trunk
TheLarkInn Sep 9, 2026
9c40269
Refresh R3A scoped producers onto native-private trunk
TheLarkInn Sep 9, 2026
a4c8126
Refresh R3B shadow lifecycle onto native-private trunk
TheLarkInn Sep 10, 2026
9834e30
Refresh R3C parity coverage onto native-private trunk
TheLarkInn Sep 10, 2026
da51dfb
Refresh R5A operation reporting onto native-private trunk
TheLarkInn Sep 10, 2026
8ae2115
Refresh corrected R5B reporters onto native-private trunk
TheLarkInn Sep 10, 2026
5c6151f
Merge pinned R5B native-private refresh into R8 qualification side
TheLarkInn Sep 10, 2026
88dcf1a
Fix AI qualification mutation test isolation
TheLarkInn Sep 10, 2026
0749f38
Clarify the frontend reporter channel identity contract
TheLarkInn Sep 10, 2026
65ba96b
Preserve rollback flags and primary file detail defaults
TheLarkInn Sep 10, 2026
ba8c9f1
fix(rush): preserve discovery after malformed configuration
TheLarkInn Sep 10, 2026
4b8db13
fix(rush): strip owned reporter controls from help
TheLarkInn Sep 10, 2026
330fa91
test(reporter): preserve post-close artifact truthfulness
TheLarkInn Sep 10, 2026
27e711a
fix(rush): retain unscoped output during operation deferral
TheLarkInn Sep 10, 2026
3fbddc0
Connect watch cancellation to shadow parity observation
TheLarkInn Sep 10, 2026
6d645ad
Fix shadow lifecycle error correlation and final registration
TheLarkInn Sep 10, 2026
68cab2b
Respect command ownership when consuming reporter controls
TheLarkInn Sep 10, 2026
a93c236
Merge reviewed R3B lifecycle fixes into R3C parity
TheLarkInn Sep 10, 2026
3726472
Merge reviewed lifecycle and parity fixes into R5A
TheLarkInn Sep 10, 2026
282b3f6
Merge reviewed R5A and lifecycle fixes into R5B presentation
TheLarkInn Sep 10, 2026
eab0577
fix(rush): preserve declared custom controls on help
TheLarkInn Sep 10, 2026
7abfad2
Merge final R2B controls into fixed R3A session handoff
TheLarkInn Sep 10, 2026
5c2a107
Merge final R3A parent into reviewed R3B lifecycle
TheLarkInn Sep 10, 2026
44c0e99
Merge final R3B parent into reviewed R3C parity
TheLarkInn Sep 10, 2026
a56fd94
Merge final R3C parent into reviewed R5A operation adapter
TheLarkInn Sep 10, 2026
f6d0a61
Merge final command-aware foundation into R5B presentation
TheLarkInn Sep 10, 2026
e51e686
Merge declaration-aware help into final R5B core staging
TheLarkInn Sep 10, 2026
3ce44c6
Preserve later full-log and root-help contracts in core staging
TheLarkInn Sep 10, 2026
eb2f9df
Merge corrected review parent into R8 side
TheLarkInn Sep 10, 2026
c857a9b
Refresh R2B reporter controls onto native-private trunk
TheLarkInn Sep 9, 2026
c4c05af
Preserve rollback flags and primary file detail defaults
TheLarkInn Sep 10, 2026
55e4328
Respect command ownership when consuming reporter controls
TheLarkInn Sep 10, 2026
d71c2ff
Refresh R3A scoped producers onto native-private trunk
TheLarkInn Sep 9, 2026
47d4f36
Clarify the frontend reporter channel identity contract
TheLarkInn Sep 10, 2026
2fc47f5
Refresh R3B shadow lifecycle onto native-private trunk
TheLarkInn Sep 10, 2026
852b04d
Fix shadow lifecycle error correlation and final registration
TheLarkInn Sep 10, 2026
188e673
Merge post-R2A native R3B into reviewed R3C parity
TheLarkInn Sep 10, 2026
313e8ff
Merge reconciled R3C into published R5A operation adapter
TheLarkInn Sep 10, 2026
f47e0ce
Merge reconciled R5A into published R5B reporter demos
TheLarkInn Sep 10, 2026
1a13d64
Normalize Rush cwd before analyzing repository inputs
TheLarkInn Sep 10, 2026
1feb3ba
Use native realpath to expand Windows short directory names
TheLarkInn Sep 10, 2026
af6ef7d
Merge native physical-cwd watch fix into R5A
TheLarkInn Sep 10, 2026
0548584
Merge native physical-cwd watch fix into R5B
TheLarkInn Sep 10, 2026
485dd44
Merge post-R2A native-cwd R5B parent into published R8
TheLarkInn Sep 10, 2026
d672867
Capture successful Git setup diagnostics in watch regression tests
TheLarkInn Sep 10, 2026
db9a2fc
Merge captured watch-fixture Git setup into R5A
TheLarkInn Sep 10, 2026
6a7180d
Merge captured watch-fixture Git setup into R5B
TheLarkInn Sep 10, 2026
570625c
Merge canonical watch fixture Git stdio parent into R8
TheLarkInn Sep 10, 2026
08cd910
Compare physical dependency targets in package manager tests
TheLarkInn Sep 10, 2026
69e2d82
Merge physical package-link assertions into R5A
TheLarkInn Sep 10, 2026
74a269d
Merge physical package-link assertions into R5B
TheLarkInn Sep 10, 2026
51f6e1c
Merge canonical physical package-link test parent into R8
TheLarkInn Sep 10, 2026
0a95349
Merge pinned landed core into R8 AI qualification
TheLarkInn Sep 11, 2026
492bca5
Fix R8 machine-source alias privacy qualification
TheLarkInn Sep 11, 2026
e87b7f9
Merge main into AI reporter qualification gates
TheLarkInn Sep 22, 2026
efde5c2
Bound and isolate AI qualification setup on Windows CI
TheLarkInn Sep 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"changes": [
{
"packageName": "@rushstack/rush-reporter",
"comment": "Redact classified secret source aliases in machine JSON without losing owner-only file context, and qualify every machine output for producer privacy.",
"comment": "Redact classified secret source aliases in machine JSON without losing owner-only file context, qualify every machine output for producer privacy, and document/test late-artifact-safe AI flush reservation.",
"type": "patch"
}
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@rushstack/rush-reporter",
"comment": "Run AI qualification setup in an owned worker with bounded work and cleanup deadlines to avoid Windows CI setup timeouts leaving the corpus running.",
"type": "patch"
}
],
"packageName": "@rushstack/rush-reporter"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@rushstack/rush-reporter",
"comment": "Isolate AI qualification test mutations and join bounded worker cleanup after delayed, rejected, or timed-out corpus work.",
"type": "none"
}
],
"packageName": "@rushstack/rush-reporter"
}
1 change: 0 additions & 1 deletion common/reviews/api/rush-reporter.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export class AiReporter implements IReporter {
constructor(options: IAiReporterOptions);
// (undocumented)
closeAsync(): Promise<void>;
// (undocumented)
flushAsync(): Promise<void>;
// (undocumented)
initializeAsync(): Promise<void>;
Expand Down
17 changes: 13 additions & 4 deletions libraries/reporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,27 @@ these gates only produces a reusable qualification decision; it does not enable
reporter selection. That decision also requires the separate telemetry privacy prerequisite to be accepted.
The pre-major Rush frontend remains explicit/repository-opt-in, and `RUSH_REPORTER=legacy` remains
authoritative.
The Jest setup hook has a bounded 15-second allowance for the three file-backed corpus passes, matching
the integration test setup policy. This allowance does not change any quality gate or production deadline.
Jest setup and mutation runs use owned workers with a 30-second work budget and a separate 2-second
termination/cleanup budget. The setup hook allows 33 seconds; tests that await two corpus sessions allow
66 seconds. Timed-out work is terminated and its temporary directory removed before the session settles.
These test-only allowances do not change any quality gate or production deadline.

AI output reserves final-record space, including its supplied log reference, before emitting progress.
Progress is buffered within the invocation byte limit until the primary log reservation is known, or until
close if no log is supplied. Excess progress/details set `truncated`; the final result remains valid JSON.
An unrendered start acknowledgement is coalesced into a known final result. Ongoing commands still expose
buffered status at the next non-terminal event or explicit flush; watch history and every final field,
An unrendered start acknowledgement is coalesced into a known final result. Once the log reservation is
known, ongoing commands expose buffered status at the next non-terminal event or explicit flush; watch history and every final field,
including the supplied log reference, are retained. No path shortening or measurement normalization is used.
The final scope carries the command name, and standard `diagnostic.<code>.summary` keys are implicit rather
than repeated alongside the same code. Custom summary keys are preserved.

Before a log artifact arrives, AI flush and signal-flush retain bounded progress rather than spend bytes
that a late, individually representable log reference may require. Reserving half the invocation budget is
not sufficient for every supplied reference. Closing drains this bounded progress and emits the final
result even if no artifact arrives; it does not invent a log path or claim full-log completeness.
This is a limitation of eager no-artifact flushing, not permission to drop a required late artifact or
exceed the invocation budget.

AI fallback message text is emitted only for public envelopes. Its context retains the known command, and
the usage-review action invokes that command's help (or `rush --help` when the command is unavailable).
Qualification checks exact expected context, remediation commands/URLs, descriptions, and execution safety;
Expand Down
8 changes: 8 additions & 0 deletions libraries/reporter/src/reporters/AiReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,14 @@ export class AiReporter implements IReporter {
}
}

/**
* Flushes progress after the primary log reservation is known.
*
* @remarks
* Before an artifact arrives, even a bounded flush can consume space needed by a later
* individually representable log reference. Keep that progress bounded and deferred;
* closeAsync drains it with the final result even when no artifact ever arrives.
*/
public async flushAsync(): Promise<void> {
if (this._logPath !== undefined) {
this._flushPendingProgress();
Expand Down
81 changes: 81 additions & 0 deletions libraries/reporter/src/test/AiReporterFlush.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.

import {
AiReporter,
ReporterManager,
type IAiFinalRecord,
type IReporterEventEnvelope
} from '../index';

describe('AI flush and required final-artifact reservation', () => {
it.each([
{ maxBytes: 2048, logPath: `/protected/${'logs/'.repeat(250)}full.log` },
{ maxBytes: 65536, logPath: `\\\\?\\C:\\${(`${'a'.repeat(250)}\\`).repeat(130)}full.log` }
])('retains a representable late reference after signal flush with $maxBytes bytes', async ({ maxBytes, logPath }) => {
let output: string = '';
const manager = new ReporterManager();
manager.addReporter(new AiReporter({ maxBytes, write: (text) => { output += text; } }));
await manager.initializeAsync();
const emit = (type: IReporterEventEnvelope<unknown>['type'], payload: unknown): void => {
manager.emit({
protocolVersion: { major: 1, minor: 1 },
sessionId: 'flush-reservation',
source: { packageName: '@microsoft/rush-lib', packageVersion: '5.179.0' },
privacy: 'public',
type,
payload
});
};
emit('commandStarted', { commandName: 'build' });
for (let iterationId: number = 0; iterationId < 1000; iterationId++) {
emit('watchCycleCompleted', { iterationId, succeeded: true });
}
await manager.signalFlushAsync();
expect(output).toBe('');
emit('artifactAvailable', { role: 'log', path: logPath, complete: true });
emit('commandResult', { succeeded: false, exitCode: 1 });
await manager.closeAsync();

const final: IAiFinalRecord = JSON.parse(output.trimEnd().split('\n').at(-1)!);
expect(Buffer.byteLength(output, 'utf8')).toBeLessThanOrEqual(maxBytes);
expect(final.log).toEqual({ path: logPath, complete: true });
expect(final).toMatchObject({ kind: 'ai.final', result: 'failed', exitCode: 1, truncated: true });
expect(final.diagnostics.length).toBeLessThanOrEqual(20);
});

it.each([512, 65536])('drains on close without inventing a missing artifact at %s bytes', async (maxBytes) => {
let output: string = '';
const reporter = new AiReporter({ maxBytes, write: (text) => { output += text; } });
const event = (type: IReporterEventEnvelope<unknown>['type'], payload: unknown): IReporterEventEnvelope<unknown> => ({
protocolVersion: { major: 1, minor: 1 },
eventId: type,
sessionId: 'no-artifact',
sequence: 1,
timestamp: '2026-09-11T00:00:00.000Z',
source: { packageName: '@microsoft/rush-lib', packageVersion: '5.179.0' },
privacy: 'public',
required: true,
type,
payload
});
reporter.report(event('commandStarted', { commandName: 'build' }));
for (let iterationId: number = 0; iterationId < 1000; iterationId++) {
reporter.report(event('watchCycleCompleted', { iterationId, succeeded: true }));
}
await reporter.flushAsync();
expect(output).toBe('');
reporter.report(event('commandResult', { succeeded: false, exitCode: 1 }));
await reporter.closeAsync();

expect(Buffer.byteLength(output, 'utf8')).toBeLessThanOrEqual(maxBytes);
expect(output.endsWith('\n')).toBe(true);
const final: IAiFinalRecord = JSON.parse(output.trimEnd().split('\n').at(-1)!);
expect(final).toMatchObject({ kind: 'ai.final', result: 'failed', exitCode: 1, truncated: true });
expect(final.log).toBeUndefined();
const closedOutput: string = output;
await reporter.flushAsync();
await reporter.closeAsync();
expect(output).toBe(closedOutput);
});
});
49 changes: 29 additions & 20 deletions libraries/reporter/src/test/AiReporterQualification.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
evaluateAiReporterQualification,
formatAiReporterQualificationFailures,
getQualifiedAiReporterDecision,
runAiReporterQualificationCorpusAsync,
type IAiDiagnostic,
type IAiReporterQualificationCaseResult,
type IAiReporterQualificationGateResult,
Expand All @@ -22,6 +21,7 @@ import {
import {
AiQualificationTestSession,
QUALIFICATION_CLEANUP_TIMEOUT_MS,
QUALIFICATION_SESSION_TIMEOUT_MS,
QUALIFICATION_TEST_TIMEOUT_MS
} from './helpers/AiQualificationTestSession';
import type { AiQualificationMutation } from './helpers/AiQualificationWorker';
Expand Down Expand Up @@ -52,10 +52,10 @@ describe('AI reporter deterministic qualification corpus', () => {
}
}, QUALIFICATION_CLEANUP_TIMEOUT_MS + 1000);

// Three file-backed corpus passes can exceed Jest's default setup allowance on Windows CI.
// Own setup work as well as mutations so a timed-out hook cannot leave the corpus running.
beforeAll(async () => {
qualification = await runAiReporterQualificationCorpusAsync();
}, 15000);
qualification = (await startSession('none').resultAsync()).qualification;
}, QUALIFICATION_SESSION_TIMEOUT_MS);

it('passes every blocking gate with machine-readable safe results', () => {
if (!qualification.passed) {
Expand Down Expand Up @@ -164,18 +164,22 @@ describe('AI reporter deterministic qualification corpus', () => {
);
});

it('fails with an actionable case list when the AI reporter omits its log reference', async () => {
const { qualification: failed } = await startSession('missing-log').resultAsync();
expect(failed.passed).toBe(false);
expect(formatAiReporterQualificationFailures(failed)).toContain(
'full-log: actual=0.00, required=>= 100%; cases='
);
expect(
failed.cases.every(({ failures }) =>
failures.includes('full log path, permissions, completeness, or correlation invalid')
)
).toBe(true);
});
it(
'fails with an actionable case list when the AI reporter omits its log reference',
async () => {
const { qualification: failed } = await startSession('missing-log').resultAsync();
expect(failed.passed).toBe(false);
expect(formatAiReporterQualificationFailures(failed)).toContain(
'full-log: actual=0.00, required=>= 100%; cases='
);
expect(
failed.cases.every(({ failures }) =>
failures.includes('full log path, permissions, completeness, or correlation invalid')
)
).toBe(true);
},
QUALIFICATION_TEST_TIMEOUT_MS
);

it(
'fails qualification when a renderer substitutes unrelated remediation',
Expand Down Expand Up @@ -212,11 +216,16 @@ describe('AI reporter deterministic qualification corpus', () => {
QUALIFICATION_TEST_TIMEOUT_MS
);

it.each(['timeout', 'reject', 'cancel'] as const)(
'joins %s mutation work before the next negative corpus',
async (failure) => {
it.each([
{ mutation: 'none', failure: 'timeout' },
{ mutation: 'missing-log', failure: 'timeout' },
{ mutation: 'missing-log', failure: 'reject' },
{ mutation: 'missing-log', failure: 'cancel' }
] as const)(
'joins $failure $mutation work before the next negative corpus',
async ({ mutation, failure }) => {
const report: typeof AiReporter.prototype.report = AiReporter.prototype.report;
const interrupted: AiQualificationTestSession = startSession('missing-log', {
const interrupted: AiQualificationTestSession = startSession(mutation, {
waitForRelease: true,
timeoutAfterReadyMs: failure === 'timeout' ? 50 : undefined
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import type {
IAiQualificationWorkerResult
} from './AiQualificationWorker';

export const QUALIFICATION_TEST_TIMEOUT_MS: number = 15000;
export const QUALIFICATION_CLEANUP_TIMEOUT_MS: number = 2000;
const WORK_TIMEOUT_MS: number = 12000;
const WORK_TIMEOUT_MS: number = 30000;
export const QUALIFICATION_SESSION_TIMEOUT_MS: number =
WORK_TIMEOUT_MS + QUALIFICATION_CLEANUP_TIMEOUT_MS + 1000;
// Isolation tests can await two complete corpus sessions sequentially.
export const QUALIFICATION_TEST_TIMEOUT_MS: number = 2 * QUALIFICATION_SESSION_TIMEOUT_MS;

type WorkerOutcome =
| { success: true; result: IAiQualificationWorkerResult }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { runAiReporterQualificationCorpusAsync } from '../../qualification/AiRep
import type { IAiReporterQualificationResult } from '../../qualification/AiReporterQualification';
import type { IReporterEventEnvelope } from '../../events/IReporterEventEnvelope';

export type AiQualificationMutation = 'missing-log' | 'unrelated-remediation' | 'capture-bytes';
export type AiQualificationMutation = 'none' | 'missing-log' | 'unrelated-remediation' | 'capture-bytes';

export interface IAiQualificationWorkerRequest {
mutation: AiQualificationMutation;
Expand Down Expand Up @@ -48,7 +48,7 @@ if (request.mutation === 'capture-bytes') {
}
return byteLength(...args);
};
} else {
} else if (request.mutation !== 'none') {
AiReporter.prototype.report = function (event: IReporterEventEnvelope<unknown>): void {
if (request.mutation === 'missing-log' && event.type === 'artifactAvailable') {
return;
Expand Down
Loading