commanders: definition versus state, and phase 2 sharing

The directory holds two kinds of thing and they must not mix. The definition —
CLAUDE.md, parameters, procedures, scripts — is what travels. The instance state
— what it has handled, what it spawned, its loop's pid — must never, or a
recipient's commander starts up believing it already handled somebody else's
recordings and silently does nothing.

Structural from the first commit rather than sorted out later, for the same
reason plugin capabilities are read in place: a directory boundary beats a
convention, because a convention is what a tired person violates.

Parameters separate from procedure, too. With a path baked into a script, a fork
is a debugging session; declared in one place, a fork is a conversation — the new
owner is asked where their memos land and the commander rewrites its own file.

Phase 2, recorded and NOT being built: a commander turns itself into a git
repository when asked, in conversation. No button — it git inits, ignores state/
and commits, which is the same shape as everything else here. What it needs to
know goes in the commander SKILL rather than an affordance, because an
affordance's body is charged to every turn of every commander forever and this
earns that approximately never.

Two rules that belong in the design now because both are awkward later. A
credential is definition-shaped — it looks like configuration — so gitignoring
state/ does not protect it; commanders name what must be configured and the
platform holds the value. And a shared commander declares what it requires, or it
lands on an install without a Whisper server, arms cleanly and fails silently at
3am, which is the worst failure this system has.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
2026-08-24 00:49:52 +00:00
co-authored by Claude Opus 5
parent ba64bcd2e6
commit 6d06acc111
+55
View File
@@ -76,6 +76,61 @@ front gets a worse answer than asking later.
watch memos, scans and a mailbox. So this is a list on the row, seeded with one, and the commander writes
additions into its own `CLAUDE.md` as they are agreed.
## What the directory holds: definition versus state
Two kinds of thing live in there and they must not mix, because one of them travels and the other must
never.
```
$DATA_PATH/<email>/commanders/<commander id>/
CLAUDE.md DEFINITION — the living document, extended as the job is agreed
parameters.* DEFINITION — the things a fork has to change. Paths, cadences, thresholds
procedures/ DEFINITION — what a spawned agent reads at fire time
scripts/ DEFINITION — the loops
state/ INSTANCE — what it has handled, what it spawned, its loop's pid
```
**Separate from the first commit, not sorted out later.** A shareable bundle is "everything except
`state/`" only if that boundary is structural; mixed together, extracting one means picking files apart by
hand and getting it wrong once. Same reasoning as plugin capabilities being read in place rather than
copied — a directory boundary beats a convention, because a convention is what a tired person violates.
The failure it prevents is specific: a recipient's commander starting up believing it has already handled
your recordings, and silently doing nothing.
**Parameters are separate from procedure, or forking means editing code.** With `~/Documents/VoiceMemos`
baked into a script, a fork is a debugging session. Declared in one place, a fork is a conversation — the
new owner is asked where their memos land and the commander rewrites its own file. That difference is the
whole point of the thing being an agent rather than a template.
## Phase 2 — a commander becomes a git repository
**Not now.** Recorded because the phase 1 layout has to leave room for it, and it costs nothing today to
leave that room.
**There is no button.** The owner asks the commander, in conversation, to make itself shareable, and it
does — `git init`, a `.gitignore` that excludes `state/`, a first commit. That is the same shape as
everything else here: the commander maintains its own directory, and the platform does not reach in.
**What it needs to know goes in the commander SKILL, not an affordance.** The layout, what is tracked,
what is ignored and how credentials are handled is reference material — read on the one day somebody asks
for it. An affordance's body is charged to every turn of every commander forever, and this would earn that
cost approximately never. `capabilities/skills/commander/SKILL.md` gains a section.
**Credentials are named, never valued.** This is the rule that matters, because the natural place to put a
Whisper URL is the config file that is about to become public. A commander declares what must be
configured — "an STT endpoint" — and the platform holds the value. Gitignoring `state/` does not cover
this: a credential is definition-shaped, it looks like configuration, and it would be committed and pushed
and stay published.
**And a shared commander declares what it requires.** Yours assumes a transcription plugin, a Whisper
server actually configured, and a folder that exists. Landing on an install without them, it arms cleanly
and fails silently at 3am — the worst failure this system has. Same problem `osDependencies` solves for a
plugin, wanting the same answer: the receiving platform refuses rather than pretends.
The forking story then reads: clone, open a conversation, answer where your memos land and what you want
done with them, and the commander rewrites its own parameters and arms.
## The consequence for the skill
`capabilities/skills/commander/SKILL.md` says turn one is orientation — *"read where you actually are