Add size-capped module output to run reports - #3842
Conversation
|
@coderabbitai review |
There was a problem hiding this comment.
Code review
Reviewed the diff, the full ModuleOutputBuffer.cs/CoordinatedTextWriter.cs context (not just the hunks), and ran two independent passes (bug-focused and CLAUDE.md-compliance-focused). No high-signal bugs or CLAUDE.md violations found.
What I verified:
ModuleOutputExcerptBuffer.Append/TrimToLimit: the UTF-16-length pre-trim heuristic (value.Length - maximumBytes) is a safe lower bound since one UTF-16 code unit is always ≥1 UTF-8 byte, andTrimToLimitre-enforces the byte cap precisely afterward while skipping UTF-8 continuation bytes and surrogate halves — traced through both unit tests (AppliesOneUtf8TailLimitAcrossBothStreams,RetainsValidUnicodeWhenTailStartsAtSurrogatePair) by hand and the boundary math checks out.- Locking:
CaptureOutputExcerptruns inside the same_lockblock as_outputs.AddinAddOutput, andGetOutputExcerpttakes the same lock, so there's no torn-read risk on the excerpt buffer. - Masking: output is obfuscated once at write time in
CoordinatedTextWriter.WriteCompletedLine/BufferedLogEvent.Format(so secrets registered before a line is written are already redacted going into the excerpt buffer), and obfuscated again inPipelineRunReportFactory.CreateOutputExcerptat report-creation time — covering secrets registered later in the run. This matches the PR description and is backed byRunReportIncludesMaskedModuleOutputWhenEnabledandRunReportMasksOutputAgainAtCreation. stdout/stderrrouting:_isErroris correctly wired only on the error writer (isError: trueon_coordinatedError), andBufferedLogEvent.GetStreamreuses the existingCommandErrorproperty-key convention to classify structured log events.- Schema/JSON:
ModuleOutputExcerptis public and reachable fromPipelineRunReportviaModuleRunReport.Output, so theSystem.Text.Jsonsource generator picks it up transitively forRunReportJsonContext— confirmed by the new round-trip test.
One minor, non-blocking design note:
OptionsValidator.cs (around the new MaxOutputBytesPerModule <= 0 check) validates that MaxOutputBytesPerModule is positive unconditionally, even when IncludeModuleOutput is false. Internally, though, 0 is already the sentinel this feature uses for "capture disabled" (ConsoleCoordinator.GetModuleBuffer passes outputExcerptMaximumBytes: 0 whenever IncludeModuleOutput is false, regardless of what MaxOutputBytesPerModule is set to). That means a user can't explicitly express "output capture is off, and the byte-budget value is irrelevant" — they're forced to leave MaxOutputBytesPerModule at a valid positive number even though it does nothing while IncludeModuleOutput is off. Scoping the check to if (options.RunReport.IncludeModuleOutput && options.RunReport.MaxOutputBytesPerModule <= 0) would make the validation match the actual runtime semantics instead of being stricter than necessary. Given the default (8 KB) is already positive, this is unlikely to bite anyone in practice — flagging only because it's a small mismatch between the validator's contract and the feature's real behavior, not because it's a bug.
Nice, well-tested change overall — the tail-biased byte budgeting with UTF-8/surrogate boundary safety and the double-masking approach are both handled carefully.
|
Addressed the review note in fdbf0bb: MaxOutputBytesPerModule is now validated only when IncludeModuleOutput is enabled. Added enabled/disabled contract tests; both focused tests pass. |
Code reviewRe-reviewed after the latest commit ( Verified the fix:
No new issues found. This closes out the previous review note cleanly. |
|
Resolved the CodeFactor complexity finding in OptionsValidator.ValidateOptions by extracting run-report validation into a focused helper. Behavior is unchanged. Revalidated after merging current main: both exact output-limit validation tests pass, and the core Release build succeeds with 0 warnings/errors. @claude review |
Code reviewRe-reviewed after the latest commit ( Verified:
No new issues found. This closes out cleanly — nice, focused fix. |
Code reviewRe-reviewed at the latest state ( I ran the tests instead of re-deriving the boundary math by hand this time, and found a real failure that both prior review passes missed: 🔴
|
|
Fixed the failing UTF-8 tail regression at d944780. The implementation's tail contract was correct; the test hard-coded a byte budget that only matched Windows CRLF. It now derives the cap from UTF-8 byte count of the emoji plus Environment.NewLine, so Windows and Unix assert the same tail/truncation behavior. Exact-head ModuleOutputExcerptBufferTests pass 3/3; core Release build passes with 0 warnings/errors. |
|
Independent exact-head validation: ModuleOutputExcerptBufferTests 3/3, ModuleOutputBufferTests 32/32, RunReportTests 60/60, core Release build 0 warnings/errors. @claude review |
Code reviewRe-reviewed at the latest state ( Verified the fix (
Everything else from prior rounds still holds and is unchanged by this commit (confirmed the diff from
Docs ( No new issues found. This closes out the review cleanly — good catch-and-fix cycle on the flaky/incorrect cross-platform assertion. |
|
Fixed the three-platform compile failure at |
|
@claude review |
Code reviewRe-reviewed at the latest state ( Verified independently (not just by reading the diff):
Everything from the prior four review rounds still holds and is unchanged by this commit (locking, double-masking, stdout/stderr routing, the UTF-8 tail-trim boundary math, the No new issues found. This closes out the review cleanly — good catch-and-fix on the multi-platform compile break. |
|
Refreshed onto current Validation:
|
|
@claude review |
Code reviewRe-reviewed at the latest state ( Verified this is a merge-only update with no functional change to this PR's feature:
Everything from the prior five review rounds still holds and is unaffected by this merge: locking ( No new issues found. This is a clean rebase — nothing further needed before merge from this feature's perspective. |
|
Fixed the branch-specific Ubuntu failure at Validation:
@claude review |
Code reviewRe-reviewed at the latest state ( Verified this is a minimal, test-only change:
Everything from the prior six review rounds still holds (locking, double-masking, stdout/stderr routing convention, UTF-8 tail-trim boundary math, No new issues found. This closes out cleanly — good fix for a legitimate test-isolation race rather than a product bug. |
|
Refreshed with current main at 91df4ed. Merge exposed two PR-owned stale PipelineOptions console initializers; migrated them to nested Console. Validation: ModuleOutputExcerptBufferTests 3/3, ModuleOutputBufferTests 32/32, RunReportTests 73/73, lightweight core Release build 0 warnings/errors. Please re-review current head. |
Code reviewRe-reviewed at the latest state ( Verified this is a merge + mechanical-fix update with no functional change to this PR's own feature:
Everything from the prior eight review rounds still holds and is unaffected by this update: locking ( No new issues found. This closes out cleanly — the merge is clean and the compile fix is correct and complete. |
|
CI triage at |
|
Addressed both latest review findings in 68472cc: coalesced small output writes before masked suffix analysis, and removed eager enumeration of arbitrary structured logging state. Validation: excerpt 20/20; output buffer 38/38; core Release build 0 warnings/errors. |
Code reviewRe-reviewed exact head What changed since the last review (
Both are reasonable, low-risk changes. Neither file's Still open — both flagged in the prior two review rounds, neither addressed here🔴 🟠 Why this is the architectural issue worth fixing now, not the two symptomsThis is the third distinct formula for "what did we actually keep" that This still needs to be resolved before merge — both issues were flagged in the prior two rounds and remain open in this commit. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 68472ccdd9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Addressed alternating-stream masked suffix rescans in 377616c using one mapped mask pass per stream. Validation: ModuleOutputExcerptBufferTests 21/21; SecretMaskingPatternTests 27/27; ModularPipelines.slnx Release build passed with 0 warnings and 0 errors. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 377616ca6b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Code reviewRe-reviewed at the latest state ( What changed: I traced the offset math by hand for the boundary case that matters most here — a truncation point falling inside a secret span: Both previously-flagged blockers are still open — neither is touched by this commit🔴 🟠 Same architectural note as the last two rounds, now reinforced by this commitThis commit is the second full rewrite of This still needs to be resolved before merge — both issues were flagged in the prior two rounds and remain open in this commit. |
|
Addressed persistence-boundary excerpt validation in 5410a73. Both report and built-in history writes now fail closed after the temp-file sink. Validation: RunReportTests 93/93 passed; ModularPipelines.slnx Release build passed with 0 warnings and 0 errors. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5410a731a4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Hold secret registration through the atomic file move so excerpts cannot become stale between validation and publication.
|
Addressed the publication-boundary race in c3168ac. Secret registration and the atomic move now share the same lock; a failed version guard rewrites and publishes excerpt-free JSON. Focused tests 94/94; core Release build clean. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c3168acdfa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Carry line-terminator metadata through buffered console output so unterminated writes remain exact in rendering and report excerpts.
|
Preserved Write vs WriteLine semantics end-to-end in 86e18dd, including excerpt byte accounting. Three affected suites pass (22/22, 19/19, 38/38); core Release build clean. |
Review: PR #3842 — Add size-capped module output to run reportsI traced the actual PR diff ( Overall this is a well-tested feature ( 1.
|
|
Addressed the latest review at exact head 77dffa3. TruncatedBytes now derives from source bytes represented by the final rebalanced masked tails; fail-closed excerpt omissions emit debug diagnostics; UTF-8 boundary and secret-match scans are centralized; decoded chunk text is cached; the secret publication lock contract is documented. Validation: ModuleOutputExcerptBufferTests 22/22, SecretObfuscatorTests 3/3, ModuleOutputBufferTests 38/38, ModularPipelines.slnx Release build 0 warnings/errors. @codex review exact head 77dffa3. @claude review exact head 77dffa3. |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce54ec037e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .Select(secret => GetMaximumMatchByteCount(secret, caseInsensitive)) | ||
| .DefaultIfEmpty() | ||
| .Max(); | ||
| if (maximumMatchBytes > maximumBytes) |
There was a problem hiding this comment.
Allow untrimmed output when a secret exceeds the cap
When any registered secret is larger than MaxOutputBytesPerModule, this unconditional check suppresses every module excerpt, even if that module emitted less than the cap and its complete output is still retained. For example, with an 8-byte cap, a registered 9-byte secret, and output ok\n, there is no discarded boundary and the whole value can be safely scanned, yet CreateExcerpt returns null. Apply this fail-closed condition only to streams whose raw prefix was actually trimmed so unrelated short diagnostics remain available.
Useful? React with 👍 / 👎.
Code reviewRe-reviewed at the latest state ( Verified the new commit (
No issues found in this delta. All four substantive findings and the minor lock-contract note from the previous full review round were addressed in |
Closes #3748
Summary
ModuleRunReport.Outputexcerpts with separate stdout/stderr tailsValidation
ModuleOutputExcerptBufferTests: 3/3ModuleOutputBufferTests: 32/32RunReportTests: 50/50, plus focused JSON round-trip 1/1ModularPipelines.slnxRelease build: 0 warnings, 0 errorsSummary by CodeRabbit
New Features
Bug Fixes
Documentation