feat: add interactive review TUI for feedback triage#153
Conversation
| */ | ||
|
|
||
| import { createInterface } from "readline"; | ||
| import type { Feedback } from "./types.js"; |
There was a problem hiding this comment.
these imports are never used — checkGhAuth and createGithubIssue are injected via ReviewDeps and the direct imports from ./github.js are dead code
| rl.question( | ||
| `\nNew title (empty to clear, Ctrl-C to cancel): [${current ?? ""}] `, | ||
| (answer) => { | ||
| rl.close(); |
There was a problem hiding this comment.
promptTitle is never called. the e key handler re-implements its own inline readline prompt. either delete this function or use it in the handler
| if (key === "p" || key === "P") { | ||
| if (!deps.checkAuth()) { | ||
| statusLine = `${RED}gh CLI not authenticated. Run 'gh auth login' first.${RESET}`; | ||
| renderCurrent(); |
There was a problem hiding this comment.
bug: after splicing the last item, feedbacks is empty so feedbacks[0] is undefined and you fall back to current. but the card header will show "1 / 0" because total is feedbacks.length (0) and index + 1 is 1. just skip the render entirely here — you already have the status line and are about to call cleanup()
| feedback: Feedback, | ||
| index: number, | ||
| total: number, | ||
| statusLine: string, |
There was a problem hiding this comment.
pendingPublish is always passed as false and never read inside the function. drop the parameter
src/review.ts
Outdated
| process.stdout.write("\x1b[2J\x1b[H"); | ||
| } | ||
|
|
||
| function moveTo(row: number, col: number): void { |
There was a problem hiding this comment.
moveTo is defined but never called. dead code, just remove it
| const voteRows = await outerDb.prepare( | ||
| "SELECT session_id, evidence, estimated_tokens_saved, estimated_time_saved_minutes, created_at FROM vote_log WHERE feedback_id = ?" | ||
| ).all(feedback.id) as any[]; | ||
|
|
There was a problem hiding this comment.
if the DB update here throws, the GitHub issue is already created but the feedback stays open in the DB. user would end up publishing a duplicate on next attempt. worth wrapping this in a try/catch and at least logging the URL if the update fails, so it's not silently lost
Adds `suggestion-box review` — a card-by-card terminal UI for triaging open feedback. Keyboard shortcuts: p — publish to GitHub (requires github_repo on entry) e — edit title inline d — dismiss s — skip to next q — quit (left arrow goes back) The TUI renders each feedback card with ANSI colours, category badges, vote counts, and wrapped content. Implemented in src/review.ts using raw stdin keypress handling and terminal escape codes — no new dependencies. Closes #92
- Remove dead imports (checkGhAuth, createGithubIssue) from review.ts - Remove unused moveTo function and ESC constant - Drop unused pendingPublish parameter from renderCard - Deduplicate inline readline logic in 'e' handler by calling promptTitle - Fix "1 / 0" header bug when publishing the last item — skip render entirely - Wrap post-publish DB update in try/catch in both publish command and review TUI so a failed DB update after a successful GitHub issue creation logs the URL rather than silently losing it
The close event fired synchronously when rl.close() was called inside the question callback, causing resolve(null) from the close handler to settle the Promise before resolve(answer) ran — so typed titles were always discarded. Drop the close event handler and resolve entirely in the question callback. On Ctrl-C readline calls the callback with an empty string, which is coerced to null via `answer || null`.
0256ed6 to
d3a34f3
Compare
Adds
suggestion-box review— a card-by-card TUI for going through open feedback without leaving the terminal.Keyboard shortcuts:
ppublish to GitHubeedit title inlineddismisssskipqquit←go backCategories get colors (friction=red, feature_request=blue, observation=yellow). Content wraps to terminal width with an overflow indicator when it doesn't fit. All built on raw stdin keypress handling and ANSI escape codes, so no new deps.
Publishing requires a
github_repoon the feedback entry. If it's missing, you get a clear error instead of a silent failure.Closes #92