Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-202Done

3.8.2 Projection load model — bounded whole-set load + Done-age window + `truncated`/`cap` signal (retire the per-column cursor)

Estimate: 32m · Depends on: 3.1.4, 3.3.4

Change boardsService.getBoard from a per-column first-page + cursor to the bounded whole-set load the mirror uses, through the 4-layer architecture (Route → Service → Repository → Prisma), keeping the explicit workspaceId gate (finding #26).

The change. Introduce a BOARD_ISSUE_CAP constant (a generous bound, e.g. 5,000 — the Jira Software figure). The projection loads each mapped column’s cards up to the board-level cap across the board (ordered by position), applies the Done-age window to terminal columns (issues resolved within ~14 days; refines 3.2.5’s count-based window to the age-based Jira behaviour, full count still surfaced), and returns a board-level truncated: boolean + cap: number alongside the existing per-column totalCount. When the board’s total exceeds the cap, truncated is true (the UI shows the banner) and the load stops at the cap — bounded, never "load every row" (finding #57 holds). The swimlane projection (3.3.4 swimlaneKey + swimlanes[] aggregate) is unchanged in shape — it just buckets the now-fully-loaded (bounded) cards.

Retire the cursor. The per-column cursor (3.1.4) and the GET /api/board/columns/[id]/cards load-more route (3.1.6) become dead with no "Load more" caller; remove them (and the PagedColumnCardsDto path) or mark them removed in this subtask — do NOT leave a half-paged contract. Keep BoardColumnDto.totalCount (the denominator the count badge + the 3.3.6 WIP chip read).

Acceptance criteria

  • getBoard loads each column’s cards up to BOARD_ISSUE_CAP (no per-column cursor paging) and applies the Done-age window to terminal columns; per-column totalCount is retained.
  • The projection returns board-level truncated + cap; truncated is true exactly when the board total exceeds the cap, and the load is bounded by the cap (never unbounded).
  • The dead per-column cursor + the /columns/[id]/cards load-more route are removed (no orphaned paging contract); DTOs updated in lib/dto/boards.ts + mapped in lib/mappers/boardMappers.ts.
  • Vitest (real Postgres) covers: the bounded load (count == min(total, cap)), truncated true past the cap / false under it, the Done-age window (old done items excluded, count still full), and the swimlane buckets still resolve over the bounded set.

Context refs

  • lib/services/boardsService.ts getBoard + lib/dto/boards.ts + lib/mappers/boardMappers.ts (3.1.4 / 3.3.4) — the projection this changes (add truncated/cap, drop cursor)
  • app/api/board/columns/[columnId]/cards/route.ts (3.1.6) — the load-more route to retire
  • lib/repositories/workItemRepository.ts — the column read + count; the Done-age filter
  • finding #57 (bounded, not load-all — the cap IS the bound); the verified Jira cap + 14-day Done window (rung 1); notes.html mistake #33; motir-core/CLAUDE.md (4-layer + DTO mapping)