todo: a self-nudge control in the chat composer

wanted while leaving an agent to work overnight — "continue every hour if you
have stalled", beside the background-job button.

tonight's script does it from outside, polling the sessions api and speaking
over the chat websocket exactly as a browser does, which is why the platform
needed no changes. that is the workaround; this is the feature.

records the two things the platform actually lacks — a recurring trigger, and
any door into a live session that is not the chat websocket — and the three
design notes that are easy to get wrong: never speak while isGenerating, the
schedule cannot be owned by the session it nudges (a chat background job dies
with its session, taking the watchdog with the agent), and bound the loop.

the same trigger is what the watcher-loop proposal in COMMS has been waiting
for, so it is one piece of infrastructure serving two asks.
This commit is contained in:
2026-08-20 03:02:10 +00:00
parent adb77882b6
commit 10e30754f3
+26
View File
@@ -705,6 +705,32 @@ outside the example's new README:
auto-loads `.env` into every PM2 process, so each one is readable from `/proc/<pid>/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`.**