Skip to content

build(deps): move to Pierre diffs 1.3.5 - #753

Merged
benvinegar merged 3 commits into
mainfrom
claude/pierre-diffs-upgrade-cy8jgm
Aug 16, 2026
Merged

build(deps): move to Pierre diffs 1.3.5#753
benvinegar merged 3 commits into
mainfrom
claude/pierre-diffs-upgrade-cy8jgm

Conversation

@benvinegar

@benvinegar benvinegar commented Aug 15, 2026

Copy link
Copy Markdown
Member

Upgrades @pierre/diffs from 1.2.2 to 1.3.5. Drop-in: no source changes were needed.

Why

Pierre 1.3.5 added realignChangeContentBySimilarity, which re-splits change blocks whose addition and deletion counts differ, pairing lines by content similarity instead of by position.

This matters to Hunk specifically because diffRows.ts, review/geometry.ts, and lineHighlightPaint.ts all build from the same hunkContent blocks, and Pierre word-diffs a deletion against whatever addition it is paired with. Bad pairing therefore shows up twice: split view puts unrelated lines side by side, and the word-level highlight marks real code as an edit of something it has nothing to do with.

Before / after

Demo changeset — two setup lines added, and one extra argument on the existing return:

 export function renderInvoice(order: Order) {
   const header = buildHeader(order);
-  return formatInvoice(header, order.items, order.taxRate);
+  assertOrderIsPayable(order);
+  const discount = resolveDiscount(order.region);
+  return formatInvoice(header, order.items, order.taxRate, discount);
 }

Before — Pierre 1.2.2. The deleted return is paired with assertOrderIsPayable(order);, so split view sets them opposite each other and the two lines that are genuinely new fall to the bottom:

 1   export function renderInvoice(order: Order) {   │ 1   export function renderInvoice(order: Order) {
 2     const header = buildHeader(order);            │ 2     const header = buildHeader(order);
 3 -   return formatInvoice(header, order.items, …); │ 3 +   assertOrderIsPayable(order);
                                                     │ 4 +   const discount = resolveDiscount(order.region);
                                                     │ 5 +   return formatInvoice(header, …, discount);
 4   }                                               │ 6   }

After — Pierre 1.3.5. The two inserted lines are reported as pure additions, and the deleted return is paired with the added return:

 1   export function renderInvoice(order: Order) {   │ 1   export function renderInvoice(order: Order) {
 2     const header = buildHeader(order);            │ 2     const header = buildHeader(order);
                                                     │ 3 +   assertOrderIsPayable(order);
                                                     │ 4 +   const discount = resolveDiscount(order.region);
 3 -   return formatInvoice(header, order.items, …); │ 5 +   return formatInvoice(header, …, discount);
 4   }                                               │ 6   }

The word-level highlight follows the same pairing. Reading the emphasis spans straight off a real PTY render of that diff, identical in --mode split and --mode stack:

emphasised on the deletion side emphasised on the addition side
1.2.2 return, formatInvoice, (header, , .items, order.taxRate assertOrderIsPayable, (
1.3.5 (nothing) , discount

1.2.2 paints most of an untouched return as changed, against a line it never had anything to do with. 1.3.5 marks exactly the edit.

How often this fires

Parsed 50 commits of this repo's own history under both versions and compared the resulting block structure:

  • 3.1% of files (59 / 1878) get different line pairing
  • those files appear in 26 of 50 commits — about half of real changesets

Small per file, regularly visible in practice.

Performance

Measured A/B in a single process with both copies loaded, interleaved and median-of-N, so machine drift and process startup cancel out.

workload 1.2.2 1.3.5 delta
parsePatchFiles, 50 real commits (3.5 MB) 72.8 ms 78.2 ms +8%
parseDiffFromFile (where Pierre's bundled diff went 8→9) flat, ±2%
launch → first painted diff row (compiled binary) ~750 ms ~750 ms no measurable difference

The +8% is the realignment pass. Note it is paid more broadly than it pays off: the similarity scan runs on every change block with mismatched counts, but only 3.1% of files actually come out different. Synthetic worst cases — patches where every block is mismatched — cost +37% to +102% on parse, though even the worst measured case is 9.2 ms vs 4.6 ms for a 290 KB patch.

Two caveats worth recording:

  • bench:changeset-parse is blind to this change. Its three fixtures contain zero mismatched change blocks, so they never execute the realignment path at all. Run against those fixtures 1.3.5 looks 8–21% faster (the file-splitting rewrite is a genuine win); that number just does not describe real diffs. Worth teaching the fixtures a mismatched-block shape in a follow-up.
  • Importing @pierre/diffs from source costs ~11% more (94.8 ms → 105.7 ms), but that does not survive into the shipped binary, which tree-shakes — end-to-end launch time is unchanged.

Other costs

  • Compiled binary grows 268 KiB on 144 MiB (0.18%)
  • Pulls in @pierre/theme 2.0.0 + @pierre/theming; diff 9.0.0 joins the existing 8.0.3

What this does not fix

1.2.2 throws and silently drops any file whose diff --git header has a quoted path (non-ASCII or spaces) — it read only the unquoted regex capture groups. 1.3.5 fixes that, but it doesn't reach Hunk: src/core/patch/gitFormat.ts already canonicalises those headers before Pierre sees them. And 1.3.5 still returns the octal-escaped name (caf\303\251.ts), so that decoding stays either way. No code to delete here.

Testing

  • bun run typecheck, bun run lint, bun run format:check — clean
  • bun test — 2688 pass, 0 fail
  • bun run test:tty-smoke — 9/9
  • bun run test:integration — 109/111. Both failures pass in isolation, and the 1.2.2 baseline fails one of the same tests under full-suite load, so they are pre-existing timing flakes rather than regressions from this change.
  • Real TTY run on a working tree containing a non-ASCII filename
  • Added a regression test in src/core/diffFile.test.ts for the pairing, and confirmed it fails on 1.2.2 rather than being a tautology

🤖 Generated with Claude Code

https://claude.ai/code/session_01WNJ2ERAzujufYixffz9iR5

@vercel

vercel Bot commented Aug 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hunk-web Ignored Ignored Preview Aug 16, 2026 3:24am

Request Review

@socket-security

socket-security Bot commented Aug 15, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​pierre/​diffs@​1.2.2 ⏵ 1.3.580 +110099 +298100

View full report

@greptile-apps

greptile-apps Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Upgrades @pierre/diffs from 1.2.2 to 1.3.5 to improve similarity-based pairing of unequal change blocks.

  • Updates the package manifest, Bun lockfile, and release changeset.
  • Adds a focused regression test for pairing a deletion with its most similar addition.

Confidence Score: 4/5

The PR appears safe to merge, with a non-blocking opportunity to make the new regression test cover the complete rendered block ordering.

The dependency and lockfile update are internally consistent, while the only accepted concern is that the regression test can miss incorrect placement of the surrounding pure additions.

Files Needing Attention: src/core/diffFile.test.ts

Important Files Changed

Filename Overview
package.json Pins @pierre/diffs to 1.3.5 without changing application source usage.
bun.lock Resolves the upgraded parser and its new theme, theming, and nested diff dependencies consistently.
src/core/diffFile.test.ts Covers similarity-based mixed-line pairing but does not assert the complete block ordering consumed by split view.
.changeset/pierre-diffs-1-3-5.md Accurately documents the user-visible alignment and word-highlight improvement.
Prompt To Fix All With AI
### Issue 1
src/core/diffFile.test.ts:96-108
**Assert complete block ordering**

The test filters out the pure-addition blocks and checks only the mixed 1:1 pair, so an ordering regression that places the two setup lines below the paired return line still passes even though split view consumes the complete `hunkContent` sequence in order.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "build(deps): move to Pierre diffs 1.3.5" | Re-trigger Greptile

Comment thread src/core/diffFile.test.ts
Comment on lines +96 to +108
);
const paired = changes.filter((change) => change.additions > 0 && change.deletions > 0);

expect(paired).toHaveLength(1);
expect(paired[0]).toMatchObject({ additions: 1, deletions: 1 });
expect(metadata.deletionLines[paired[0]!.deletionLineIndex]).toContain(
"return computeTotal(items, taxRate);",
);
expect(metadata.additionLines[paired[0]!.additionLineIndex]).toContain(
"return computeTotal(items, taxRate, discount);",
);
});
});

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.

P2 Assert complete block ordering

The test filters out the pure-addition blocks and checks only the mixed 1:1 pair, so an ordering regression that places the two setup lines below the paired return line still passes even though split view consumes the complete hunkContent sequence in order.

Knowledge Base Used: VCS Diff Sourcing

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/core/diffFile.test.ts
Line: 96-108

Comment:
**Assert complete block ordering**

The test filters out the pure-addition blocks and checks only the mixed 1:1 pair, so an ordering regression that places the two setup lines below the paired return line still passes even though split view consumes the complete `hunkContent` sequence in order.

**Knowledge Base Used:** [VCS Diff Sourcing](https://app.greptile.com/modem/-/custom-context/knowledge-base/modem-dev/hunk/-/docs/vcs-diff-sourcing.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

Updated the regression test to assert both change blocks, including the leading pure-addition block and its order before the paired return line.

This comment was generated by Pi using gpt-5.6-terra

Pierre 1.3.5 re-splits change blocks whose addition and deletion counts
differ, pairing lines by content similarity instead of by position. Hunk
builds split-view rows and Pierre's inline word-diff spans from those
same hunkContent blocks, so the old position-based pairing could sit a
changed line opposite an unrelated one and smear the word highlight
across the whole row. Across 50 commits of this repo's own history the
pairing changes for 3% of files, touching about half of all commits.

The upgrade is otherwise a drop-in: no source changes were needed, parse
timings are unchanged, and the compiled binary grows 268 KiB (0.2%).

Add a regression test for the pairing, which fails on 1.2.2.
@benvinegar
benvinegar force-pushed the claude/pierre-diffs-upgrade-cy8jgm branch from 76f7262 to 5d81e59 Compare August 15, 2026 19:43
@benvinegar
benvinegar merged commit cfe8eee into main Aug 16, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants