cli-forge-chef — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cli-forge-chef (Agent Skill) and scored it 66/100 (yellow). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 8 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 8 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Optimization: Heavy content lives in references/. Load on demand.Language rule: Skill instructions are written in English. When generating user-facing files (prompts, shared-state, tmuxinator comments, reports), detect the project's primary language (from README, comments, docs, commit messages) and produce those files in that language. If the project is bilingual, ask the user which language to use before proceeding. The Brigade vocabulary (Menu, Commis, Sous-Chef, Chef, Plat, Mise en place, etc.) stays in French regardless — it's the pattern's canonical terminology, not prose.
Gotchas: Read../gotchas.mdANDreferences/gotchas-chef.mdbefore producing output.
"On ne cuisine pas seul. On cuisine en brigade." — Auguste Escoffier ("You don't cook alone. You cook in a brigade.")
┌─────────────────────────────────────────────────────┐
│ CLIENT │
│ (user, ticket, roadmap) │
│ │
│ Orders plats via the MENU (PERT) │
│ "I want: decision tokens + E2E + sokolsky" │
└──────────────────────┬──────────────────────────────┘
│ order
┌──────────────────────▼──────────────────────────────┐
│ CHEF DE CUISINE │
│ (plans, decides, orchestrates) │
│ │
│ - Reads the menu (PERT / roadmap) │
│ - Assigns plats to the commis │
│ - Decides the order in which to send them out │
│ - Asks the Sous-Chef to taste before sending │
│ - Calls "Envoyez !" when it's ready │
│ - NEVER COOKS │
└──────────────────────┬──────────────────────────────┘
│ SendMessage
┌──────────────────────▼──────────────────────────────┐
│ 3 VOTING SOUS-CHEFS │
│ (taste, judge — quorum 2/3) │
│ │
│ sous-chef-scope : is the plat in your station? │
│ sous-chef-secu : any broken glass in the plat? │
│ sous-chef-qualite : does it taste right? │
│ │
│ 2/3 APPROVE → passes │
│ 1 DENY → sent back to the kitchen │
│ 1 ESCALATE → call the patron (human, ~5% of cases) │
├──────────────────────────────────────────────────────┤
│ SOUS-CHEF MERGE │
│ (plates up, sends to the pass) │
│ │
│ - Quality gates (/cli-audit-*) │
│ - Merge + CI (tmux send-keys gate) │
│ - Updates the carnet (shared-state.md) │
│ - Runs in bypassPermissions │
│ - CWD = {project}-wt-gate │
│ (push + PR allowed, apply DENIED) │
├──────────────────────────────────────────────────────┤
│ APPLY PANE (only if infra present) │
│ (executes tofu/helm/kubectl after 3/3 quorum) │
│ │
│ - Receives APPLY_REQUEST from any agent │
│ - Runs the plan (tofu plan, helm diff, kubectl diff)│
│ - Submits plan to 3 voting sous-chefs — 3/3 needed │
│ - Executes only after unanimous APPROVE │
│ - Prod target → extra PATRON ACK │
│ - CWD = {project}-wt-apply │
│ (tofu/helm/kubectl allowed, git push DENIED) │
│ - See references/apply-quorum.md │
└──────────────────────┬──────────────────────────────┘
│ SendMessage
┌──────────────────────▼──────────────────────────────┐
│ COMMIS (x N) │
│ (cook, prep, plate) │
│ │
│ - Each has their own station (worktree / project) │
│ - Prepare their plat (code, test, commit) │
│ - Announce "Pret !" to the sous-chef │
│ - DO NOT DECIDE when to send out │
└──────────────────────┬──────────────────────────────┘
│ "Plat au passe"
┌──────────────────────▼──────────────────────────────┐
│ MAITRE D'HOTEL │
│ (pass → client, landing watchdog) │
│ │
│ - Receives PRs once auto-merge is enabled │
│ - Polls until MERGED (not just "auto-merge on") │
│ - Rattrapage: rebase BEHIND branches when main moves│
│ - Relance: rerun transient CI failures (max 2x) │
│ - Renvoi: real failures go back to the Sous-Chef │
│ - Encaissement: tag verified + shared-state updated │
│ - Reports "Client content" only when all 6 done │
│ │
│ Read references/maitre-dhotel.md for the full role │
└──────────────────────┬──────────────────────────────┘
│ "Client content + tag"
┌──────────────────────▼──────────────────────────────┐
│ CLIENT (happy) │
│ Release tag cut, prod deploy green, sprint done │
└─────────────────────────────────────────────────────┘~5% of cases. The human is called only when a Sous-Chef votes ESCALATE:
| Case | Who escalates | Why |
|---|---|---|
Edit on .github/workflows/ | sous-chef-scope | CI = global impact |
| New dep in Cargo.toml | sous-chef-secu | Supply chain risk |
| Test removal | sous-chef-secu | Never auto-approve |
| Diff > 200 lines | sous-chef-qualite | Too big to judge quickly |
| File from another worker | sous-chef-scope | Potential conflict |
Everything else passes without human intervention.
| Brigade term | Meaning | Example |
|---|---|---|
| Carte du jour | Review of sensitive zones (sprint start) | "ci.yml moves to 3/3, log_backend stays 2/3" |
| Marche | Project inventory (git log, PRs, incidents) | "3 DENYs on ci.yml during sprint S3" |
| Produit frais | Normal zone (2/3) with no incidents | "src/features/ : 0 DENY in 3 sprints" |
| Produit sensible | 3/3 unanimity required | "Cargo.toml: rustls-pemfile advisory" |
| Produit retire | Past hallucination → now a test case | "Blind auto-approve → G16" |
| Nouvelle recette | New module to classify | "log_backend → normal, self_tuning → sensitive" |
| Menu | PERT (dependency DAG of plats with durations) | "Sprint S3: 4 plats, critical path A→C→D" |
| Commande | Ticket / task | "feat/hit-decision-tokens" |
| Plat | Feature merged + CI green | PR #88 merged |
| Mise en place | shared-state.md "In progress" | Worker writes its target files |
| Cuisson | Coding + tests | Worker codes in its worktree |
| Dressage | Commit + cleanup | cargo fmt, clippy clean |
| Gouter | Quorum vote by the Sous-Chefs | "2/3 APPROVE (normal) or 3/3 (sensitive)" |
| Pass | CI pipeline | gh run watch |
| Envoi | Merge + green light | "Envoyez! feat/x merged." |
| Plat au passe | Sous-Chef hands a PR to the Maître d'hôtel with auto-merge on | "Plat au passe: #201, auto-merge squash" |
| Rattrapage | Maître d'hôtel rebases a BEHIND branch | "Rattrapage #201: main moved after #200 landed" |
| Relance | Maître d'hôtel reruns a transient CI failure (max 2x per cause) | "Relance #202: CodeQL rate-limit" |
| Encaissement | Maître d'hôtel confirms MERGED + tag cut + shared-state updated | "Encaissement #201 → v0.36.17" |
| Client content | Maître d'hôtel signals full landing to the Chef | "Client content: 3 plats, 2 tags, 0 orphans" |
| Renvoi | Gate failed or quorum DENY, or real failure from Maître d'hôtel | "Renvoie! Sous-Chef Secu proposes: ..." |
| Appel au patron | ESCALATE (< 2%) | "Patron, edit on ci.yml, 3 rounds without consensus" |
| Coup de feu | Parallel phase | 4 commis at the same time |
| Service | Full sprint | Phase 0 → Phase N → report |
A plat moves through a fixed sequence of states between Ready and Envoye. A DENY from a sous-chef loops back to Cuisson; a critical failure (same diff rejected twice, regression, 30-min idle) triggers Apoptosis and the plat re-enters the pool.
stateDiagram-v2
[*] --> Ready
Ready --> MiseEnPlace: dispatched to commis
MiseEnPlace --> Cuisson: write-set locked in shared-state
Cuisson --> Dressage: code + tests pass locally
Dressage --> Gouter: commit + lint clean, sent to Sous-Chef
Gouter --> Envoi: 2/3 APPROVE (normal) or 3/3 (sensitive)
Gouter --> Renvoi: DENY or CONCERN with solution
Renvoi --> Cuisson: commis applies the proposed fix
Envoi --> PlatAuPasse: Sous-Chef creates PR with auto-merge + F8 conflict scan
PlatAuPasse --> EnSalle: Maitre d'hotel receives the plat
EnSalle --> Surveillance: polling loop every 45s
Surveillance --> Surveillance: CLEAN / HAS_HOOKS / UNSTABLE (wait)
Surveillance --> Rattrapage: BEHIND (main moved)
Rattrapage --> Surveillance: rebase + force-push-with-lease + re-enable auto-merge
Rattrapage --> Renvoi: rebase conflict
Surveillance --> Relance: BLOCKED + transient CI
Relance --> Surveillance: gh run rerun --failed
Relance --> Escalade: 3rd transient in a row
Surveillance --> Renvoi: BLOCKED + real failure OR DIRTY merge conflict
Surveillance --> Encaissement: MERGED
Encaissement --> ClientContent: tag verified + shared-state Valid merges updated + cascade Rattrapage on other in-flight
ClientContent --> [*]: Chef notified, plat fully served
Escalade --> [*]: > 2h timeout, Chef takes over
Cuisson --> Apoptosis: same diff rejected 2x / idle 30min / regression
Dressage --> Apoptosis: same diff rejected 2x / regression
Apoptosis --> Ready: revert + locks released, plat re-enters the pool
Gouter --> AppelAuPatron: 3 rounds without consensus
AppelAuPatron --> Cuisson: human decision applied
AppelAuPatron --> [*]: human aborts the platThis is the authoritative plat lifecycle — if prose anywhere else disagrees, fix the prose.
Commis edits a file
→ Chef sends the diff to the 3 voting Sous-Chefs (parallel)
→ 2/3 APPROVE → passes automatically (zero human)
→ 1 DENY → sent back to the commis with a reason
→ 1 ESCALATE → Chef notifies the patron (human)
Commis finishes cooking
→ "Pret !" to the Sous-Chef (SendMessage)
→ Sous-Chef tastes (quality gates)
→ IF good:
→ Sous-Chef plates up and sends (merge + CI)
→ Sous-Chef to Chef: "Plat sent, table served"
→ Chef to dependent commis: "Envoyez the next one!"
→ IF not good:
→ Sous-Chef to Commis: "Renvoi! Too much salt in fn X"
→ Sous-Chef to Chef: "Renvoi on plat Y, commis is fixing it"$ARGUMENTS is the target project path or name.
First, check whether a sprint is currently running or paused:
Read references/sprint-persistence.md. Check .claude/sprint-history/current/:
Before generating anything, understand the project:
| Signal | Type | Build tools | Test command | Lint command |
|---|---|---|---|---|
Cargo.toml | Rust | cargo | cargo test | cargo fmt && cargo clippy |
go.mod | Go | go | go test ./... | golangci-lint run |
package.json | JS/TS | npm, npx | npm test | npm run lint |
pyproject.toml / setup.py | Python | python3, pip, uv | pytest | ruff check |
*.tf / terragrunt.hcl | Terraform | terraform, tofu | terraform plan | terraform validate |
Chart.yaml / helmfile.yaml | Helm | helm | helm template | helm lint |
docker-compose*.yml | Docker | docker, podman | N/A | docker compose config |
flake.nix | Nix | nix | nix flake check | nix flake check |
| Multiple of above | Monorepo | union | per-workspace | per-workspace |
If no manifest found → ask the user: "What type of project is this? (Rust, Go, JS/TS, Python, Infra, Other)"
Use the detected type to:
settings.local.json (only include relevant tools)#### Tools
| Tool | Check | Install (Fedora/RHEL) | Install (macOS) | Install (Debian/Ubuntu) | Fallback |
|---|---|---|---|---|---|
| tmux | which tmux | sudo dnf install tmux | brew install tmux | sudo apt install tmux | None — required |
| tmuxinator | which tmuxinator | brew install tmuxinator (preferred) or gem install tmuxinator | brew install tmuxinator | gem install tmuxinator | Raw tmux script — see references/raw-tmux-fallback.md |
| claude | which claude | npm i -g @anthropic-ai/claude-code | npm i -g @anthropic-ai/claude-code | npm i -g @anthropic-ai/claude-code | None — required |
| gh | which gh | sudo dnf install gh | brew install gh | sudo apt install gh | Manual CI checks |
# Check all prerequisites
for tool in tmux tmuxinator claude gh; do
which "$tool" >/dev/null 2>&1 || echo "MISSING: $tool"
done
grep -q "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS" ~/.claude/settings.json 2>/dev/null || echo "AGENT_TEAMS_NOT_ENABLED"If a tool is missing → show the install command for the detected OS and stop.
#### VCS — git or jj
The project MUST be a version-controlled repository. Check:
# Detect VCS type
if [ -d .jj ]; then
VCS="jj"
elif git rev-parse --git-dir >/dev/null 2>&1; then
VCS="git"
else
echo "FATAL: not a git or jj repository. Initialize with 'git init' or 'jj git init' first."
exit 1
fiIf not a repo → stop and ask the user to init. The Chef never creates a repo — that's a user decision.
#### Branching model detection
Auto-detect the project's branching model. Never assume Git Flow.
# Detect GitHub repo
REPO=$(gh repo view --json nameWithOwner,defaultBranchRef -q '.nameWithOwner' 2>/dev/null)
DEFAULT_BRANCH=$(gh repo view --json defaultBranchRef -q '.defaultBranchRef.name' 2>/dev/null)
# Detect branching model by examining existing branches
HAS_DEVELOP=$(git branch -r 2>/dev/null | grep -c 'origin/develop')
HAS_RELEASE_BRANCHES=$(git branch -r 2>/dev/null | grep -c 'origin/release/')
HAS_RELEASE_PLZ=$(test -f release-plz.toml && echo 1 || echo 0)
if [ "$HAS_DEVELOP" -gt 0 ] && [ "$HAS_RELEASE_BRANCHES" -gt 0 ]; then
BRANCH_MODEL="gitflow"
BASE_BRANCH="develop"
RELEASE_BRANCH="main"
elif [ "$HAS_DEVELOP" -gt 0 ]; then
BRANCH_MODEL="github-flow-develop"
BASE_BRANCH="develop"
RELEASE_BRANCH="main"
elif [ "$DEFAULT_BRANCH" = "main" ] || [ "$DEFAULT_BRANCH" = "master" ]; then
BRANCH_MODEL="github-flow"
BASE_BRANCH="${DEFAULT_BRANCH}"
RELEASE_BRANCH="${DEFAULT_BRANCH}"
else
BRANCH_MODEL="trunk"
BASE_BRANCH="${DEFAULT_BRANCH:-main}"
RELEASE_BRANCH="${BASE_BRANCH}"
fi| Detected model | Base branch | Release branch | Commis branch from | PR target | Sync-main needed? |
|---|---|---|---|---|---|
| github-flow | main | main | main | main | No |
| github-flow-develop | develop | main | develop | develop | Yes |
| gitflow | develop | main | develop | develop | Yes (via release branches) |
| trunk | main/master | same | main | main | No |
Impact on the brigade:
#### GitHub repo & branch protection (G26)
if [ -z "$REPO" ]; then
echo "WARNING: not a GitHub repo or gh not authenticated. PR mode unavailable."
MERGE_MODE="direct"
else
# Detect if base branch requires PRs (G26)
PROTECTED=$(gh api repos/${REPO}/rulesets 2>/dev/null | grep -c 'pull_request')
if [ "$PROTECTED" -gt 0 ]; then
MERGE_MODE="pr"
echo "DETECTED: branch protection requires PRs → Sous-Chef will use PR mode"
# Check auto-merge is enabled in repo settings
AUTO_MERGE=$(gh api repos/${REPO} --jq '.allow_auto_merge' 2>/dev/null)
if [ "$AUTO_MERGE" != "true" ]; then
echo "FIX: enabling auto-merge on the repo (required for PR mode)"
gh api repos/${REPO} --method PATCH -f allow_auto_merge=true 2>/dev/null
fi
else
MERGE_MODE="direct"
fi
fiRecord ALL detected config in shared-state.md so the Sous-Chef and commis know at runtime:
## Sprint config
| Key | Value |
|-----|-------|
| VCS | {git or jj} |
| Branch model | {github-flow / github-flow-develop / gitflow / trunk} |
| Base branch | {main / develop / master} |
| Release branch | {main / master} |
| Merge mode | {direct or pr} |
| Repo | {owner/repo} |
| Default branch | {from GitHub API} |
| Sync-main needed | {yes or no} |#### gh auth scopes
# Check gh has the required scopes
gh auth status 2>&1 | grep -q "repo" || echo "MISSING: gh scope 'repo'"If the project has CI workflow files that may need editing, warn:
NOTE: pushing .github/workflows/ changes requires the 'workflow' scope.
If needed during the sprint: gh auth refresh -s workflow
After the push: gh auth refresh (to remove it)#### Agent isolation model (CRITICAL — G26 + industry best practice 2026)
Every commis MUST work in an isolated worktree with its own branch. Never on the base branch directly.
RULE: 1 commis = 1 worktree = 1 branch = 1 PR
Base branch (develop or main) is NEVER modified directly by a commis.
All work flows through: worktree → branch → push → PR → auto-merge.This is the pattern used in production by teams running 4-7 parallel agents (incident.io, 2026). It prevents:
Worktree setup per commis:
# Chef creates worktrees in Phase 0 (in on_project_start or manually)
git worktree add ../{project}-wt-{commis_name} -b {branch_name} 2>/dev/null || trueConflict pre-detection (optional but recommended for 3+ commis):
If clash is installed (which clash), add to the ccheck or Sous-Chef loop:
clash status # shows conflict matrix across all worktrees
clash check {file} # check before writing a specific fileIf not installed, the coupling matrix from Phase 0.5 (/cli-audit-tangle) serves as the static conflict prevention.
Merge sequencing:
When multiple commis are done:
git rebase origin/{base_branch}Never merge all PRs simultaneously — sequential merge with rebase between each avoids the quadratic conflict explosion.
Exception: missing tmuxinator is NOT a blocker. If Ruby/gem is not available (air-gapped env, immutable OS like Bluefin/Silverblue), generate the raw-tmux fallback instead:
references/raw-tmux-fallback.md{project}/.claude/scripts/boss-{session}.sh (chmod +x)bash {project}/.claude/scripts/boss-{session}.sh instead of tmuxinator start {session}Auto-fix configuration (G19, G20, G22) — do ALL of these automatically, don't ask:
~/.claude/settings.json: ensure CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 + skipDangerousModePermissionPrompt=true~/.claude.json: ensure "teammateMode": "tmux"{project}/.claude/settings.local.json: ensure all permissions (build tools, shared-state, external repos, Obsidian vault, Team tools)on_project_start: ensure auto-kick message with sleep 12 && tmux send-keys ... & (G20)Read references/simplified-model.md. Two models exist — pick based on tier. The S/M/L/XL semantics are canonical in ../shared/tiering.md — this skill's tier table specializes them to brigade composition (1 commis → full XL brigade w/ sous-chef clusters).
| Signal | Tier | Model | Agents | Quality gates |
|---|---|---|---|---|
| 1-2 tasks, single repo | S | No brigade | 1 commis alone | Auto-check (proofreading) |
| 3-4 tasks, single repo | M | Stigmergy | 1 sous-chef (3 lenses) + N commis | Adaptive (DNA repair) |
| 5+ tasks or multi-repo | L | Stigmergy | 1 sous-chef (3 lenses) + N commis | Adaptive (DNA repair) |
| 10+ tasks, monorepo, regulated | XL | Full brigade | Chef + sous-chef clusters + N commis | Full (vote, audit trail) |
Tiers S/M/L: the Chef generates files in Phase 0 and then disappears. Commis self-organize via shared-state.md (Boids + stigmergy). The single Sous-Chef reviews with 3 lenses. Commis that fail self-terminate (apoptosis).
Tier XL: the full brigade is kept for regulatory compliance (vote audit trail, decision traceability).
For tier S: skip tmuxinator entirely. Use a single claude invocation with --append-system-prompt and one worktree.
For large projects (monorepos, multi-domain, regulated), each domain has its own cluster of 3 sous-chefs. Each cluster votes internally (2/3), then the clusters vote among themselves (2/3 normal, 3/3 sensitive).
Chef de Cuisine
│
├── SECURITY cluster (3 sous-chefs) — internal vote 2/3
│ ├── sous-chef-secrets (DLP, credentials, env vars)
│ ├── sous-chef-deps (supply chain, advisories, licenses)
│ └── sous-chef-perimeter (scope, access, file permissions)
│ → Produces 1 consolidated verdict: APPROVE / DENY+solution
│
├── QUALITY cluster (3 sous-chefs) — internal vote 2/3
│ ├── sous-chef-coherence (mission, design, architecture)
│ ├── sous-chef-tests (coverage, pyramid, regression)
│ └── sous-chef-proprete (code smells, dead code, naming)
│ → Produces 1 consolidated verdict
│
└── OPS cluster (3 sous-chefs) — internal vote 2/3
├── sous-chef-ci (pipelines, workflows, matrix)
├── sous-chef-deploy (infra, docker, helm)
└── sous-chef-perf (benchmarks, timeouts, resources)
→ Produces 1 consolidated verdict
Inter-cluster vote:
Normal zone: 2/3 clusters APPROVE → passes
Sensitive zone: 3/3 clusters APPROVE → passes
DENY: the cluster that DENYs proposes a solution
Resolution rounds: identical to tier MTier XL means 9 sous-chefs + 1 merge = 10 validation agents. Use it only when the cost of errors justifies the cost of the agents (regulated, defense, finance).
Selection logic (the Chef decides in Phase 0):
The Chef detects the tier at startup:
- Number of tasks → S/M/L
- Multi-repo → L minimum
- CONTRACTS.md file or compliance/ → XL
- Mention of "regulated", "defense", "finance" in README/CONTRIBUTING.md → XL
- User can force: /cli-forge-chef --tier XLCost confirmation for tier XL (MANDATORY — auto-detect or flag):
Tier XL costs roughly 5-8x the tier L token spend (10 validation agents instead of ~2, each diff voted on by 9 sous-chefs instead of 3, audit trail generated every round).
Before spawning the XL brigade, always display and ask for confirmation:
=== TIER XL DETECTED ===
Reason: {detection_reason} # e.g., "CONTRACTS.md present" or "--tier XL flag"
Brigade: Chef + 9 Sous-Chefs (3 clusters) + 1 Sous-Chef + N Commis
Estimated cost: ~5-8x tier L (each diff voted on by 9 agents instead of 3)
Estimated duration: ~2-3x tier L (inter-cluster resolution rounds)
Recommended justification:
- Regulated project (defense, finance, healthcare)
- Legal audit trail required
- Cost of errors > cost of agents
Continue with XL? [y/N/downgrade-to-L]If the user answers downgrade-to-L, switch to tier L and note in the Phase 4 report: "Tier XL detected but downgraded to L at user request".
This confirmation is as mandatory as the Phase 0.6 confirmation for EXPLORATION.
Read references/conflict-resolution.md. Before assigning tasks:
/cli-audit-tangle on the projectRead references/parallel-exploration.md. For each task, the Chef asks:
EXPLORATION tasks use 2-3 commis on the same problem with different approaches. The Sous-Chef runs the comparison grid and the Chef picks the winner. Confirm with user before launching (2-3x token cost).
LANGUAGE RULE: run `git log --oneline -10` + `head -20 README.md`. If the project is in French → ALL generated files (prompts, shared-state, tmuxinator comments, reports) are in French. If English → English. The Brigade vocabulary (Menu, Commis, Sous-Chef) stays in French regardless of the project language.
COMMITS RULE: commis and the Sous-Chef use `cli-git-conventional` for ALL commits. Ghostwriter style, zero AI marker, project language.
RULE: do NOT ask any question if the answer is in the project. Read EVERYTHING before asking anything:
{project}/.claude/shared-state.md "Backlog" section (work from the previous sprint)gh issue list (open issues)git log --oneline -20 (recent work, what's missing)Only if NOTHING found → ask
references/pert-computation.md end-to-end. Summary:cli-audit-tangle). If present, each plat is matched to its Fiedler cluster and one commis owns one cluster for the sprint — file-exclusion becomes structural, not a runtime filter. Boundary functions become mandatory fan-in barriers in the PERT. If absent, run /cli-audit-tangle first on any sprint with > 5 plats; otherwise fall back to file-level coupling detection.cli-audit-tangle couplings + explicit semantic dependencies. W on a file created by A → depends on A. Otherwise → parallel.E=(O+4M+P)/6 and σ=(P-O)/6.done (not readiness alone). Critical-path plats go to the first free commis.flowchart LR with :::critical, see pert-computation.md §5) + the companion text table to shared-state.md under ## PERT. This is the scheduling contract for the whole sprint.Don't ask.
ls {workspace}/ for neighbouring reposDon't ask.
/cli-audit-code onlyDon't ask.
git branch -a | head + CONTRIBUTING.md. It's always written down. Don't ask.Only ask the user if:
Present the deduced menu and ask for confirmation: "Here's what I'm going to launch. OK?"
Read references/templates.md for templates. Generate:
{project}/.claude/shared-state.md)Read references/shared-state-template.md and customize.
{project}/.claude/prompts/chef-{session}.md)ABSOLUTE REQUIREMENT: read `references/chef-prompt-template.md` BEFORE generating the prompt. The generated prompt MUST contain the 3 voting Sous-Chefs + the Sous-Chef. If the prompt does not contain "sous-chef-scope", "sous-chef-secu", "sous-chef-qualite", "sous-chef" → the prompt is INVALID.
The Chef prompt MUST include, in this order:
The Chef:
COPY the prompts of the 3 sous-chefs from `references/chef-prompt-template.md` section "Spawn the 3 Sous-Chefs".
Each votes independently: APPROVE / DENY+solution / CONCERN+solution. Resolution rounds if no consensus. Human escalation < 2%.
Prompts are CLI surfaces — ask once, default sensibly, recap before action, ship as committable files. The canonical 4 Laws + surface mapping is ../shared/cli-ergonomics.md.
COPY the prompt from `references/chef-prompt-template.md` section "Spawn the Sous-Chef".
Handles quality gates, merges, CI. Does not vote on permissions. On PR creation, runs the F8 parallel conflict scan (cli-forge-github), enables auto-merge, and hands off to the Maître d'hôtel — the Sous-Chef does NOT wait for the PR to land.
COPY the prompt from `references/chef-prompt-template.md` section "Spawn the Maître d'hôtel". Read `references/maitre-dhotel.md` for the full role specification.
The Maître d'hôtel is the brigade's post-merge landing watchdog. He receives every PR the Sous-Chef hands off (with auto-merge already enabled), polls the GitHub merge queue every 45 s, and stays on the plat until it is MERGED, the release tag is cut (if applicable), cascading BEHIND rebases are done on every other in-flight PR, shared-state.md "Valid merges" is updated, and the Chef has received the "Client content" signal.
Why mandatory at tier ≥ M: without a Maître d'hôtel, "auto-merge enabled" is mistaken for "merged". The operator ends up rebasing PRs by hand every time release-plz bumps a version, exactly what this brigade pattern is designed to avoid. One Maître d'hôtel per brigade, centralized polling, cheap (Sonnet, no judgement).
Scale rule (from maitre-dhotel.md §7):
| Signal | Spawn M'H? |
|---|---|
| 1 plat in the sprint | No — Sous-Chef inline |
| 2-3 plats, no release automation | No — Sous-Chef inline |
| ≥ 4 plats OR release-plz present OR branch protection active | Yes, mandatory |
| Critical-path sprint (any failure = sprint slip) | Yes, mandatory |
| Project uses GitHub merge queue | Yes, mandatory |
Each commis prompt includes:
Generate one script into {project}/scripts/:
scripts/brigade-setup-worktrees.sh — copy verbatim from references/brigade-setup-worktrees.sh, chmod +x. Idempotent worktree + permission setup, recovers from orphan state, avoids SIGPIPE on git worktree add (G35), one branch per commis (G36).The script creates every role's worktree, installs the per-worktree .claude/settings.local.json files, and creates the integration branch. It is called by on_project_start in the tmuxinator YAML.
Note on the previous launcher wrapper: earlier iterations of this skill also generated scripts/brigade-launch-agent.sh to work around $(cat prompt.md) shell-mangling (G34). That wrapper is no longer generated — use the native --append-system-prompt-file flag directly in the tmuxinator YAML (see §2.5c). The wrapper was overkill.
~/.config/tmuxinator/{session}.yml)Read references/tmuxinator-template.md.
# Chef — use --append-system-prompt-file (native, G34-safe)
- claude
--dangerously-skip-permissions
--permission-mode bypassPermissions
--teammate-mode tmux
--append-system-prompt-file {project}/.claude/prompts/chef-{session}.md
"Demarre IMMEDIATEMENT Phase 0 selon le system prompt."No wrapper script, no $(cat ...), no .initial.txt files.
Generate `{project}/.claude/prompts/ccheck-{session}.md`.
Read references/ccheck-prompt-template.md and customize with the project paths.
The ccheck is a dedicated Claude instance in its own tmux window that watches the Chef pane and auto-approves UI keyboard permissions in normal zones. Without it, the Chef blocks on every worker edit and the brigade stalls.
The ccheck:
/tmp/{session}-ccheck.logThis replaces the Phase 5 `/loop` approach which was fragile (depended on the user's session staying open) and optional (it should never have been optional).
Why this exists : ccheck handles only UI keyboard prompts (Do you want to make this edit?). In Agent Teams mode (tier ≥ M), commis request permissions through the team protocol — these appear as Permission request sent to team "<team>" leader cards that cannot be approved via keyboard. The Chef (team leader) must approve via SendMessage tool call. If the Chef is in a thinking loop or busy, these requests queue up for 30+ min and block commis. Observed on grob-s5 (2026-04-17) : commis-2 waited 45 min for a shared-state.md edit on normal zone.
Generate `{project}/.claude/prompts/contre-chef-inter-{session}.md`.
Read references/contre-chef-inter-prompt-template.md and customize with the project paths.
The contre-chef-inter is a Haiku-powered team member in its own tmux window that:
(commis, tool, file) tuple from each pending cardSendMessage to the Chef with pre-chewed APPROVE or HOLD recommendation/tmp/{session}-inter.logScale rule:
| Tier | Spawn contre-chef-inter? |
|---|---|
| S (1 commis, no Agent Teams) | No |
| M (2-5 commis via TeamCreate) | Yes, mandatory |
| L+ (parallel Agent Teams) | Yes, mandatory |
Cost: ~$0.05 per 6h sprint (Haiku 4.5, ~50 iterations × ~2k input tokens).
Why different from ccheck: ccheck sends tmux send-keys Enter (keyboard); contre-chef-inter sends SendMessage (team protocol). They handle orthogonal permission pathways. Both are needed at tier ≥ M.
Note on `tmux send-keys` as rung 5: keyboard injection into a UI is rung 5 of `../shared/escalation-ladder.md` — used here only because the underlying Claude Code UI exposes no programmatic permission-grant API (rungs 1-4 don't exist for this specific flow). It is gated on the ccheck's read-the-diff decision and logged for audit. Never extend this pattern to operations that have a real API.
settings.local.json per worktree)Read references/permissions-template.md.
Every role gets its own `.claude/settings.local.json` inside its own worktree — BUT the Agent Teams reality is more nuanced than « one file per role, filesystem-isolated » (see G32). In practice:
read their own cwd's settings.local.json. These are separate claude processes, each with its own permission file. Filesystem isolation works for them.
TeamCreate/Agent): DO NOT support cwd: on spawn. They inherit the team lead's (Chef's) settings.local.json. The per-worktree files for these roles exist on disk (useful for documentation and for potential future migration to standalone panes) but they are ignored at runtime.
Practical implication: the Chef's root settings.local.json is the only one that actually gates commis / sous-chef Bash commands. Put the strictest deny list there — teammates inherit it. Allow dangerous primitives only in standalone pane files (gate, apply, maitre).
Generate the following files (see the template for exact contents):
| File | Role | Key allow | Key deny |
|---|---|---|---|
{project}/.claude/settings.local.json | Chef root | SendMessage, read-only git, Skill(cli-*) | all git push, tofu, helm upgrade, gh release |
{project}-wt-gate/.claude/settings.local.json | Sous-Chef Merge | git push, gh pr merge | tofu apply, helm upgrade, git push --force* |
{project}-wt-maitre/.claude/settings.local.json | Maître d'hôtel | git rebase, git push --force-with-lease (feature only) | force-push on main/master/develop/trunk, tofu, kubectl apply |
{project}-wt-apply/.claude/settings.local.json | Apply pane | tofu:*, helm:*, kubectl:*, ansible:* | git push, git commit, gh pr |
{project}-wt-vote-{scope,secu,qualite}/.claude/settings.local.json | 3 voters | Read, SendMessage | all Write/Edit, all mutating Bash |
{project}-wt-commis-N/.claude/settings.local.json | Commis N | build tools, local git (no push), plan/diff variants | git push, tofu apply, helm upgrade, kubectl apply, PR merge |
Apply quorum (read references/apply-quorum.md): tofu apply, helm upgrade, kubectl apply, gh release create, and feature-branch force-push all go through the apply pane AFTER a 3/3 unanimous vote on the plan by the 3 sous-chefs. The permissions above deny these commands to every other role; the apply quorum protocol gates the apply pane itself.
ALWAYS include gotchas from references/gotchas-chef.md in the chef prompt.
The 8+ hard gates below are this phase's post-verification step; the 3-phase definition-of-done structure (pre → during → post) is canonical in ../shared/done-gate.md.
tmuxinator doctor git branch | grep -c "chore/phase-a-{session}" # expect (N commis) + 1 integrationtest -x {project}/scripts/brigade-setup-worktrees.sh — if missing/non-exec, STOP! grep -q 'pipefail' {project}/scripts/brigade-setup-worktrees.sh — setup must NOT set pipefail (G35)! grep -q '\$(cat ' ~/.config/tmuxinator/{session}.yml — YAML must NOT shell-expand the prompt (G34)grep -qc 'append-system-prompt-file' ~/.config/tmuxinator/{session}.yml — YAML uses native file flag (G34)! test -f {project}/scripts/brigade-launch-agent.sh — obsolete wrapper should NOT exist (delete if found)git branch | grep -c '{base_branch}-' equals number of commis (G36)grep -q 'ccheck' ~/.config/tmuxinator/{session}.yml — if missing, STOP and add the ccheck windowtest -f {project}/.claude/prompts/ccheck-{session}.md — if missing, STOP and generate the ccheck promptgrep -q 'inter' ~/.config/tmuxinator/{session}.yml — if tier ≥ M and missing, STOP and add the inter windowtest -f {project}/.claude/prompts/contre-chef-inter-{session}.md — if missing, STOP and generateAgent { name: "contre-chef-inter" in the TeamCreate spawn blockPresent to the user:
tmuxinator start {session}references/gotchas-chef.md G39 (process count, open PRs, remote branches). All three must be > 0 by T+10 min..claude/prompts/chef-{session}.md are valid specs to execute manually.Agent + TeamCreate permission delivery is broken.references/gotchas-chef.md)The ccheck (contre-chef) window is part of the tmuxinator config — it starts automatically with tmuxinator start {session}. No manual `/loop` setup needed. The user does not need to do anything.
The ccheck watches the Chef pane every 30 seconds and:
/tmp/{session}-ccheck.log for traceabilityThe user can leave. The ccheck keeps watch.
Why this replaced the old `/loop` approach:
/loop ran in the user's session, not in tmux → closing the terminal killed it/loop was described as optional ("Phase 5") → but without it the Chef blocks/loop prompt was frozen at creation → zones added mid-sprint were ignoredtmuxinator start/stop), reads fresh state every tick, and cannot be accidentally closedTo stop: CronDelete {job_id}
| File | Content |
|---|---|
references/gotchas-chef.md | 19 known pitfalls (G24 ccheck, G25 trust guard, G26 protected branch, G39 inter-agent permission deadlock + takeover protocol, G40 empty worktree shells) |
references/templates.md | Index of all templates |
references/shared-state-template.md | The carnet de cuisine |
references/chef-prompt-template.md | Chef + Sous-Chef + Commis instructions |
references/tmuxinator-template.md | Tmuxinator YAML |
references/permissions-template.md | settings.local.json |
references/quality-gates.md | The tasting card (audit skills) |
references/conflict-resolution.md | Decision tree, coupling matrix, file locking, escalation, stigmergy, patch bankruptcy, divergence, convergence, sprint health |
references/anti-patterns-chef.md | 10 named brigade anti-patterns (Ping-Pong, Ghost Commis, God Commis, etc.) |
references/sprint-persistence.md | Checkpoint, resume, rewind, fresh restart, sprint history (inspired by jj operation log) |
references/simplified-model.md | Stigmergy model for tiers S/M/L — Boids, quorum sensing, DNA repair, reaction-diffusion, apoptosis |
references/pert-computation.md | O/M/P estimates, critical path, list scheduling with file-exclusion, precedence patterns, triage quadrant — "aller vite sans s'emmêler les pinceaux" |
references/maitre-dhotel.md | Post-merge landing watchdog — receives PRs from the Sous-Chef and polls until MERGED + tag cut + shared-state updated. Handles BEHIND/BLOCKED/DIRTY/transient without waking the operator |
references/sprint-report-template.md | Post-sprint report — gitGraph (branch topology), sankey (commis-hours flow), radar (quality), xyChart (Amdahl) |
references/parallel-exploration.md | Competing hypotheses, parallel approaches, comparison grid |
references/ccheck-prompt-template.md | Contre-chef prompt (permission auto-approver) |
references/raw-tmux-fallback.md | POSIX bash script equivalent to the tmuxinator YAML (for Ruby-less environments) |
references/apply-quorum.md | Plan-then-apply 3/3 quorum protocol for tofu apply, helm upgrade, kubectl apply, gh release create, feature-branch force-push |
references/brigade-setup-worktrees.sh | Idempotent worktree + permissions setup (G35 fix — no SIGPIPE; G36 fix — one branch per commis; orphan dir recovery) |
| Skill | Relation |
|---|---|
/cli-audit-tangle | Phase 0 — identify couplings to assign modules to commis without conflicts |
/cli-audit-code | Quality gate per merge — the sous-chef runs it before each merge |
/cli-audit-drift | Quality gate per merge — checks that code honours the contracts |
/cli-audit-test | Quality gate per merge — checks the test pyramid |
/cli-audit-sync | Post-merge quality gate — checks doc/code coherence |
/cli-cycle | End of service — global sprint scorecard |
/cli-forge-pipeline | Optimize the CI pipeline the commis will trigger |
/cli-forge-tree | Validate the project structure before assigning worktrees |
/cli-git-conventional | ALWAYS — every commit from the commis and Sous-Chef goes through ghostwriter. Zero AI markers |
/cli-forge-doc | If a quality gate detects missing docs — the Sous-Chef triggers generation |
/cli-forge-schema | If a quality gate detects a missing diagram — Mermaid generation |
/cli-forge-github | Post-sprint — clean orphan branches, check rulesets vs CI alignment, close stale PRs |
/cli-forge-perf | Tier XL's sous-chef-perf (OPS cluster) runs cli-forge-perf as a quality gate before merge — the catalogued bench protocol replaces ad-hoc perf claims |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.