fix(desktop): order project-tree lanes by recency in the overview, not alphabetically
_build_repos emptied each lane's sessions array for the overview (hydrate=False) payload BEFORE _sort_lanes ran. _lane_sort_key derives a lane's activity from max(_session_time(s) for s in group["sessions"]), so with the rows already gone every non-trunk lane scored activity=0.0 and the sort key (is_trunk, is_kanban, -activity, label) collapsed to alphabetical-by-label. The documented intent — branches and linked worktrees sort by most-recent activity, then label — was silently defeated on the projects.tree RPC that feeds the desktop sidebar overview, while the drill-in path (hydrate=True) kept the rows and sorted correctly. Any repo with two or more non-trunk lanes showed a different order in the overview than when opened. Move the session-clearing to after _sort_lanes/_disambiguate_labels so the sort reads real recency. Lane counts are still captured before clearing, so sessionCount and the slim overview payload are unchanged — only the order is fixed, and the overview now matches the drill-in.
This commit is contained in:
@@ -125,6 +125,42 @@ def test_linked_worktrees_fold_under_their_common_repo_root():
|
||||
assert linked["path"] == "/elsewhere/wt"
|
||||
|
||||
|
||||
def test_overview_orders_lanes_by_recency_not_alphabetically():
|
||||
# Two linked-worktree lanes under one common repo root whose ALPHABETICAL
|
||||
# order (wt-aaa, wt-zzz) is the OPPOSITE of their activity order (wt-zzz is
|
||||
# the more recently active). The overview (hydrate=False) empties lane
|
||||
# session arrays for payload slimness — but the lane sort must still run on
|
||||
# real recency, matching the drill-in (hydrate=True) order, not collapse to
|
||||
# alphabetical because the rows were dropped before sorting.
|
||||
resolve = _resolver(
|
||||
{
|
||||
"/repo": ("/repo", "/repo"),
|
||||
"/wt-aaa": ("/repo", "/wt-aaa"),
|
||||
"/wt-zzz": ("/repo", "/wt-zzz"),
|
||||
}
|
||||
)
|
||||
sessions = [
|
||||
_session("/repo", branch="main", last_active=5000),
|
||||
_session("/wt-aaa", last_active=1000), # alphabetically first, older
|
||||
_session("/wt-zzz", last_active=9000), # alphabetically last, newer
|
||||
]
|
||||
|
||||
def _non_trunk_labels(hydrate):
|
||||
tree = pt.build_tree([], sessions, [], resolve, hydrate=hydrate)
|
||||
project = tree["projects"][0]
|
||||
return [
|
||||
g["label"]
|
||||
for repo in project["repos"]
|
||||
for g in repo["groups"]
|
||||
if not g["isMain"]
|
||||
]
|
||||
|
||||
# Overview path: recency order (newer first), NOT alphabetical.
|
||||
assert _non_trunk_labels(hydrate=False) == ["wt-zzz", "wt-aaa"]
|
||||
# Drill-in path already sorts by recency — the two paths must agree.
|
||||
assert _non_trunk_labels(hydrate=True) == ["wt-zzz", "wt-aaa"]
|
||||
|
||||
|
||||
def test_kanban_task_worktrees_collapse_into_one_bucket():
|
||||
resolve = _resolver(
|
||||
{
|
||||
|
||||
@@ -376,8 +376,6 @@ def _build_repos(sessions: list[dict], resolve: Optional[Resolve], hydrate: bool
|
||||
group = entry["group"]
|
||||
group["sessions"].sort(key=_session_time, reverse=True)
|
||||
count = len(group["sessions"])
|
||||
if not hydrate:
|
||||
group["sessions"] = []
|
||||
|
||||
repo_identity = _path_key(entry["repo_key"])
|
||||
repo = repos.get(repo_identity)
|
||||
@@ -397,6 +395,15 @@ def _build_repos(sessions: list[dict], resolve: Optional[Resolve], hydrate: bool
|
||||
for repo in repo_list:
|
||||
repo["groups"] = _sort_lanes(repo["groups"])
|
||||
_disambiguate_labels(repo["groups"])
|
||||
# Drop per-lane session rows only AFTER sorting: _lane_sort_key ranks
|
||||
# non-trunk lanes by most-recent activity, which it derives from the
|
||||
# session rows. Clearing them earlier makes every lane look inactive on
|
||||
# the overview (hydrate=False) path and collapses the sort to
|
||||
# alphabetical. Counts were already captured above, so the payload stays
|
||||
# slim without losing the recency order.
|
||||
if not hydrate:
|
||||
for group in repo["groups"]:
|
||||
group["sessions"] = []
|
||||
_disambiguate_labels(repo_list)
|
||||
return repo_list
|
||||
|
||||
|
||||
Reference in New Issue
Block a user