Conversation
There was a problem hiding this comment.
Review: Approved
Clean, focused fix that addresses the scrollbar lingering issue at the right layer.
What is good:
- Correct approach: Fixing this in
EditorTextViewConfiguration.updateTextkeeps scroll behavior coupled with text updates, rather than scattering workarounds across tab-switching logic - Belt-and-suspenders reset: Using both
scrollRangeToVisibleandcontentView.scroll(to: .zero)plusreflectScrolledClipViewensures reliable reset across AppKit edge cases - Solid test: The regression test properly simulates the scenario (scroll to bottom, update text, verify reset)
Minor observations (no action required):
-
Unconditional reset: Every
updateTextcall now resets scroll position. This is fine because:- User keystrokes do not go through this method (NSTextView handles native editing)
- The early return guard (
textView.string != text) skips no-op updates - Resetting to top on tab switch is reasonable UX
-
Force-unwrap in test (
textView.textContainer!): Safe here sincemakeScrollViewalways creates a valid text container, but could use optional binding for consistency with the surrounding code style.
Good work keeping the fix minimal and testable.
There was a problem hiding this comment.
Review: Changes Requested
Critical Issue: Unrelated changes bundled in PR
This PR claims to "reset editor scroll state on tab changes" but bundles 19 unrelated files alongside the 2 files that actually implement the fix. The majority of changes are beads issue tracking infrastructure that have nothing to do with the scrollbar fix:
Files that belong in this PR (2):
Ghostly/Utilities/EditorTextViewConfiguration.swift- the actual fixGhostlyTests/EditorTextViewConfigurationTests.swift- the test
Files that should NOT be in this PR (20):
.beads/directory changes (README, metadata, hooks, backup files).beads/dolt-monitor.pid,.beads/dolt-server.activity,.beads/dolt-server.port- runtime files with machine-specific data (PIDs, ports, timestamps) that should NEVER be committed.gitignorechangesAGENTS.mdadditions
Why this matters:
- PRs should be atomic - one logical change per PR makes review easier and rollbacks cleaner
- Runtime files committed -
.beads/dolt-monitor.pid(contains79528),.beads/dolt-server.port(contains14049),.beads/dolt-server.activity(timestamp) are machine-specific and will conflict/be stale on other machines - Review confusion - the existing approval review completely missed these unrelated files
The actual code fix looks good
The resetScrollState implementation is correct:
@MainActor
private static func resetScrollState(for textView: NSTextView) {
guard let scrollView = textView.enclosingScrollView else { return }
textView.scrollRangeToVisible(NSRange(location: 0, length: 0))
scrollView.contentView.scroll(to: .zero)
scrollView.reflectScrolledClipView(scrollView.contentView)
}The test is also reasonable, though the final assertion is outside the if let block which could technically pass vacuously if textView were nil (though it won't be in practice).
Recommended action:
- Remove all
.beads/changes from this PR (especially the runtime files) - Remove
AGENTS.mdand.gitignorechanges - Create a separate PR for beads integration if that's desired
- Add
.beads/dolt-monitor.pid,.beads/dolt-server.activity,.beads/dolt-server.portto.gitignore- these should never be tracked
Once the unrelated files are removed, this PR can be approved.
There was a problem hiding this comment.
Review
Major Issue: Unrelated changes bundled
This PR bundles two completely unrelated changes:
- The actual scrollbar fix (good) -
EditorTextViewConfiguration.swiftand its test - Beads issue tracking initialization (unrelated) - all the
.beads/files,AGENTS.mdupdates,.gitignorechanges
These should be separate PRs. The beads setup is a significant addition to the repo that deserves its own review and commit history.
Runtime files committed
The following files should NOT be committed as they are runtime/ephemeral:
.beads/dolt-monitor.pid- process ID (machine-specific).beads/dolt-server.activity- timestamp.beads/dolt-server.port- port number (machine-specific).beads/backup/backup_state.json- contains timestamps specific to when backup ran
These will cause merge conflicts and contain stale data. They should be in .beads/.gitignore.
The scrollbar fix itself
The core fix is sound:
@MainActor
private static func resetScrollState(for textView: NSTextView) {
guard let scrollView = textView.enclosingScrollView else { return }
textView.scrollRangeToVisible(NSRange(location: 0, length: 0))
scrollView.contentView.scroll(to: .zero)
scrollView.reflectScrolledClipView(scrollView.contentView)
}- Correctly placed at the configuration layer
- Called when text content changes (appropriate trigger)
- Test covers the regression scenario
Minor note on test (line 76):
textView.layoutManager?.ensureLayout(for: textView.textContainer!)Force-unwrap of textContainer could be avoided with optional chaining since the test is already inside if let textView.
Recommendation
- Remove all
.beads/changes and beads-related updates from this PR - Remove the runtime files from the commit
- Create a separate PR for beads initialization if desired
The scrollbar fix alone is approvable once the unrelated changes are removed.
Summary
Testing