202288784c
The vendored upstream example exposes list/add/toggle/clear and no way to change an item's text. On a long-lived list that leaves two bad options: add a "patch" item that describes a DIFFERENT item, or clear and re-add everything. Both were hit for real on 2026-08-17 while tracking a 17-item fleet plan -- the list ended up with #18 correcting #17, which reads as nonsense in a sidebar that truncates each item to a few words. edit takes id + text, replaces the text, and KEEPS the id and the done status. Id stability is the point: ids are the only handle the palace snapshot of a plan can refer to, so a correction must not renumber anything. nextId is untouched. Error branches match the existing style: distinct messages for a missing id, a missing text, and an unknown id, each returning the full todos array in details so state stays consistent. No pi-atelier change needed. Its tool_result hook only checks that details.todos is a well-shaped array and ignores the action string, so the new action flows through its normalizer and sidebar untouched. Note renderResult's switch has no default case, so an action without a render arm returns undefined; edit adds one. The file is a verbatim vendored copy of upstream's example, so divergence has a cost: the header now carries a numbered LOCAL DELTAS list (the earlier ctx.mode -> ctx.hasUI API fix, and this) to keep reconciling a future upstream version mechanical. Worth offering upstream as a PR -- the example is arguably incomplete without it. Verified live in-container by pointing ~/.pi/agent/extensions/todo.ts at this copy for one session: edit on an unknown id and with no text both error as intended, and editing a completed item preserved both its id and its done state. Symlink since reverted to the image copy.