Context
maxNotesBytes (default 8192) is intentional bloat-prevention — notes auto-inject into every pi prompt as the ## Open TODOs (N) block, so unbounded notes = unbounded context cost (see #1). The cap + the hard-reject at src/caps.ts:34 / src/todo-store.ts:205,276 are correct for human-written notes.
The gap is for programmatic callers. The hard-fail + the message "notes 8.2KB > max 8.0KB (maxNotesBytes 8192) — trim the detail or split into multiple todos" is human-oriented: a programmatic caller (e.g. @getpipher/armory-fleet subagent tool, src/todo-sync/adapter.ts:57) can neither "trim the detail" on the fly nor "split into multiple todos" for a single dispatch. It just fails — and in the armory-fleet case, the failure cancels the whole subagent dispatch (see getpipher/armory-fleet#34).
Proposal (defensive DX, not a cap change)
Keep maxNotesBytes + the hard-reject for the human /todo + todo tool surface. For programmatic callers, add ONE of:
- An opt-in
truncateNotes flag on addTodo/updateTodo — when set, notes are truncated to maxNotesBytes (with a …[truncated] marker) instead of rejected. The caller explicitly accepts truncation. Default unchanged (hard-reject).
- A
notesSummary field distinct from notes — programmatic callers write a short summary (always under cap) into notes; the full body lives elsewhere (run-log, report file). This matches how armory-fleet SHOULD use it (tracking stub, not transcript).
- A programmatic-callers README section documenting the cap + the recommended pattern (keep
notes < ~1 KB; store the full body out-of-band). Cheapest; no API change.
My lean: (1) is the smallest change that unblocks armory-fleet without a design conversation; (3) is a free win regardless. (2) is the cleanest model but a bigger API change.
Cross-ref
Context
maxNotesBytes(default 8192) is intentional bloat-prevention — notes auto-inject into every pi prompt as the## Open TODOs (N)block, so unbounded notes = unbounded context cost (see #1). The cap + the hard-reject atsrc/caps.ts:34/src/todo-store.ts:205,276are correct for human-written notes.The gap is for programmatic callers. The hard-fail + the message
"notes 8.2KB > max 8.0KB (maxNotesBytes 8192) — trim the detail or split into multiple todos"is human-oriented: a programmatic caller (e.g.@getpipher/armory-fleetsubagent tool,src/todo-sync/adapter.ts:57) can neither "trim the detail" on the fly nor "split into multiple todos" for a single dispatch. It just fails — and in the armory-fleet case, the failure cancels the whole subagent dispatch (see getpipher/armory-fleet#34).Proposal (defensive DX, not a cap change)
Keep
maxNotesBytes+ the hard-reject for the human/todo+todotool surface. For programmatic callers, add ONE of:truncateNotesflag onaddTodo/updateTodo— when set, notes are truncated tomaxNotesBytes(with a…[truncated]marker) instead of rejected. The caller explicitly accepts truncation. Default unchanged (hard-reject).notesSummaryfield distinct fromnotes— programmatic callers write a short summary (always under cap) intonotes; the full body lives elsewhere (run-log, report file). This matches how armory-fleet SHOULD use it (tracking stub, not transcript).notes< ~1 KB; store the full body out-of-band). Cheapest; no API change.My lean: (1) is the smallest change that unblocks armory-fleet without a design conversation; (3) is a free win regardless. (2) is the cleanest model but a bigger API change.
Cross-ref
track:truedumps the full task intonotes, hits this cap, cancels the dispatch). The fix for #34 (don't store the full task in notes) makes armory-fleet resilient regardless, but a documented/flagged programmatic path would prevent the next integration from hitting the same wall.