diff --git a/docs/commander-directory.md b/docs/commander-directory.md index d4f84365..049948c8 100644 --- a/docs/commander-directory.md +++ b/docs/commander-directory.md @@ -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//commanders// + 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