@getpipher/armory-todo 0.2.0 → 0.3.1
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 +32 -9
- package/docs/superpowers/plans/2026-07-21-auto-prune-done-view.md +893 -0
- package/docs/superpowers/plans/2026-07-21-title-notes-split.md +1586 -0
- package/docs/superpowers/specs/2026-07-21-auto-prune-done-view-design.md +217 -0
- package/docs/superpowers/specs/2026-07-21-title-notes-split-design.md +411 -0
- package/docs/todo-SPEC.md +5 -0
- package/extensions/todo.ts +116 -34
- package/package.json +2 -2
- package/src/archive.ts +68 -6
- package/src/auto-prune.ts +15 -0
- package/src/health.ts +17 -1
- package/src/migrate.ts +110 -1
- package/src/panel-data.ts +26 -15
- package/src/panel.ts +67 -13
- package/src/todo-store.ts +43 -21
package/README.md
CHANGED
|
@@ -55,6 +55,13 @@ TODOs live in one of three states, only one of which hits the agent context:
|
|
|
55
55
|
todos from the live file to `todo-archive.json` — nothing is deleted. `prune --all`
|
|
56
56
|
ignores age. `restore <id>` brings an archived todo back as `open`.
|
|
57
57
|
|
|
58
|
+
**Auto-prune (v0.3.1):** on every `session_start`, done/cancelled todos older
|
|
59
|
+
than `config.prune.defaultAgeDays` (default 7d) archive *themselves* — no need
|
|
60
|
+
to run `prune` manually. Fresh done (<7d) stays in live. The startup notify
|
|
61
|
+
reports what moved (`auto-pruned N stale done (>7d): …` + a `restore` hint);
|
|
62
|
+
it's a transient message, not a prompt injection. Reversible via `restore <id>`.
|
|
63
|
+
`prune --all` (move fresh done too) and `prune --hard` (irreversible) stay manual.
|
|
64
|
+
|
|
58
65
|
The only irreversible action is `prune --hard` (hard-prune) — it requires an
|
|
59
66
|
explicit `confirm: true` and is always user-confirmed. See **Self-awareness**
|
|
60
67
|
below.
|
|
@@ -92,14 +99,20 @@ todos. It's gated three ways:
|
|
|
92
99
|
Everything else in armory-todo is reversible. `prune --hard` is the one
|
|
93
100
|
irreversible escape hatch, always user-confirmed.
|
|
94
101
|
|
|
102
|
+
## Title + notes (v0.3.0)
|
|
103
|
+
|
|
104
|
+
The single `text` field is split into **`title`** (≤120 chars, one-line summary — the only thing injected into the prompt or shown in compact lists) and **`notes`** (any length, the running detail/log — never auto-injected). A hard cap rejects `title` >120 chars at `add`/`update` so the junk-drawer pattern can't re-form. `list` shows titles + a `•` marker when notes exist; `get <id>` reads a todo's full notes before acting on it. v2 `text`-only stores migrate on first load (curated for the 2 known todos + a first-line fallback).
|
|
105
|
+
|
|
95
106
|
## Interactive panel (SPEC-3)
|
|
96
107
|
|
|
97
108
|
Run `/todo` (no arg) in a TUI session to open the interactive triage panel:
|
|
98
109
|
|
|
99
|
-
- **Box tabs** (Tab / Shift+Tab): Active · Parked · Archive · Config
|
|
110
|
+
- **Box tabs** (Tab / Shift+Tab): Active · Parked · **Done** · Archive · Config
|
|
100
111
|
- **Filter input**: type to search by text (live filter)
|
|
101
112
|
- **SelectList**: arrow keys navigate, Enter selects
|
|
102
|
-
- **Action submenu** (on Enter): Complete / Park / Re-activate / Restore / Edit
|
|
113
|
+
- **Action submenu** (on Enter): View detail / Complete / Park / Re-activate / Restore / Edit title / Delete
|
|
114
|
+
- **Done tab** (v0.3.1): all finished work (`status: done`) unified across live + archive, location-tagged (`[live Nd]` / `[archived YYYY-MM-DD]`), filterable; Enter → View detail, or Restore-from-archive. Excludes `cancelled` (that's in the Archive tab).
|
|
115
|
+
- **Detail view** (View detail, or Enter on a row): renders the title + full `notes` read-only, with a footer hint on editing notes via the `todo` tool
|
|
103
116
|
- **Archive box**: summary-first (counts by project + month) → Enter on a bucket to drill down
|
|
104
117
|
- **Config box**: SettingsList with prune ages + health thresholds — edit live, persists to `todo.config.json`
|
|
105
118
|
- **Escape**: exit the panel
|
|
@@ -120,7 +133,8 @@ Typed subcommands (`/todo park <id>`, `/todo prune`, etc.) all still work alongs
|
|
|
120
133
|
```
|
|
121
134
|
/todo list open + in-progress TODOs
|
|
122
135
|
/todo all include parked/done/cancelled
|
|
123
|
-
/todo add <
|
|
136
|
+
/todo add <title> quick add (priority: med; notes via the todo tool)
|
|
137
|
+
/todo finished list all done todos (live + archived, recent first)
|
|
124
138
|
/todo done <id> mark done
|
|
125
139
|
/todo rm <id> cancel (tombstone)
|
|
126
140
|
/todo park <id> defer (parked — not injected, recoverable)
|
|
@@ -138,8 +152,9 @@ Typed subcommands (`/todo park <id>`, `/todo prune`, etc.) all still work alongs
|
|
|
138
152
|
| action | params | effect |
|
|
139
153
|
|---|---|---|
|
|
140
154
|
| `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 |
|
|
141
|
-
| `add` | `
|
|
142
|
-
| `
|
|
155
|
+
| `add` | `title`, `notes?`, `project?`, `tags?`, `priority?`, `source?` | create a TODO (`title` ≤120 chars; long detail goes in `notes`) |
|
|
156
|
+
| `get` | `id` | read a TODO's full record incl. `notes` |
|
|
157
|
+
| `update` | `id`, `title?`, `notes?`, `priority?`, `status?`, `project?`, `tags?` | edit a TODO (set `status: parked` to defer; `notes=""` clears) |
|
|
143
158
|
| `complete` | `id` | mark done |
|
|
144
159
|
| `delete` | `id` | cancel (tombstone) |
|
|
145
160
|
| `park` | `id` | defer (parked — not injected) |
|
|
@@ -149,17 +164,20 @@ Typed subcommands (`/todo park <id>`, `/todo prune`, etc.) all still work alongs
|
|
|
149
164
|
| `prune` (hard) | `hard:true`, `confirm:true`, `box?`, `olderThan?`, `project?`, `tag?` | PERMANENT deletion — the only irreversible action |
|
|
150
165
|
| `clear` | `status?` (default `done`) | bulk-clear a status (deprecated — use prune) |
|
|
151
166
|
|
|
152
|
-
Each TODO carries `id,
|
|
167
|
+
Each TODO carries `id, title (≤120 chars), notes (any length), project, tags, priority (low|med|high|critical), status (open|in_progress|parked|done|cancelled), source, createdAt, updatedAt, closedAt`. The auto-injected block + list/panel show `title` only; `notes` is read via `get` and never injected.
|
|
153
168
|
|
|
154
169
|
## How it works
|
|
155
170
|
|
|
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:
|
|
171
|
+
- **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: 3` schema (`title` ≤120 chars + `notes` any length; v2 `text`-only stores migrate to v3 on first load). Not pi session entries, so it outlives any conversation.
|
|
157
172
|
- **`todo` tool** — model CRUD + lifecycle (above).
|
|
158
173
|
- **`/todo` command** — human triage (above).
|
|
159
174
|
- **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
175
|
- **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.
|
|
161
176
|
|
|
162
|
-
Full design + decisions:
|
|
177
|
+
Full design + decisions:
|
|
178
|
+
- v0.3.0 (title + notes split): [`docs/superpowers/specs/2026-07-21-title-notes-split-design.md`](docs/superpowers/specs/2026-07-21-title-notes-split-design.md)
|
|
179
|
+
- v0.2.0 (lifecycle boxes + prune + health): [`docs/superpowers/specs/2026-07-20-lifecycle-boxes-prune-design.md`](docs/superpowers/specs/2026-07-20-lifecycle-boxes-prune-design.md)
|
|
180
|
+
- Original v0.1.0 spec: [`docs/todo-SPEC.md`](docs/todo-SPEC.md)
|
|
163
181
|
|
|
164
182
|
## Configuration
|
|
165
183
|
|
|
@@ -167,7 +185,12 @@ Full design + decisions: [`docs/superpowers/specs/2026-07-20-lifecycle-boxes-pru
|
|
|
167
185
|
|---|---|---|
|
|
168
186
|
| `TODO_DIR` | `~/.pi/agent/todo/` | override the store folder (tests / multiple profiles) |
|
|
169
187
|
|
|
170
|
-
Run the store tests: `npm test` (
|
|
188
|
+
Run the store tests: `npm test` (255/255 across 9 suites).
|
|
189
|
+
|
|
190
|
+
## Known issues
|
|
191
|
+
|
|
192
|
+
- **No in-panel multi-line `notes` editing.** The panel's inline Edit is single-line (`Input`) for `title` only; `ctx.ui.editor()` from inside `ctx.ui.custom()` triggers a nested-UI bug (`/todo` won't reopen). `notes` is model-managed via the `todo` tool (`action: update, id, notes`). When a safe `ctx.ui.editor()`-from-`custom()` pattern lands in pi-tui, in-panel notes editing is a clean follow-up.
|
|
193
|
+
- **Preventive caps-on-add** (notes length cap + project registry) are deferred to Workstream C (v0.4.0). Until then, `health` reports notes-bytes as a read-only diagnostic.
|
|
171
194
|
|
|
172
195
|
## Security
|
|
173
196
|
|