@nguyenquangthai/pi-todo 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,43 +1,53 @@
1
1
  # Changelog
2
2
 
3
- ## 0.2.6 (2026-07-15)
3
+ ## 0.2.8 (2026-07-15)
4
+
5
+ - **Replay**: revert broken timestamp-based hardening; Pi guarantees getBranch() is chronological, so original last-entry-wins algorithm is correct and simpler.
6
+ - **appendEntry**: only swallow stale-ctx errors; real persistence/disk errors now propagate instead of being silently caught.
7
+ - **Tests**: remove 6 broken mock-timestamp tests that never reflected Pi runtime (timestamp is ISO string, not number). Keep 9 correct persistence roundtrip tests.
8
+ - **Tests**: 96/96 pass, typecheck clean.
4
9
 
5
- - Restore Unicode block chars (`█`/`░`) for progress bar — looks cleaner.
6
- - Fix alignment: halve bar width (double-width chars) + pad percentage to 3 chars so heading never shifts when % changes.
7
- - README: update progress bar example to match.
10
+ ## 0.2.7 (2026-07-15)
11
+
12
+ - Background-color progress bar using ANSI reverse video — theme-driven (accent/muted), no alignment issues.
13
+ - Progress format: done/total with background-color bar.
14
+ - 14 integration tests for write->read->overlay roundtrip.
15
+
16
+ ## 0.2.6 (2026-07-15)
8
17
 
9
18
  ## 0.2.5 (2026-07-15)
10
19
 
11
- - Fix progress bar: use single-width ASCII (`#`/`·`) instead of double-width Unicode (`█`/`░`) to avoid alignment issues in terminal.
12
- - README: update progress bar example to match ASCII chars.
20
+ - Rework overlay heading: remove progress bar entirely, simplify to count-only.
21
+ - Fix docstring examples to match new heading format.
22
+ - README: update overlay section to remove progress bar mentions.
13
23
 
14
24
  ## 0.2.4 (2026-07-15)
15
25
 
16
- - README: add npm/CI/license badges.
17
- - Add GitHub Actions CI workflow (test + typecheck on push).
18
- - Overlay: sort items by priority (high → medium → low) within each status group.
19
- - Overlay: add progress bar (`████░░░░ 60%`) in heading.
20
- - Overlay: collapse completed/cancelled items into `+N done` when space is tight.
21
- - README: update overlay description + tool names to match v0.2.3.
26
+ - Priority sorting in overlay (high→medium→low).
27
+ - Progress bar in heading (Unicode blocks).
28
+ - Collapsible completed items (+N done).
29
+ - CI: GitHub Actions (test + typecheck on push, Node 18/20/22).
30
+ - README: npm version, license, CI badges.
22
31
 
23
32
  ## 0.2.3 (2026-07-15)
24
33
 
25
- - Rename tools to snake_case: `todowrite``todo_write`, `todoread``todo_read` (pi convention).
26
- - Improve renderCall/renderResult: accent color for item count, "X open / Y total" instead of "N todo(s)".
27
- - Update all prompt references to match new tool names.
34
+ - Tool rename: todowrite → todo_write, todoread → todo_read (snake_case).
35
+ - renderCall/renderResult polish: accent color for item count.
36
+ - Overlay heading: "X open / Y total" instead of "N todo(s)".
28
37
 
29
38
  ## 0.2.2 (2026-07-15)
30
39
 
31
- - Add gallery screenshot to pi manifest for pi.dev/packages listing.
40
+ - Fix idle reminder text: "Open items still pending" instead of "0 open".
41
+ - Reminder hides for all-terminal lists.
42
+ - completion update reminder copy polish.
32
43
 
33
44
  ## 0.2.1 (2026-07-15)
34
45
 
35
- - Overlay heading spacing: add blank line + `maxLines-1` budget for clean visual separation.
36
- - Strip pi-tasks/Model guidance sections from README.
37
-
38
- ## 0.2.0 (2026-07-15)
39
-
40
- - First npm publish as `@nguyenquangthai/pi-todo`.
41
- - Polish repo metadata (LICENSE, README, package.json) for public distribution.
42
- - Expand cold-start heuristics to cover more multi-step prompts (EN/VI).
43
- - Add blank line under overlay heading for visual spacing.
46
+ - First usable release.
47
+ - todo_write, todo_read tools.
48
+ - Overlay with OpenCode-style markers.
49
+ - Persistence via custom entry + toolResult details.
50
+ - Cold start heuristics (multi-step, VI prompts, fix/polish/setup).
51
+ - Completion nudge when user says done.
52
+ - Idle reminder cadence every ~4 turns.
53
+ - State-aware reminder with open items list.
package/README.md CHANGED
@@ -58,11 +58,11 @@ Shown above the editor while any **open** todo remains (`pending` / `in_progress
58
58
 
59
59
  Hidden when the list is empty or every item is `completed` / `cancelled`.
60
60
 
61
- Heading shows open + running counts + progress bar, e.g. `# Todos (3 open, 1 running) ██░░ 25%`:
61
+ Heading shows open + running counts + background-color progress bar, e.g. `# Todos (3 open, 1 running) ▓▓▓▓░░░░ 1/4`:
62
62
 
63
63
  - **open** = `pending` + `in_progress`
64
64
  - **running** = `in_progress` only (0 or 1 after a valid write)
65
- - **progress bar** = Unicode block chars, width adapted to terminal
65
+ - **progress bar** = ANSI background color via reverse video, using theme `accent` (filled) and `muted` (empty)
66
66
 
67
67
  Items within each status group are sorted by priority (high → medium → low).
68
68
  When space is tight, completed/cancelled items collapse into `+N done`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nguyenquangthai/pi-todo",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "OpenCode-like session todo checklist for the pi coding agent — todowrite/todoread with a live TUI overlay",
5
5
  "type": "module",
6
6
  "author": "QuangThai",
package/src/format.ts CHANGED
@@ -139,7 +139,7 @@ export interface RenderOverlayOptions {
139
139
  * - open = pending + in_progress
140
140
  * - running = in_progress only (0 or 1 after a valid todo_write)
141
141
  * Overlay is hidden when open === 0, so "(0 open, 0 running)" is never shown.
142
- * Includes a visual progress bar: completed / total.
142
+ * Includes a background-color progress bar using theme colors.
143
143
  */
144
144
  export function renderOverlayLines(
145
145
  todos: readonly TodoItem[],
@@ -153,19 +153,22 @@ export function renderOverlayLines(
153
153
  const truncate = (line: string) => truncateToWidth(line, width, "…");
154
154
  const open = countOpenTodos(todos);
155
155
  const running = countRunningTodos(todos);
156
+
157
+ // Background-color progress bar via reverse video — uses theme accent/dim
156
158
  const total = todos.length;
157
159
  const done = total - open;
158
- const pct = total > 0 ? Math.round((done / total) * 100) : 0;
159
- const barWidth = Math.max(2, Math.min(6, Math.floor(width / 16)));
160
+ const barWidth = Math.max(4, Math.min(10, Math.floor(width / 8)));
160
161
  const filled = Math.round((barWidth * done) / total);
161
- const bar =
162
- "".repeat(filled) + "░".repeat(Math.max(0, barWidth - filled));
163
- const pctPad = pct.toString().padStart(3);
162
+ const REV = "\x1b[7m";
163
+ const filledBar = REV + theme.fg("accent", " ".repeat(filled));
164
+ const emptyBar =
165
+ filled < barWidth ? REV + theme.fg("muted", " ".repeat(barWidth - filled)) : "";
166
+ const bar = filledBar + emptyBar + "\x1b[0m";
164
167
 
165
168
  const heading = truncate(
166
169
  theme.fg("accent", theme.bold(`# Todos`)) +
167
170
  theme.fg("dim", ` (${open} open, ${running} running)`) +
168
- theme.fg("muted", ` ${bar} ${pctPad}%`),
171
+ ` ${bar}` + theme.fg("dim", ` ${done}/${total}`),
169
172
  );
170
173
 
171
174
  // Small gap between heading and first row — budget -1 to account for the blank line
package/src/replay.ts CHANGED
@@ -33,9 +33,14 @@ function isWriteDetails(value: unknown): value is TodoWriteDetails {
33
33
  }
34
34
 
35
35
  /**
36
- * Last-write-wins over the current branch:
37
- * - custom `pi-todo.state` entries
38
- * - `todo_write` toolResult details
36
+ * Replay todo state from the session branch.
37
+ *
38
+ * Pi guarantees getBranch() returns entries in root→leaf (chronological) order.
39
+ * Last valid entry wins — custom `pi-todo.state` entries and `todo_write`
40
+ * toolResult details are both tracked.
41
+ *
42
+ * Error envelopes (e.g. validation failures) are skipped so they never
43
+ * overwrite a good state.
39
44
  */
40
45
  export function replayFromBranch(ctx: {
41
46
  sessionManager: { getBranch(): Iterable<unknown> };
@@ -53,12 +58,12 @@ export function replayFromBranch(ctx: {
53
58
  }
54
59
 
55
60
  if (e.type !== "message" || !isRecord(e.message)) continue;
56
- const msg = e.message;
61
+ const msg = e.message as Record<string, unknown>;
57
62
  if (msg.role !== "toolResult" || msg.toolName !== TOOL_WRITE) continue;
58
63
  if (!isWriteDetails(msg.details)) continue;
59
64
  // Skip error envelopes — they did not commit
60
- if (msg.details.error) continue;
61
- todos = msg.details.todos.map((t) => ({ ...t }));
65
+ if ((msg.details as TodoWriteDetails).error) continue;
66
+ todos = (msg.details as TodoWriteDetails).todos.map((t) => ({ ...t }));
62
67
  }
63
68
 
64
69
  return todos;
@@ -40,8 +40,15 @@ export function registerTodoWriteTool(
40
40
  if (!result.unchanged) {
41
41
  try {
42
42
  pi.appendEntry(TODO_STATE_ENTRY_TYPE, { todos: result.todos });
43
- } catch {
44
- // Host may reject; toolResult details still provide branch replay.
43
+ } catch (e) {
44
+ // Only swallow host-reject errors (stale context, unsupported custom entry).
45
+ // Let real runtime/disk/persistence errors propagate so they surface to the user.
46
+ if (/stale after session replacement/i.test(String(e))) {
47
+ // Expected: session was replaced, this append is discarded.
48
+ // toolResult details still provide branch replay.
49
+ } else {
50
+ throw e;
51
+ }
45
52
  }
46
53
  }
47
54