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>
34 lines
1.9 KiB
Markdown
34 lines
1.9 KiB
Markdown
---
|
|
id: infra/nudger-a-control-in-the-chat-composer-beside
|
|
title: "Nudger — a control in the chat composer, beside the background-job button"
|
|
theme: infra
|
|
status: open
|
|
created: 2026-08-20
|
|
date_source: stated
|
|
order: 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.
|