Files
platform/todo/infra/nudger-a-control-in-the-chat-composer-beside.md
pastilhasandClaude Fable 5 6071ded175 todo: one file per item, grouped by theme, with a generated index
TODO.md had reached 1050 lines and 72 open items across 28 sections, read mostly
on a phone. It is now a directory: todo/<theme>/<item>.md, one card per file, with
frontmatter carrying id, status, created date and order, and the prose body copied
across verbatim. TODO.md becomes a generated index (bun run todo:index).

Dates: where an item's prose stated one it is used; otherwise its old section's;
otherwise 2026-08-20, floored at the day before the split rather than invented.
date_source records which.

Shaped for a two-way Kanban board, filed as todo/tooling — a card is a file, id is
the identity, frontmatter is the machine's half and the body is the owner's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 05:42:39 +00:00

1.9 KiB

id, title, theme, status, created, date_source, order
id title theme status created date_source order
infra/nudger-a-control-in-the-chat-composer-beside Nudger — a control in the chat composer, beside the background-job button infra open 2026-08-20 stated 4

Nudger — a control in the chat composer, beside the background-job button. Wanted 2026-08-20 while leaving an agent to work overnight: "continue every hour if you have stalled".

scripts/nudge-agent.ts does it from outside tonight — it polls GET /api/chat/sessions?all=1 and speaks over the chat websocket, exactly as a browser does, so the platform needed no changes. That is the workaround, not the feature.

Both things this said the platform lacked have since been built (verified 2026-08-21): the recurring trigger is startNudger() at server.tsx:182, ticking once a minute over a nudges table; the door into a session is startClaudeTurn({ ws: null }) at nudger.ts:102. What is left is the UI — a control in the chat composer, beside the background-job button — plus generalising delivery beyond the nudger's own schedule. See "Speaking into a session from the backend".

Design notes worth keeping:

  • Never interrupt work. Check isGenerating immediately before speaking. The point is to restart a stopped agent, not to hurry a busy one — the script already gets this right.
  • It must outlive what it nudges. A chat background job is owned by its session, so a nudge job launched from the session being nudged dies with it — the 30-minute idle GC, a clear, or a restart takes the watchdog with the agent. Whatever owns the schedule cannot be the session.
  • Bound it. The script stops after --max (12). A loop nobody is watching should end.
  • The same trigger would serve COMMS/command-hq/watcher-loop-proposal.md, which wants infrastructure to own a loop rather than a model holding a protocol across turns.