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

Every change writes down what it was: a label in the action row, and an undo that returns it #118

shipped production is serving it opened this has it
opened this

Split out of #43, which was tried twice (pulls #114 and #116, both killed mid-run by the provider's weekly limit) and pushed nothing either time. #43 asks for the database, the route and the page in one run; this is the database half alone, which is the part everything else waits on and the part that can be finished and tested without touching a rendered page.

Done looks like

  • [ ] Every mutation in src/db.ts writes a short human label into its action row alongside the payload it already logs: moved "Ship it", deleted the column "Doing", renamed the board, added a card. The label is built from the data the write already holds — nothing re-reads the board to make it.
  • [ ] The label is stored as a field of the existing payload JSON (no new column, no migration), so a row written before this change still parses.
  • [ ] undo(boardId) returns string | null — the label of what it just reversed, null when there was nothing to undo. An action row written before this change undoes cleanly and reports a change.
  • [ ] db.peekUndo(boardId) returns the label of what Undo would reverse, as one indexed read (SELECT payload FROM action WHERE board_id = ?1 ORDER BY id DESC LIMIT 1), or null.
  • [ ] Labels hold card and column titles — someone else's text. This issue stores them raw and says, in a comment at the top of the label helper, that every caller escapes at the boundary (escape() on the page, the control-character strip in the terminal). Nothing here renders anything.
  • [ ] Tests in src/db.test.ts that fail without the change: a label round-trips through the action row for each kind of mutation; peekUndo names the last change and does not consume it; a legacy payload with no label undoes and reports a change; undo on an empty log returns null.
  • [ ] Every existing caller of undo() still compiles and behaves: src/routes.ts treats a string as success and null as "nothing to undo" (its 404/{ok:false} path is unchanged), and src/tty.ts/src/keys.ts keep working. No page markup changes in this issue.

Files I expect to change

src/db.ts, src/db.test.ts, and the one-line truthiness adjustments in src/routes.ts and the terminal's undo call site.

Out of scope

The Undo button's title/aria-label preview, the disabled "Nothing to undo" state, and the JSON { ok, undid } shape — all of that stays in #43, which now waits for this.

Risks

  • #107 removes the three action rows a new board logs for its own default columns. If it lands first there is one fewer call site to label; either order is a trivial merge.
  • Keep the label short and fixed-shape: it is about to be rendered in an aria-label (#43) and drawn in a terminal (#34). A title longer than ~40 characters should be elided in the label itself, once, here — not by every renderer.

Suggested: scout.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs