Let a board start from a list somebody already has: paste ten lines, get ten cards, in one change.
What it is like today. A card is added one at a time through one form and one request. Moving a real backlog into this app — a list in a notes app, the output of a meeting, a checklist from a document — means typing each line and pressing Enter, and nothing about the app suggests it can be started any faster. Every write is already one transaction with one action row (src/db.ts), so the machinery for "many cards, one change" exists; nothing exposes it.
Done looks like
[ ] db.createCards(boardId, columnId, titles) inserts many cards into one column in a single immediate() transaction, appending them in the order given, logging one action row so a single Undo removes exactly the cards that paste created and nothing else.
[ ] It respects the board's card cap: a paste that would exceed MAX_CARDS_PER_BOARD inserts nothing and reports how many would fit, so a person is told "this board has room for 12 more" rather than getting a half-finished import.
[ ] A named constant bounds one paste (MAX_CARDS_PER_PASTE, in src/limits.ts with the others), and each line is trimmed, stripped of control characters through the existing src/text.ts boundary, cut to the 200-character title limit, and dropped when it is empty. Blank lines between items do not become cards.
[ ] POST /b/:id/columns/:columnId/cards accepts a multi-line title field: one line behaves exactly as today (one card, one event, the existing JSON answer), many lines take the bulk path. No second route, so the no-JS form, the board script and the terminal all get this for free.
[ ] One live event for the whole paste, so another tab draws the new cards once rather than ten times — reuse whatever shape #122 settles on for a bulk change, or external if that is honest, and say which in the pull.
[ ] The card input on a column accepts a paste with newlines without submitting on the first one, and the hint says a pasted list becomes one card per line.
[ ] The agent seat gets it too: add_card accepts either title or titles, validated the same way, and says so in its description.
[ ] Tests that fail without the change: ten lines become ten cards in order, in one transaction, undone by one press; blank and control-character lines are dropped; a paste over the cap inserts nothing and names the room left; a paste over MAX_CARDS_PER_PASTE is refused with the board's own error shape; one line still behaves exactly as before.
Files I expect to change
src/db.ts, src/limits.ts, src/routes.ts, src/pages/board.ts (the add-card control and its hint), src/mcp.ts, static/board.<new-hash>.js, src/db.test.ts, src/server.test.ts, README.md.
Risks
Waits for #122, which establishes how a bulk change is logged as one undoable action and announced as one event. Two different answers to that question in the same action table is the thing to avoid.
Rate limiting: one paste is one write for the bucket, which is right — but it is also up to MAX_CARDS_PER_PASTE rows and one large action payload. Keep the paste cap well under the board cap so one refusal path is enough.
Do not turn this into Markdown or CSV import. Lines in, cards out; anything cleverer is a different issue.
Let a board start from a list somebody already has: paste ten lines, get ten cards, in one change.
What it is like today. A card is added one at a time through one form and one request. Moving a real backlog into this app — a list in a notes app, the output of a meeting, a checklist from a document — means typing each line and pressing Enter, and nothing about the app suggests it can be started any faster. Every write is already one transaction with one action row (
src/db.ts), so the machinery for "many cards, one change" exists; nothing exposes it.Done looks like
db.createCards(boardId, columnId, titles)inserts many cards into one column in a singleimmediate()transaction, appending them in the order given, logging one action row so a single Undo removes exactly the cards that paste created and nothing else.MAX_CARDS_PER_BOARDinserts nothing and reports how many would fit, so a person is told "this board has room for 12 more" rather than getting a half-finished import.MAX_CARDS_PER_PASTE, insrc/limits.tswith the others), and each line is trimmed, stripped of control characters through the existingsrc/text.tsboundary, cut to the 200-character title limit, and dropped when it is empty. Blank lines between items do not become cards.POST /b/:id/columns/:columnId/cardsaccepts a multi-linetitlefield: one line behaves exactly as today (one card, one event, the existing JSON answer), many lines take the bulk path. No second route, so the no-JS form, the board script and the terminal all get this for free.externalif that is honest, and say which in the pull.add_cardaccepts eithertitleortitles, validated the same way, and says so in its description.MAX_CARDS_PER_PASTEis refused with the board's own error shape; one line still behaves exactly as before.Files I expect to change
src/db.ts,src/limits.ts,src/routes.ts,src/pages/board.ts(the add-card control and its hint),src/mcp.ts,static/board.<new-hash>.js,src/db.test.ts,src/server.test.ts,README.md.Risks
actiontable is the thing to avoid.MAX_CARDS_PER_PASTErows and one large action payload. Keep the paste cap well under the board cap so one refusal path is enough.Suggested: scout. Waits for #122.