Skip to content

Show the Code tab's lines side by side behind a split view row - #77

Merged
krishhgg merged 18 commits into
masterfrom
t3term/pull-request-split
Oct 18, 2026
Merged

krishhgg merged 18 commits into
masterfrom
t3term/pull-request-split

Conversation

@krishhgg

@krishhgg krishhgg commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Adds a row to the Code tab that sets the lines before the change beside those after it, as the desktop's split view does.

  • ◫ Split diff view sits between the fold row and the wrap row once the tab has files. Enter or a click sets the lines before the change on the left and those after it on the right, and the row then reads ⊟ Stacked diff view. A read again and another diff picked from the commits keep the choice. The status line says Enter show split diff view or Enter show stacked diff view.
  • Side by side, each line in context shows on both sides with its number on each. A run of lines removed and added pairs them by position, as @pierre/diffs does, and the shorter side stays blank. A row is as tall as its taller side. A file added or deleted keeps one column. No newline at end of file goes under the hunk's last row on its own side.
  • Review threads show across both sides under the row with their line, a thread on the left side's line first.
  • Unwrapped, both sides' text scrolls by the same columns, each cut at the end of its side. The text stops once the end of the side that runs on furthest shows.
  • Below 6 columns the lines stack.
  • docs/pull-request-panel.md gains a Layout row, and the README names the row.
  • The Code recipe drives the split view at 100x30: pairs, blank sides, both sides scrolling sideways and an added file in one column. It keeps the choice through a read again, a commit picked and another link (94fca91, 2d10ef4). A read of the first slice drops the later ones, and once the layout row pushes the files down, Home after r is too far from the end to read them again, so the viewed-marks steps press r at the end of the files.

Stacked on #76.

The details dialog on #7's Code tab with src/config/reader.rs unfolded, its lines one under the other, and the row ◫ Split diff view chosen between ⇈ Collapse all files and ↵ Disable line wrapping. The status line reads Enter show split diff view.

After Enter, the row reads ⊟ Stacked diff view and the lines show side by side with a bar between them. Line 4 before the change, use crate::config::Source in red, sits beside line 4 after it in green, and line 5 after it has a blank left side. Line 26, let first, removed in red, has a blank right side.

With line wrapping disabled, each line side by side takes one row, cut at the end of its side.

After L, both sides' text has moved 26 columns to the left while each side's numbers and marks stay, so line 4 after the change reads :Schema; and line 33 reads and checks the file.

All four come from the fixture server at 120x48, where the details show as a dialog 54 columns wide inside.

Decision log

What I noticed. docs/pull-request-panel.md listed the desktop's split view among what the Code tab lacked. t3term always stacked the lines, so a reader couldn't set a line removed beside the line that replaced it.

How I confirmed it. In the pinned T3 source (f570bd2):

  • diffLayout is a client setting that defaults to stacked (packages/contracts/src/settings.ts:53-55 and 378). The toolbar's toggle group has Stacked diff view and Split diff view (apps/web/src/components/pullRequest/PullRequestCodeTab.tsx:1259-1278), and sets @pierre/diffs' diffStyle to unified or split (872).
  • In pierre 1.5.2, a change is every run of lines removed and added in a row, in any order (dist/utils/parsePatchFiles.js:182-205). Split, the lines removed pair with those added by position, and the shorter side's rows are buffers (dist/utils/iterateOverDiff.js:213 and 443-446), drawn with diagonal stripes. A file added or deleted shows in one column (dist/renderers/DiffHunksRenderer.js:916-922). The no-newline note goes under the hunk's last row on the side it belongs to (863-898). The two sides are equally wide, and with overflow: scroll they scroll together (dist/managers/ScrollSyncManager.js:47 and 56).

Options.

  • Chosen: one row that names the other layout, as Stop the Code tab's lines wrapping, and scroll them sideways #76 did for wrap. Rejected: two rows, one per layout, which take a row more to say the same.
  • Chosen: one sideways offset for both sides, as pierre syncs them. The text stops where the side that runs on furthest ends, so the other side may end in blanks.
  • Chosen: the left side's width decides whether numbers show, for both sides. Rejected: deciding each side on its own, which at an odd width could show numbers on the right and not the left.
  • Chosen: a bar and a space between the sides. A bare bar left the right side's two-digit numbers touching it in the screenshots, where the left side's stand a space from the details' edge.
  • Chosen: review threads across both sides under the paired row. Rejected: each thread under its own side, as the desktop does. The details are at most 54 columns wide, so a card under one side would have about 24 columns for its comments.
  • Chosen: lines stack below 6 columns, where two sides can't each fit a mark and a column of text. The row stays, so the choice holds once the details are wider again.

What review changed.

  • The first screenshots showed the right side's numbers touching the bar, so a space now follows it.
  • A mutation pass changed code.rs and pull_requests.rs in 58 ways, and the tests caught 48 at first.
    • Six survived for want of a case. A renamed file shown in one column, the note after a line in context (two ways) or after a line added, a left side whose text runs further than the right's, and the column an odd width leaves over. A renamed file joins the one-column test, and two new tests catch the rest.
    • Three changed no row, so the code they changed is gone. Every run of a file's rows had the same sides, so the file keeps them once rather than comparing them per run. The left side's padding to SIDE spans now happens whether the lines wrap or not. The right side no longer drops the number before the change, which line_rows never shows where a line has a number after it.
    • One pattern matched two places. Run as two mutants, the tests caught both.
    • A second pass of 12, over the survivors and the code reworked for them, caught all 12.
  • Greptile found that the numbers' column was sized by the hunks and by the new numbers of the unchanged lines shown, but not by their old numbers. Lines after a removal can have an old number with more digits, so the left side's text started a column late. a1788a2 also counts their old numbers side by side, and a test removes five lines so that old line 10 shows beside new line 5.

fbaad0f and 2403b06 merge #76 at a634a86 and ef9e2ca, which bring #66's fix for a hunk that removes nothing at the highest line number (8073497) and its test, with the same patch.

3064610 merges #76 at bc9fb2d, which returns from the Timeline before #75's whitespace steps (d9fd767), with the same patch.

50e1660 and f78d5f7 merge #76 at b916980 and 044993f, which bring #72's fix that counts each Enter on a run while the file's text is read, #75's test that no hunk is read once the whitespace steps run out, and the fixes that lay a thread's comments and its loaded pages out again when the theme changes (#68's ad1590c and #69's 942dad5).

Known limits.

  • The details are at most 54 columns wide in a dialog and 34 in a pane, so each side has at most 26 columns. The desktop's panel is much wider.
  • A review thread shows across both sides, where the desktop shows it under its own side. A side with no line is blank, where the desktop fills it with diagonal stripes.
  • The diffLayout setting isn't read, so the lines always start stacked, and the choice isn't saved. The desktop saves it to the client settings.
  • A run that removes more lines than it adds, or adds more than it removes, pairs its lines in git's order. pierre may move the extra lines before or after the rest to line up the most alike lines (dist/utils/realignChangeContent.js), which changes which lines sit side by side.
  • The Code tab still lacks the file tree.

Tests

  • code/tests.rs: no row before a slice or with no files. The row's label, action, color and target both ways, and bodies laid out again after the toggle. The rows side by side at 40 columns, with uneven pairs, a blank side, a wrapped line making its row taller and the note on its own side. The same rows with whitespace shown, where the patch interleaves its lines. The numbers' threshold, the odd column going right, the fallback below 6 columns and back to stacked. Threads under paired rows, the left first, and the unwrapped runs stopping at each card. Unchanged lines with a different number on each side. Added and deleted files in one column, with runs and widest, and a renamed file side by side. The no-newline note on both sides after a line in context and on the right after a line added. At 41 columns, the right side taking the spare column and a left side that runs furthest setting the widest. The choice kept through a later slice, a read again and a commit's diff. Every row fits widths 1 to 80 side by side too, and wide characters keep the bar in line.
  • pull_requests.rs: a row side by side slid sideways, with wide characters cut at either edge of each side, styles kept and blank sides. Both sides scrolling together on a page, the clamp at the side that runs on furthest, and stacking again scrolling back.
  • On 2403b06, fmt, clippy and all 897 tests pass (816 lib, 2 main, 31 CLI, 48 RPC). The Code recipe passes on 2403b06's build and fails on Stop the Code tab's lines wrapping, and scroll them sideways #76's (ef9e2ca) at recipe line 24, the first wait for the ◫ Split diff view row. 3064610 changes only the Code recipe, which passes with it on 2403b06's build.
  • On f78d5f7, fmt, clippy and all 900 tests pass (819 lib, 2 main, 31 CLI, 48 RPC), and the Code recipe passes on its build.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no actionable new issues remain.

Summary

Adds a Code-tab row for switching between stacked and split diffs.

  • The Code tab can show old and new diff lines side by side.

Reviewed the full PR because the previous and current heads have different merge bases with the supplied target. No runtime tests or terminal captures were run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Toggle[Choose split or stacked] --> Clear[Clear cached file rows]
  Clear --> Layout{File layout}
  Layout -->|Added or deleted file| One[One column]
  Layout -->|Split with enough room| Pair[Pair old and new lines]
  Layout -->|Stacked or too narrow| Stack[Stack lines]
  Pair --> Threads[Place threads below their rows]
  One --> Threads
  Stack --> Threads
  Threads --> Page[Draw visible rows]
  Page --> Scroll[Scroll both sides together]
Loading

Reviews (8) · Last reviewed commit: "Merge the wrap branch at 044993f, which ..." · Reviewed by Greptile

krishhgg and others added 3 commits October 15, 2026 08:48
`◫ Split diff view` sits between the fold row and the wrap row, as the desktop's toolbar
orders its toggles, and reads `⊟ Stacked diff view` once the lines show side by side.

Side by side, each line in context shows on both sides with its number on each, and each
run of lines removed and added pairs them by position, as @pierre/diffs 1.5.2 pairs them.
The shorter side stays blank, and a row is as tall as its taller side. A file added or
deleted keeps one column. The note that a line has no end goes under the hunk's last row
on its own side. Review threads show across both sides under the row with their line, the
left side's first.

Unwrapped, both sides' text scrolls by the same columns, each cut at the end of its side,
and the widest row counts the side whose text runs on furthest. Below 5 columns the lines
stack. The choice stays through a read again and another diff picked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
On the fixture's diff, the right side's two-digit numbers touched the bar, while the left
side's stand a space from the details' edge. The bar and a space now take two columns, so
the lines stack below 6 columns rather than 5.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s that can't fail

The note after a line in context shows on both sides and after a line added on the
right, and at an odd width the right side takes the spare column. Slides keep their
halves once per file, since every run in a file shares them, and the left side's
number filter and the wrap guard on its padding go, as neither changed a row.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@krishhgg
krishhgg marked this pull request as ready for review October 15, 2026 16:10
Comment thread src/tui/pull_requests/code.rs
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lines shown around a hunk count on the left from where they were before
the change. Five lines removed at the top put new line 5 at old line 10,
so the left side's numbers need two columns where the hunks need one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krishhgg added a commit that referenced this pull request Oct 17, 2026
The new test counts rows from the one after the file's header, which sits
a row lower here under the tree's row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krishhgg and others added 4 commits October 17, 2026 14:05
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fter a theme change

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cipe

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… toolbar rows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread src/tui/pull_requests/code.rs
krishhgg and others added 7 commits October 18, 2026 01:32
…nd the fixes and recipes under it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… recipe

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The recipe now counts four toolbar rows, drives the split view at
100x30 (pairs, blank sides, both sides scrolling sideways, an added
file in one column) and checks the choice through a read again, a
commit picked and another link. The viewed-marks steps press r at the
end of the files, since a read of the first slice drops the later
ones and Home after r is too far from the end once the layout row
pushes the files down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t at the highest line number

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e boundary unfold test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ore the whitespace steps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krishhgg added a commit that referenced this pull request Oct 18, 2026
The trip that reads no marks has to come back within 15 s of their
first read. The whitespace steps sat inside that span, and on a macOS
runner on CI the trip came back after 19 s, so t3term read the marks
again and the recipe failed at its check on #76, #77 and #79. The trip
now comes right after the second slice, as on #73 and #74, and a
gotcha keeps later steps out of the span.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krishhgg and others added 2 commits October 18, 2026 06:04
…ile the file's text is read, tests that no hunk is read once the whitespace steps run out and brings #68's fix that lays review threads out again when the theme changes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… out again when the theme changes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@krishhgg

Copy link
Copy Markdown
Owner Author

PASS+NOTES for head f78d5f703875b8c27d7c11b49f5353eceb1bd578, patch id c8b54bc16314d39cbb9df4f46340ce813bb390b5.
Verifier: GPT-6.1 Sol (xhigh), not the author. Base 044993f15bfd829e0da8e28444418027cf87693a. Scenario links, 100x30 and 80x24, truecolor. This verdict covers this layer against the requested parent head.

Claim Base Head
The layout row switches stacked lines to split lines No split row; lines remain stacked Enter and a click switch layouts; pairs, blank sides and taller wrapped rows show at 100x30 and 80x24; refresh and picked commits preserve the choice; another link starts stacked
Threads span both sides; both sides scroll together unwrapped; added files keep one column Threads appear under stacked lines Hand-driven with resolved and open threads at both sizes, wrapping off and an added file; captures show fixed numbers, cards and divider while both texts scroll
Pairing agrees with Pierre 1.5.2 subject to the declared unequal-run limit Stacked view Ran Pierre's actual split renderer on all recipe files and the test's 3-removed/2-added hunk; the latter pairs 10/10, 11/11, then 12/blank, with the no-newline note on the left
Expanded old line numbers reserve enough space Scratch head with only the old-number sizing chain removed fails its regression test Test passes; old line 10 beside new line 5 is aligned; all 819 library tests pass

manual-head-100-r3/ and manual-head-80-r5/ hold the thread, wrapping and added-file drives. I inspected their rendered PNGs. pierre-render.json comes from DiffHunksRenderer.asyncRender in the downloaded @pierre/diffs 1.5.2 package; pierre-pairs.json records the renderer's iteration. test-side-fixed.log, test-numbers-reverted.log and tests-lib.log record the number-column control and the 819 passing library tests. The below-six-column fallback and no-newline variants pass in those tests. A one-row Summary difference in the broad sweep disappears in summary-control-base/page.txt versus summary-control-head/page.txt after waiting for the conversation read and pressing Home before PageDown.

Regression sweep: 13 of 13 own-checkout recipes pass on each side. Base evidence /tmp/t3v-verdict/76/smoke-head; head evidence /tmp/t3v-verdict/77/smoke-head. The identical parent-head build and recipe run are reused as the next layer's base. The changed source files reach Code layout, review comments, details input and the status line; the sweep drives all mapped features. Matched link-list, Summary and Timeline captures are identical. Thread details differ only by the fake server's port. Other capture differences are elapsed ages, spinner phases, generated run paths, the reconnect attempt's current error, and a Summary capture before versus after the three-second conversation reply fills its reviewers. matched-comparison.json and sweep-capture-comparison.json retain the comparisons.

Rules: doctor and check pass in the focused drives and before and after stop in the sweeps. Matched steps send the same rpcRequestsByTag: one each of subscribeServerConfig, orchestration.subscribeShell, orchestration.subscribeThread, pullRequests.subscribeRefreshes, pullRequests.detail, pullRequests.activity, pullRequests.stack and pullRequests.filesViewed. Both read the same two HTTP diff slices. The matched drive adds no RPC cost; the feature recipes and unit tests also check that toggles read nothing.

CI: all four checks pass on this exact head, including macOS and E2E smoke. Greptile: 2 threads, both resolved; the feature map and expanded old-number finding are addressed; no new unanswered finding. The head updates .claude/skills/verify-t3term/features/pull-request-code.md.

Binary provenance: base /tmp/t3v-bin/044993f15bfd829e0da8e28444418027cf87693a/t3term, LC_UUID 3928E993-ADD1-3443-9128-C8EEE9D4B8F4; head /tmp/t3v-bin/f78d5f703875b8c27d7c11b49f5353eceb1bd578/t3term, LC_UUID 564057C5-F085-38F0-833E-3E0AFB0A52E8. The base cache was reused; each newly built head logged Compiling t3term. The builds use t3v from master c250a7510b9d6ee71b635fd8ea6f9fa793f72fbe.

Notes: master's current sweep is 11 of 13 on both sides, at /tmp/t3v-verdict/76/master-smoke-head and /tmp/t3v-verdict/77/master-smoke-head. Its CLI recipe at .claude/skills/verify-t3term/features/cli.md:32 asks these older pinned builds for the later launch command. Its Code recipe at .claude/skills/verify-t3term/features/pull-request-code.md:39 expects the pre-stack count and loading layout, before the viewed count and toolbar rows. Both fail on base as well as head. The updated recipes in this stack pass; these shared master-recipe incompatibilities are not a regression in this layer. A merge with newer master still needs the integration recheck from the skill.

The declared pairing limit is confirmed at src/tui/pull_requests/code.rs:1957: t3term pairs reader.rs old line 32 with new line 33, while Pierre moves the blank left side to new line 33 and pairs old 32 with new 34. This is the unequal-run realignment limit already named in the PR and documentation, so it is a note, not a new blocker. Threads spanning the full width and blank rather than striped sides also match the declared limits.

No new blocking findings. Evidence stays under the paths above. All owned runs were stopped and checked; no branch or PR code was changed.

@krishhgg
krishhgg changed the base branch from t3term/pull-request-wrap to master October 18, 2026 20:02
@krishhgg
krishhgg merged commit 748c6b8 into master Oct 18, 2026
4 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.

1 participant