the status dot was on the wrong axis
a commander watching its folder perfectly showed AMBER, titled "Armed, not currently running", because green was keyed on `running` — which is an agent TURN in progress, not the loop. so the healthy steady state, which is what a commander is in for weeks at a time, was painted as the failure colour and the owner reasonably concluded nothing was watching. the failure amber was designed for could not happen either: watcherArmed is computed from the live pid, so a dead loop turns it off rather than leaving the pair mismatched. the server now reports `watcherRunning` separately — the loop pid is alive, right now — which is what makes the distinction available at all. green is watching, amber is a row that says armed while its loop is gone, grey is a commander that never watched. and the flow: after arming, do not wait for the backlog. the pipeline was proved on one item, so the rest working is expected rather than news — say it is armed and move to the next question. a failure in the backlog is worth saying; a success is not. then ask what comes next, because a watcher that quietly does one job is a complete answer and the conversation should offer it rather than assume it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
@@ -351,8 +351,12 @@ export function commanderClaudeMd(params: CommanderClaudeMdParams): string {
|
||||
'broken on its first day.',
|
||||
'',
|
||||
'Then how often to look — and offer **as soon as it lands** alongside the intervals, because that is a',
|
||||
'real option here rather than a wish. Categories and dispatching come later still, one at a time, and',
|
||||
'most commanders never need either.',
|
||||
'real option here rather than a wish.',
|
||||
'',
|
||||
'Once it is armed, the conversation is not over: ask what should happen next. Filing what it produces',
|
||||
'into categories, doing something with a result beyond keeping it, or nothing at all — leaving it as a',
|
||||
'watcher that quietly does one job is a complete answer and often the right one. Ask, one at a time,',
|
||||
'rather than deciding for them that there is nothing more to discuss.',
|
||||
'',
|
||||
'**Never arm a watcher before the owner has agreed what it does.** Arming ahead of that is arming a',
|
||||
'guess, and a wrong condition either never fires or fires constantly — either way it is found out days',
|
||||
@@ -367,6 +371,14 @@ export function commanderClaudeMd(params: CommanderClaudeMdParams): string {
|
||||
'knows how to handle items it has not seen — that is the whole of what a watcher is — so handing it the',
|
||||
'backlog costs nothing and hands the owner a running commander in the time one item takes.',
|
||||
'',
|
||||
'**Then keep talking. Do not wait for the backlog to finish.** You proved the pipeline on one item, so',
|
||||
'the rest working is expected rather than news — say it is armed and move straight to the next',
|
||||
'question. No sleeping, no polling a log, no "I will confirm once it is done". The owner does not need a',
|
||||
'progress report on work they already know succeeds.',
|
||||
'',
|
||||
'If something DOES go wrong in the backlog, that is worth saying — in the conversation if it is still',
|
||||
'open, or as a notification if it is not. A failure is news. A success is not.',
|
||||
'',
|
||||
'Once the job is settled, write it into this file, replacing this section: what you watch for, what you',
|
||||
'do about it, and which numbers were guesses. The next session should read the answer, not the',
|
||||
'questions.',
|
||||
|
||||
@@ -274,6 +274,9 @@ commandHqRouter.get('/commanders', async (ctx) => {
|
||||
// on `dirName`, not the transcript id: the pid file lives in this commander's OWN `state/`, not
|
||||
// beside the transcript.
|
||||
watcherArmed: row.watcherArmed || liveLoopPid(who.email, row.dirName) !== null,
|
||||
// Whether the LOOP is alive right now, separate from `running` (an agent turn in progress) and from
|
||||
// `watcherArmed` (which is also true for a row that says armed but whose loop has gone).
|
||||
watcherRunning: liveLoopPid(who.email, row.dirName) !== null,
|
||||
watcherArmedAt: row.watcherArmedAt,
|
||||
watcherStoppedAt: row.watcherStoppedAt,
|
||||
watcherLastFiredAt: lastFiredByRow.get(row.id) ?? null,
|
||||
@@ -457,6 +460,7 @@ commandHqRouter.get('/commanders/:sessionId', async (ctx) => {
|
||||
tagIds: tagsByRow.get(row.id) ?? [],
|
||||
running,
|
||||
watcherArmed: row.watcherArmed || liveLoopPid(who.email, row.dirName) !== null,
|
||||
watcherRunning: liveLoopPid(who.email, row.dirName) !== null,
|
||||
watcherArmedAt: row.watcherArmedAt,
|
||||
watcherStoppedAt: row.watcherStoppedAt,
|
||||
watcherLastFiredAt: lastFiredByRow.get(row.id) ?? null,
|
||||
|
||||
Reference in New Issue
Block a user