Files
Carlos Florêncio 45cef11630
Architecture Lint / Architecture boundaries do not regress (push) Has been cancelled
Backend Tests / Plan external runner allocation (push) Has been cancelled
Backend Tests / Detect relevant changes (push) Has been cancelled
E2E Tests / Plan external runner allocation (push) Has been cancelled
Frontend Tests / Plan external runner allocation (push) Has been cancelled
Lint Action Pinning / All action refs are SHA-pinned (push) Has been cancelled
Lint Harness Files / Harness files pass lint (push) Has been cancelled
Backend Tests / Backend Static Checks (push) Has been cancelled
Backend Tests / Backend Tests (1/2) (push) Has been cancelled
Backend Tests / Backend Tests (2/2) (push) Has been cancelled
Backend Tests / Backend (ambient integration env) (push) Has been cancelled
Backend Tests / Run Backend Tests (push) Has been cancelled
Backend Tests / Backend Postgres (push) Has been cancelled
Backend Tests / Backend Postgres 18 (push) Has been cancelled
Backend Tests / Backend (windows) (push) Has been cancelled
E2E Tests / Detect relevant changes (push) Has been cancelled
E2E Tests / Build (push) Has been cancelled
E2E Tests / E2E Shard ${{ matrix.shard }}/14 (push) Has been cancelled
E2E Tests / Resolve Playwright runtime image (push) Has been cancelled
E2E Tests / E2E Containers Shard 1/6 (push) Has been cancelled
E2E Tests / E2E Containers Shard 2/6 (push) Has been cancelled
E2E Tests / E2E Containers Shard 3/6 (push) Has been cancelled
E2E Tests / E2E Containers Shard 4/6 (push) Has been cancelled
E2E Tests / E2E Containers Shard 5/6 (push) Has been cancelled
E2E Tests / E2E Containers Shard 6/6 (push) Has been cancelled
E2E Tests / Kubernetes Compatibility (v1.34.8) (push) Has been cancelled
E2E Tests / Kubernetes Compatibility (v1.36.1) (push) Has been cancelled
E2E Tests / Desktop E2E Smoke (push) Has been cancelled
E2E Tests / Merge E2E Reports (push) Has been cancelled
E2E Tests / E2E Tests Passed (push) Has been cancelled
Frontend Tests / Detect relevant changes (push) Has been cancelled
Frontend Tests / Run Frontend Lint, Tests, and Build (push) Has been cancelled
Frontend Tests / Frontend Tests Passed (push) Has been cancelled
feat: sort sidebar task trees by newest descendant activity (#3935)
2026-09-25 18:48:32 +01:00

4.8 KiB

created, status, requirements, system_design, legacy_specs
created status requirements system_design legacy_specs
2026-09-25 complete
REQ-UI-SIDEBAR-LAST-ACTIVITY-SORT-002
../../specs/ui/system-design/sidebar-task-tree-activity-sort.md

Implementation Plan: Sidebar Task Tree Activity Sort

Overview

Make Last activity sort rank each visible task tree by its newest included member. The shared sort path serves both desktop and phone, so one focused work order can add the derived key and prove it through unit and rendered scenarios.

Scope

In scope

  • Apply the tree's latest activity to root and nested sibling placement for ascending and descending Last activity views.
  • Respect active filters, collapse state, stable ties, and existing pin and manual-order precedence.
  • Prove the shared result in the desktop sidebar and phone task-switcher drawer.

Out of scope

  • Changes to how a task's own activity timestamp is published or displayed.
  • Changes to Updated, state, custom, or other sort keys; group-heading order; task-row presentation; saved-view storage.

Technical approach

applyView in apps/web/lib/sidebar/apply-view.ts already filters before building subTasksByParentId, then calls applySort. Add a pure iterative resolver in apps/web/lib/sidebar/task-tree-activity.ts that uses each task's Last activity fallback and memoizes the maximum for each included subtree. The phone task-switcher projection must pass through the task's own activity timestamp instead of summary freshness. Use the derived value only in the lastActivityAt comparator branch of applySort. Keep the stable index tiebreak, sort-direction sign, applyGroup, pin floating, and applySubtaskOrder in their current order. Neither the backend nor TaskSwitcherItem changes.

ASCII UI preview

UI-01: Desktop Tasks sidebar, entry point: a saved view with Last activity descending. The example rows share one existing group. Times are illustrative; each label is the task's own time.

CURRENT                             EXPECTED
Tasks | Last activity v             Tasks | Last activity v
  Standalone task          2d          v Parent task           4d
  v Parent task           4d            Child task           10s
    Child task           10s          Standalone task        2d

UI-02: Phone task-switcher drawer, entry point: the existing Tasks picker and shared saved view.

Tasks                         [New]
[Last activity view v] [Filters]
---------------------------------
v Parent task              4d
  Child task              10s
Standalone task            2d

Only tree order is required to change. The existing desktop sidebar and phone drawer keep their respective headers and navigation. Their task lists remain the scroll owners. A collapsed parent keeps the same rank, with its child row hidden. No new controls or copy are required. These previews cover AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.1, .2, .4, .5, and .6.

Tests

apps/web/lib/sidebar/task-tree-activity.test.ts and apply-view.test.ts will cover AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.1 through .5: both directions, deep descendants, sibling subtrees, equal values, fallbacks, filtered-out descendants, orphan promotion, collapsed trees, and precedence of pin, manual order, and other sort modes. Include a deep chain to catch recursion limits.

E2E tests

  • apps/web/e2e/tests/task/sidebar-task-tree-activity-sort.spec.ts (chromium) covers the desktop parent-versus-standalone order and individual row time after a child activity update (AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.1, .5, .6).
  • apps/web/e2e/tests/task/mobile-sidebar-task-tree-activity-sort.spec.ts (mobile-chrome) covers the same saved-view order in the phone drawer and touch navigation to the child (AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.1, .6).

Work orders

Verification results

Task 01 is complete. The focused unit suite passed (3 files, 83 tests), frontend typecheck and changed-file ESLint passed, including mixed fractional precision and malformed RFC3339 coverage, and focused desktop (chromium) and phone (mobile-chrome) Playwright tests passed. Specification validation and lint passed.

Risks

  • A recursive per-comparison tree walk would grow with list size and can overflow on deep trees; compute the map once per sort.
  • A child excluded by filtering must not influence its former parent's key. The resolver must consume the filtered parent-child map, not the original task list.
  • The parent row's own time may appear older than its position. Keep that established row meaning and prove the child's activity explains the tree's placement.
  • The phone task drawer must use each task's activity time for both Last activity sorting and row display, with task-local fallbacks when the summary field is absent.