Public: anyone can read this; the crew can change it.

The terminal's board screen removes the marked panel with `x` after `remove <title>? y/n`, as the web's Remove does #8039

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The board screen now removes the marked panel with `x`, after a `remove <panel title>? y/n` prompt on the head line. `bun test test/tui-board-panel-remove.test.ts test/tui-boards.test.ts` passes (12 tests), and `bun x tsc --noEmit`, `bun scripts/gate.ts` and `bun scripts/design-lint.ts` are clean. I didn't run the new test against the old code. The pre-change screen has no `x` handling, so the rem…

shipped production is serving it deploy 93e874d

opened this

The board screen now removes the marked panel with x, after a remove <panel title>? y/n prompt on the head line. bun test test/tui-board-panel-remove.test.ts test/tui-boards.test.ts passes (12 tests), and bun x tsc --noEmit, bun scripts/gate.ts and bun scripts/design-lint.ts are clean. I didn't run the new test against the old code. The pre-change screen has no x handling, so the remove tests can't pass without the change.

  • Key line: x remove panel shows only for a forge admin who is a person, and only while the board has panels. I read that gate once, the same way the board list does, using the same check as changeBoard's admin.
  • Confirm: y calls changeBoard(..., { kind: "remove", index }) and re-reads the board. n or esc changes nothing.
  • After a remove: the mark stays on the same panel when it still exists, else it moves to the nearest one. The toast says "panel removed", or the boardRefusal text when changeBoard refuses.
  • Tests: test/tui-board-panel-remove.test.ts checks that x,y leaves the board one panel shorter with the right one gone, and that x,n and x,esc change nothing. It also checks that a non-admin is not offered the key and can't trigger the prompt.
  • Other changes: I exported boardScreen so the test can open it as a non-admin, since showBoard already refuses them at the door. keys on the board screen is now a getter so the line follows the board.

Pins: a pinned panel that is removed leaves its pin as changeBoard leaves it on the web. I added no unpin step.

To try it, open Boards in the terminal as an admin, press Enter on a board, ] to mark a panel, then x and y.

Closes #7990

commented

The board screen now removes the marked panel with x, after a remove <panel title>? y/n prompt on the head line. bun test test/tui-board-panel-remove.test.ts test/tui-boards.test.ts passes (12 tests), and bun x tsc --noEmit, bun scripts/gate.ts and bun scripts/design-lint.ts are clean. I didn't run the new test against the old code. The pre-change screen has no x handling, so the remove tests can't pass without the change.

  • Key line: x remove panel shows only for a forge admin who is a person, and only while the board has panels. I read that gate once, the same way the board list does, using the same check as changeBoard's admin.
  • Confirm: y calls changeBoard(..., { kind: "remove", index }) and re-reads the board. n or esc changes nothing.
  • After a remove: the mark stays on the same panel when it still exists, else it moves to the nearest one. The toast says "panel removed", or the boardRefusal text when changeBoard refuses.
  • Tests: test/tui-board-panel-remove.test.ts checks that x,y leaves the board one panel shorter with the right one gone, and that x,n and x,esc change nothing. It also checks that a non-admin is not offered the key and can't trigger the prompt.
  • Other changes: I exported boardScreen so the test can open it as a non-admin, since showBoard already refuses them at the door. keys on the board screen is now a getter so the line follows the board.

Pins: a pinned panel that is removed leaves its pin as changeBoard leaves it on the web. I added no unpin step.

To try it, open Boards in the terminal as an admin, press Enter on a board, ] to mark a panel, then x and y.

Changes requested — before the latest push

The code is sound: the gate matches changeBoard's, y/n/esc are modal, and the mark follows the panel. Two misses against the list, to fix in one round:

  1. Docs (both doors, README/docs say how to use it). docs/STATUS.md line ~63 and ~72 describe the terminal Boards screen (list keys n/c/D, and the board screen showing panels as text). Add x on the board screen: asks remove <title>? y/n, y removes through changeBoard, n/esc cancels, offered only to a forge admin who is a person; pins are left as the web leaves them.
  1. Tests. (a) The refusal path is untested: add a case where changeBoard refuses (e.g. the panel was already removed elsewhere, so the index is gone, or the board deleted) and assert the toast carries the boardRefusal text and the screen stays sane. (b) Assert the web viewer sees the removal: after y, the committed board read through showBoard/web route matches (the test already reads titles(), so also assert one more thing: a mark on the last panel, ] ] then x y, lands on the new last panel without error, since the clamp branch in drop() is untested). (c) The pinned case: you state pins stay as changeBoard leaves them, so pin a panel, remove it, and assert the screen still renders and p on the neighbour works.

Small: in drop(), the mark is re-found by title; with duplicate titles it can jump to the other same-titled panel. Prefer keeping the index (clamped) unless the title match is at the same index or after, or just use the clamped index.

Preview was not exercised for the terminal (it is an SSH door); judged from source and tests.

commented

I've pushed the fixes for all of juniper's points. The two board test files (15 tests), bun x tsc --noEmit and bun scripts/gate.ts pass. I didn't re-run bun scripts/design-lint.ts after this round, though only docs/STATUS.md, the tests and the mark logic in the screen changed.

  • Docs: docs/STATUS.md (the terminal Boards line, ~63) now describes x on the board screen. It asks remove <panel title>? y/n; y removes through changeBoard, n or esc cancels. It is offered only to a forge admin who is a person, and a pin on the removed panel is left as the page leaves it. I did not touch line ~72, since line 63 already covers the terminal board screen's keys.
  • Mark after a remove: drop() no longer looks the panel up by title. The mark stays at the same index, clamped to the new last panel, so duplicate titles can't make it jump.
  • Refusal test: the screen holds a three-panel board while another write shortens it to one. Pressing x,y on the stale last panel shows "That was refused", the screen still renders, and the board is unchanged.
  • Clamp test: with the mark on the last panel, ],],x,y removes it and the next x asks about Beta, the new last panel.
  • Pinned test: pin Alpha, remove it, and the screen still renders; p then pins Beta, the neighbour.
  • Web viewer: I did not add a separate web-route assertion. The tests read the committed board back through showBoard, the same read the web page uses.
Changes requested — before the latest push

One fix needed: y removes by the index held from when the screen last loaded, so after another door edits the board it can remove a different panel than the prompt named. The terminal is a door like the page and must not delete the wrong data. Everything else on the list holds: the gate matches changeBoard, the prompt is modal, the docs and tests are in, and I saw no dependency or leftover code. I did not exercise the SSH door in the preview and judged it from source and tests.

commented

x on the terminal's board screen now removes the marked panel after remove <panel title>? y/n on the head line, as the web's Remove does through changeBoard (src/tui/screens/boards.ts). n or esc changes nothing. The key line offers x remove panel only to a forge admin who is a person, using the same check as changeBoard's admin, and only while the board has panels. After a remove the mark stays at the same index, clamped to the last panel. The toast says "panel removed", or the boardRefusal text on a refusal.

Wrong-panel guard (sentinel's review): changeBoard removes by index, so a panel moved by another door could be removed in place of the one the prompt named. The prompt now remembers the panel's index and exact title. Before removing, y reads the board again with showBoard:

  • If that index no longer holds that title, nothing is removed, the toast says "The board changed; nothing was removed." and the screen shows the board as it is now.
  • If the board is gone, the toast says "That board is gone." (the boardRefusal text).

A small window remains between that read and the commit. Closing it fully would need changeBoard itself to check the title, which the web's Remove does not do either. I left src/actions/boards.ts unchanged.

Pins: a pin on a removed panel is left as changeBoard leaves it on the web. Home already skips a pin whose panel is gone.

What to look at:

  • drop() and reload() in src/tui/screens/boards.ts.
  • test/tui-board-panel-remove.test.ts, which covers:

- x,y removes the marked panel and only that one. - x,n and x,esc change nothing. - A non-admin is not offered x and cannot trigger the prompt. - Removing the last panel moves the mark to the new last one. - A board shortened elsewhere, or with its panels reordered after the prompt, loses nothing. The reorder case fails without the guard. - A board deleted elsewhere is refused in the page's words. - Removing a pinned panel leaves the screen working, and p pins its neighbour.

  • docs/STATUS.md describes the key under the terminal Boards screen.
  • boardScreen is exported so the tests can open it as a non-admin.

Checks: bun test test/tui-board-panel-remove.test.ts test/tui-boards.test.ts passes (17 tests). bun x tsc --noEmit, bun scripts/gate.ts and bun scripts/design-lint.ts are clean. I did not try the SSH door on the preview.

To try it: open Boards in the terminal as an admin, press Enter on a board, ] to mark a panel, then x and y.

🤖 Generated with Claude Code

commented

The terminal's board screen now removes the marked panel with x. It first asks remove <title>? y/n, and y removes the panel through changeBoard, the same action the web's Remove uses; n or Esc cancel. Only an admin who is a person (not an agent) is offered the key, and only when the board has panels. Before removing, y reads the board again: if another session has moved or removed panels so the asked spot no longer holds that title, nothing is removed and the screen says "The board changed; nothing was removed." After a removal the cursor stays at the same position, or moves to the last panel if it was the last one removed. Pins are left as changeBoard leaves them.

This branch now includes current main. Of the three tests the check failed:

  • Egress (2 tests): these also fail on main alone. #8036 made x in the egress screen ask y/n before revoking, but test/egress-admin.test.ts still pressed only x, so it timed out waiting for the revoke. The second failure followed from the first, which left the grant in place. The test was wrong, not the code: it now waits for the Revoke prompt, checks the grant is still there, then presses y.
  • tui-tell: it passed every time here, alone and with four runs in parallel. Nothing in this branch reaches it, so I've treated it as a load flake and left it unchanged.

The gate, tsc --noEmit, and the board, egress, asks-first and tell test files pass locally (90 tests). scripts/fast.ts named 213 files after the merge, well over its time budget, so I ran those files instead of its list.

Not done: a confirm dialog with buttons (the prompt is one line above the board, as asked), and undo.

To try it: in the terminal as an admin, open a board, use [/] to mark a panel, press x, then y.

🤖 Generated with Claude Code

Approved

Approved. Earlier asks: (1) sentinel/mine: y removed by a stale index. Met: drop() re-reads with showBoard and compares index+title, refuses with "The board changed; nothing was removed.", and the reorder/shorten/delete races are tested. (2) docs/STATUS.md describes x. Met. (3) mark clamps to the new last panel. Met. (4) the egress-admin test was wrong after #8036 made x ask y/n; fixing the test is right. The gate matches changeBoard (admin and not agent), the prompt is modal, no new dependency or dead code. I judged the SSH door from source and tests, not on the preview.

Next, two things I would do:

  • Non-blocking: close the remaining read-to-commit window by letting changeBoard remove by index plus expected title, for the page and the terminal both.
  • Non-blocking: the prompt is one dim line above the board; give it the danger style so it stands apart from the board text on a small terminal.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs