Skip to content

feat(task-board): redesign the card dialog with autosave, human keys and short links - #6342

Merged
viktormarinho merged 7 commits into
mainfrom
rafavalls/task-header-row
Aug 20, 2026
Merged

feat(task-board): redesign the card dialog with autosave, human keys and short links#6342
viktormarinho merged 7 commits into
mainfrom
rafavalls/task-header-row

Conversation

@rafavalls

@rafavalls rafavalls commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

What is this contribution about?

Adds a per-org, human-readable key to each task board card (e.g. DECO-01), derived from a new key_seq column assigned at create time (with retry on raced inserts) and exposed via packages/shared/task-key.ts. Adds a shareable short link route (/$org/t/DECO-01) that resolves the key to a card and forwards to the board's deep link. Reworks the task dialog header to show the new key row, and fixes list-continuation handling in the markdown editor.

How did you verify your code works?

Added unit tests for task-key.ts (prefix derivation, key formatting, term parsing) and for the markdown editor's unwrap-list-continuations. Added a Postgres integration test (task-board-key-seq.integration.test.ts) covering key_seq assignment and the raced-insert retry path. Updated existing task-board schema/reaction/update/filters/config tests for the new keySeq field.

Screenshots/Demonstration

N/A — no screenshots captured in this session; the task dialog header now renders the card's DECO-01-style key.

How to Test

  1. Run bun run --cwd=apps/api migrate to apply migration 172-task-board-item-key-seq.
  2. Create a new task board card and confirm it shows a DECO-01-style key in the dialog header.
  3. Visit /$org/t/<key> and confirm it redirects to the board with that card opened.

Migration Notes

Requires running the new Kysely migration apps/api/migrations/172-task-board-item-key-seq.ts, which adds and backfills the key_seq column on task_board_items.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • Documentation is updated (if needed)
  • No breaking changes

Summary by cubic

Redesigns the task dialog with autosave and human task keys plus short links. Old behavior: a Save button and each autosave spammed the timeline; new behavior: a 2s autosave with blur flush and server‑side coalescing that merges repeated title/description edits by the same actor within 10 minutes.

Assigns a per‑org sequence (key_seq) at create under a per‑org advisory lock, with a unique (organization_id, key_seq) index to prevent duplicates. Exposes keySeq and renders keys like DECO-01. Adds /$org/t/DECO-01 short links that resolve by human key or raw id and forward to the board; the router preserves a task param through the landing redirect; board search matches keys (DECO-07, deco-7, or 7). Reworks the dialog: moves actions into a menu (clone, archive, delete, new chat, auto‑fix/rerun), adds copy/share for the key, collapses long descriptions and folds long activity runs, shows PRs as read‑only rows, and clips the description only while folded so image controls stay clickable. Normalizes wrapped list items before parsing so the editor does not drop text. Tests cover Postgres key allocation under lock (forced interleaving) and activity coalescing, key helpers and resolvers, and markdown normalization; e2e closes the dialog to flush autosave.

Rollout

  • Run migration 172-task-board-item-key-seq to add/backfill key_seq and create the unique index.
  • Verify a new card shows a DECO-01‑style key and that visiting /$org/t/<key or id> opens that card on the board.

Written for commit 68339c3. Summary will update on new commits.

Review in cubic

rafavalls and others added 2 commits August 20, 2026 13:08
Assigns each card a per-org sequence (key_seq) at create time, exposed as a
human key (DECO-01) via packages/shared/task-key.ts, with a shareable short
link route (/$org/t/DECO-01) that resolves to the board deep link. Adds the
172 migration/backfill, storage retry on raced key_seq inserts, and reworks
task-dialog's header to show the new key row. Also fixes list-continuation
handling in the markdown editor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A card written before the key backfill has no key, so the share button falls
back to its id — which the /$org/t/ route couldn't parse, sending the link to
an empty board. Resolve either shape, so any link already pasted somewhere
keeps working.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rafavalls rafavalls changed the title feat(task-board): add human-readable task keys and header row feat(task-board): redesign the card dialog with autosave, human keys and short links Aug 20, 2026
rafavalls and others added 5 commits August 20, 2026 13:55
Every debounced save logged its own entry, so writing one paragraph buried the
card's history under a dozen identical "updated the description" lines.

Coalesce prose edits in `recordActivities`: a repeat of the same action by the
same actor within 10 minutes moves the existing entry to now instead of adding
one. It lives in storage because that is the single write path, so any client
gets it. Every other action stays a discrete event.

Client-side, the text debounce goes 700ms -> 2s and blur flushes the pending
write, so a sentence costs one request instead of five.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The dialog lost its Save button when editing became autosave, and these three
specs still waited 3 minutes for it. Close the dialog instead — that is the
flush point now — and assert it unmounted before reading the wire.

Escape would be locale-proof but tiptap swallows it while the editor has
focus, which is exactly where these tests leave it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fold's container carried `overflow-hidden` unconditionally, and it starts
exactly at the pane's content edge. An image node is only as wide as its image,
so its absolutely-positioned remove button reaches ~35px to the LEFT of a 1px
image — outside that box, clipped, and unclickable. The e2e caught it as the
pane intercepting the click.

Clip only when folded, and raise the cap clear of the editor's empty footprint
(~364px measured, so 420 folded a description holding one image).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI found the allocator's real limit: 8 concurrent creates in one org exhausted
the 5 retries and the create FAILED, so a card could be lost to contention. The
retry only re-read a `max(key_seq)` the next writer was already racing.

Take a per-org advisory lock for the length of the insert instead. The read and
the write are one critical section, so there is nothing to retry and no ceiling
on concurrency. The unique index stays as the backstop.

The test now bursts 24 creates, well past what broke the old path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…harder

A burst only races if the round trips overlap, and against a loopback Postgres
they don't: 50 concurrent creates come out distinct on a laptop even with the
retry-on-conflict allocator that CI failed. Bursting to 24 raises the odds but
still leaves the test dependent on the runner being slow.

Hold one create's transaction open instead, so the second provably reads
`max(key_seq)` while the first is uncommitted — the interleaving the lock
exists for. Verified red without the lock, green with it. It waits on
pg_stat_activity for the blocked backend rather than sleeping a guessed
interval.

Also namespace the lock key (`task-board-key-seq:<org>`) and cast it, matching
ensure-user-organization and sandbox-runner-state: hashing the bare org id
shares a lock space with any other feature that hashes the same id.
@viktormarinho
viktormarinho merged commit 5a7cbc1 into main Aug 20, 2026
34 checks passed
@viktormarinho
viktormarinho deleted the rafavalls/task-header-row branch August 20, 2026 20:11
decocms Bot pushed a commit that referenced this pull request Aug 20, 2026
PR: #6342 feat(task-board): redesign the card dialog with autosave, human keys and short links
Bump type: minor

- decocms (apps/api/package.json): 4.248.5 -> 4.249.0
- @decocms/native (apps/native/package.json): 4.248.5 -> 4.249.0
- @decocms/e2e (packages/e2e/package.json): 1.41.1 -> 1.42.0
- @decocms/shared (packages/shared/package.json): 0.47.0 -> 0.48.0

Deploy-Scope: both
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants