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

A card can say when it is due, and a board can show what is late #121

open not picked up yet opened this
opened this

Give a card a date, so a shared board can say what is due and what is late instead of being a wall of undated text.

Why. A board people share for real work is planned in time: "Ship it" matters on Friday. Today a card holds a title and nothing else (src/db.ts's card table has title, position, created_at, updated_at, and none of the last three is ever shown). #89 gives a column a WIP limit and #49 gives a card a note; a due date is the third thing every person who has used a kanban board reaches for, and it costs one nullable column, one validated field and one rendered <time>.

Done looks like

  • [ ] card.due_on — a nullable TEXT holding a plain YYYY-MM-DD date, added through the ordered migration list from #97 (no second hand-written PRAGMA table_info patch).
  • [ ] POST /b/:id/cards/:cardId/due sets or clears it: a date validated at the boundary against /^\d{4}-\d{2}-\d{2}$/ and Date.parse, an empty value clearing it, anything else refused with the board's own error shape. The write is one transaction, logs its previous value for undo, bumps the revision and publishes card.edited — the existing event is enough, no new kind.
  • [ ] The card shows it as <time datetime="2026-09-25">25 Sep</time>, escaped like everything else, with a "late" style when the date is before today (computed server-side, so a wrong client clock cannot make a card look late) and no layout shift when the slot is empty.
  • [ ] The filter (q) still only matches titles; due: syntax is explicitly out of scope and said so in the pull.
  • [ ] list_cards returns due_on, and add_card accepts an optional due_on with the same validation, so the agent seat can plan too.
  • [ ] The terminal shows the date beside a card's title where the width allows, and has one key to set it — what a person can do on the page they can do over ssh (AGENTS.md).
  • [ ] Tests that fail without the change: the boundary rejects 2026-13-45, tomorrow, and a 200-character string; clearing works; undo restores the previous date; the rendered card carries the <time> element and the late class only when late; list_cards carries the field.
  • [ ] The README's card paragraph says what a date is and is not (no time of day, no timezone, no reminders).

Files I expect to change

src/db.ts, src/routes.ts, src/pages/board.ts, src/mcp.ts, src/keys.ts and src/tty.ts, src/db.test.ts, src/server.test.ts, README.md.

Risks

  • Waits for #97 (one ordered migration list): this is the second nullable column queued behind that, after #89's wip_limit, and adding it by hand is exactly the failure #97 exists to prevent.
  • #48 moves per-card controls onto a card page. If it has landed, the date control belongs there and the card itself only shows the date — check before building a second inline form.
  • Timezones: store a date, never an instant, and compare against the server's own day. Say that in a comment; it is the thing that goes wrong later.

Suggested: scout, reviewed by juniper. Waits for #97.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs