Release notes: 0.3.0
For someone who runs a team on 0.2.0. This page says what changed between the tags v0.2.0 and
v0.3.0, what to do when you upgrade, and what the release still does not do. 0.3.0 is the latest
release (see Project facts).
When you upgrade
Do these in order. The first two apply to every team; the rest apply if the line names something you use.
- Run
checkwith the new version before you stop or restart anything. Two team files that 0.2.0 accepted are refused by 0.3.0. The first: a role whosetmpdiris, holds or sits inside another role'stmpdir, the team's state folder, the repository or a seat's working directory, or that is or holds the worktree folder (Temp files, #300). The second: a team or a role with anaskor anallowrule that is one of the patterns fortmux kill-serverortmux kill-session, which every seat is now denied (Safety, #308); the error names the rule and says it has no effect. Every command that loads the team file refuses such a file,sayanddownincluded, so find out, and fix the file, before you depend on the new version to stop a running team. - Restart every seat. A seat's prompt, settings and hooks are written by
upand read when the seat starts, so a running seat keeps the 0.2.0 rules until it is restarted:down --yes <role>, thenup <role>, after the seat has written its handoff. - A team on a pinned release: restart the whole team, not one seat at a time. 0.3.0 keeps more
in the state folder than 0.2.0 did:
say-refusals.log, and undersay/the records of a box that holds text and of a paste in progress (say). A seat that still runs 0.2.0 uses the oldsayand the old logging hook on that same folder: it ignores those records, and it writes the text of a message to or fromsecinto the log. See Upgrade to a newer release, "A full restart". - If you add the writer role with
repo.docs_repos: protect the default branch of each listed repository with a ruleset on that repository. The ask on a push to the base branch does not see a push writtengit -C <clone> push, the form the writer prompt gives for a clone of such a repository (Safety); #346 tracks the fix. - Progress notes get a first line. From its restart on, each seat starts its note with a
Status:line, and writes it the next time it rewrites the note. Until then the engineering manager's check lists the seat with "no Status line" (The Status line). Nothing rewrites a note for you. - The message log changes from the restart on. The text of a message to or from
secis left out of new lines, which show[body not logged: sec]in its place, and a message to an address the logging hook could not resolve to a seat shows[body not logged: unresolved address](The message log). Lines already in the log stay as they are.
Nothing in 0.3.0 renames a command or a team-file key. factory.sh, the old name of the launcher, is
still there as a shim that prints a notice.
New
Commands
run-exclusive -- <command>runs one heavy command at a time across every team on the host, in arrival order (One heavy run at a time).flush <role>sends one Enter to a seat whose input box holds text thatsayitself left there, and nothing else (say).fabrikitocan be run through a symlink to its file, for example from a folder on yourPATH(Commands).
Team file
state:names the team's state folder, so a team run from a pinned release needs no link in each release checkout (The team file).repo.docs_reposlists documentation repositories that a writer seat may also change (The team file).
Roles and skills
- A Technical Writer prompt (
roles/writer.md) and a writer seat, commented out, inteams/example.yaml(Right-sizing a team). - The
security-auditskill, for the security seat only (The security-audit skill).
Seats
- A seat in a permission mode that prompts may edit files under its own
tmpdirwithout being asked: its settings carry anEditallow on that folder and on no other role's (Temp files). - Every seat is denied a typed
tmux kill-serverandtmux kill-session, which can end other seats or every team on the machine.test/live-env.sh downstops a test server instead (Safety, Live tests). repo.bootstrapruns with the role'stmpdiras itsTMPDIR(New worktrees).- Each progress note starts with a
Status:line, and the engineering manager's prompt has it check every seat for work after each assignment, done report, verdict and merge;team-statuslists the seats without work first (The Status line).
Changed
Messaging
- A message refused because the receiver's box holds text is no longer worth resending in a loop: the
same text sent again within 300 seconds is refused as a repeat, the refusal is recorded in
say-refusals.log, andstatusprints aNOTICEline for a seat after three such refusals (say). - The log leaves out the text of a message to or from
sec, and records aSendMessagethat only asks to be told when a seat is idle asNOTIFY-WHEN-IDLE, not as an empty message (The message log). - When
messages.logor a gate log is a hard link, the message says to remove the other name and never to delete the file (The message log, The gate).
Team file checks
- A role's
tmpdirthat overlaps another role's, the state folder, the repository, a working directory or the worktree folder is refused (Temp files). - An
askor anallowrule on atmux kill-serverortmux kill-sessionpattern is refused, because the new deny makes it useless (Safety). - A folder listed under
other_teamsthat does not exist yet, or is still empty, is accepted, and a folder holding only a.DS_Storefile counts as empty (Safety).
Starting a team
- An interrupt while git is still adding a new worktree removes that worktree and starts no seat (New worktrees).
- A state folder with a non-ASCII character in its path no longer stops every command under
LC_ALL=Cor with no locale set (#360).
The shared rules and the skills
- A pull request names at least one issue and may close several, each with its own closing keyword (Issues first).
- A possible security finding goes to the security seat and the engineering manager first, whoever finds it (Held security points).
- No push to a head that a reviewer cleared, QA checked or the manager is merging, and a reviewer's follow-up comment takes one of two forms (A pull request in review).
- A seat puts the rules that apply into the brief of a subagent it starts, and answers for what the subagent does (Safety, "What the rules cannot do").
Hardening
Six hardening fixes, in these areas:
- which tmux sessions a command treats as its team's:
upstores the team's state folder and repository in each session it starts, andup,down,say,flush,attach,viewandtitlesstop at a session whose stored values are not their own, and print the command that hands it over. Two teams on one tmux server need two prefixes (Its parts,sessions); - the text
saytypes into a seat; - the permissions of the state folder:
uptakes group and other permission off the folder, the folders it makes in it and the message log; - the tmux server named in the commands the launcher prints and in the iTerm view;
- pull requests from a fork: a new hard rule in the shared prompt, "Never run code from a fork's pull request", and the review and verification skills read such a pull request by its diff;
- which review comments count: only those posted from the team's own account.
A session that a 0.2.0 seat started holds neither stored value, and is taken for that seat until it next starts, so the upgrade needs no step for it. A team that moves its state folder stops its seats first, or hands each over with the command the refusal prints.
Documentation
- The README is now an introduction. The reference moved to
docs/: Messaging, Safety, Updating Claude Code, and a page of checked statements for someone who describes the project elsewhere (Project facts). Pointers in the code, the prompts and the example team file name those pages.
For contributors
- The gate's syntax step checks every script, one file at a time, with the two commands in
CLAUDE.md. The end-to-end test andtest/live-env.sh runput a tmux guard first onPATH, so a test's tmux call reaches only the run's own server (The tmux guard). test/e2e.shtakes the host's run lock itself and waits for its turn, whoever starts it, so it no longer needsrun-exclusivein front of it. It stops before it makes anything if the tree changed while it waited, andE2E_NO_LOCK=1runs it without the lock (One run at a time).
Known limits
The standing list is Known limits on the facts page. These are the ones that the changes in this release touch:
- The push ask does not see a push written
git -C <dir> push, which is the form the writer prompt gives for a documentation repository. The writer prompt is the only guard the team provides there (#346). - The deny on
tmux kill-serverandtmux kill-sessioncatches the typed command only. A script that runs one,sh -c, tmux under another path, and a signal to the tmux process (pkill tmux) are not caught (Safety, "What the rules cannot do"; #358). - The stop gate does not take the run lock, and a gate command that takes it itself, as this
repository's
test/e2e.shnow does, waits inside the gate's time limit while another heavy run holds the lock (How it behaves, #236). - The writer prompt is long. The example's writer seat renders 195 lines of the 199 that
checkwarns above, so a team with more than a few lines ofprompts.projectgets that warning for the writer (#347). - Running seats do not know a seat added later until each is restarted (#231).
- Separate temp folders are not a boundary between seats. The
Editallow is on a seat's own folder, and nothing denies a seat another seat's (#337). - The rules are an accident guard, not a security boundary, as before (Safety, #29).