Files
kandev/docs/plans/sidebar-task-tree-activity-sort/task-01-sort-visible-task-trees.md
T
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

5.7 KiB

id, title, status, wave, depends_on, plan, requirements, acceptance_criteria, system_design
id title status wave depends_on plan requirements acceptance_criteria system_design
01-sort-visible-task-trees Sort visible task trees by activity done 1
plan.md
REQ-UI-SIDEBAR-LAST-ACTIVITY-SORT-002
AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.1
AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.2
AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.3
AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.4
AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.5
AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.6
../../specs/ui/system-design/sidebar-task-tree-activity-sort.md

Task 01: Sort Visible Task Trees by Activity

Summary

Derive each visible task subtree's latest activity and use it for Last activity sorting. Prove that a recently active child moves its parent tree in both desktop and phone task lists while every row retains its own time.

In scope

  • Add a cycle-safe, iterative, memoized tree-activity resolver over the included parent-child map.
  • Use the derived key only in the Last activity sort path, preserving direction, ties, filtered roots, and existing later ordering overrides.
  • Preserve the phone task drawer's task-local activity field and fallback through its row projection.
  • Add focused unit and desktop/phone Playwright coverage.

Out of scope

  • Backend generation of activity timestamps, Updated and other sort keys, group-heading sort, settings format, and visual layout changes.

Acceptance

  1. A direct or nested child's newer activity ranks its included parent tree ahead of an older tree in descending order, with the inverse order for ascending views; siblings follow the same subtree rule.
  2. Filtered-out descendants have no effect, collapsed descendants still contribute, and ties, missing timestamps, pinning, manual order, and other sort keys retain their established behavior.
  3. Desktop and phone rendered tests show the same parent-tree order, and the parent's visible time remains its own.

ASCII UI preview

UI-01: Desktop Tasks sidebar, Last activity descending, before and after. The complete preview is in plan.md.

CURRENT                       EXPECTED
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, same saved view and ordering.

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

The times illustrate each row's own activity; the tree's rank follows the child. These views cover AC-UI-SIDEBAR-LAST-ACTIVITY-SORT-002.1, .2, .5, and .6.

Verification

(cd apps && pnpm install --frozen-lockfile)
(cd apps && pnpm --filter @kandev/web exec vitest run lib/sidebar/task-tree-activity.test.ts lib/sidebar/apply-view.test.ts)
(cd apps/web && pnpm run typecheck)
(cd apps/web && pnpm e2e:run --project chromium tests/task/sidebar-task-tree-activity-sort.spec.ts)
(cd apps/web && pnpm e2e:run --project mobile-chrome tests/task/mobile-sidebar-task-tree-activity-sort.spec.ts)

Run the new focused unit case red before production edits, then green after the resolver and sort integration. The managed E2E runner builds the current web bundle before browser assertions.

Files likely touched

  • apps/web/lib/sidebar/task-tree-activity.ts
  • apps/web/lib/sidebar/task-tree-activity.test.ts
  • apps/web/lib/sidebar/apply-view.ts
  • apps/web/lib/sidebar/apply-view.test.ts
  • apps/web/components/task/mobile/session-task-switcher-sheet-item.ts
  • apps/web/components/task/mobile/session-task-switcher-sheet-item.test.ts
  • apps/web/e2e/tests/task/sidebar-task-tree-activity-sort.spec.ts
  • apps/web/e2e/tests/task/mobile-sidebar-task-tree-activity-sort.spec.ts
  • apps/web/e2e/tests/task/sidebar-task-tree-activity-sort-helpers.ts

Dependencies

None. Read the requirement and the system design before implementation.

Risks

  • The tree resolver must use filtered descendants and remain bounded for deep or malformed parent graphs.
  • Existing mobile task views use the same applyView result but a separate drawer; prove the rendered order rather than assuming shared code is sufficient.

Parallelism

sequential

Inputs

  • applyView, applySort, separateSubtasks, and existing lastActivitySortValue in apps/web/lib/sidebar/apply-view.ts.
  • The existing state-tree resolver and its tests as a traversal pattern.
  • Existing desktop Last activity and phone view E2E fixtures.

Results

Implemented a cycle-safe iterative resolver that aggregates the newest activity across each included subtree. Filters run before aggregation, collapse does not affect it, and each row keeps its own activity timestamp. The phone row projection now carries lastActivityAt with task update and creation fallbacks while preserving summary freshness in updatedAt.

Activity keys compare chronological RFC3339 instants with full fractional precision and timezone offsets through the shared strict parser. Malformed or semantically invalid timestamps retain the existing lexical fallback instead of being normalized by Date.parse. Equal instants retain stable order, and missing timestamps keep their existing fallback order.

Validation passed:

  • Focused Vitest suite after review: 3 files, 83 tests, including malformed calendar dates and shorthand timestamp fallback.
  • Frontend typecheck.
  • ESLint on all changed TypeScript files with --max-warnings 0.
  • Desktop Playwright regression in chromium.
  • Phone Playwright regression in mobile-chrome.
  • Specification validation and lint.
  • git diff --check.