Uni system · down and back up
How work moves
Work goes down: Aaron to #Uni, #Uni to the room that owns it, the room to a Claude Code worker. Results come back up the same chain. The way down is solid today. The way back up still leans on a watch job that checks every 30 minutes, which the hooks project replaces.
Today
- #Uni routes. #Uni is a router, not a builder. When Aaron asks for something that has a home, #Uni wakes that room with his words, the source and the deliverable, and says in one line where it went.
- The room owns the job. It writes a brief (outcome, context, boundaries, what counts as done), records a run note on the task, and starts a Claude Code worker as a background service. It checks within minutes that the worker is really running.
- The worker builds. It reads only the brief and its own instructions; Aaron's private context reaches it only through the brief. It tests, commits, asks Codex for an independent review when the brief says so, and ends with a report: status, summary, artifacts, checks, open items.
- A watch job notices the finish. Each worker gets a scheduled watch job that stays silent while it runs and, once it has finished, reads the result and posts it. This is the stopgap the hooks replace.
- The room closes the loop. It checks the work, tells Aaron what he needs, and writes
[done T-NN]. The relay plugin's hook marks the task done, closes the run note and wakes whoever asked.
Technical detail: today's moving parts
relay_wake(in the relay plugin) places[relay from #Uni] …in the target room's session, and records the hand-off with a 45-minute stall timer.- A run note is a vault note per worker run, with the task, the room and
state: running. - Launch: Claude Code in headless mode (
claude -p "Do the task in the brief") on Claude Opus 5.5 at high effort, as a background service with its own log. The rules for it are in Hermes's operating file and a written skill. - Watch jobs are Hermes scheduled jobs: every 30 minutes, for a limited number of runs, reporting to the room that made them.
- A plain
[done]reaches #Uni only if #Uni started or handed out the work; otherwise it hears through the digest. - The four gaps are from a written survey of today's flow that found ten in all, each traced to a line of code.
After the hooks
The design gives every worker exactly one "finished" event, written the moment it stops, and delivers that event to the room that launched it until the room confirms it. No watch jobs, no polling turns, and a failed launch is reported like any other finish.
| Question | Today | After the hooks |
|---|---|---|
| Who notices a finish? | A watch job, every 30 minutes, set up by hand per worker | The worker's own exit, at once |
| A launch that fails at once? | Looks like silence until the next check | A "failed to start" event, like any finish |
| What reaches the room? | Whatever the watch job's model turn writes | A fixed event with a status, and the worker's report as data |
| Lost or doubled news? | Possible: the wake queue can drop or repeat a line | Delivered until the room confirms; repeats are skipped |
| Cost of waiting | A model turn per check | No model turns until there is news |
Technical detail: the design
- The design went through four revisions and three independent Codex reviews before Aaron approved the build on 18 Oct 2026.
- One small record file per run, each with its own lock. The worker learns its run's identity from an environment variable; the hooks are passed to that run only, not added to Claude Code's global settings.
- The finish step is attached to the worker's service as a stop action (systemd's
ExecStopPost), so it runs however the process ends. Reconcile is a 5-minute timer. - The new events use a new queue file, so the old drainer never sees them. Rollout is behind switches: off, record, notify.
- Stage 1 is judged by a health check: does every worker exit have a record whose status matches what the service manager saw?
- Status on 18 Oct 2026: stages 0 and 1 are built, tested and live in record-only mode. Nothing wakes rooms yet.