Repository navigation
Runtime
Status: Draft — may change (2026-10-19)
What does the Runtime keep, run, read and deliver, so that a team is started, known by name, reached by name, watched, stopped and put right, with every record the Kernel calls for and no rule the Kernel does not?
Fifty-three commitments in ten chapters. Each says what the Runtime does when it is built, in the present tense, and ends with Today: what the code at the tag does, checked clause by clause. Nothing here gives the Runtime a power the Kernel does not name: where the Runtime acts by itself it acts inside a row of the §9 table, a policy of the Kernel's Policies section or a setting a level declared, and anything else waits for someone who holds the right. The registry comes first in order and in priority (an owner decision: "registry first, as it holds the ids"), because every other chapter addresses a seat by what the registry says it is.
-
The Runtime decides nothing of authority. Every refusal it executes MUST name a Kernel rule,
a row of the §9 table, a policy of the Kernel's Policies section or a setting a level declared, and print that
name. It keeps the records the Kernel defines (§15), executes the operations the table
authorises (
start,stop,add,remove), reads what the seats show, delivers what waits, and measures the machine. A reading it cannot make is said as not known, never guessed (007 commitment 5; §11, the general fail-closed rule: it refuses or waits, and says why): a screen it cannot read, a caller it cannot place and a registry it cannot read each end in a refusal or an "unknown" that names itself. Spec: Specs-registry §5; the command-to-capability map is handed to Specs-grants (via §12). Proof:test/permissions/fail-closed.test.ts. Today (v0.5.0). The map from commands to gates is one closed table insrc/permissions/map.ts, one row per command, each row in the decision record's own words (an owner decision); a command the map does not name is refused rather than judged, and every refusal of the resolver names its rule. The two gates that live elsewhere, the send admission and pane authority, are named as such, and the map admits no one to them. The gates hold against a mistake, not an attempt (§3 below).
-
One record per seat, with an immutable id. A seat MUST be registered once, at its first launch, under an id minted at random, never reused, never renamed and never derived from a name. The code calls the record an agent and its id an agent id; since an owner decision the texts read it as the seat's record, the position that keeps the id, its list and its leases across its occupants. The record holds the signing triple (model, version, role) the commit check reads; the lab and the CLI; the launch line as it was started; where the agent answers (its team by team id, its seat, its herdr session, its pane, re-pointed on every relaunch, and a cross-session address when its CLI has one); its lifecycle; and its provenance: who registered it and when, when it was last updated, whether the last registration ran under dev mode and by whom, and the delegation the last write ran under (commitment 24). A record's identity is the pair (team, seat), never the pane: a pane change re-points the same record, and one pair holds at most one live record. Records are appended, never deleted: ending a seat marks its record and nothing else. A rename edits the nickname alone, the display name that is a name for humans and confers nothing (an owner decision); a seat rename keeps the id and the grants. Spec: Specs-registry §3.1, §3.2, §5. Proof:
test/registry-agents.test.ts,test/registry/identity.test.ts,test/rename.test.ts. Today (v0.5.0). Built as described: one file per agent under the tool's configuration folder in the owner's home, written through a temporary file and a rename under the folder's lock;up,add,restartandreloadregister a seat at its first launch and re-point it at every relaunch;removeretires, a stop marks the record stopped, and a stopped seat comes back as the same record (src/registry/agents.ts).team renamecarries the record, the grants and the state across the rename (src/commands/rename.ts). Thelauncherreference and themcpandskillslists are declared and empty; the launchers registry and the per-seat resume record are not built, so continuity acrossteam upis the live pane's, never a conversation resumed. -
Teams, projects and the chain. The hierarchy MUST be entity, then project, then team, then seat (the levels of the Kernel's Policies section §2.2, from an owner decision). A team's record is keyed by its team id, so two stores of one checkout are one team; it carries the team's own name, the project it sits in (by project id, or none: a team no project names is its own project), the entity, the session, the root, the lobby recorded per session, the roster and the lifecycle. A project's record is keyed by an id derived once from its display name and never moved; it carries the entity, the lead by agent id and the teams it groups. A team names its project in its file; one team per project may claim to lead it, and the project's lead is then the agent of that team's lead seat, re-resolved at every launch and cleared when the claim or the team goes; a team two projects name is refused by
team check, naming both. Nothing resolves by a role's name, in any language: a lead is the seat whose role holdsleads(an owner decision; 009 Roles and skills), carried on the roster line as a mark; the roster also marks the entity's assistant, a place in the chain the send admission reads and not a Kernel capability (§3; 009 Roles and skills: the first assistant is just a role). Spec: Specs-registry §3.2, §3.3, §5. Proof:test/registry-teams.test.ts,test/registry/projects.test.ts. Today (v0.5.0). Built, withteam projectsandteam status --projectas its read surfaces (src/commands/projects.ts,src/commands/status.ts). The roster line carries the two marks admission reads, theleadscapability and theassistantplace; a line written before the marks existed reads as not known to hold them. The entity level is a name on the team record and the lobby's key, and the machine's entity configuration now lets it declare liveness and policies (src/entities.ts,src/policy/sources.ts); it is still no record of its own. The registry's cost view is not built:team usagereads accounts and seats, not agent records. -
A record is a report; it confers no right. Registration, lifecycle records and signing roles MUST NOT authorize an act by themselves (007 commitment 3; §4, identity signs and does not grant). What a seat may do is decided from the pair's relationships and the capabilities on the record, by the resolver (chapter G) and by the send admission (chapter E). The roster line is the seat's identity for every gate: a seat the roster does not list has no record, whatever the file declares, and is refused what the file says it holds; a registry that cannot be read refuses every seat, closed, and is never read as "no record". The file's own declaration stands only for a team the registry has never seen, and then with no agent id, so no grant can name such a seat and no read surface admits it. Spec: Specs-registry §5. Proof:
test/permissions/record-acceptance.test.ts. Today (v0.5.0). Built as described;team checkreports a live seat the roster does not list, repaired withteam register <seat>(src/commands/check.ts). -
Registration at launch, and the adoption of a seat already running.
upandaddMUST write a seat's record in the run that launches it. A seat someone else started, an earlier release or a CLI run by hand in a session the team owns, is a live pane no command may address untilteam register <seat>writes the recordupwould have written. It verifies what herdr and the pane say: herdr names an agent of that name in the session's own workspace, the pane holds a process in front of its shell, that process is the one the seat's CLI profile names, and the screen is the seat at its prompt. It writes the state, the log, the launched-pane pointer and the registry's agent and roster line, records the seat's cross-session address where its CLI has one, re-applies the two sidebar lines from the file, and types nothing into the pane.--pane <id>adopts a pane herdr never named, naming it as the seat through herdr; a pane herdr names as another agent is refused, never renamed. What only a launch knows (the model, version, effort and launch line a launch declared) it does not write. Spec: Specs-registry §4; Specs-launch §4. Proof:test/register.test.ts,test/register-pane.test.ts. Today (v0.5.0). Built (src/commands/register.ts,src/launch/identity.ts). The run is also the repair: on a seat already recorded it verifies the pane again and rewrites the registry record from the file, and a team the registry holds no record of is written by it too. Who may run it is the map's row, with the file'sdelegatesandgrantentries and a create-grant's runner (commitment 24). -
Departed seats. A seat that stops MUST keep its roster line and its record, marked stopped with its pane cleared, and its next launch is the same agent; a seat removed is retired, taken out of the roster, its record kept; a session found dead stops every agent launched in it;
upends as stopped every seat the file stops or that did not reach ready, and marks the team stopped when no seat is left running. A stop in one session never ends the agent that now lives in another. Nothing is deleted, and the history stays readable. Spec: Specs-registry §5. Proof:test/registry-down-session.test.ts,test/state-departed-seats.test.ts. Today (v0.5.0). Built (src/registry/sync.ts,src/state.ts).team seats --allshows the stopped rows;team listshows the registry beside herdr's sessions with three words, defined, approved and running (§10, question 5 on the second) (src/commands/seats.ts,src/commands/list.ts). -
The lobby, recorded per session. A team's seats MUST start and wait in its lobby: the file's explicit
lobby:if it names one, else the lobby the registry recorded for this session, else the entity's own lobby (one folder per entity under the tool's configuration folder; an owner decision, the lobby keyed by entity, never by project), else the machine-global lobby of the releases before entities. Once a session's lobby is recorded, editing the file'sentity:never moves it; an explicitlobby:is the owner's own declaration and is re-recorded. The lobby must be trusted by the file and verified by the lobby gate (a real folder of the user's own, with no link on the way), and the seat's CLI trust record is written there before the workspace exists, so the launch meets no trust dialog on the lobby. Spec: Specs-launch §3.7; Specs-registry §3.2. Proof:test/commands/lobby.test.ts,test/lobby-recorded-acceptance.test.ts. Today (v0.5.0). Built (src/lobby/gate.ts,src/lobby/recorded.ts,src/launch/pretrust.ts). The record keeps one entry per session, so a second session and a second team file in one checkout each record their own entry without taking another's. -
The registry is the home of a team's definition. A team's definition MUST be held in the registry: its seats, its roles, the role-and-trade briefs, the general brief, the start briefs, and, as today, its grants, policies and records. The registry is keyed by entity, then project, then team, and the defaults shipped with TeamCLI are overridden by the entity's then the project's, with the inheritance the policies already use (an owner decision). A project carries no new TeamCLI file, and a repository stays free of team definitions: a record changes by a command, never by editing a file in a project, and every change is signed and logged (
team role setandteam brief set start <seat>are the decision's examples).team.yamlretires in steps: first the registry is the source and the file an export, then the file is no longer read.team exportandteam importkeep a readable copy for review, backup or another machine outside the repository. Spec: Specs-registry §3.5, §7 (the planned store; no brief record has a format yet); Specs-roles §3.2. Proof: none at the tag. Today (v0.5.0). Not built: the team's definition is still theteam.yamlin the project root, with grants and policies signed in the machine's configuration; the registry holds the agent, team and project records and no role or brief; no command sets a role or a brief, and no command exports or imports a store (src/check/team.ts,src/registry/). -
Storage is a backend, never the authority. The registry MUST be reachable through one storage contract with five operations — read, write, list, watch, and an atomic compare-and-set — and a backend holds the records without deciding anything about them (an owner decision). The built-in default is files in TeamCLI's machine configuration, with no runtime dependency. A database (for example MongoDB or PostgreSQL, for several machines sharing one team), Redis (fast shared state for the event bus, never the only copy unless it is durable) and an online service (possibly hosted from teamcli.io one day) are optional add-on packages, so the core stays dependency-free. Records are verified whatever the backend: a signed grant, policy or brief proves itself wherever it is stored, and a compromised database or service cannot forge one; backend credentials go through the entity's accounts, by keychain reference, never into a file (commitment 50). Spec: Specs-registry §3.5, §7. Proof: none at the tag. Today (v0.5.0). Not built: the only store is the files under the tool's configuration folder in the owner's home; grants and policies are owner-signed and verified whenever they are read or used, while the agent, team and project records carry no signature; there is no backend setting and no add-on (
src/registry/,src/permissions/grants.ts,src/policy/). -
Agents are connected; seats are attributed; the address is the seat. An agent MUST be the connection to a model — a CLI or API session on one lab's model at one effort — and a seat MUST be a station of the team, attributed to at most one agent at a time, or to none (an owner decision). A message addressed to a seat MUST be delivered to the agent on watch at the moment of delivery: a swap, a failover or a re-cast changes the watch, never the address. The registry MUST record which agent stood which seat, from when to when, as the seat's watch history (an owner decision); the code's record keeps its name and stays the seat's record, the position that holds the id (commitment 2), while the attribution is what the watch adds to it. An agent MAY also be addressed directly, for example to ask it about its own watch after it was relieved (an owner decision). Spec: Specs-registry §3.1, §5 — the watch history is the registry's next revision; the address rule is handed to Specs-messaging (via §12). Proof: none yet. Today (v0.5.0). Not built at v0.5.0: the registry's record is one per seat, holds no attribution and no watch, and every send resolves its recipient from the seat's live pane (commitments 15 and 17); no agent is recorded apart from the seat it stands.
-
The session record, written by the tool. TeamCLI MUST write one record per session under its seat — a seat holds many sessions over time — and MUST write it itself at
up,restart, the swap anddown, never from the agent's word (an owner decision). The record MUST hold the entity, project, team, seat and nickname; the CLI, lab, model and version, effort, and the account or route spent; the start and end times and the end reason (swap, restart, crash, owner stop, quota); the sessions before and after it; the CLI's session ID, whether it can still be resumed and until when (the CLI's own retention), and the handover file; the tokens in, out and cached and the cost, each marked measured or estimated, with unknown never shown as zero; and the commits, pull requests and releases it produced. Where the CLI allows it, TeamCLI MUST set the session ID at launch (Claude Code's--session-id), so it never reads a CLI's session files; records are only ever appended. The read commands MUST beteam sessions [<seat>]andteam sessions --by model|team|entity, and the resume command MUST beteam resume <seat> --session <id>, a resumed session reading the latest handover first. Both are planned commands. Spec: Specs-registry §3.1, §5; Specs-launch §4, the commands and their exit codes. Proof: none yet. Today (v0.5.0). Not built at v0.5.0: nothing records a session, no command lists or resumes one, and continuity acrossteam upis the live pane's, never a conversation resumed (commitment 2). -
The model rule is a policy the tool carries out across the entity. A model rule MUST be a policy at the entity level, held in the registry, set and changed by one owner command and never by hand edits to each team's file (an owner decision; the Kernel's Policies section). TeamCLI MUST carry it out in every team of the entity: list the seats that break the rule, propose each replacement from the seat's allowed models and the team's visibility, and swap them one by one — ask the seat for a handover and wait for it, restart the seat on the new model, pass the handover to the new session, and read the new status bar back to verify the model. The steps done by hand on 2026-10-19 MUST become the tool's: unsent text in a seat's input box, a seat that is not the signed one, the folder-trust prompt, a lead whose restart is owner-only, the handover, the model read on screen, and panes a lead opened outside the team file.
team checkandteam watchMUST flag every seat that breaks the rule, including a pane a lead opened by hand. Spec: Specs-policies, the entity-level policy and its catalogue (via §12); Specs-seat-state-and-watch §3.3, the checks. Proof: none yet. Today (v0.5.0). Not built at v0.5.0: no entity-level model rule exists and neitherteam checknorteam watchknows one; the watch reports model drift against the file (commitment 9), and the swap steps of 2026-10-19 were done by hand. -
A swap waits for the task boundary; a broken seat swaps at once. A swap TeamCLI plans under a model rule MUST NOT interrupt a working seat: it MUST be queued on the seat, and the seat takes no new task while it waits (an owner decision). It MUST run at the seat's next task boundary — the task reported done, or the seat idle with nothing queued for it — and that boundary MUST be a state of the workflow of 010, marked by TeamCLI and never by the agent's word; the seat writes its handover as the last step of the task, and the swap then follows: restart on the new model, the handover passed on, the model read back. A seat that is out of usage or keeps failing MUST swap at once, because it cannot finish its task. The wait MUST be a setting (thirty minutes proposed); after it, the swap runs at the next pause between two turns, and that is logged. When only the model or the endpoint changes and the CLI stays the same, TeamCLI MUST try to resume the same conversation on the new model, so nothing is lost. Same-CLI resumption across models has not been tested (an owner decision): trying it is the promise, and lossless resumption is not an observed fact. A handover file is required only when the CLI changes.
team statusMUST show the queued swap and what it waits for, the owner MAY force a swap at once and the force is logged, and the same queue MUST serve any change that needs a restart. A pane a lead opened by hand that breaks the rule MUST be flagged to its lead and toteam check, and MUST NOT be closed automatically, since it may be doing work (an owner decision). Spec: Specs-launch §4, the restart and swap commands; Specs-seat-state-and-watch §3.2, the settings; the boundary is 010 Workflow's state. Proof: none yet. Today (v0.5.0). Not built at v0.5.0: there is no queue and no swap,restartrelaunches without a handover (commitment 13), and no surface shows a pending swap. -
Temporary seats and worktrees end on proof, and the watch removes only what it may. A temporary seat and a worktree MUST end only on a validated condition:
result:<path>when the lexical path exists, ormerged:<branch>when the branch's own commits, read after a fetch that succeeded in the same pass, were non-empty at an earlier pass and are empty now. A branch with no own commit MUST never count as merged, including a fast-forward-only update; a branch committed and merged between two passes MUST be reported, not removed; a failed fetch, a vanished branch or an unprovable squash or rebase MUST remove nothing; and a temporary seat's condition MUST be acted on only after the seat has beenworkingonce since its rules were delivered and isfree, while a worktree MUST NOT be held to either test.--untilMUST be validated lexically for every caller: an absolute path,~, every..segment and any symlink refused forresult:, and Git's ref rule (checked withgit check-ref-format --branch), no leading-and--end-of-optionsbefore the revision formerged:. The watch MUST judge and report the end and write the own-commit proof back; it MUST close a temporary seat when the validated end holds and the seat hasworkedand isfree, and a laterupMUST NOT recreate it; it MUST remove a worktree only when the end holds, no seat is recorded in it, andremovewould not refuse, with noworkedorfreetest on a worktree. A removed worktree keeps its branch. Spec: Specs-operational-safety §3.1 to §3.3, §5 Rules 1–4. Proof:test/end.test.ts,test/commands/add.test.ts,test/commands/worktree.test.ts,test/commands/watch-close.test.tsandtest/watch-workspace.test.tsat v0.5.0. Today (v0.5.0). Built in part, with two named gaps: the end conditions and own-commit proof are built, and worktree removal on the proof, with its refusals and the branch kept, is built; aresult:path that is a symlink is accepted, because the lexical check never stats the path and the existence test follows the link (the archived requirement refuses it); and the watch judges and reports a temporary seat's end but does not remove the seat, so at v0.5.0 the owner'steam remove <name> --abandonis the stop. -
One writer over a seat's dialog state, and a recorded recovery for every answer. One exclusive lock per session and seat MUST guard a seat's dialog state for the whole command span: a complete
<pid> <nonce>token taken by hard link, an unreadable lock treated as held, and a stale lock taken over only through a second link and a re-read of the token. A launch that opens a dialog by hand MUST record the manual marker under the lock before focusing the pane (at v0.5.0 the marker iswaiting.manual: trueon thewaiting-ownerrecord, Specs-launch §3.5;manual-owner-controlis the archived prose word), andteam answerMUST refuse the marker. An answer MUST take two fresh reads, compare the exact label, version and folder, require the lobby folder on three readings, write the recoverytrust-sent-recoverybefore the key, restore the waiting state when the send is refused, and only observe after a send. Spec: Specs-operational-safety §3.4, §3.5, §5 Rules 5–7. Proof:test/launch/seat-lock.test.ts,test/launch/pause.test.ts,test/answer.test.tsandtest/close.test.tsat v0.5.0. Today (v0.5.0). Built: the manual marker is the booleanwaiting.manual: trueon thewaiting-ownerrecord (launch.md §3.5), refused byteam answerwith${seatName}: the owner has the pane open;manual-owner-controlis the archived prose word and appears nowhere insrc/at v0.5.0. -
A launched seat's child gets only its declared Git identity. TeamCLI MUST clear the inherited Git and GitHub inputs that would carry the owner's identity, set the declared values from the account fields of Specs-accounts-and-gates §3.4 in the child process only, never print or log a value, and make the Git forms that would escape the identity run
false. Spec: Specs-operational-safety §3.6, §5 Rule 8. Proof: none at v0.5.0 or at int/0.5.1 (8acb470b). Today (v0.5.0). Not built at v0.5.0 or at int/0.5.1 (8acb470b): no declared identity is set and no inherited input is cleared; the herdr server starts detached in a clean environment (HOME,USER,LOGNAME,PATH,SHELL,TERM,LANG) and passes the owner'sSSH_AUTH_SOCKwhen set. -
Commits that claim a seat are checked against the declared account.
team checkMUST apply the account rule to the selected commits: merges exempt; declared humans exempt; a trailer naming an inheriting seat requires author and committer name and email to equal the declared seat account; anidentity: offseat or no seat gets no comparison; squash, GitHub rebase, web edits and rewritten rebases are checked when the trailer names an inheriting seat.identity.sinceunset excludes nothing; set, it excludes that commit and every commit reachable from it. A failure MUST sayauthor is not the declared seat accountorcommitter is not the declared seat accountand name configuration, never a token. The check is a consistency check, not proof, and stays read-only with exit 1. Spec: Specs-operational-safety §3.7, §5 Rule 9. Proof: none at v0.5.0 or at int/0.5.1 (8acb470b). Today (v0.5.0). Not built at v0.5.0 or at int/0.5.1 (8acb470b):team checkruns its signature and forbidden-pattern checks and compares no author or committer with a declared account. -
A message to a seat with no agent on watch waits, and the sender is told at once. A message to a seat with no agent on watch MUST wait in the seat's inbox until an agent is attributed; the sender MUST get an "off watch" receipt at once; and the team's lead MUST be told at the next status, at once when the message is marked urgent (an owner decision). Spec: Specs-messaging, the delivery rules this answer extends; Specs-registry §3.1, the attribution commitment 38 adds. Proof: none at v0.5.0. Today (v0.5.0). Not built at v0.5.0: a send resolves the recipient from the seat's live pane, and no inbox wait, "off watch" receipt or lead notice exists.
-
The project root is selected by one rule, and a folder root is shared-only. A command MUST first ask Git for the invocation directory's checkout and select the main checkout's
.agents/team.yamlwhen it exists; failing that, it MUST walk the invocation directory and its existing ancestors lexically, nearest first, and select the first.agents/team.yaml, searching a symbolic-link candidate for the file and ending the walk without continuing through its target. A folder root MUST beworkspace.mode: sharedonly, and its effectiveworkspace.protectedlist MUST be empty; a folder file MUST rejectworkspace.mode: worktree, a worktree seat and a declaredworkspace.protectedwithfolder.git-required, and the Git-dependent operations MUST refuse from a folder root as Specs-projects-and-knowledge §5 Rules 6 and 7 state. Spec: Specs-projects-and-knowledge §5 Rules 1–8, §3.5 and §4. Proof:test/load.test.ts(the main-checkout, subfolder and folder cases) andtest/commands/plain-folder.test.tsat v0.5.0. Today (v0.5.0). In part: the invocation directory's checkout selects the main checkout, and the plain-folder loader reads the invocation directory's.agents/team.yaml; the lexical walk to a parent, the symbolic-link stop, the folder-root restrictions and the Git-required refusals are not built. -
Setup detection is read-only, and a proposal's preview bytes are rechecked before anything is applied. A detector MUST read only safe project metadata and shipped install, version and login observations; it MUST NOT read credentials, session files, keys, quotas, account identities, shell history or CLI configuration, MUST NOT execute a discovered check, and MUST discard a login probe's output, use its exit status and disclose that probes may use a CLI's network session. A proposal MUST explain each selection that is not an observation, and an unmet fit requirement MUST be reported rather than cured by creating a resource or widening authority. A create flow MUST render one byte snapshot, compare the candidate bytes with it immediately before applying, and apply only that previewed candidate under current valid authority; any console that applies a proposal MUST use the same preview, authority and unchanged-byte rule. A mismatch or a decline MUST leave the application, grant creation and launch unapplied, and MUST NOT add another mandatory approval or revive the removed start, sign-only or console flow. Spec: Specs-setup-and-team-models §3.1 to §3.3, §5 Rules 1–6. Proof: none at v0.5.0. Today (v0.5.0). Not built at v0.5.0:
contract/cli.jsonregisters none ofdetect,presets,presetorguide;doctor's opt-in--loginprobes andinit's one-seat starter are supporting pieces only, and no proposal or preview transaction exists.
Accepted 2026-10-18 as amendment 01; frozen, editorial changes only.
Commitment 51 below is Runtime amendment 01's: accepted on 2026-10-18 under the owner's delegation
(an owner decision) and folded as the text stood at batch 11 (9cc3b10). Its four sibling
clauses sit in the chapters Runtime amendment 01 declares — 49 in chapter C, 50 in D, 52 in I, 53 in J —
each under this heading, each frozen: editorial changes only, until a later amendment. Their Today
lines read at int/0.5.1 (8acb470b, unreleased); the tag v0.5.0 does not build them.
-
A seat is launched only under its entity's GitHub identity. When launching a seat of an
entity that declares a GitHub identity, TeamCLI MUST verify that the entity's keychain token
carries a fine-grained token prefix (
github_pat_…) or, when the identity declares an app-installation kind, an installation prefix (ghs_…), refusing classic (ghp_…) and OAuth (gho_…) tokens (an owner decision, and an owner decision; §10 questions 21 and 22), inject the GitHub token and commit author/committer identity into the child process environment only, and rewrite both SCP-style and URL-style SSH GitHub remotes to HTTPS through the GitHub CLI credential helper, so no seat pushes with the owner's ambient SSH key or personal login. Until the Kernel'sact-as(account)gate is enforced (Kernel §3, §14; unbuilt in 0.5.0), this entity-wide injection is the mistake-guard default, and TeamCLI MUST resolve the identity strictly from that entity's configuration without falling back to another entity's token or the owner's login. Spec: Specs-accounts-and-gates §3.4, §5 Rule 5. Proof: none yet. Today (v0.5.0). Not built at v0.5.0 or at int/0.5.1 (8acb470b): seats use wrapper scripts in the knowledge-base tools folder to injectGH_TOKEN, author variables and Git config rewrites (an owner decision).
Cross-reference: the launch it guards is commitment 10 (chapter D); the account resolution that precedes it is commitment 50 (chapter D).
-
One state per seat, read from ranked sources, with the source said beside it. The word MUST be one of the state words of this chapter's reading (the owner's decision of 2026-10-17, outline item 5), read from the first source that is certain: a hold over the team; herdr unable to reach the seat; the launched process no longer in its pane; a screen that is neither mid-turn nor at its prompt, a dialog, a question, an error, a composer holding unsent text, whatever any clock says; the CLI's own signal through the hooks the launch installed; the pane's screen read against the seat's CLI; herdr's own status word; and TeamCLI's traces within a window (the seat's last commit, ack or message, each with its own instant). The one exception to that order: a trace inside the window outranks an idle word from the hook, the screen or herdr, because a seat that just committed, acked or was messaged is working even while its prompt shows (010 commitment 14 ranks the traces last with no exception; §10, question 3). Otherwise the seat is unknown; past the blind threshold an unknown seat counts as not working and is flagged blind, a must-fix in
statusandcheck. A tool row on a screen carries no clock and is kept for display, never weighed as recency. The thresholds are settings inherited entity, project, team, seat; a lower level may shorten them, never lengthen them (the Kernel's Policies section §2.3; 010 §2c). Spec: Specs-seat-state-and-watch §3.1, §3.2. Proof:test/seat-state.test.ts,test/labels-traces.test.ts. Today (v0.5.0). Built as described, withteam seatsprinting STATE and SOURCE per seat and--watchrefreshing every two seconds (src/labels/state.ts,src/commands/seats.ts). The hooks: for a CLI whose per-launch settings file reaches command hooks, the launch installs two, at turn start and turn end, that rewrite one small file per seat in the project state folder; the reading stands for a day, and its working word outranks the screen for a short window, after which a prompt that shows again answers (src/launch/cli-hook.ts). The trace window, the hook's standing and the blind threshold are enforced policies (seat-state §3.2; an owner decision); the code lets the project lengthen what the entity set, which the Kernel's Policies section's inheritance does not allow (§10, question 3). Planned: the receipts of 002 phase 2 as a trace; the round's liveness thresholds of 010 Workflow. -
The label follows the observed value. Each seat's pane MUST carry two sidebar lines: the file's label (the workspace title) and the display line (model, version, effort). While a seat runs, the watch repaints the second with the running model and version the screen shows when they differ from the file's, and with the effort word the screen shows; a screen it cannot read keeps the file's display, never the CLI's name. The difference between the file and the observation is reported (
team check, the watch's model-drift report), never written into the file. Spec: Specs-seat-state-and-watch §3.9. Proof:test/labels-observe.test.ts. Today (v0.5.0). Built (src/labels/observe.ts,src/watch/seat-label.ts).team registerre-applies both lines from the file without a relaunch. The observed model is not stored on the agent record: the commit-signature policy's model match needs it (§10, question 11).
Accepted 2026-10-18 as amendment 01; frozen, editorial changes only.
-
A seat's conversation is resumed deterministically, or the seat is refused. When a seat
declares conversation resume, TeamCLI MUST pre-assign a deterministic conversation identifier
at initial launch or resume the recorded conversation identifier across CLI process exits only
after verifying a non-empty conversation transcript on disk, and MUST atomically refuse to
launch a seat when another live pane or CLI process on the machine already holds that
conversation. A resumable seat MUST use a profile-built launch and never a custom launch
command string; when a seat's pane and CLI process are already alive, starting the team leaves
the seat untouched. If a recorded conversation identifier has no verified transcript on disk,
launching MUST refuse that seat only (fail-closed, Kernel §11), record the refusal on that
seat's state entry, report the error and continue launching the remaining seats (
team checkstays read-only). An explicit fresh-conversation request (settled by an owner decision; §10 question 21) MUST mint a new identifier, replace the recorded one once the new transcript appears, and log both retired and new identifiers. Before checking or binding a conversation identifier, TeamCLI MUST hold the session mutator lock and a machine-wide per-conversation lock with process-start-time reuse protection, leave unowned locks to owner-only repair after verifying no live holder, scan live panes, state and registry records (primary guard) and the process table (best-effort guard), and refuse the launch before creating, closing or typing into a pane if any live holder is found. CLI profiles that lack deterministic pre-assignment or resume MUST be refused fail-closed until evidenced by a measured run. Spec: Specs-accounts-and-gates §3.1, §3.2, §4.2, §5 Rules 1–3. Proof: none yet. Today (v0.5.0). Not built at v0.5.0 or at int/0.5.1 (8acb470b): no conversation resume (resume: true), fresh-conversation request or per-conversation lock exists;src/state.ts,src/commands/up.ts,src/commands/add.ts,src/commands/restart.tsandsrc/launch/execute.tsrecordagent_session,start_cwdand launched process ids to recognize a surviving live pane across runs (Specs-registry §4).
Cross-reference: chapter B records the conversation identifier in the session record (commitment 39); chapter D performs the refusal at launch, before a pane is created (commitment 10).
-
One command starts the team, and a seat is known before it is addressed.
upMUST start the herdr session when it is absent, one workspace per seat in file order (concurrently, or one at a time with--serial), run the seat's launch line in its folder (the orchestrator's and the operator's seat in the project folder, every other seat in the lobby), wait for the idle prompt, name the pane as the seat, record the process identity it left in the pane (the shell's pid and the CLI's pids), deliver the seat's rules as one typed line read back and entered, write the state (the stage, the pane, the workspace, what the launch declared), the log, the launched-pane pointer and the registry (commitment 5), paint the two sidebar lines, and start the watch in a workspace of its own. A seat already ready is left as it is. A dialog at launch is never answered. A kept seat is left out with its classification (trust, permission, question, vendor notice), its workspace kept and a waiting-owner record written, for the owner to finish, or forteam answer <seat> trustwhere the file allows it (commitment 21). A delegated or terminal-less run takes the close path: it closes the workspace without input only when the seat's identity and ownership are proved, and only then drops the waiting record and says the close; a refused or failed close keeps the record. A refusal before the first step launches nothing. Spec: Specs-launch §3.1 to §3.6, §4. Proof:test/launch/launch.test.ts,test/launch/pause.test.ts. Today (v0.5.0). Built (src/launch/execute.ts,src/launch/plan.ts,src/launch/pause.ts), with the dialog handling of the spec's rule 10: a kept seat's workspace and waiting record, and the close path without input only after identity and ownership are proved, dropping the record and saying the close, with a refused or failed close keeping it. The hash-pinned start command with its hashed execution context (§9start; §10) and the per-seat digest of prompt, instructions, environment and permissions (the second step of the restart design) are not built: the launch line is the file's text, checked where it will start and recorded as it ran. A file still on the legacy trust list, not yet migrated to per-entity lobbies, starts a shared seat in its own folder. -
Who may start, stop, add, remove and restart is the §9 table, as code. The map MUST admit, before any caller is read, each operation to the holders the decision record names (an owner decision), read from the roster's mark, never a role's name. Beside the map stand the file's own entries, read as the owner's standing authorizations (commitment 24): a
delegatesentry whose pane is the caller and whose commands name the act; thegrantsection naming the orchestrator's seat (and the word that is still read and inert, commitment 24); and a create-grant record, which admits its grantee by registry id, an agent id or a team id (an owner decision), under the paths it covers, before it expires (§10, question 14). A caller is placed by its parent processes, never by its environment: the owner is a terminal outside herdr; a run outside herdr with no terminal is refused; a seat is the agent herdr vouches for on a pane whose root process is among the caller's ancestors, and an admitted seat must stand in the session judged, on the pane the state recorded for it; everything else is unplaced. A refused realupanswers one word and nothing else; a dry run says what would refuse it and what unblocks it. A lead never acts on its own pane, and never on the orchestrator's or the operator's seat. Orchestrator, operator and coordinator name places in the file's chain throughout this text, the seat the file declares as its lead or its operator, carried as a roster mark, never a seat found by a role's word. Spec: the map's rows are handed to Specs-grants (via §12). Proof:test/permissions/up-register-gates.test.ts,test/permissions/delegates.test.ts. Today (v0.5.0). Built as described (the map, the bridge, the walk; "caller gates are strict now", UPGRADE-0.5.md;src/permissions/map.ts,src/caller.ts). The constraints the Kernel re-checks on every authority change (§5) are not: oneleadsper team is refused byteam checkand atupwhen the file is read, and nothing is re-checked when a grant is made or a seat added. Placement is an accident guard: the pane ancestry and herdr's vouch are forgeable by a process of the same user, which the tool does not resist (§3 below). -
Gate-lift is a policy, applied to the caller gate alone. While it is on, the "who may run it" gate of the everyday operations MUST accept a caller it would otherwise refuse for not being the owner's terminal; the placement, CLI, record and scope checks stay; every use warns and is logged; the record a dev-mode run writes says so in its provenance, and the owner's own run in force takes the mark off (an owner decision; the Kernel's Policies section §2.7 and the catalogue's
dev-mode). Spec: Specs-policies, thegate-liftvalue (via §12); the operations' synopses are in Specs-launch §4. Proof:test/dev-mode.test.ts,test/dev-mode-gates-matrix.test.ts. Today (v0.5.0). Built as the policy:dev-modeis a value of the policy object, set at the entity, the project or the team byteam policy set, never at a seat, with an optional expiry; while it is on for the caller's level the caller gate of nine operations folds into a warning, every use warning on stderr and writing a log line with the caller, the command and the level that set it; the environment variableTEAMCLI_DEV_MODE=1is honoured only while nodev-modevalue governs anywhere in the chain, and is ignored and logged once after; an expiry reverts the gate to off and is named in the next refusal (src/policy/types.ts,src/commands/policy.ts).team broker,team tempo, the owner's--abandonand a delegate's file-editingaddare outside, as an owner decision asked. The agent record carries the mark with who and when;team seatsprints it beside the id andteam checkreports it as a difference until the owner's own run in force rewrites the record. Two words beyond the decision's seven,reloadandrename, are in the code's list; they are put to the round of the Kernel's Grants section (§10, question 1). -
Stopping stops; a seat is changed in place; a stopped seat comes back as itself.
downMUST ask every free seat to exit, wait for its pane to return to its shell, close its workspace, stop the session and clear it, so a laterupstarts from the beginning; a working, blocked or half-typed seat is left running and named,--waitgives a working seat a bounded time to come free, and the owner's--abandoncloses a workspace without typing into it. A pane herdr names with something the file does not carry is closed only where the state records that pane and that workspace for one seat, and, where the state holds the launched process, only while that process is still there.restart <seat>stops and relaunches one declared seat in place without editing the file, after printing three facts (the input box, the turn, what the close ends); a busy seat is left as it is unless abandoned, and a seat never restarts its own pane.remove <seat>takes a seat out and edits the file so it is not started again;--keepparks it as stopped, or, on the orchestrator's or the operator's seat, is the first half of a swap that keeps the lead through the gap. The seat's handle survivesdownand--keepand comes back on the nextuporadd. A handover MUST carry what is done, what is in progress, who it waits on and what comes next; where the departing seat cannot be asked, TeamCLI MUST write it from its records and say "not known" where the record is silent, and the arriving seat MUST say back what it understood before it acts (007 commitment 7); a handover file is required only when the CLI changes (an owner decision; commitment 41). A caller other than the owner meeting an idle seat that is not free takes it out and leaves the pane running, renamed so it no longer answers the seat's name. Spec: Specs-launch §4; Specs-registry §5. Proof:test/restart.test.ts,test/registry-down-session.test.ts. Today (v0.5.0). Built as described (src/commands/down.ts,src/commands/restart.ts,src/commands/remove.ts). Whole-teamrestartandrestart --changedare designed, in the repository's restart design note, not built. The handover of 007 commitment 7 (what is done, in progress, waiting on whom, and next) is not built: a restart relaunches without the old transcript and says so in its three facts. Of 007 commitment 9's repairs, one is made:team check --repair, the owner's, drops the state's leftovers (a record for a seat the file no longer declares, a session with no seat of the team in it); every other repair is named and printed, never made. -
The machine is part of the team.
doctorMUST check the machine against the file before anything starts: herdr, each CLI, its login, the launcher, the model;upandaddrefuse a launch past the machine's limits (load, free memory, free disk, free swap) and write the figures they decided on into the log; the watch logs the machine's readings at its own interval and reports a figure past its limit;team lockandteam unlocktake and release a named machine lock so one heavy run holds it at a time (an owner decision, the hourly suite in a heavy slot);team prockeeps the processes the seats started as a register in the state. Spec: Specs-seat-state-and-watch §3.3, the machine's limits and the readings the watch logs. Proof:test/doctor-machine.test.ts,test/lock.test.ts,test/proc.test.ts. Today (v0.5.0). Built as listed (src/commands/doctor.ts,src/commands/lock.ts,src/lock/machine.ts,src/commands/proc.ts, with the state helpers insrc/state.ts). Keeping the machine awake, pausing before the battery ends, and finding the team again after a sleep or a restart (007 commitment 10) are not built; a restored pane is recognised (commitment 10's process identity, with the agent session herdr reports), which is as far as waking goes.
Accepted 2026-10-18 as amendment 01; frozen, editorial changes only.
-
A seat's declared account resolves against the entity's launch accounts first. TeamCLI
MUST resolve a seat's declared account against the entity's secret-adjacent launch-accounts
configuration first and fall back to the machine's billing-accounts configuration when absent
there, building the provider's environment and CLI arguments from the entity's launch account
without storing secrets in any file. The owner-signed entities file MUST remain the single
source for an entity's declared roots and entity policies (the Kernel's Policies section §2.12;
commitment 27), while the per-entity subfolder holds only unsigned, owner-only mode
0600operational files. When a seat's account resolves to a launch account, TeamCLI MUST require the team to declare its entity, attribute usage to the launch account's mapped billing target, retrieve the provider credential from the system keychain on macOS at launch (the Kernel §11 exception settled by an owner decision; §10 question 21), enforce forbidden key prefixes, inject the provider's environment and isolation arguments into the child process only, and refuse if the account resolves in neither launch nor billing configuration. Static CLI profiles MUST stay in code, with an optional binary override on an account replacing a separate launchers file; a customlaunch:command remains an escape hatch mutually exclusive with a launch account, andteam checkMUST warn whenlaunch:references a path inside a docs repository. On non-macOS platforms, checks, diagnostics and launch MUST fail closed when a keychain entry is referenced; on macOS, the diagnostic check MUST verify keychain item attributes without reading secret values into memory. The machine-level billingaccounts.yamlstays separate and linked byusage_account:until the registry's pluggable storage holds accounts (an owner decision; §10 question 23). Spec: Specs-accounts-and-gates §3.3, §4.2, §5 Rules 4–5. Proof:test/usage.test.tsat v0.5.0 (52db9b75) for billing accounts; none yet for entity launch accounts. Today (v0.5.0). Not built at v0.5.0 or at int/0.5.1 (8acb470b) for per-entity launch accounts, keychain retrieval at seat launch, or attribute-only keychain diagnostics;src/entities.ts,src/policy/sources.ts,src/information/machine-accounts.tsandsrc/information/usage.tsread entity roots and policies from the machine entities file and attribute seat usage to machine billing subscriptions or wrapper script names.
Cross-reference: the registry's pluggable storage it waits for is commitment 29 (chapter B); the entity configuration it reads is commitment 27 (chapter J); the GitHub identity launched with it is commitment 51 (chapter B).
The workspace adapters. Eight commitments from the design note of 2026-10-18
(an owner decision), not yet reviewed;none is built at v0.5.0.
The note's terms are used here: an adapter is one of several interchangeable implementations
the core picks (workspace: headless, built in and the default, herdr, tmux; registry
storage: files, a database, Redis, an online service); a plugin is an optional add-on that
brings a new capability (decision support, a knowledge base, a future chat connector); a
profile is how TeamCLI drives one CLI (claude-code, codex, grok, cursor,
antigravity, jules, muse, gemini).
-
No workspace backend is a dependency of the core. The core MUST NOT depend on any
workspace backend:
headlessis the built-in default adapter, andherdrandtmuxare optional adapters on one contract. Spec: Specs-workspace-adapters §2, the terms, and §3, the contract; §5 rule 1. Proof: none at v0.5.0; planned 0.6. Today (v0.5.0). Not built: the core calls herdr directly for the operations of commitments 10 and 13; there is no adapter contract. -
A seat's persistence does not depend on a live process. What persists MUST be the seat's
conversation (its session id in the registry,
resume, commitment 49), its messages and the event log (002 commitments 17–34); a seat whose process ended loses nothing, and its next turn resumes the conversation. Spec: Specs-workspace-adapters §3,turn.run, and §5 rule 6. Proof: none at v0.5.0. Today (v0.5.0). Not built: no conversation record and noresume; a seat's life is its live process. -
Headless seats are turn runners. When a message reaches a seat, TeamCLI MUST run one turn
of the seat's CLI non-interactively on its saved conversation, record the reply and the
outcome, and let the process end. No terminal or multiplexer is needed.
Spec: Specs-workspace-adapters §3,
turn.runand the turn runner's per-profile flags; §5 rule 2. Proof: none at v0.5.0; planned 0.5.3. Today (v0.5.0). Not built: no headless path and no turn runner. -
The optional adapters keep a CLI alive only for viewing.
herdrandtmuxMAY keep a seat's CLI alive interactively for live viewing andattach; they MUST NOT be required for any command. Spec: Specs-workspace-adapters §4, the adapter setting, and §3, the mapping per adapter. Proof: none at v0.5.0. Today (v0.5.0). Not built: herdr is required; a run outside it with no terminal is refused (commitment 11). -
The events, their recipients and the escalation are TeamCLI's. They MUST be identical
whatever the adapter.
Spec: Specs-workspace-adapters §5 rule 4 and §6,
seat-states. Proof: none at v0.5.0; planned 0.5.2. Today (v0.5.0). Not built as an adapter commitment: the watch's reports are TeamCLI's; the status events are not built. -
An adapter's states map onto TeamCLI's five.
working,idle,done,blockedandunknown; an adapter that cannot telldonefromidleMUST say so and report both asidle; inheadlessthe turn runner knows them exactly — a turn running isworking, one ended with output isdone, one ended at a permission or input request isblocked, and no turn isidle. Spec: Specs-workspace-adapters §5 rule 2 and §3, the mapping per adapter. Proof: none at v0.5.0. Today (v0.5.0). Not built: no adapter contract exists. -
Status waiters and turn runners never answer. They MUST NOT type into, or answer a
prompt in, a pane marked
human: true; answering stays a human act, or a lead's act under its rights. Spec: Specs-workspace-adapters §5 rule 3. Proof: none at v0.5.0. Today (v0.5.0). Not built: no status waiter and no turn runner; the watch's nudge is commitment 21's. -
Every status event is a signed record. It MUST be a signed record in the event log (002
commitments 17–34), one per transition, never one per poll.
Spec: Specs-workspace-adapters §5 rule 4 and §6,
seat-states. Proof: none at v0.5.0; planned 0.5.2. Today (v0.5.0). Not built: no status event and no signed event record.
-
One message to one seat ends in one confirmed outcome. A send MUST end in exactly one of the outcomes of the messaging spec, printed and matched by the exit code. The body is never typed and never split: a plain send writes it whole to a drop file under the receiving team's own state, by renaming a temporary file into place, and types one short trigger line naming that file. Delivery rests on evidence from this line, never on the exit code of the typing: after Enter, the trigger has left the box and either herdr reports the seat working (or a new done or blocked), or the transcript shows the drop being read. A composer that already holds text is never typed into (held); a screen that is a dialog is not reached (unreachable); a line typed and never taken is not submitted, with what the box holds. A bounded number of Enters go to a box that still holds exactly the trigger, at growing waits, and a box that has cleared is waited on for a bounded time in all. Every drop file opens with a header naming the sender's agent id and the rule that admitted the send. Spec: Specs-messaging, the outcome words, the drop file and the trigger line (via §12). Proof:
test/send-deliver.test.ts,test/send-readback-boundaries.test.ts. Today (v0.5.0). Built as described for the typed path (src/send/deliver.ts); in part for the compose path: the Jules profile's compose module types the brief through the CLI's screens (src/commands/send.ts:1090and:1136–1143,src/profiles/jules.yaml:47;test/jules-compose.test.ts), and its delivery evidence is a created-session proof line, not the generic wake-line evidence (Specs-messaging, "Whatdeliveredmeans"). The seat's lock is held around the write, so a launch of the same seat cannot act beside it and two sends cannot type into one pane at once. A receiver-side hold is held, never delivered (002 Communication). -
The delivery order is the receiving seat's policy. A send MUST walk the legs of the receiving seat's delivery order, the order in force when no level of its chain declares another: the entity, the project's registry record, the team file and the seat's own each may drop a leg or reorder the legs it keeps, never add one (the catalogue's within relation for a list); a word naming a leg the order in force does not have is set aside and the order stands. Each leg either takes the send, which ends the walk, or definitely cannot, which is recorded as a failure and hands the send to the next leg; a missing acknowledgement after a send that went through is never a failure (an owner decision; the catalogue's
delivery-order). Spec: Specs-messaging, the legs and the order's rule (via §12); thedelivery-legsregistry (via §12). Proof:test/send-delivery-order.test.ts. Today (v0.5.0). The walk, the chain and the records are built (src/send/deliver.ts,src/settings/inherit.ts), and the order is a signed policy in the chain, written byteam policy setand read fresh (src/policy/sources.ts,src/commands/policy.ts); a legacydelivery_orderfield shadowed by a signed policy is reported byteam check(src/check/team.ts).team sendopens no socket: a frame written to a busy Claude Code session lands at its held-message dialog, where the box is blocked, so inside the command the native legs are recorded unavailable and every delivery the command makes goes by the typed leg; the native leg is carried outside the command, byteam route, the sender's own tool and--record(commitment 17), which is how the record's "native then typed" is met.--wait, which would ride a frame, is refused for every seat before anything is written. The catalogue'ssocket-acceptedleg is not a leg the code knows (§10, question 4). -
The native channel is the sender's own delivery, with TeamCLI's address, admission and record. Where the recipient's CLI carries a cross-session channel, the sender MUST deliver with its own tool:
team route <seat>judges the pair by the same admission as a send, resolves the recipient live (herdr must name the seat on a pane of its session, running the CLI its record names; a recorded pane is never trusted on its own), reads the address from the registry and the pane, named so a stale address is never dialled, writes a route record before it answers, and dials nothing; the sender then addresses the session by name with its own cross-session tool; andteam send --record <seat> --channel native --ms <n>writes the delivery down as one history line, the body not passing through the CLI. TeamCLI attests nothing on the sender's behalf: a CLI process holds no permission mode, and a false attestation to another tool's gate would be spoofing (an owner decision). Spec: Specs-messaging, the route record and the address words (via §12). Proof:test/route.test.ts,test/send-native-channel.test.ts. Today (v0.5.0). Built (src/commands/route.ts,src/commands/send.ts), with the rules item a team pastes into its file quoted on the send page; this repository writes no team file. Measured on this machine in a live test of the channel, a routed delivery took a few seconds to a working seat and a millisecond to record; the figures are not a promise. A seat the registry holds no record for is refused a route:team uporteam registerwrites the record first. -
Admission is a rule table, deny by default, by chain position and capability. A send MUST be admitted by exactly one named rule, and the drop file's header says which: the owner, to any agent; the project rules first where the records know their projects; an orchestrator to an orchestrator of its own team or of a team of its entity, never across entities; a team's orchestrator or operator to any seat of its own team; the entity's assistant to the entity's main coordinator (the lead of the team whose project is the entity); any seat to its own team's orchestrator; and last an owner-signed send grant naming the pair and its expiry. Which seat leads is the roster's
leadsmark and which is the assistant itsassistantmark (a place in the chain, not a capability, commitment 3), never a role word; a pair with a record on each side and no rule is refused exactly as a pair the registry never knew, and the refusal lists the rules. Spec: Specs-messaging, the admission rule table (via §12). Proof:test/send-admit.test.ts,test/send/project-admission.test.ts. Today (v0.5.0). Built as described (002 Communication, the hybrid model; the project level included;src/send/admit.ts). A sender the registry holds no record for yet is judged as the seat the live file declares, so the rules inside its team still reach it (the bootstrap a seat needs before its firstup), and its header says the record is missing; a target in another team and a grant both wait for its record. The project-level admissions are settings, not capabilities (an owner decision:sendis admission). -
Every send and every route is a record. A completed send MUST append one line to the project's message history: the time, the sender, the recipient, the body, an id, the outcome, the milliseconds from send to outcome, the leg that carried it and the legs that failed before it; the history rotates at its size and keeps its set of files, and
team feedreads and follows it, across every project with--all. A route appends one line to the project's route records: the pair, the rule, the address and its state. A refusal, a dry run and--listwrite no history line and one log line.team messagesshows a message already waiting in a seat's mailbox and writes the receipt that says it was shown. Spec: Specs-messaging, the history and route records (via §12). Proof:test/feed.test.ts,test/messages.test.ts. Today (v0.5.0). The history, the route records andteam feedare built (src/send/history.ts,src/commands/feed.ts). The mailbox and its receipts are the read side of 002 phase 2:team messagesverifies and receipts a record, and nothing in this build writes one, so the watch's ring fires only on a record an earlier tool left (src/commands/messages.ts). The receipt as a trace of the seat state (commitment 8) waits on that phase.
-
A team never stands still in silence. The watch MUST run in a workspace of its own, labelled with the project, one per session:
upstarts it and records its pane, each pass writes its pid and a heartbeat, a second watch refuses while the first is alive, andteam checkflags a heartbeat older than two intervals. Every interval it reads the seats, their screens and herdr's words, the file (again, so a seat parked or stopped since is seen), the state and the machine, and prints what is wrong: a report is said when it starts and again only after it has cleared, except the operator's idle report, which repeats atwatch.idle_repeatwhile the same idle period continues, and the owner's idle escalation, said once per idle period. Each report is addressed to the owner or to the operator: the owner's (a permission prompt, a trust question, a vendor notice, a provider error, a rate limit, a machine figure past its limit, an account inside its reserve) and the operator's (a question, an idle seat, unsent text, a model that drifted, among others) are desktop notifications, and--no-notifysilences the operator's alone; the operator's are also what the nudge stands for, one fixed line typed into an idle seat so that seat reads the log. Every line goes to the team log with its time, and the machine's readings go there at the watch's own interval. Spec: Specs-seat-state-and-watch §3.1 to §3.5. Proof:test/watch.test.ts,test/watch-checks.test.ts. Today (v0.5.0). Built as described (src/watch/pass.ts,src/watch/check.ts). The interval, the idle windows, the blind window and the escalation to the owner are the enforced liveness policies of an owner decision, every level may shorten them and none may lengthen them, beside the blind window the project alone may lengthen; a lead or a parked seat is reported on but its idle time is not the team's;tempohalves or doubles the waits; the checks run in a fixed order with four always on and the rest switchable off per file;idle_repeatrepeats the operator's idle report while the same idle period continues, and the owner is told once. Nothing crosses from one team to another, and a stall is not named as such: the reports say which seat waits on what, by kind, never who is above whom (007 commitment 8, in part; the idle escalation of an owner decision is built at v0.5.0, §10 question 3). -
The watch types only the nudge, into an idle seat, and answers nothing. The nudge MUST go to a seat whose box is an empty idle prompt, never to the operator, the orchestrator or the pane the watch runs in, never to a dialog or a box holding unsent text; a box that holds the watch's own typed line is sent, not typed into twice, and only by the process that typed it. A permission dialog, a trust question, a vendor notice, a provider error and a rate limit are left alone and reported. The one key TeamCLI ever presses in a dialog is
team answer <seat> trust: the recorded key of a folder-trust dialog, on two fresh reads of the pane, only where the folder is the lobby on three readings at once, by the owner from outside herdr or by the orchestrator from its own seat, and only where the file's trust setting allows it (the default allows nobody; settled by an owner decision, §10 question 15). That is thepane-authoritypolicy's one sanctioned path (the Kernel's Policies section catalogue; 002 Communication): a key into another agent's pane belongs to its lead, a seat above it, or the owner's word for that case. Spec: Specs-seat-state-and-watch §3.6. Proof:test/watch-nudge-boundaries.test.ts. Today (v0.5.0). Built as described (src/watch/pass.ts,src/commands/answer.ts). The paths by which TeamCLI types into another agent's pane are three: a seat'steam send(the trigger line), the orchestrator'steam answer <seat> trust(the one key), and the watch's own nudge and ring; raw herdr keys from an agent remain possible and nothing refuses them.
-
The resolver: records in, one decision out, the rule named. The map says what admits a caller to each command; the bridge reads the caller as a record (the owner, or the roster line of the team at the root the command is about); the resolver MUST decide from the active grants, read fresh at every gate, and the same inputs always give the same answer. Deny by default and absent is deny; the most specific admitting rule wins and is recorded (a seat grant over a role's bundle, both under the team envelope); deny beats allow, because a revoked or expired record is not in the active set. A seat's effective authority on a capability row is its own list, the capabilities its role's resolved bundle names plus its own seat-level grants, intersected with the team's envelope, never a union: a team grant gives no seat a capability its role does not hold, and a seat grant only narrows. Every grant is read within its scope against the target, and a target outside the scope is refused under its own rule. A seat resolves within its own team's envelope and never another's. The mechanics are the Runtime's; what each capability means, and that a capability is not a competence, stays the Kernel's (§3, §4) (an owner decision, points c and f). Spec: Specs-grants, the resolver's mechanics (via §12). Proof:
test/permissions/resolve.test.ts. Today (v0.5.0). Built as described (src/permissions/resolve.ts,src/permissions/who.ts). The role bundle is empty in 0.5.0: the file declares no per-role capabilities, so capabilities come from grants alone, and the capability rows gate nothing yet (the map says so in each row). The placement proof is mandatory after an allow: a seat the map admits must stand on its recorded pane in the session judged, or the decision is unplaced. -
Standing grants and their revocation are signed records, read fresh at every gate. A grant MUST be a record in the owner's grants folder: the grantor (the owner), the grantee by registry identity (an agent id for a seat, a team id for a team), the kind written and never inferred, the capabilities from the closed vocabulary pinned to its version, the scope as absolute paths each inside a declared root (the roots themselves when none is given), the time issued, an optional expiry checked at every use, a generation from one sequence per folder, and the owner's signature over the record under a domain tag of its own, so a renamed or edited record is not a grant. A team grant never carries
grant,create,agreeorleads, and naming one is refused with the rule. A revocation is its own appended record naming the grant and its generation; it takes effect at the next gate check, depends on no ledger, and never restores an older record: a later grant under the same name is a new record (the decision record of the Kernel's Grants section, points a, d and g). Spec: Specs-grants, the grant and revocation records (via §12); thecapabilitiesregistry (via §12). Proof:test/grant.test.ts,test/grant-boundaries.test.ts. Today (v0.5.0). Built (src/grant.ts,src/permissions/grants.ts):team grant <seat|@team> --capabilities <cap,...> [--scope] [--expires] [--name]writes the record,team revoke <name>the revocation, both the owner's alone from a terminal outside herdr, with a dry run that refuses exactly what a write refuses and no mode that waives the gate. A seat grant names a registered agent's id, never the seat name, so an unregistered seat names nothing; a team grant needs the registered team. The file's older forms stay:team grant <seat> --scope <act,...>sets the orchestrator's one grant in the team file, andteam revoke grantremoves it. Of point (d) of the record, a holder renouncing its own grant and the cascade from a team grant to the seat grants inside it are not built:team revokeis the owner's alone and ends one record. Nothing tells the owner of a grant or a revocation beyond the command's own line, which the owner is running (§10, question 8). -
A delegate entry is the owner's standing authorization; the delegate is the actor. The file's
delegatessection MUST name only panes outside the team's session, each with a command list out of the acts the map knows, and the file'sgrantnames the orchestrator's seat for a set of lifecycle acts; both are owner sections, and an entry can never widen itself. A delegated run is attributed before its effects, in the log and in the record it writes: the owner as signer, the pane as actor, the one command the mark speaks for (§9: the ledger keeps the approver as signer and the submitter as actor). A delegate adds only a same-copy seat, one the file already declares exactly as written, and nothing that would edit the file; a delegate'sdownstops the whole team; a delegate'sremovenever reaches a lead;swapadmits the replacement of a lead's agent and nothing else;restartis not delegable. In 0.5.0 adelegatesentry is read as a standing grant with a command list (the Kernel's Policies section, open question 4, closed for 0.5.0 by an owner decision). Spec: Specs-grants, the delegation record and the delegate entry (via §12). Proof:test/delegate.test.ts,test/delegate-section.test.ts,test/permissions/delegates.test.ts. Today (v0.5.0). Built (src/commands/delegate.ts,src/permissions/grants.ts):team delegate <session/pane> --commands <act,...> [--dry-run] [--json]writes a delegate entry, owner-only, with a dry run, and an existing delegate cannot widen itself; the agent record's provenance carries the delegation. The wordapproveis still read in a command list and in the grant's scope so that older files parse, and no command consults it:team approveis not a command, granting is the approval (the owner's decision of 2026-10-15; the record's point b; the Kernel's Policies section §2.10). A delegatedregisterwrites the log line and not the record's mark. The create-grant record names its grantee by a registry identity alone, and a record spelling a name, a seat, a pane, a session or a runner grants nothing (an owner decision; §10, question 14); its paths are the ones it names or the roots the entity declares in the machine's entity configuration, narrowed never widened, and no root is in the source (an owner decision; §10, question 2); it admits its grantee to the lifecycle acts the map names under the paths it covers, before it expires.
-
Every piece of work is an item one seat holds, and the Runtime keeps time.
team issuesMUST list the typed records of the one source the team file names;team nextclaims one and holds it by a lease in this clone, releases it, and waits at the file's cadence;team planprints the queue a claim would consider, a passed deadline marked and never dropped;team broker, the owner's foreground process, one per clone, holds the tracker's credential and answersteam nextover a local socket, the file's policy filtering every record before it crosses. The plan lives in the tracker the team already uses; with none, in the file (007 commitment 11). Spec: Specs-tasks-and-broker (via §12). Proof:test/issues.test.ts,test/next.test.ts,test/broker-contract.test.ts. Today (v0.5.0). Built as listed (src/commands/issues.ts,src/commands/next.ts,src/commands/plan.ts,src/commands/broker.ts). The lease is local to the clone, nothing writes the tracker or the file, nothing is scheduled, estimated or kept beside what happened, and the broker runs as the same OS principal as the seats: integrity, not authenticity, isolating nothing. The broker process is Planning's and hosts the Kernel's credential-withholding and per-seat check (§11, §13); the Runtime only runs it. The item lifecycle of 007 commitment 11 (asked, taken, waiting, checked, done), kept by 008 Planning, is not built.
-
What the Runtime keeps, where, and how it is written. Five record sets MUST each be written
whole or not at all: the registry (one file per agent, one teams file, one projects file, each
under a lock and an atomic rename, with provenance on every record); the owner's grants folder
(grants, revocations, send grants and create grants, plain files, no link followed, a
generation sequence for the signed ones); the project's state folder in the owner's home (the
message history and the route records, rotated at their size, their set of files kept); the
team's state beside its file (the seats with their stage, pane, workspace, launched identity
and what the launch declared, the worktrees, the watch, the hold, the processes and the
retained handles; written under a lock through a temporary file) and its log (one cleaned line
per change, when, which command, by whom, what, rotated at its size, a write that fails dropped
so no command depends on it); and the seat's own files (the hooks' settings and state, the drop
files). The log is evidence, never a decision.
Spec: Specs-launch §3.5;
Specs-registry §3; the record sets' shapes are handed to
Specs-records-and-ledger (via §12). Proof:
test/state.test.ts,test/log.test.ts,test/unsigned-state-boundaries.test.ts. Today (v0.5.0). Built as listed, and this is the whole of §15 that exists: no record carries the hash of the previous one, there is no signed head, no intent and outcome pair around an act, no refusal record beyond a log line, and no reconciliation; the owner's stop and a revocation never depend on a store (the one §15 property that holds, by there being no store to depend on). The owner is told (§11) by the watch's desktop notifications for the reports addressed to the owner and by each command's own stderr; nothing reaches the owner unasked for a grant, a delegate's act or a revocation. The machine-wide stop is not built: there is onedownper team.
Accepted 2026-10-18 as amendment 01; frozen, editorial changes only.
-
Declared gates run under bounded machine-wide slots. TeamCLI MUST run a project's declared
light check, background hub sweep, hourly full suite and pre-push gate under bounded
machine-wide light, heavy and hourly slot locks that reclaim dead holder processes by checking
both process liveness and process start time while keeping the shipped
team locksingle-lock semantics intact. No process may wait for a heavy slot while holding a light slot or wait for a light slot while holding a heavy slot, and any single process MUST hold at most one heavy slot. The light check MUST run under a wall-clock timeout that terminates only its own test process tree and detaches a background heavy-slot sweep for deferred hub and tail tests. The hourly full suite MUST sweep any prior interrupted run's missing report first, skip when the tip SHA is unchanged or when any heavy slot is held (logging the skip so a skipped hour is never mistaken for a passing one), and guarantee through an exit trap and pending sidecar that any interrupted run writes a missing-report notice and red marker and frees its locks. The pre-push gate MUST scan against the entity's private-patterns file and fail closed when the file is missing, unreadable or matched;team gate pushMUST acquire one of the four light slots during its dependency-aware test leg (an owner decision; §10 question 25). A gate lock with no readable process id MUST never be auto-reclaimed by a timer and MUST be cleared only by an explicit owner command after verifying no runner is active. Spec: Specs-accounts-and-gates §3.5, §3.6, §4.1, §4.2, §5 Rule 6; Specs-quality-gates §3, §4, §5. Proof:test/lock.test.tsat v0.5.0 (52db9b75) forteam lock/team unlock; gate script stub suites (hourly-suite.test.zsh,lock-reclaim.test.zsh,light-check-limit.test.zsh,light-check-release-race.test.zsh,cli-smoke-selection.test.zsh) outside the repository; none yet insrc/forteam gate. Today (v0.5.0). In part:src/lock/machine.ts(built at v0.5.0, 52db9b75, and unchanged at int/0.5.1, 8acb470b) implementsteam lockandteam unlockwithwhoholder files;team gateand thelstartprocess-reuse guard are not built at v0.5.0 or at int/0.5.1 (8acb470b), and the gates run from external zsh scripts with two-line/one-lineownerfiles andkill -0reclamation.
Cross-reference: the locks and atomic writes it extends are commitment 26's (this chapter).
-
The policy store, the load and the view are the Runtime's mechanics; the rules are the Kernel's Policies section's. The Runtime MUST keep one source per level (the Kernel's Policies section §2.12): the entity's
configuration under the tool's own folder, the project's registry record, the team file's owner
sections and the seat's own registry record; write them through
team policyunder the setters the Kernel's Policies section names (§2.4), signed as the grants are, with the provenance and the owner's notice of §2.6; read the chain outermost first, fresh at every gate, and refuse a command whose chain it cannot read, verify or order, naming the level; and answerteam policywith the effective value per level, its setter, its expiry and its kind, from the one resolution the gates use. A policy is a reserved object (§3): the store is written by the tool's own commands alone. Spec: Specs-policies (via §12); thepolicy-namesregistry (via §12). Proof:test/policy.test.ts,test/settings-as-policies.test.ts. Today (v0.5.0). Built (src/policy/types.ts,src/policy/sources.ts,src/policy/resolve.ts,src/commands/policy.ts): four sources, the policy object with its signature and generation,team policy setandunsetwith--until,--kindand a dry run; the chain is read outermost first, a source it cannot read or verify refuses naming the level, an expired value is unset at its level, and a lower level may tighten but never loosen, a loosening being refused at load naming both levels.team checkreads the team's and the seat's chains and reports a legacy field shadowed by a signed policy (src/check/team.ts). The advised names gate nothing, and the owner's notice is the command's log line.
Accepted 2026-10-18 as amendment 01; frozen, editorial changes only.
-
One entity-root command and one-release forwarders carry the migration. TeamCLI MUST
provide a canonical entity-root lookup command (
team root) and an in-process launch-environment forwarder command (team launch-env), so the remaining launch, provider-account (deepseek,glm,kimi), identity and gate wrappers stay as one-line forwarders for one release while teams migrate one by one (after the six obsolete scripts already removed ineca38e5). Per two owner decisions, the replacement of the two session-resume wrappers, the three provider wrappers, the entity GitHub identity wrapper and the gate scripts folder is targeted after the event-driventeam sendwork of an owner decision and is outside 0.5.1's guaranteed scope unless time allows;merge-train.shis deferred to Runtime amendment 02 after 0.5.1. Migration MUST touch nothing during 0.5.0, ship usage attribution and dry-run equivalence checks first, populate each entity's configuration files and import verified session transcripts before reloading resumable seats, migrate non-primary entities first and the tool's own team last while seats are idle with external backups, and delete the forwarders once zero references remain. Spec: Specs-accounts-and-gates §4.2, §5 Rules 4, 7. Proof: none yet. Today (v0.5.0). Not built at v0.5.0 or at int/0.5.1 (8acb470b) forteam rootorteam launch-env;src/entities.ts(built at v0.5.0, 52db9b75, and unchanged at int/0.5.1, 8acb470b) loads<entity>.rootsfrom the machine entities file for grant path narrowing (src/grant.ts).
Cross-reference: the root rule the command answers is commitment 47 (chapter B); the entity configuration it reads is this chapter's (commitment 27).
Each commitment answers something that happened, the older ones in 007 §3 and these since:
- The registry. After a power cut every seat of three teams came back as a different model than its label said, and nothing noticed (007). The tool had needed an agent's place renamed by hand for it to be recognised (007); on 2026-10-16 the owner set the registry first (an owner decision). Since 0.5.0 a seat is a record with an id, and a pane is where the record points.
- The seat state. The watch nudged seats that were working and left seats that were blind; the owner asked for one state per seat with its source, read from the CLI's own signal first (2026-10-17). The same morning the watch could not reach the coordinator's pane because its box held unsent text, and nudged only the idle seats: the reports reached the owner through another seat.
-
Delivery. A review brief sat typed and never submitted in a reviewer's box for hours; a
socket frame reached a Claude Code seat in a quarter of a second and was held by its dialog,
blocking the box.
deliverednow rests on evidence, a receiver-side hold isheld, and the order of the legs is the receiving seat's policy. - Dev mode. A team's own registration was refused in dev mode on 2026-10-17 at 00:15; the owner bounded the lift to the everyday operations and kept the owner powers outside (an owner decision).
-
Grants. On 2026-10-16 a brief sent a seat to
team initin a folder the entity did not declare, and a grant file named another entity; the owner had the grant revoked and the file trashed, and asked for grants at team and seat level, never by a role's name (an owner decision). The signed records and the resolver of chapter G are the answer, and the hard-coded roots still in the source are question 2. - Checks. A release candidate was cut on light checks and its full suite came out red; the owner set the hourly suite in a heavy slot, which is what the machine lock is for (an owner decision).
- The ship. A team is a ship: its seats are stations, the agents that stand them are on watch, and the registry is its log. A message is addressed to the station, so a change of watch never breaks the line.
- A Runtime reads other companies' programs. To know a seat's state it reads screens, hooks and herdr's words; each lab changes its program when it likes, and each CLI's screens are captured at a version. When the reading cannot be made the state is unknown and the text says so; it does not guess. A new version of a lab's program can make a commitment here untrue for that lab until the profile catches up (007 §4).
- Records are files on the owner's machine. The registry, the grants, the history and the state are one more thing an agent can read, until containment (§11, §12). They hold no secret: the hooks take nothing from the CLI's input, the log keeps classifications and never a screen's text, the process identity keeps pids and never a command line.
- A reading is not a fact, and a record is not a right. The seat state, the label and the delivery evidence are observations with a named source; the registry and the roster are reports. Authority is the Kernel's and comes from a record the owner signed.
- A handover carries facts, not judgment. The agent going off watch writes what is done, what is in progress, who it waits on and what comes next; where it cannot be asked, TeamCLI writes that from its records and says "not known" where the record is silent. The agent coming on reads it first and says back what it understood before it acts. What it inherits is a report, not a decision, and a judgment written as a fact costs the next watch what a gap costs (007 §4; commitment 13).
- Noticing is not fixing. The watch names the repair and prints the command; the one repair the Runtime makes by itself drops the state's own leftovers (commitment 13).
- Not covered here: what a capability means and who holds it (the Kernel); what a role is and how a skill is delivered (009); how messages are worded and what a receipt means (002); the round, its thresholds and its daily report (010); what counts as done (005); how several voices decide (006); the broker's process and the work queue's policy (Planning, 008).
The decision record's lines, and the Runtime's own. At the tag the printed block holds five
plain-language entries, before team doctor's full run and team --about, not in team status
or team check (src/permissions/must-not-pretend.ts).
The decision record's lines:
- Integrity, not authority: every gate 0.5.0 ships holds against a mistake, not against an attempt.
- Standing grants with an expiry, not leases.
- No two-granter agreement, no
agree, nocreatebounds. - No read scoping (§3, every disclosure is a
read), noact-as, nouse-broker, nodeploygating. - No constraint program beyond the one-
leadscardinality and launch-time mutual exclusion (§5).
And the Runtime's own, which the texts above say where they apply:
- Placement is process ancestry. A caller is placed by its parent processes and herdr's vouch, which a process of the same user can forge; a seat's pane is an accident guard, not a boundary.
- A state is a reading. Every seat state names its source, and unknown is a word, not a fact; a screen the profile cannot read, a CLI whose program changed, a herdr that lags each make the reading wrong until the profile catches up; each CLI with a profile is captured at a version.
-
deliveredis evidence of submission, not of reading. The seat took the line; whether it read the drop and understood it is the seat's. - A record is a report. The registry says which agent a seat is, as strongly as the machine's honesty; every record and view says so.
- The ledger is not built. The records of commitment 26 are five files, none chained or headed.
- The stop is per team. One owner action does not stop every team on the machine.
- An agent started on the side has no record. It is unknown to every gate, counts against nothing and cannot be stopped with the team (007 commitment 4); until containment the tool refuses to count it and cannot prevent it.
- Labs offering, themselves, a state signal, a delivery channel and a stop for their agents, as Claude Code's hooks and cross-session channel already do in part. Then the Runtime should read theirs first and keep the screen reading for the CLIs that have none, which is the ranking of commitment 8.
- A registry that people do not read and the commands do not use. Then it is a file, not a commitment (007 §5). Today every send, route, grant and check reads it.
- Stall reports that fire when nothing is wrong, turned off by the teams that run them. Then the thresholds are wrong or the state is, and 010's round should say what "moving" means.
- A ledger whose cost in writes and reconciliation exceeds what the Kernel's gates need from it. Then §15's first files are the grants and the outcomes of gated acts, not every record of chapter I.
- Handovers prove to be ceremony. If teams change agents often and work no worse without handovers, 007's commitment 7 shrinks to a restart, and so does the handover this text carries in commitment 13; that is the standing test of its worth (007 §5's first reversal).
"Today" is the tag v0.5.0 (52db9b75), released 2026-10-18, read only and clause by clause (the current text's first reading was at 1342e0b4; every row below was re-read at the tag, and rows 49 to 53 also at int/0.5.1, 8acb470b, unreleased). Rows are the commitments above.
| # | Commitment | Today |
|---|---|---|
| 1 | The Runtime decides nothing of authority | Yes, as far as the map reaches: a closed table, every refusal named; the gates hold against a mistake only |
| 2 | One record per seat, immutable id | Yes. team rename keeps the id and the grants; no launchers registry, no resume record |
| 3 | Teams, projects, the chain | Yes. The entity declares liveness and policies in the machine's configuration; still no entity record; no cost view |
| 4 | A record confers no right | Yes |
| 5 | Registration at launch; team register
|
Yes, --pane included |
| 6 | Departed seats | Yes |
| 7 | The lobby, recorded per session | Yes |
| 8 | One state per seat, ranked sources, blind | Yes. The receipts as a trace and the round's thresholds are not |
| 9 | The label follows the observed value | Yes. The observed model is not on the record (§10 q11) |
| 10 | One command starts the team | Yes, with the dialog close path's conditions. No hash-pinned start command, no execution-context digest |
| 11 | The §9 table as code; placement | Yes. No constraint re-check beyond one leads
|
| 12 | Gate-lift, the caller gate alone | Yes. The dev-mode policy object and the logged use; two words beyond the decision's seven (§10 q1) |
| 13 | Stop, restart, remove, the handle | Yes for one seat; whole-team restart designed; no handover; one repair |
| 14 | The machine | In part: checks, readings, locks; no wake, battery or recovery |
| 15 | One confirmed outcome per send | In part: the typed path as described; the jules compose path types the brief through the CLI's screens and proves delivery by a created session |
| 16 | The delivery order as the seat's policy | Yes for the walk and the chain, and the order is a signed policy at every level; the typed leg is the only one team send makes; no socket-accepted leg |
| 17 | The native channel | Yes: route, the sender's own tool, --record
|
| 18 | Admission, deny by default | Yes, the project level included |
| 19 | Every send and route a record | Yes for the history and the routes; the mailbox is read-only, nothing writes a record |
| 20 | Never still in silence | Yes: reports by kind, the escalation, the nudge, notifications; nothing across teams; a stall is not named as such |
| 21 | The nudge only; team answer <seat> trust
|
Yes; raw keys from an agent are not refused |
| 22 | The resolver | Yes; the role bundle is empty and the capability rows gate nothing |
| 23 | Standing grants and revocation | Yes; the owner is told only by the command's own line |
| 24 | Delegate as signer and actor | Yes; a delegated register writes no mark on the record |
| 25 | Work items and time | In part: queue, lease, plan, broker; no lifecycle, no time |
| 26 | The records and the store | In part: five record sets; no chain, head, intent, outcome or refusal record; no machine-wide stop; the owner told by the watch and stderr only |
| 27 | Policies: the store, the load, the view | Yes. The store, four sources, the chain and team policy; the advised names gate nothing, and the owner's notice is the log line |
| 28 | The registry is the home of a team's definition | Not at all: team.yaml in the project root is still the definition; no role, brief or seat record is set by a command, and no export or import exists |
| 29 | Storage is a backend, never the authority | Not at all: files in the machine's configuration, no contract, no second backend, no add-on |
| 30 | No workspace backend is a dependency of the core | Not at all: the core calls herdr directly |
| 31 | A seat's persistence does not depend on a live process | Not at all: no conversation record and no resume; a seat's life is its live process |
| 32 | Headless seats are turn runners | Not at all: no headless path and no turn runner |
| 33 | The optional adapters keep a CLI alive only for viewing | Not at all: herdr is required; a run outside it with no terminal is refused (commitment 11) |
| 34 | Status events, recipients and escalation are TeamCLI's | Not at all as an adapter commitment: the watch's reports are TeamCLI's; the status events are not built |
| 35 | An adapter's states map onto the five | Not at all: no adapter contract exists |
| 36 | Waiters and turn runners never answer | Not at all: no status waiter and no turn runner; the watch's nudge is commitment 21's |
| 37 | Every status event is a signed record | Not at all: no status event and no signed event record |
| 38 | Agents are connected; seats are attributed; the address is the seat | Not at all: the record is one per seat, with no attribution or watch |
| 39 | The session record, written by the tool | Not at all: no session record, no team sessions, no team resume
|
| 40 | The model rule is an entity policy, carried out across the entity | Not at all: no model rule; the watch reports drift against the file only |
| 41 | A swap waits for the task boundary; a broken seat at once | Not at all: no queue, no swap; restart relaunches without a handover |
| 42 | Temporary seats and worktrees end on proof; the watch removes only what it may | Yes, with two named gaps: end conditions, own-commit proof, worktree removal and its refusals are built; a result: path that is a symlink is accepted (the check never stats, and the existence test follows a link); and the watch reports a temporary seat's end but never removes it, so the owner's team remove is the stop |
| 43 | One writer over a seat's dialog state; every answer records its recovery | Yes |
| 44 | A launched seat's child gets only its declared Git identity | Not at all: no declared identity and no clearing; the herdr server's clean environment passes the owner's SSH_AUTH_SOCK
|
| 45 | Commits that claim a seat are checked against the declared account | Not at all: team check compares no author or committer with a declared account |
| 46 | A message to a seat with no agent on watch waits, and the sender is told at once | Not at all: no inbox wait, no "off watch" receipt, no lead notice |
| 47 | The project root is selected by one rule; a folder root is shared-only | In part: the main checkout and the invocation-directory plain-folder loader are selected; the lexical walk to a parent, the symbolic-link stop, the folder-root restrictions and the Git-required refusals are not built |
| 48 | Setup detection is read-only; a proposal's preview bytes are rechecked before application | Not at all: no detect, presets, preset or guide, no proposal and no preview transaction |
| 49 | A seat's conversation is resumed deterministically, or the seat is refused | Not at all: no resume: true, no fresh-conversation request and no per-conversation lock; agent_session and start_cwd are recorded for live-pane continuity only |
| 50 | A seat's declared account resolves against the entity's launch accounts first | In part: entity roots, policies and machine billing accounts are read; entity launch accounts, keychain reads at launch and attribute-only keychain checks are not built |
| 51 | A seat is launched only under its entity's GitHub identity | Not at all: no identity.yaml and no built-in Git environment injection; seats use external wrapper scripts |
| 52 | Declared gates run under bounded machine-wide slots | In part: team lock and team unlock with who files are built and the gates run externally; gates:, team gate and the lstart guard are not built |
| 53 | One entity-root command and one-release forwarders carry the migration | In part: six obsolete scripts are removed (eca38e5) and src/entities.ts reads <entity>.roots; team root and team launch-env are not built |
Fifty-three rows: seven hold with nothing missing, eighteen hold with a named gap beside them, seven in part, one (the ledger of §15) in its first files only, and twenty not at all (the eight workspace-adapter commitments 30 to 37, the registry as the team's definition, pluggable storage, the four commitments of 2026-10-19 — seat attribution, the session record, the model rule and the queued swap — the three added the same day: the child's Git environment, the author and committer checks, and the off-watch message; the setup detection, proposal and preview commitment; and two from Runtime amendment 01 (commitments 49 and 51) — seat conversation resume and the entity GitHub identity). That is further than 007's table of 2026-10-06 (five of eleven in part, six not at all), and the shape of what is left is clear: the ledger, the handover, the escalation, the machine's sleep, the sharing controls, and Runtime amendment 01's launch, account and gate mechanics.
- Every gate is integrity, not authority, until containment (§11, §12): every seat runs as the owner's user and the signing key is readable on the machine. The Runtime says so in every view that carries a right, and the must-not-pretend block is printed where the check runs.
- The registry is written only by the tool, atomically, under a lock, and a record the writer would refuse is never handed out: a file whose body disagrees with its name, or that fails the writer's own rules, reads as no record. A registry that cannot be read refuses every seat, closed.
- A record confers no right, and a record's absence is a refusal: a seat the roster does not list is refused what the file says it holds; a caller with no record is refused and told the rule.
- Nothing is typed into a pane that shows a dialog or holds text, by a send or by the watch; the one key TeamCLI presses in a dialog is the trust key, on two fresh reads, where the file allows it, by the owner or the orchestrator.
-
Dev mode lifts the caller gate only, for the everyday operations, with a warning, a mark on
the record and a log line for every use; it never reaches
grant,delegate,revoke, the owner sections or the trust record. - No path is a boundary: the lobby gate, the trust list and the declared roots are checks against a mistake, and a folder is not a boundary (§12). The texts name no operating-system folder (an owner decision): the roots are configuration, and a path hard-coded in the source is a defect (§10, question 2).
- The history keeps bodies, the log keeps none: a message's text is in the project's history, in the owner's home, and never in a lobby or the checkout; the log and the route records keep sizes, outcomes and ids.
- A delegate's reach is an allowlist (same-copy add, the ordinary sections, never its own entry), and its placement by pane ancestry guards a mistaken agent, not a hostile one.
Tier 2, between the Kernel it conforms to and the modules that use it (Kernel §16; the organisation
of 2026-10-17). It implements the registry, the seat state, the launch, the channels' adapters, the
watch, the resolver's mechanics, the records and the meters; it defines no capability, no admission
rule's authority and no policy. Who may run which command and who may agree to more: the Kernel and the Kernel's Grants section. The policy object, its levels and its catalogue: the Kernel's Policies section. How agents and people
reach each other, what a message's receipt means, and the rules of a pane: 002 Communication; this
text supplies the adapters, the records and the outcome words. What a role is and which seat holds
leads: 009; the Runtime reads the mark. The round, its liveness thresholds and its daily report:
010; the Runtime supplies the seat state and the timers. What makes an item checked: 005. How voices
become one decision: 006. The work queue's policy and the broker's process: Planning.
None argued in this text.
Each was found where the code and a decision differ; none is answered here except where an owner decision settled it. Questions 19 and 20 are the concept note's open points, put to the owner; questions 21 to 25 are Runtime amendment 01's five, folded here on 2026-10-19 and settled by the decisions named beside them.
-
Dev mode's reach: settled (an owner decision). Exactly the seven operations of an owner decision
and the Kernel's Policies section §2.7;
remove --abandonstays the owner's even in dev mode;team broker,team tempoand a delegate's file-editingaddare outside; every dev-mode use writes the log line. At v0.5.0: the policy object, the variable honoured only until a value governs, every use logged, the four reaches outside; the code's list has nine words, the seven andreloadandrename, which the round on the Kernel's Grants section confirms or takes out (grants.md, question 4). - An entity's roots hard-coded in the source: settled (an owner decision). The fix reads roots only from the entity's declared configuration and removes the line from the trunk at the merge; the trunk's history stays as it is, and the names go into a private patterns file the gate scripts scan. At v0.5.0: done; the roots come from the entity configuration alone.
- Liveness: the defaults settled (an owner decision), two points open. An idle seat is told to the lead and to the owner at the decision's windows, and a seat unknown past its blind window is blind; all three are settings. At v0.5.0: at the decided values, as enforced policies; the two idle windows only ever tighten, and the project may lengthen the blind, trace and hook windows. The 010 text's two-minute unknown threshold is read as five minutes (the decided blind window, 300 s; seat-state-and-watch.md §3.2). Still open: the code ranks a fresh trace above an idle word, which 010's order does not, and lets the project lengthen a threshold the entity set, which the Kernel's Policies section §2.3 does not; decide the order and which level may loosen.
-
The
socket-acceptedleg. The catalogue'sdelivery-orderpolicy names four legs; the code knows three, and itsnativeis the sender's own tool with TeamCLI's route and record, which matches the catalogue's definition.socket-accepted(the owner lowering a seat's guard by an explicit act, recorded at launch) is planned, not coded. Keep it in the policy as planned, or drop it until it exists. -
team list's second word. Its three states read defined, approved and running; sinceteam approveleft the command set, "approved" means "the team file loads and validates". Rename the word, or keep it with that meaning said. -
register's admission. The decision record's row says the owner or the seat's own team; the code also admits adelegatesentry namingupand the file'sgrantnamingup, as a launch would be admitted. Consistent with the delegate reading of commitment 24. Resolved in the fold: the registry's register row now names the admissions (registry.md operations table), citing note 3 and row 9. -
The hold.
team holdis a note the state shows and the seat state reads as held; no command, launch or watch changes what it does while one stands. Whether a hold stops a round's merges or a launch is 010's to decide, and the Runtime then enforces it. - The owner is told. §11 wants a notice for every change to what a team may do (a grant, a lease, a revocation, a rebind, a ceiling change, a lost minimum), delivered by the Runtime without being asked. Today the watch notifies the owner of its own reports and the commands print to the owner who runs them; a delegate's act and a dev-mode run leave a log line and a mark. Decide the minimum notice channel for 0.5.x (the owner's channels are phase 5 of an owner decision).
- The ledger's first file. §15 is defined and kept here; the records exist in five places, none chained. Which of them does the ledger absorb first, and does the signed head come with the first gated act or with the grants?
-
The mailbox.
team messagesreceipts a record and nothing writes one; the trace reader says the receipts are a later phase. Confirm 002 phase 2's record shape before the Runtime keeps it. -
For the build: The observed model on the record. The commit-signature policy matches a signature's model
against the seat's observed model (the catalogue's
commit-signatureblock, on an owner decision); the record carries the file's signing triple, and the observation lives in the watch's memory and the labels. Decide where the observed value is stored, and whetherteam registerwrites it. -
The project's delivery order: answered in the code, not by a decision. The project record
reads a
delivery_orderfield, and at v0.5.0 a signed project-leveldelivery-orderpolicy, written byteam policy set, governs it;team checkreports the legacy field when a signed policy shadows it. Whether the legacy field is retired, and who may set the project's policy, is the policies round's. -
The reach projection. One file per lobby describes the reach grants of the team whose
launch ran last, for the bridge and the shuttle (the MCP seam). It belongs to 002 or to the
Runtime's adapters; the Kernel's
sendadmission does not read it. Decide its home and whether one file per lobby is enough once two teams serve a front. -
The create-grant's admission: settled (an owner decision). A create-grant admits by registry
id only, an agent id or a team id, never an agent name, a session or a runner process name.
At v0.5.0: done, by registry id only. Whether a create-grant to an agent id is the
createcapability of Kernel §10, which the record says no agent holds in 0.5.0, is the next revision's question. -
The trust key: settled (an owner decision). A lead answers a trust prompt on the owner's
word, through a setting only the owner turns on, off by default: the catalogue's
pane-authorityas written, and the code'sdialogs.trust. The grants record's row forteam answeris amended to say so. - Offline behaviour and conflicts. An owner decision leaves it to specify: a store the machine cannot reach either works from a local cache with queued writes or refuses, and two writers' changes either meet the contract's atomic compare-and-set or wait. Nothing is decided here.
-
Moving between backends. The same decision leaves the move to specify, under the names
team registry exportandteam registry import; the file copy outside a repository (team exportandteam import) is the neighbouring surface, and whether they are one pair of commands or two is open. - The backend as an entity setting. Also left to specify: one store per entity, shared by all its projects, with the setting where the entity's other configuration lives, who may change it, and how a project's team finds it.
- Settled by an owner decision: a message to a seat with no agent on watch waits in the seat's inbox until an agent is attributed; the sender gets an "off watch" receipt at once; the team's lead is told at the next status, at once if the message is marked urgent. Commitment 46 carries it.
- Settled by an owner decision: one agent per seat at a time, always; parallel work is parallel seats.
- Settled by an owner decision: the unattended per-launch macOS Keychain reads of the
seat's declared
account.keychainandidentity.github.keychainentries join Kernel §11's disclosed exceptions, and--fresh, UUID-plus-transcript validation,skip_permissions,key_prefix_denyand thegithub_pat_prefix check are standardized when Runtime amendment 01 ships. Commitments 49, 50 and 51 carry it. - Settled by an owner decision: short-lived GitHub App installation tokens (
ghs_…) are accepted alongside fine-grained PATs (github_pat_…) when the identity declares an app-installation kind, while classic (ghp_…) and OAuth (gho_…) tokens are refused. Commitment 51 carries it. - Settled by an owner decision: the machine-level billing
accounts.yamlstays separate and linked byusage_account:, preserving billing-only seataccount:entries, until the registry's pluggable storage holds accounts, and then migrates. Commitment 50 carries it. - Settled by an owner decision: a test uses a fixture entity named by the test itself, never a real entity; the TeamCLI team picks the name.
- Settled by an owner decision:
team gate pushacquires one of the four light slots during its dependency-aware test leg. Commitment 52 carries it. - The config carry as numbered promises. An earlier proposal asks for the config direction (three owner decisions) as a numbered Runtime promise with the config spec link, target 0.5.3 and its Today unbuilt, the two revoked decisions not revived. That would add commitments, so it is not an exact fold item; the carry below stands as written until the question is decided.
- The MCP and voice carries as numbered promises. An earlier proposal asks for explicit promises for the generated command tools and the device-tested voice matrix, each command's authority rule, logging and confirmations kept, read-only in 0.5.2 and state-changing in 0.5.3, and the non-MCP fallback left a study. That would add commitments, so it is not an exact fold item; the carry below stands as written until the question is decided.
To fold at the round: three owner decisions. Changing a seat's model and effort; the
0.5.3 shape with three commands — team config for the levels above a seat, team settings for a
seat's settings, team seat for the seat as an object; one key registry; restart and resume for a
live seat and the next turn for a headless one; signed and logged. The spec draft is
Specs-config; none is built at v0.5.0. (The two revoked decisions are not folded.)
To fold at the round: two owner decisions. The TeamCLI MCP offers every command: its tools are generated from TeamCLI's own command list, so a new command reaches the MCP without extra work; the same rules as the terminal hold (the caller is the signed-in owner, each command keeps its who-may-run rule and is never looser, and every call is logged); sensitive commands — grant, revoke, forced remove and publish — show the plan and run only on the owner's confirmation. The target is read-only commands in 0.5.2 and state-changing commands and confirmations in 0.5.3, with the transport kept by the MCP server and the tool list and command runs provided by TeamCLI. Voice from any lab's mobile app: the owner can talk to teams from any lab's mobile voice mode, not only one bot, over a lab-neutral MCP; the first step (0.5.2) is a device-verified matrix of mobile voice clients (Claude, ChatGPT, Gemini, Grok, Meta and others) against a remote MCP call, authentication, reading a long answer aloud and confirming an action; state-changing commands are read back and confirmed aloud, and every call is logged; a fallback where a voice app cannot call MCP is to be studied, not decided.
-
Specs-registry §3, the agent, team and project records; §3.5, the
planned store (commitments 28 and 29); §5, the rules; §6, the
operationsandexit-codesentries this area writes. -
Specs-seat-state-and-watch §3.1, the state's sources;
§3.2, the thresholds; §3.3, the checks; §3.4 and §3.5, the report; §3.6, the two typed lines;
§3.7, the watch record; §3.9, the two sidebar lines; §5, the rules; §6, the
seat-states-and-prompt-kindsandpolicy-namesentries. -
Specs-launch §3.1 to §3.6, the rules delivery, the profiles, the
overrides and the state file; §3.7, the lobby; §4, the commands and the exit codes; §6, the
operations,exit-codesandcli-rangesentries. The handover of 007 commitment 7 — the four facts, the reconstruction from records with "not known", and the arriving seat's read-back — is handed here for launch.md to specify (commitment 13). -
Specs-workspace-adapters §2 to §6, the eight proposed
workspace-adapter commitments (30 to 37), the terms, the contract's operations, the herdr and
tmux mappings, the turn runner's flags, the state mapping and the status events; §6, its
workspace-adaptersandseat-statesentries. -
Specs-operational-safety §3.1 to §3.7, the end conditions
and their proof, the temporary seats, the worktrees, the one dialog writer and the manual
marker, the answer's checks and recovery, the child's Git environment and the commit account
rule; §4, the commands and their result ids; §5, the rules; §6, the
exit-codesrows; the waiting record'sstatevalues andmanualfield are Specs-launch §3.5's, read here and not contributed again. -
Specs-projects-and-knowledge §3.1 to §3.6, the
knowledgesection, the resolved directory, the README and init stub, the delivered rules line, the output lines and the approval record's observation; §4, the commands; §5, the rules; §6, theexit-codesentries and the vault mapping. - Specs-setup-and-team-models §3.1 to §3.3, the detection report, the presets and model package, and the preview; §4, the commands at the tag and the proposed read-only interfaces; §5, the rules; §6, the proposed result ids.
-
Specs-accounts-and-gates §3.1 and §3.2, the resume fields
and the per-conversation lock; §3.3, the entity launch accounts; §3.4, the entity GitHub
identity; §3.5 and §3.6, the private patterns and the declared gates; §4.1 and §4.2,
team lock,team unlock,--fresh,team check --repair,team root,team launch-envandteam gate; §5 Rules 1–7; §7, its open points. Commitments 49 to 53. - Specs-quality-gates §3 to §5, the gate test selection, the reports and the markers (commitment 52).
Registries this text contributes to: operations, exit-codes, cli-ranges,
seat-states-and-prompt-kinds, policy-names, delivery-legs, capabilities.
Lines for other areas, for their owners to take (§12's rule in the plan):
- for messaging: the outcome words and the drop file's header; the trigger line; the retry and verify windows; the delivery legs and the within relation for a list; the route record and its address states; the admission rule table; the history and route records, their fields and rotation; the mailbox record and its receipt; the address by seat, delivered to the agent on watch (an owner decision).
- for grants: the command-to-capability map's rows, one per command; the grant and revocation records, their fields, the capability vocabulary, the scope and the domain tag; the delegation record and the delegate entry; the create-grant record's fields and its five acts.
-
for policies: the policy object's fields; the four sources and their paths; the chain's
order, the refusal on an unreadable or unverifiable source, expiry and tightening-only; the
gate-liftvalue and its operation list (in codedev-mode, until the rename ships); the enforced and advised names; theteam policysynopsis and its dry run; the model rule as an entity-level policy (an owner decision) and the swap's wait as a setting (an owner decision). - for tasks-and-broker: the task record, the lease in this clone, the broker's socket and protocol, the field policy that filters a record before it crosses.
- for budgets: the spend and budget readings the watch reports. The machine's limits (load, free memory, free disk, free swap) and the readings the watch logs are seat-state-and-watch.md §3.3's.
- for records-and-ledger: the five record sets' shapes, their locks and atomic renames, the session record's fields (an owner decision), and the chain, signed head, intent and outcome the Kernel's §15 will add.