a commander never arms on its first turn, and the missing paths are how it knows

The first-turn gap is closed by a rule rather than a mechanism, and the two halves interlock instead of
conflicting.

A commander cannot be told its record paths on the very first turn: the transcript id is minted as that turn
begins, so there is no id to key a path on. That was written up as a limitation. It is not one, because
arming on the first turn is not permissible anyway — the first exchange is for agreeing what to watch and
what to do about it, and a watcher armed before that agreement is armed on a guess. A wrong condition fails
silently in both directions: never fires, or fires constantly, discovered days later.

So the absence became the signal, and the block says so: "If you were given no paths above, you ARE on your
first turn: that is what their absence means." An agent with no paths is on the turn it must not arm on, and
an agent that armed anyway would be unstoppable and undeletable — the same rule reached from the other side.

The rule is in both places on purpose. The block, always loaded, carries the instruction and the interlock in
four lines. The Commanders skill carries why, at length, for the agent that is about to arm one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 17:54:47 +00:00
co-authored by Claude Opus 5
parent 87ff6ed326
commit cabc4825ef
+11 -4
View File
@@ -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');
}