Skip to content

Final pass: bug fixes, black-box tests, stdlib cleanup, and docs - #11

Merged
rednafi merged 119 commits into
herdr-parityfrom
final-pass
Oct 26, 2026
Merged

rednafi merged 119 commits into
herdr-parityfrom
final-pass

Conversation

@rednafi

@rednafi rednafi commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Stacked on #10.

  • Fixes found by the new black-box tests and a real Rex run: the first frame used a guessed size, a cold code search showed no match, a hung clipboard tool froze the UI, git got a stale PWD, git cat-file errors had no message, and rexdiff install said it added the require line when it was already there.
  • Tests: the libraries are tested only through their public API. tui has no tests. test/ runs the real binary in a terminal, as a user does, with a fake rex that replays recorded Rex output. TestRealRex checks that fake against a real Rex.
  • Code: stdlib cleanups for Go 1.27, a smaller API (rex.ReloadConfig returns only an error), strict golangci-lint, govulncheck, and Dependabot.
  • Docs: the guides move to .doc/, with screenshots in .asset/. test.md explains the tests.

relist also lists the untracked directories with --directory and walks
the directories below them that git does not ignore. A new file in an
empty untracked directory, or in one with only ignored files, is then a
change. Files and the watcher share the ls-files arguments.
compress and loneFile stop at a directory that git lists as one path.
An expanded ignored directory with one child then keeps its row, and
the user can collapse it.
The relist runs two git processes, so a check after a change can take
longer than the first check. TestPRBranchSwitch then missed the switch
in about one run of 16.
- Branches hides the HEAD of each remote. It filters by the full ref
  name, then shortens.
- PullRequest selects the forge by the host of the remote URL, in the
  URL and the scp forms. A host override matches the host only.
  GitLab is gitlab.com or the gitlab host, as in herdr-reviewr.
- copyIndex returns a stat error other than a missing index.
- ForkPoint wraps the error of git merge-base.
ErrNoPullRequest names what is not found. MergeBaseCommit runs git
merge-base, and MergeBase returns its tree.
Agent.Status is a field, as Event.Status is. The fields of Status do
not show as fields of Agent.
Watch sends an Event with Reconnect when it starts rex events again.
tui then calls Tracker.Gap, forgets the agents, and lists them again,
as herdr-reviewr does after a lost connection.

turn exports only Tracker: Observe takes the states of the agents, and
the fold and its states are internal.
Snapshot, Watcher, Owns, ReadFile, SavedBase, SavedTurn, and Contains
tell what they do and return. The rex states name no consumer. Install
tells why it ignores a cancel. editor.Program and search.CodeLimit have
plain docs.
encoding/json/v2 rejects invalid UTF-8, so a comment on a Latin-1 line
or path broke the resume file. Such bytes become U+FFFD.
A cluster of several code points, for example an emoji with a joiner or
a flag, takes one width on the screen. Cell counted the width of each
rune, so it gave the wrong rune after such a cluster.
A sideways scroll that starts inside a wide character kept or dropped
the whole character, so Cell was one cell off. CutLeft puts a space in
place of the cut character, in Render and in RenderFile.
A state file of v0.2.7 has no anchors, so its comments loaded on the
working tree diff. A comment in the commits scope then never showed.
SetOldRev gives them the revision of the saved scope.
The flag package stops at the first argument that is not a flag, so
flags after the repo and extra arguments were ignored.
The smart case match of the find band belongs with the search, not
with the diff API.
RenderFile styled each line number. It formats the number in a styled
format, and counts the lines without a slice. BenchmarkRenderFile of
4000 lines goes from 5.2 ms and 31800 allocations to 2.5 ms and 14800.
A tick does not reload while the comment box is open. The reload runs
when the box closes. A failed reload of the Changes tab keeps the files,
the selection, and the cursor, and flashes the error. The error shows in
place of the files only if nothing loaded. A failed read of the pull
request keeps the last good one, except when the branch has no pull
request.

Without a watcher, a tick reloads every 5 s. A failed start or an error
of the watcher starts it again on the retry backoff, as in
herdr-reviewr.
…stale

The end of a code search rebuilds the list only in the code mode, so
the cursor of the file matches stays. A click or a pick of a file drops
an armed crossing. A change of the scope clears the selection and the
arm. Tab shows a hidden file list with the focus, as in herdr-reviewr.
A click above the rows that show in an overlay picks no row.
The comment box takes the width of the main pane at each render and
when it opens. A release of the mouse and a key in the box scroll the
box into view. An edit from the comment list opens the box only if the
pane shows the line of the comment. Else it flashes.
Without file_list_width, the file list at a side takes 32% of the
width, as in herdr-reviewr. A body that leaves no row for a list above
or below shows no list, so the screen keeps its footer. The Files tab
keeps the path that it shows in its own field, so a tick does not
render Markdown again.
As in herdr-reviewr, Q does nothing outside the prompt before a quit,
so it cannot drop unsent comments. The check of the keybindings setting
includes the fixed key U of the upgrade. The README lists each key that
rexdiff binds, and the width that side by side needs.
As in herdr-reviewr, a code search stops after 80 ms. Grep returns the
matches that it finds before the deadline of its context, with more set,
so the chip shows a "+". A cancel is still an error.
tui checks the options and the settings with choice. The flag check in
cmd joins the names with strings.Join.
View finds the hits once and gives them to the footer and to the main
pane. The callers that need only the rows of the screen give no hits.
With a watcher, the Files tab reads the open file after the watcher
reports a change of the files, and no more on each tick. The watcher
also gets the open ignored file, as in herdr-reviewr, because git does
not list it. Without a watcher, each tick reads the file.
editor.Resolve picks the editor of the settings, $VISUAL, $EDITOR, or
core.editor, and returns the messages for the user. tui only runs the
command. Template and Program are not exported.
… with herdr-reviewr

- agent picker: a digit moves the cursor, and enter sends
- o opens only an http(s) URL, runs the opener as argv, and tells it
- url_opener must name a program first
- the old key names list-wider, list-narrower and preview work
- a copy failure shows herdr-reviewr's text, and logs the error
- the scope and picker keys do nothing on the PR tab
- e does nothing while a selection is active
- an edit keeps the ID and place of the comment
- -wrap takes on or off
- base picker: the PR base and the default branch first, with tags
- the wheel scrolls the view of the file list and the search preview
- PR comments show their age
@rednafi
rednafi merged commit b048eea into herdr-parity Oct 26, 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