fix(default-reporter): restore ansi-diff to stop duplicated output lines#12698
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRestores ChangesRestore ansi-diff in default reporter
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested labels: Suggested reviewers: ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoRestore ansi-diff rendering to prevent duplicated default-reporter output Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
Context used 1. Diff not reset on logs
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pnpm11/cli/default-reporter/src/index.ts`:
- Around line 73-76: The differ in createDiffer is sized from proc.stdout even
though DefaultReporter may render to proc.stderr when useStderr is enabled, so
update the geometry source to match the actual output stream being written to.
Adjust the logic around the DefaultReporter/createDiffer setup to choose rows
and columns from the active render stream, using proc.stderr when useStderr is
true and proc.stdout otherwise, so ansi-diff gets the correct dimensions.
In `@pnpm11/cli/default-reporter/test/reporterRenderer.ts`:
- Around line 20-22: The reporter tests are using the settle() helper as a fixed
30 ms sleep, which makes them flaky on slower CI. Replace the time-based wait
with a deterministic wait on an observable reporter signal, such as a change in
writes, a specific sticky-line entry, or the next expected progress write after
invoking the reporter logic. Update the affected assertions to await the exact
state they need, and reuse settle() only if it waits for that concrete condition
rather than wall-clock time.
- Around line 73-77: The reporter test only checks the first and last writes, so
it can miss a duplicated sticky verdict in the middle; update the assertion in
reporterRenderer’s sticky-verdict test to verify every write after the first
render does not contain the sticky block. Use the existing writes array in the
test and the stripAnsi checks around “Lockfile passes supply-chain policies” to
assert no subsequent entry reprints that text after the initial appearance.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 47fa8528-75b6-48e5-ac4b-7779236b54c7
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml,!pnpm-lock.yaml
📒 Files selected for processing (5)
.changeset/restore-ansi-diff.mdpnpm-workspace.yamlpnpm11/cli/default-reporter/package.jsonpnpm11/cli/default-reporter/src/index.tspnpm11/cli/default-reporter/test/reporterRenderer.ts
|
Code review by qodo was updated up to the latest commit 935c1fe |
935c1fe to
8359f95
Compare
|
Code review by qodo was updated up to the latest commit 8359f95 |
1 similar comment
|
Code review by qodo was updated up to the latest commit 8359f95 |
Integrated-Benchmark Report (Linux)Commit: Each scenario reports direct installs and pnpr installs. Bencher consumes pacquet@HEAD and pnpr@HEAD. Scenario: Isolated linker: fresh restore, cold cache + cold store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 4.04023242602,
"stddev": 0.16297494369737053,
"median": 3.9942584072200003,
"user": 3.902401799999999,
"system": 3.37636738,
"min": 3.85822772022,
"max": 4.386433241220001,
"times": [
4.14305278822,
4.17253396122,
3.8988361452199998,
4.10917139922,
4.386433241220001,
3.96997172822,
3.85822772022,
4.0185450862200005,
3.93388181622,
3.91167037422
]
},
{
"command": "pacquet@main",
"mean": 3.9562374204200004,
"stddev": 0.11640007381476733,
"median": 3.9062300417199998,
"user": 3.9197683999999997,
"system": 3.3459535799999998,
"min": 3.85170351222,
"max": 4.17055854322,
"times": [
4.12941787222,
3.85874949322,
3.85170351222,
4.17055854322,
4.04164126522,
3.9096435122199997,
3.9397079382199998,
3.90281657122,
3.9023315792199997,
3.85580391722
]
},
{
"command": "pnpr@HEAD",
"mean": 2.1009889123199996,
"stddev": 0.10680160968424873,
"median": 2.0673269937199996,
"user": 2.7198554999999995,
"system": 2.87009518,
"min": 1.97612854322,
"max": 2.2413004962199996,
"times": [
2.0197827892199998,
1.97612854322,
2.23391190722,
2.0463781532199996,
1.97669412722,
2.2413004962199996,
2.03451025522,
2.0882758342199996,
2.2271072522199997,
2.1657997652199996
]
},
{
"command": "pnpr@main",
"mean": 2.16106185512,
"stddev": 0.13562892317747247,
"median": 2.20318067372,
"user": 2.6988987,
"system": 2.88268368,
"min": 1.95966859622,
"max": 2.35652720622,
"times": [
2.21576502722,
2.1228377362199997,
1.97140313222,
2.19572525122,
2.2286178792199998,
2.35652720622,
2.3121432392199996,
1.95966859622,
2.21063609622,
2.03729438722
]
}
]
}Scenario: Isolated linker: fresh restore, hot cache + hot store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 0.6443029957599999,
"stddev": 0.009318673484328318,
"median": 0.6432083981600001,
"user": 0.3901028,
"system": 1.32245758,
"min": 0.63030807666,
"max": 0.65770906966,
"times": [
0.63666744766,
0.6552924396600001,
0.63829415666,
0.65770906966,
0.64649867766,
0.63030807666,
0.65500128266,
0.63684201066,
0.64061552966,
0.64580126666
]
},
{
"command": "pacquet@main",
"mean": 0.63530658336,
"stddev": 0.009075043929393532,
"median": 0.63483265166,
"user": 0.3713532,
"system": 1.30797428,
"min": 0.6201502306600001,
"max": 0.6531826886600001,
"times": [
0.63242417066,
0.6268708766600001,
0.64411450666,
0.63158554066,
0.63523316166,
0.6398393546600001,
0.6531826886600001,
0.6201502306600001,
0.63468794166,
0.6349773616600001
]
},
{
"command": "pnpr@HEAD",
"mean": 0.71387516566,
"stddev": 0.09026405292753106,
"median": 0.6883881836600001,
"user": 0.4090644,
"system": 1.35477268,
"min": 0.66599244266,
"max": 0.9686076556600001,
"times": [
0.69093931366,
0.6834826096600001,
0.66599244266,
0.68583705366,
0.67564913766,
0.69855362666,
0.69708853066,
0.7006641676600001,
0.67193711866,
0.9686076556600001
]
},
{
"command": "pnpr@main",
"mean": 0.69028119276,
"stddev": 0.02058241036034452,
"median": 0.6927431161600001,
"user": 0.38197509999999996,
"system": 1.3548669800000002,
"min": 0.6653587696600001,
"max": 0.7368641326600001,
"times": [
0.6988794016600001,
0.68150317666,
0.69861737366,
0.6653587696600001,
0.69256023466,
0.6703137866600001,
0.67103838066,
0.69475067366,
0.7368641326600001,
0.6929259976600001
]
}
]
}Scenario: Isolated linker: fresh install, cold cache + cold store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 4.22013982302,
"stddev": 0.05337813253976519,
"median": 4.22364630542,
"user": 3.8210879999999996,
"system": 3.2773365000000005,
"min": 4.13187914692,
"max": 4.29633080392,
"times": [
4.28679111692,
4.20981567292,
4.15015677292,
4.13187914692,
4.18962068292,
4.21729347492,
4.23147427992,
4.22999913592,
4.29633080392,
4.25803714292
]
},
{
"command": "pacquet@main",
"mean": 4.21856663312,
"stddev": 0.06627048737547761,
"median": 4.20820094692,
"user": 3.8118811999999993,
"system": 3.2779556999999997,
"min": 4.09797089292,
"max": 4.35652365492,
"times": [
4.24412168592,
4.19831035392,
4.20207195592,
4.21052154092,
4.17210546892,
4.2058803529199995,
4.23550429492,
4.26265612992,
4.09797089292,
4.35652365492
]
},
{
"command": "pnpr@HEAD",
"mean": 2.19500767012,
"stddev": 0.11276061482110641,
"median": 2.14992208642,
"user": 2.5560032,
"system": 2.7880747,
"min": 2.05472537692,
"max": 2.38058135292,
"times": [
2.12604874192,
2.13544092992,
2.05472537692,
2.31807175592,
2.08904473792,
2.22109953992,
2.1644032429199997,
2.33408172192,
2.38058135292,
2.12657930092
]
},
{
"command": "pnpr@main",
"mean": 2.2318869251199995,
"stddev": 0.17124758028635934,
"median": 2.2723088044199997,
"user": 2.5362066,
"system": 2.7873469,
"min": 1.97765763092,
"max": 2.45622668292,
"times": [
2.45622668292,
2.33666207492,
1.98722575692,
2.36739932592,
2.18207216192,
2.31057726592,
1.97765763092,
2.39332682092,
2.07368118792,
2.2340403429199998
]
}
]
}Scenario: Isolated linker: fresh install, hot cache + hot store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 1.3807709204800003,
"stddev": 0.012380852075941022,
"median": 1.37923366188,
"user": 1.3413869199999997,
"system": 1.74325728,
"min": 1.36643363588,
"max": 1.4011470028800002,
"times": [
1.38068341588,
1.3672068188800002,
1.4011470028800002,
1.3895595848800002,
1.38477683688,
1.3974634028800001,
1.36643363588,
1.37778390788,
1.3741220578800002,
1.36853254088
]
},
{
"command": "pacquet@main",
"mean": 1.38655501118,
"stddev": 0.07536432676660415,
"median": 1.36208052738,
"user": 1.3125663199999997,
"system": 1.70842588,
"min": 1.3475363428800002,
"max": 1.5988863128800002,
"times": [
1.37590062688,
1.5988863128800002,
1.3560200958800002,
1.36545363888,
1.37626668988,
1.3475363428800002,
1.35870741588,
1.3562459178800002,
1.3527474488800002,
1.3777856218800002
]
},
{
"command": "pnpr@HEAD",
"mean": 0.67117803338,
"stddev": 0.03347406318517879,
"median": 0.6628736098800001,
"user": 0.35202432000000006,
"system": 1.30030008,
"min": 0.64625809488,
"max": 0.76226442888,
"times": [
0.66237791288,
0.64625809488,
0.65392173288,
0.64739019888,
0.76226442888,
0.6633693068800001,
0.67622080188,
0.67374660588,
0.66429675688,
0.66193449388
]
},
{
"command": "pnpr@main",
"mean": 0.6484898949800001,
"stddev": 0.008222503246224302,
"median": 0.64863895438,
"user": 0.31801872,
"system": 1.28419408,
"min": 0.63504486988,
"max": 0.65915258188,
"times": [
0.64271068088,
0.64942009888,
0.65658973888,
0.64266044288,
0.63504486988,
0.65262734788,
0.64044745488,
0.65915258188,
0.65838792388,
0.64785780988
]
}
]
}Scenario: Isolated linker: fresh install, cold cache + hot store
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 3.0546317284199995,
"stddev": 0.048033795995897674,
"median": 3.04471167182,
"user": 1.8037268800000004,
"system": 2.01147858,
"min": 2.99748853782,
"max": 3.16152963482,
"times": [
2.99748853782,
3.07123209282,
3.0092442128199997,
3.0452275418199997,
3.0881493988199997,
3.07500201682,
3.01150309382,
3.16152963482,
3.04419580182,
3.0427449528199997
]
},
{
"command": "pacquet@main",
"mean": 3.0158926195199998,
"stddev": 0.016724959251692068,
"median": 3.01339305632,
"user": 1.75189938,
"system": 1.9993786799999995,
"min": 2.98818732082,
"max": 3.05188848382,
"times": [
3.00300975382,
3.01232567382,
3.02620593082,
3.02617039682,
3.01395679582,
3.0155519268199997,
3.01282931682,
2.98818732082,
3.05188848382,
3.00880059582
]
},
{
"command": "pnpr@HEAD",
"mean": 0.6695108290199998,
"stddev": 0.011740548468366831,
"median": 0.6698445363200001,
"user": 0.34496977999999995,
"system": 1.31073588,
"min": 0.65062622182,
"max": 0.68380402982,
"times": [
0.65724556382,
0.65837784382,
0.68177287882,
0.66711803682,
0.67932636682,
0.66407976982,
0.67257103582,
0.65062622182,
0.68380402982,
0.68018654282
]
},
{
"command": "pnpr@main",
"mean": 0.64909312562,
"stddev": 0.008259728924758953,
"median": 0.64813122682,
"user": 0.3350743799999999,
"system": 1.2641922799999998,
"min": 0.63679997882,
"max": 0.66629852982,
"times": [
0.64743957882,
0.64839381482,
0.64417944582,
0.65647025482,
0.63679997882,
0.64994010682,
0.64786863882,
0.66629852982,
0.64076775382,
0.65277315382
]
}
]
}Scenario: Isolated linker: fresh restore, cold cache + cold store + cold pnpr
BENCHMARK_REPORT.json{
"results": [
{
"command": "pacquet@HEAD",
"mean": 6.758182756679998,
"stddev": 0.16251191726906428,
"median": 6.6841924847800005,
"user": 4.075884820000001,
"system": 3.6476667399999996,
"min": 6.57428153728,
"max": 7.03176838028,
"times": [
6.73828741528,
6.67528608828,
7.02973257928,
6.68810319828,
6.86617460028,
6.67645557228,
7.03176838028,
6.680281771280001,
6.621456424280001,
6.57428153728
]
},
{
"command": "pacquet@main",
"mean": 6.8089628182799995,
"stddev": 0.18444629337322235,
"median": 6.734120967780001,
"user": 4.04005412,
"system": 3.66157444,
"min": 6.59239039028,
"max": 7.10332520928,
"times": [
6.77265857328,
6.975362625280001,
6.629149416280001,
6.68812777028,
6.99751126828,
7.10332520928,
6.695583362280001,
6.66263076028,
6.59239039028,
6.97288880728
]
},
{
"command": "pnpr@HEAD",
"mean": 4.84177453788,
"stddev": 0.11164007810040211,
"median": 4.82685081378,
"user": 2.83000792,
"system": 3.08916594,
"min": 4.75197609928,
"max": 5.1185402282800005,
"times": [
4.75485135028,
4.8650274832800005,
4.89053003128,
5.1185402282800005,
4.753538580280001,
4.8688990082800006,
4.79953602528,
4.76068097028,
4.75197609928,
4.85416560228
]
},
{
"command": "pnpr@main",
"mean": 4.870695733380001,
"stddev": 0.05428566292421363,
"median": 4.867455796780001,
"user": 2.8150612199999996,
"system": 3.1030313400000002,
"min": 4.7984344322800006,
"max": 4.991076312280001,
"times": [
4.88594138928,
4.79896298328,
4.858696972280001,
4.894029217280001,
4.853549511280001,
4.891354922280001,
4.868159637280001,
4.991076312280001,
4.866751956280001,
4.7984344322800006
]
}
]
} |
|
| Branch | pr/12698 |
| Testbed | pnpr |
⚠️ WARNING: No Threshold found!Without a Threshold, no Alerts will ever be generated.
Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the--ci-only-thresholdsflag.
Click to view all benchmark results
| Benchmark | Latency | milliseconds (ms) |
|---|---|---|
| isolated-linker.fresh-install.cold-cache.cold-store | 📈 view plot | 2,195.01 ms |
| isolated-linker.fresh-install.cold-cache.hot-store | 📈 view plot | 669.51 ms |
| isolated-linker.fresh-install.hot-cache.hot-store | 📈 view plot | 671.18 ms |
| isolated-linker.fresh-restore.cold-cache.cold-store | 📈 view plot | 2,100.99 ms |
| isolated-linker.fresh-restore.cold-cache.cold-store.cold-pnpr | 📈 view plot | 4,841.77 ms |
| isolated-linker.fresh-restore.hot-cache.hot-store | 📈 view plot | 713.88 ms |
8359f95 to
f3fa416
Compare
|
Code review by qodo was updated up to the latest commit f3fa416 |
1 similar comment
|
Code review by qodo was updated up to the latest commit f3fa416 |
|
The same fix should be implemented in pacquet if you want this to be merged. |
|
|
@zkochan on second thought, ok I'll add the same fix to pacquet. Three ways to go about it:
I lean toward 3 unless you'd prefer to keep it internal (2) or you're OK with the existing crate's deps (1). |
f3fa416 to
6886fff
Compare
There was a problem hiding this comment.
Pull request overview
Restores ansi-diff-based differential rendering in the pnpm v11 default reporter to eliminate repeated “sticky” output blocks and avoid cursor-up growth issues from the prior full-frame redraw approach, while preserving the “clear external output below the frame” behavior.
Changes:
- Reintroduce
ansi-diffin the default reporter render loop and append\x1b[0Jafter each update to clear below-frame output. - Add regression tests to ensure unchanged sticky blocks aren’t reprinted and that each write ends with erase-to-end-of-display.
- Add
ansi-diffto the workspace catalog, lockfile, and the@pnpm/cli.default-reporterpackage dependencies, plus a changeset entry.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm11/cli/default-reporter/test/reporterRenderer.ts | Adds regression tests for differential rendering (no duplicated sticky blocks) and “erase below frame” behavior. |
| pnpm11/cli/default-reporter/src/index.ts | Switches rendering back to ansi-diff updates and appends erase-to-end-of-display per write. |
| pnpm11/cli/default-reporter/package.json | Adds ansi-diff dependency via the workspace catalog. |
| pnpm-workspace.yaml | Adds ansi-diff to the workspace catalog. |
| pnpm-lock.yaml | Locks ansi-diff@1.2.0 in catalogs and importer deps. |
| .changeset/restore-ansi-diff.md | Adds a patch changeset for @pnpm/cli.default-reporter and pnpm. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Code review by qodo was updated up to the latest commit 6886fff |
1 similar comment
|
Code review by qodo was updated up to the latest commit 6886fff |
6886fff to
c6e936b
Compare
|
Code review by qodo was updated up to the latest commit c6e936b |
|
@zkochan PR is ready |
0887ec2 to
5c4e051
Compare
|
Code review by qodo was updated up to the latest commit 5c4e051 |
1 similar comment
|
Code review by qodo was updated up to the latest commit 5c4e051 |
PR pnpm#12351 replaced ansi-diff with manual full-frame reprint, which re-writes unchanged sticky blocks on every progress tick. This caused cached lockfile verdicts and deprecation warnings to appear dozens of times in terminals that record each write (Warp, script, CI logs). The manual countRows also produced unbounded cursor-up values when the frame was taller than the terminal, causing an infinite repaint loop on pnpm run --parallel. TypeScript CLI: restore the `ansi-diff` npm package for differential rendering, wrapping its output with \r (column reset) + \x1b[0J (erase below frame) to preserve the external-process-output fix from pnpm#12351. Rust pacquet port: implement a zero-dependency differential renderer (`diff.rs`) with the same algorithm, replacing the full-frame reprint in `Sink::write_output`. Closes pnpm#12634.
…rter test Builds on the restored ansi-diff differential renderer: - pacquet: guarantee a trailing newline before diffing a frame, matching the TypeScript reporter. This keeps an interactive prompt on a fresh line below the frame instead of joined onto the last progress line, and leaves the differ's tracked cursor column at 0 so it stays in sync with the \r prepended on the next update (otherwise the inline diff computes relative moves from a stale column and corrupts in-place rendering). - pacquet: move the differ's inline test module into src/diff/tests.rs with explicit imports and drop a stray trailing comma, so cargo dylint passes. - TypeScript: locate the sticky lockfile verdict's first render with findIndex instead of assuming writes[0], and wrap each reporter test body in try/finally so the subscription is always stopped.
- Add col !== width guard before inline diff, matching the JS ansi-diff edgecase check that prevents mispositioning at exact-width wrap boundaries. - Fix clearDown to start from the cursor's current row (self.row) instead of new_last_row, matching the JS _clearDown pattern. The previous code could clear frame content when trailing lines were unchanged and the frame shrank. - Document the visible_width vs wcwidth simplification.
Add 8 new tests covering: - inline diff skipped for ANSI-containing lines - inline diff threshold edge case - full line rewrite with clear - clear_down starting from cursor row (not new_last_row) - soft-wrapped line height tracking - empty frame clears all previous content - multiple progress ticks (simulated install sequence) - frame without trailing newline
…ocation - clear_down_from_cursor_row: replace weak || assertion with direct checks that Line A is absent, Line B changed is present, and clear sequence is emitted. - TS reporterRenderer: capture writes.length before the 'fetched' event and wait for an increase, so the test can't pass early. - pacquet Sink::write_output: write \r, diff output, and erase codes as separate write_all calls instead of format!() which allocated a new String on every frame.
…test Compose the \r + diff + erase sequence into a reusable per-sink buffer and emit it with one write_all, keeping each frame update atomic against interleaved writers without allocating on the hot progress path. Rework inline_diff_skipped_for_small_change (which actually exercised the inline-diff happy path already covered by inline_diff_writes_only_changed_chars) into inline_diff_skipped_for_short_common_affix, covering the left + right <= 4 full-rewrite branch its name promised.
|
@zkochan the same tests are failing on all of my PRs. They're infra stuff. |
5c4e051 to
6fb996a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pacquet/crates/default-reporter/src/diff.rs`:
- Line 64: `Diff::update_into` is writing `new_line.raw` directly into the
frame, so terminal control sequences from lifecycle stdout/stderr can reach the
renderer unchanged. Update the frame-building path in `diff.rs` to sanitize or
strip VT/ANSI controls before `out.push_str`, and make the same sanitization
change in the matching default-reporter implementation in
`@pnpm/cli.default-reporter` so both renderers handle the same safe text.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 6826d1dc-13de-4e56-a937-578e3006d259
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml,!pnpm-lock.yaml
📒 Files selected for processing (8)
.changeset/restore-ansi-diff.mdpacquet/crates/default-reporter/src/diff.rspacquet/crates/default-reporter/src/diff/tests.rspacquet/crates/default-reporter/src/lib.rspnpm-workspace.yamlpnpm11/cli/default-reporter/package.jsonpnpm11/cli/default-reporter/src/index.tspnpm11/cli/default-reporter/test/reporterRenderer.ts
✅ Files skipped from review due to trivial changes (1)
- .changeset/restore-ansi-diff.md
🚧 Files skipped from review as they are similar to previous changes (6)
- pnpm11/cli/default-reporter/package.json
- pnpm11/cli/default-reporter/test/reporterRenderer.ts
- pnpm11/cli/default-reporter/src/index.ts
- pnpm-workspace.yaml
- pacquet/crates/default-reporter/src/lib.rs
- pacquet/crates/default-reporter/src/diff/tests.rs
|
Code review by qodo was updated up to the latest commit 6fb996a |
1 similar comment
|
Code review by qodo was updated up to the latest commit 6fb996a |
|
Status update on CI:
Root cause, in two parts:
The fix belongs in a separate PR against Written by an agent (Claude Code, claude-fable-5). |
|
@zkochan incoming PR soon. |
|
The TS CI regression diagnosed above is fixed by pnpm/pnpm#12769 — once that lands on Written by an agent (Claude Code, claude-fable-5). |
Summary
PR #12351 replaced
ansi-diff(differential rendering) with manual full-frame reprint to fix external-process output bleeding into the progress line (#12350). The full-frame reprint caused two regressions:script, CI logs, scrollback).countRows/prevRowsgrows without bound when the frame is taller than the terminal, causing an infinite scroll/repaint loop onpnpm run --parallel.This PR restores
ansi-difffor differential rendering, wrapping its output with\r(column reset) +\x1b[0J(erase below frame) to preserve the #12350 fix. Instrumented traces confirmed the root cause and verified the duplication fix.The Rust
pacquet/port is fixed in this same PR:pacquet/crates/default-reporter/had the identical manual full-frame reprint (prev_rows/count_rows+ cursor-up), so aFrameDifferthat ports theansi-diffline-diff algorithm now replaces it, driven through the sink with the same\r+\x1b[0Jwrapper. Both stacks stay behaviorally aligned.Closes #12634.
Squash Commit Body
Checklist
pacquet/port, or the description notes what still needs porting.— Implemented in both: TypeScript
@pnpm/cli.default-reporter(restoredansi-diff) and pacquetpacquet/crates/default-reporter/(aFrameDifferporting theansi-diffalgorithm).pnpm changeset) if this PR changes any publishedpackage. Keep it short and written for pnpm users — it becomes a release note.
Written by an agent (opencode, glm-5.2).
Updated by an agent (Claude Code, claude-opus-4-8).
Summary by CodeRabbit
ansi-diffpatch releases.