FN-7659: paginate and sort the Archived column newest-first
Adds server-side pagination for the Archived task column, sorted by most-recently-archived first, with a Show more control on the dashboard.
- Add ArchiveDatabase.listPage and TaskStore.listArchivedTasks for a bounded SQL LIMIT/OFFSET read ordered by archivedAt DESC
- Add GET /tasks/archived route for paged archive fetches, leaving the legacy merged listTasks({includeArchived}) path unchanged
- Wire useTasks.loadArchivedTasks to fetch page 1 on first Archived-column expand and loadMoreArchivedTasks for subsequent pages
- Add a "Show more" affordance in Column.tsx/Board.tsx/MainContent.tsx to trigger loading additional archived pages
- Extend taskSorting.ts to keep archived task ordering stable with the new paged data
- Add core and dashboard tests covering archive pagination and store/route behavior
- Add changeset for @runfusion/fusion (minor) and update docs/storage.md and docs/dashboard-guide.md
Files changed:
.changeset/FN-7659-archived-pagination.md | 7 +
docs/dashboard-guide.md | 4 +-
docs/storage.md | 7 +
packages/core/src/__tests__/archive-db-pagination.test.ts | 94 ++++++++
packages/core/src/__tests__/store-archive-search.test.ts | 63 ++++++
packages/core/src/archive-db.ts | 18 ++
packages/core/src/store.ts | 32 +++
packages/dashboard/app/App.tsx | 5 +-
packages/dashboard/app/api/legacy.ts | 19 ++
packages/dashboard/app/components/Board.tsx | 19 +-
packages/dashboard/app/components/Column.tsx | 48 ++++-
packages/dashboard/app/components/__tests__/Column.test.tsx | 41 ++++
packages/dashboard/app/components/__tests__/taskSorting.test.ts | 27 +++
packages/dashboard/app/components/dashboard/MainContent.tsx | 9 +
packages/dashboard/app/components/dashboard/types.ts | 6 +
packages/dashboard/app/components/taskSorting.ts | 16 ++
packages/dashboard/app/hooks/__tests__/useTasks.test.ts | 236 ++++++++++++++++++++-
packages/dashboard/app/hooks/useTasks.ts | 173 ++++++++++++++-
packages/dashboard/app/test/mockApi.ts | 3 +
packages/dashboard/src/routes/__tests__/tasks-archived-pagination.test.ts | 94 ++++++++
packages/dashboard/src/routes/register-task-workflow-routes.ts | 32 +++
21 files changed, 930 insertions(+), 23 deletions(-)
Fusion-Task-Id: FN-7659
Fusion-Task-Lineage: 7a5a1f62-277c-4f29-883c-62e75b269bc5
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
@@ -223,7 +223,9 @@ FNXC:TaskCardMobileSelection 2026-07-01-00:00: Mobile Board long-press is a task
|
||||
FNXC:PlanApproval 2026-07-07-00:00 (FN-7653 correction): the switch is intake/planning-column-only — it must not appear on hold (Todo-like) columns, even though hold columns also gate planning-adjacent behavior. The built-in Coding workflow's Todo column (hold trait) was wrongly showing this control; docs now match the corrected intake-only gating.
|
||||
FNXC:TriageRename 2026-07-08-00:00 (FN-7660): the board column formerly labeled "Triage" is canonically "Planning"; docs refer to it as the Planning column throughout. -->
|
||||
- The Planning column actions dropdown includes **Auto-approve plan**. Turning it on sets the project plan approval mode to auto-approve all planned tasks; turning it off returns to the workflow/default plan approval behavior. In workflow-mode Boards, the same switch appears only on the intake/planning column and on the equivalent **All workflows** aggregate intake column — not on hold (Todo-like) or other lifecycle columns. Use Settings → Merge for the full three-state project control, including **Require approval for all tasks**.
|
||||
- Column ordering semantics: `todo` mirrors scheduler pickup order (priority descending, then oldest `createdAt`, then task ID); `triage`, `in-progress`, `in-review`, and `archived` remain priority-first with task-ID tie-breaks; `done` defaults to most recent completion first (`columnMovedAt`, then `updatedAt`, then `createdAt` fallback) and can be switched from the Done/complete column actions dropdown to descending task ID. In workflow mode, non-archived columns marked with the `complete` flag use the same Done menu items even when their column ID or label is customized.
|
||||
- Column ordering semantics: `todo` mirrors scheduler pickup order (priority descending, then oldest `createdAt`, then task ID); `triage`, `in-progress`, and `in-review` remain priority-first with task-ID tie-breaks; `done` defaults to most recent completion first (`columnMovedAt`, then `updatedAt`, then `createdAt` fallback) and can be switched from the Done/complete column actions dropdown to descending task ID. In workflow mode, non-archived columns marked with the `complete` flag use the same Done menu items even when their column ID or label is customized.
|
||||
<!-- FNXC:ArchivePagination 2026-07-08-00:00 (FN-7659): the Archived column is newest-first (`archivedAt DESC`), not priority-first — it is loaded from a dedicated server-backed paged read and is intentionally excluded from every other column's client-side priority/task-ID sort. -->
|
||||
- The Archived column loads newest-first (most recently archived first) in server-backed pages of 100 tasks. Expanding the collapsed Archived column fetches the first page; a **Show more** button at the bottom fetches the next page on demand. The full archive is never loaded in one request — large archives page incrementally as the operator scrolls and clicks Show more.
|
||||
- Done-column sorting has two descending modes: **Completion date (newest first)** keeps the default completion-time order, while **Task ID (newest first)** places the highest numeric task IDs first. The sort actions are only shown in Done/complete column action menus, including custom workflow completion lanes; Archive All Done lives in the same menu when available.
|
||||
- On mobile, both default and workflow-mode boards fill the project viewport while the column strip remains the internal horizontal scroller with contained edge overscroll.
|
||||
<!-- FNXC:WorkflowSelection 2026-06-29-13:34: Board, List, Header, and Graph workflow selectors now share a durable per-project selection so operators return to the same lane after remounts, task refreshes, or respecification flows; stale saved workflow ids must fall back to a valid default/first workflow instead of hiding all tasks. -->
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
- SQLite operational-log pruning is controlled separately by `settings.operationalLogRetentionDays`. It now prunes `activityLog`, `runAuditEvents`, `agentHeartbeats`, terminal `agentRuns` rows by `endedAt`, and `agentConfigRevisions` by `createdAt`.
|
||||
- Safety invariants for operational pruning: in-flight `agentRuns` (`endedAt IS NULL`) are never deleted, and the most-recent `agentConfigRevisions` row per agent is always preserved even when older than the retention window.
|
||||
|
||||
### Archived-column pagination (FN-7659)
|
||||
|
||||
- The Archived board column no longer loads the full archive into memory. `ArchiveDatabase.listPage(limit, offset)` reads a bounded page ordered `archivedAt DESC, rowid DESC` via SQL `LIMIT/OFFSET`, backed by the existing `idxArchivedTasksArchivedAt` index.
|
||||
- `TaskStore.listArchivedTasks({ limit, offset, slim })` is a dedicated, archive-only read path (default page size 100) that maps paged entries through `archiveEntryToTask` and returns `{ tasks, total, hasMore }` in `archivedAt DESC` order. It intentionally does **not** run the `createdAt ASC` sort used by the merged `listTasks({ includeArchived: true })` path — that merged path (and its non-board consumers: github-tracking reconciler, signal routes, agent-token-usage, self-healing) is unchanged.
|
||||
- `GET /tasks/archived?limit=&offset=` exposes the paged read with `projectId` scoping and `limit`/`offset` validation, returning the same `{ tasks, total, hasMore }` shape.
|
||||
- The dashboard's `useTasks` hook loads page 1 on first Archived-column expand and fetches subsequent pages only via an explicit "Show more" click (`loadMoreArchivedTasks`); it never re-fetches the whole archive on SSE reconnect, tab-visibility recovery, or repeated expand calls. Fetched pages merge into the board `tasks` array de-duplicated by id, with active SQLite rows authoritative over archive snapshots.
|
||||
|
||||
### Activity-log no-op `task:moved` cleanup (FN-5940)
|
||||
|
||||
- `TaskStore` now defends the invariant that `activityLog` never records a `task:moved` row when `metadata.from === metadata.to`.
|
||||
|
||||
Reference in New Issue
Block a user