# Task, proof, review and output Ordinary command output shows the board, every owner request, wait counts by kind and at most five grouped waits. Waits of the same kind and task share a line with their count and oldest age. Assignments and current delivery/read handoffs come first, then active-window pings and process alerts; age orders each priority. Unflagged historical notices still require ACK and remain in the counts. Messages sent with `--info` do not. A table retains up to five open tasks' next steps and the windows/roles holding them, with an explicit remainder. Use `squadra status --all --root REGISTRY` for the complete previous text view and every wait. Ordinary `stato.md` is a bounded current summary; `squadra export` refreshes its complete projection. JSON results and dashboard data retain their complete contents. ## Forecast from comparable work `squadra forecast --task TASK --root REGISTRY` verifies and reads an existing registry without exporting it or writing an event. Task creation, briefing and start also print this comparison. Follow [the previsione guide](skills/previsione.md) for cohort selection, the three-sample minimum and elapsed-time interpretation. The coordinator follows the suggested route or records a reason to deviate; the forecast itself cannot change a route, reviewer, budget or permission. The System skills page explains the automatic trigger and shows **Computed on demand**, because no historical activation counter is recorded for forecasts. ## Balance of windows and models `squadra balance [--task TASK] [--reference FILE] --root REGISTRY` reads the registry and the Usage collector's numbers without writing anything. Task creation, briefing and start also print a short balance: the first window for building and for reading, each with its reason and the number of candidates, without tokens or quota, and the `squadra balance --task` command that prints the whole ranking. Follow [the bilanciamento guide](skills/bilanciamento.md) for the order, the missing-data rule, the quota slots and the Claude estimate. The coordinator follows the suggestion or records a reason; the advice cannot change an owner, reviewer, route, budget or permission. `status`, `stato.md`, `census` and the dashboard's overview also show a **Composition** line: the Claude and Codex windows that can build or read, counted from the registered windows (the coordinator's window and windows in stand-by left out), with the source named. `census` adds the processes it sees, never counted as windows, and says when its scan is partial; before any registration it counts those processes and says so. The advice follows the cross-model rule below: with one client only, open a window of the other model or record a `--same-client-reason` for each read (with only Codex, a Claude window still coordinates); with an imbalance such as 2 Claude and 1 Codex, the lone Codex window reads everything and becomes the bottleneck, so give it a build lane read by a Claude window or open another Codex window; with a balanced squad, pair each builder with a reader of the other model, listed for the newest open tasks that record no same-client reason; in the [final block](#final-block) that is the ledger's planned reader of the other model for the builder's delta. The coordinator gives this advice to the owner when it introduces itself, at every resume and when a window joins or leaves. It assigns nothing and refuses nothing. ## Triage on one page At task creation, on a finding and when the scope changes, the builder proposes; the coordinator settles it and records the reason. The non-author reader checks the choice in the assigned read; this does not add a per-lane gate before the default final block. Keep the answers and choice in one line of the scope or report. This is a judgment about effects: no regex, path pattern, score or parser turns these answers into automatic permissions. | Italiano | English | |---|---| | 1. Tocca sicurezza, dati dei clienti, chiavi, permessi, integrità delle prove o azioni difficili da annullare? | Does it affect security, customer data, keys, permissions, evidence integrity or actions hard to undo? | | 2. Conosciamo tutto l'effetto e possiamo annullare la modifica senza danni? | Do we understand its full effect and can we undo it without harm? | | 3. È una correzione circoscritta, senza scelte di progetto, dimostrabile con una prova mirata? | Is it a bounded fix, with no design choice, demonstrated by a focused check? | | 4. Quale requisito richiesto o controllo obbligatorio rischia di non essere rispettato? | Which required behavior or mandatory check could be left unmet? | | 5. Un errore potrebbe restare nascosto o far prendere una decisione sbagliata? | Could an error stay hidden or lead to the wrong decision? | **At creation:** - **Fix now with proof:** Q1 no, effect known and reversible, Q3 yes. The builder fixes within the confirmed scope; a non-author checks the bounded diff and proof in the final block, or before standalone closure. Tests alone are not enough; no separate plan ceremony unless required by a mandate. - **One code read:** a bounded ordinary behavior or choice, Q1 no, effect known and reversible. Scope, bound proof and an independent read of the changed contracts and callers in the assigned block; relevant checks. - **Full path:** Q1 yes **or unknown**, Q2 unresolved, material hidden harm under Q5, or an existing mandate. Use the required full proof, a non-author read and relevant probes; a full gate where required. A plan read before construction is an option on the owner's word or for a lane touching a trust boundary; an already required plan still needs acceptance. Q4 does not authorize omitting a requirement or check. **On a finding:** - **Block:** only a grave finding: demonstrated harm to security, permissions, data, evidence or essential safe operation. Missing or invalid mandatory security evidence also prevents acceptance. Preserve the counterexample; the consequence matters, not an old label. - **Fix now, demonstrate it:** a bounded remedy with no protected impact and a precise expected result. The builder fixes it; the non-author checks the new diff and original case within the authorized budget. - **Record for later:** in final-block mode, collect unresolved non-grave findings in the single carry-over decision described below and create their tasks at the next milestone's kickoff. For a standalone task, record the candidate, effect, owner, observable trigger or deadline and acceptance check in **its own task in the registry** (`task`, scope and proof), or in **a `decision --task ID` naming the task that owns it**. Link the entry from the report: the work stays visible and open until closed, not merely buried in prose. If deferring a binding requirement, the coordinator records the authorized scope disposition before the current closure; do not mark it satisfied or defer required safety. `Choice: fix now with proof; Q1 no, Q2 yes, Q3 yes, Q4 none, Q5 no; reason: typo with no operational effect; builder proposes, reader confirms on the candidate.` A new protected impact stops dependent actions; do not invent a prior plan after the fact. A final report covers all retained requirements. In the structured runner, `findings` contains blockers: an `accepted` response with nonempty `findings` is refused. Authorized nonblocking follow-ups go in the report/ `limitations`, with links to the registered entries, without hiding them. ## Default: one final block per milestone This is Rule 7's default for coordinated lanes. Standalone tasks and owner-selected per-lane reads keep their own proof/read/close sequence; a plan read can precede building on the owner's word or for a lane that touches a trust boundary. 1. **Set the seams before building.** The coordinator writes the shared formats, interfaces, fixed limits and owned files per lane. Relay a seam question to the affected lanes and record the answer as a decision linked to those tasks; private agreement between two builders is not the shared contract. 2. **Merge proven deliveries.** Each lane ACKs, builds on its own tree, proves its exact committed head and delivers. The coordinator checks the proof, merges the delivered bytes and resolves conflicts. There is no per-lane read. Keep a delta ledger: range/head, author, owned files, proof, coordinator/merge-resolution changes and planned Claude/Codex readers for every delta. 3. **Freeze and read together.** Tag the integration `-rcN`. Register final-read tasks on that exact candidate, with scopes partitioned by author: every delta and seam gets both a Claude and a Codex non-author read. Include coordinator commits, merge resolutions, version, pins, mirrors and release docs. Each actual recipient ACKs its handoff before reading a frozen private copy. A coordinator may use a fresh-context subagent for a non-author read, supplied with the candidate, scope and raw evidence; it verifies the subagent's main claims before recording its own verdict. Keep the real identity: a fresh context or alias never makes the coordinator's own work independently reviewable. 4. **Use one fix round.** Collect all findings, then assign bounded fix tasks on branches from the frozen candidate. Deliver each with its normal green proof and red-to-green evidence in its task output: original base, exact remedy, frozen test/probe bytes, assertion outcomes and log paths. Distinguish setup errors, skips and timeouts from an assertion failure. Do not register a `challenge` agreement for a fix covered by the re-read block. That marks it as a defect fix that cannot be superseded by an ordinary read task and pins a host interpreter. Already declared defect fixes retain all their obligations; this workflow is not a waiver or a way to replace them with ordinary tasks. 5. **Re-read the fix deltas once.** Merge their proven deliveries, freeze the next candidate and open one non-author re-read block for the fix deltas and any new integration resolutions. Keep accepted reads on the unchanged work. Only grave findings block; an unresolved grave finding keeps the gate closed. 6. **Defer non-grave findings explicitly.** Record all unresolved non-grave findings in one ordinary deferral decision linked to the release read tasks, naming each source finding, intended owner, acceptance check and next-milestone kickoff. At that kickoff, create each carry-over task with those fields and link it back to the decision and source report. This does not mark a binding requirement met or silently defer required safety evidence. Do not use `--defer-read` for findings: that option names one unread light task and one release gate. 7. **Prove the release head.** Whole-suite proof uses `tools/parallel_tests.py` when present, with collected equal to executed. Required runtime/native proofs bind the exact release-head sources, rather than only lane heads. Check both readers' coverage against the ledger, record the accepted scope and close the read tasks. Completion grants no authority to publish. **Represent the block with existing tasks.** Final-read tasks name the lanes/fixes they cover and the paired reader's scope. Supersede each covered open lane/fix with its responsible final-read task; the ledger retains the second reader's coverage. Do not close an ordinary unread lane as though it had its own accepted read. The replacement must be registered later and must not depend, even indirectly, on the task it replaces. Reconcile runs, reservations and open questions first. Supersession preserves history, failed proofs and spent budgets; it never resets a read budget. ```sh # REL-CODEX already exists, covers LANE-A and does not depend on it. squadra supersede --actor coord --task LANE-A --by REL-CODEX --reason "Covered in the final block; paired Claude scope is in the delta ledger" ``` `--read-at-gate` remains light-only. `--gate-covers` is for its outstanding tasks, not a general coverage flag for full lanes; `--release-gate` does not enforce the whole delta ledger or choose the two readers. The coordinator checks that coverage and the exact proof bindings. This is an agent workflow, not a registry format or CLI change. On the owner's word, record the former per-lane read plus final fix block, or individual corrective re-reads, instead. ## Available readers, parallel work and capability When creating a read task, use `task --reviewer` to choose an available non-author reader by real identity; an alias does not create independence. **Codex writes and Claude reads; Claude writes and Codex reads** (owner, 2026-10-23): the read that counts comes from the other model, and a same-client read only adds to it. For a Claude or Codex owner, `task` refuses a reader of the owner's client and names both clients, unless `--same-client-reason TEXT` records why, for example because no window of the other model is available; `check` and `close` then need an accepted read of the current candidate from the other client, or that recorded reason. The rule binds tasks recorded by the 3.10.4 `task` command (they carry `cross_client`); tasks recorded earlier are never re-judged, and work by a manual or Cursor seat, whose model is not known, is not judged by it. A task read at a release gate is judged on the gate's reader ([Read at the gate](#read-at-gate)). In the [final block](#final-block) every delta already gets a Claude and a Codex read, and the one that counts is the read by the other model than the delta's author. A final-read task whose reader shares its owner's model, such as the Claude read of a Claude coordinator's integration, names its paired read of the other model in `--same-client-reason`. Readers of different tasks work at the same time and may run alongside construction on other trees. One builder per tree; reads on frozen copies, dependencies respected, shared gates/ports/databases still reserved. Do not wait for a single reader when another suitable identity is available; do not reassign by changing state or reset the budget with an equivalent task. The handoff generated by `deliver` starts the already assigned read: the reader ACKs it and begins, without another "go" from the coordinator. Delivery neither invokes the client nor proves it is awake. In final-block mode, gather corrections into the single fix/re-read round above. For an individual corrective read, a change suspends the read on the frozen copy: the builder fixes, a new proof/delivery, actual ACK, then a reread of the delta and counterexample. **A narrow corrective reread is still a read within the same budget**; spent rounds stay spent. Before assigning browser or installation work, the window demonstrates actual capability with a `probe` receipt in the relevant context and destination path. The probe uses synthetic/private resources and already authorized actions: it does not implicitly install or publish. For the browser, set timeouts for the **DevTools connection**, each protocol call and the entire step; preserve exit status, errors and cleanup of owned processes only. Isolated DOM checks are not evidence of a real browser. Without a capable window, declare the step **not run**, cite the last valid evidence and its limits (or state that none exists), and refer the limit to the coordinator. **Do not give the owner commands to run.** Delegation and capability do not override actual permissions; no sandbox bypass or falsely claimed execution. ## Questions for the owner Prepare `choices.json` as a list of at least two objects with distinct IDs: ```json [ {"id":"A","label":"Continue","say":"Continue within scope","buys":"Completion","costs":"One check"}, {"id":"B","label":"Stop","say":"Stop and save"} ] ``` ```sh squadra ask --actor coord --id Q1 --question "How should we proceed?" --options-file /evidence/choices.json --recommended A --task T1 --waiting builder --evidence /evidence/report.md # After the owner's actual response: squadra decision --actor coord --reason "Owner decision" --answers Q1 --choice A --channel typed-here --owner-words "Continue within scope" # If the question has become obsolete, instead of answering it: squadra decision --actor coord --reason "Question superseded" --withdraws Q1 ``` `--channel relayed` explicitly preserves an answer reported by another window. Answering and withdrawing are mutually exclusive and cannot be repeated. Earlier decisions without a linked question stay historical and do not close questions through similar wording. Link each decision to its source so the Decisions graph traces it to the result: ```sh squadra decision --actor coord --id D-SCOPE --task T1 --follows ask:Q1 --follows decision:D-BEFORE --reason "Relayed instruction" --owner-words "Old keys remain readable for one month" --channel relayed ``` `--id` is optional: without it, the decision is named `dec-e` (a reserved form). `--task` names existing tasks; `--follows` always requires the `ask:` or `decision:` prefix and resolves once, when recorded: reusing a name later does not move the link. An owner instruction without a registered question may have `--channel typed-here|relayed` with nonempty `--owner-words`; without `--channel`, it remains "channel not recorded". Do not use instructions, mentions or `--follows` to close a question: use `--answers` or `--withdraws`. No link is inferred from text, mail or proximity in time. The Who's waiting view and next step per task depend on events, not on `output.next`, which remains a window's statement. Prepare `scope.md` outside the delivered code: expected behavior, owned paths, dependencies, mandatory checks, resources and publication boundaries. Prepare `proof.json` with exact argv, for example `["python3", "-m", "pytest", "tests/test_fix.py", "-q"]`. Probe/log paths must stay outside the candidate: a test writing into sources invalidates the proof. Git-ignored files are not part of the fingerprint: declare relevant external configurations/dependency locks separately. Submodules require explicit evidence. ```sh squadra task --actor coord --id T1 --owner builder --reviewer reader --title "Fix the behavior" --repo /checkout/builder --scope-file /evidence/scope.md --proof-file /evidence/proof.json squadra inbox --agent builder squadra ack --actor builder --message assign-T1 squadra start --actor builder --task T1 ``` Use `send --info` for progress and FYI notices that need no confirmation: they remain visible as information without an ACK wait. Requests, assignments, review handoffs, presence challenges and messages to unregistered recipients still need confirmation and cannot use this flag. A voluntary ACK of information is a real sign of life, never a substitute for a required assignment, review or ping ACK. Existing messages keep their original receipt contract; old readers may still show an unnecessary wait for new information messages until they are upgraded. `inbox` prints a JSON list of the messages addressed to the named `--agent` names and every registered role of their identities, oldest first, once per message, each with its full body, original recipient, sender, task, receipts and ACK. By default it keeps it short: every message still waiting for an ACK (the same waits that `status` and the follower count) plus the latest ten messages. When older messages are left out, one line on standard error says how many and how to see them. `--message ID` prints only that message, refused unless it is addressed to one of those identities; `--all` prints the whole history. ACK still uses the actual recipient role shown in `to`; reading through another alias never ACKs it. After assignment, explain the task in plain words: the first line becomes its dashboard title, followed by why it exists, who it is for and when it will be finished (UTF-8, at most 8192 bytes). ```sh squadra brief --actor coord --task T1 --file /evidence/t1.md ``` If an open task becomes obsolete, register a new one with `task ... --supersedes T0`. T0 leaves the next steps and its waits, keeps its history, and tasks depending on T0 remain blocked: nothing is cancelled, released or reassigned. The command refuses replacement while T0 has a run in progress or a stop awaiting verification, while T0's owner holds a reservation, or while a question on T0 is open; a task cannot depend on the task it replaces. If the new task already exists because work moved there before the replacement was recorded, the coordinator alone records it afterwards: ```sh squadra supersede --actor coord --task T0 --by T1 --reason "Work moved to T1 by recorded decision" ``` Effects and refusals are the same as for `--supersedes`; additionally T1 must have been registered after T0, must not depend on T0 (directly or through other tasks), and the reason cannot be empty. T0's reads, failed proofs and spent budget stay in its history; the Decisions graph draws the same replacement arrow from T0 to T1, taken only from the registered event. For an optional or already required plan read before construction: ```sh squadra plan --actor coord --task T1 --file /evidence/plan.md squadra review --actor reader --task T1 --stage plan --verdict accepted --report /evidence/plan-read.md ``` The review must match the latest plan bytes. A later `changes-required` invalidates a previous acceptance. Keep the original file; if it changes, register and reread the new version. Budgets are set at init (`--plan-rounds`, `--review-rounds`); automatic construction allows at most three attempts. Do not create an equivalent new task to evade them. `decision` preserves a choice; it does not automatically increase counters. An extension requires a newly, explicitly authorized scope; all earlier findings are preserved. For a standalone task or owner-selected per-lane read, after the change with frozen sources (coordinated lanes use the [final block](#final-block)): ```sh squadra prove --actor builder --task T1 --timeout 120 -- python3 -m pytest tests/test_fix.py -q squadra deliver --actor builder --task T1 # The reader confirms the actual ID returned by deliver, then reads the frozen copy. squadra ack --actor reader --message "review-ID-RETURNED-BY-DELIVER" squadra review --actor reader --task T1 --verdict accepted --report /evidence/code-read.md squadra check --actor coord --task T1 squadra close --actor coord --task T1 ``` The argv for `prove` must match the agreed command. `--expected N` on the task checks the count of executed tests in recognized pytest/unittest summaries; it refuses a missing count. Skipped tests never count as executed: `1 passed, 9 skipped` or unittest's `OK (skipped=9)` after `Ran 10 tests` executes 1 of 10 and refuses. The receipt records each category apart (`passed`, `skipped`, `xfailed`, `xpassed`). Other runners require their own explicit check. `--full-gate` requires a gate-labelled proof: first `resource acquire --actor builder --name gate --reason ...`, then `prove --gate`, finally `resource release` after the terminal receipt. The label does not prove the command is the whole suite: the coordinator must agree on the correct command and project reservations. `prove`, a probe, the quick checks, `selftest` and an offline benchmark give their process HOME and TMPDIR in a private folder made for that run (`sq-` and eight characters, mode 0700) in the system temporary folder, never under the registry: Unix socket paths stop near 104 bytes, and a registry deep under a shared folder such as MAMP's `htdocs` gave paths of 146 characters under folders others can write. `SQUADRA_TMP` chooses another parent folder. Before anything starts and before any run is recorded, a folder path over 64 characters, one under a folder others can write that is not a root-owned sticky folder like `/tmp`, or one inside the registry, even through a link, is refused with the path and the fix (`SQUADRA_TMP=`). Cleanup first reopens to its owner any folder the process left unreadable, and never follows a link. Logs, metadata and the lease stay in `/runs//`; the run record names the private folder and whether it was removed when the run ended, whatever its outcome. Claude and Codex turns keep the caller's HOME, where the client keeps its sign-in. Apart from HOME and TMPDIR, every run inherits the caller's environment unfiltered, so a credential in an environment variable (an API key, a token) reaches the measured process and may appear in its retained, immutable logs: start proofs from a shell without secrets the tests must not see. ### One execution for the two final reads When final-read tasks bind the same repository, exact source snapshot, proof argv and expected test count, one physical proof can serve them both. First verify that **each reader's actual executable** lists `--also` in `prove --help`; the version string alone does not distinguish refreshed builds. Otherwise prove each task separately. Deliveries, handoff ACKs, independent reads, checks and closes remain separate for each task. ```sh squadra prove --help squadra resource acquire --actor builder --name gate --reason "Both final reads" squadra prove --actor builder --task REL-CODEX --also REL-CLAUDE --gate --timeout 2400 \ --covers RF1 --covers RF2 -- python3 -B tools/parallel_tests.py squadra resource release --actor builder --name gate --reason "Run ended" squadra deliver --actor builder --task REL-CODEX squadra deliver --actor builder --task REL-CLAUDE ``` Repeat `--also` for additional tasks. `--covers` must cover every requirement of every served task (the example assumes RF1/RF2 are the complete union). Before starting, every member's assignment, dependencies, plan, route and proof contract must qualify. One run ID, process, native result and source binding are retained; each task sees its own coverage. A failed, interrupted or changed-source run cannot qualify any member. The secondary handoff names the physical run and its primary task. Older builds still read and audit the registry, but see the extra task as unproven and refuse its delivery, formal read, check or close. ### Parallel whole-suite proof For this repository, the coordinator may agree on `["python3", "-B", "tools/parallel_tests.py"]` as the whole-suite proof argv. The serial `python3 -B -m unittest discover -s tests -v` remains available; a task's registered argv must still match its proof exactly. The parallel runner uses unittest discovery, including `load_tests`, and runs modules in fresh processes with separate synthetic HOME, CODEX_HOME, CLAUDE_CONFIG_DIR and temporary directories. It compares collected and executed IDs including multiplicity; missing tests, worker crashes and skips cannot yield a passing complete proof. The default is `min(cpu count, 8)` concurrent modules; `--jobs N` overrides it. Each module and the discovery process has a **300-second timeout**, overridden with `--timeout SECONDS`. A timed-out module is named with its elapsed time and fails the run. Any modules that require serial execution are listed in the runner's `SERIAL_MODULES` mapping with a reason and announced before execution. There is no silent serial retry. Module fixtures stay together. Logs, structured receipts and profiles are kept in a temporary directory printed at startup, or a new `--output DIRECTORY` outside the source tree. Python runs with bytecode writes disabled. Each module's output retains failing test names and tracebacks; the final summary gives collected, executed, failed, errors, skipped and wall seconds. A test is counted as executed when unittest starts it; a crash after that point still fails through its native exit or missing receipt. Keep the logs as evidence and inspect the summary, not only the exit code. ### Quick checks before proof and delivery A repository can declare quick checks in one tracked file at its root, `.squadra-precheck.json`. `prove` and `deliver` run every declared check on the exact candidate before the proof process starts or the delivery and handoff are written. Without the file nothing changes. ```json {"schema": 1, "total_seconds": 30, "checks": [ {"name": "pin-label", "argv": ["python3", "-B", "tests/precheck_checks.py", "pin-label"], "timeout_seconds": 10} ]} ``` - `argv` is a list run without a shell, from the repository root, with a private HOME and TMPDIR. A shell string is refused. - Each check has its own `timeout_seconds` (1–60). `total_seconds` (1–120) is a deadline that starts before any precheck work: no check starts after it, and a running check is stopped at it. Cleanup, the last snapshot and the record finish afterwards; the reported `seconds` include them. - Names are unique (`a-z`, `0-9`, `.`, `_`, `-`). There are at most 32 checks, the file is at most 16 KiB, and duplicate or unknown keys are refused. - Each check is recorded like a probe, as a run of mode `precheck`: argv, exit code, logs, seconds, and the candidate fingerprint before and after. A precheck never counts as a proof. - A check that exits nonzero, times out, cannot start, or changes the source refuses the command with `precheck_failed`, naming every failing check. An untracked, ignored, symlinked or malformed declaration refuses with `precheck_invalid` and is never skipped. - After the checks pass, `prove` runs the proof only if the source is still the one that was checked. Otherwise it refuses with `precheck_failed: source changed after the checks`, before any run or process. The optional `review --findings-file findings.json` records observations for the **Reads** dashboard view. The file is a UTF-8 JSON array, at most 16 KiB and 32 items; each item has exactly `severity` (`grave`, `minor`, `info`) and `title` (one nonblank line, 1–200 characters, no control characters). Duplicate JSON keys and unknown fields are refused. Use safe summaries, never secrets or copied private content. For example: ```json [{"severity":"minor","title":"The example omits the retry limit"}] ``` Omitting the option leaves observations unrecorded; `[]` explicitly declares none. It does not change the verdict, closure rules or runtime reply schema. Old registries and frozen protocols need no migration or backfill. The dashboard counts recorded observations, not unique or unresolved defects. A changed plan or delivery after a bound changes-required read is a chronological revision, not proof of causation or a successful fix. “Accepted with conditions” remains unrecorded because the protocol has only three verdicts. Reports and task stories retain the evidence behind each count. The review records a non-author report bound to the current fingerprint; it does not magically run tests. The reviewer may use `probe --actor reader --task T1 --expected-rc 0 -- argv...` for independent probes, or `--expected-rc 1` for a negative control. Expected native 1 is called `matched`, not a passing product proof. A non-author's probe of a frozen delivery runs on a private writable copy of the frozen candidate inside the run's temporary folder, bound to the delivered fingerprint (`frozen_copy` in the run), so a builder who keeps editing the live tree cannot change what it tests; the builder's own probes run in the live checkout. `prove` runs in the builder's checkout before the freeze, so git-ignored files there can still affect it. Do not put mutants in the frozen checkout: use isolated copies and preserve the original probe before modifying it. Report limits, collection, assertions/ errors/skips, configuration and provenance. Reproduce the original issue on the exact remedy. One substantive output per completed step: a result, decision, blocker or handoff that adds information. Routine progress comes from the registry. Do not duplicate generated assignments or handoffs with manual "ready" messages; an existing proof does not need a second narrative. ACKs, decisions, pauses and receipts stay explicit. ```sh squadra output --actor builder --task T1 --file /evidence/update.md --next "Candidate reread" --artifact /evidence/report.md ``` The command saves the complete text, UTC, author, task, content-addressed artifacts, next step and receipt. Show a compact summary of registered facts when useful, without an output for every chat turn. The dashboard shows the details. The reviewer also uses the ID of the task read for its output. Mail: `send --actor coord --to builder --body-file /evidence/message.md --id M1` saves a message. `ack --actor builder --message M1` is a separate recipient action. `transport --via manual` provides the exact handoff without pretending delivery or wakeup, and records `delivered: null`: unconfirmed, not failed. `--via codex-queue` requires a known session ID and checks the local CLI; native 0 means queued, not read. `send` and `transport` print short JSON receipts without the board; full transport evidence stays in the journal; a failed or unconfirmed queue attempt also shows at most 300 characters from stderr in its receipt. Read-only JSON commands, including `check`, `candidate status` and `lesson --list`, print one JSON document on stdout; `status` keeps its human board. **To forward.** A Codex window has no follower of its own, so mail to a Codex seat waits on the coordinator until a transport reports `delivered: true` or the recipient ACKs: with failed or unconfirmed attempts, or with none at all (a review handoff that `deliver` records as sent by the coordinator, an assignment, a ping). After 120 seconds from the first attempt, or from the message when there was none, it is listed first as «To forward», naming the coordinators; the coordinator relays it with `transport --via codex-queue`. Mail to Claude, Cursor or manual windows is never «to forward»: they follow their own mail, so a transport could not end the wait, and it stays an ordinary ACK wait. The dashboard's Communications tab shows the same events in words (who wrote to whom, about which task, sent, queued, acknowledged or late against the `ack` threshold); a message's text opens only on request, and no read is inferred from text. Do not send email/Slack or use external channels without the owner's authorization. Shared mail is enough across mixed clients. ## Following mail without a native queue Every Claude window and every other window without a native queue, including the coordinator, starts a follower when joining or resuming. Name one of its roles with `--agent`; all registered roles of that identity are included, including roles added while the follower runs. Repeated `--agent` can explicitly include several identities; the coordinator includes `coord`. The follower leaves the journal and its projections read-only and saves its cursor separately under `$XDG_STATE_HOME/squadra/inbox` (default `~/.local/state/squadra/inbox`). Re-arm the same command without manually copying an event number. Cursor keys use identities, so changing the named role does not start a second stream. An older seat-based cursor is migrated when re-arming its original command (or using its explicit `--cursor-file`); the old file remains untouched. New roles expose previously pending mail at registration, and replacement digests are visible even though they belong to one compound event. In Claude Code, arm **Monitor** with a timeout longer than the command's timeout: ```json {"command":"squadra --root /shared/registry inbox --agent claude-build --agent claude-review --follow --timeout 1740","description":"mail for claude-build, claude-review","timeout_ms":1800000} ``` A background Bash command with `run_in_background` and `--until-first` has no 30-minute limit: it exits after the first batch that shows mail and wakes the window. Read the full mail and acknowledge it, then re-arm the same command: ```sh squadra --root /shared/registry inbox --agent claude-build --agent claude-review --follow --until-first ``` Use `--cursor-file PATH` to choose a private cursor file, `--since EVENT` to override its starting point or `--no-cursor` to track the cursor manually. The saved cursor binds the registry path, recipients and the event hash. A foreign cursor or mismatched recorded hash anchor is refused. Each batch is saved only after its output was flushed; interruption before that point may repeat a message. No cursor proves consumption or an ACK. On the first run, pending mail is shown oldest first, at most ten in the first batch with a `more` line for the remainder. The saved position never skips mail that was not printed; subsequent polls or a restarted follower drain that remainder. On resume it prints new matching mail, including messages sent between watches. On restart a `pending` row lists the count and IDs still needing ACK, including previously printed mail. This row does not wake `--until-first`; only a new message does. Message lines carry `kind: "message"`, creation `event`, sender, recipient, task, ID, `info`, `ack_needed`, a bounded preview and the root-bound `ack_command`. Read full content with `inbox --agent NAME --message ID`, then explicitly ACK when required. The follower polls every two seconds, releases views before sleeping and verifies new events from its last hash anchor. It has no periodic output ticks. SIGINT, SIGTERM and a timeout exit 0; a registry/cursor error exits nonzero without a journal diagnostic. `--since` and `--timeout` require `--follow`; `--all` and `--message` do not apply to it. A stopped follower is not proof of an empty mailbox; status cannot tell whether it is still running: Monitor or an actively watched background process must wake the window, which re-arms after restart or compaction. Redirection alone does not wake an agent. Stop only your own processes. The follower saves no ACKs or transport receipts. ## Worth remembering at close An optional declaration by the closing agent, without changing the `output` protocol or starting a proposal. If a memory service is in use, declare at close and do not propose the same item through another channel. **Da ricordare.** Questo incarico ha prodotto qualcosa che vale oltre la sua chiusura: una decisione e chi l'ha presa, un vincolo, una trappola già pagata? Se sì, una frase per ciascuna, la prova (numero di evento o rapporto registrato) e quanto ne sei sicuro (sicuro / probabile). La frase contiene segreti, dati personali o percorsi privati? Se sì, riscrivila senza; se non puoi, non scrivere la frase: indica solo la prova e `private_content: yes`. **Worth remembering.** Did this task produce something that matters beyond its close: a decision and who took it, a constraint, a trap already paid for? If yes, one sentence each, the proof (event number or registered report) and how sure you are (sure / likely). Does the sentence contain secrets, personal data or private paths? If so, rewrite it without them; if you cannot, do not write the sentence: give only the evidence and `private_content: yes`. Name the file **exactly `da-ricordare.json`**, attached to the closing agent's output with `--artifact /evidence/da-ricordare.json`. The command's path is local: do not copy it into the content. The registry retains artifacts permanently; secrets, personal data and private paths written by mistake cannot be removed. Refer only to event numbers or hashes of already registered reports. The public schema is `form: "da-ricordare/1"`, `task` (task ID), `answer` (`yes` or `no`), `items` (list; empty with `no`). Each item contains: `type` (`decision`, `constraint`, `trap`), `certainty` (`sure`, `likely`), `private_content` (`no`, `yes`) and `evidence` (list of `{ "event": }` or `{ "artifact": }`). With `private_content: no`, add `sentence`, one sentence of at most 1500 characters; a decision also states `who`. With `private_content: yes`, **omit `sentence`**: keep only type, certainty, private flag and evidence. Do not put private content in other fields. These examples are synthetic: use evidence that is actually registered. ```json { "form": "da-ricordare/1", "task": "T1", "answer": "yes", "items": [ {"type": "decision", "sentence": "Use a bounded queue.", "who": "owner", "certainty": "sure", "private_content": "no", "evidence": [{"event": 12}]}, {"type": "trap", "certainty": "likely", "private_content": "yes", "evidence": [{"event": 15}]} ] } ``` ```json {"form": "da-ricordare/1", "task": "T2", "answer": "no", "items": []} ``` This is a declaration, not evidence of sending or approval. A consumer may produce drafts; the user's explicit selection is a separate request. ## Candidate, reader and requirement coverage `task --reviewer reader` selects an already registered reader whose identity differs from the authors' and, for a Claude or Codex author, whose client is the other model's (see above). `deliver` saves the candidate, content-addressed packet with scope/plan/proofs and `review-...` message in one transaction. The command returns that ID. The recipient ACKs it before the code review or `read` turn. The message names the commit only when the working tree equals it byte for byte (compared by Git blob id, so skip-worktree or assume-unchanged flags cannot hide a change); otherwise it names the working-tree snapshot and the uncommitted or untracked paths the commit lacks. For a frozen delivery it names the frozen copy instead (`candidates//repo` in the registry) and warns that the builder's working tree may differ; a reassigned read says the same. A new fingerprint requires a new handoff and ACK. **Reader evidence lives outside the candidate tree**. New CLI tasks copy the exact proved source, including relevant uncommitted and untracked files, into the registry at delivery. The builder may then continue; `review`, `check` and `close` measure the frozen copy and refuse tampering. Legacy tasks continue measuring their live checkout and refuse candidate drift. Ignored dependencies still need their own evidence. Freeze refuses secret-filter matches in untracked or changed working-tree rows, absolute/escaping symlinks, symlinked parent directories and case/Unicode-normalization aliases in the index. Unchanged tracked content already committed at HEAD is Git history and is not refused later either. A frozen template's name-only exemption requires membership in delivered HEAD; commit staged-only or untracked templates such as `.env.example` before delivery, or leave them untracked and ignored. Checkpoint and save include healthy retained frozen candidates. They check what a candidate adds to its delivered HEAD: untracked or changed working-tree rows by name and private-key header, and staged blobs that differ from HEAD by private-key header. A match refuses the copy with its SHA and path; unavailable caches are reported. Content committed at the delivered HEAD is Git history, like the all-ref bundle: an unchanged committed path such as `deploy/credentials.py`, or a committed test fixture with a PEM header, can be copied. Saving the live repository still judges its own tracked files, and a live name-only refusal still needs `--allow-name`. Restored readers resolve candidates relative to the restored registry. Repeating the same packet does not duplicate events. New proofs change the packet and require a new message/ACK, even when returning to an earlier candidate. Without `--reviewer`, the manual protocol remains. `advance --actor builder --task T1` reconciles an existing delivery: it can create the missing handoff for the same proven candidate; the coordinator can inspect an existing handoff. It does not build, approve, assign or invoke models. For an explicit matrix, `requirements.json` is a JSON list: ```json [{"id":"R1","text":"The valid request works"}, {"id":"R2","text":"The invalid request is refused"}] ``` Pass it to `task --requirements-file /evidence/requirements.json`. During `prove` and `review`, repeat `--covers R1 --covers R2`. A passing native proof covers only the current fingerprint; the reviewer declares coverage separately. Delivery and closure refuse missing requirements; unknown IDs are refused before the proof starts. The dashboard shows the requirement, proof IDs/results and read. Test sufficiency needs independent judgment: `--covers` alone does not establish it. ## Reviewer pool Repeat `--reviewer` to name 2 to 4 eligible readers instead of one. Each member must be a registered reviewer or coordinator, not in stand-by, and of an identity other than the owner's; one invalid member refuses the whole registration (`review_pool_member`), and five or more refuse it as `review_pool_size`. One `--reviewer` is the single-reader task exactly as before. `deliver` saves one immutable packet and one handoff message per member, all named after that packet. The first valid ACK claims the read: another member's ACK, code review or read run on the same packet is refused with `review_claimed` and changes nothing; only the claimant's verdict counts toward check and close. Repeating the same packet (`deliver` or `advance`) keeps its ACKs and claim; a new packet (new bytes or new proofs) starts unclaimed, and an ACK on an earlier packet claims nothing. Budgets and history are kept. Delivery skips a member in stand-by: it gets no handoff of that packet, the result names it in `skipped_standby`, and the others can claim the read. Only a pool whose members are all in stand-by is refused. Changing availability stays a coordinator action, and a member back from stand-by reads from the next packet. Until the claim, waits show one entry listing the members holding a handoff; nothing is reassigned, retried or released by the wait. Plan reads are not tied to a handoff and work as before. ```sh squadra task --actor coord --id T2 --title "Retry limit" --owner builder --repo /work/repo \ --scope-file /evidence/t2.md --reviewer reader-a --reviewer reader-b --reviewer reader-c squadra deliver --actor builder --task T2 # returns three handoffs, one per member squadra ack --actor reader-b --message "review--reader-b" # reader-b claims the read squadra ack --actor reader-a --message "review--reader-a" # refused: review_claimed squadra review --actor reader-b --task T2 --verdict accepted --report /evidence/t2-read.md squadra check --actor coord --task T2 squadra close --actor coord --task T2 ``` ## Waits and windows not yet registered ```sh squadra send --actor coord --to-new expected-reader --body-file /evidence/handoff.md --id M-EXPECTED # The actual window registers with that ID, then ACKs M-EXPECTED. squadra settings --actor coord --file /evidence/thresholds.json ``` `--to-new` creates an expected recipient without assigning it an identity. It refuses an already registered name; after registration, only the recipient may ACK. `thresholds.json` is an object containing only the selected keys from `ack`, `delivered`, `reviewed`, `heartbeat`, `alive`, `to-forward`, `plan`; values are nonnegative integers in **seconds**, 0 for an immediate warning. The first five defaults are 900, 3600, 1800, 1800, 300; `to-forward` defaults to 120 and `plan` to 3600. The latest settings event replaces custom values. A settings write by a window on the published 3.10.1 restores both additional thresholds to their defaults, because that writer records neither optional value. This is intentional compatibility behavior. `cleanup-unknown` is always flagged. CLI, doctor and API calculate age at read time; projections do not retain an age that appears current. A warning is not proof of liveness and performs no actions. ## Squad outputs Omit `--task` when the text concerns coordination of the area, for example the arrival of an outside reviewer. Previous outputs do not change their association. Each write appends new event records and updates affected UTC days in `posta/exchange-YYYY-MM-DD.md` and bounded summaries. Complete `state.json` and mail/history exports are refreshed by `export`, `checkpoint` or `save`, not by every command. Do not create authoritative copies per clone or edit projections. A commit can precede its projection update: compare the exported sequence/head with the current Store view before treating a file as complete. Use the current `inbox` for reception and transport; an old complete mailbox is not a live queue. `squadra export` rebuilds the complete projections from verified authority. ### Registry read boundaries Ordinary commands verify the anchor event and its hash, the newer event hashes and links, and authenticated proofs for the cache values/indexes they read. They do not reverify pre-anchor events, untouched leaves, or the cached root against complete reducer replay. At startup/resume use read-only `doctor --quick` for explicitly limited anchor, suffix and demanded-cache checks. Full verification runs in `doctor` without `--quick`, `export`, `checkpoint`, `save`, `restore-check` and release-gate `close`. Dashboard startup performs the same full audit in the background, on a private copy of the registry: ordinary verified data is marked pending until completion, and an audit failure stops data responses and removes the displayed view. A missing, foreign or invalid cache also falls back to verified reconstruction. See the exact [verification table](recovery.md#registry-verification). Read-only commands do not write the registry or projections. A full audit reports cache/journal disagreement as a mismatch, not a successful fallback. Default doctor refuses it; explicit `doctor --repair` rebuilds derived tables and re-audits, but refuses saved packages and checkpoint folders; it also copies the [write-ahead log](recovery.md#registry-wal) back into the database. The dashboard never repairs: its audit fails closed. Cold-cache computation and release-gate auditing happen before the short write transaction; concurrent changes may produce a plain retryable refusal. Coordinate every writer's upgrade before new source-manifest references are used; unsupported older tools must refuse them. ## Keep-alive and stand-by ```sh squadra census squadra ping --actor coord --all squadra ping --actor coord --to builder # Replace PING-ID with the returned ID; forward every message to its recipients. squadra transport --actor coord --message PING-ID --via codex-queue squadra ack --actor builder --message PING-ID squadra ping --actor coord --sweep # Explicit stand-by and return, with a recorded reason: squadra standby --actor coord --agent builder --reason "Window unavailable" squadra standby --actor coord --agent builder --resume --reason "Availability confirmed" ``` `ping --all`, coordinator only, calls each other active identity once; it excludes those in stand-by. A pending ping is reused without moving its deadline. **The sweep acts only on a ping with a recorded delivery** (a transport that reported `delivered: true`, which today only the Codex queue gives): a window cannot answer a call that never reached it. A ping to a Codex window that is not delivered is listed «to forward» instead; a window that receives mail only through its follower or by hand is never put in stand-by by the sweep, so record that with `standby --reason` when you know it. To recall a window in stand-by, use `--to`: it creates a fresh call linked to that stand-by. The ACK of that call allows a return at the coordinator's next `ping --sweep`. An old ACK, an alias or a repeated `agent` command does not reactivate the window. The CLI performs no implicit transport: record and forward the returned messages. `alive` is the ping response threshold in seconds, default 300; `ack` continues to measure mail generally. The `settings` file replaces previous custom thresholds: include those you want to retain, for example `{"ack": 900, "alive": 300}`. Omitting a key restores its default. Age and deadline are calculated at read time; changing `alive` also applies to pending calls. Persistent projections retain events, not ages. Only the coordinator changes availability with `standby` or `ping --sweep`, recording an event. The sweep rechecks the response, call and threshold inside the transaction: an earlier read does not decide the current state. All roles of the same identity share stand-by. New executor or reader assignments and new review handoffs are refused until the return is recorded. Status and the dashboard distinguish windows in stand-by. Stand-by **does not** cancel processes, release resources, transfer roles or reassign work. Return **does not** restart anything. No response is not proof that a process ended. No timer or dashboard read changes state. The census remains a partial snapshot, to be supplemented with the clients. **Waits on a window in stand-by are counted, not listed.** Mail to a window in stand-by leaves «Who is waiting» in `status`, `stato.md` and the dashboard: its ACK and to-forward waits become one line per window, for example «3 messages to core-A on stand-by (Window closed)», in Italian «3 messaggi a core-A in stand-by (Window closed)». The old heartbeats of that window's runs fold into the same line («1 run of core-A, state uncertain»), and the runs themselves stay listed with their uncertain result: a run without a receipt is never declared stopped. This is computed at read time and records nothing. The messages stay without ACK: an ACK from the window still closes one, the pending-ACK count and the mail filter still include them, and `standby --resume` (or a return through the sweep) brings their waits back. Pool handoffs and task steps are not folded. To silence a window that is gone for good, put it in stand-by with a reason, even when it has not answered for days: no ping is needed for an explicit `standby`. Earlier registries can be read without migration. After new presence events, all writing windows must use the same updated version: an earlier CLI does not enforce the new constraints. This does not authorize installation or migration of an already active squad. ## Light route for a small change After the same question-based triage, the coordinator may use `task --route light`. The task must start at a clean Git base, with a nonempty scope, requirements, configured independent reader and exact proof argv. These form an immutable contract under **light-v1: 80 added plus deleted lines, 4 files, profile P2**, and at most 16 KiB (16,384 bytes) of added plus deleted lines, so one long line counts by its size. Equality is allowed; 81 lines, 5 files or 16,385 bytes refuse. Tests, documentation, comments and whitespace count. Git raw Myers diff counts renames as deletion plus addition, without textconv, external diff or whitespace exemptions. Intermediate commits do not change the original base. There is no flag to enlarge these limits. P2 permits README.md/README.it.md, Markdown under docs/ or references/ and tests/**, except the following protected names: all scripts/**, plugins/**, assets/vendor/**, assets/dashboard.html (the dashboard page holds the dashboard token and calls its write routes), client/CI directories (.github, .agents, .codex, .claude, .cursor, .claude-plugin, .codex-plugin), .gitignore/.gitattributes/.gitmodules, VERSION, pyproject.toml, requirements*.txt, *.lock, package-lock.json, pnpm-lock.yaml, yarn.lock, Makefile, package*.json, AGENTS.md/CLAUDE.md at any depth, SKILL.md, references/{work,start,runtime,recovery,plugins,plugin-authoring}.md and docs/plugin-authoring.it.md. Patterns match whole relative paths (`*` includes slashes), with NFC/case-folded comparison. Aliases/collisions, unknown paths, symlinks/submodules (including in the base), type/mode changes, non-UTF-8/binary changes, unavailable bases, unstable snapshots and no-op changes require full. No plan or plan read on light; use the agreed targeted proof and one code-read round. ACKs, non-author identity, native proof on unchanged exact bytes and the same contract, requirement covers, dependencies, pauses, resources and budgets remain. Required browser or other domain evidence remains too. A fix to the dashboard page, however small, takes the full route with its browser measurement, because the page is protected. Release final reads and the owner's explicit typed publication permission never relax. No minification to qualify, and no path/size threshold replaces judgment about security or irreversible impact. The central validator remeasures before a proof process, at deliver, check and close, also for direct Store events; packets retain the verified measurement. Refusals use `light_lines_exceeded`, `light_bytes_exceeded`, `light_files_exceeded`, `light_protected_path`, `light_unmeasurable`, `light_empty_change`, `light_contract_required`, `light_policy_unsupported`, `light_plan_requires_full` or `light_read_round_exhausted`, with a native nonzero exit and “Full route required”. No proof process or handoff follows a refusal. Both automated read starts and recorded code verdicts allow at most one round. A changes-required verdict stops light work; it is not another light fix cycle. Only the coordinator may promote an open light task: ```sh squadra route --actor coord --task T1 --full --scope-file /evidence/full-scope.md --proof-file /evidence/full-proof.json --reason "Broader impact" ``` Use `--full-gate` if that scope requires a reserved gate; `--expected` updates an agreed collection count (otherwise the count is retained). Promotion keeps base, authors, all old proofs/reads and spent counters. It changes the contract, clears current delivery/plan, and requires fresh proof and independent read; the normal triage determines whether a new plan is needed. There is no demotion. Exhausted budgets still stop work; neither promotion nor a fresh equivalent task can reset them. Exact same-base/scope/proof/requirements aliases with spent budgets refuse; semantic disguises are still the coordinator's responsibility, not a classifier. No-route tasks and historical projections keep their existing behavior. Unknown future light policies are readable but cannot qualify work. A frozen squad must coordinate every writer's explicit upgrade before opting in: older CLI versions ignore new route metadata, so mixed-version enforcement is not supported, and a 3.6.x window still shows a task promoted to the full route as light. No launcher, installation or workspace version is changed automatically. The change that implements this protocol itself takes the full route and full suite. ### Read at the gate A light task may be registered with `--read-at-gate` and no `--reviewer`. It keeps every light-v1 rule above; it simply closes without its own code read, once its assignment is ACKed, its native proof on the exact bytes covers every requirement and, for a defect fix, its challenge has matched. A defect fix closed by a recorded exception needs a reader for that exception: promote it to the full route for its own read (`read_at_gate_fix_exception_needs_read`). It cannot have its own read (`read_at_gate_no_own_read`); a full-route task, or a light task after promotion, always has its own read (`read_at_gate_requires_light`). Until a gate reads it, status, board, the dashboard and the complete `stato.md` written by `squadra export` show it as **closed — read at the gate**, never as read, with its own count. A release gate is an ordinary task the coordinator registers with `--release-gate`, usually the integration of the batch. Its `check` and `close` refuse, naming each task, while any outstanding read-at-gate task lacks the gate's current accepted code read covering it from a reader who is not its author (`gate_read_missing`), or while a path that task changed does not have its exact delivered bytes in the gate's candidate (`gate_bytes_missing`). The gate reader lists what the read covers with `--gate-covers`; a task that is not outstanding, whose author is the reader or, under the cross-model rule, whose author's model is the reader's, is refused (`gate_covers_invalid`). Such a same-model gate read recorded anyway, for example by an older window, makes the gate's `check` and `close` refuse, naming the task (`cross_client_read_missing`): have the gate read by the other model, or defer the task. Equality is per whole file, including mode and deletion: a later change to the same file can keep the earlier task outstanding, and only a deferral then lets the gate close. Only the coordinator defers, with a reason, one outstanding task from one named open gate (`decision --defer-read ... --gate ...`; otherwise `gate_defer_invalid`). The deferral shows in status; the task stays outstanding and the next gate must cover or defer it again. Nothing is ever deferred implicitly. ```sh squadra task --actor coord --id D1 --title "Typo" --owner builder --repo /work/repo --route light \ --read-at-gate --scope-file /evidence/d1.md --proof-file /evidence/d1-proof.json --requirements-file /evidence/d1-req.json squadra prove --actor builder --task D1 --covers R1 -- python3 -B -m unittest tests.test_docs -v squadra deliver --actor builder --task D1 squadra close --actor coord --task D1 # status: closed — read at the gate squadra task --actor coord --id REL --title "Release batch" --owner integrator --repo /work/repo \ --scope-file /evidence/rel.md --reviewer reader --release-gate # ... prove and deliver REL; the reader ACKs its handoff ... squadra review --actor reader --task REL --verdict accepted --report /evidence/rel-read.md --gate-covers D1 squadra check --actor coord --task REL squadra close --actor coord --task REL # D1 is now read # Instead of covering D1, the coordinator may defer it from REL to the next gate: squadra decision --actor coord --defer-read D1 --gate REL --reason "Docs only; next release" ``` Older windows ignore pool and read-at-gate metadata: every writer of a squad upgrades together before using them. ## Defect fixes: show that the regression detects the original Fixes covered by the final re-read block use normal proof and red-to-green evidence in their task output, as described [above](#final-block), without registering an agreement. This section applies to standalone declared defect fixes. Existing declarations cannot be undone or superseded by ordinary final-read tasks. The coordinator marks a task with `task --defect-fix`. It can register the oracle at creation with `--challenge-file`, or later on an open task as below. Marking is one-way and coordinator-only; a title containing “fix” is not a declaration. Both forms of task replacement refuse to replace a defect fix unless the replacement is itself marked as a defect fix, with its own base and oracle agreement. For a correction of `VALUE = 1` to `VALUE = 2`, the regression's own method reads the actual value and asserts 2. After writing the fix and its test, register: ```json {"ids":["test_value.ValueTest.test_value"],"files":["tests/test_value.py"]} ``` ```sh squadra challenge --actor coord --task T1 --register \ --contract-file /evidence/regression.json --reason "Value regression" # Run the task's agreed prove command on the frozen candidate, then: squadra challenge --actor builder --task T1 --output /evidence/challenge-T1 --timeout 30 squadra deliver --actor builder --task T1 ``` The default runner is `python-unittest-v1`. `ids` contains complete unittest method IDs, not discovery patterns or classes. `files` explicitly lists the test and Python test helpers (`tests/**/*.py` or a root `test_*.py`); these exact bytes are frozen as artifacts and placed on both private inputs. Include needed `__init__.py` files. Each case class and underlying test method must be defined in the listed files; an unregistered module with the same name cannot substitute for them. Imports use the input root and its `tests` directory. Only test files are overlaid: original product bytes come from the registered base, never current HEAD. The remedy includes the exact tracked and non-ignored untracked candidate, including uncommitted changes. Version 1 admits regular files, not symlinks/submodules; unavailable bases and unsupported inputs refuse. Every selected method must execute and fail by AssertionError in its test body on the original and pass on the remedy. A passing original, import/setup/teardown error, skipped/expected-failure test, unknown ID, timeout or uncertain cleanup does not match. Results come from unittest objects, not a search for “FAIL” in stdout. Keep ordinary positive tests in the delivery proof; there is no separate control input for task fixes. Native results and both logs are retained on failure. Write the oracle against behaviour the base already exposes: importing or calling code that the fix adds errors on the base and cannot qualify as an assertion failure. Custom oracles use `{"runner":"python-check-v1","oracle":"/evidence/oracle.py"}`, the existing `check(repo)` interface. An assertion during module loading is an instrument error. The agreement pins oracle/runner bytes, interpreter and the resolved argv; arbitrary exit codes are not assertion evidence. Oracles are trusted code, not sandboxed: the reader must check that they test the defect, do not disguise setup failure as an assertion, and use declared dependencies. The normal proof remains separate. `check` and Store close require a matching task/base/contract/candidate receipt and its current independent read. A direct Store close cannot waive it. Delivery includes the challenge; recording a new receipt or exception after delivery needs redelivery and a fresh read within the existing budget. Replacing the agreement needs a coordinator reason and new proof; it preserves the base, prior attempts and spent rounds. Source drift invalidates the old proof/read/challenge. Light fixes retain this obligation and their 80/4/P2 limits; promotion to full retains the fix but requires new bindings. If an automated regression cannot reach the defect, the coordinator records: ```sh squadra challenge --actor coord --task T1 --exception \ --reason "Hardware-only failure; manual evidence and limits in the report" ``` The exception is candidate-bound, visible with its reason, and must be checked by the independent reader. It waives only the automated red/green demonstration; proof, review and publication authority are unchanged. It never says `matched`. The dashboard places the result or exception next to the proof, with original commit, remedy fingerprint and logs. A fingerprint is not an uncommitted commit. Tasks without fix metadata and unbound historical challenges keep their behavior; old challenge records do not qualify new fix tasks. Existing frozen squads need an explicit coordinated upgrade of every writer. Old CLIs ignore these fields; mixed-version enforcement is not promised. Unsupported future contracts can be read but cannot qualify a close. Nothing installs or migrates a live squad. ## Lessons (errata) and the rasoio lens The two built-in skills record their activations as registry events. The guides are [errata](skills/errata.md) and [rasoio](skills/rasoio.md). | Kind | Actor | Fields | |---|---|---| | `lesson` | the author | `id` (`L` + at least 4 digits, unique), `text` (1–1000 characters), `trigger` `{"paths": [glob…], "words": [word…]}` (each list at most 10, at least one entry overall), `source` `{"task", "event", "eligible"}` | | `lesson.retire` | the coordinator or the lesson's author | `lesson`, `reason` (1–500 characters) | | `lesson.recall` | the actor of `brief --task` or `start` | `task`, `at` (`brief` or `start`), `lessons` (1–5 distinct ids, none retired) | | `lesson.ineffective` | any seat | `lesson`, `recall` (the seq of a `lesson.recall` that showed it), `reason` | | `review` | unchanged | optional `lens` (`rasoio`) and `net_lines` (integer 0–1,000,000, only with `lens`) | `squadra lesson --task T --source-event N --text … --path GLOB --word WORD` records a lesson. The source must be one of the task's reds: a code review with `changes-required`, the `run.end` of a failed proof, or the `close` of a task with `fix`. `--any-source` accepts another event of the task and records `"eligible": false`. `--retire ID --reason …`, `--ineffective ID --recall SEQ --reason …` and the read-only `--list` complete it. `review --lens rasoio --net-lines N` declares the lens. `brief --task` and `start` show at most five matching lessons: 3 points per trigger glob matching a path named in the task's title, scope, requirements or brief, 1 per trigger word found there, and 1 more if the lesson is already ineffective. Retired lessons are excluded; ties go to the newest. When at least one matches, the `brief` or `start` event and a `lesson.recall` are appended in one transaction; otherwise output and events are those of 3.8.0. A code read with `changes-required`, a failed `prove` and the `close` of a defect fix add an `errata` object to their output: `record_lesson`, `task`, `source_event`, `responsible` (the actor who ran the command), `reason` and a `command` template whose text the agent writes. The registry never writes a lesson by itself. Derived state, created on the first lesson event only: `state["lessons"][id]` with `retired`, `recalls` (recall seqs), `recalled_tasks` (distinct tasks) and `ineffective`; `state["lesson_recalls"]`. A lesson's status is `retired`, `ineffective`, `active` (shown) or `new`. `lesson --list` returns the lessons with their status and the counts `lesson_events`, `recall_events`, `recalled_pairs` (distinct task and lesson pairs), `ineffective_marks`, `rasoio_reads` and `net_lines_declared`. Older Squadra windows ignore these kinds, so mixed-version enforcement is not promised. | Refusal | When | |---|---| | `lesson_text_required` | empty, blank, too long or control-character text | | `lesson_trigger_required` | no glob and no word | | `lesson_trigger_invalid` | a malformed glob or word, or more than 10 of either | | `lesson_source_required` | missing or unknown task, an event outside the registry, no `eligible` | | `lesson_source_not_eligible` | the cited event is not a red of the task (CLI; `--any-source` allows it) | | `lesson_source_unrelated` | the cited event concerns another task (CLI) | | `lesson_id_invalid`, `lesson_id_taken` | a malformed or reused id | | `lesson_fields_invalid` | unknown fields | | `lesson_unknown` | retire or ineffective on an unknown lesson | | `lesson_already_retired`, `lesson_retire_not_allowed` | a second retirement, or by a seat that is neither the coordinator nor the author | | `lesson_reason_required` | an empty reason | | `lesson_recall_invalid` | a recall with an unknown stage, no lessons, more than five, repeats, retired or unknown lessons | | `lesson_recall_unknown` | an ineffective mark citing a recall that did not show the lesson | | `lesson_actor_required` | `lesson` without `--actor`, except `--list` (CLI) | | `lens_unknown` | a lens other than `rasoio` | | `net_lines_requires_lens`, `net_lines_invalid` | `net_lines` without the lens, or not an integer from 0 to 1,000,000 | ## Protocol details from the README *Moved from the README, word for word; the README keeps a summary of each part and links here.* Readers may supply `review --findings-file findings.json` with bounded observations (`severity`: `grave`, `minor` or `info`; a safe one-line `title`). See [the review command](work.md). Missing observations say **Not recorded**; `[]` explicitly means none. The view shows how many reads supplied this data. **Accepted with conditions** is not recorded by the three-verdict protocol. The optional metadata does not change approval, closing rules or frozen protocols. A project brief starts with its goal; `## Steps` and `## Glossary` (or `## Passi`, `## Glossario`) are optional, and their steps stay the brief's own claim, shown apart from the closures the registry records. A task brief's first line becomes the task's title everywhere on the page, and the rest says why it exists, for whom and when it is finished; without one, the task keeps its recorded title and reads «descrizione non ancora scritta» (description not written yet). Only the coordinator records briefs: UTF-8, at most 8192 bytes, kept as artifacts. A new brief replaces the old one on the page, every version stays in the history, and a brief never changes a task's state. `--id` names the decision (otherwise `dec-e`, a reserved form). `--task` links existing tasks; `--follows` names an earlier `ask:` or `decision:`, never a bare name, and is fixed when written. An owner instruction without a question may carry `--channel typed-here` or `relayed` with non-empty `--owner-words`; without one the page says «canale non registrato» (channel not recorded). `--choice` requires `--answers`, and an instruction, a mention or a `--follows` never closes a question. **Replacing a task.** `task ... --supersedes T0` records that a new task replaces the open task T0; `supersede --actor coord --task T0 --by T1 --reason "..."` records it afterwards, when the work already moved to an existing, later T1 that does not wait for T0. T0 leaves the next steps and waits and keeps its whole history; tasks that depend on it stay blocked, and nothing is cancelled, released, completed or reassigned. Both are refused while T0 has a run still running or with an unverified stop, an owner holding a reservation, or an open question, and a task cannot depend on the task it replaces; `supersede` also needs a non-empty reason. **Reading the graph.** Each box is a recorded fact, earlier on the left. **Solid lines** are recorded links; **dashed lines** only mean "later, in the same task", never a reason. Owner boxes always show the channel: «scritto qui» (typed here), «riferito da un'altra finestra» (relayed by another window) or «canale non registrato»; verdicts are written in words as well as colours. Select a box (click, Enter or Space) for who, when, the full words and the links both ways; filter by task and zoom. Refreshes keep selection, filter, zoom and focus, and say «elemento non più presente» when an item is gone. On a phone the graph becomes a list in time order, with reduced motion respected; circular links, possible only in an altered registry, are listed under «Collegamenti non ordinabili». The full rules are in [work, proof and review](work.md). **The rules of the read.** - **Block only on a grave finding**, including missing or invalid mandatory safety evidence; fix the rest now with a non-author check of the delta and the original case, or record medium and low findings as follow-ups. Each follow-up has its own task, or a decision naming the responsible one, with an observable trigger or deadline and an acceptance check, linked from the report until closed. A deferred requirement is not satisfied, and mandatory safety requirements are kept. - **Readers** are available non-authors chosen with `task --reviewer`, working in parallel on frozen copies, with shared gates, ports and databases reserved. The handoff that `deliver` generates is the go for the assigned read once its recipient ACKs it; the CLI never invokes a client by itself. A corrective read uses the same budget, and no alias or new task resets spent rounds. - **Browser and installation steps** need the capability proven first by a probe receipt in the right context (for a browser: a named DevTools connection, timeouts, private resources, owned cleanup). Without it, declare the step **not run**, cite the last valid run and inform the coordinator. **Never hand commands to the owner**, and no capability bypasses execution permissions. - **Options and budgets:** `--depends T0` (prerequisites closed independently first), `--expected N` (recognized count of executed tests; skips never count), `--full-gate` (a gate-labelled proof); none of them proves a suite complete, so agree the real command with the project. By default three plan reads, two code reads and three build attempts in the optional runner (`init --plan-rounds/--review-rounds`); acceptance binds to the latest plan bytes; exhausted budgets need an explicit disposition, never a reset. Small changes get proportionate checks. - **`prove`** keeps the native status, duration, output and before/after fingerprints of tracked and non-ignored files; ignored dependencies need their own evidence. **`deliver`** needs a passing proof on the exact current source, freezes an immutable packet, returns a `review-…` ID and never invokes a model. - **`review`** records `accepted`, `changes-required` or `blocked`. `probe` records independent tests and negative controls (`--expected-rc 1`; a matched negative is not a product pass); mutants go in isolated copies. `--covers` records coverage, not test adequacy, which the reader judges. - **`check`** binds candidate, plan, proof, artifacts and coverage again before `close`. For new CLI tasks the delivered frozen source binds the proof and review; changing that copy invalidates both. Legacy tasks retain live-source binding. `advance` reconciles a delivered handoff without building, approving or waking clients; without `--reviewer` the manual review protocol applies. `--reply-to` answers; `--to-new waiting-reader` creates an expected recipient, not an identity: register the real seat before its ACK. `transport --via manual` returns a pending handoff instruction and records `delivered: null` (unconfirmed), and success with `--via codex-queue` means queued, not read or awake. Every codex-queue attempt is recorded: one that did not deliver keeps `delivered: false` (or `null` after a timeout) with its `stage`, and the command exits 1. The coordinator relays any message a sandboxed window could not deliver (`transport --actor --message --via codex-queue`, or `--via manual`), recorded with `relayed_by`; only the recipient's ACK ends it. A Codex window keeps the registry folder among its writable roots (`codex --add-dir `). The protocol authorizes no external messaging. Save **one substantive output per completed step**: a result, decision, blocker or handoff that adds information (omit `--task` for area-wide coordination). Its declared next step is not evidence that anything happened. Routine progress comes from the registry, so no manual "ready" messages and no retelling of an existing proof; real ACKs, decisions, pauses and receipts stay required. Attach an artifact named exactly `da-ricordare.json` (`form: "da-ricordare/1"`, task ID, `answer: "yes"` or `"no"`, `items`) to the closing agent's usual `squadra output --artifact ...`; see [the schema and examples](work.md#da-ricordare-at-close). Nothing is proposed or approved by itself. **If a memory service is in use, declare at close and do not propose the same item through another channel.** **Never** put secrets, personal data or private paths in it: registered artifacts are immutable, so an accidental secret cannot be removed. Plugin consumers may turn declarations into drafts; the action API only saves the user's selection and never sends it or runs a plugin ([action contract](plugins.md#action-requests)). `--channel relayed` keeps words reported by another window. `decision --withdraws Q1` closes an obsolete question without inventing an answer; a `decision --reason` without links keeps a reason without closing a question. Answers and withdrawals are exclusive and never repeated. Chat text, mail prose and `output.next` are never silently read as decisions or authority. Wait ages are computed when a view is read. Defaults, in seconds: **ACK 900**, **delivered 3600**, **reviewed 1800**, **heartbeat 1800**, **alive 300**; `cleanup-unknown` is always shown. `settings --actor coord --file /evidence/thresholds.json` sets chosen keys, such as `{"ack": 600, "alive": 300}` (zero warns at once); it replaces earlier custom values, and omitted keys use the defaults. A warning never retries, reassigns or releases anything. ```sh squadra resource acquire --actor builder --name gate --reason "Frozen candidate" # For a full-gate task, run its agreed proof with prove --gate. # Release only after the terminal result and resource reconciliation. squadra resource release --actor builder --name gate --reason "Run ended" squadra ping --actor coord --to builder # Forward each returned ID (codex-queue needs a Codex seat registered with --session); ping invokes no client. squadra transport --actor coord --message PING-ID --via codex-queue squadra standby --actor coord --agent builder --reason "Window unavailable" squadra standby --actor coord --agent builder --resume --reason "Availability confirmed" ``` - **Resources:** reserve gates, ports and databases before use, and respect other windows' reservations. A stale heartbeat or a timeout does not prove a process stopped, nor does it free its resources. - **Presence:** `ping --all` calls each other active identity once, skipping stand-by; a pending ping is reused and never extended. The sweep counts only a ping a transport reported `delivered: true`. `--to` can call a window in stand-by, whose real ACK lets it return at the next sweep; old ACKs, aliases and new registrations never do. - **Only the coordinator changes availability**, with `ping --sweep` (re-checked inside the transaction) or `standby`. All aliases of a window share its stand-by, during which new assignments and review handoffs to it are refused. - **Stand-by stops nothing:** it **does not cancel processes, release resources, transfer roles or reassign work**; return restarts nothing; no timer or page view changes the state; an unanswered ping proves no absence. ### Waiting for a resource and declaring proof coverage `resource acquire --actor builder --name gate --reason "Frozen candidate" --wait 3600` waits up to one hour, in arrival order among callers using `--wait`. The command prints the holder and initial queue position once, polls every 0.2 seconds without journal or projection writes, and reserves only after an actual release. A timeout records one refusal; a dead waiter does not block the line. `--wait 0` tries the resource once without waiting for a holder or passing earlier waiters. Its queue bookkeeping tolerates up to 250 ms per mutex acquisition (two acquisitions), so a brief concurrent `resource status` does not cause an immediate refusal. Positive waits retain their single total deadline. A caller already holding the resource (including an alias of its identity) refuses immediately. Without `--wait`, immediate acquisition/refusal is unchanged; older or immediate callers do not join the line and may win a reservation race. Waiting requires POSIX locks and a private queue for one OS user: 0700 directories and 0600 files under `resource-waits/` in the registry. Shared-user queues and Windows waiting are refused explicitly; immediate resource commands remain available. Each poll closes its SQLite transaction before sleeping and demands only authenticated cache leaves. A missing, foreign or stale cache refuses waiting rather than replaying/rebuilding history in a poll; prepare a moved or copied registry with an ordinary write first, and use `doctor` for integrity details. Queue tickets are runtime sidecars, outside checkpoints and the journal. Non-ticket entries such as Finder's .DS_Store are ignored without opening or removing them; ticket and mutex safety checks still apply. If the queue mutex stays busy until the deadline, the refusal says "Resource queue mutex busy; wait deadline expired", rather than claiming the resource is already reserved. On a task with requirements, `prove` needs explicit `--covers ID` before any precheck or proof starts. Partial coverage is allowed. A successful proof prints `coverage_on_this_source`, with covered and uncovered IDs per task; it counts only passing proofs with the current contract on the same exact source. This summary is not delivery or review acceptance. Tasks without requirements keep their previous behavior. A shared proof's coverage is the union of member IDs; the shared-proof preflight also requires complete coverage for every member. Every window writing to one registry should run the same Squadra version, or some rules may not be enforced; moving a working squad to another version is an explicit, authorized step. For a task declared with `task --defect-fix`, closure requires proof that the regression fails without the change. Register its own unittest method IDs and frozen test files with `challenge --task T1 --register --contract-file ... --reason ...` as coordinator, then run `challenge --actor builder --task T1 --output /evidence/challenge-T1`. For example, a value regression asserts 2: it fails on the original value 1 and passes after the fix. The same test bytes run on the registered base and exact candidate, even before commit. Errors, skips, missing IDs and a test that passes both versions never qualify. The result and logs appear next to the proof. A coordinator may declare an exception with a reason; the independent reader checks it, and it never appears as a passed challenge. Source or agreement changes need fresh bindings; light fixes keep the requirement. The normal proof and independent review still apply. Old tasks keep working; frozen squads require an explicit upgrade of every writer, with no mixed-version enforcement. See the [complete example and limits](work.md#defect-fixes-show-that-the-regression-detects-the-original). The coordinator may declare `task --route light` for a bounded, reversible change after the usual questions. Policy **light-v1 / P2** allows at most **80 added plus deleted lines in four files** and 16 KiB of changed lines, counted from the original clean Git base, including tests and documents. Replacing one line counts as two; commits during the task do not reset the count. Binary files, symlinks, type/mode changes, missing bases, unstable snapshots and empty changes refuse. No compression to qualify. P2 admits descriptive Markdown under docs/references, README EN/IT and tests. All scripts, plugin bundles, the dashboard page (`assets/dashboard.html`, which holds the dashboard token), client/CI/build/dependency files, instruction files and normative contracts stay protected; unknown paths are protected too. The exact exclusions are in [the workflow](work.md#light-route). A security impact or required whole gate still takes the full route: size and paths never grant permission. The light route skips a plan read and uses the agreed targeted proof instead of a whole suite; it allows one code-read round. A non-author reader, assignment/handoff ACKs, exact source and contract bindings, native results, explicit requirement coverage, pauses, reservations, budgets and required evidence remain. Release final reads and the owner's typed publication permission do not change. Example: a wording fix of **12 added/deleted lines in README.md and README.it.md** can use the agreed targeted test of those two files; a fix to the dashboard page cannot, because the page is protected. The registry remeasures before a proof process, on delivery, check and close, including direct Store writes. An excess or protected path refuses with a `light_*` code and “Full route required”; a second light read is refused too. Only the coordinator can promote with `route --full --scope-file ... --proof-file ... --reason ...` (and `--full-gate` or `--expected` when required). Promotion keeps the base, authors, history and spent counters, invalidates old proof/read bindings, and has no reverse. It cannot reset an exhausted budget. Existing tasks without a route keep their behavior. A frozen squad must explicitly coordinate an upgrade of **every writer** before registering light tasks; installing this release does not migrate it. Older CLIs ignore this new metadata: mixed-version enforcement is not promised, and a 3.6.x window in such a squad still shows a task promoted to the full route as light. Unknown future policies remain readable but cannot qualify work. ### Dashboard transfers The page polls every two seconds while visible. Its compact state request includes the token of the copy it holds; an unchanged reply retains that copy and advances relative times locally. Registry changes, overdue-wait/presence transitions, activity buckets and plugin discovery invalidate the token. Authentication and registry verification still precede a cached answer. Older compact clients that do not send the state-token header retain their previous response format. The overview receives text previews and evidence summaries. Full message bodies, outputs, history and artifact references load when their page, overview details or task story is opened. Details are bound to the registry head, so an older reply cannot overwrite newer state; a failed read offers retry. The full task/run JSON remains available from the technical-data control. Usage and, after integration, Balance poll independently because session data can change without registry events. ## Reader transfer, resource inspection and workflow improvements (3.11) Upgrade every window before the first new task or transfer: these events use hash format 3, which old clients refuse. Existing histories are not rewritten. ```text squadra reassign --actor coord --task T1 --reviewer reader2 --reason "Reader occupied" squadra resource status --name cpu-heavy squadra resource acquire --actor builder --name port-8000 --task T1 --reason "T1 preview" squadra task ... --proof python3 -B -m unittest tests.test_feature squadra deliver --actor builder --task T1 --note "Check the deletion case too" squadra close --actor coord --task T1 --note "Frozen candidate accepted" ``` Reassignment preserves the delivery, native proofs and spent budgets and replaces only its reader/packet. The new reader ACKs its exact handoff. A live or uncertain native reader must be reconciled first. Previous handoffs leave the pending queue; old readers cannot record a verdict. A recorded verdict needs an explicit review amendment, never a transfer that silently replaces it. New-policy verdict retries return their receipt without another round; legacy CLI reviews retain their record shape and stable event IDs prevent repeated submissions. For new-policy tasks, `review --amend RECEIPT` explicitly amends the current verdict within the original budget. Resource status shows reservations and locked FIFO tickets, never inferred process presence. Stale tickets are omitted without cleanup. Task-scoped reservations stop unrelated work from blocking supersession; legacy reservations remain conservative. `send` returns the message receipt without the project table; use `status` for it. At close, apply [migliora](skills/migliora.md) to evidenced friction. It adds no rule without a trigger, evidence, real check and retirement condition. The helper can append an instruction in `AGENTS.md`, check it and create a local pathspec commit, with `--defer-commit` and a later explicit `migliora commit` when a required review must happen between them. It preserves other staged work and native hooks. It never publishes, pushes or approves project memory proposals. ## Frozen source storage and recovery Each new delivery retains the working-tree bytes and Git objects for its delivered commit (shallow depth 1), plus the light task base commit/tree/blobs when needed. Both roots count toward the storage quota; other history and ignored dependencies are excluded. A shared candidate can retain an additional light base without changing its read-only checkout bytes. Default limits are 512 MiB per copy and 2 GiB total, including damaged copies and staging. A conservative estimate is checked before fetching and actual bytes before sealing; concurrent deliveries, repair, retirement and checkpoint copies share a storage lock. Checkpoint candidate metadata comes from its exact SQLite backup, with registry read views released before slow file copying. A checkpoint can require up to one additional total quota. It includes registry artifacts, projections, run-lease evidence and healthy frozen repositories, but not `runs/`, queue tickets or dashboard/transport sidecars; reconcile process and abandonment evidence on the original machine before resuming. Save packages also retain their separately documented all-refs repository bundles, HEAD, staging/worktree patches and filtered untracked or explicitly included files. See [the exact filters and unscanned history/stash/artifacts](recovery.md#esclusioni-e-destinazione). `squadra candidate status` reports retained bytes and per-delivery availability. `doctor` reports journal integrity separately from `candidate_integrity`; a damaged or missing source cache degrades the latter. Checkpoint/save/export preserve the journal and artifacts even when a source cache is unavailable; the checkpoint report and save manifest list omitted copies. Their historical proof is not a restored source. Review and close still refuse unavailable or changed candidates, naming task, SHA and paths. All mutations below require the coordinator and a recorded `--reason`: ```text squadra candidate repair --actor COORD --task TASK --reason "Recover reader pollution" squadra candidate retire --actor COORD --task CLOSED_TASK --reason "Retention after closure" squadra candidate retire --actor COORD --sha256 SHA --reason "Obsolete delivery no longer in use" squadra candidate limits --actor COORD --max-copy-mib 1024 --max-total-mib 4096 --reason "Larger project" ``` Repair requires the original checkout to match the exact proved snapshot; it preserves the damaged folder as `candidates/damaged-*` and rematerializes in read-only mode. If those original bytes are gone, restore them or create a newly proved delivery. Retirement by `--task` selects its current delivery; `--sha256` selects a historical delivery, including copies made obsolete by redelivery, promotion or a fix. It is refused only while an open, non-superseded task's current delivery uses that SHA. The receipt names the historical task. Retirement records removal, preserves the journal/proofs, and makes doctor/checkpoint agree on `retired`. No cache is silently collected. Quarantine remains evidence and counts toward quota; archive the registry if that evidence fills storage. Quotas may be explicitly raised (up to 100 GiB total) before delivering a larger project. A successful repair receipt contains `phase: completed`; an interrupted attempt may retain only `phase: started`. Delivery and close notes remain in the journal/state and delivery packet; the compact `stato.md` table does not display the closure note. Read the task state for its full text. Claude plugin paths are explicit (`./` and `./migliora`), following the [official manifest contract](https://code.claude.com/docs/en/plugins-reference#fields). Manifest guards verify both paths; client discovery is a separate integration check. ## Reader readiness An assigned independent reader can declare availability before delivery: ```sh squadra ready --actor reader --task T1 squadra ready --actor reader --task T1 --revoke ``` The first command records `reader.ready` in journal format 4. Status, board and dashboard show “reader ready, waiting for delivery” / “lettore pronto, attende consegna”. A pool member declares only its own readiness. Registration alone makes no declaration. Readiness does not ACK an assignment or a future delivery, claim a pool, start a read, consume a read budget, or record approval. The actual delivery clears it and creates the usual handoff: the configured reader still explicitly ACKs that exact message. Revocation, stand-by, window re-registration, delivery and replacement clear stale readiness. Returning from stand-by does not restore it; declare it again. A changed author window also clears readiness so the reader can recheck independence. The follower normally shows ten pending messages on its first arm. It keeps all messages of one atomic event together, even at that boundary, so a sequence cursor never skips part of a replacement. Reading the mailbox still leaves every ACK explicit.