Found during the 2026-07-25 regression run (RT-12a). See docs/regression-report-2026-07-25.md.
Summary
DiffCodeViewer classifies lines purely from the diff library's positional added/removed
flags, so left is always red and right is always green regardless of which commit is newer.
When the newer commit is placed on the left, its unique lines render as red deletions and the
older commit's unique lines render as green additions.
Relationship to #196
#196 described exactly this inversion and was closed as completed by PR #201. PR #201 added
temporal awareness and affordances — referenceIsNewer / temporalOrderKnown in
useBrowseState.ts, older/newer chips on the panel headers, and a "Swap panels (put older on
left)" button — but it did not change the coloring. frontend/src/pages/Browse.tsx:604 passes
only leftContent / rightContent to <DiffCodeViewer>; no temporal props reach the component,
and DiffCodeViewer.tsx (lines ~58-88, computeSideBySideDiff, and getDiffBgColor ~503) still
derives add/remove entirely from position.
So the mitigation works — the user can see which side is which and can swap — but the underlying
colour semantics from #196 still reproduce.
Reproduction
File src/inxr2/adapters/external/treesitter/php_parser.py in the inxr2 test repo.
newer = 7f548aa2856220e8d163ca4065c01ae8a833b896 (2026-07-19 20:16 UTC)
older = ff935edf1867a52b9d58bb6660d253540de031a1 (2026-07-19 16:12 UTC)
git diff --numstat ff935edf 7f548aa -- <file>
138 47
Going older → newer: 138 added, 47 removed.
# Case A - older on the left (default orientation)
/browse/inxr2/<file>?commit=7f548aa...&branch=main&diff=ff935edf...
# Case B - newer on the left (commit/diff swapped)
/browse/inxr2/<file>?commit=ff935edf...&branch=main&diff=7f548aa...
Counting row background colours via getComputedStyle:
| Case |
Left panel |
Chips shown |
Green rgba(80,161,79,.14) |
Red rgba(228,86,73,.14) |
| A - older on left |
ff935ed |
newer / older |
138 |
47 |
| B - newer on left |
7f548aa |
newer / older |
47 |
138 |
In Case B the gutter markers agree with the colours (+ appears on the older side).
Expected
The 138 lines that exist only in the newer commit should be green additions in both
orientations; the 47 older-only lines should be red. This is the criterion RT-12a in
docs/regression-tests.md asserts: "Colors are correct regardless of which side (left/right)
each commit appears on."
Notes on severity / scope
Not critical. The default orientation the UI produces is Case A, which is correct, and the
older/newer chips plus the swap button mean a user is not left without a signal. But a reader
who lands on a swapped diff sees additions labelled as deletions.
Worth deciding explicitly whether the intended contract is:
Affected files
frontend/src/components/DiffCodeViewer/DiffCodeViewer.tsx - computeSideBySideDiff(), getDiffBgColor()
frontend/src/pages/Browse.tsx:604 - does not forward temporal context
frontend/src/hooks/useBrowseState.ts:112-145 - computes referenceIsNewer / temporalOrderKnown (used for chips only)
Found during the 2026-07-25 regression run (RT-12a). See
docs/regression-report-2026-07-25.md.Summary
DiffCodeViewerclassifies lines purely from the diff library's positionaladded/removedflags, so left is always red and right is always green regardless of which commit is newer.
When the newer commit is placed on the left, its unique lines render as red deletions and the
older commit's unique lines render as green additions.
Relationship to #196
#196 described exactly this inversion and was closed as completed by PR #201. PR #201 added
temporal awareness and affordances —
referenceIsNewer/temporalOrderKnowninuseBrowseState.ts,older/newerchips on the panel headers, and a "Swap panels (put older onleft)" button — but it did not change the coloring.
frontend/src/pages/Browse.tsx:604passesonly
leftContent/rightContentto<DiffCodeViewer>; no temporal props reach the component,and
DiffCodeViewer.tsx(lines ~58-88,computeSideBySideDiff, andgetDiffBgColor~503) stillderives add/remove entirely from position.
So the mitigation works — the user can see which side is which and can swap — but the underlying
colour semantics from #196 still reproduce.
Reproduction
File
src/inxr2/adapters/external/treesitter/php_parser.pyin theinxr2test repo.Going older → newer: 138 added, 47 removed.
Counting row background colours via
getComputedStyle:rgba(80,161,79,.14)rgba(228,86,73,.14)ff935ed7f548aaIn Case B the gutter markers agree with the colours (
+appears on the older side).Expected
The 138 lines that exist only in the newer commit should be green additions in both
orientations; the 47 older-only lines should be red. This is the criterion RT-12a in
docs/regression-tests.mdasserts: "Colors are correct regardless of which side (left/right)each commit appears on."
Notes on severity / scope
Not critical. The default orientation the UI produces is Case A, which is correct, and the
older/newerchips plus the swap button mean a user is not left without a signal. But a readerwho lands on a swapped diff sees additions labelled as deletions.
Worth deciding explicitly whether the intended contract is:
added/removedwhenreferenceIsNewer, i.e. option A/C from Diff viewer colors are reversed when left commit is newer than right commit #196), orgit diffsemantics, relying on the chips) — in which case RT-12a indocs/regression-tests.mdshould be rewritten to match, since it currently asserts temporal.Affected files
frontend/src/components/DiffCodeViewer/DiffCodeViewer.tsx-computeSideBySideDiff(),getDiffBgColor()frontend/src/pages/Browse.tsx:604- does not forward temporal contextfrontend/src/hooks/useBrowseState.ts:112-145- computesreferenceIsNewer/temporalOrderKnown(used for chips only)