teams-setup

v2026.09.24

Creates and manages dynamic teams of domain agents. Triggers: create team, agent team, team status, cleanup team.

GitHub
Install command
npx skhub add kochetkov-ma/teams-setup
Markdown
SKILL.md
<!-- brewcode-meta: version=6.2.0 content_version=6.2.0 generated_by=brewcode:teams-setup --> <instructions>

Teams

Manage dynamic teams of domain-specific agents with tracking framework.

Arguments: $ARGUMENTS


Prompt contract

Position 1 of $ARGUMENTS is a free-form prompt (RU/EN) — the mode and the [name] positional are optional and may follow in any order. Nobody types keys: resolve mode + team name FROM the prompt.

ModeEN keywordsRU keywordsMutates?
status(empty), status, show, list, checkстатус, покажи, что, проверьno
installinstall, create, setup, new team, buildустанови, создай, настрой, новая командаyes
upgradeupgrade, update, tune, improve, retuneобнови, улучши, настрой лучшеyes
enableenable, on, turn on, activate, restoreвключи, активируй, верни, восстановиyes
disabledisable, off, turn off, pause, parkвыключи, отключи, пауза, приостановиyes
uninstalluninstall, remove, delete, clean up, tear downудали, убери, сними, очистиyes, destructive
purgepurge, wipe, nuke, delete everything, remove allснеси, удали всё, вычисти, полностью удалиyes, destructive
  1. Strip flags (--skip-review, --review). An explicit mode token anywhere wins outright, no scoring.
  2. Else score modes by distinct whole-word keyword hits (table above). Highest unique score wins. Tie with a destructive mode -> AskUserQuestion; tie with status -> status; tie of two mutating modes -> the keyword appearing first; all zero -> the documented default: status if the named team already exists, else install (detect-mode.sh already applies this default when the input is empty or the first word is not a canonical mode).
  3. Empty arguments -> the same default. status asks nothing; install and the other mutating defaults ask ONE scoping question only when the answer changes what gets written.
  4. Outcome-changing ambiguity -> ONE AskUserQuestion (max 4 questions) BEFORE any work.
  5. A prompt that is not a bare mode [name] pair is still input, never an error: extract the team NAME (and, for install, the team description) from the prose. Never treat the first word of a sentence as the positional [name] — "disable the payments team" names team payments, not disable; detect-mode.sh's literal first-word parse is only correct for a bare mode [name] shape, see Error Handling below for the prose case.

Then print this block ONCE, before the first action (## Universal Prelude Step 0.4):

PLAN — brewcode:teams-setup
INPUT:  <arguments verbatim, or "(empty)">
MODE:   <resolved> — <explicit | matched keyword: X | default>
SCOPE:  <team name, agent count/roster, paths under .claude/teams/{name}/ and .claude/agents/>
DO:     <2-5 imperative bullets>
RESULT: <what the user ends up holding>

Labels are literal; values follow the conversation language. status still prints it — asks nothing.


Phase 1: Parse Arguments

EXECUTE using Bash tool:

bash "${CLAUDE_SKILL_DIR}/scripts/detect-mode.sh" "$ARGUMENTS" && echo "OK" || echo "FAILED"

Output: MODE:, TEAM_NAME:, PROMPT: (optional), plus the artifact-metadata scalars PLUGIN_VERSION:, CONTENT_VERSION:, GENERATED_BY:, LAST_UPDATED:. Store all of them.

Artifact metadata — every file this skill writes. team.md and every generated domain agent carry version = PLUGIN_VERSION:, generated_by = GENERATED_BY: (brewcode:teams-setup), last_updated = LAST_UPDATED:, and doc_type: llm on the agents. team.md's header table ALSO carries content_version = CONTENT_VERSION:, right after Version — self-located by detect-mode.sh from THIS skill's own SKILL.md line-1 brewcode-meta: marker (the one bump-version.sh stamps at release), never copied from PLUGIN_VERSION: and never invented. Take the values from the output above — never hardcode a version, never call date a second time with a different format, and never stamp a "template version": the plugin version replaces it. .claude/agents/intent-guard.md is the ONE exception: generate.sh emit-agent stamps it with generated_by: brewcode:superreview-setup, and teams never touches those keys.

Resolve INTENT_GUARD_POLICY before a write: a new team defaults to required; an existing team.md with |Intent guard|required| or |Intent guard|legacy-absent| keeps that exact value. When the row predates this field, presence of an intent-guard roster member migrates to required; absence migrates to legacy-absent. These are the only values. required requires the fixed review-only row; legacy-absent forbids that row and MUST NOT add the role during upgrade.

Resolve REPORT_ROOT from the applicable project guidance before every team.md write. The narrowest durable project instruction wins (for example, Dusk's Codex guidance requires .codex/reports even when this Claude workflow performs the write); otherwise use .claude/reports. Store a normalized project-relative path with no trailing slash. Reject absolute paths, ~, .. segments, backslashes, whitespace, doubled slashes, unresolved {...} tokens, control characters, or shell metacharacters. Every slash-separated segment MUST match ^[A-Za-z0-9._-]+$ and MUST NOT equal . or ..; this rejects $(), backticks, ;, &, and | by construction. If equally specific applicable guidance declares two distinct report roots, STOP on the conflict instead of selecting either. Never infer the report root from this plugin's own defaults when project guidance declares one.

MODE is one of the canonical seven, in this order: status | install | upgrade | enable | disable | uninstall | purge. On any ERROR: line: report it verbatim and STOP. Never guess a mode, and never treat a canonical verb as a team name — install enable creates a team NAMED enable, so the verb always comes first and the optional [name] positional after it.

How a team is enabled or disabled. Claude Code discovers a project agent only through .claude/agents/<name>.md. disable renames each member to <name>.md.disabled; enable renames it back. The file body, team.md, trace.jsonl, trace-archive.jsonl and the cursor are untouched either way, so the toggle is fully reversible and loses no configuration and no history. It is NOT an uninstall: nothing is deleted. Under required, intent-guard is never parked — it is shared with /brewcode:superreview-setup, exactly as in UNINSTALL and PURGE. Under legacy-absent, no guard file or roster row is introduced.


Universal Prelude (every mode)

Step 0: Init + Validate + Confirm

  1. Output: Mode: {MODE}, Team: {TEAM_NAME}

  2. Load environment:

ActionCommand / Path
Read agent template${CLAUDE_SKILL_DIR}/references/agent-template.md
Read framework templates${CLAUDE_SKILL_DIR}/references/framework-files.md
Check team dir.claude/teams/{TEAM_NAME}/ -- exists?
Check existing agents.claude/agents/ -- list all
If team.md existsRead, show current roster
If trace.jsonl existsShow entry counts via trace-ops.sh read

An absent trace.jsonl is valid before the first event or after cleanup: status reports zero events, verification stays read-only, and trace-ops.sh add creates it safely on the first write. A present trace target must be a non-symlink regular file.

  1. Preflight the durable tokenizer without network or mutation:

    python3 -I -S "${CLAUDE_SKILL_DIR}/scripts/prepare-tokenizer.py" check
    

    If it is missing, retain the emitted REPAIR: ... prepare command. status reports the missing prerequisite and does not run team verification. A mutating mode waits for step 5 approval before preparation. If the preflight passes and the team exists, verify:

    bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
    
  2. Print the PLAN block (## Prompt contract above) — once, before step 5's confirmation and before any mutation. status prints it too, then skips straight to its report — no AskUserQuestion.

  3. Mutating modes only — ASK using AskUserQuestion: "PLAN above. Continue?" Options: "Yes, continue" | "No, I want changes" | "Cancel"

    • "changes" -> AskUserQuestion for details, revise the PLAN and reprint it
    • "Cancel" -> STOP
  4. After approval, prepare the isolated tokenizer when step 3 reported it missing, then preflight it again. This explicit step is the only tokenizer install/network path; it downloads the exact platform wheel and BPE into the user cache, verifies both SHA-256 values, creates a dedicated venv, and installs the wheel with --no-deps --no-index:

    python3 -I -S "${CLAUDE_SKILL_DIR}/scripts/prepare-tokenizer.py" prepare \
      && python3 -I -S "${CLAUDE_SKILL_DIR}/scripts/prepare-tokenizer.py" check
    

    STOP on failure. verify-team.sh and count-tokens.py never install, download, or use a temporary runtime; they fail closed with the same repair command.


Delegation (applies to EVERY Task spawn in this skill)

A big task handed to one agent = an agent gone for an hour: you cannot observe it, cannot correct it, and it usually drifts off-target. One subagent = ONE bounded unit — one deliverable (here: ONE agent file), ~<=5 files, ~<=10 steps. Bigger MUST be split into N tasks, all spawned in ONE message. That is why agents are created one-per-spawn and reviews are fanned out.

Every spawn prompt MUST carry:

FieldContent
GOALthe overall task and why it exists — the point beyond the file edit
ROLEwhat this agent owns; what it must NOT touch
SCOPEexact paths/commands in bounds + explicit out-of-bounds
CONTEXTwhat is already done, by whom, what runs in parallel — trimmed to what THIS agent needs
CONSUMERwho or what uses the result next, and the shape it must fit
DONEacceptance criteria + the exact report shape you want back

A bare one-line task is never enough. See C8 for the canonical spawn shape. Every code/test brief MUST make the agent find the closest well-built counterpart in the repo and follow its principles - IN ADDITION to conventions/rules/docs, never instead.


Mode: INSTALL (9 phases)

C1: Project Analysis

Spawn 3-5 Explore agents in ONE message via Task tool:

#Focus
1Code structure: modules, packages, domains, architectural layers
2Existing agents (.claude/agents/, brewcode/agents/, ~/.claude/agents/) + Claude Code infrastructure
3Tech stack: build files, frameworks, dependencies, languages
4CI/CD, testing, deploy, infrastructure
5 (optional)Domain boundaries: business logic, API, data layer, UI

All via Task(subagent_type="Explore"). Consolidate into single analysis document.

For the new team's default required policy, also harvest the intent-guard facts (agent #1 and #4 cover most of these; add explicit asks to their prompts). These fill the placeholders of the shared intent-guard.md.template in C3 — an unharvested fact must be recorded as none / not present in this project, never invented:

FactFillsWhere to look
Project name{PROJECT_NAME}repo dir, root CLAUDE.md, package.json/build file
Where original requirements live (tracker, issues, Slack, "chat only"){TRACKER_LABEL}CLAUDE.md, .github/, issue templates, CI links
Spec / design-doc paths or globs{SPEC_LOCATION}.claude/specs/**, docs/, adr/
Plan / task-board / task-graph paths{PLAN_LOCATION}.claude/features/**, TASKS.md, board files
Policy paths: root + nested CLAUDE.md, rules, conventions{POLICY_LOCATION}CLAUDE.md, .claude/rules/**
Planned scale / user count, testing policy, dependency policy, file-layout policy, architecture stance{PROJECT_INVARIANTS_TABLE}CLAUDE.md, rules, test dirs, manifests, module layout
3-6 plausible drift instances in this repo's vocabulary{DRIFT_EXAMPLES_TABLE}derived from the invariants above
Cheap evidence commands (diffstat, manifest diff, test-file count, new-file list) for this stack{EVIDENCE_COMMANDS_BASH}build/test tooling found by agent #3 and #4

Also resolve and store REPORT_ROOT from applicable root/nested project guidance using the prelude rule. An exact durable project path wins; guidance silence falls back to .claude/reports. Equal-specificity conflicting report-root directives -> STOP. Validate the winning path before C2.6.

C2: Team Proposal (interactive)

Based on analysis + PROMPT (if provided), propose 3 variants via AskUserQuestion.

New installs use INTENT_GUARD_POLICY=required: intent-guard is a fixed review-only anti-drift member (asked-vs-delivered), outside the domain-agent count. The 5 / 10-12 / 15-20 counts describe DOMAIN agents only. Show it as fixed in every new-install variant:

Fixed member (every variant, not counted):
| Agent | Domain | Mission |
| intent-guard | -- (review-only) | Compares what was ASKED vs what was DELIVERED; explicit invocation only |

Minimal (5 domain agents + intent-guard):
| Agent | Domain | Mission |

Balanced (10-12 domain agents + intent-guard) -- Recommended:
| Agent | Domain | Mission |

Maximum (15-20 domain agents + intent-guard):
| Agent | Domain | Mission |

Options: "Minimal (5)" | "Balanced (recommended)" | "Maximum (15-20)" | "Custom -- I'll specify"

If "Custom" -- second AskUserQuestion for free input; the new-install required policy stays fixed. Final confirmation of agent list before proceeding. Existing legacy-absent teams are handled only by UPGRADE and retain their explicit policy without adding intent-guard.

If .claude/agents/intent-guard.md already exists (e.g. /brewcode:superreview-setup created it), label the fixed row reuse (already present) — C3-IG's emit-agent call will report REUSE and leave the file untouched.

Agent names are globally unique across teams — REJECT a name another team already owns. Two teams listing the same agent share one file: one team's upgrade rewrites the other's member, and the other's uninstall/purge is then blocked by the ownership check (cleanup-flow.md Step 3 step 0c), leaving an undeletable roster row. Before showing the variants, run from the project root for every proposed name (intent-guard excluded — it is shared BY DESIGN and exempt from this check):

for a in {PROPOSED_NAMES}; do
  o=$(bash "${CLAUDE_SKILL_DIR}/scripts/agent-owners.sh" "$a") && echo "TAKEN $a <- $o"
done; echo "OK"
  • exit 0 (any owner printed) -> the name is TAKEN. Drop it from the variant and propose a distinct one — a domain-qualified rename such as {name}-{TEAM_NAME} or a different domain word. Never reuse, never "join" the other team's agent.
  • exit 2 (no owner) -> free, use it.
  • exit 1 (refusal, reason on stderr) -> treat the name as TAKEN until the reason is fixed; report the stderr line, do not guess.

Say which names were renamed and why in the confirmation before C3.

C2.5: Model Selection (AskUserQuestion)

"Default model for domain agents: Opus (most reliable)."

ModelBest forCost
opusComplex domains, architecture, critical logicHigh
sonnetStandard domains, CRUD, testing, utilitiesMedium
haikuSimple utility agents, formatting, validationLow

Options: "Opus (recommended)" | "Sonnet" | "Haiku" | "Mixed -- I'll choose per agent"

If "Mixed" -- ask model per agent in C3. Store as DEFAULT_MODEL (default: opus).

DEFAULT_MODEL applies to DOMAIN agents only. intent-guard keeps the model: sonnet its shared template ships — do not ask about it, do not override it.

C2.6: Shared Contract Bootstrap (before agent discovery)

This gate MUST finish before any team-owned .claude/agents/{name}.md is written. An interrupted install may leave a partial roster, but no discoverable compact profile may ever point at a missing shared contract.

  1. Create .claude/teams/{TEAM_NAME}/.
  2. Read ${CLAUDE_SKILL_DIR}/references/framework-files.md; write team.md with substituted metadata, validated REPORT_ROOT, INTENT_GUARD_POLICY=required, the byte-faithful ## Shared Agent Contract, exact "intent-guard is review-only, keeps its own output contract, and never implements." substitution, the ## Agents header, and only the required fixed intent-guard row. Do not add domain-agent rows yet; C4 finalizes the successfully created roster.
  3. Create empty trace.jsonl; copy the project-local trace-ops.sh and make it executable.
  4. Gate before C3: team.md exists, contains ## Shared Agent Contract, the project-local tracer path, and A task traced \took` ends with exactly one terminal track: `completed` or `failed`.`

STOP on any failure. Do not spawn or write an agent. Resume by repairing this bootstrap first; never strip shared rules from a profile until its target team.md passes the gate.

C3: Agent Creation (agent-creator x N)

  1. Read ${CLAUDE_SKILL_DIR}/references/agent-template.md 1a. Confirm C2.6 completed. .claude/teams/{TEAM_NAME}/team.md is already written and gated; if missing or incomplete, STOP before the first spawn and repair the bootstrap. 1b. Re-run the C2 uniqueness check on the FINAL confirmed roster, immediately before the first spawn — the user may have typed names in the "Custom" branch that never passed it. Same script, same exit-code reading. Any TAKEN name -> do not spawn; go back and rename it with the user first. Also refuse a name whose .claude/agents/{name}.md.disabled exists with no live file: that is another install's parked agent, and writing the live path recreates the dual-copy state both enable and disable refuse.

  2. For each agent, spawn Task(subagent_type="brewcode:agent-creator") — ONE agent file per spawn, never a whole team. Prompt carries GOAL (build this one {TEAM_NAME} roster member; siblings own other domains), ROLE (owns .claude/agents/{name}.md only), SCOPE (that file; other agents, team.md, project source out), CONTEXT (settled mission/domain/project analysis, selected model, 3-4 sibling names; no trigger/domain overlap; the gated shared contract already exists), CONSUMER (C4 adds the final roster row; C5 reviews; the roster routes work), DONE:

    • description <=100 chars (optimal ~80), single-line role + 2-3 triggers, no <example>;
    • body <=3200 bytes and <=800 exact tiktoken==0.13.0 o200k_base tokens, with exactly these ordered headings and no others: ## Mission, ## Owned surfaces, ## Exclusions, ## Must-load references, ## Unique invariants, ## Unique verification;
    • ## Must-load references names .claude/teams/{TEAM_NAME}/team.md first;
    • profile contains only domain-unique facts. Task Acceptance Protocol, Return Contract, Trace Instructions, Colleagues, Scope Fit, shared routing, and shared output rules stay only in team.md;
    • placeholders substituted; return file path + description line.

    Every spawn prompt MUST also carry the template path and the four metadata lines, resolved — the subagent cannot see Phase 1's output, so replace {PLUGIN_VERSION} and {LAST_UPDATED} below with the literal values from the Phase 1 PLUGIN_VERSION: / LAST_UPDATED: lines before you send the prompt. A token that reaches the subagent ships verbatim into the agent file, and setup-status then reports that agent partial forever. Those two spellings are the only sanctioned ones — never an angle form, never a double brace:

    CONTEXT (cont.): structure from ${CLAUDE_SKILL_DIR}/references/agent-template.md — read it first.
    DONE (cont.): the frontmatter ends with exactly these four keys, in this order, AFTER the agent's
      own keys (name, description, model, tools — leave those byte-untouched, `tools` above all):
        doc_type: llm
        version: "{PLUGIN_VERSION}"
        generated_by: "brewcode:teams-setup"
        last_updated: "{LAST_UPDATED}"
    

    verify-team.sh re-reads every generated agent's frontmatter and FAILS on a wrong order, a missing key or wrong quoting, so a prompt that shipped a token does not pass C4.

  3. Batch 3-4 agents in parallel per message

  4. After each batch, optimize without changing the six-heading contract:

    Task(subagent_type="brewtools:text-optimizer", prompt="Light-optimize .claude/agents/{agent-name}.md; preserve its exact six ordered headings, team.md reference, names/numbers/negations/scope. Output metrics.")
    

    brewtools not installed (text-optimizer unavailable) — skip the pass, agents stay as written. Never run the optimizer on .claude/agents/intent-guard.md. Its frontmatter description is deliberately short and review-only; an optimizer pass may reword, lengthen or reflow it into a normal domain-agent description, which would make it compete for auto-activation. Excluded.

C3-IG: intent-guard (required policy, exactly once)

.claude/agents/intent-guard.md has exactly ONE writer: generate.sh emit-agent, shared with /brewcode:superreview-setup. Never author this file from the template yourself, and never spawn an agent to author it — that would fork the file into two divergent pipelines. agent-creator appears in this phase only as a post-processor that replaces three seeded BLOCKs.

Step 1 — emit. Run from the project root, exporting the C1 facts. Unharvested fact -> none / not present in this project; never invent a tracker, a path or a ticket id.

EXECUTE using Bash tool (substitute the C1 values first):

PROJECT_NAME="PROJECT_NAME_HERE" \
TRACKER_LABEL="TRACKER_LABEL_HERE" \
SPEC_LOCATION="SPEC_LOCATION_HERE" \
PLAN_LOCATION="PLAN_LOCATION_HERE" \
POLICY_LOCATION="POLICY_LOCATION_HERE" \
bash "${CLAUDE_SKILL_DIR}/../superreview-setup/scripts/generate.sh" emit-agent && echo "OK" || echo "FAILED"

It creates-or-reuses ONLY .claude/agents/intent-guard.md (superreview does not need to have run) and prints exactly one INTENT_GUARD: line on STDOUT: INTENT_GUARD: CREATED <path>, INTENT_GUARD: REUSE <path> or INTENT_GUARD: MIGRATED <path> (a pre-standard file of ours, restamped in place — metadata only, tailored body preserved). Diagnostics (e.g. "recreating from template") go to stderr and never add a second status line.

STOP if FAILED -- report the script output; do not fall back to hand-authoring the file.

Step 2 — sanity-check the emitted file (a pre-existing file may be empty, truncated or placeholder-laden; -f alone proves nothing). This runs on the REUSE path too, where $f is somebody's already-adapted agent whose evidence block legitimately holds shell expansions — so strip ${VAR} FIRST and match bare tokens on what is left. Without the strip a ${BASE} scores as an unresolved placeholder, and this step's remedy is rm -f: it would delete a tailored file.

f=.claude/agents/intent-guard.md
[ -s "$f" ] && grep -q '^name: intent-guard' "$f" \
  && ! sed 's/\${[A-Z_][A-Z_]*}//g' "$f" | grep -q '{[A-Z_]\{2,\}}' && echo "SANE" || echo "CORRUPT"
grep -qF '<!-- generated_by: brewcode:superreview-setup' "$f" 2>/dev/null && echo "OURS" || echo "FOREIGN"
  • CORRUPT + OURS -> the file came out of this pipeline, so rm -f .claude/agents/intent-guard.md, re-run Step 1 once (a fresh emit is now a CREATED), re-check. Still CORRUPT -> STOP and report; do not patch it by hand.
  • CORRUPT + FOREIGN -> STOP. Never rm it. An unstamped file is the project's own agent and its {TOKENS} may be its own convention; deleting it is the data loss this check exists to prevent (emit-agent already REUSED it byte-untouched and printed the tokens as a conflict on stderr). Report the path and the tokens and let the user decide.

Step 3 — adapt the seeded BLOCKs. Only on INTENT_GUARD: CREATED. On REUSE or MIGRATED skip this step entirely: the existing file is already project-adapted and must not be rewritten or "refreshed".

emit-agent seeds three BLOCKs with GENERIC marked defaults. Spawn ONE Task(subagent_type="brewcode:agent-creator"), alone (not batched with the domain agents), to replace them with project-specific content:

Task(subagent_type="brewcode:agent-creator", prompt="
  GOAL: team '{TEAM_NAME}' has its fixed review-only member intent-guard — the anti-drift check that
        compares what was ASKED against what was DELIVERED. The file is ALREADY WRITTEN by
        superreview-setup/scripts/generate.sh emit-agent with generic placeholder content in three BLOCKs.
        Your only job is to tailor those three BLOCKs to this project.
  ROLE: you own exactly three marked BLOCKs inside .claude/agents/intent-guard.md:
        PROJECT_INVARIANTS_TABLE, DRIFT_EXAMPLES_TABLE, EVIDENCE_COMMANDS_BASH.
        You do NOT author this agent and you do NOT re-instantiate it from any template.
  SCOPE: Edit only the content of those three BLOCKs, in place.
        EACH REPLACEMENT MUST CONSUME ITS MARKER. Every seeded BLOCK ends in its own
          `<!-- SEEDED-DEFAULT: ... -->` line. Key each Edit on that marker: `old_string` = the
          seeded block PLUS its marker line, `new_string` = your project-specific replacement
          WITHOUT any marker. A surviving marker is what makes a skipped adaptation detectable —
          `generate.sh validate` reports any file that still carries one as UNTAILORED.
        HARD out of bounds — a single byte changed here is a failed task:
          - the frontmatter (name, description, model: sonnet, tools, color, maxTurns). The
            description is <= 100 chars, review-only, explicitly-invoked BY DESIGN; do NOT rewrite,
            lengthen or 'improve' it. This overrides any default description-authoring habit.
          - the file header, every heading, and every other section of the file
          - the shared template, other agent files, team.md, trace.jsonl, project source
  CONTEXT: C1 project analysis is settled — use these facts, invent nothing:
        PROJECT_INVARIANTS_TABLE = from C1: planned scale/user count, testing policy, dependency
                            policy, file-layout policy, architecture stance
        DRIFT_EXAMPLES_TABLE     = 3-6 drift instances in THIS repo's vocabulary
        EVIDENCE_COMMANDS_BASH   = cheap evidence commands for THIS stack (diffstat, manifest diff,
                            test-file count, new-file list)
        Unknown fact -> write 'none' / 'not present in this project'. Never fabricate a tracker,
        a path or a ticket id. Do not add a Scope Fit block, Task Acceptance Protocol, trace
        instructions or a Domain Instructions section — this agent has no code domain.
  CONSUMER: /brewcode:superreview-setup spawns this same file by name during review, and C4 adds its row to
        .claude/teams/{TEAM_NAME}/team.md — the file name and agent name stay exactly 'intent-guard'.
  DONE: three BLOCKs project-specific, all three SEEDED-DEFAULT markers gone (consumed by the
        replacements), everything else byte-identical to what emit-agent wrote.
        Report: path + the three BLOCK contents + confirmation that frontmatter and header are untouched.
")

Step 4 — verify. FOUR counts, one grep per line, in this order. Each pattern matches the ARTIFACT, never prose ABOUT it: the emitted agent legitimately keeps a tail comment that NAMES the stripped TEMPLATE HEADER, so an unanchored grep -c 'TEMPLATE HEADER' reports 1 on every healthy file and turns this gate into an unpassable loop. Match the header's opening line, not the phrase. Same reason the placeholder count strips ${VAR} first: {PROJECT_NAME} is a token, ${CLAUDE_PLUGIN_ROOT} in an adapted evidence command is not, and only a strip-then-match tells them apart — a $-guard inside the pattern mis-handles adjacent tokens. || true on every line: zero matches is the happy path for three of the four counts (repo rule avoid#7), and a count must still PRINT under set -o pipefail, especially when it is the one going red.

f=.claude/agents/intent-guard.md
sed 's/\${[A-Z_][A-Z_]*}//g' "$f" | grep -c '{[A-Z_]\{2,\}}' || true   # 0 — unresolved placeholder
grep -c '^<!-- TEMPLATE HEADER' "$f" || true    # 0 — header comment not stripped by emit
grep -c '^name: intent-guard' "$f" || true      # 1 — frontmatter name key intact
grep -cF '<!-- SEEDED-DEFAULT:' "$f" || true    # 0 — every seeded BLOCK marker consumed

Must print 0, 0, 1, 0. A non-zero last count means an adaptation left its marker (or skipped the block) and generate.sh validate will report the agent UNTAILORED.

STOP if not -- re-spawn Step 3 once with the offending lines named.

Report intent-guard: created (adapted) or intent-guard: reused (already present) and continue to C4. Either way a required team gets its team.md row. This phase is skipped for an existing legacy-absent team; never emit or adapt the agent merely to upgrade that team.

C4: Roster Finalization + Verification

  1. Re-check the C2.6 bootstrap before editing the roster. Missing/malformed shared contract, unsafe or unresolved report root, or wrong policy-conditional intent-guard sentence -> STOP; never finalize discoverable agents against an absent authority.

  2. Finalize team.md from ${CLAUDE_SKILL_DIR}/references/framework-files.md: preserve the bootstrapped Shared Agent Contract byte-faithful, add one compact domain row per successfully created agent, and apply the explicit intent policy (required retains the fixed row; legacy-absent has no row). Then touch trace.jsonl. No confirmed-but-unwritten agent enters the roster.

    Then install the project-local tracer the generated agents call. A .claude/agents/*.md file is not plugin-owned, so ${CLAUDE_PLUGIN_ROOT} is NOT substituted inside it and no *_PLUGIN_ROOT env var exists — the only path an agent can rely on is a repo-relative one:

    cp "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" ".claude/teams/TEAM_NAME_HERE/trace-ops.sh" && \
    chmod +x ".claude/teams/TEAM_NAME_HERE/trace-ops.sh" && echo "OK" || echo "FAILED"
    

    STOP if FAILED — without it every agent's trace call is a no-op, STATUS reports 0 tasks and UPGRADE misclassifies the whole roster as Inactive. Re-copy it in UPGRADE too (cp is idempotent) so a team created by an older version gains it.

    team.md MUST carry |Intent guard|required| plus an intent-guard row (trailing Kind column = review-only, trailing Version column = PLUGIN_VERSION:), whether C3-IG created or reused it. Under legacy-absent, it MUST carry |Intent guard|legacy-absent| and no such row. Agents | {N} counts DOMAIN agents only.

    The header table MUST carry these four rows, adjacent and in exactly this order, filled from the Phase 1 PLUGIN_VERSION: / CONTENT_VERSION: / GENERATED_BY: / LAST_UPDATED: lines:

    | Version | {PLUGIN_VERSION} |
    | Content version | {CONTENT_VERSION} |
    | Generated by | brewcode:teams-setup |
    | Last update | {LAST_UPDATED} |
    

    No placeholder token may survive into the written file — a literal {PLUGIN_VERSION} in team.md means substitution never happened.

    Add |Agent defaults|active;{LAST_UPDATED};domain;{PLUGIN_VERSION}|. A domain row using all four defaults keeps the seven-column shape but leaves those cells empty: |name|domain|mission|||||. Write all four cells only for an override; the fixed review-only intent-guard row stays explicit.

    Keep roster Domain/Mission cells terse; agent profiles own detail. For up to 13 domain agents, the complete written team.md (metadata + shared contract + every row) MUST be <=2800 characters and <=700 exact tiktoken==0.13.0 o200k_base tokens. verify-team.sh fails closed when the approved durable runtime or hash-verified cache is absent/mismatched; only Universal Prelude step 6 prepares it. Measure the full substituted file, not the empty template; if over, compress only roster wording without dropping members, columns, policy, or contract facts.

  3. Verify:

    bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
    

    STOP if FAIL -- fix missing files before continuing.

  4. AskUserQuestion: final report + suggest /brewcode:teams-setup status {TEAM_NAME}

C5: Quorum Review

Spawn 3 reviewer agents in ONE message via Task tool. REVIEWER (here and in C7/C9) = the project's reviewer agent from .claude/agents/, else general-purpose.

intent-guard is never the REVIEWER. It is not a general reviewer: it only compares asked-vs-delivered on a real delivery, and it has no code domain. Never select it for the C5/C7/C9 pipeline role, and never as an implementation owner in C8 or U4.

#Focus
1Profile contract: body only (frontmatter excluded) <=3200 bytes / <=800 exact tiktoken==0.13.0 o200k_base tokens; exactly six ordered body headings (Mission, Owned surfaces, Exclusions, Must-load references, Unique invariants, Unique verification); .claude/teams/{TEAM_NAME}/team.md loaded first; no repeated shared-contract heading/rule
2Domain accuracy: correct scope, tool selection, model fit, description triggers
3Architecture: no domain overlaps; owned surfaces/exclusions/routing agree with the roster; acceptance/tracing/returns/colleagues/scope-fit exist once in team.md

.claude/agents/intent-guard.md is reviewed under DIFFERENT criteria — it is an instantiated shared template, not an authored domain agent. Judge only: placeholders all resolved, template header stripped, frontmatter identical to the template (short review-only description, model: sonnet, read-only tools), project facts accurate and not invented. Do NOT judge it on the six-heading domain profile, domain fit/scope, description triggers, acceptance, scope-fit, shared return or tracing — it has none by design, and "add the missing sections" is a FALSE POSITIVE here. Never propose lengthening its description.

Each reads ALL agent files in .claude/agents/ and outputs:

FILE: .claude/agents/{name}.md
SEVERITY: critical/important/minor
ISSUE: description
FIX: suggested fix

C6: Consensus Filter

Quorum threshold: 2/3 agreement = confirmed. Match criteria: same file + same area (+/- 5 lines or same section) + same category (instruction/domain/architecture/trigger).

OutcomeAction
2/3+ confirmMark confirmed, keep severity from highest reporter
1/3 onlyLog as unconfirmed, skip
Minor severity (all reporters)Log but skip fix

C7: Verification

Task(subagent_type=REVIEWER, prompt="
  Verify these findings against actual agent files. For each:
  1. Read the agent file
  2. Check if the issue actually exists
  3. Mark: VERIFIED or FALSE_POSITIVE
  {confirmed_findings}
")

Filter out false positives. Final list = verified critical + important issues.

C8: Fix

For each verified critical/important issue:

Task(subagent_type="brewcode:agent-creator", prompt="
  GOAL: team '{TEAM_NAME}' was just generated and quorum-reviewed; this task clears ONE
        confirmed defect so the roster ships clean.
  ROLE: you own {agent_file} only. Do NOT touch other agent files, team.md, trace.jsonl,
        CLAUDE.md, or project source.
  SCOPE: {agent_file}. Out of bounds: everything else.
  CONTEXT: C3 already wrote the whole roster and C5-C7 quorum-reviewed it; this finding is
    verified (2/3 reviewers + C7 double-check) — do NOT re-litigate it. Up to 3 sibling
    agent-creators fix other agent files in this same batch; team.md already lists the final
    roster, so do not rename the agent or change its domain.
    Read `${CLAUDE_SKILL_DIR}/references/agent-template.md` first; it is the canonical domain-profile
    shape. For a domain agent, preserve exactly its six ordered body headings and shared-team reference.
    ISSUE: {description}
    FIX: {suggested_fix}
    SEVERITY: {severity}
  CONSUMER: C9 re-verifies your file for "issue resolved + no regression", and the team
    manifest .claude/teams/{TEAM_NAME}/team.md must stay accurate — keep name, domain and
    description shape intact so its roster row still matches.
  DONE: fix applied and validated. Domain-agent body (frontmatter excluded) <=3200 bytes, exactly the
    canonical six ordered headings, team.md loaded first, no shared contract duplicated. Report:
    file | what changed | validation result.
")

Batch: up to 3 parallel per message. Minor issues skipped.

If {agent_file} is .claude/agents/intent-guard.md, add to the ROLE: frontmatter is frozen — the description stays short and review-only, tools stay read-only, model: sonnet stays. Only placeholder content (project facts, invariants, drift examples, evidence commands) may be fixed.

C9: Re-verify

Task(subagent_type=REVIEWER, prompt="
  Re-verify these fixes. For each:
  1. Read the fixed agent file
  2. Check original issue is resolved
  3. Check no regression introduced
  4. For every domain agent, hard-gate exactly one single-line description <=100 characters and the
     body only (frontmatter excluded): <=3200 bytes; exactly
     `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`,
     `Unique verification` in order with no other headings; team.md first; no shared rule duplicated.
     `intent-guard` is exempt from this six-heading gate and keeps its frozen review-only contract.
  Mark: FIXED or REGRESSION
  {fixes_applied}
")
OutcomeAction
All FIXEDPipeline complete, proceed to Epilogue
REGRESSION foundReturn to C8 for that file (max 2 cycles)
Still failing after 2 cyclesLog as unresolved, proceed to Epilogue

To skip review pipeline: add --skip-review to install arguments. To run review on existing team: /brewcode:teams-setup upgrade {TEAM_NAME} --review


Mode: STATUS (read-only)

No modifications. Read + report only.

  1. Read .claude/teams/{TEAM_NAME}/team.md
  2. Read trace data:
    bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" read ".claude/teams/{TEAM_NAME}" && echo "OK" || echo "FAILED"
    
    Parse JSONL: group by src (agent) and k (kind). Compute per-agent stats from k=track (took/refused/completed/failed counts), issues from k=issue, insights from k=insight.

Output:

# Team Status: {TEAM_NAME}

## Summary
| Metric | Value |
|--------|-------|
| Agents | {N} |
| Tasks tracked | {N} |
| Success rate | {%} |
| Open issues | {N} (high: {N}, critical: {N}) |
| Insights | {N} |
| Last activity | {date} |

## Per Agent
| Agent | Tasks | Success | Refused | Issues | Insights | Health |
|-------|-------|---------|---------|--------|----------|--------|

## Recommendations

Health:

LabelCriteria
Healthy>70% success, active
Needs tuning30-70% success or many refusals
Underperforming/Inactive<30% success or inactive

Recommendations: underperformers -> suggest /brewcode:teams-setup upgrade; >200 trace rows -> suggest uninstall; 0 activity -> suggest review.

No AskUserQuestion -- purely informational.


Mode: UPGRADE (self-reflection)

U1: Load & Parse

UPGRADE_CUTOFF=$(date -u +%Y-%m-%dT%H:%M:%SZ)
CURSOR=$(bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" cursor ".claude/teams/{TEAM_NAME}")
bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" read ".claude/teams/{TEAM_NAME}" --since "$CURSOR" && echo "OK" || echo "FAILED"

If cursor empty: all entries returned. If team not found -> STOP. If cursor exists and <10 post-cursor entries: expand to last 30 days. Capture UPGRADE_CUTOFF before the initial cursor/trace read and keep it unchanged throughout U1-U4. Entries created after that cutoff may be analyzed twice, but must never be skipped by advancing the cursor past them.

Refuse to upgrade a PARKED member. Every write in U4 targets .claude/agents/{name}.md; writing that path while the member sits at {name}.md.disabled creates a live+parked dual copy — the state toggle-team.sh now REFUSES in BOTH directions (CONFLICT:) and verify-team.sh FAILS on. Probe every roster member before U2, from the project root:

for m in {AGENT_NAMES}; do
  [ -f ".claude/agents/$m.md" ] || { [ -f ".claude/agents/$m.md.disabled" ] && echo "PARKED $m"; }
done; echo "OK"
  • any PARKED row -> STOP the whole mode. Do not tune, do not regenerate, do not delete, do not touch team.md. Report the parked members and the single remedy: /brewcode:teams-setup {TEAM_NAME} enable, then re-run upgrade. Never "upgrade the live ones only" — a half-upgraded roster is what the guards exist to prevent.
  • all members live -> continue.

U1b: Shared Contract Migration Gate

Before U2 analysis or any U4 agent write, read ${CLAUDE_SKILL_DIR}/references/framework-files.md and upgrade team.md to the current shared contract. For a legacy file with no ## Shared Agent Contract, insert the canonical block before ## Agents, substituting {TEAM_NAME}, the current validated REPORT_ROOT, and policy-conditional guard wording while preserving Created, roster rows, statuses, and history. Re-resolve REPORT_ROOT from current applicable project guidance; do not preserve a stale plugin-default report path. Resolve and write the explicit Intent guard field first: an existing intent-guard roster row -> required; no row -> legacy-absent. Substitute the exact review-only guard sentence only for required; for legacy-absent substitute an empty string so the shared contract never names a phantom role. Never synthesize the row on the latter path. If a shared block exists but is incomplete, replace that block from the canonical reference before proceeding. Re-copy trace-ops.sh, then run verify-team.sh.

Legacy agent bodies remain byte-identical during this gate. No agent may be tuned, regenerated, stripped, deleted, or spawned until the shared contract passes. A legacy-profile warning is safe; a shared-contract failure stops the whole upgrade. Thus U4 can relocate repeated rules only after their destination exists.

U2: Analyze Performance

Filter post-cursor trace: k=track for task stats, k=issue for problems, k=insight for patterns.

StatusCriteriaAction
Healthy>70% success, activeNo changes
Needs tuning30-70% success or many refusalsUpdate instructions
Underperforming<30% successAskUser: update or delete+create new
Inactive0 recordsAskUser: delete or keep

Under required, intent-guard is EXCLUDED from this table. It does not trace and is invoked only during review, so 0 records is normal and never grounds for deletion or tuning. Under legacy-absent, there is no member to analyze. UNINSTALL enforces the same exclusion in references/cleanup-flow.md Step 3.

U3: Present & Confirm

ASK using AskUserQuestion with analysis table and proposed actions (Update/Delete/No changes per agent). Options: "Apply all" | "Let me choose" | "Show detailed analysis"

If "Let me choose" -> AskUserQuestion per agent. If "Show detailed" -> output full stats, then re-ask.

U4: Apply Changes

Agent StatusAction
Needs tuningTask(subagent_type="brewcode:agent-creator") update mode with tracking/issues/insights data
Underperforming (update)Same as tuning
Underperforming (replace)Delete agent file + create new via agent-creator
Inactive (delete)Remove .claude/agents/{name}.md + update team.md status to removed

Both delete rows run the ownership check first — cleanup-flow.md Step 3 step 0c, same script, same exit-code table: bash "${CLAUDE_SKILL_DIR}/scripts/agent-owners.sh" "{name}". More than one owner line, or exit 1 (owners unknown) -> SKIP the delete, keep the file, report it as shared/unknown and leave the roster row alone. intent-guard is never a candidate here at all (U2 note).

Immutable traits (Name, Base Role) -> delete + create new. Mutable traits (Character, Instructions) -> update during tuning.

Update team.md with current state: the header Version / Content version / Generated by / Last update rows (that order) from the Phase 1 PLUGIN_VERSION: / CONTENT_VERSION: / GENERATED_BY: / LAST_UPDATED: lines, and — for each agent row you actually touched — its Updated and Version cells. Rows left alone keep the version they were generated under. A pre-5.0 team.md has neither the Version / Generated by header rows nor the trailing Version column: ADD them here (append the column at the END of the roster table, never before Agent), do not treat their absence as an error.

Each agent file you regenerate or tune gets its version / last_updated frontmatter keys refreshed to the same values; generated_by stays brewcode:teams-setup. intent-guard.md is byte-untouchable.

Every domain agent touched here migrates to the current compact template: body only (frontmatter excluded) <=3200 bytes / <=800 exact tiktoken==0.13.0 o200k_base tokens, exactly the six ordered headings, .claude/teams/{TEAM_NAME}/team.md first under Must-load references, and no repeated acceptance/tracing/routing/return/colleague/scope-fit contract. Preserve every unique fact while relocating shared rules to team.md. Untouched legacy agents keep their bodies; verifier warnings identify the next migration set. intent-guard.md remains byte-untouchable.

Set cursor:

bash "${CLAUDE_SKILL_DIR}/scripts/trace-ops.sh" cursor ".claude/teams/{TEAM_NAME}" set "$UPGRADE_CUTOFF" && echo "✅" || echo "❌ FAILED"

Mode: ENABLE

Un-parks a team that was previously disabled. Nothing is generated, nothing is analyzed — this is a rename, and it is the exact inverse of DISABLE.

  1. Team not found -> report and STOP. Never "enable" a team that was never installed.
  2. Show what will move (no writes):
    bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" enable --dry-run && echo "OK" || echo "FAILED"
    
  3. Every member already live (NOOP: on all rows) -> say "team already enabled" and STOP. Do not ask, do not rename.
  4. Apply:
    bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" enable && echo "OK" || echo "FAILED"
    
  5. Edit team.md: set each restored member's Status cell back to active, and refresh all FOUR header rows — Version / Content version / Generated by / Last update, that order — from PLUGIN_VERSION: / CONTENT_VERSION: / GENERATED_BY: / LAST_UPDATED:. The quartet always travels together: this mode rewrote team.md, so the header records the version of THAT write. Do NOT touch the per-agent Version cells — no agent body was rewritten, so no agent changed version.
  6. Re-verify and report:
    bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
    
    DISABLED_AGENTS:0 is the success signal. Tell the user the roster is visible to the NEXT session — agent discovery is read at session start, so a rename mid-session is not picked up until reload.

Mode: DISABLE

Takes the team out of the roster without deleting anything. Use it when a team should stop self-selecting work but its instructions, trace history and archive must survive intact — a paused team, not a removed one. uninstall/purge delete; disable does not.

  1. Team not found -> report and STOP.
  2. Show what will move (no writes):
    bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" disable --dry-run && echo "OK" || echo "FAILED"
    
  3. ASK using AskUserQuestion: "Disable team {TEAM_NAME}? {N} domain-agent files are parked as .md.disabled — nothing is deleted, enable restores them. A required intent-guard stays live; legacy-absent adds nothing." Options: "Yes, disable" | "Uninstall instead (deletes agents, keeps archive)" | "Cancel"
    • anything but "Yes, disable" -> switch to UNINSTALL or STOP
  4. Apply:
    bash "${CLAUDE_SKILL_DIR}/scripts/toggle-team.sh" "TEAM_NAME_HERE" disable && echo "OK" || echo "FAILED"
    
  5. Edit team.md: set each parked member's Status cell to disabled, refresh all FOUR header rows (Version / Content version / Generated by / Last update, that order) from the Phase 1 lines — the quartet travels together on every mode that writes the file — and leave the per-agent Version cells alone. The roster rows themselves are never removed — a disabled team still has a full roster, which is what enable reads back.
  6. Re-verify and report: verify-team.sh prints DISABLED per parked member, DISABLED_AGENTS:{N} and still exits PASS — a parked member is a state, not a missing file. Say the agents disappear from the roster on the NEXT session.

Mode: UNINSTALL

Read ${CLAUDE_SKILL_DIR}/references/cleanup-flow.md and execute step by step:

  1. Overview scan -> show trace.jsonl entry counts by kind
  2. AskUserQuestion: what to clean (all / trace data / agents / step-by-step)
  3. Trace cleanup (if selected) -- AskUserQuestion with archive options
  4. Agents review (if selected) -- AskUserQuestion per agent if needed. intent-guard is never listed and never deleted (cleanup-flow.md Step 3); deleting it would break verify-team.sh for the team
  5. Summary report

Archive: entries appended to .claude/teams/{TEAM_NAME}/trace-archive.jsonl. Cursor reset after cleanup.


Mode: PURGE

UNINSTALL's total variant: no selective menus, no archive kept. Removes the team's entire footprint — the agents, the framework dir, the trace and its archive.

Read ${CLAUDE_SKILL_DIR}/references/cleanup-flow.md "Step P: Purge" and execute it.

  1. Show exactly what will be deleted (agent list from team.md, dir contents, byte sizes)
  2. ASK using AskUserQuestion: "Purge team {TEAM_NAME}? This deletes {N} agent files and .claude/teams/{TEAM_NAME}/ including trace-archive.jsonl. Not recoverable." Options: "Yes, purge" | "Uninstall instead (interactive, keeps archive)" | "Cancel"
    • anything but "Yes, purge" -> switch to UNINSTALL or STOP
  3. Execute the purge block in cleanup-flow.md Step P
  4. Summary report

intent-guard is NEVER deleted, by purge either — it is shared with /brewcode:superreview-setup and may belong to a superreview install that has nothing to do with this team.

Team not found -> report and STOP; do not "purge" a team that was never installed.


Universal Epilogue (every mode)

Step E1: Update CLAUDE.md (conditional)

Only for modes that change what the roster actually offers (INSTALL, UPGRADE with removals, ENABLE, DISABLE — which flips the Status: line to disabled and leaves the table in place, UNINSTALL with agent removal, PURGE — which removes the ## Teams section entirely):

ASK using AskUserQuestion: "Update team info in CLAUDE.md?" Options: "Yes, in project CLAUDE.md" | "Yes, in .claude/CLAUDE.local.md" | "No, skip"

Format to write:

## Teams

Team: {TEAM_NAME} | Domain agents: {N} | Intent guard: {required (review-only) | legacy-absent} | Status: active

| Agent | Domain | Mission |
|-------|--------|---------|

When required, `intent-guard` is a review-only anti-drift check (asked vs delivered), shared with
`/brewcode:superreview-setup`, invoked explicitly by name during review, and never an implementation
owner. Under `legacy-absent`, do not add this paragraph or the role.

Protocol: agents self-select tasks, trace in `.claude/teams/{TEAM_NAME}/trace.jsonl`.
Manage: `/brewcode:teams-setup [status|install|upgrade|enable|disable|uninstall|purge] [name]`

Step E2: Final Status

Always run STATUS mode logic after all changes: read team.md + trace.jsonl, compute stats, output Team Status table. Exception: after PURGE there is no team left — output the purge summary instead.


Output Format

# teams [{MODE}]

## Detection
| Field | Value |
|-------|-------|
| Arguments | `{raw args}` |
| Mode | `{MODE}` |
| Team | `{TEAM_NAME}` |
| Prompt | `{PROMPT or none}` |

## Results
{Mode-specific output}

## Next Steps
- {recommendations}

Error Handling

ConditionAction
detect-mode.sh prints ERROR:Report the line verbatim. STOP — never fall back to INSTALL
Prose argument, first word not a canonical mode (e.g. "create a new team for billing", "убери команду платежей")detect-mode.sh takes the literal first word as TEAM_NAME — do not trust that here. Apply ## Prompt contract step 5: score the mode table against the full prompt, extract the team name from the noun phrase (not the first word), then re-invoke detect-mode.sh with a normalized "<mode> <name> [rest]" (or set MODE/TEAM_NAME directly) before continuing Phase 1
PLAN block missing, or printed after Step 0.3 (verify-team.sh) / after any mutation startedDefect — STOP. A PLAN printed late does not count; return to Step 0.4, print it, then resume
Team not found (STATUS/UPGRADE/ENABLE/DISABLE/UNINSTALL/PURGE)"Team '{TEAM_NAME}' not found. Run /brewcode:teams-setup install {TEAM_NAME}." STOP
ENABLE on a live team / DISABLE on a parked teamtoggle-team.sh prints NOOP: for every row. Report "already {enabled|disabled}" and STOP — do not rename, do not ask
toggle-team.sh prints MISSING:A roster member has neither .md nor .md.disabled. STOP with the name — the team is broken, not disabled; run upgrade or re-create that agent
toggle-team.sh prints SKIP:invalid agent id / INVALID:{N>0} (or verify-team.sh FAILs the same row)A roster value is not ^[a-z0-9][a-z0-9-]*$ — it is a path, and it would have been moved or deleted OUTSIDE .claude/agents/. The script touched nothing for that row and exits 1. STOP: show the row and have team.md's ## Agents table fixed by hand
toggle-team.sh prints CONFLICT:{agent} / CONFLICT:{N>0} (or verify-team.sh reports CONFLICT and FAILs)That member has BOTH .claude/agents/{a}.md and {a}.md.disabled. BOTH directions refuse identically — enable would overwrite the live file, disable the parked one — all-or-nothing before any mv, so nothing moved and both bodies are byte-intact. CONFLICT:{N} is printed on EVERY toggle run, either action; {N>0} exits 1. STOP: name every conflicting member, have the user keep one copy and delete/rename the other, then re-run the SAME action. Never delete either copy yourself, never --force around it
verify-team.sh prints DISABLED_AGENTS:{N>0}Expected on a disabled team, and it still exits PASS. Never report it as a failure and never "repair" it by regenerating the agents — enable is the fix
Team already exists (INSTALL)Show roster, AskUserQuestion: "Upgrade instead?"
verify-team.sh FAILShow missing items, attempt fix, re-verify
No agents created (C3 failure)Retry failed agents once, then report
0 trace entries (UPGRADE)Classify all agents as Inactive
</instructions>
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

NOASSERTION

Source path

brewcode/skills/teams-setup

Default branch

main

Latest commit

7f5b5d8

Tree SHA

5bfd4fc