fix: unblock CI (README formatting, note-geometry scroll clamp, test config isolation)#506
Conversation
Note rows previously rendered only for files near the viewport, a set that decays with rapid-scroll state on a timer, while file overscan and prefetch keep sections mounted beyond it. A mounted section that skipped its notes painted shorter than its note-inclusive layout height, transiently shrinking the scrollbox content height so bottom-edge over-scrolls clamped short. This was the intermittent Windows CI failure in 'DiffPane keeps bottom scroll stable when offscreen agent notes are windowed out'; the regression test now waits out the overscan decay window, which reproduced the failure deterministically on every platform. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extends the #494 PTY-harness isolation to test/session/ and test/smoke/, which still inherited the developer's real ~/.config/hunk/config.toml and failed locally whenever it changed defaults like agent_notes or line_numbers. CI was unaffected (runners have no user config). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile SummaryThis PR unblocks CI with three targeted fixes: a README blank-line to satisfy the
Confidence Score: 4/5Safe to merge; all three changes address well-understood, reproducible CI failures with no new logic paths that could regress the rest of the diff view. The DiffPane refactor is sound — selectedFileId is already folded into mountedFileIndices via buildFileRenderWindow, and showAgentNotes propagates correctly through allAgentNotesByFile. The only loose end is that testConfigHome temp dirs are created at module load and never removed; they are empty and harmless, but the pattern differs from the tempDirs cleanup already present in the same files. The four test files that call createTestConfigHome() at module level (broker-e2e.test.ts, cli.test.ts, daemon.test.ts, tty.test.ts) and the helper itself — each accumulates one unreleased temp dir per run. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[allAgentNotesByFile\nfull note set per file] --> B[sectionGeometry\nmeasured with full notes]
B --> C[fileSectionLayouts\nlayout heights]
C --> D[fileRenderWindow\nmountedFileIndices]
D --> E{windowing\nenabled?}
E -- yes --> F[mountedFileIndices\nfrom render window\nincludes selectedFileId\n+ overscan + prefetch]
E -- no --> G[all file indices]
F --> H[visibleAgentNotesByFile\nnotes for exactly\nmounted sections]
G --> H
A --> H
H --> I[DiffSection render\nnote rows match\nlayout height]
I --> J[scrollbox content height\nstable — no clamp]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[allAgentNotesByFile\nfull note set per file] --> B[sectionGeometry\nmeasured with full notes]
B --> C[fileSectionLayouts\nlayout heights]
C --> D[fileRenderWindow\nmountedFileIndices]
D --> E{windowing\nenabled?}
E -- yes --> F[mountedFileIndices\nfrom render window\nincludes selectedFileId\n+ overscan + prefetch]
E -- no --> G[all file indices]
F --> H[visibleAgentNotesByFile\nnotes for exactly\nmounted sections]
G --> H
A --> H
H --> I[DiffSection render\nnote rows match\nlayout height]
I --> J[scrollbox content height\nstable — no clamp]
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
test/helpers/config-home.ts:10-12
**Temp dir created at module load but never cleaned up**
`createTestConfigHome()` is called at the module level in every test file and the resulting directory is never removed — it's not tracked in the `tempDirs` arrays that get cleaned up in `afterEach`. Each test run leaves one extra empty directory per file in the OS temp dir. Because each call is at the top level rather than inside a `beforeAll`, there's no natural hook to delete it. An `afterAll(() => rmSync(testConfigHome, { recursive: true, force: true }))` in each consumer would seal the leak.
Reviews (1): Last reviewed commit: "test: isolate session and tty-smoke test..." | Re-trigger Greptile |
| export function createTestConfigHome(prefix = "hunk-test-config-") { | ||
| return mkdtempSync(join(tmpdir(), prefix)); | ||
| } |
There was a problem hiding this comment.
Temp dir created at module load but never cleaned up
createTestConfigHome() is called at the module level in every test file and the resulting directory is never removed — it's not tracked in the tempDirs arrays that get cleaned up in afterEach. Each test run leaves one extra empty directory per file in the OS temp dir. Because each call is at the top level rather than inside a beforeAll, there's no natural hook to delete it. An afterAll(() => rmSync(testConfigHome, { recursive: true, force: true })) in each consumer would seal the leak.
Prompt To Fix With AI
This is a comment left during a code review.
Path: test/helpers/config-home.ts
Line: 10-12
Comment:
**Temp dir created at module load but never cleaned up**
`createTestConfigHome()` is called at the module level in every test file and the resulting directory is never removed — it's not tracked in the `tempDirs` arrays that get cleaned up in `afterEach`. Each test run leaves one extra empty directory per file in the OS temp dir. Because each call is at the top level rather than inside a `beforeAll`, there's no natural hook to delete it. An `afterAll(() => rmSync(testConfigHome, { recursive: true, force: true }))` in each consumer would seal the leak.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Fixed in #509. Went with the afterAll-per-consumer shape you suggested — a central sweep was tried first, but Bun's test runner never emits process.on("exit") (verified with a probe), so the helper now exports cleanupTestConfigHomes() and each of the four consumers registers it via afterAll. Verified /tmp stays clean across the session and tty-smoke suites.
Responded by Claude Code using claude-fable-5.
What
Three fixes that unblock CI and local test runs:
README formatting — the Homebrew note from Update hunk installation instructions in README #497/Recommend installation from the main homebrew tap #498 was missing a blank line after the install code fence, so
oxfmt --checkhas been failing on main and short-circuiting the Typecheck + Test steps on every PR since 2026-07-02.Flaky Windows test root-caused and fixed —
DiffPane keeps bottom scroll stable when offscreen agent notes are windowed outfailed intermittently on Windows (chore(deps): bump the github-actions group with 3 updates #501, fix: quit only on q shortcut #505 runs) withExpected: 48, Received: 40. Not a Windows quirk: note rows rendered only for files near the viewport, a set that decays with rapid-scroll state on a 160ms timer, while file overscan and prefetch keep sections mounted beyond it. A mounted section that skipped its notes painted 8 rows shorter than its note-inclusive layout height, transiently shrinking the scrollbox content height so a bottom-edge over-scroll clamped short. Fix: render note rows for exactly the mounted set — the same set the spacer math assumes — and delete the now-dead viewport-proximity set and its base-layout chain. The regression test waits out the overscan decay window, which reproduced the CI failure deterministically on Linux too.Test isolation — extends the test(pty): isolate integration tests from ambient user config #494 PTY-harness ambient-config isolation to
test/session/andtest/smoke/, which still inherited the developer's real~/.config/hunk/config.tomland failed locally whenever it changed defaults (agent_notes,line_numbers,hunk_headers). CI was unaffected.Testing
bun run typecheck,bun test(full suite),bun run test:integration(51/51),bun run test:tty-smoke(9/9, now green with a customized user config present),bun run format:check,bun run lint.48 vs 40failure as Windows CI) and pass with it.🤖 Generated with Claude Code