@getpipher/armory-todo 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -41,22 +41,95 @@ Then restart pi (or `/reload`). Or add to `~/.pi/agent/settings.json`:
41
41
  { "packages": ["npm:@getpipher/armory-todo"] }
42
42
  ```
43
43
 
44
+ ## Lifecycle boxes (v0.2.0)
45
+
46
+ TODOs live in one of three states, only one of which hits the agent context:
47
+
48
+ | Box | Status(es) | Auto-injected? | Recoverable? |
49
+ |---|---|:---:|:---:|
50
+ | **Active** | `open`, `in_progress` | ✅ Yes (capped 15) | n/a |
51
+ | **Parked** | `parked` | ❌ No | ✅ `update --status open` |
52
+ | **Archive** | `done`, `cancelled` | ❌ No | ✅ `restore <id>` |
53
+
54
+ **Pruning:** `prune` (default: done/cancelled older than 7 days) moves finished
55
+ todos from the live file to `todo-archive.json` — nothing is deleted. `prune --all`
56
+ ignores age. `restore <id>` brings an archived todo back as `open`.
57
+
58
+ The only irreversible action is `prune --hard` (hard-prune) — it requires an
59
+ explicit `confirm: true` and is always user-confirmed. See **Self-awareness**
60
+ below.
61
+
62
+ **Storage layout:**
63
+
64
+ ```
65
+ ~/.pi/agent/todo/
66
+ todo.json # active + parked
67
+ todo-archive.json # done + cancelled (sealed history)
68
+ todo.config.json # prune ages + health thresholds
69
+ ```
70
+
71
+ A v1 single-file store at `~/.pi/agent/todo.json` is migrated automatically on
72
+ first load after upgrade.
73
+
74
+ ## Self-awareness: health + hard-prune
75
+
76
+ **`health`** reports bloat across all three boxes — counts, stale items, and
77
+ actionable suggestions (e.g. "archive: 41 items older than 180d → consider
78
+ `prune --hard --box archive --older-than 180 --confirm`"). On `session_start`,
79
+ if any bloat flags are detected, the startup notify appends a `⚠ N bloat
80
+ signals` nudge.
81
+
82
+ **`prune --hard`** is the **only irreversible action** — it permanently deletes
83
+ todos. It's gated three ways:
84
+ 1. **Tool-level:** `confirm: true` is required in the tool call; without it the
85
+ action refuses with a clear message.
86
+ 2. **Prompt-level:** the agent is instructed to always run `health` first,
87
+ surface the report + the exact proposed command, and wait for an explicit
88
+ user "yes" before passing `confirm: true`.
89
+ 3. **Slash-level:** `/todo prune --hard` prompts an interactive `ctx.ui.confirm`
90
+ yes/no dialog before executing.
91
+
92
+ Everything else in armory-todo is reversible. `prune --hard` is the one
93
+ irreversible escape hatch, always user-confirmed.
94
+
95
+ ## Interactive panel (SPEC-3)
96
+
97
+ Run `/todo` (no arg) in a TUI session to open the interactive triage panel:
98
+
99
+ - **Box tabs** (Tab / Shift+Tab): Active · Parked · Archive · Config
100
+ - **Filter input**: type to search by text (live filter)
101
+ - **SelectList**: arrow keys navigate, Enter selects
102
+ - **Action submenu** (on Enter): Complete / Park / Re-activate / Restore / Edit text / Delete
103
+ - **Archive box**: summary-first (counts by project + month) → Enter on a bucket to drill down
104
+ - **Config box**: SettingsList with prune ages + health thresholds — edit live, persists to `todo.config.json`
105
+ - **Escape**: exit the panel
106
+
107
+ Typed subcommands (`/todo park <id>`, `/todo prune`, etc.) all still work alongside the panel. Non-TUI sessions (`pi -p`, RPC) fall back to the text list.
108
+
44
109
  ## Usage
45
110
 
46
111
  **Say it naturally** — the model calls the `todo` tool:
47
112
 
48
113
  > “put this in our TODO: decouple global rules into AGENTS.md”
49
114
  > “show me the TODO” → “mark td-… done”
115
+ > “park td-… for now” → later: “restore td-…”
116
+ > “prune the done todos”
50
117
 
51
118
  **Slash command** for quick human triage:
52
119
 
53
120
  ```
54
121
  /todo list open + in-progress TODOs
55
- /todo all include done/cancelled
122
+ /todo all include parked/done/cancelled
56
123
  /todo add <text> quick add (priority: med)
57
124
  /todo done <id> mark done
58
125
  /todo rm <id> cancel (tombstone)
59
- /todo clean clear all done
126
+ /todo park <id> defer (parked — not injected, recoverable)
127
+ /todo restore <id> bring an archived todo back as open
128
+ /todo prune [--all] move done/cancelled to archive (reversible)
129
+ /todo prune --hard permanent deletion (interactive confirm prompt)
130
+ /todo archive [filter] archive summary, or filtered slice (project:X / text:Y)
131
+ /todo health bloat report across all boxes + flags + suggestions
132
+ /todo clean clear all done (deprecated — use prune)
60
133
  /todo path show the store file path
61
134
  ```
62
135
 
@@ -64,31 +137,37 @@ Then restart pi (or `/reload`). Or add to `~/.pi/agent/settings.json`:
64
137
 
65
138
  | action | params | effect |
66
139
  |---|---|---|
67
- | `list` | `statusFilter?`, `projectFilter?`, `tagFilter?` | matching TODOs (default: open + in_progress) |
140
+ | `list` | `statusFilter?`, `projectFilter?`, `tagFilter?`, `text?`, `since?`, `before?`, `limit?`, `page?`, `archived?` | matching TODOs (default: open + in_progress). `archived:true` queries the archive — bare call returns a summary, filters return paginated slices |
68
141
  | `add` | `text`, `project?`, `tags?`, `priority?`, `source?` | create a TODO |
69
- | `update` | `id`, `text?`, `priority?`, `status?`, `project?`, `tags?` | edit a TODO |
142
+ | `update` | `id`, `text?`, `priority?`, `status?`, `project?`, `tags?` | edit a TODO (set `status: parked` to defer) |
70
143
  | `complete` | `id` | mark done |
71
144
  | `delete` | `id` | cancel (tombstone) |
72
- | `clear` | `status?` (default `done`) | bulk-clear a status |
145
+ | `park` | `id` | defer (parked not injected) |
146
+ | `prune` | `ageDays?`, `all?` | move done/cancelled to archive (reversible via restore) |
147
+ | `restore` | `id` | bring an archived TODO back as open |
148
+ | `health` | (none) | bloat report across active/parked/archive + flags + suggestions |
149
+ | `prune` (hard) | `hard:true`, `confirm:true`, `box?`, `olderThan?`, `project?`, `tag?` | PERMANENT deletion — the only irreversible action |
150
+ | `clear` | `status?` (default `done`) | bulk-clear a status (deprecated — use prune) |
73
151
 
74
- Each TODO carries `id, text, project, tags, priority (low|med|high|critical), status (open|in_progress|done|cancelled), source, createdAt, updatedAt, closedAt`.
152
+ Each TODO carries `id, text, project, tags, priority (low|med|high|critical), status (open|in_progress|parked|done|cancelled), source, createdAt, updatedAt, closedAt`.
75
153
 
76
154
  ## How it works
77
155
 
78
- - **Disk store** — `~/.pi/agent/todo.json`, atomic `0600` writes, corrupt-file auto-recovery, `version: 1` schema. Not pi session entries, so it outlives any conversation.
79
- - **`todo` tool** — model CRUD (above).
156
+ - **Disk store** — `~/.pi/agent/todo/` folder: `todo.json` (live: active + parked), `todo-archive.json` (sealed: done + cancelled), `todo.config.json` (prune ages + health thresholds). Atomic `0600` writes, corrupt-file auto-recovery, `version: 2` schema. Not pi session entries, so it outlives any conversation.
157
+ - **`todo` tool** — model CRUD + lifecycle (above).
80
158
  - **`/todo` command** — human triage (above).
81
- - **Auto-inject** — on every `before_agent_start`, a compact `## Open TODOs (N)` block (titles + ids, capped at 15, sorted by priority) is appended to the system prompt, so the agent starts every turn already aware of pending work. Mutations refresh it on the next turn.
159
+ - **Auto-inject** — on every `before_agent_start`, a compact `## Open TODOs (N)` block (titles + ids, capped at 15, sorted by priority) is appended to the system prompt, so the agent starts every turn already aware of pending work. Only `open` + `in_progress` are injected — `parked` and archived todos are excluded (the lifecycle-box boundary). Mutations refresh it on the next turn.
160
+ - **Archive query** — `list` with `archived:true` is summary-first (counts by project + month) then filtered/paginated on demand, so a large archive never bloats a single query.
82
161
 
83
- Full design + decisions: [`docs/todo-SPEC.md`](docs/todo-SPEC.md).
162
+ Full design + decisions: [`docs/superpowers/specs/2026-07-20-lifecycle-boxes-prune-design.md`](docs/superpowers/specs/2026-07-20-lifecycle-boxes-prune-design.md). Original v0.1.0 spec: [`docs/todo-SPEC.md`](docs/todo-SPEC.md).
84
163
 
85
164
  ## Configuration
86
165
 
87
166
  | env var | default | purpose |
88
167
  |---|---|---|
89
- | `TODO_STORE_PATH` | `~/.pi/agent/todo.json` | override the store location (tests / multiple profiles) |
168
+ | `TODO_DIR` | `~/.pi/agent/todo/` | override the store folder (tests / multiple profiles) |
90
169
 
91
- Run the store tests: `npm test` (24/24).
170
+ Run the store tests: `npm test` (147/147 across 7 suites).
92
171
 
93
172
  ## Security
94
173