diff --git a/src/servers/api/command-hq/commander-block.ts b/src/servers/api/command-hq/commander-block.ts index 022ffefb..44d5eafb 100644 --- a/src/servers/api/command-hq/commander-block.ts +++ b/src/servers/api/command-hq/commander-block.ts @@ -51,10 +51,12 @@ function accountFromCommandersCwd(cwd: string): string | null { * The block, or null when this session is not a commander. * * **A brand-new commander's FIRST turn gets no block**, because there is no transcript id yet — the harness - * mints it as that turn begins, and nothing can be told a path keyed on an id that does not exist. In - * practice the first turn is the conversation about what to watch, and the loop is started on a later one, - * by which point every turn carries it. Worth knowing rather than discovering: a commander that somehow - * armed itself on its very first message would not have been told where to record. + * mints it as that turn begins, and nothing can be told a path keyed on an id that does not exist. + * + * That is not a gap, because arming on the first turn is not permitted: the first turn is for agreeing what + * to watch, and a watcher armed before that agreement is a guess. So the two facts interlock rather than + * conflict — an agent with no paths is by definition on its first turn, which is the turn it must not arm on + * anyway. The block says so explicitly, so the absence reads as a signal rather than as something missing. * * Keyed on the cwd rather than a database lookup, and deliberately: `isCommandersDir` is the same test the * sessions list, `/chat/live` and the detail route all use, so a session cannot be a commander in one place @@ -80,5 +82,10 @@ export function commanderBlock(params: CommanderBlockParams): string | null { '', 'The platform cannot find your process and cannot recover a spawned agent id after it exits, so this', 'record is the only one. Without it, deleting this commander leaves your loop running.', + '', + '**Never arm a watcher on your first turn.** The first turn is for settling what to watch and what to do', + 'about it — arming before that is arming a guess, and a wrong condition either never fires or fires', + 'constantly and is found out days later. If you were given no paths above, you ARE on your first turn:', + 'that is what their absence means. Ask, and arm once it is agreed.', ].join('\n'); }