$team
Parallel execution across lanes that do not touch each other. Coordination is not free — use this only when the work genuinely splits.
Entry contract
$team is independently invocable.
| Requirement | How it can be satisfied |
|---|---|
objective |
Stated inline, or on record |
parallel-lanes |
Derived from a $plan artifact, or described inline as 2+ independent lanes |
goat contract team
The independence test
Before splitting, every pair of lanes must pass all three:
- Disjoint files. No two lanes edit the same file. Shared files are a merge conflict waiting to happen, and resolving them costs more than the parallelism saved.
- No ordering dependency. Lane B does not need Lane A's output to start.
- Independent verification. Each lane can be verified on its own.
If any pair fails, they are one lane. One lane is not a team — run $ultragoal
instead and say so:
This splits into 1 real lane (all three candidates edit
src/router.ts). Running$ultragoalinstead;$teamwould add coordination cost for no parallelism.
Method
1. Declare the split
goat state set --stage team --status active --objective "<objective>"
Write .goat/goals/<slug>-team.md:
# <objective>
## Lanes
### L1 — <name>
- Files: <exact paths this lane owns>
- Outcome: <what done looks like>
- Verify: `<command>`
### L2 — <name>
...
## Merge order
<L1, L2, ... and why>
## Shared invariants
<what every lane must not break>
File ownership is exclusive. A lane that needs a file it does not own stops and reports; it does not reach across.
2. Run the lanes
Each lane, independently:
- Implement only inside its owned files.
- Run its verification command.
- Record evidence, tagged with the lane:
goat ledger evidence --stage team --exit <code> -- <command> # L<n>: <lane name>
A failing lane does not stop the others. Record it as blocked, keep the rest moving, and report it at merge.
3. Merge
- Merge in the declared order.
- Run the whole project's verification, not just the per-lane commands. Lanes that pass alone can still break together — this run is the point of the merge step.
- Record the merged evidence:
goat ledger evidence --stage team --exit <code> -- <full verification command>
4. Close
complete only when every lane merged and the whole-project verification exited 0. If any
lane is still blocked, close blocked — this stage tells lanes to keep moving past a
failure, so arriving here with one unresolved is an expected outcome, not an error:
# every lane merged, full verification green
goat state set --stage team --status complete --artifact .goat/goals/<slug>-team.md \
--summary "<lanes merged, what shipped>"
# any lane blocked, or the merged verification failed
goat state set --stage team --status blocked --artifact .goat/goals/<slug>-team.md \
--summary "<which lanes landed, which did not, who owns the rest>"
The merged verification command is this stage's proof, and the report file must be on disk
at the path you record — goat status opens it, and a path that was never written reports
complete*. Lane commands alone do not close the stage: they prove lanes, not the merge.
Report contract
Return, per lane: name, owned files, outcome, verification command and exit code, and blocked status if any. Then the merged verification result. A lane with no evidence is reported as unverified, never as done.
Handoff
$code-review— review the merged change as one unit.$ultraqa— adversarial QA once merged behavior is runnable.