The loop
voss team run composes the team config, board, session tree, and the Reviewer-A/B pair, then drives em_loop to completion and persists a final record. The EM, the role workers, and both reviewers all call the provider you pick with --auth and --model.
Write scope and approval
Workers run unattended. They edit files and run shell commands without asking for each action, so a run needs a write scope before it starts:- Pass
--scope(repeatable), or setceiling.scopein.voss/team.voss. With neither, the command exits with an error.--scopecan’t replace a ceiling scope the team file already sets. - Each worker can write only inside its role scope, or the ceiling scope when the role sets none. On a terminal you’re asked before a write outside it. Without a terminal the write is refused.
- Shell commands aren’t scope-limited. Any
.voss/safety.ymland.voss/permissions.ymlrules still apply to them. - Before any work starts, the command asks once whether to continue.
--yesskips that question.
Done only when the worker’s own test run exits 0 and both reviewers pass it. A failed gate or review sends the card back to its worker with the reviewer’s notes, up to the retry ceiling. After that the card is Blocked.
When the run ends, the command prints the card counts and the path to run-final.json, then asks you to approve or reject the run. --no-signoff skips that question and leaves the run unsigned, so scripts can run voss team run --yes --no-signoff without a terminal.
Done or Blocked, when max-iterations is reached (default 50), or when the budget is exhausted.
EM operations
The EM agent emits a plan of typed ops — it never mutates state directly:The cage
The cage is enforced by API surface, not by trusting the model. The handle the EM drives has noset_ceiling, set_budget, extend_budget, register_role, or mutate_team_config method. Violations raise EMCageViolation(op, reason):
- Dispatching or ticketing a
worker_rolenot in the roster. - Rescoping to a scope not contained in the ceiling.
- Killing or rescoping a card already in
Done.
Blocked and ends the run.
The final record
When the loop ends it persists aRunFinal record:
Kill and rescope events persist their own lineage records, so a killed or rescoped card stays inspectable. Inspect the result with
voss review, voss board, and voss session tree.