TUI is read-only apart from creating an issue: no comment, review, or close #74

Closed
opened 2026-08-12 16:57:16 +00:00 by a73x · 1 comment
a73x commented 2026-08-12 16:57:16 +00:00 (Migrated from git.a73x.sh)

The dashboard writes exactly one kind of event. n opens an issue (title, then body) via issue::open. Grepping src/tui/ for calls into crate::issue::* / crate::patch::* returns that one path and nothing else.

Missing: comment, review, close, reopen, label, assign, revise, merge, resolve/unresolve, edit or delete a comment. Everything the CLI grew this cycle.

So the dashboard is a browser with one write button — and arguably the wrong one, if only one were to exist. You can read a patch, walk its revisions, view diffs and interdiffs, read every review comment, and then you must quit to say anything about what you just read. For a tool whose thesis is that review should preserve the correspondence between feedback and the change answering it, the review surface cannot leave a comment.

Two things to decide rather than assume:

  • How much of the CLI belongs here. Not all of it. patch merge and revise are tied to the working tree and arguably do not belong in a browser. Commenting, reviewing, resolving and closing are the review loop and clearly do.
  • How text gets in. The existing n flow is a hand-rolled single-line buffer with no editing beyond backspace. Bodies are markdown and often long. 6edf0fa2 settled this for the CLI — -F, stdin, and $EDITOR — and the TUI should suspend to $EDITOR the same way rather than growing a second, worse text input.

Related: o is not a collab action at all — it leaves the TUI and runs git checkout on PatchState.branch. Since 659f0350 that field is provenance only and is full of dead worktree branch names (850f3b8e), so on agent-produced patches that key mostly fails. Worth revisiting alongside this, since it should check out the latest revision's commit, which is pinned by a revision ref and always resolves.

Found while reviewing what the TUI can do (5c62b43b).


Migrated from git-collab issue 094b055b2ae57b5f9b0992b9aa6aeedf5bb137b7.

Original author: a73x dev@a73x.sh.

Close reason: merged in patch 07a78a60

The dashboard writes exactly one kind of event. `n` opens an issue (title, then body) via `issue::open`. Grepping `src/tui/` for calls into `crate::issue::*` / `crate::patch::*` returns that one path and nothing else. Missing: comment, review, close, reopen, label, assign, revise, merge, resolve/unresolve, edit or delete a comment. Everything the CLI grew this cycle. So the dashboard is a browser with one write button — and arguably the wrong one, if only one were to exist. You can read a patch, walk its revisions, view diffs and interdiffs, read every review comment, and then you must quit to say anything about what you just read. For a tool whose thesis is that review should preserve the correspondence between feedback and the change answering it, the review surface cannot leave a comment. Two things to decide rather than assume: - **How much of the CLI belongs here.** Not all of it. `patch merge` and `revise` are tied to the working tree and arguably do not belong in a browser. Commenting, reviewing, resolving and closing are the review loop and clearly do. - **How text gets in.** The existing `n` flow is a hand-rolled single-line buffer with no editing beyond backspace. Bodies are markdown and often long. 6edf0fa2 settled this for the CLI — `-F`, stdin, and `$EDITOR` — and the TUI should suspend to `$EDITOR` the same way rather than growing a second, worse text input. Related: `o` is not a collab action at all — it leaves the TUI and runs `git checkout` on `PatchState.branch`. Since 659f0350 that field is provenance only and is full of dead worktree branch names (850f3b8e), so on agent-produced patches that key mostly fails. Worth revisiting alongside this, since it should check out the latest revision's commit, which is pinned by a revision ref and always resolves. Found while reviewing what the TUI can do (5c62b43b). --- Migrated from git-collab issue `094b055b2ae57b5f9b0992b9aa6aeedf5bb137b7`. Original author: a73x <dev@a73x.sh>. Close reason: merged in patch 07a78a60
a73x commented 2026-08-12 17:20:36 +00:00 (Migrated from git.a73x.sh)

Refined 2026-08-12. Decisions made; this is now buildable.

Purpose: the TUI is a review surface. The place you read a patch and respond to it, closing the loop you already walk (revisions, diffs, interdiffs) so you never leave to say what you think. Not a triage tool, not a monitor.

In scope — the review loop, all of which anchor to something already on screen:

  • c comment on the selected diff line (inline) or on the patch (thread)
  • R review with a verdict: approve / request-changes / comment
  • x resolve / unresolve the selected comment
  • a show what answered the selected comment (--answers, already built)

Out of scope, deliberately: merge and revise are tied to the working tree and do not belong in a browser; label/assign/close are triage, which is a different product decision. n (new issue) stays — it exists, people have the muscle memory, and it now gets the editor treatment below.

Text input: suspend to $EDITOR, exactly as git commit does. Leave the alternate screen, edit a temp file, return, submit. No second text editor gets written; 6edf0fa2 already set this convention for the CLI and the two surfaces should agree.

Pre-fill the buffer with context, so suspending does not cost you the thing you are writing about:

# Commenting on src/merge_scan.rs:305
# Lines starting with # are ignored.

<cursor>

# --- the hunk you're commenting on ---
#  if let Ok(bound) = repo.merge_base_many(&bases) {
#      let _ = revwalk.hide(bound);
#  }

Details that will otherwise be guessed:

  • An empty body after stripping # lines aborts the write, like git commit. Say so on return.
  • No $EDITOR/$VISUAL set is a status message naming the alternatives, never a hang and never a silent no-op.
  • The terminal dance already has a precedent in this file: the o key leaves raw mode and the alternate screen to run git checkout. Follow it, and restore the screen even if the editor exits non-zero or is killed.
  • Inline anchoring must go through the same validation as the CLI (fe555587): the file and line are checked against the revision the comment anchors to, not the working tree. 9a0a143b added --at file:line; reuse that path rather than building a second one.
  • x needs comment identity. resolve_comment resolves an OID prefix and patch show prints ids in brackets; surface the same id in the TUI so the two agree.
  • After any write, reload — and that reload must not make the staleness banner in 59ab40e8 announce your own change as external.

Related, fix while here: o runs git checkout on PatchState.branch, provenance-only since 659f0350 and mostly dead names on agent patches (850f3b8e). It should check out the latest revision's commit, which is pinned by a revision ref and always resolves.

**Refined 2026-08-12. Decisions made; this is now buildable.** **Purpose: the TUI is a review surface.** The place you read a patch and respond to it, closing the loop you already walk (revisions, diffs, interdiffs) so you never leave to say what you think. Not a triage tool, not a monitor. **In scope** — the review loop, all of which anchor to something already on screen: - `c` comment on the selected diff line (inline) or on the patch (thread) - `R` review with a verdict: approve / request-changes / comment - `x` resolve / unresolve the selected comment - `a` show what answered the selected comment (`--answers`, already built) **Out of scope, deliberately:** `merge` and `revise` are tied to the working tree and do not belong in a browser; `label`/`assign`/`close` are triage, which is a different product decision. `n` (new issue) stays — it exists, people have the muscle memory, and it now gets the editor treatment below. **Text input: suspend to $EDITOR**, exactly as `git commit` does. Leave the alternate screen, edit a temp file, return, submit. No second text editor gets written; `6edf0fa2` already set this convention for the CLI and the two surfaces should agree. Pre-fill the buffer with context, so suspending does not cost you the thing you are writing about: ``` # Commenting on src/merge_scan.rs:305 # Lines starting with # are ignored. <cursor> # --- the hunk you're commenting on --- # if let Ok(bound) = repo.merge_base_many(&bases) { # let _ = revwalk.hide(bound); # } ``` Details that will otherwise be guessed: - An empty body after stripping `#` lines **aborts** the write, like `git commit`. Say so on return. - No `$EDITOR`/`$VISUAL` set is a status message naming the alternatives, never a hang and never a silent no-op. - The terminal dance already has a precedent in this file: the `o` key leaves raw mode and the alternate screen to run `git checkout`. Follow it, and restore the screen even if the editor exits non-zero or is killed. - Inline anchoring must go through the same validation as the CLI (fe555587): the file and line are checked against the **revision the comment anchors to**, not the working tree. `9a0a143b` added `--at file:line`; reuse that path rather than building a second one. - `x` needs comment identity. `resolve_comment` resolves an OID prefix and `patch show` prints ids in brackets; surface the same id in the TUI so the two agree. - After any write, reload — and that reload must not make the staleness banner in 59ab40e8 announce your own change as external. **Related, fix while here:** `o` runs `git checkout` on `PatchState.branch`, provenance-only since `659f0350` and mostly dead names on agent patches (850f3b8e). It should check out the latest revision's commit, which is pinned by a revision ref and always resolves.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
a73x/git-collab#74
No description provided.