@getpipher/armory-todo 0.5.4 → 0.5.5
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 +17 -0
- package/extensions/todo.ts +23 -11
- package/package.json +1 -1
- package/src/config.ts +14 -0
package/README.md
CHANGED
|
@@ -221,6 +221,23 @@ Full design + decisions:
|
|
|
221
221
|
|---|---|---|
|
|
222
222
|
| `TODO_DIR` | `~/.pi/agent/todo/` | override the store folder (tests / multiple profiles) |
|
|
223
223
|
|
|
224
|
+
`todo.config.json` (in `TODO_DIR`) holds prune ages, health thresholds, and notify toggles. All values are optional — missing fields are merged with defaults on load.
|
|
225
|
+
|
|
226
|
+
```jsonc
|
|
227
|
+
{
|
|
228
|
+
"version": 1,
|
|
229
|
+
"prune": { "defaultAgeDays": 7, "hardAgeDays": 180, "statuses": ["done", "cancelled"] },
|
|
230
|
+
"health": { "activeMaxOpen": 15, "activeStaleDays": 30, "parkedMax": 10,
|
|
231
|
+
"parkedStaleDays": 60, "archiveMax": 200, "archiveOldDays": 180,
|
|
232
|
+
"perProjectDefaultMax": 8, "maxNotesBytes": 8192 },
|
|
233
|
+
"notify": { "sessionStartCount": true }
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
| `notify.*` | default | purpose |
|
|
238
|
+
|---|---|---|
|
|
239
|
+
| `sessionStartCount` | `true` | Show the `armory-todo: N open TODOs` startup line. Set `false` to silence it — safety messages (wipe-recovery alert, auto-prune undo info) still surface. |
|
|
240
|
+
|
|
224
241
|
Run the store tests: `npm test` (315/315 across 11 suites).
|
|
225
242
|
|
|
226
243
|
## Known issues
|
package/extensions/todo.ts
CHANGED
|
@@ -39,7 +39,7 @@ import { healthReport } from "../src/health";
|
|
|
39
39
|
import { hardPrune } from "../src/hard-prune";
|
|
40
40
|
import { TodoPanel } from "../src/panel";
|
|
41
41
|
import { autoPruneOnSessionStart } from "../src/auto-prune";
|
|
42
|
-
import { loadConfig } from "../src/config";
|
|
42
|
+
import { loadConfig, type TodoConfig } from "../src/config";
|
|
43
43
|
import { projectsOverview } from "../src/projects";
|
|
44
44
|
import { renameProject } from "../src/registry";
|
|
45
45
|
import { readAndClearWipeAlert } from "../src/backup";
|
|
@@ -90,10 +90,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
90
90
|
} catch {
|
|
91
91
|
// alert optional
|
|
92
92
|
}
|
|
93
|
+
// One config load reused for the prune age + the notify-suppress flag.
|
|
94
|
+
let cfg: TodoConfig | undefined;
|
|
95
|
+
try { cfg = loadConfig(); } catch { /* config optional */ }
|
|
93
96
|
let autoMsg = "";
|
|
94
|
-
let ageDays = 7;
|
|
97
|
+
let ageDays = cfg?.prune.defaultAgeDays ?? 7;
|
|
95
98
|
try {
|
|
96
|
-
ageDays = loadConfig().prune.defaultAgeDays;
|
|
97
99
|
const ap = autoPruneOnSessionStart();
|
|
98
100
|
if (ap) {
|
|
99
101
|
const lines = ap.items.map((i) => ` [${i.id}] ${i.status} ${i.title}`);
|
|
@@ -102,17 +104,27 @@ export default function (pi: ExtensionAPI) {
|
|
|
102
104
|
} catch {
|
|
103
105
|
// auto-prune optional — don't crash the session notify
|
|
104
106
|
}
|
|
107
|
+
const showCount = cfg?.notify?.sessionStartCount !== false;
|
|
105
108
|
const open = listTodos();
|
|
106
|
-
let msg =
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
let msg = "";
|
|
110
|
+
if (showCount) {
|
|
111
|
+
msg = `armory-todo: ${open.length} open TODO${open.length === 1 ? "" : "s"}${autoMsg}`;
|
|
112
|
+
try {
|
|
113
|
+
const report = healthReport();
|
|
114
|
+
if (report.flags.length > 0) {
|
|
115
|
+
msg += `${autoMsg ? "\n" : " — "}` + `⚠ ${report.flags.length} bloat signal${report.flags.length === 1 ? "" : "s"} (run /todo health)`;
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
// health check optional
|
|
111
119
|
}
|
|
112
|
-
}
|
|
113
|
-
//
|
|
120
|
+
} else if (autoMsg) {
|
|
121
|
+
// Count line suppressed; still surface the auto-prune undo info.
|
|
122
|
+
msg = `armory-todo${autoMsg}`;
|
|
123
|
+
}
|
|
124
|
+
if (ctx.hasUI) {
|
|
125
|
+
const out = (wipeMsg ? wipeMsg + "\n" : "") + msg;
|
|
126
|
+
if (out) ctx.ui.notify(out, "info");
|
|
114
127
|
}
|
|
115
|
-
if (ctx.hasUI) ctx.ui.notify((wipeMsg ? wipeMsg + "\n" : "") + msg, "info");
|
|
116
128
|
} catch {
|
|
117
129
|
// store unavailable — never crash the session
|
|
118
130
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpipher/armory-todo",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Global, cross-session TODO for pi \u2014 persists across all sessions and is auto-injected into every prompt. The disk-backed counterpart to branch-scoped pi todo extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
package/src/config.ts
CHANGED
|
@@ -28,10 +28,18 @@ export interface HealthConfig {
|
|
|
28
28
|
maxNotesBytes: number; // v0.5.0: per-todo notes byte cap (hard-reject at add/update)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export interface NotifyConfig {
|
|
32
|
+
/** Show the `armory-todo: N open TODOs` session-start count line.
|
|
33
|
+
* Safety messages (wipe-recovery alert, auto-prune undo info) still surface
|
|
34
|
+
* when this is false. Default true. */
|
|
35
|
+
sessionStartCount: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
export interface TodoConfig {
|
|
32
39
|
version: 1;
|
|
33
40
|
prune: PruneConfig;
|
|
34
41
|
health: HealthConfig;
|
|
42
|
+
notify: NotifyConfig;
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
export const DEFAULT_CONFIG: TodoConfig = {
|
|
@@ -51,6 +59,9 @@ export const DEFAULT_CONFIG: TodoConfig = {
|
|
|
51
59
|
perProjectDefaultMax: 8,
|
|
52
60
|
maxNotesBytes: 8192,
|
|
53
61
|
},
|
|
62
|
+
notify: {
|
|
63
|
+
sessionStartCount: true,
|
|
64
|
+
},
|
|
54
65
|
};
|
|
55
66
|
|
|
56
67
|
/** Deep clone of DEFAULT_CONFIG (so callers can't mutate the constant). */
|
|
@@ -77,10 +88,13 @@ export function loadConfig(): TodoConfig {
|
|
|
77
88
|
if (health.maxNotesBytes === undefined || typeof health.maxNotesBytes !== "number" || Number.isNaN(health.maxNotesBytes) || health.maxNotesBytes < 0) {
|
|
78
89
|
health.maxNotesBytes = DEFAULT_CONFIG.health.maxNotesBytes;
|
|
79
90
|
}
|
|
91
|
+
const notify = { ...DEFAULT_CONFIG.notify, ...(parsed.notify ?? {}) };
|
|
92
|
+
if (typeof notify.sessionStartCount !== "boolean") notify.sessionStartCount = true;
|
|
80
93
|
return {
|
|
81
94
|
version: 1,
|
|
82
95
|
prune: { ...DEFAULT_CONFIG.prune, ...parsed.prune },
|
|
83
96
|
health,
|
|
97
|
+
notify,
|
|
84
98
|
};
|
|
85
99
|
} catch {
|
|
86
100
|
try {
|