@getpipher/armory-todo 0.3.1 → 0.4.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 +20 -7
- package/assets/hero.svg +4 -4
- package/docs/superpowers/plans/2026-07-21-project-scope-management.md +1537 -0
- package/docs/superpowers/specs/2026-07-21-auto-prune-done-view-design.md +1 -1
- package/docs/superpowers/specs/2026-07-21-project-scope-management-design.md +319 -0
- package/extensions/todo.ts +59 -2
- package/package.json +2 -2
- package/src/config.ts +5 -1
- package/src/health.ts +60 -2
- package/src/levenshtein.ts +22 -0
- package/src/panel-data.ts +31 -0
- package/src/panel.ts +98 -6
- package/src/paths.ts +5 -0
- package/src/projects.ts +91 -0
- package/src/registry.ts +175 -0
package/README.md
CHANGED
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
<img src="https://img.shields.io/badge/dependencies-0-9aa7a1" alt="no dependencies">
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
|
+
<p align="center">
|
|
19
|
+
<strong>lifecycle boxes</strong> · <strong>title + notes</strong> · <strong>auto-prune</strong> · <strong>interactive panel</strong> · <strong>health diagnostics</strong> · <strong>hard-prune gate</strong>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
18
22
|
---
|
|
19
23
|
|
|
20
24
|
## The problem
|
|
@@ -99,21 +103,28 @@ todos. It's gated three ways:
|
|
|
99
103
|
Everything else in armory-todo is reversible. `prune --hard` is the one
|
|
100
104
|
irreversible escape hatch, always user-confirmed.
|
|
101
105
|
|
|
102
|
-
##
|
|
106
|
+
## Project-scope management (v0.4.0)
|
|
107
|
+
|
|
108
|
+
A project registry (`~/.pi/agent/todo/projects.json`, lazy-synced on read) tracks known projects + an advisory per-project **`maxOpen`** cap slot. The `todo` tool gains two actions: **`projects`** (per-project scope overview — open/in_progress/parked/done counts + `maxOpen` + `OVER`/`?typo` markers + last-updated) and **`project_rename`** (rename or merge a project; rewrites live + archive + registry — the typo-cleanup path, e.g. `getpither` → `getpipher`).
|
|
109
|
+
|
|
110
|
+
`health` gains four per-project flags: **`PROJECT_OVER`** (open > a project's `maxOpen` slot), **`PROJECT_LARGE`** (open > `health.perProjectDefaultMax`, default 8 — fires out-of-the-box, no per-project config needed), **`PROJECT_STALE`** (project untouched > `activeStaleDays`), **`PROJECT_TYPO`** (1-todo project with a near-named sibling, Levenshtein ≤ 2). The `/todo health` report + the `todo` `health` action both show a `projects:` section.
|
|
111
|
+
|
|
112
|
+
The interactive `/todo` panel gains a 6th tab — **Projects** — listing the overview rows + a `(no project)` summary, with an action submenu per project: **Rename / merge** (inline input), **Set maxOpen** (number or `clear`), **Filter active to project** (jump to the Active tab scoped). A thin `/todo projects` slash mirrors the overview as text.
|
|
103
113
|
|
|
104
|
-
|
|
114
|
+
**Advisory only in v0.4.0** — `maxOpen` drives a `health` flag, it does **not** block `add` (enforcement graduates in v0.5.0, alongside count + notes caps + over-cap injection truncation).
|
|
105
115
|
|
|
106
116
|
## Interactive panel (SPEC-3)
|
|
107
117
|
|
|
108
118
|
Run `/todo` (no arg) in a TUI session to open the interactive triage panel:
|
|
109
119
|
|
|
110
|
-
- **Box tabs** (Tab / Shift+Tab): Active · Parked · **Done** · Archive · Config
|
|
120
|
+
- **Box tabs** (Tab / Shift+Tab): Active · Parked · **Done** · Archive · **Projects** · Config
|
|
111
121
|
- **Filter input**: type to search by text (live filter)
|
|
112
122
|
- **SelectList**: arrow keys navigate, Enter selects
|
|
113
123
|
- **Action submenu** (on Enter): View detail / Complete / Park / Re-activate / Restore / Edit title / Delete
|
|
114
124
|
- **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
125
|
- **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
|
|
116
126
|
- **Archive box**: summary-first (counts by project + month) → Enter on a bucket to drill down
|
|
127
|
+
- **Projects tab** (v0.4.0): per-project scope overview (open/in_progress/parked/done counts + `maxOpen` + `OVER`/`?typo` markers) + a `(no project)` summary row; Enter on a project → action submenu: Rename / merge · Set maxOpen · Filter active to project.
|
|
117
128
|
- **Config box**: SettingsList with prune ages + health thresholds — edit live, persists to `todo.config.json`
|
|
118
129
|
- **Escape**: exit the panel
|
|
119
130
|
|
|
@@ -134,7 +145,7 @@ Typed subcommands (`/todo park <id>`, `/todo prune`, etc.) all still work alongs
|
|
|
134
145
|
/todo list open + in-progress TODOs
|
|
135
146
|
/todo all include parked/done/cancelled
|
|
136
147
|
/todo add <title> quick add (priority: med; notes via the todo tool)
|
|
137
|
-
/todo finished
|
|
148
|
+
/todo finished list all done todos (live + archived, recent first)
|
|
138
149
|
/todo done <id> mark done
|
|
139
150
|
/todo rm <id> cancel (tombstone)
|
|
140
151
|
/todo park <id> defer (parked — not injected, recoverable)
|
|
@@ -168,13 +179,15 @@ Each TODO carries `id, title (≤120 chars), notes (any length), project, tags,
|
|
|
168
179
|
|
|
169
180
|
## How it works
|
|
170
181
|
|
|
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.
|
|
182
|
+
- **Disk store** — `~/.pi/agent/todo/` folder: `todo.json` (live: active + parked), `todo-archive.json` (sealed: done + cancelled), `todo.config.json` (prune ages + health thresholds), `projects.json` (project registry: canonical names + advisory `maxOpen` slots, v0.4.0). Atomic `0600` writes, corrupt-file auto-recovery, `version: 3` store 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.
|
|
172
183
|
- **`todo` tool** — model CRUD + lifecycle (above).
|
|
173
184
|
- **`/todo` command** — human triage (above).
|
|
174
185
|
- **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.
|
|
175
186
|
- **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.
|
|
176
187
|
|
|
177
188
|
Full design + decisions:
|
|
189
|
+
- v0.4.0 (project-scope management): [`docs/superpowers/specs/2026-07-21-project-scope-management-design.md`](docs/superpowers/specs/2026-07-21-project-scope-management-design.md)
|
|
190
|
+
- v0.3.1 (auto-prune + unified Done view): [`docs/superpowers/specs/2026-07-21-auto-prune-done-view-design.md`](docs/superpowers/specs/2026-07-21-auto-prune-done-view-design.md)
|
|
178
191
|
- 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
192
|
- 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
193
|
- Original v0.1.0 spec: [`docs/todo-SPEC.md`](docs/todo-SPEC.md)
|
|
@@ -185,12 +198,12 @@ Full design + decisions:
|
|
|
185
198
|
|---|---|---|
|
|
186
199
|
| `TODO_DIR` | `~/.pi/agent/todo/` | override the store folder (tests / multiple profiles) |
|
|
187
200
|
|
|
188
|
-
Run the store tests: `npm test` (
|
|
201
|
+
Run the store tests: `npm test` (315/315 across 11 suites).
|
|
189
202
|
|
|
190
203
|
## Known issues
|
|
191
204
|
|
|
192
205
|
- **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
|
-
- **
|
|
206
|
+
- **No caps enforcement yet (count / notes / injection).** v0.4.0's `maxOpen` slot is advisory only (drives a `health` flag); block-on-add for count + notes caps + over-cap injection truncation land in v0.5.0. Until then, `health` reports counts + notes-bytes as read-only diagnostics.
|
|
194
207
|
|
|
195
208
|
## Security
|
|
196
209
|
|
package/assets/hero.svg
CHANGED
|
@@ -103,11 +103,11 @@
|
|
|
103
103
|
<path d="M14,8 L14,18 M11,8 L17,8 M11,18 L17,18" fill="none" stroke="#8a9791" stroke-width="1.4" stroke-linecap="round"/>
|
|
104
104
|
<text x="27" y="17.5" fill="#c2cfc9" letter-spacing="0.4">MIT</text>
|
|
105
105
|
</g>
|
|
106
|
-
<!-- v0.1
|
|
106
|
+
<!-- v0.3.1 -->
|
|
107
107
|
<g transform="translate(234, 0)">
|
|
108
108
|
<rect x="0" y="0" rx="13" ry="13" width="98" height="26" fill="#10171a" stroke="#3a4a44" stroke-width="1"/>
|
|
109
109
|
<path d="M14,9 L14,17 M14,9 L11,12 M14,9 L17,12" fill="none" stroke="#8a9791" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
110
|
-
<text x="27" y="17.5" fill="#c2cfc9" letter-spacing="0.4">v0.1
|
|
110
|
+
<text x="27" y="17.5" fill="#c2cfc9" letter-spacing="0.4">v0.3.1</text>
|
|
111
111
|
</g>
|
|
112
112
|
<!-- no dependencies -->
|
|
113
113
|
<g transform="translate(342, 0)">
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
<rect x="0" y="0" rx="6" ry="6" width="40" height="20" fill="#3a2a0e" stroke="#fbbf24" stroke-width="1"/>
|
|
153
153
|
<text x="20" y="14.5" font-size="11" font-weight="700" fill="#fcd34d" text-anchor="middle" letter-spacing="0.4">high</text>
|
|
154
154
|
<text x="52" y="14.5" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="12" fill="#b8c4be">[td-…m6pjxhj]</text>
|
|
155
|
-
<text x="184" y="14.5" font-size="13" fill="#f4f7f4">⏵ Decouple global rules → AGENTS.md
|
|
155
|
+
<text x="184" y="14.5" font-size="13" fill="#f4f7f4">⏵ Decouple global rules → AGENTS.md •</text>
|
|
156
156
|
<rect x="408" y="2" rx="8" ry="8" width="44" height="16" fill="#13202b" stroke="#2b4250"/>
|
|
157
157
|
<text x="430" y="13.5" font-size="10.5" fill="#a8b5af" text-anchor="middle">(pi)</text>
|
|
158
158
|
</g>
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
<rect x="0" y="0" rx="6" ry="6" width="34" height="20" fill="#0e1f33" stroke="#60a5fa" stroke-width="1"/>
|
|
163
163
|
<text x="17" y="14.5" font-size="11" font-weight="700" fill="#93c5fd" text-anchor="middle" letter-spacing="0.4">med</text>
|
|
164
164
|
<text x="46" y="14.5" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="12" fill="#b8c4be">[td-…mzr0qs9]</text>
|
|
165
|
-
<text x="178" y="14.5" font-size="13" fill="#f4f7f4">Research browser-use vs Chrome MCP
|
|
165
|
+
<text x="178" y="14.5" font-size="13" fill="#f4f7f4">Research browser-use vs Chrome MCP •</text>
|
|
166
166
|
</g>
|
|
167
167
|
|
|
168
168
|
<!-- row 3: low -->
|