diff --git a/TODO.md b/TODO.md index 3585b647..eeee0b30 100644 --- a/TODO.md +++ b/TODO.md @@ -705,6 +705,32 @@ outside the example's new README: auto-loads `.env` into every PM2 process, so each one is readable from `/proc//environ` of twenty processes that have no business with it. +- [ ] **A self-nudge 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. + + **Two things the platform genuinely lacks**, and they are the work: + + 1. **A recurring trigger.** The queue has retries and delays but nothing periodic, and + `queue/handlers/index.ts` is empty. `officer-notify` is now a natural home for "fire this + later" — it already runs as core and already fans out on a schedule-free signal. + 2. **A way to put a prompt into a live session.** `pushTurn` has exactly ONE caller, the chat + websocket handler. Anything server-side that wants to speak to a session has no door. + + 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. + ## Backburner - [ ] **Four foreign keys are over Postgres's 63-character limit and re-create on every `db:push`.**