Skip to content

Commit d857150

Browse files
committed
feat: add execution counter column to task stack display
Tracks how many times each task has been moved to the top of the stack via a new `execution_count` field on Task, incremented in `mark_current()`. Displays the count as ×N in a new column before "started at", persisted to YAML and backward-compatible (defaults to 0 for existing tasks). https://claude.ai/code/session_01WfpSrDsJqKjvjCoS8uMkAF
1 parent 34aa1c2 commit d857150

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

python/src/task_stack/stack.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Task:
2222
duration: float = field(default=0.0)
2323
deleted_at: datetime | None = field(default=None)
2424
description: str = field(default="")
25+
execution_count: int = field(default=0)
2526

2627
@property
2728
def is_deleted(self) -> bool:
@@ -34,6 +35,7 @@ def mark_current(self, now: datetime | None = None) -> None:
3435
if self.started_at is None:
3536
self.started_at = now
3637
self.last_current = now
38+
self.execution_count += 1
3739

3840
def end_current_stint(self, now: datetime | None = None) -> None:
3941
"""Accumulate the live stint into ``duration``.
@@ -79,6 +81,8 @@ def to_dict(self) -> dict:
7981
d["deleted_at"] = self.deleted_at.isoformat()
8082
if self.description:
8183
d["description"] = self.description
84+
if self.execution_count:
85+
d["execution_count"] = self.execution_count
8286
return d
8387

8488
@staticmethod
@@ -100,6 +104,7 @@ def _parse(v: object) -> datetime | None:
100104
duration=duration,
101105
deleted_at=_parse(d.get("deleted_at")),
102106
description=d.get("description") or "",
107+
execution_count=int(d.get("execution_count") or 0),
103108
)
104109

105110

python/src/task_stack/window.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ def _update_fonts(self) -> None:
353353
self._ts_col_w = f.measure("00m ago") + 8
354354
self._lc_col_w = f.measure("00m ago") + 8
355355
self._idx_col_w = f.measure("999") + 4
356+
self._exec_col_w = f.measure("×99") + 4
356357

357358
def _truncate(self, text: str, max_px: int, is_current: bool) -> str:
358359
font = self._font_obj_current if is_current else self._font_obj_normal
@@ -628,7 +629,8 @@ def _redraw(self) -> None:
628629
dur_x = width - right_pad
629630
lc_x = dur_x - self._dur_col_w - gap
630631
ts_x = lc_x - self._lc_col_w - gap
631-
text_right = ts_x - self._ts_col_w - gap
632+
exec_x = ts_x - self._ts_col_w - gap
633+
text_right = exec_x - self._exec_col_w - gap
632634

633635
if self._filter_text:
634636
self._visible_indices = [
@@ -685,6 +687,15 @@ def _redraw(self) -> None:
685687
ts_text = st.format_timestamp(task.started_at, now)
686688
dur_seconds = task.duration
687689
col_fill = t.fg_muted
690+
exec_text = f"×{task.execution_count}" if task.execution_count else "—"
691+
c.create_text(
692+
exec_x,
693+
y0 + _ROW_HEIGHT // 2,
694+
text=exec_text,
695+
anchor=tk.E,
696+
font=self._font_normal,
697+
fill=col_fill,
698+
)
688699
c.create_text(
689700
ts_x,
690701
y0 + _ROW_HEIGHT // 2,

0 commit comments

Comments
 (0)