@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 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
- ## Title + notes (v0.3.0)
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
- 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).
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 list all done todos (live + archived, recent first)
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` (255/255 across 9 suites).
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
- - **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.
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.0 -->
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.0</text>
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</text>
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</text>
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 -->