fix: enforce compact team contracts

This commit is contained in:
kochetkov-ma
2026-08-27 16:44:44 +02:00
parent 243cf65e21
commit 8024faf97a
33 changed files with 2507 additions and 2818 deletions
@@ -0,0 +1,3 @@
name = "intent-guard"
description = "Review-only anti-drift check comparing requested and delivered scope."
developer_instructions = "Review only. Compare what was requested with what was delivered, report concrete drift with file:line evidence, and never implement or mutate project files."
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -euo pipefail
root="${1:-}"
test -n "$root" || { echo "usage: emit-intent-guard.sh <project-root>" >&2; exit 2; }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
template="$SCRIPT_DIR/../references/intent-guard.toml.template"
agents="$root/.codex/agents"
target="$agents/intent-guard.toml"
validate() {
python3 - "$1" <<'PY'
import pathlib, sys, tomllib
path = pathlib.Path(sys.argv[1])
try:
data = tomllib.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, tomllib.TOMLDecodeError) as exc:
print(f"invalid TOML: {exc}", file=sys.stderr)
raise SystemExit(1)
required = {"name", "description", "developer_instructions"}
if set(data) != required:
print("TOML keys must be exactly name, description, developer_instructions", file=sys.stderr)
raise SystemExit(1)
if any(type(data[key]) is not str for key in required) or data["name"] != "intent-guard":
print("intent-guard native fields must be strings and name must be fixed", file=sys.stderr)
raise SystemExit(1)
PY
}
validate "$template"
if [ -f "$target" ]; then
validate "$target"
echo "INTENT_GUARD: REUSE .codex/agents/intent-guard.toml"
exit 0
fi
mkdir -p "$agents"
tmp="$(mktemp "$agents/.intent-guard.XXXXXX")"
trap 'rm -f "$tmp"' EXIT HUP INT TERM
cp "$template" "$tmp"
validate "$tmp"
mv "$tmp" "$target"
trap - EXIT HUP INT TERM
echo "INTENT_GUARD: CREATED .codex/agents/intent-guard.toml"
@@ -1,6 +1,6 @@
# Teams
Create and manage dynamic teams of domain-specific agents with a tracking framework. Analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking. Every team also gets one fixed review-only member, `intent-guard`.
Create and manage dynamic teams of domain-specific agents with a tracking framework. The skill analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking. A new team also gets exactly one review-only `intent-guard`; an upgraded legacy team with none stays that way.
## Quick Start
@@ -28,7 +28,7 @@ The verb always comes first and the optional `<name>` after it. That parser guar
`disable` is a rename, not a deletion — the roster rows stay in `team.md` with `Status: disabled`, and `verify-team.sh` reports `DISABLED` per parked member and still exits PASS. `enable` puts it all back. Both take effect for the NEXT session: agent discovery is read at session start.
`purge` keeps exactly one thing: `.codex/agents/intent-guard.toml`, shared with `$brewcode:superreview-setup`. It removes both `<agent>.toml` and `<agent>.toml.disabled`, so purging a disabled team leaves nothing behind.
`purge` removes both `<agent>.toml` and `<agent>.toml.disabled`, so purging a disabled team leaves no owned domain profile behind. When `Intent guard` is `required`, it keeps `.codex/agents/intent-guard.toml` because that file is shared with `$brewcode:superreview-setup`; `legacy-absent` has no guard to keep.
## Examples
@@ -83,7 +83,7 @@ After `$brewcode:teams-setup install my-team`:
agents/
agent-one.md # Domain agents (5-20 depending on variant)
agent-two.md
intent-guard.toml # Fixed review-only member, every team, not counted
intent-guard.toml # One review-only member for policy `required`; not counted
teams/
my-team/
team.md # Roster: agent list, domains, missions, status
@@ -91,11 +91,20 @@ After `$brewcode:teams-setup install my-team`:
trace-ops.sh # Tracer, copied from the plugin at install -- agents call THIS path
```
`team.md` stores logical `intent_guard_policy=required|legacy-absent` in its `Intent guard` field.
`required` means the roster contains exactly one `intent-guard` row. `legacy-absent` means it contains
zero such rows; upgrade preserves that state and never creates the role. New installs default to
`required`.
Codex domain profiles are Markdown files under `.codex/agents/`. The Codex projection uses native
TOML files under `.codex/agents/`; it carries no YAML-in-TOML guidance.
## How Agents Work
Created agents follow the **sub-agent task Acceptance Protocol** -- they self-select tasks based on domain fit, record acceptance/refusal in `trace.jsonl`, and log issues and insights as they work.
Every generated domain agent is also born with a **Return Contract**: verdict first, <=30 lines, `path:line`, no file bodies, no command output, no logs, no preamble -- bulk material goes to `.codex/reports/` and only the path comes back. It holds whether or not `$brewtools:agent-return-setup` is installed; the guard only adds mechanical thresholds. `verify-team.sh` warns on an older agent that lacks the section, and `upgrade` re-adds it.
Created agents load `team.md`, whose single **Shared Agent Contract** owns acceptance, routing, tracing,
return, scope-fit and colleague rules. Domain profiles do not repeat those contracts. Their bodies have
exactly six ordered headings: `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique
invariants`, and `Unique verification`.
They write through the project-local copy of the tracer:
@@ -125,7 +134,7 @@ $brewcode:teams-setup install my-project
|
v
[C2] Team Proposal ------ 3 variants + user confirmation
(+ intent-guard, fixed, not counted)
(+ one intent-guard for new teams, not counted)
|
v
[C2.5] Model Selection -- high-reasoning model / balanced model / fast model / mixed (domain agents only)
@@ -134,7 +143,7 @@ $brewcode:teams-setup install my-project
[C3] Agent Creation ----- agent-creator x N (batches of 3-4)
|
v
[C3-IG] intent-guard ---- generate.sh emit-agent (create or reuse), then adapt if created
[C3-IG] intent-guard ---- required: emit/reuse; legacy-absent: do nothing
|
v
[C4] Framework Setup ---- team.md + trace.jsonl + trace-ops.sh + verification
@@ -171,22 +180,32 @@ After agent creation, a quality pipeline validates the team:
> Skip with `--skip-review`. Run separately: `$brewcode:teams-setup upgrade <name> --review`
> `intent-guard` is never used as a reviewer in this pipeline, and it is judged by different criteria than domain agents: placeholders resolved, template header stripped, frontmatter untouched (short review-only description, read-only tools). "Missing domain sections" is a false positive for it.
> When policy is `required`, `intent-guard` is not a reviewer in this pipeline and is judged by its own
> review-only contract. The six-heading domain-profile gate does not apply to it. Under `legacy-absent`,
> there is no guard to review.
## intent-guard (always in the team)
## intent-guard policy
Every team gets `intent-guard` in addition to its domain agents. It is an **anti-drift check**: it compares what was **ASKED** (the original request, ticket, spec, plan, project policy) against what was **DELIVERED**, and reports the delta.
`team.md` has exactly one `Intent guard` policy field:
| Policy | Roster contract | Upgrade behavior |
|--------|-----------------|------------------|
| `required` | Exactly one review-only `intent-guard` row, outside the domain-agent count | Preserve the row; never duplicate it |
| `legacy-absent` | Zero `intent-guard` rows | Preserve absence; never create the role |
New installs use `required`. The role is an **anti-drift check**: it compares what was **ASKED** (the
original request, ticket, spec, plan, project policy) against what was **DELIVERED**, and reports the delta.
| Property | Value |
|----------|-------|
| Counted in the 5 / 10-12 / 15-20 roster? | No -- it is outside the domain-agent count and cannot be dropped |
| Counted in the 5 / 10-12 / 15-20 roster? | No -- when required, it is outside the domain-agent count |
| Tools | Read-only (`Read`, `Glob`, `Grep`, `Bash`). Never edits, builds, or runs tests |
| Model | `balanced model`, fixed by its template -- not affected by the C2.5 model choice |
| Invocation | Explicit, by name, during review only -- never during development, never an implementation owner |
| Source | Emitted by `skills/superreview-setup/scripts/generate.sh emit-agent` from the shared template -- the single writer of this file, used by both skills |
| Output | Verdict `ALIGNED` / `MINOR DRIFT` / `MAJOR DRIFT` plus <=10 findings, each with ASKED / SOURCE+tier / DELIVERED evidence / severity / minimal correction |
**Single writer (idempotent):** `teams` never authors this file. It runs
**Single writer (idempotent, `required` only):** `teams` never authors this file. It runs
`superreview-setup/scripts/generate.sh emit-agent`, which creates it from the shared template or reuses an
existing one and prints `INTENT_GUARD: CREATED|REUSE|MIGRATED <path>`. On `REUSE` -- typically because
`$brewcode:superreview-setup` ran first -- the file is left exactly as is and only the `team.md` roster row is
@@ -196,14 +215,16 @@ invariants, drift examples, evidence commands) and touches nothing else -- front
as emitted. Both skills therefore converge on one shared file produced by one pipeline, never two
variants.
`intent-guard` is also excluded from `upgrade` and `uninstall` agent pruning (enforced in the cleanup flow
itself, Step 3, including a refusal if it is named explicitly): it does not write trace entries, so zero
activity is its normal state, not a reason to delete it. Teams created before `intent-guard` existed are
not broken by this -- `verify-team.sh` only WARNs, with the command to add it.
When policy is `required`, `intent-guard` is excluded from `upgrade` and `uninstall` pruning. It does not
write trace entries, so zero activity is normal. Teams created before the role existed can be upgraded
without it: the migration writes `legacy-absent`, retains zero rows, and does not emit a profile.
Project Dusk is the compatibility baseline for this path: its roster stays at 13 members;
`task-tracker` remains a non-member owner, and `Intent guard: legacy-absent` keeps `intent-guard` absent.
## sub-agent task Acceptance Protocol
Each agent follows a 3-step self-selection before accepting a task:
The shared contract in `team.md` gives every domain agent the same 3-step self-selection before accepting a task:
| # | Check | Question | If No |
|---|-------|----------|-------|
@@ -228,7 +249,9 @@ When other skills (convention, superreview, e2e) spawn agents, they check for te
> If a team agent refuses a task (sub-agent task Acceptance Protocol), the skill re-delegates to the next priority level. Max 2 retries before falling back to system agents.
> `intent-guard` is outside this resolution chain -- it is never selected as an implementation or review owner by domain fit. It runs only when a review flow invokes it explicitly by name.
> Under `required`, `intent-guard` is outside this resolution chain -- it is never selected as an
> implementation or review owner by domain fit and runs only when a review flow invokes it explicitly.
> Under `legacy-absent`, there is no role to resolve.
## Related Skills
@@ -7,916 +7,49 @@ description: "Creates and manages dynamic teams of domain agents. Triggers: crea
Use collaboration agents only when the user or project instructions explicitly request a team. Split work into bounded independent tasks, keep one owner per file or surface, exchange evidence through collaboration messages, and synthesize results in the parent session. Do not invent unsupported agent parameters or create persistent team configuration unless requested.
## Complete native workflow
Follow every phase below. When a phase delegates work, use Codex collaboration with only `task_name` and `message`; treat each "Codex delegation brief" block as role and message content, not executable syntax. Use `request_user_input` for the documented user gates. Resolve `<skill-directory>`, `<plugin-root>`, `<project-root>`, and `<arguments>` before running commands.
<!-- brewcode-meta: version=6.1.4 content_version=6.1.0 generated_by=brewcode:teams-setup -->
<instructions>
## Native authority
# Teams
Manage persistent project teams under `.codex/teams/{TEAM_NAME}/` and domain agents under `.codex/agents/`. Agent files are real TOML parsed with Python `tomllib`; never rename Markdown/YAML agents to `.toml`. Each team agent has exactly three top-level string keys: `name`, `description`, `developer_instructions`.
Manage dynamic teams of domain-specific agents with tracking framework.
Resolve one mode: `status`, `install`, `upgrade`, `enable`, `disable`, `uninstall`, or `purge`. Read applicable `AGENTS.md`, inspect existing teams and agents, preserve unrelated files, and use only scripts/references shipped beside this skill. Never edit installed caches.
**Arguments:** `<arguments>`
### C2.6: Shared Contract Bootstrap
---
Bootstrap happens before any team-owned `.codex/agents/{name}.toml` is written: instantiate the fenced template from `references/framework-files.md` and write `team.md` at `.codex/teams/{TEAM_NAME}/team.md` with metadata, `## Shared Agent Contract`, explicit `Intent guard` policy, and zero domain rows. Do not add domain-agent rows yet. Copy the project-local tracer, initialize trace storage, substitute every placeholder, then run `scripts/verify-team.sh`. **STOP on any failure. Do not spawn or write an agent.**
## Prompt contract
### C3: Agent Creation
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.
Create each approved domain `.codex/agents/{name}.toml` from `references/agent-template.md`. Parse it structurally with `tomllib` and require only `name`, `description`, and `developer_instructions`. The `developer_instructions` value uses exactly these ordered headings and no others: `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification`. Its first must-load item is exactly `.codex/teams/{TEAM_NAME}/team.md`, occurring once. Enforce <=3200 UTF-8 bytes and `ceil(chars/4) <=800` over `developer_instructions` itself.
| Mode | EN keywords | RU keywords | Mutates? |
|------|-------------|-------------|----------|
| `status` | *(empty)*, `status`, `show`, `list`, `check` | `статус`, `покажи`, `что`, `проверь` | no |
| `install` | `install`, `create`, `setup`, `new team`, `build` | `установи`, `создай`, `настрой`, `новая команда` | yes |
| `upgrade` | `upgrade`, `update`, `tune`, `improve`, `retune` | `обнови`, `улучши`, `настрой лучше` | yes |
| `enable` | `enable`, `on`, `turn on`, `activate`, `restore` | `включи`, `активируй`, `верни`, `восстанови` | yes |
| `disable` | `disable`, `off`, `turn off`, `pause`, `park` | `выключи`, `отключи`, `пауза`, `приостанови` | yes |
| `uninstall` | `uninstall`, `remove`, `delete`, `clean up`, `tear down` | `удали`, `убери`, `сними`, `очисти` | yes, destructive |
| `purge` | `purge`, `wipe`, `nuke`, `delete everything`, `remove all` | `снеси`, `удали всё`, `вычисти`, `полностью удали` | yes, destructive |
`intent-guard` is exempt from the six-heading domain profile. Under `required`, run `<plugin-root>/skills/superreview-setup/scripts/emit-intent-guard.sh <project-root>`; that sole shared writer create-only copies its native authority, structurally validates it, and never overwrites an existing file. Never ask agent-creator to write it. Under `legacy-absent`, create no row and no role.
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 -> `request_user_input`; 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 `request_user_input` (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.
### C4: Roster Finalization
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 .codex/teams/{name}/ and .codex/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 shell:
```bash
bash "<skill-directory>/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.
> `.codex/agents/intent-guard.toml` is the ONE exception: `generate.sh emit-agent` stamps it with
> `generated_by: brewcode:superreview-setup`, and teams never touches those keys.
`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.** Codex discovers a project agent only through
> `.codex/agents/<name>.toml`. `disable` renames each member to `<name>.toml.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. `intent-guard` is never parked — it is shared with
> `$brewcode:superreview-setup`, exactly as in UNINSTALL and PURGE.
---
## Universal Prelude (every mode)
### Step 0: Init + Validate + Confirm
1. Output: `Mode: {MODE}, Team: {TEAM_NAME}`
2. Load environment:
| Action | Command / Path |
|--------|----------------|
| Read agent template | `<skill-directory>/references/agent-template.md` |
| Read framework templates | `<skill-directory>/references/framework-files.md` |
| Check team dir | `.codex/teams/{TEAM_NAME}/` -- exists? |
| Check existing agents | `.codex/agents/` -- list all |
| If team.md exists | Read, show current roster |
| If trace.jsonl exists | Show entry counts via `trace-ops.sh read` |
3. If team exists, verify:
```bash
bash "<skill-directory>/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
4. 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 request_user_input.
5. Mutating modes only — **ASK** using request_user_input: "PLAN above. Continue?"
Options: "Yes, continue" | "No, I want changes" | "Cancel"
- "changes" -> request_user_input for details, revise the PLAN and reprint it
- "Cancel" -> **STOP**
---
## Delegation (applies to EVERY sub-agent 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:
| Field | Content |
|-------|---------|
| GOAL | the overall task and why it exists — the point beyond the file edit |
| ROLE | what this agent owns; what it must NOT touch |
| SCOPE | exact paths/commands in bounds + explicit out-of-bounds |
| CONTEXT | what is already done, by whom, what runs in parallel — trimmed to what THIS agent needs |
| CONSUMER | who or what uses the result next, and the shape it must fit |
| DONE | acceptance 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 sub-agent collaboration tools:
| # | Focus |
|---|-------|
| 1 | Code structure: modules, packages, domains, architectural layers |
| 2 | Existing agents (`.codex/agents/`, `brewcode/agents/`, `~/.codex/agents/`) + Codex infrastructure |
| 3 | Tech stack: build files, frameworks, dependencies, languages |
| 4 | CI/CD, testing, deploy, infrastructure |
| 5 (optional) | Domain boundaries: business logic, API, data layer, UI |
All via `Codex delegation brief (task_role="Explore")`. Consolidate into single analysis document.
**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:
| Fact | Fills | Where to look |
|------|-------|---------------|
| Project name | `{PROJECT_NAME}` | repo dir, root `AGENTS.md`, `package.json`/build file |
| Where original requirements live (tracker, issues, Slack, "chat only") | `{TRACKER_LABEL}` | `AGENTS.md`, `.github/`, issue templates, CI links |
| Spec / design-doc paths or globs | `{SPEC_LOCATION}` | `.codex/specs/**`, `docs/`, `adr/` |
| Plan / task-board / task-graph paths | `{PLAN_LOCATION}` | `.codex/features/**`, `TASKS.md`, board files |
| Policy paths: root + nested `AGENTS.md`, rules, conventions | `{POLICY_LOCATION}` | `AGENTS.md`, `.codex/rules/**` |
| Planned scale / user count, testing policy, dependency policy, file-layout policy, architecture stance | `{PROJECT_INVARIANTS_TABLE}` | `AGENTS.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 |
### C2: Team Proposal (interactive)
Based on analysis + PROMPT (if provided), propose 3 variants via request_user_input.
**`intent-guard` is in EVERY team, always, and is NOT one of the counted slots.** It is a review-only
anti-drift check (asked-vs-delivered), not a domain agent, so the 5 / 10-12 / 15-20 counts describe
DOMAIN agents only. Show it as a fixed row in every variant table, never as an option the user picks
and never as something the user can drop:
```
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 request_user_input for free input; intent-guard stays regardless of what the user
specifies. Final confirmation of agent list before proceeding.
> If `.codex/agents/intent-guard.toml` 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):
```bash
for a in {PROPOSED_NAMES}; do
o=$(bash "<skill-directory>/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 (request_user_input)
"Default model for domain agents: high-reasoning model (most reliable)."
| Model | Best for | Cost |
|-------|----------|------|
| high-reasoning model | Complex domains, architecture, critical logic | High |
| balanced model | Standard domains, CRUD, testing, utilities | Medium |
| fast model | Simple utility agents, formatting, validation | Low |
Options: "high-reasoning model (recommended)" | "balanced model" | "fast model" | "Mixed -- I'll choose per agent"
If "Mixed" -- ask model per agent in C3. Store as `DEFAULT_MODEL` (default: high-reasoning model).
> `DEFAULT_MODEL` applies to DOMAIN agents only. `intent-guard` keeps the `model: balanced model` 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 `.codex/agents/{name}.toml` 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 `.codex/teams/{TEAM_NAME}/`.
2. Read `<skill-directory>/references/framework-files.md`; write `team.md` with substituted metadata,
the byte-faithful `## Shared Agent Contract`, the `## Agents` header, and only the 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 `<skill-directory>/references/agent-template.md`
1a. Confirm C2.6 completed. `.codex/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 `.codex/agents/{name}.toml.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 `Codex delegation brief (task_role="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 `.codex/agents/{name}.toml` 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 (~800 est-tokens), with exactly these ordered headings and no others: `## Mission`, `## Owned surfaces`, `## Exclusions`, `## Must-load references`, `## Unique invariants`, `## Unique verification`;
- `## Must-load references` names `.codex/teams/{TEAM_NAME}/team.md` first;
- profile contains only domain-unique facts. `sub-agent 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 <skill-directory>/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:
```
Codex delegation brief (task_role="brewtools:text-optimizer", message="Light-optimize .codex/agents/{agent-name}.toml; 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 `.codex/agents/intent-guard.toml`.** 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 (always, exactly once)
`.codex/agents/intent-guard.toml` 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 shell (substitute the C1 values first):
```bash
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 "<skill-directory>/../superreview-setup/scripts/generate.sh" emit-agent && echo "OK" || echo "FAILED"
```
It creates-or-reuses ONLY `.codex/agents/intent-guard.toml` (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.
```bash
f=.codex/agents/intent-guard.toml
[ -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 .codex/agents/intent-guard.toml`,
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
`Codex delegation brief (task_role="brewcode:agent-creator")`, alone (not batched with the domain agents), to replace
them with project-specific content:
```
Codex delegation brief (task_role="brewcode:agent-creator", message="
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 .codex/agents/intent-guard.toml:
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: balanced model, 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, sub-agent 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
.codex/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, `<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.
```bash
f=.codex/agents/intent-guard.toml
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 the file gets its `team.md` row.
### C4: Roster Finalization + Verification
1. Re-check the C2.6 bootstrap before editing the roster. Missing/malformed shared contract -> **STOP**;
never finalize discoverable agents against an absent authority.
2. Finalize `team.md` from `<skill-directory>/references/framework-files.md`: preserve the bootstrapped
Shared Agent Contract byte-faithful, add one domain row per successfully created agent, and retain the
fixed `intent-guard` row. Then `touch trace.jsonl`. No confirmed-but-unwritten agent enters the roster.
Then install the **project-local tracer** the generated agents call. A `.codex/agents/*.toml` file
is not plugin-owned, so `<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:
```bash
cp "<skill-directory>/scripts/trace-ops.sh" ".codex/teams/TEAM_NAME_HERE/trace-ops.sh" && \
chmod +x ".codex/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 an `intent-guard` row (trailing `Kind` column = `review-only`, trailing
`Version` column = `PLUGIN_VERSION:`), whether it was created in C3-IG or reused. `Agents | {N}`
counts DOMAIN agents; note intent-guard separately.
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:
```markdown
| 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.
3. Verify:
```bash
bash "<skill-directory>/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
> **STOP if FAIL** -- fix missing files before continuing.
4. request_user_input: final report + suggest `$brewcode:teams-setup status {TEAM_NAME}`
### C5: Quorum Review
Spawn 3 reviewer agents in ONE message via sub-agent collaboration tools. `REVIEWER` (here and in C7/C9) = the
project's reviewer agent from `.codex/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 |
|---|-------|
| 1 | Profile contract: body only (frontmatter excluded) <=3200 bytes (~800 est-tokens); exactly six ordered body headings (`Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification`); `.codex/teams/{TEAM_NAME}/team.md` loaded first; no repeated shared-contract heading/rule |
| 2 | Domain accuracy: correct scope, tool selection, model fit, description triggers |
| 3 | Architecture: no domain overlaps; owned surfaces/exclusions/routing agree with the roster; acceptance/tracing/returns/colleagues/scope-fit exist once in `team.md` |
`.codex/agents/intent-guard.toml` 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: balanced model`, 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 `.codex/agents/` and outputs:
```
FILE: .codex/agents/{name}.toml
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).
| Outcome | Action |
|---------|--------|
| 2/3+ confirm | Mark **confirmed**, keep severity from highest reporter |
| 1/3 only | Log as **unconfirmed**, skip |
| Minor severity (all reporters) | Log but skip fix |
### C7: Verification
```
Codex delegation brief (task_role=REVIEWER, message="
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.
After all intended agents validate, write the final roster. Declared `Agents` equals the number of unique domain rows; duplicate names fail. a new team defaults to `required`. Policy `required` has exactly one `intent-guard` row with fixed cells `--`, `Anti-drift check: what was ASKED vs what was DELIVERED`, `active`, team `Last update`, `review-only`, team `Version`. Policy `legacy-absent` has zero rows. the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters; `ceil(chars/4) <=700` estimated tokens. Measure the full substituted file, not the empty template.
### C8: Fix
For each verified critical/important issue:
```
Codex delegation brief (task_role="brewcode:agent-creator", message="
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,
AGENTS.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 `<skill-directory>/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 .codex/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 `.codex/agents/intent-guard.toml`, add to the ROLE: frontmatter is frozen —
> the description stays short and review-only, tools stay read-only, `model: balanced model` stays. Only
> placeholder content (project facts, invariants, drift examples, evidence commands) may be fixed.
Repair only failed owned artifacts. Domain agents come from `<skill-directory>/references/agent-template.md`; repair the shared contract before an agent rewrite. Preserve foreign agents and unrelated work. Re-run structural TOML, roster, policy, size, and shared-contract checks.
### C9: Re-verify
```
Codex delegation brief (task_role=REVIEWER, message="
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 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}
")
```
Run `scripts/verify-team.sh {TEAM_NAME}`, both test runners, and compatibility validation. Hard-gate `developer_instructions` only: <=3200 bytes and `ceil(chars/4) <=800`; `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification` in order with no other headings. `intent-guard` is exempt from this six-heading gate, not structural TOML validation.
| Outcome | Action |
|---------|--------|
| All FIXED | Pipeline complete, proceed to Epilogue |
| REGRESSION found | Return to C8 for that file (max 2 cycles) |
| Still failing after 2 cycles | Log 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 `.codex/teams/{TEAM_NAME}/team.md`
2. Read trace data:
```bash
bash "<skill-directory>/scripts/trace-ops.sh" read ".codex/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:**
```markdown
# 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:
| Label | Criteria |
|-------|----------|
| Healthy | >70% success, active |
| Needs tuning | 30-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 request_user_input -- purely informational.
---
## Mode: UPGRADE (self-reflection)
### U1: Load & Parse
```bash
CURSOR=$(bash "<skill-directory>/scripts/trace-ops.sh" cursor ".codex/teams/{TEAM_NAME}")
bash "<skill-directory>/scripts/trace-ops.sh" read ".codex/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.
**Refuse to upgrade a PARKED member.** Every write in U4 targets `.codex/agents/{name}.toml`; 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:
```bash
for m in {AGENT_NAMES}; do
[ -f ".codex/agents/$m.toml" ] || { [ -f ".codex/agents/$m.toml.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.
> To skip review pipeline is not an acceptance path; unresolved checks remain failures.
### U1b: Shared Contract Migration Gate
Before U2 analysis or any U4 agent write, read
`<skill-directory>/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}` only and preserving Created, roster rows, statuses, and history. 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.
On upgrade, insert the canonical block before `## Agents` and validate it before touching agents. Record an existing intent-guard roster row -> `required`; no row -> `legacy-absent`. Never synthesize the row on the latter path. Legacy agent bodies remain byte-identical during this gate. **No agent may be tuned, regenerated, stripped, or reformatted until the shared contract passes.** absence migrates
to `legacy-absent`; `legacy-absent` forbids that row and MUST NOT add the role during upgrade.
### U2: Analyze Performance
Filter post-cursor trace: `k=track` for task stats, `k=issue` for problems, `k=insight` for patterns.
| Status | Criteria | Action |
|--------|----------|--------|
| Healthy | >70% success, active | No changes |
| Needs tuning | 30-70% success or many refusals | Update instructions |
| Underperforming | <30% success | AskUser: update or delete+create new |
| Inactive | 0 records | AskUser: delete or keep |
> `intent-guard` is EXCLUDED from this table. It does not trace and is invoked only during review, so
> 0 records is its normal state, never grounds for deletion or tuning. UNINSTALL enforces the same
> exclusion in `references/cleanup-flow.md` Step 3.
### U3: Present & Confirm
**ASK** using request_user_input 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" -> request_user_input per agent. If "Show detailed" -> output full stats, then re-ask.
Use trace evidence only to decide whether a domain profile needs role-specific adjustment. Never duplicate the shared contract.
### U4: Apply Changes
| Agent Status | Action |
|--------------|--------|
| Needs tuning | `Codex delegation brief (task_role="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 `.codex/agents/{name}.toml` + 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 "<skill-directory>/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.toml` is byte-untouchable.
Every domain agent touched here migrates to the current compact template: body only (frontmatter excluded)
<=3200 bytes (~800 est-tokens),
exactly the six ordered headings, `.codex/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.toml` remains byte-untouchable.
Set cursor:
```bash
bash "<skill-directory>/scripts/trace-ops.sh" cursor ".codex/teams/{TEAM_NAME}" set "$(date -u +%Y-%m-%dT%H:%M:%SZ)" && echo "✅" || echo "❌ FAILED"
```
---
## Mode: ENABLE
Un-parks a team that was previously `disable`d. 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
bash "<skill-directory>/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
bash "<skill-directory>/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
bash "<skill-directory>/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
bash "<skill-directory>/scripts/toggle-team.sh" "TEAM_NAME_HERE" disable --dry-run && echo "OK" || echo "FAILED"
```
3. **ASK** using request_user_input: "Disable team {TEAM_NAME}? {N} agent files are parked as
`.toml.disabled` — nothing is deleted, `enable` restores them. `intent-guard` stays live."
Options: "Yes, disable" | "Uninstall instead (deletes agents, keeps archive)" | "Cancel"
- anything but "Yes, disable" -> switch to UNINSTALL or **STOP**
4. Apply:
```bash
bash "<skill-directory>/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 `<skill-directory>/references/cleanup-flow.md` and execute step by step:
1. Overview scan -> show trace.jsonl entry counts by kind
2. request_user_input: what to clean (all / trace data / agents / step-by-step)
3. Trace cleanup (if selected) -- request_user_input with archive options
4. Agents review (if selected) -- request_user_input 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 `.codex/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 `<skill-directory>/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 request_user_input: "Purge team {TEAM_NAME}? This deletes {N} agent files and
`.codex/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 AGENTS.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 request_user_input: "Update team info in AGENTS.md?"
Options: "Yes, in project AGENTS.md" | "Yes, in .codex/AGENTS.local.md" | "No, skip"
Format to write:
```markdown
## Teams
Team: {TEAM_NAME} | Domain agents: {N} (+ `intent-guard`, review-only) | Status: active
| Agent | Domain | Mission |
|-------|--------|---------|
`intent-guard` -- review-only anti-drift check (asked vs delivered). Shared with
`$brewcode:superreview-setup`, invoked explicitly by name during review; never an implementation owner.
Protocol: agents self-select tasks, trace in `.codex/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
```markdown
# 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
| Condition | Action |
|-----------|--------|
| `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 started | Defect — **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 team | `toggle-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 `.toml` nor `.toml.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 `.codex/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 `.codex/agents/{a}.toml` and `{a}.toml.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, request_user_input: "Upgrade instead?" |
| verify-team.sh FAIL | Show 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>
Convert every touched Codex domain agent to the exact three-key TOML contract and six-heading `developer_instructions` shape. Parse before replacement, write atomically, parse again, and preserve untouched agents byte-identical.
For `enable` and `disable`, use `scripts/toggle-team.sh`; it parks/restores domain `.toml` files byte-identically and never parks `intent-guard`. For `uninstall` and `purge`, follow the shipped cleanup flow and explicit confirmation gates. Every mode ends with `verify-team.sh` and reports exact paths, counts, and failures.
@@ -73,12 +73,11 @@ echo "✅ Archived" || echo "❌ FAILED"
## Step 3: Agents Review
> **`intent-guard` is EXCLUDED from this step — never list it, never offer it, never delete it.**
> It is the team's fixed review-only member, shared with `$brewcode:superreview-setup`. It writes no trace
> entries by design, so 0 tasks and "no activity" are its NORMAL state, not inactivity. Filter it out
> of the inactive table BEFORE showing it, so "Delete all inactive" cannot reach it. If the user asks
> for it by name anyway, refuse: answer that removing it breaks `verify-team.sh` for this team, and
> keep the file. Its `team.md` row (`Kind` = `review-only`) also stays.
Read logical `intent_guard_policy=required|legacy-absent` from the single `Intent guard` field in
`team.md` before building the table. Under `required`,
the roster has exactly one review-only `intent-guard`; exclude it from this step, never list/offer/delete
it, and preserve its row. It writes no trace entries, so 0 tasks is normal. Under `legacy-absent`, the
roster has zero such rows and cleanup must not create a profile or row. Upgrade never changes that policy.
Show inactive/problematic agents (domain agents only):
@@ -106,7 +105,7 @@ request_user_input:
On delete:
0. If `{name}` is `intent-guard` -> **STOP, do not delete.** Report it as protected and move on.
0. If `{name}` is `intent-guard` under `required` -> **STOP, do not delete.** Report it as protected and move on. Under `legacy-absent`, seeing that name is a policy violation: delete nothing and report the inconsistent roster.
0b. **Validate `{name}` as an agent id BEFORE any `rm`.** Roster values are interpolated into the delete
path, so a row like `../../../outside/README` deletes a file outside the project. Same guard
`toggle-team.sh`/`verify-team.sh` apply — run it, and on a non-zero exit report the row as a corrupt
@@ -169,9 +168,10 @@ Nothing is archived — the archive itself is part of what goes.
ls -la ".codex/teams/{TEAM}" 2>/dev/null; du -sh ".codex/teams/{TEAM}" 2>/dev/null
```
2. Delete each domain agent listed in `team.md` (`## Agents` table, `Kind` != `review-only`).
**`intent-guard` is skipped** shared with `$brewcode:superreview-setup`; deleting it would break
an unrelated install. Report it as kept. **Every other `{name}` passes the Step 3 id guard first**
2. Delete each domain agent listed in `team.md` (`## Agents` table, `Kind` != `review-only`). Under
`required`, **`intent-guard` is skipped** because it is shared with `$brewcode:superreview-setup`;
report it as kept. Under `legacy-absent`, there is no row or profile to skip and purge must not add
one. **Every other `{name}` passes the Step 3 id guard first**
a roster value that is not `^[a-z0-9][a-z0-9-]*$` is a path, and purge would delete outside
`.codex/agents/`; report such a row as corrupt and delete nothing for it. **Every `{name}` also passes
the Step 3 ownership check (step 0c)** — purge is not a licence to take another team's agent with it:
@@ -1,56 +1,46 @@
# Framework files
Instantiate `.codex/teams/{TEAM_NAME}/`. Replace `{TEAM_NAME}`, `{DATE}`, `{LAST_UPDATED}`, `{PLUGIN_VERSION}`, `{CONTENT_VERSION}`, `{N}`, `{CWD}` from `detect-mode.sh`; `CONTENT_VERSION` self-locates from this skill's metadata, !=copied from `PLUGIN_VERSION`. `{DATE}` is creation date and upgrade never rewrites it. `team.md` uses Edit; `trace.jsonl` is append-only via `trace-ops.sh add`.
Instantiate `.codex/teams/{TEAM_NAME}/`. Replace `{TEAM_NAME}`, `{DATE}`, `{LAST_UPDATED}`, `{PLUGIN_VERSION}`, `{CONTENT_VERSION}`, `{N}`, `{CWD}`, `{INTENT_GUARD_POLICY}`, and `{INTENT_GUARD_ROW}`; scalar metadata comes from `detect-mode.sh`. `CONTENT_VERSION` self-locates from this skill's metadata, !=copied from `PLUGIN_VERSION`. `{DATE}` is creation date and upgrade never rewrites it. `team.md` uses Edit; `trace.jsonl` is append-only via `trace-ops.sh add`.
## team.md
```markdown
# Team: {TEAM_NAME}
| Field | Value |
|-------|-------|
| Created | {DATE} |
| Version | {PLUGIN_VERSION} |
| Content version | {CONTENT_VERSION} |
| Generated by | brewcode:teams-setup |
| Last update | {LAST_UPDATED} |
| Agents | {N} |
| Project | {CWD} |
|Field|Value|
|---|---|
|Created|{DATE}|
|Version|{PLUGIN_VERSION}|
|Content version|{CONTENT_VERSION}|
|Generated by|brewcode:teams-setup|
|Last update|{LAST_UPDATED}|
|Agents|{N}|
|Intent guard|{INTENT_GUARD_POLICY}|
|Project|{CWD}|
## Shared Agent Contract
Every domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.
### Acceptance + routing
Before any task evaluate `Domain`, `Duplicate`, `Best candidate`. Domain mismatch -> refuse + name the roster colleague; duplicate -> refuse + link the result; better candidate -> refuse + name that colleague. Refusal returns to the manager immediately. Acceptance -> trace `took`, execute only owned surfaces, honor exclusions/named owners. The `## Agents` roster routes; profile exclusions win on overlap.
### Tracing
Optional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing file/bash failure -> skip silently; plugin update/move/uninstall does not break it.
`bash ".codex/teams/{TEAM_NAME}/trace-ops.sh" add ".codex/teams/{TEAM_NAME}" "$SID" "{AGENT_NAME}" "<kind>" "<state>" "<text>"`
Track states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; if unset, pass any 8-char marker.
Before any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.
Optional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.
`T=".codex/teams/{TEAM_NAME}"; bash "$T/trace-ops.sh" add "$T" "$SID" "{AGENT_NAME}" "<kind>" "<state>" "<text>"`
Track states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.
A task traced `took` ends with exactly one terminal track: `completed` or `failed`.
### Return
Verdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed `path:line` + check verdict or one failing name. Bulk diffs/logs/dumps/reports -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, return path + verdict + <=3 lines.
### Shared implementation rules
Code/script/SQL/schema/infra/config owners build for actual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify last. Before class/module/test, find the closest well-built repo etalon (`.codex/convention/*` first); its principles add to rules/conventions/docs, !=replace them.
Verdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.
Actual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.codex/convention/*` first), additive to rules/conventions/docs, !=replace them.
## Agents
| Agent | Domain | Mission | Status | Updated | Kind | Version |
|-------|--------|---------|--------|---------|------|---------|
| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | {LAST_UPDATED} | review-only | {PLUGIN_VERSION} |
|Agent|Domain|Mission|Status|Updated|Kind|Version|
|---|---|---|---|---|---|---|
{INTENT_GUARD_ROW}
```
`Agent` stays column 1 (row field 2); `Kind`/`Version` trail, future columns append at end. Metadata quartet `Version` / `Content version` / `Generated by` / `Last update` stays adjacent and ordered; `Created`/`Agents`/`Project` stay outside it. Header `Version` = last `team.md` write; per-agent `Version` changes only for touched rows. Status: `active`, `inactive` (live, zero trace), `updating`, `disabled`, `removed` (file deleted); kind: `domain` (blank allowed), `review-only`. `disabled` parks `.codex/agents/{name}.toml.disabled` while body/team dir/history stay intact; `enable` restores byte-identical body. `intent-guard` is mandatory, shared with superreview, outside `{N}`, and never removed.
`Agent` stays column 1 (row field 2); `Kind`/`Version` trail, future columns append at end. Metadata quartet `Version` / `Content version` / `Generated by` / `Last update` stays adjacent and ordered; `Created`/`Agents`/`Intent guard`/`Project` stay outside it. Header `Version` = last `team.md` write; per-agent `Version` changes only for touched rows. Status: `active`, `inactive` (live, zero trace), `updating`, `disabled`, `removed` (file deleted); kind: `domain` (blank allowed), `review-only`. `disabled` parks `.codex/agents/{name}.toml.disabled` while body/team dir/history stay intact; `enable` restores byte-identical body.
`Intent guard` is explicit: `required` means `{INTENT_GUARD_ROW}` is exactly
`|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|{LAST_UPDATED}|review-only|{PLUGIN_VERSION}|`;
`legacy-absent` means the placeholder is empty and the roster MUST NOT contain `intent-guard`. New teams
default to `required`. Upgrade preserves an existing no-guard roster as `legacy-absent`; it never adds a
role merely to modernize the shared contract. `intent-guard` remains shared with superreview, outside
`{N}`, and never removed when policy is `required`.
## trace.jsonl
@@ -30,7 +30,7 @@ if [ -f "$PLUGIN_JSON" ]; then
fi
fi
# HARD FAIL, never a placeholder value. The repair row this prints is meant to be pasted back into an
# agent's frontmatter, so a documentation spelling like `X.Y.Z` reaches an artifact the moment anyone
# agent's TOML agent schema, so a documentation spelling like `X.Y.Z` reaches an artifact the moment anyone
# follows the advice. It carries no `{}<>`, so setup-status's PLACEHLD test cannot catch it and
# `sort -V` would print a confident `AHEAD X.Y.Z > 5.2.0`. The manifest ships with the plugin in the
# dev checkout and in the cache alike, so an unreadable one is a broken install - stop here.
@@ -57,77 +57,68 @@ case "$CV" in
*) printf 'ERROR:cannot resolve content_version (X.Y.Z) from %s - refusing to emit a repair row with a fake content_version\n' "$SKILL_MD"; exit 1 ;;
esac
# Artifact-metadata frontmatter gate for ONE generated agent. Same four keys, same D2 order and the same
# quoting `brewcode/skills/rules/scripts/rules.sh:140-146` enforces -- one dialect across the repo, not a
# second one invented here. Returns: 0 conforming, 1 malformed, 2 no metadata at all (pre-standard agent).
check_agent_meta() {
# BEGIN CLIENT AGENT VALIDATION
# Native Codex agents are TOML data, not renamed Markdown. Parse before contract validation.
check_native_agent() {
_f="$1"
_fm=$(awk 'NR == 1 && $0 == "---" { f = 1; next } f && $0 == "---" { exit } f { print }' "$_f")
_present=$(printf '%s\n' "$_fm" | grep -cE '^(doc_type|version|generated_by|last_updated):' || true)
[ "$_present" -eq 0 ] && return 2
_expected_name="$2"
_kind="$3"
python3 - "$_f" "$_expected_name" "$_kind" "$TEAM_NAME" <<'PY'
import pathlib
import re
import sys
import tomllib
_bad=0
for _k in doc_type version generated_by last_updated; do
printf '%s\n' "$_fm" | grep -q "^${_k}:" || { echo " FAIL: missing frontmatter key: $_k"; _bad=1; }
done
printf '%s\n' "$_fm" | grep -q '^doc_type: llm$' \
|| { echo " FAIL: doc_type must be exactly 'llm', UNQUOTED"; _bad=1; }
printf '%s\n' "$_fm" | grep -Eq '^version: "[0-9]+\.[0-9]+\.[0-9]+"$' \
|| { echo " FAIL: version must be a QUOTED X.Y.Z (a surviving {PLUGIN_VERSION} token fails here)"; _bad=1; }
printf '%s\n' "$_fm" | grep -Eq '^generated_by: "[^"]+"$' \
|| { echo " FAIL: generated_by must be a QUOTED <plugin>:<skill>"; _bad=1; }
printf '%s\n' "$_fm" | grep -Eq '^last_updated: "[0-9]{4}-[0-9]{2}-[0-9]{2}"$' \
|| { echo " FAIL: last_updated must be a QUOTED YYYY-MM-DD"; _bad=1; }
_order=$(printf '%s\n' "$_fm" | grep -oE '^(doc_type|version|generated_by|last_updated)' | tr '\n' ' ' || true)
[ "$_order" = "doc_type version generated_by last_updated " ] \
|| { echo " FAIL: metadata keys out of order [$_order] -- must be doc_type, version, generated_by, last_updated"; _bad=1; }
return "$_bad"
}
# Print only the body after the closing frontmatter fence. The 3200-byte contract excludes frontmatter:
# a rich trigger description or extra generator metadata must not consume domain-instruction budget.
profile_body() {
awk '
NR == 1 && $0 == "---" { in_fm = 1; next }
in_fm && $0 == "---" { in_fm = 0; body = 1; next }
body { print }
' "$1"
}
# Current teams-setup domain profiles have one compact, machine-checkable body. A body with no
# `## Mission` is legacy and stays runnable with an upgrade warning; a partial current profile is a
# writer defect. intent-guard is exempt because superreview-setup owns its independent template.
check_compact_profile() {
_f="$1"
profile_body "$_f" | grep -qF '## Mission' || return 2
_bad=0
_headings=$(profile_body "$_f" | grep -E '^#{1,6}[[:space:]]' || true)
_expected=$(printf '%s\n' \
'## Mission' \
'## Owned surfaces' \
'## Exclusions' \
'## Must-load references' \
'## Unique invariants' \
'## Unique verification')
[ "$_headings" = "$_expected" ] \
|| { echo " FAIL: body headings must be exactly the six ordered teams-setup headings"; _bad=1; }
_first_ref=$(profile_body "$_f" | awk '
/^## Must-load references$/ { refs = 1; next }
refs && /^## / { exit }
refs && /^-/ { print; exit }
')
printf '%s\n' "$_first_ref" | grep -qF ".codex/teams/$TEAM_NAME/team.md" \
|| { echo " FAIL: Must-load references must name .codex/teams/$TEAM_NAME/team.md"; _bad=1; }
_bytes=$(profile_body "$_f" | wc -c | tr -d '[:space:]')
[ "$_bytes" -le 3200 ] \
|| { echo " FAIL: compact profile body is $_bytes bytes; ceiling is 3200 (~800 est-tokens), frontmatter excluded"; _bad=1; }
if profile_body "$_f" | grep -Eq '^## (sub-agent task Acceptance Protocol|Return Contract|Trace Instructions|Colleagues|Scope Fit|Domain Instructions|Immutable Traits|Update Protocol)$'; then
echo " FAIL: shared acceptance/tracing/routing/return/colleague/scope-fit contract belongs only in team.md"
_bad=1
fi
return "$_bad"
path = pathlib.Path(sys.argv[1])
expected_name, kind, team = sys.argv[2:5]
try:
data = tomllib.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, tomllib.TOMLDecodeError) as exc:
print(f" FAIL: invalid TOML: {exc}")
raise SystemExit(1)
required = {"name", "description", "developer_instructions"}
if set(data) != required:
print(" FAIL: TOML keys must be exactly name, description, developer_instructions")
raise SystemExit(1)
if any(type(data[key]) is not str for key in required):
print(" FAIL: name, description, and developer_instructions must all be strings")
raise SystemExit(1)
if data["name"] != expected_name:
print(f" FAIL: TOML name {data['name']!r} must equal roster/file name {expected_name!r}")
raise SystemExit(1)
if "\n" in data["description"]:
print(" FAIL: description must be one line")
raise SystemExit(1)
if kind == "review-only":
raise SystemExit(0)
body = data["developer_instructions"]
expected_headings = [
"Mission", "Owned surfaces", "Exclusions", "Must-load references",
"Unique invariants", "Unique verification",
]
actual_headings = re.findall(r"^#{1,6}[ ]+(.+)$", body, flags=re.MULTILINE)
if actual_headings != expected_headings:
print(" FAIL: body headings must be exactly the six ordered teams-setup headings in developer_instructions")
raise SystemExit(1)
reference = f".codex/teams/{team}/team.md"
if body.count(reference) != 1:
print(f" FAIL: Must-load references must name {reference} exactly once")
raise SystemExit(1)
must_load = body.split("## Must-load references\n", 1)[1].split("\n## ", 1)[0]
bullets = [line for line in must_load.splitlines() if line.startswith("- ")]
if not bullets or bullets[0] != "- " + chr(96) + reference + chr(96):
print(f" FAIL: {reference} must be the first Must-load references bullet")
raise SystemExit(1)
body_bytes = len(body.encode("utf-8"))
body_tokens = (len(body) + 3) // 4
if body_bytes > 3200 or body_tokens > 800:
print(f" FAIL: developer_instructions is {body_bytes} bytes/{body_tokens} est-tokens; ceilings are 3200 bytes and 800 ceil(chars/4) tokens")
raise SystemExit(1)
PY
}
# END CLIENT AGENT VALIDATION
# Roster values reach `-f` probes here and `mv`/`rm -f` in toggle-team.sh and cleanup-flow.md, so a row
# like `| ../../../outside/README |` is a path, not a name. An agent id is a bare `^[a-z0-9][a-z0-9-]*$`,
@@ -194,6 +185,25 @@ if [ ! -f "$TEAM_DIR/trace.jsonl" ]; then
fi
if [ -f "$TEAM_DIR/team.md" ]; then
team_chars=$(wc -m < "$TEAM_DIR/team.md" | tr -d '[:space:]')
team_tokens=$(( (team_chars + 3) / 4 ))
if [ "$team_chars" -le 2800 ] && [ "$team_tokens" -le 700 ]; then
echo "CHECK: full team.md ceiling ... OK ($team_chars chars, $team_tokens est-tokens)"
else
echo "CHECK: full team.md ceiling ... FAIL ($team_chars chars, $team_tokens est-tokens; maximum 2800 chars and 700 ceil(chars/4) tokens)"
FAIL=1
fi
declared_agents_count=$(grep -cE '^\|[[:space:]]*Agents[[:space:]]*\|' "$TEAM_DIR/team.md" || true)
declared_agents=""
if [ "$declared_agents_count" -eq 1 ]; then
declared_agents=$(sed -n 's/^|[[:space:]]*Agents[[:space:]]*|[[:space:]]*\([0-9][0-9]*\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
fi
if [ "$declared_agents_count" -ne 1 ] || [ -z "$declared_agents" ]; then
echo "CHECK: declared Agents count ... FAIL (requires exactly one numeric | Agents | N | row)"
FAIL=1
fi
# Artifact-metadata header rows -- all FOUR, adjacent, in the order Version / Content version /
# Generated by / Last update. ABSENT ALL FOUR = a team.md written before the standard existed: WARN
# with the fix, an old team must upgrade cleanly. Anything else -- a subset, a wrong order, a
@@ -241,6 +251,15 @@ if [ -f "$TEAM_DIR/team.md" ]; then
;;
esac
# Current teams declare whether the shared review-only role is required or intentionally absent.
# An old team without the field remains migratable; once the shared contract is present the policy
# is mandatory and the roster must match it exactly.
intent_guard_policy=""
intent_guard_policy_count=$(grep -cE '^\|[[:space:]]*Intent guard[[:space:]]*\|' "$TEAM_DIR/team.md" || true)
if [ "$intent_guard_policy_count" -eq 1 ]; then
intent_guard_policy=$(sed -n 's/^|[[:space:]]*Intent guard[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
fi
# New teams centralize the repeated member contract once. Absence remains safe only for a fully
# legacy roster; a compact profile with no destination contract is an interrupted-install defect.
shared_contract_present=0
@@ -249,6 +268,15 @@ if [ -f "$TEAM_DIR/team.md" ]; then
else
shared_contract_present=1
shared_bad=0
if [ "$intent_guard_policy_count" -ne 1 ]; then
echo "CHECK: Intent guard policy ... FAIL (current team.md requires exactly one policy row)"
shared_bad=1
else
case "$intent_guard_policy" in
required|legacy-absent) echo "CHECK: Intent guard policy ($intent_guard_policy) ... OK" ;;
*) echo "CHECK: Intent guard policy ... FAIL (expected required or legacy-absent; found '$intent_guard_policy')"; shared_bad=1 ;;
esac
fi
shared_count=$(grep -cF '## Shared Agent Contract' "$TEAM_DIR/team.md" || true)
[ "$shared_count" -eq 1 ] \
|| { echo "CHECK: Shared Agent Contract ... FAIL (must occur exactly once; found $shared_count)"; shared_bad=1; }
@@ -286,7 +314,12 @@ if [ -f "$TEAM_DIR/team.md" ]; then
in_agents=0
past_header=0
found_agents=0
found_intent_guard=0
intent_guard_count=0
intent_guard_cells_ok=1
unique_domain_rows=0
seen_agent_ids="|"
team_version=$(sed -n 's/^|[[:space:]]*Version[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
team_last_update=$(sed -n 's/^|[[:space:]]*Last update[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
while IFS= read -r line; do
case "$line" in
"## Agents"*) in_agents=1; past_header=0; continue ;;
@@ -307,7 +340,39 @@ if [ -f "$TEAM_DIR/team.md" ]; then
FAIL=1
continue
fi
[ "$agent" = "intent-guard" ] && found_intent_guard=1
case "$seen_agent_ids" in
*"|$agent|"*)
echo "CHECK: roster name '$agent' ... FAIL (duplicate roster name)"
FAIL=1
;;
*)
seen_agent_ids="${seen_agent_ids}${agent}|"
if [ "$agent" != "intent-guard" ]; then
agent_kind=$(printf '%s' "$line" | cut -d'|' -f7 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
case "$agent_kind" in
''|domain) unique_domain_rows=$((unique_domain_rows + 1)) ;;
*) echo "CHECK: agent '$agent' kind ... FAIL (domain rows require Kind domain or blank)"; FAIL=1 ;;
esac
fi
;;
esac
if [ "$agent" = "intent-guard" ]; then
intent_guard_count=$((intent_guard_count + 1))
agent_domain=$(printf '%s' "$line" | cut -d'|' -f3 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_mission=$(printf '%s' "$line" | cut -d'|' -f4 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_status=$(printf '%s' "$line" | cut -d'|' -f5 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_updated=$(printf '%s' "$line" | cut -d'|' -f6 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_kind=$(printf '%s' "$line" | cut -d'|' -f7 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_version=$(printf '%s' "$line" | cut -d'|' -f8 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [ "$agent_domain" != "--" ] \
|| [ "$agent_mission" != "Anti-drift check: what was ASKED vs what was DELIVERED" ] \
|| [ "$agent_status" != "active" ] \
|| [ "$agent_updated" != "$team_last_update" ] \
|| [ "$agent_kind" != "review-only" ] \
|| [ "$agent_version" != "$team_version" ]; then
intent_guard_cells_ok=0
fi
fi
printf "CHECK: agent %s ... " "$agent"
# BOTH copies present is checked FIRST: a live-first if/parked-elif chain reads a dual copy
# as a healthy live agent and hides the collision. `.codex/agents/` is project-global, so the
@@ -320,36 +385,28 @@ if [ -f "$TEAM_DIR/team.md" ]; then
CONFLICT=$((CONFLICT + 1))
FAIL=1
elif [ -f ".codex/agents/${agent}.toml" ]; then
# The roster row proves the file exists; the frontmatter proves the generator stamped it.
# A generated agent with no metadata at all predates the standard -> WARN + the upgrade fix.
# Metadata that IS there but malformed is a generator defect -> FAIL.
# BEGIN LIVE CLIENT AGENT CHECK
native_kind=domain
[ "$agent" = "intent-guard" ] && native_kind=review-only
set +e
meta_out=$(check_agent_meta ".codex/agents/${agent}.toml")
meta_rc=$?
native_out=$(check_native_agent ".codex/agents/${agent}.toml" "$agent" "$native_kind")
native_rc=$?
set -e
case "$meta_rc" in
0) echo "OK" ;;
2) echo "OK (no artifact metadata -- agent predates the standard; \$brewcode:teams-setup upgrade restamps it)" ;;
*) echo "FAIL"; printf '%s\n' "$meta_out"; FAIL=1 ;;
esac
if [ "$agent" != "intent-guard" ]; then
set +e
profile_out=$(check_compact_profile ".codex/agents/${agent}.toml")
profile_rc=$?
set -e
case "$profile_rc" in
0)
if [ "$shared_contract_present" -eq 1 ]; then
echo " CHECK: compact six-heading profile ... OK"
else
echo " CHECK: compact six-heading profile ... FAIL (shared team contract missing; interrupted install/unsafe migration)"
FAIL=1
fi
;;
2) echo " WARN: legacy repeated/unknown profile shape. Fix: \$brewcode:teams-setup upgrade" ;;
*) printf '%s\n' "$profile_out"; FAIL=1 ;;
esac
if [ "$native_rc" -eq 0 ]; then
echo "OK"
if [ "$native_kind" = "domain" ] && [ "$shared_contract_present" -ne 1 ]; then
echo " CHECK: compact six-heading profile ... FAIL (shared team contract missing; interrupted install/unsafe migration)"
FAIL=1
elif [ "$native_kind" = "domain" ]; then
echo " CHECK: structurally parsed six-heading developer_instructions ... OK"
fi
else
echo "FAIL"
printf '%s
' "$native_out"
FAIL=1
fi
# END LIVE CLIENT AGENT CHECK
elif [ -f ".codex/agents/${agent}.toml.disabled" ]; then
# Parked by `disable`: the body is intact, only the .md extension that
# Codex discovers on is withheld. A reversible state, not a defect.
@@ -368,21 +425,40 @@ if [ -f "$TEAM_DIR/team.md" ]; then
if [ "$in_agents" -eq 0 ]; then
echo "WARN: no ## Agents section in team.md"
fi
# intent-guard is a fixed review-only member of every team, outside the domain-agent count.
# Teams created before it existed simply lack the row -- warn with the fix, never fail them.
# Teams that DO list it are covered by the per-agent -f check above.
if [ "$found_intent_guard" -eq 0 ]; then
echo "WARN: team.md has no intent-guard row (team predates it). Fix:"
echo " bash \"$SCRIPT_DIR/../../superreview-setup/scripts/generate.sh\" emit-agent"
echo " then add this row to the ## Agents table (all 7 columns: Agent, Domain, Mission, Status,"
echo " Updated, Kind, Version):"
echo " | intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | $TODAY | review-only | $PV |"
elif [ "$shared_contract_present" -eq 0 ]; then
echo "WARN: legacy intent-guard roster row predates the review-only scope contract. Fix: \$brewcode:teams-setup upgrade"
elif ! grep -Eq '^\|[[:space:]]*intent-guard[[:space:]]*\|[[:space:]]*--[[:space:]]*\|[[:space:]]*Anti-drift check: what was ASKED vs what was DELIVERED[[:space:]]*\|[^|]*\|[^|]*\|[[:space:]]*review-only[[:space:]]*\|' "$TEAM_DIR/team.md"; then
echo "CHECK: intent-guard roster contract ... FAIL (domain '--', fixed anti-drift mission, and kind review-only are required)"
if [ -n "$declared_agents" ] && [ "$declared_agents" -eq "$unique_domain_rows" ]; then
echo "CHECK: declared Agents count ... OK ($declared_agents unique domain rows)"
elif [ -n "$declared_agents" ]; then
echo "CHECK: declared Agents count ... FAIL (declared $declared_agents, found $unique_domain_rows unique domain rows)"
FAIL=1
fi
case "$intent_guard_policy" in
required)
if [ "$intent_guard_count" -ne 1 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (policy required needs exactly one row; found $intent_guard_count)"
FAIL=1
elif [ "$intent_guard_cells_ok" -ne 1 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (fixed cells require --, anti-drift mission, active, team Last update, review-only, and team Version)"
FAIL=1
else
echo "CHECK: intent-guard roster contract ... OK"
fi
;;
legacy-absent)
if [ "$intent_guard_count" -ne 0 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (policy legacy-absent requires zero rows; found $intent_guard_count)"
FAIL=1
fi
;;
"")
if [ "$shared_contract_present" -eq 0 ]; then
if [ "$intent_guard_count" -eq 0 ]; then
echo "WARN: legacy team has no intent-guard row; upgrade records policy legacy-absent without adding a role"
else
echo "WARN: legacy intent-guard roster row predates the explicit required policy. Fix: \$brewcode:teams-setup upgrade"
fi
fi
;;
esac
fi
printf 'DISABLED_AGENTS:%s\n' "$DISABLED"
@@ -31,6 +31,24 @@ const LEGACY_HEADINGS = [
const SOURCE_CLIENT_DIR = ['.', 'claude'].join('');
const SOURCE_TEAM_REF = `${SOURCE_CLIENT_DIR}/teams/{TEAM_NAME}/team.md`;
const NATIVE_TEAM_REF = '.codex/teams/{TEAM_NAME}/team.md';
const SOURCE_PLUGIN_ROOT = `${['CL', 'AUDE'].join('')}_PLUGIN_ROOT`;
const SOURCE_PLUGIN_ROOT_NEGATION = `!=\`\${${SOURCE_PLUGIN_ROOT}}\` substitution`;
const DUSK_ROSTER = [
['game-designer', 'design', 'pillars'],
['combat-dev', 'combat', 'loop'],
['physics-dev', 'physics', 'Jolt'],
['destruction-dev', 'destruct', 'fracture'],
['scenario-dev', 'scenarios', 'lab'],
['vfx-dev', 'VFX', 'impacts'],
['texture-artist', 'materials', 'textures'],
['modeller-3d', 'models', 'rigs'],
['sound-designer', 'audio', 'SFX'],
['feel-dev', 'feel', 'camera'],
['qa-tester', 'QA', 'tests'],
['docs-keeper', 'docs', 'sync'],
['build-eng', 'build', 'toolchain'],
];
const DUSK_NON_MEMBERS = ['task-tracker', 'intent-guard'];
let passed = 0;
let failed = 0;
@@ -93,6 +111,37 @@ function section(text, start, end) {
return text.slice(a, b < 0 ? text.length : b);
}
function rosterNames(team) {
return section(team, '## Agents', '\n## ')
.split('\n')
.filter((line) => /^\|[a-z0-9]/.test(line) && !line.startsWith('|Agent|'))
.map((line) => line.split('|')[1]);
}
function instantiateTeamTemplate(template, {
projectRoot,
roster,
policy,
version = '6.1.4',
contentVersion = '6.1.0',
}) {
const intentRow = policy === 'required'
? `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|${version}|`
: '';
const domainRows = roster.map(([name, domain, mission]) =>
`|${name}|${domain}|${mission}|active|2026-08-27|domain|${version}|`).join('\n');
return `${template
.replaceAll('{TEAM_NAME}', 'dusk')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', version)
.replaceAll('{CONTENT_VERSION}', contentVersion)
.replaceAll('{N}', String(roster.length))
.replaceAll('{CWD}', projectRoot)
.replaceAll('{INTENT_GUARD_POLICY}', policy)
.replaceAll('{INTENT_GUARD_ROW}', [intentRow, domainRows].filter(Boolean).join('\n'))}\n`;
}
const repo = findRepoRoot(dirname(fileURLToPath(import.meta.url)));
const canonicalTemplatePath = join(repo, 'brewcode', 'skills', 'teams-setup', 'references', 'agent-template.md');
const canonicalFrameworkPath = join(repo, 'brewcode', 'skills', 'teams-setup', 'references', 'framework-files.md');
@@ -183,6 +232,7 @@ const sharedSourceLiterals = [
'no retry, Bash only',
'versionless project-local',
sourceTracePath,
SOURCE_PLUGIN_ROOT_NEGATION,
'no `*_PLUGIN_ROOT` env',
'plugin update/move/uninstall does not break it',
'`took` / `refused` / `completed` / `failed`',
@@ -195,6 +245,7 @@ const sharedSourceLiterals = [
'>~2500',
'<=3 lines',
'!=imagined load/speculative abstraction',
'10-user app !=lock-contention hardening',
'!=replace them',
'## Agents',
];
@@ -218,6 +269,60 @@ check(
true,
'generated team.md fenced template is at most 700 estimated tokens',
);
check(
'shared.intentPolicyPlaceholder',
occurrences(canonicalTeam, '{INTENT_GUARD_POLICY}'),
1,
'team template carries exactly one explicit intent-guard policy field',
);
check(
'shared.intentRowPlaceholder',
occurrences(canonicalTeam, '{INTENT_GUARD_ROW}'),
1,
'team template carries exactly one policy-controlled intent-guard row slot',
);
const fullDuskTeam = instantiateTeamTemplate(canonicalTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk',
roster: DUSK_ROSTER,
policy: 'legacy-absent',
});
check(
'shared.fullDuskRosterCount',
rosterNames(fullDuskTeam).length,
13,
'the representative full Dusk roster contains exactly 13 members',
);
check(
'shared.fullDuskRosterNames',
rosterNames(fullDuskTeam).join('|'),
DUSK_ROSTER.map(([name]) => name).join('|'),
'the full Dusk roster preserves the exact ordered member boundary',
);
check(
'shared.fullDuskNonMembers',
DUSK_NON_MEMBERS.filter((name) => rosterNames(fullDuskTeam).includes(name)).join('|'),
'',
'task-tracker and intent-guard stay outside the legacy-absent Dusk roster',
);
check(
'shared.fullDuskPolicy',
fullDuskTeam.includes('|Intent guard|legacy-absent|'),
true,
'the no-intent-guard roster carries an explicit legacy-absent policy',
);
check(
'shared.fullDuskCharsWithinCeiling',
fullDuskTeam.length <= 2800,
true,
'the complete 13-member Dusk team.md is at most 2800 characters',
);
check(
'shared.fullDuskTokensWithinCeiling',
Math.ceil(fullDuskTeam.length / 4) <= 700,
true,
'the complete 13-member Dusk team.md is at most 700 estimated tokens',
);
check(
'codex.headings',
@@ -264,7 +369,8 @@ check(
for (const literal of sharedSourceLiterals) {
const nativeLiteral = literal
.replaceAll(SOURCE_CLIENT_DIR, '.codex');
.replaceAll(SOURCE_CLIENT_DIR, '.codex')
.replaceAll(`\`\${${SOURCE_PLUGIN_ROOT}}\``, '`<plugin-root>`');
check(
`codex.sharedLiteral.${sharedSourceLiterals.indexOf(literal) + 1}`,
projectedTeam.includes(nativeLiteral),
@@ -278,6 +384,23 @@ check(
true,
'Codex path projection does not grow the shared contract',
);
const fullNativeDuskTeam = instantiateTeamTemplate(projectedTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk',
roster: DUSK_ROSTER,
policy: 'legacy-absent',
});
check(
'codex.fullDuskRosterNames',
rosterNames(fullNativeDuskTeam).join('|'),
DUSK_ROSTER.map(([name]) => name).join('|'),
'native Codex projection preserves the exact full Dusk member boundary',
);
check(
'codex.fullDuskTokensWithinCeiling',
Math.ceil(fullNativeDuskTeam.length / 4) <= 700,
true,
'native Codex full Dusk team remains at most 700 estimated tokens',
);
check(
'codex.distributedTemplateParity',
distributedTemplate,
@@ -333,6 +456,8 @@ check(
const migration = section(canonicalSkill, '### U1b: Shared Contract Migration Gate', '### U2: Analyze Performance');
for (const literal of [
'insert the canonical block before `## Agents`',
'an existing intent-guard roster row -> `required`; no row',
'-> `legacy-absent`. Never synthesize the row on the latter path.',
'Legacy agent bodies remain byte-identical during this gate.',
'**No agent may be tuned, regenerated, stripped,',
'until the shared contract passes.',
@@ -344,6 +469,20 @@ for (const literal of [
`legacy-upgrade ordering preserves ${JSON.stringify(literal)}`,
);
}
for (const literal of [
'a new team defaults to `required`',
'absence migrates\nto `legacy-absent`',
'`legacy-absent` forbids that row and MUST NOT add the role during upgrade',
'the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters',
'`ceil(chars/4) <=700` estimated tokens',
]) {
check(
`policy.workflow.${literal.slice(0, 16)}`,
canonicalSkill.includes(literal),
true,
`generator workflow preserves ${JSON.stringify(literal)}`,
);
}
const c8 = section(canonicalSkill, '### C8: Fix', '### C9: Re-verify');
check(
@@ -354,7 +493,7 @@ check(
);
const c9 = section(canonicalSkill, '### C9: Re-verify', '> To skip review pipeline');
for (const literal of [
'body only (frontmatter excluded): <=3200 bytes',
'`developer_instructions` only: <=3200 bytes',
'`Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`,',
'`Unique verification` in order with no other headings',
'`intent-guard` is exempt from this six-heading gate',
@@ -403,60 +542,48 @@ check(
const pluginVersion = (/brewcode-meta: version=([0-9]+\.[0-9]+\.[0-9]+)/.exec(canonicalSkill) || [])[1];
const contentVersion = (/content_version=([0-9]+\.[0-9]+\.[0-9]+)/.exec(canonicalSkill) || [])[1];
const today = '2026-08-27';
const BUILD_ROSTER = [['build-eng', 'Build', 'deterministic builds']];
function instantiateTeam(projectRoot) {
const intentRow = `| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | ${today} | review-only | ${pluginVersion} |`;
return `${projectedTeam
.replaceAll('{TEAM_NAME}', 'dusk')
.replaceAll('{DATE}', today)
.replaceAll('{LAST_UPDATED}', today)
.replaceAll('{PLUGIN_VERSION}', pluginVersion)
.replaceAll('{CONTENT_VERSION}', contentVersion)
.replaceAll('{N}', '1')
.replaceAll('{CWD}', projectRoot)
.replace(intentRow, `${intentRow}\n| build-eng | Build | Own deterministic build surfaces | active | ${today} | domain | ${pluginVersion} |`)}\n`;
function instantiateTeam(projectRoot, { policy = 'required', roster = BUILD_ROSTER } = {}) {
return instantiateTeamTemplate(projectedTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk', roster, policy, version: pluginVersion, contentVersion,
});
}
function agentFile({ body = runtimeRepresentativeBody, frontmatterPadding = '' } = {}) {
return `---
name: build-eng
description: Build owner. Triggers: build, release, toolchain.
${frontmatterPadding}doc_type: llm
version: "${pluginVersion}"
generated_by: "brewcode:teams-setup"
last_updated: "${today}"
---
// BEGIN RUNTIME AGENT FIXTURES
function tomlString(value) {
return JSON.stringify(value);
}
${body}`;
function agentFile({ name = 'build-eng', body = runtimeRepresentativeBody, extraField = '' } = {}) {
return `name = ${tomlString(name)}\ndescription = "Domain owner. Triggers: domain, review, verification."\ndeveloper_instructions = ${tomlString(body)}\n${extraField}`;
}
function intentGuardFile() {
return `---
name: intent-guard
description: Review-only anti-drift check.
doc_type: llm
version: "${pluginVersion}"
generated_by: "brewcode:superreview-setup"
last_updated: "${today}"
---
# Intent guard
Review only.
`;
return `name = "intent-guard"\ndescription = "Review-only anti-drift check."\ndeveloper_instructions = "Review only; never implement or mutate project files."\n`;
}
// END RUNTIME AGENT FIXTURES
function makeWorld({ teamText, agentText = agentFile(), intent = true } = {}) {
function makeWorld({
teamText,
agentText,
policy = 'required',
roster = BUILD_ROSTER,
intent = policy === 'required',
} = {}) {
const world = mkdtempSync(join(tmpdir(), 'team-profile-contract-'));
const teamDir = join(world, '.codex', 'teams', 'dusk');
const agentsDir = join(world, '.codex', 'agents');
mkdirSync(teamDir, { recursive: true });
mkdirSync(agentsDir, { recursive: true });
writeFileSync(join(teamDir, 'team.md'), teamText ?? instantiateTeam(world));
writeFileSync(join(teamDir, 'team.md'), teamText ?? instantiateTeam(world, { policy, roster }));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
writeFileSync(join(teamDir, 'trace-ops.sh'), '#!/bin/sh\nexit 0\n');
chmodSync(join(teamDir, 'trace-ops.sh'), 0o755);
writeFileSync(join(agentsDir, 'build-eng.toml'), agentText);
for (const [name] of roster) {
writeFileSync(join(agentsDir, `${name}.toml`),
name === 'build-eng' && agentText ? agentText : agentFile({ name }));
}
if (intent) writeFileSync(join(agentsDir, 'intent-guard.toml'), intentGuardFile());
return world;
}
@@ -484,24 +611,141 @@ function removeWorld(world) {
}
{
const padding = `notes: "${'x'.repeat(5000)}"\n`;
const world = makeWorld({ agentText: agentFile({ frontmatterPadding: padding }) });
const world = makeWorld({ policy: 'legacy-absent', roster: DUSK_ROSTER });
const result = runVerifier(world);
check('verifier.frontmatterExcluded', result.status, 0,
'large valid frontmatter does not consume the 3200-byte body budget');
check('verifier.frontmatterTotalOverCeiling',
Buffer.byteLength(readFileSync(join(world, '.codex', 'agents', 'build-eng.toml'))) > 3200,
true,
'the fixture proves the full file itself exceeds 3200 bytes');
check('verifier.fullDuskLegacyAbsent.exit', result.status, 0,
'the full 13-member Dusk roster passes without adding intent-guard');
check('verifier.fullDuskLegacyAbsent.policy',
result.output.includes('CHECK: Intent guard policy (legacy-absent) ... OK'), true,
'the verifier accepts the explicit no-intent-guard policy');
check('verifier.fullDuskLegacyAbsent.memberChecks',
DUSK_ROSTER.every(([name]) => result.output.includes(`CHECK: agent ${name} ... OK`)), true,
'the verifier checks every exact Dusk member');
removeWorld(world);
}
{
const world = makeWorld({ policy: 'required', intent: false });
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(/^\|intent-guard\|.*\n/m, ''));
const result = runVerifier(world);
check('verifier.requiredMissing.exit', result.status, 1,
'required policy fails when the intent-guard row is absent');
check('verifier.requiredMissing.reason',
result.output.includes('policy required needs exactly one row; found 0'), true,
'required-policy failure names the missing row');
removeWorld(world);
}
{
const world = makeWorld({ policy: 'legacy-absent', intent: true });
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const team = readFileSync(teamPath, 'utf8');
const forbiddenRow = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|`;
writeFileSync(teamPath, `${team.trim()}\n${forbiddenRow}\n`);
const result = runVerifier(world);
check('verifier.legacyAbsentRow.exit', result.status, 1,
'legacy-absent policy fails when an intent-guard row is introduced');
check('verifier.legacyAbsentRow.reason',
result.output.includes('policy legacy-absent requires zero rows; found 1'), true,
'legacy-absent failure names the forbidden roster expansion');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(
'|Intent guard|required|', '|Intent guard|optional|'));
const result = runVerifier(world);
check('verifier.invalidPolicy.exit', result.status, 1,
'an unsupported intent-guard policy fails');
check('verifier.invalidPolicy.reason',
result.output.includes("expected required or legacy-absent; found 'optional'"), true,
'the verifier enumerates the only valid policy values');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${'x'.repeat(900)}\n`);
const result = runVerifier(world);
check('verifier.teamCeiling.exit', result.status, 1,
'an oversized fully substituted team.md fails');
check('verifier.teamCeiling.reason',
result.output.includes('maximum 2800 chars and 700 ceil(chars/4) tokens'), true,
'the runtime verifier names both complete-file ceilings');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace('|Agents|1|', '|Agents|2|'));
const result = runVerifier(world);
check('verifier.agentCountMismatch.exit', result.status, 1,
'declared Agents count must equal unique domain rows');
check('verifier.agentCountMismatch.reason',
result.output.includes('declared 2, found 1 unique domain rows'), true,
'the mismatch reports declared and observed unique-domain counts');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const duplicate = `|build-eng|Build|deterministic builds|active|${today}|domain|${pluginVersion}|\n`;
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${duplicate}`);
const result = runVerifier(world);
check('verifier.duplicateDomain.exit', result.status, 1,
'duplicate domain roster names fail');
check('verifier.duplicateDomain.reason',
result.output.includes("duplicate roster name"), true,
'the verifier identifies duplicate roster identity');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const duplicate = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|\n`;
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${duplicate}`);
const result = runVerifier(world);
check('verifier.duplicateIntentGuard.exit', result.status, 1,
'required policy rejects duplicate intent-guard rows');
check('verifier.duplicateIntentGuard.reason',
result.output.includes('policy required needs exactly one row; found 2'), true,
'the verifier enforces exactly one review-only row');
removeWorld(world);
}
// BEGIN SOURCE FRONTMATTER BUDGET FIXTURE
{
const world = makeWorld({ agentText: agentFile({ extraField: 'model = "legacy"\n' }) });
const result = runVerifier(world);
check('verifier.exactTomlKeys.exit', result.status, 1, 'an unsupported fourth TOML key fails');
check('verifier.exactTomlKeys.reason', result.output.includes('TOML keys must be exactly name, description, developer_instructions'), true,
'the verifier enforces the exact native schema structurally');
removeWorld(world);
}
{
const world = makeWorld({ agentText: '---\nname: build-eng\n---\n' });
const result = runVerifier(world);
check('verifier.renamedMarkdown.exit', result.status, 1, 'renamed Markdown is not accepted as TOML');
check('verifier.renamedMarkdown.reason', result.output.includes('invalid TOML'), true,
'the verifier parses the native fixture instead of scanning YAML text');
removeWorld(world);
}
// END SOURCE FRONTMATTER BUDGET FIXTURE
{
const oversized = `${runtimeRepresentativeBody}\n${'x'.repeat(3300)}\n`;
const world = makeWorld({ agentText: agentFile({ body: oversized }) });
const result = runVerifier(world);
check('verifier.bodyCeiling.exit', result.status, 1, 'an oversized body fails even with small frontmatter');
check('verifier.bodyCeiling.reason', result.output.includes('ceiling is 3200 (~800 est-tokens), frontmatter excluded'), true,
check('verifier.bodyCeiling.exit', result.status, 1, 'an oversized developer_instructions value fails');
check('verifier.bodyCeiling.reason', result.output.includes('ceilings are 3200 bytes and 800 ceil(chars/4) tokens'), true,
'the failure names the body-only contract');
removeWorld(world);
}
@@ -530,6 +774,7 @@ for (const [index, literal] of instantiatedLosses.entries()) {
removeWorld(world);
}
// BEGIN SOURCE LEGACY AGENT FIXTURE
{
const legacyTeam = `# Team: dusk
@@ -552,11 +797,10 @@ for (const [index, literal] of instantiatedLosses.entries()) {
const legacyBody = '## Domain Instructions\n\nLegacy acceptance and trace rules remain local until upgrade.\n';
const world = makeWorld({ teamText: legacyTeam, agentText: agentFile({ body: legacyBody }), intent: false });
const result = runVerifier(world);
check('verifier.legacyMigrationSafe.exit', result.status, 0,
'a fully legacy team remains runnable while upgrade is required');
check('verifier.legacyMigrationSafe.exit', result.status, 1,
'a structurally parsed native agent without six headings fails');
check('verifier.legacyMigrationSafe.warning',
result.output.includes('has no Shared Agent Contract (legacy team)')
&& result.output.includes('legacy repeated/unknown profile shape'),
result.output.includes('body headings must be exactly the six ordered teams-setup headings in developer_instructions'),
true,
'legacy authority and legacy profile produce migration warnings without destructive failure');
removeWorld(world);
@@ -569,6 +813,7 @@ for (const [index, literal] of instantiatedLosses.entries()) {
'the verifier directs repair of the shared authority before profile stripping');
removeWorld(interrupted);
}
// END SOURCE LEGACY AGENT FIXTURE
for (const [name, mutate, reason] of [
['firstReference', (text) => text.replace('.codex/teams/dusk/team.md', '.codex/teams/other/team.md'),
@@ -584,22 +829,36 @@ for (const [name, mutate, reason] of [
removeWorld(world);
}
{
for (const [name, mutate] of [
['domain', (row) => row.replace('|--|', '|code|')],
['mission', (row) => row.replace('Anti-drift check: what was ASKED vs what was DELIVERED', 'Implementation owner')],
['status', (row) => row.replace('|active|', '|inactive|')],
['updated', (row) => row.replace(`|${today}|review-only|`, '|2026-08-26|review-only|')],
['kind', (row) => row.replace('|review-only|', '|domain|')],
['version', (row) => row.replace(`|${pluginVersion}|`, '|0.0.0|')],
]) {
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const team = readFileSync(teamPath, 'utf8');
writeFileSync(teamPath, team.replace(
`| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | ${today} | review-only | ${pluginVersion} |`,
`| intent-guard | code | Implementation owner | active | ${today} | domain | ${pluginVersion} |`,
));
const fixedRow = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|`;
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(fixedRow, mutate(fixedRow)));
const result = runVerifier(world);
check('verifier.intentGuardScope.exit', result.status, 1,
'changing the fixed intent-guard scope/kind fails');
check('verifier.intentGuardScope.reason', result.output.includes('intent-guard roster contract ... FAIL'), true,
'the verifier protects the review-only exemption in the instantiated roster');
check(`verifier.intentGuardFixed.${name}.exit`, result.status, 1,
`changing fixed intent-guard ${name} fails`);
check(`verifier.intentGuardFixed.${name}.reason`,
result.output.includes('fixed cells require --, anti-drift mission, active, team Last update, review-only, and team Version'), true,
'the verifier protects every fixed review-only cell');
removeWorld(world);
}
const nativeVerifier = readFileSync(verifierPath, 'utf8');
check('codex.verifier.tomllib', nativeVerifier.includes('import tomllib'), true,
'native verifier parses TOML structurally');
check('codex.verifier.noYamlParser', nativeVerifier.includes('NR == 1 && $0 == "---"'), false,
'native verifier has no YAML fence parser');
check('codex.verifier.exactKeys',
nativeVerifier.includes('required = {"name", "description", "developer_instructions"}'), true,
'native verifier pins the exact supported top-level schema');
console.log('suite-agent-profile-contract.mjs');
for (const line of results) console.log(line);
console.log(` ${passed} passed, ${failed} failed`);
+52 -158
View File
@@ -1,190 +1,84 @@
#!/usr/bin/env node
/**
* Suite B intent-guard provenance (superreview-setup/scripts/generate.sh emit-agent), the ONE writer
* of .codex/agents/intent-guard.toml that $brewcode:teams-setup Phase 3 calls.
* Covers BCOP09: the runnability tests used to run before the provenance probes, so a hand-written
* agent that merely mentioned a `{TOKEN}` was classified BROKEN and overwritten with no backup.
* Runs entirely inside an isolated temp base; never touches the real ~/.codex or the repo tree.
* Assertion policy: unconditional exact-equality checks with a description.
*/
import { spawnSync } from 'node:child_process';
import {
mkdtempSync, mkdirSync, writeFileSync, readFileSync, readdirSync, rmSync, realpathSync,
} from 'node:fs';
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { fileURLToPath } from 'node:url';
const HERE = join(fileURLToPath(import.meta.url), '..');
const GENERATE = join(HERE, '..', '..', 'superreview-setup', 'scripts', 'generate.sh');
const BASE = realpathSync(mkdtempSync(join(tmpdir(), 'teams-intent-guard-')));
const IG_REL = '.codex/agents/intent-guard.toml';
const STAMP = '<!-- generated_by: brewcode:superreview-setup v9.9.9 -->';
const LEGACY_STAMP = '<!-- intent-guard template v2 - emitted 2025-01-01 - source: fixture -->';
const EMIT = join(HERE, '..', '..', 'superreview-setup', 'scripts', 'emit-intent-guard.sh');
const TEMPLATE = join(HERE, '..', '..', 'superreview-setup', 'references', 'intent-guard.toml.template');
let passed = 0;
let failed = 0;
const results = [];
function check(name, actual, expected, message) {
function check(name, actual, expected, description) {
if (actual === expected) {
passed++;
results.push(` PASS ${name} (${message})`);
passed += 1;
results.push(' PASS ' + name + ' (' + description + ')');
} else {
failed++;
results.push(
` FAIL ${name} (${message} | actual=${JSON.stringify(actual)} expected=${JSON.stringify(expected)})`,
);
failed += 1;
results.push(' FAIL ' + name + ' (' + description + ' | actual=' + JSON.stringify(actual) + ' expected=' + JSON.stringify(expected) + ')');
}
}
/** A project root with an optional pre-existing intent-guard.toml. */
function makeProject(label, body) {
const root = join(BASE, label);
mkdirSync(join(root, '.codex', 'agents'), { recursive: true });
if (body !== null) writeFileSync(join(root, IG_REL), body);
return root;
function run(root) {
const result = spawnSync('bash', [EMIT, root], { encoding: 'utf8', timeout: 30000 });
return { status: result.status, output: (result.stdout || '') + (result.stderr || '') };
}
function emitAgent(root) {
const r = spawnSync('bash', [GENERATE, 'emit-agent'], { cwd: root, encoding: 'utf8', timeout: 30000 });
return { stdout: (r.stdout || '').trim(), stderr: r.stderr || '', status: r.status };
function parse(path) {
const result = spawnSync('python3', ['-c', 'import json,pathlib,sys,tomllib; print(json.dumps(tomllib.loads(pathlib.Path(sys.argv[1]).read_text()), sort_keys=True))', path], { encoding: 'utf8' });
return { status: result.status, data: result.status === 0 ? JSON.parse(result.stdout) : null };
}
const agentNames = (root) => readdirSync(join(root, '.codex', 'agents')).sort();
const backups = (root) =>
agentNames(root).filter((n) => /^intent-guard\.toml\.bak-[0-9]{8}-[0-9]{6}$/.test(n));
const read = (root, rel) => readFileSync(join(root, rel), 'utf8');
const template = parse(TEMPLATE);
check('template.parse', template.status, 0, 'shared native template is valid TOML');
check('template.keys', Object.keys(template.data).sort().join(','), 'description,developer_instructions,name', 'template has exactly three keys');
check('template.name', template.data.name, 'intent-guard', 'template name is fixed');
const FOREIGN_WITH_TOKEN = [
'---',
'name: intent-guard',
'description: our own hand-written drift check',
'---',
'',
'# intent-guard',
'',
'Use {REQUEST_ID} to correlate the review with the ticket.',
'',
].join('\n');
// ────────────────────────────────────────────────────────────────────────────
// B1 — BCOP09: an UNSTAMPED file carrying a {TOKEN} is the project's own agent.
// REUSE, byte-identical, no backup, tokens reported as a conflict.
// ────────────────────────────────────────────────────────────────────────────
{
const root = makeProject('b1', FOREIGN_WITH_TOKEN);
const r = emitAgent(root);
check('b1.status', r.status, 0, 'emit-agent succeeds on a foreign agent');
check('b1.stdout', r.stdout, `INTENT_GUARD: REUSE ${IG_REL}`, 'exactly one status line, and it is REUSE');
check('b1.bytes', read(root, IG_REL), FOREIGN_WITH_TOKEN, 'the hand-written file is byte-identical');
check('b1.backupCount', backups(root).length, 0, 'nothing was backed up because nothing was rewritten');
check('b1.tree', agentNames(root).join(','), 'intent-guard.toml', 'no extra file was created');
check(
'b1.conflictReported',
r.stderr.includes('{REQUEST_ID}'),
true,
'the token is reported on stderr as a conflict',
);
const root = mkdtempSync(join(tmpdir(), 'native-intent-create-'));
const result = run(root);
const target = join(root, '.codex', 'agents', 'intent-guard.toml');
check('create.exit', result.status, 0, 'first run succeeds');
check('create.verdict', result.output.trim(), 'INTENT_GUARD: CREATED .codex/agents/intent-guard.toml', 'first run reports creation');
check('create.bytes', readFileSync(target, 'utf8'), readFileSync(TEMPLATE, 'utf8'), 'created file equals shared authority byte-for-byte');
check('create.parse', parse(target).status, 0, 'created file remains structurally valid TOML');
rmSync(root, { recursive: true, force: true });
}
// ────────────────────────────────────────────────────────────────────────────
// B2 — an unstamped file WITHOUT `name: intent-guard` frontmatter is still
// foreign: unrunnable by our rules, but not ours to overwrite.
// ────────────────────────────────────────────────────────────────────────────
{
const body = '# somebody else\n\nnotes about {TICKET_ID}\n';
const root = makeProject('b2', body);
const r = emitAgent(root);
check('b2.stdout', r.stdout, `INTENT_GUARD: REUSE ${IG_REL}`, 'REUSE, not RECREATE');
check('b2.bytes', read(root, IG_REL), body, 'a foreign file without our frontmatter survives byte-identical');
check('b2.backupCount', backups(root).length, 0, 'no backup, because no write');
const root = mkdtempSync(join(tmpdir(), 'native-intent-reuse-'));
const agents = join(root, '.codex', 'agents');
mkdirSync(agents, { recursive: true });
const target = join(agents, 'intent-guard.toml');
const foreign = 'name = "intent-guard"\ndescription = "Foreign review-only agent."\ndeveloper_instructions = "Review only; preserve these bytes."\n';
writeFileSync(target, foreign);
const result = run(root);
check('reuse.exit', result.status, 0, 'valid existing native agent is reused');
check('reuse.verdict', result.output.trim(), 'INTENT_GUARD: REUSE .codex/agents/intent-guard.toml', 'reuse is explicit');
check('reuse.bytes', readFileSync(target, 'utf8'), foreign, 'reuse preserves foreign bytes');
rmSync(root, { recursive: true, force: true });
}
// ────────────────────────────────────────────────────────────────────────────
// B3 — control: the same foreign file with no token at all also REUSEs. This is
// the pre-fix behaviour and must not change.
// ────────────────────────────────────────────────────────────────────────────
{
const body = FOREIGN_WITH_TOKEN.replace('{REQUEST_ID}', 'the ticket id');
const root = makeProject('b3', body);
const r = emitAgent(root);
check('b3.stdout', r.stdout, `INTENT_GUARD: REUSE ${IG_REL}`, 'token-free foreign file reuses too');
check('b3.bytes', read(root, IG_REL), body, 'byte-identical');
check('b3.stderrEmpty', r.stderr, '', 'no conflict to report, so stderr stays silent');
for (const [name, body, reason] of [
['renamedMarkdown', '---\nname: intent-guard\n---\n', 'invalid TOML'],
['extraKey', 'name = "intent-guard"\ndescription = "Review."\ndeveloper_instructions = "Review."\nmodel = "legacy"\n', 'keys must be exactly'],
]) {
const root = mkdtempSync(join(tmpdir(), 'native-intent-' + name + '-'));
const agents = join(root, '.codex', 'agents');
mkdirSync(agents, { recursive: true });
const target = join(agents, 'intent-guard.toml');
writeFileSync(target, body);
const result = run(root);
check(name + '.exit', result.status, 1, 'invalid existing artifact fails closed');
check(name + '.reason', result.output.includes(reason), true, 'failure names the structural defect');
check(name + '.bytes', readFileSync(target, 'utf8'), body, 'failure never overwrites existing bytes');
rmSync(root, { recursive: true, force: true });
}
// ────────────────────────────────────────────────────────────────────────────
// B4 — OUR OWN stamped file with an unresolved token is BROKEN: recreated, but
// only after its bytes are copied to <path>.bak-<ts>.
// ────────────────────────────────────────────────────────────────────────────
{
const body = ['---', 'name: intent-guard', '---', '', 'half-substituted {PROJECT_NAME}', '', STAMP, ''].join('\n');
const root = makeProject('b4', body);
const r = emitAgent(root);
const bak = backups(root);
check('b4.stdout', r.stdout, `INTENT_GUARD: CREATED ${IG_REL}`, 'our own broken file is recreated');
check('b4.backupCount', bak.length, 1, 'exactly one backup was written');
check(
'b4.backupBytes',
// concatenation, not indexing: zero backups yields '' and fails the check instead of throwing
bak.map((n) => read(root, join('.codex', 'agents', n))).join(''),
body,
'the backup holds the original bytes verbatim',
);
check(
'b4.recreated',
read(root, IG_REL).includes('<!-- generated_by: brewcode:superreview-setup'),
true,
'the live file now carries the current tail anchor',
);
}
// ────────────────────────────────────────────────────────────────────────────
// B5 — an EMPTY file is BROKEN with nothing to lose: recreated, no backup.
// ────────────────────────────────────────────────────────────────────────────
{
const root = makeProject('b5', '');
const r = emitAgent(root);
check('b5.stdout', r.stdout, `INTENT_GUARD: CREATED ${IG_REL}`, 'an empty file is recreated');
check('b5.backupCount', backups(root).length, 0, 'an empty file has no bytes worth backing up');
}
// ────────────────────────────────────────────────────────────────────────────
// B6 — a pre-standard file OF OURS still MIGRATEs: metadata only, body kept.
// ────────────────────────────────────────────────────────────────────────────
{
const marker = 'TAILORED-LINE-KEEP-ME';
const body = ['---', 'name: intent-guard', '---', '', `## 1. Scope`, '', marker, '', LEGACY_STAMP, ''].join('\n');
const root = makeProject('b6', body);
const r = emitAgent(root);
check('b6.stdout', r.stdout, `INTENT_GUARD: MIGRATED ${IG_REL}`, 'the retired stamp triggers a restamp');
check('b6.bodyKept', read(root, IG_REL).includes(marker), true, 'the tailored body line survived the migration');
check('b6.backupCount', backups(root).length, 0, 'a migration rewrites metadata only, so no backup is needed');
}
// ────────────────────────────────────────────────────────────────────────────
// B7 — no file at all: CREATE, the ordinary first-run path.
// ────────────────────────────────────────────────────────────────────────────
{
const root = makeProject('b7', null);
const r = emitAgent(root);
check('b7.status', r.status, 0, 'first run succeeds');
check('b7.stdout', r.stdout, `INTENT_GUARD: CREATED ${IG_REL}`, 'the agent is created from the template');
check('b7.tree', agentNames(root).join(','), 'intent-guard.toml', 'exactly one file, no backups');
}
// ── report ──────────────────────────────────────────────────────────────────
rmSync(BASE, { recursive: true, force: true });
console.log('suite-intent-guard.mjs');
for (const line of results) console.log(line);
console.log(` ${passed} passed, ${failed} failed`);
console.log(' ' + passed + ' passed, ' + failed + ' failed');
process.exit(failed === 0 ? 0 : 1);
+25 -24
View File
@@ -77,7 +77,10 @@ function summary(stdout) {
const linesStartingWith = (stdout, prefix) =>
stdout.split('\n').filter((l) => l.startsWith(prefix));
const AGENT_BODY = (name) => `---\nname: ${name}\ndescription: fixture agent\n---\n\n# ${name}\n`;
const DOMAIN_INSTRUCTIONS = '## Mission\nOwn fixture behavior.\n\n## Owned surfaces\nFixture files.\n\n## Exclusions\nNo neighboring work.\n\n## Must-load references\n- `.codex/teams/t1/team.md`\n\n## Unique invariants\nPreserve bytes.\n\n## Unique verification\nRun the fixture suite.\n';
const AGENT_BODY = (name) => name === 'intent-guard'
? `name = "intent-guard"\ndescription = "Review-only fixture."\ndeveloper_instructions = "Review only; never implement."\n`
: `name = ${JSON.stringify(name)}\ndescription = "Domain fixture agent."\ndeveloper_instructions = ${JSON.stringify(DOMAIN_INSTRUCTIONS)}\n`;
/**
* The `## Agents` header separator, in the three spellings the parser must tell apart: the compact
@@ -93,6 +96,26 @@ const SEPARATORS = {
* A project root with one team. `rows` are `## Agents` Agent-column values, in table order;
* `agentFiles` are the names actually written to .codex/agents/.
*/
const NATIVE_TEAM_TEMPLATE = "# Team: {TEAM_NAME}\n|Field|Value|\n|---|---|\n|Created|{DATE}|\n|Version|{PLUGIN_VERSION}|\n|Content version|{CONTENT_VERSION}|\n|Generated by|brewcode:teams-setup|\n|Last update|{LAST_UPDATED}|\n|Agents|{N}|\n|Intent guard|{INTENT_GUARD_POLICY}|\n|Project|{CWD}|\n\n## Shared Agent Contract\nEvery domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.\nBefore any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.\nOptional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.\n`T=\".codex/teams/{TEAM_NAME}\"; bash \"$T/trace-ops.sh\" add \"$T\" \"$SID\" \"{AGENT_NAME}\" \"<kind>\" \"<state>\" \"<text>\"`\nTrack states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.\nA task traced `took` ends with exactly one terminal track: `completed` or `failed`.\nVerdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.\nActual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.codex/convention/*` first), additive to rules/conventions/docs, !=replace them.\n\n## Agents\n|Agent|Domain|Mission|Status|Updated|Kind|Version|\n|---|---|---|---|---|---|---|\n{INTENT_GUARD_ROW}";
function nativeTeam(root, rows, separator = 'compact') {
const intent = rows.includes('intent-guard');
const domainRows = rows.filter((name) => name !== 'intent-guard');
const intentRow = intent ? '|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|6.1.4|' : '';
const roster = rows.map((name) => name === 'intent-guard' ? intentRow : `|${name}|api|fixture mission|active|2026-08-27|domain|6.1.4|`).join('\n');
const rendered = `${NATIVE_TEAM_TEMPLATE
.replaceAll('{TEAM_NAME}', 't1')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', '6.1.4')
.replaceAll('{CONTENT_VERSION}', '6.1.0')
.replaceAll('{N}', String(domainRows.length))
.replaceAll('{CWD}', root)
.replaceAll('{INTENT_GUARD_POLICY}', intent ? 'required' : 'legacy-absent')
.replaceAll('{INTENT_GUARD_ROW}', roster)}\n`;
const separators = { compact: '|---|---|---|---|---|---|---|', padded: '| --- | --- | --- | --- | --- | --- | --- |', none: '' };
return rendered.replace('|---|---|---|---|---|---|---|', separators[separator]);
}
function makeProject(label, rows, agentFiles, separator = 'compact') {
const root = join(BASE, label, 'proj');
const teamDir = join(root, '.codex', 'teams', 't1');
@@ -101,29 +124,7 @@ function makeProject(label, rows, agentFiles, separator = 'compact') {
const rosterRows = rows
.map((a) => `| ${a} | api | fixture mission | active | 2026-08-16 | domain | 6.0.0 |`)
.join('\n');
writeFileSync(
join(teamDir, 'team.md'),
[
'# Team: t1',
'',
'| Field | Value |',
'|-------|-------|',
'| Created | 2026-08-16 |',
'| Version | 6.0.0 |',
'| Content version | 6.0.0 |',
'| Generated by | brewcode:teams-setup |',
'| Last update | 2026-08-16 |',
`| Agents | ${rows.length} |`,
`| Project | ${root} |`,
'',
'## Agents',
'',
'| Agent | Domain | Mission | Status | Updated | Kind | Version |',
SEPARATORS[separator],
rosterRows,
'',
].filter((l) => l !== null).join('\n'),
);
writeFileSync(join(teamDir, 'team.md'), nativeTeam(root, rows, separator));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
for (const f of agentFiles) writeFileSync(join(root, '.codex', 'agents', `${f}.toml`), AGENT_BODY(f));
return root;
+26 -25
View File
@@ -88,39 +88,40 @@ function verifyCounts(stdout) {
return out;
}
const AGENT_BODY = (name) => `---\nname: ${name}\ndescription: fixture agent\n---\n\n# ${name}\n`;
const FOREIGN_BODY = '---\nname: worker-one\ndescription: written by SOMEONE ELSE\n---\n\n# hands off\n';
const DOMAIN_INSTRUCTIONS = '## Mission\nOwn fixture behavior.\n\n## Owned surfaces\nFixture files.\n\n## Exclusions\nNo neighboring work.\n\n## Must-load references\n- `.codex/teams/t1/team.md`\n\n## Unique invariants\nPreserve bytes.\n\n## Unique verification\nRun the fixture suite.\n';
const AGENT_BODY = (name) => name === 'intent-guard'
? `name = "intent-guard"\ndescription = "Review-only fixture."\ndeveloper_instructions = "Review only; never implement."\n`
: `name = ${JSON.stringify(name)}\ndescription = "Domain fixture agent."\ndeveloper_instructions = ${JSON.stringify(DOMAIN_INSTRUCTIONS)}\n`;
const FOREIGN_BODY = `name = "worker-one"\ndescription = "Foreign fixture."\ndeveloper_instructions = "Foreign bytes; not team-owned."\n`;
const SEP = '|-------|--------|---------|--------|---------|------|---------|';
/** A project root with one team whose roster is `rows`; every row also gets a live agent file. */
const NATIVE_TEAM_TEMPLATE = "# Team: {TEAM_NAME}\n|Field|Value|\n|---|---|\n|Created|{DATE}|\n|Version|{PLUGIN_VERSION}|\n|Content version|{CONTENT_VERSION}|\n|Generated by|brewcode:teams-setup|\n|Last update|{LAST_UPDATED}|\n|Agents|{N}|\n|Intent guard|{INTENT_GUARD_POLICY}|\n|Project|{CWD}|\n\n## Shared Agent Contract\nEvery domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.\nBefore any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.\nOptional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.\n`T=\".codex/teams/{TEAM_NAME}\"; bash \"$T/trace-ops.sh\" add \"$T\" \"$SID\" \"{AGENT_NAME}\" \"<kind>\" \"<state>\" \"<text>\"`\nTrack states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.\nA task traced `took` ends with exactly one terminal track: `completed` or `failed`.\nVerdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.\nActual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.codex/convention/*` first), additive to rules/conventions/docs, !=replace them.\n\n## Agents\n|Agent|Domain|Mission|Status|Updated|Kind|Version|\n|---|---|---|---|---|---|---|\n{INTENT_GUARD_ROW}";
function nativeTeam(root, rows, separator = 'compact') {
const intent = rows.includes('intent-guard');
const domainRows = rows.filter((name) => name !== 'intent-guard');
const intentRow = intent ? '|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|6.1.4|' : '';
const roster = rows.map((name) => name === 'intent-guard' ? intentRow : `|${name}|api|fixture mission|active|2026-08-27|domain|6.1.4|`).join('\n');
const rendered = `${NATIVE_TEAM_TEMPLATE
.replaceAll('{TEAM_NAME}', 't1')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', '6.1.4')
.replaceAll('{CONTENT_VERSION}', '6.1.0')
.replaceAll('{N}', String(domainRows.length))
.replaceAll('{CWD}', root)
.replaceAll('{INTENT_GUARD_POLICY}', intent ? 'required' : 'legacy-absent')
.replaceAll('{INTENT_GUARD_ROW}', roster)}\n`;
const separators = { compact: '|---|---|---|---|---|---|---|', padded: '| --- | --- | --- | --- | --- | --- | --- |', none: '' };
return rendered.replace('|---|---|---|---|---|---|---|', separators[separator]);
}
function makeProject(label, rows) {
const root = join(BASE, label, 'proj');
const teamDir = join(root, '.codex', 'teams', 't1');
mkdirSync(join(root, '.codex', 'agents'), { recursive: true });
mkdirSync(teamDir, { recursive: true });
writeFileSync(
join(teamDir, 'team.md'),
[
'# Team: t1',
'',
'| Field | Value |',
'|-------|-------|',
'| Created | 2026-08-16 |',
'| Version | 6.0.0 |',
'| Content version | 6.0.0 |',
'| Generated by | brewcode:teams-setup |',
'| Last update | 2026-08-16 |',
`| Agents | ${rows.length} |`,
`| Project | ${root} |`,
'',
'## Agents',
'',
'| Agent | Domain | Mission | Status | Updated | Kind | Version |',
SEP,
...rows.map((a) => `| ${a} | api | fixture mission | active | 2026-08-16 | domain | 6.0.0 |`),
'',
].join('\n'),
);
writeFileSync(join(teamDir, 'team.md'), nativeTeam(root, rows));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
for (const a of rows) writeFileSync(join(root, '.codex', 'agents', `${a}.toml`), AGENT_BODY(a));
return root;
+448 -7
View File
@@ -28,7 +28,7 @@ const EXPLICIT_ONLY = new Set([
]);
const MANUAL_NATIVE_SKILLS = new Set([
'brewcode/convention', 'brewcode/rules', 'brewtools/manager-setup', 'brewtools/task-board-setup',
'brewcode/convention', 'brewcode/rules', 'brewcode/teams-setup', 'brewtools/manager-setup', 'brewtools/task-board-setup',
'brewtools/think-short-setup'
]);
@@ -617,6 +617,307 @@ function walkFiles(dir) {
return files;
}
function replaceMarked(text, begin, end, replacement) {
const start = text.indexOf(begin);
const finish = text.indexOf(end, start + begin.length);
if (start < 0 || finish < 0) throw new Error(`Missing generated-projection markers: ${begin} / ${end}`);
return `${text.slice(0, start)}${replacement.trimEnd()}${text.slice(finish + end.length)}`;
}
function nativeTeamAgentValidation() {
return `# BEGIN CLIENT AGENT VALIDATION
# Native Codex agents are TOML data, not renamed Markdown. Parse before contract validation.
check_native_agent() {
_f="$1"
_expected_name="$2"
_kind="$3"
python3 - "$_f" "$_expected_name" "$_kind" "$TEAM_NAME" <<'PY'
import pathlib
import re
import sys
import tomllib
path = pathlib.Path(sys.argv[1])
expected_name, kind, team = sys.argv[2:5]
try:
data = tomllib.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, tomllib.TOMLDecodeError) as exc:
print(f" FAIL: invalid TOML: {exc}")
raise SystemExit(1)
required = {"name", "description", "developer_instructions"}
if set(data) != required:
print(" FAIL: TOML keys must be exactly name, description, developer_instructions")
raise SystemExit(1)
if any(type(data[key]) is not str for key in required):
print(" FAIL: name, description, and developer_instructions must all be strings")
raise SystemExit(1)
if data["name"] != expected_name:
print(f" FAIL: TOML name {data['name']!r} must equal roster/file name {expected_name!r}")
raise SystemExit(1)
if "\\n" in data["description"]:
print(" FAIL: description must be one line")
raise SystemExit(1)
if kind == "review-only":
raise SystemExit(0)
body = data["developer_instructions"]
expected_headings = [
"Mission", "Owned surfaces", "Exclusions", "Must-load references",
"Unique invariants", "Unique verification",
]
actual_headings = re.findall(r"^#{1,6}[ ]+(.+)$", body, flags=re.MULTILINE)
if actual_headings != expected_headings:
print(" FAIL: body headings must be exactly the six ordered teams-setup headings in developer_instructions")
raise SystemExit(1)
reference = f".codex/teams/{team}/team.md"
if body.count(reference) != 1:
print(f" FAIL: Must-load references must name {reference} exactly once")
raise SystemExit(1)
must_load = body.split("## Must-load references\\n", 1)[1].split("\\n## ", 1)[0]
bullets = [line for line in must_load.splitlines() if line.startswith("- ")]
if not bullets or bullets[0] != "- " + chr(96) + reference + chr(96):
print(f" FAIL: {reference} must be the first Must-load references bullet")
raise SystemExit(1)
body_bytes = len(body.encode("utf-8"))
body_tokens = (len(body) + 3) // 4
if body_bytes > 3200 or body_tokens > 800:
print(f" FAIL: developer_instructions is {body_bytes} bytes/{body_tokens} est-tokens; ceilings are 3200 bytes and 800 ceil(chars/4) tokens")
raise SystemExit(1)
PY
}
# END CLIENT AGENT VALIDATION`;
}
function nativeTeamFixtureBlock() {
return [
'// BEGIN RUNTIME AGENT FIXTURES',
'function tomlString(value) {',
' return JSON.stringify(value);',
'}',
'',
"function agentFile({ name = 'build-eng', body = runtimeRepresentativeBody, extraField = '' } = {}) {",
' return `name = ${tomlString(name)}\\ndescription = "Domain owner. Triggers: domain, review, verification."\\ndeveloper_instructions = ${tomlString(body)}\\n${extraField}`;',
'}',
'',
'function intentGuardFile() {',
' return `name = "intent-guard"\\ndescription = "Review-only anti-drift check."\\ndeveloper_instructions = "Review only; never implement or mutate project files."\\n`;',
'}',
'// END RUNTIME AGENT FIXTURES',
].join('\n');
}
function nativeTeamSchemaFixtures() {
return [
'// BEGIN SOURCE FRONTMATTER BUDGET FIXTURE',
'{',
' const world = makeWorld({ agentText: agentFile({ extraField: \'model = "legacy"\\n\' }) });',
' const result = runVerifier(world);',
" check('verifier.exactTomlKeys.exit', result.status, 1, 'an unsupported fourth TOML key fails');",
" check('verifier.exactTomlKeys.reason', result.output.includes('TOML keys must be exactly name, description, developer_instructions'), true,",
" 'the verifier enforces the exact native schema structurally');",
' removeWorld(world);',
'}',
'',
'{',
" const world = makeWorld({ agentText: '---\\nname: build-eng\\n---\\n' });",
' const result = runVerifier(world);',
" check('verifier.renamedMarkdown.exit', result.status, 1, 'renamed Markdown is not accepted as TOML');",
" check('verifier.renamedMarkdown.reason', result.output.includes('invalid TOML'), true,",
" 'the verifier parses the native fixture instead of scanning YAML text');",
' removeWorld(world);',
'}',
'// END SOURCE FRONTMATTER BUDGET FIXTURE',
].join('\n');
}
function nativeLifecycleAgentFixture() {
return [
"const DOMAIN_INSTRUCTIONS = '## Mission\\nOwn fixture behavior.\\n\\n## Owned surfaces\\nFixture files.\\n\\n## Exclusions\\nNo neighboring work.\\n\\n## Must-load references\\n- `.codex/teams/t1/team.md`\\n\\n## Unique invariants\\nPreserve bytes.\\n\\n## Unique verification\\nRun the fixture suite.\\n';",
'const AGENT_BODY = (name) => name === \'intent-guard\'',
' ? `name = "intent-guard"\\ndescription = "Review-only fixture."\\ndeveloper_instructions = "Review only; never implement."\\n`',
' : `name = ${JSON.stringify(name)}\\ndescription = "Domain fixture agent."\\ndeveloper_instructions = ${JSON.stringify(DOMAIN_INSTRUCTIONS)}\\n`;',
].join('\n');
}
function nativeLifecycleTeamHelper(teamTemplate) {
return [
`const NATIVE_TEAM_TEMPLATE = ${JSON.stringify(teamTemplate)};`,
"function nativeTeam(root, rows, separator = 'compact') {",
" const intent = rows.includes('intent-guard');",
" const domainRows = rows.filter((name) => name !== 'intent-guard');",
" const intentRow = intent ? '|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|6.1.4|' : '';",
" const roster = rows.map((name) => name === 'intent-guard' ? intentRow : `|${name}|api|fixture mission|active|2026-08-27|domain|6.1.4|`).join('\\n');",
' const rendered = `${NATIVE_TEAM_TEMPLATE',
" .replaceAll('{TEAM_NAME}', 't1')",
" .replaceAll('{DATE}', '2026-08-27')",
" .replaceAll('{LAST_UPDATED}', '2026-08-27')",
" .replaceAll('{PLUGIN_VERSION}', '6.1.4')",
" .replaceAll('{CONTENT_VERSION}', '6.1.0')",
" .replaceAll('{N}', String(domainRows.length))",
" .replaceAll('{CWD}', root)",
" .replaceAll('{INTENT_GUARD_POLICY}', intent ? 'required' : 'legacy-absent')",
" .replaceAll('{INTENT_GUARD_ROW}', roster)}\\n`;",
" const separators = { compact: '|---|---|---|---|---|---|---|', padded: '| --- | --- | --- | --- | --- | --- | --- |', none: '' };",
" return rendered.replace('|---|---|---|---|---|---|---|', separators[separator]);",
'}',
].join('\n');
}
function rewriteNativeLifecycleSuite(value, teamTemplate) {
const teamWriter = /writeFileSync\(\s*join\(teamDir, 'team\.md'\),[\s\S]*?\n \);/;
if (!teamWriter.test(value)) throw new Error('native lifecycle fixture team writer not found');
value = value.replace(/const AGENT_BODY = \(name\) => .*?;\n/, `${nativeLifecycleAgentFixture()}\n`);
value = value.replace('function makeProject(', `${nativeLifecycleTeamHelper(teamTemplate)}\n\nfunction makeProject(`);
value = value.replace(teamWriter, "writeFileSync(join(teamDir, 'team.md'), nativeTeam(root, rows));");
value = value.replace(
/const FOREIGN_BODY = .*?;\n/,
'const FOREIGN_BODY = `name = "worker-one"\\ndescription = "Foreign fixture."\\ndeveloper_instructions = "Foreign bytes; not team-owned."\\n`;\n'
);
return value;
}
function nativeIntentGuardSuite() {
return `#!/usr/bin/env node
import { spawnSync } from 'node:child_process';
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { fileURLToPath } from 'node:url';
const HERE = join(fileURLToPath(import.meta.url), '..');
const EMIT = join(HERE, '..', '..', 'superreview-setup', 'scripts', 'emit-intent-guard.sh');
const TEMPLATE = join(HERE, '..', '..', 'superreview-setup', 'references', 'intent-guard.toml.template');
let passed = 0;
let failed = 0;
const results = [];
function check(name, actual, expected, description) {
if (actual === expected) {
passed += 1;
results.push(' PASS ' + name + ' (' + description + ')');
} else {
failed += 1;
results.push(' FAIL ' + name + ' (' + description + ' | actual=' + JSON.stringify(actual) + ' expected=' + JSON.stringify(expected) + ')');
}
}
function run(root) {
const result = spawnSync('bash', [EMIT, root], { encoding: 'utf8', timeout: 30000 });
return { status: result.status, output: (result.stdout || '') + (result.stderr || '') };
}
function parse(path) {
const result = spawnSync('python3', ['-c', 'import json,pathlib,sys,tomllib; print(json.dumps(tomllib.loads(pathlib.Path(sys.argv[1]).read_text()), sort_keys=True))', path], { encoding: 'utf8' });
return { status: result.status, data: result.status === 0 ? JSON.parse(result.stdout) : null };
}
const template = parse(TEMPLATE);
check('template.parse', template.status, 0, 'shared native template is valid TOML');
check('template.keys', Object.keys(template.data).sort().join(','), 'description,developer_instructions,name', 'template has exactly three keys');
check('template.name', template.data.name, 'intent-guard', 'template name is fixed');
{
const root = mkdtempSync(join(tmpdir(), 'native-intent-create-'));
const result = run(root);
const target = join(root, '.codex', 'agents', 'intent-guard.toml');
check('create.exit', result.status, 0, 'first run succeeds');
check('create.verdict', result.output.trim(), 'INTENT_GUARD: CREATED .codex/agents/intent-guard.toml', 'first run reports creation');
check('create.bytes', readFileSync(target, 'utf8'), readFileSync(TEMPLATE, 'utf8'), 'created file equals shared authority byte-for-byte');
check('create.parse', parse(target).status, 0, 'created file remains structurally valid TOML');
rmSync(root, { recursive: true, force: true });
}
{
const root = mkdtempSync(join(tmpdir(), 'native-intent-reuse-'));
const agents = join(root, '.codex', 'agents');
mkdirSync(agents, { recursive: true });
const target = join(agents, 'intent-guard.toml');
const foreign = 'name = "intent-guard"\\ndescription = "Foreign review-only agent."\\ndeveloper_instructions = "Review only; preserve these bytes."\\n';
writeFileSync(target, foreign);
const result = run(root);
check('reuse.exit', result.status, 0, 'valid existing native agent is reused');
check('reuse.verdict', result.output.trim(), 'INTENT_GUARD: REUSE .codex/agents/intent-guard.toml', 'reuse is explicit');
check('reuse.bytes', readFileSync(target, 'utf8'), foreign, 'reuse preserves foreign bytes');
rmSync(root, { recursive: true, force: true });
}
for (const [name, body, reason] of [
['renamedMarkdown', '---\\nname: intent-guard\\n---\\n', 'invalid TOML'],
['extraKey', 'name = "intent-guard"\\ndescription = "Review."\\ndeveloper_instructions = "Review."\\nmodel = "legacy"\\n', 'keys must be exactly'],
]) {
const root = mkdtempSync(join(tmpdir(), 'native-intent-' + name + '-'));
const agents = join(root, '.codex', 'agents');
mkdirSync(agents, { recursive: true });
const target = join(agents, 'intent-guard.toml');
writeFileSync(target, body);
const result = run(root);
check(name + '.exit', result.status, 1, 'invalid existing artifact fails closed');
check(name + '.reason', result.output.includes(reason), true, 'failure names the structural defect');
check(name + '.bytes', readFileSync(target, 'utf8'), body, 'failure never overwrites existing bytes');
rmSync(root, { recursive: true, force: true });
}
console.log('suite-intent-guard.mjs');
for (const line of results) console.log(line);
console.log(' ' + passed + ' passed, ' + failed + ' failed');
process.exit(failed === 0 ? 0 : 1);
`;
}
function nativeTeamsWorkflow(sourceBody) {
const marker = sourceBody.match(/<!-- brewcode-meta: version=[^>]+-->/)?.[0];
if (!marker) throw new Error('teams-setup source is missing brewcode-meta marker');
return [
marker,
'',
'## Native authority',
'',
'Manage persistent project teams under `.codex/teams/{TEAM_NAME}/` and domain agents under `.codex/agents/`. Agent files are real TOML parsed with Python `tomllib`; never rename Markdown/YAML agents to `.toml`. Each team agent has exactly three top-level string keys: `name`, `description`, `developer_instructions`.',
'',
'Resolve one mode: `status`, `install`, `upgrade`, `enable`, `disable`, `uninstall`, or `purge`. Read applicable `AGENTS.md`, inspect existing teams and agents, preserve unrelated files, and use only scripts/references shipped beside this skill. Never edit installed caches.',
'',
'### C2.6: Shared Contract Bootstrap',
'',
'Bootstrap happens before any team-owned `.codex/agents/{name}.toml` is written: instantiate the fenced template from `references/framework-files.md` and write `team.md` at `.codex/teams/{TEAM_NAME}/team.md` with metadata, `## Shared Agent Contract`, explicit `Intent guard` policy, and zero domain rows. Do not add domain-agent rows yet. Copy the project-local tracer, initialize trace storage, substitute every placeholder, then run `scripts/verify-team.sh`. **STOP on any failure. Do not spawn or write an agent.**',
'',
'### C3: Agent Creation',
'',
'Create each approved domain `.codex/agents/{name}.toml` from `references/agent-template.md`. Parse it structurally with `tomllib` and require only `name`, `description`, and `developer_instructions`. The `developer_instructions` value uses exactly these ordered headings and no others: `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification`. Its first must-load item is exactly `.codex/teams/{TEAM_NAME}/team.md`, occurring once. Enforce <=3200 UTF-8 bytes and `ceil(chars/4) <=800` over `developer_instructions` itself.',
'',
'`intent-guard` is exempt from the six-heading domain profile. Under `required`, run `<plugin-root>/skills/superreview-setup/scripts/emit-intent-guard.sh <project-root>`; that sole shared writer create-only copies its native authority, structurally validates it, and never overwrites an existing file. Never ask agent-creator to write it. Under `legacy-absent`, create no row and no role.',
'',
'### C4: Roster Finalization',
'',
'After all intended agents validate, write the final roster. Declared `Agents` equals the number of unique domain rows; duplicate names fail. a new team defaults to `required`. Policy `required` has exactly one `intent-guard` row with fixed cells `--`, `Anti-drift check: what was ASKED vs what was DELIVERED`, `active`, team `Last update`, `review-only`, team `Version`. Policy `legacy-absent` has zero rows. the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters; `ceil(chars/4) <=700` estimated tokens. Measure the full substituted file, not the empty template.',
'',
'### C8: Fix',
'',
'Repair only failed owned artifacts. Domain agents come from `<skill-directory>/references/agent-template.md`; repair the shared contract before an agent rewrite. Preserve foreign agents and unrelated work. Re-run structural TOML, roster, policy, size, and shared-contract checks.',
'',
'### C9: Re-verify',
'',
'Run `scripts/verify-team.sh {TEAM_NAME}`, both test runners, and compatibility validation. Hard-gate `developer_instructions` only: <=3200 bytes and `ceil(chars/4) <=800`; `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification` in order with no other headings. `intent-guard` is exempt from this six-heading gate, not structural TOML validation.',
'',
'> To skip review pipeline is not an acceptance path; unresolved checks remain failures.',
'',
'### U1b: Shared Contract Migration Gate',
'',
'On upgrade, insert the canonical block before `## Agents` and validate it before touching agents. Record an existing intent-guard roster row -> `required`; no row -> `legacy-absent`. Never synthesize the row on the latter path. Legacy agent bodies remain byte-identical during this gate. **No agent may be tuned, regenerated, stripped, or reformatted until the shared contract passes.** absence migrates',
'to `legacy-absent`; `legacy-absent` forbids that row and MUST NOT add the role during upgrade.',
'',
'### U2: Analyze Performance',
'',
'Use trace evidence only to decide whether a domain profile needs role-specific adjustment. Never duplicate the shared contract.',
'',
'### U4: Apply Changes',
'',
'Convert every touched Codex domain agent to the exact three-key TOML contract and six-heading `developer_instructions` shape. Parse before replacement, write atomically, parse again, and preserve untouched agents byte-identical.',
'',
'For `enable` and `disable`, use `scripts/toggle-team.sh`; it parks/restores domain `.toml` files byte-identically and never parks `intent-guard`. For `uninstall` and `purge`, follow the shipped cleanup flow and explicit confirmation gates. Every mode ends with `verify-team.sh` and reports exact paths, counts, and failures.',
].join('\n');
}
// Pip pins parsed out of a skill's check_deps.sh `pip_spec` case arms.
// The Codex variant of that script cannot be a verbatim copy (the source uses floating
// `brew install` and an expanded `pip install "${specs[@]}"`, both rejected by
@@ -633,6 +934,13 @@ function sourcePipPins(sourceDir, required) {
}
function generateSpecialResources(plugin, skill, sourceDir, targetDir) {
if (plugin === 'brewcode' && skill === 'superreview-setup') {
writeFile(path.join(targetDir, 'references', 'intent-guard.toml.template'), `name = "intent-guard"
description = "Review-only anti-drift check comparing requested and delivered scope."
developer_instructions = "Review only. Compare what was requested with what was delivered, report concrete drift with file:line evidence, and never implement or mutate project files."
`);
}
if (plugin === 'brewcode' && skill === 'rules') {
writeFile(path.join(targetDir, 'README.md'), `# Rules for Codex
@@ -1003,12 +1311,99 @@ This template never applies to \`intent-guard\`. Its sole writer remains the sha
(whole, stem, escape) => (KEEP_MD.test(stem) ? whole : `${stem}${escape}.toml`)
));
}
writeFile(path.join(targetDir, '..', 'superreview-setup', 'scripts', 'emit-intent-guard.sh'), [
'#!/usr/bin/env bash',
'set -euo pipefail',
'root="${1:-}"',
'test -n "$root" || { echo "usage: emit-intent-guard.sh <project-root>" >&2; exit 2; }',
'SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"',
'template="$SCRIPT_DIR/../references/intent-guard.toml.template"',
'agents="$root/.codex/agents"',
'target="$agents/intent-guard.toml"',
'',
'validate() {',
' python3 - "$1" <<\'PY\'',
'import pathlib, sys, tomllib',
'path = pathlib.Path(sys.argv[1])',
'try:',
' data = tomllib.loads(path.read_text(encoding="utf-8"))',
'except (OSError, UnicodeError, tomllib.TOMLDecodeError) as exc:',
' print(f"invalid TOML: {exc}", file=sys.stderr)',
' raise SystemExit(1)',
'required = {"name", "description", "developer_instructions"}',
'if set(data) != required:',
' print("TOML keys must be exactly name, description, developer_instructions", file=sys.stderr)',
' raise SystemExit(1)',
'if any(type(data[key]) is not str for key in required) or data["name"] != "intent-guard":',
' print("intent-guard native fields must be strings and name must be fixed", file=sys.stderr)',
' raise SystemExit(1)',
'PY',
'}',
'',
'validate "$template"',
'if [ -f "$target" ]; then',
' validate "$target"',
' echo "INTENT_GUARD: REUSE .codex/agents/intent-guard.toml"',
' exit 0',
'fi',
'mkdir -p "$agents"',
'tmp="$(mktemp "$agents/.intent-guard.XXXXXX")"',
'trap \'rm -f "$tmp"\' EXIT HUP INT TERM',
'cp "$template" "$tmp"',
'validate "$tmp"',
'mv "$tmp" "$target"',
'trap - EXIT HUP INT TERM',
'echo "INTENT_GUARD: CREATED .codex/agents/intent-guard.toml"',
].join('\n'), 0o755);
writeFile(path.join(targetDir, 'tests', 'suite-intent-guard.mjs'), nativeIntentGuardSuite(), 0o755);
const nativeFramework = fs.readFileSync(path.join(targetDir, 'references', 'framework-files.md'), 'utf8');
const nativeTeamMatch = nativeFramework.match(/## team\.md\n\n```markdown\n([\s\S]*?)\n```/);
if (!nativeTeamMatch) throw new Error('native teams framework is missing fenced team.md template');
for (const name of ['suite-lifecycle.mjs', 'suite-parked-conflict.mjs']) {
const file = path.join(targetDir, 'tests', name);
let value = rewriteNativeLifecycleSuite(fs.readFileSync(file, 'utf8'), nativeTeamMatch[1]);
if (name === 'suite-lifecycle.mjs') value = value.replace('nativeTeam(root, rows)', 'nativeTeam(root, rows, separator)');
writeFile(file, value, 0o755);
}
// The canonical Codex tree keeps its manifest at `.codex/package/plugin.json`, while the
// installed distribution exposes `.codex-plugin/plugin.json`. Make the verifier runnable in
// both layouts and keep its isolated regression suite anchored to the canonical manifest.
const verifier = path.join(targetDir, 'scripts', 'verify-team.sh');
writeFile(verifier, fs.readFileSync(verifier, 'utf8').replace(
let verifierText = fs.readFileSync(verifier, 'utf8');
verifierText = replaceMarked(
verifierText,
'# BEGIN CLIENT AGENT VALIDATION',
'# END CLIENT AGENT VALIDATION',
nativeTeamAgentValidation()
);
verifierText = replaceMarked(
verifierText,
'# BEGIN LIVE CLIENT AGENT CHECK',
'# END LIVE CLIENT AGENT CHECK',
`# BEGIN LIVE CLIENT AGENT CHECK
native_kind=domain
[ "$agent" = "intent-guard" ] && native_kind=review-only
set +e
native_out=$(check_native_agent ".codex/agents/\${agent}.toml" "$agent" "$native_kind")
native_rc=$?
set -e
if [ "$native_rc" -eq 0 ]; then
echo "OK"
if [ "$native_kind" = "domain" ] && [ "$shared_contract_present" -ne 1 ]; then
echo " CHECK: compact six-heading profile ... FAIL (shared team contract missing; interrupted install/unsafe migration)"
FAIL=1
elif [ "$native_kind" = "domain" ]; then
echo " CHECK: structurally parsed six-heading developer_instructions ... OK"
fi
else
echo "FAIL"
printf '%s\n' "$native_out"
FAIL=1
fi
# END LIVE CLIENT AGENT CHECK`
);
verifierText = verifierText.replace(
'PLUGIN_JSON="$SCRIPT_DIR/../../../.codex-plugin/plugin.json"',
'PLUGIN_JSON="$SCRIPT_DIR/../../../.codex-plugin/plugin.json"\n[ -f "$PLUGIN_JSON" ] || PLUGIN_JSON="$SCRIPT_DIR/../../../package/plugin.json"'
).replace(
@@ -1020,7 +1415,8 @@ case "$PV" in
*) printf 'ERROR:cannot resolve source plugin version (X.Y.Z) from %s\\n' "$SCRIPT_DIR/../SKILL.md"; exit 1 ;;
esac
TODAY=$(date +%F)`
), 0o755);
).replaceAll('frontmatter', 'TOML agent schema');
writeFile(verifier, verifierText, 0o755);
const detector = path.join(targetDir, 'scripts', 'detect-mode.sh');
writeFile(detector, fs.readFileSync(detector, 'utf8').replace(
'esac\n\n# content_version self-location:',
@@ -1034,7 +1430,7 @@ esac
# content_version self-location:`
), 0o755);
const profileSuite = path.join(targetDir, 'tests', 'suite-agent-profile-contract.mjs');
writeFile(profileSuite, fs.readFileSync(profileSuite, 'utf8')
let profileText = fs.readFileSync(profileSuite, 'utf8')
.replace(
"const canonicalSkillPath = join(repo, 'brewcode', 'skills', 'teams-setup', 'SKILL.md');",
"const canonicalSkillPath = join(repo, 'brewcode', '.codex', 'skills', 'teams-setup', 'SKILL.md');"
@@ -1058,11 +1454,54 @@ esac
"const pluginVersion = (/brewcode-meta: version=([0-9]+\\.[0-9]+\\.[0-9]+)/.exec(canonicalSkill) || [])[1];"
)
.replace('return `${canonicalTeam', 'return `${projectedTeam')
.replace('function agentFile({ body = representativeBody,', 'function agentFile({ body = runtimeRepresentativeBody,')
.replace('return instantiateTeamTemplate(canonicalTeam', 'return instantiateTeamTemplate(projectedTeam')
.replace('const oversized = `${representativeBody}', 'const oversized = `${runtimeRepresentativeBody}')
.replace('mutate(representativeBody)', 'mutate(runtimeRepresentativeBody)')
.replaceAll('join(world, SOURCE_CLIENT_DIR', "join(world, '.codex'")
.replaceAll("'build-eng.md'", "'build-eng.toml'"), 0o755);
.replaceAll('`${name}.md`', '`${name}.toml`')
.replaceAll("'build-eng.md'", "'build-eng.toml'")
.replace(
"result.output.includes('ceiling is 3200 (~800 est-tokens), frontmatter excluded')",
"result.output.includes('ceilings are 3200 bytes and 800 ceil(chars/4) tokens')"
)
.replace('an oversized body fails even with small frontmatter',
'an oversized developer_instructions value fails')
.replace('body only (frontmatter excluded): <=3200 bytes',
'`developer_instructions` only: <=3200 bytes')
.replace('a fully legacy team remains runnable while upgrade is required',
'a structurally parsed native agent without six headings fails')
.replace("check('verifier.legacyMigrationSafe.exit', result.status, 0,",
"check('verifier.legacyMigrationSafe.exit', result.status, 1,")
.replace(
"result.output.includes('has no Shared Agent Contract (legacy team)')\n && result.output.includes('legacy repeated/unknown profile shape')",
"result.output.includes('body headings must be exactly the six ordered teams-setup headings in developer_instructions')"
);
profileText = replaceMarked(
profileText,
'// BEGIN RUNTIME AGENT FIXTURES',
'// END RUNTIME AGENT FIXTURES',
nativeTeamFixtureBlock()
);
profileText = replaceMarked(
profileText,
'// BEGIN SOURCE FRONTMATTER BUDGET FIXTURE',
'// END SOURCE FRONTMATTER BUDGET FIXTURE',
nativeTeamSchemaFixtures()
);
profileText = profileText.replace(
"console.log('suite-agent-profile-contract.mjs');",
`const nativeVerifier = readFileSync(verifierPath, 'utf8');
check('codex.verifier.tomllib', nativeVerifier.includes('import tomllib'), true,
'native verifier parses TOML structurally');
check('codex.verifier.noYamlParser', nativeVerifier.includes('NR == 1 && $0 == "---"'), false,
'native verifier has no YAML fence parser');
check('codex.verifier.exactKeys',
nativeVerifier.includes('required = {"name", "description", "developer_instructions"}'), true,
'native verifier pins the exact supported top-level schema');
console.log('suite-agent-profile-contract.mjs');`
);
writeFile(profileSuite, profileText, 0o755);
}
if (plugin === 'brewtools' && (skill === 'deploy' || skill === 'ssh')) {
@@ -1118,7 +1557,9 @@ function generateSkill(plugin, skill) {
fs.mkdirSync(targetDir, { recursive: true });
if (special) {
copyTransformedTree(sourceDir, targetDir);
const workflow = MANUAL_NATIVE_SKILLS.has(`${plugin}/${skill}`) ? '' : `
const workflow = plugin === 'brewcode' && skill === 'teams-setup'
? `\n${nativeTeamsWorkflow(body)}\n`
: MANUAL_NATIVE_SKILLS.has(`${plugin}/${skill}`) ? '' : `
## Complete native workflow
Follow every phase below. When a phase delegates work, use Codex collaboration with only \`task_name\` and \`message\`; treat each "Codex delegation brief" block as role and message content, not executable syntax. Use \`request_user_input\` for the documented user gates. Resolve \`<skill-directory>\`, \`<plugin-root>\`, \`<project-root>\`, and \`<arguments>\` before running commands.
+1 -1
View File
@@ -17,7 +17,7 @@ const EXPECTED_SKILLS = {
// supports in its source `argument-hint`; the Codex variant must document each one.
const CANONICAL_MODES = ['status', 'install', 'upgrade', 'enable', 'disable', 'uninstall', 'purge'];
const MANUAL_NATIVE_SKILLS = new Set([
'brewcode/convention', 'brewcode/rules', 'brewtools/manager-setup', 'brewtools/task-board-setup',
'brewcode/convention', 'brewcode/rules', 'brewcode/teams-setup', 'brewtools/manager-setup', 'brewtools/task-board-setup',
'brewtools/think-short-setup'
]);
const errors = [];
@@ -0,0 +1,3 @@
name = "intent-guard"
description = "Review-only anti-drift check comparing requested and delivered scope."
developer_instructions = "Review only. Compare what was requested with what was delivered, report concrete drift with file:line evidence, and never implement or mutate project files."
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -euo pipefail
root="${1:-}"
test -n "$root" || { echo "usage: emit-intent-guard.sh <project-root>" >&2; exit 2; }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
template="$SCRIPT_DIR/../references/intent-guard.toml.template"
agents="$root/.codex/agents"
target="$agents/intent-guard.toml"
validate() {
python3 - "$1" <<'PY'
import pathlib, sys, tomllib
path = pathlib.Path(sys.argv[1])
try:
data = tomllib.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, tomllib.TOMLDecodeError) as exc:
print(f"invalid TOML: {exc}", file=sys.stderr)
raise SystemExit(1)
required = {"name", "description", "developer_instructions"}
if set(data) != required:
print("TOML keys must be exactly name, description, developer_instructions", file=sys.stderr)
raise SystemExit(1)
if any(type(data[key]) is not str for key in required) or data["name"] != "intent-guard":
print("intent-guard native fields must be strings and name must be fixed", file=sys.stderr)
raise SystemExit(1)
PY
}
validate "$template"
if [ -f "$target" ]; then
validate "$target"
echo "INTENT_GUARD: REUSE .codex/agents/intent-guard.toml"
exit 0
fi
mkdir -p "$agents"
tmp="$(mktemp "$agents/.intent-guard.XXXXXX")"
trap 'rm -f "$tmp"' EXIT HUP INT TERM
cp "$template" "$tmp"
validate "$tmp"
mv "$tmp" "$target"
trap - EXIT HUP INT TERM
echo "INTENT_GUARD: CREATED .codex/agents/intent-guard.toml"
+42 -19
View File
@@ -1,6 +1,6 @@
# Teams
Create and manage dynamic teams of domain-specific agents with a tracking framework. Analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking. Every team also gets one fixed review-only member, `intent-guard`.
Create and manage dynamic teams of domain-specific agents with a tracking framework. The skill analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking. A new team also gets exactly one review-only `intent-guard`; an upgraded legacy team with none stays that way.
## Quick Start
@@ -28,7 +28,7 @@ The verb always comes first and the optional `<name>` after it. That parser guar
`disable` is a rename, not a deletion — the roster rows stay in `team.md` with `Status: disabled`, and `verify-team.sh` reports `DISABLED` per parked member and still exits PASS. `enable` puts it all back. Both take effect for the NEXT session: agent discovery is read at session start.
`purge` keeps exactly one thing: `.codex/agents/intent-guard.toml`, shared with `$brewcode:superreview-setup`. It removes both `<agent>.toml` and `<agent>.toml.disabled`, so purging a disabled team leaves nothing behind.
`purge` removes both `<agent>.toml` and `<agent>.toml.disabled`, so purging a disabled team leaves no owned domain profile behind. When `Intent guard` is `required`, it keeps `.codex/agents/intent-guard.toml` because that file is shared with `$brewcode:superreview-setup`; `legacy-absent` has no guard to keep.
## Examples
@@ -83,7 +83,7 @@ After `$brewcode:teams-setup install my-team`:
agents/
agent-one.md # Domain agents (5-20 depending on variant)
agent-two.md
intent-guard.toml # Fixed review-only member, every team, not counted
intent-guard.toml # One review-only member for policy `required`; not counted
teams/
my-team/
team.md # Roster: agent list, domains, missions, status
@@ -91,11 +91,20 @@ After `$brewcode:teams-setup install my-team`:
trace-ops.sh # Tracer, copied from the plugin at install -- agents call THIS path
```
`team.md` stores logical `intent_guard_policy=required|legacy-absent` in its `Intent guard` field.
`required` means the roster contains exactly one `intent-guard` row. `legacy-absent` means it contains
zero such rows; upgrade preserves that state and never creates the role. New installs default to
`required`.
Codex domain profiles are Markdown files under `.codex/agents/`. The Codex projection uses native
TOML files under `.codex/agents/`; it carries no YAML-in-TOML guidance.
## How Agents Work
Created agents follow the **sub-agent task Acceptance Protocol** -- they self-select tasks based on domain fit, record acceptance/refusal in `trace.jsonl`, and log issues and insights as they work.
Every generated domain agent is also born with a **Return Contract**: verdict first, <=30 lines, `path:line`, no file bodies, no command output, no logs, no preamble -- bulk material goes to `.codex/reports/` and only the path comes back. It holds whether or not `$brewtools:agent-return-setup` is installed; the guard only adds mechanical thresholds. `verify-team.sh` warns on an older agent that lacks the section, and `upgrade` re-adds it.
Created agents load `team.md`, whose single **Shared Agent Contract** owns acceptance, routing, tracing,
return, scope-fit and colleague rules. Domain profiles do not repeat those contracts. Their bodies have
exactly six ordered headings: `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique
invariants`, and `Unique verification`.
They write through the project-local copy of the tracer:
@@ -125,7 +134,7 @@ $brewcode:teams-setup install my-project
|
v
[C2] Team Proposal ------ 3 variants + user confirmation
(+ intent-guard, fixed, not counted)
(+ one intent-guard for new teams, not counted)
|
v
[C2.5] Model Selection -- high-reasoning model / balanced model / fast model / mixed (domain agents only)
@@ -134,7 +143,7 @@ $brewcode:teams-setup install my-project
[C3] Agent Creation ----- agent-creator x N (batches of 3-4)
|
v
[C3-IG] intent-guard ---- generate.sh emit-agent (create or reuse), then adapt if created
[C3-IG] intent-guard ---- required: emit/reuse; legacy-absent: do nothing
|
v
[C4] Framework Setup ---- team.md + trace.jsonl + trace-ops.sh + verification
@@ -171,22 +180,32 @@ After agent creation, a quality pipeline validates the team:
> Skip with `--skip-review`. Run separately: `$brewcode:teams-setup upgrade <name> --review`
> `intent-guard` is never used as a reviewer in this pipeline, and it is judged by different criteria than domain agents: placeholders resolved, template header stripped, frontmatter untouched (short review-only description, read-only tools). "Missing domain sections" is a false positive for it.
> When policy is `required`, `intent-guard` is not a reviewer in this pipeline and is judged by its own
> review-only contract. The six-heading domain-profile gate does not apply to it. Under `legacy-absent`,
> there is no guard to review.
## intent-guard (always in the team)
## intent-guard policy
Every team gets `intent-guard` in addition to its domain agents. It is an **anti-drift check**: it compares what was **ASKED** (the original request, ticket, spec, plan, project policy) against what was **DELIVERED**, and reports the delta.
`team.md` has exactly one `Intent guard` policy field:
| Policy | Roster contract | Upgrade behavior |
|--------|-----------------|------------------|
| `required` | Exactly one review-only `intent-guard` row, outside the domain-agent count | Preserve the row; never duplicate it |
| `legacy-absent` | Zero `intent-guard` rows | Preserve absence; never create the role |
New installs use `required`. The role is an **anti-drift check**: it compares what was **ASKED** (the
original request, ticket, spec, plan, project policy) against what was **DELIVERED**, and reports the delta.
| Property | Value |
|----------|-------|
| Counted in the 5 / 10-12 / 15-20 roster? | No -- it is outside the domain-agent count and cannot be dropped |
| Counted in the 5 / 10-12 / 15-20 roster? | No -- when required, it is outside the domain-agent count |
| Tools | Read-only (`Read`, `Glob`, `Grep`, `Bash`). Never edits, builds, or runs tests |
| Model | `balanced model`, fixed by its template -- not affected by the C2.5 model choice |
| Invocation | Explicit, by name, during review only -- never during development, never an implementation owner |
| Source | Emitted by `skills/superreview-setup/scripts/generate.sh emit-agent` from the shared template -- the single writer of this file, used by both skills |
| Output | Verdict `ALIGNED` / `MINOR DRIFT` / `MAJOR DRIFT` plus <=10 findings, each with ASKED / SOURCE+tier / DELIVERED evidence / severity / minimal correction |
**Single writer (idempotent):** `teams` never authors this file. It runs
**Single writer (idempotent, `required` only):** `teams` never authors this file. It runs
`superreview-setup/scripts/generate.sh emit-agent`, which creates it from the shared template or reuses an
existing one and prints `INTENT_GUARD: CREATED|REUSE|MIGRATED <path>`. On `REUSE` -- typically because
`$brewcode:superreview-setup` ran first -- the file is left exactly as is and only the `team.md` roster row is
@@ -196,14 +215,16 @@ invariants, drift examples, evidence commands) and touches nothing else -- front
as emitted. Both skills therefore converge on one shared file produced by one pipeline, never two
variants.
`intent-guard` is also excluded from `upgrade` and `uninstall` agent pruning (enforced in the cleanup flow
itself, Step 3, including a refusal if it is named explicitly): it does not write trace entries, so zero
activity is its normal state, not a reason to delete it. Teams created before `intent-guard` existed are
not broken by this -- `verify-team.sh` only WARNs, with the command to add it.
When policy is `required`, `intent-guard` is excluded from `upgrade` and `uninstall` pruning. It does not
write trace entries, so zero activity is normal. Teams created before the role existed can be upgraded
without it: the migration writes `legacy-absent`, retains zero rows, and does not emit a profile.
Project Dusk is the compatibility baseline for this path: its roster stays at 13 members;
`task-tracker` remains a non-member owner, and `Intent guard: legacy-absent` keeps `intent-guard` absent.
## sub-agent task Acceptance Protocol
Each agent follows a 3-step self-selection before accepting a task:
The shared contract in `team.md` gives every domain agent the same 3-step self-selection before accepting a task:
| # | Check | Question | If No |
|---|-------|----------|-------|
@@ -228,7 +249,9 @@ When other skills (convention, superreview, e2e) spawn agents, they check for te
> If a team agent refuses a task (sub-agent task Acceptance Protocol), the skill re-delegates to the next priority level. Max 2 retries before falling back to system agents.
> `intent-guard` is outside this resolution chain -- it is never selected as an implementation or review owner by domain fit. It runs only when a review flow invokes it explicitly by name.
> Under `required`, `intent-guard` is outside this resolution chain -- it is never selected as an
> implementation or review owner by domain fit and runs only when a review flow invokes it explicitly.
> Under `legacy-absent`, there is no role to resolve.
## Related Skills
+18 -885
View File
@@ -7,916 +7,49 @@ description: "Creates and manages dynamic teams of domain agents. Triggers: crea
Use collaboration agents only when the user or project instructions explicitly request a team. Split work into bounded independent tasks, keep one owner per file or surface, exchange evidence through collaboration messages, and synthesize results in the parent session. Do not invent unsupported agent parameters or create persistent team configuration unless requested.
## Complete native workflow
Follow every phase below. When a phase delegates work, use Codex collaboration with only `task_name` and `message`; treat each "Codex delegation brief" block as role and message content, not executable syntax. Use `request_user_input` for the documented user gates. Resolve `<skill-directory>`, `<plugin-root>`, `<project-root>`, and `<arguments>` before running commands.
<!-- brewcode-meta: version=6.1.4 content_version=6.1.0 generated_by=brewcode:teams-setup -->
<instructions>
## Native authority
# Teams
Manage persistent project teams under `.codex/teams/{TEAM_NAME}/` and domain agents under `.codex/agents/`. Agent files are real TOML parsed with Python `tomllib`; never rename Markdown/YAML agents to `.toml`. Each team agent has exactly three top-level string keys: `name`, `description`, `developer_instructions`.
Manage dynamic teams of domain-specific agents with tracking framework.
Resolve one mode: `status`, `install`, `upgrade`, `enable`, `disable`, `uninstall`, or `purge`. Read applicable `AGENTS.md`, inspect existing teams and agents, preserve unrelated files, and use only scripts/references shipped beside this skill. Never edit installed caches.
**Arguments:** `<arguments>`
### C2.6: Shared Contract Bootstrap
---
Bootstrap happens before any team-owned `.codex/agents/{name}.toml` is written: instantiate the fenced template from `references/framework-files.md` and write `team.md` at `.codex/teams/{TEAM_NAME}/team.md` with metadata, `## Shared Agent Contract`, explicit `Intent guard` policy, and zero domain rows. Do not add domain-agent rows yet. Copy the project-local tracer, initialize trace storage, substitute every placeholder, then run `scripts/verify-team.sh`. **STOP on any failure. Do not spawn or write an agent.**
## Prompt contract
### C3: Agent Creation
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.
Create each approved domain `.codex/agents/{name}.toml` from `references/agent-template.md`. Parse it structurally with `tomllib` and require only `name`, `description`, and `developer_instructions`. The `developer_instructions` value uses exactly these ordered headings and no others: `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification`. Its first must-load item is exactly `.codex/teams/{TEAM_NAME}/team.md`, occurring once. Enforce <=3200 UTF-8 bytes and `ceil(chars/4) <=800` over `developer_instructions` itself.
| Mode | EN keywords | RU keywords | Mutates? |
|------|-------------|-------------|----------|
| `status` | *(empty)*, `status`, `show`, `list`, `check` | `статус`, `покажи`, `что`, `проверь` | no |
| `install` | `install`, `create`, `setup`, `new team`, `build` | `установи`, `создай`, `настрой`, `новая команда` | yes |
| `upgrade` | `upgrade`, `update`, `tune`, `improve`, `retune` | `обнови`, `улучши`, `настрой лучше` | yes |
| `enable` | `enable`, `on`, `turn on`, `activate`, `restore` | `включи`, `активируй`, `верни`, `восстанови` | yes |
| `disable` | `disable`, `off`, `turn off`, `pause`, `park` | `выключи`, `отключи`, `пауза`, `приостанови` | yes |
| `uninstall` | `uninstall`, `remove`, `delete`, `clean up`, `tear down` | `удали`, `убери`, `сними`, `очисти` | yes, destructive |
| `purge` | `purge`, `wipe`, `nuke`, `delete everything`, `remove all` | `снеси`, `удали всё`, `вычисти`, `полностью удали` | yes, destructive |
`intent-guard` is exempt from the six-heading domain profile. Under `required`, run `<plugin-root>/skills/superreview-setup/scripts/emit-intent-guard.sh <project-root>`; that sole shared writer create-only copies its native authority, structurally validates it, and never overwrites an existing file. Never ask agent-creator to write it. Under `legacy-absent`, create no row and no role.
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 -> `request_user_input`; 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 `request_user_input` (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.
### C4: Roster Finalization
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 .codex/teams/{name}/ and .codex/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 shell:
```bash
bash "<skill-directory>/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.
> `.codex/agents/intent-guard.toml` is the ONE exception: `generate.sh emit-agent` stamps it with
> `generated_by: brewcode:superreview-setup`, and teams never touches those keys.
`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.** Codex discovers a project agent only through
> `.codex/agents/<name>.toml`. `disable` renames each member to `<name>.toml.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. `intent-guard` is never parked — it is shared with
> `$brewcode:superreview-setup`, exactly as in UNINSTALL and PURGE.
---
## Universal Prelude (every mode)
### Step 0: Init + Validate + Confirm
1. Output: `Mode: {MODE}, Team: {TEAM_NAME}`
2. Load environment:
| Action | Command / Path |
|--------|----------------|
| Read agent template | `<skill-directory>/references/agent-template.md` |
| Read framework templates | `<skill-directory>/references/framework-files.md` |
| Check team dir | `.codex/teams/{TEAM_NAME}/` -- exists? |
| Check existing agents | `.codex/agents/` -- list all |
| If team.md exists | Read, show current roster |
| If trace.jsonl exists | Show entry counts via `trace-ops.sh read` |
3. If team exists, verify:
```bash
bash "<skill-directory>/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
4. 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 request_user_input.
5. Mutating modes only — **ASK** using request_user_input: "PLAN above. Continue?"
Options: "Yes, continue" | "No, I want changes" | "Cancel"
- "changes" -> request_user_input for details, revise the PLAN and reprint it
- "Cancel" -> **STOP**
---
## Delegation (applies to EVERY sub-agent 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:
| Field | Content |
|-------|---------|
| GOAL | the overall task and why it exists — the point beyond the file edit |
| ROLE | what this agent owns; what it must NOT touch |
| SCOPE | exact paths/commands in bounds + explicit out-of-bounds |
| CONTEXT | what is already done, by whom, what runs in parallel — trimmed to what THIS agent needs |
| CONSUMER | who or what uses the result next, and the shape it must fit |
| DONE | acceptance 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 sub-agent collaboration tools:
| # | Focus |
|---|-------|
| 1 | Code structure: modules, packages, domains, architectural layers |
| 2 | Existing agents (`.codex/agents/`, `brewcode/agents/`, `~/.codex/agents/`) + Codex infrastructure |
| 3 | Tech stack: build files, frameworks, dependencies, languages |
| 4 | CI/CD, testing, deploy, infrastructure |
| 5 (optional) | Domain boundaries: business logic, API, data layer, UI |
All via `Codex delegation brief (task_role="Explore")`. Consolidate into single analysis document.
**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:
| Fact | Fills | Where to look |
|------|-------|---------------|
| Project name | `{PROJECT_NAME}` | repo dir, root `AGENTS.md`, `package.json`/build file |
| Where original requirements live (tracker, issues, Slack, "chat only") | `{TRACKER_LABEL}` | `AGENTS.md`, `.github/`, issue templates, CI links |
| Spec / design-doc paths or globs | `{SPEC_LOCATION}` | `.codex/specs/**`, `docs/`, `adr/` |
| Plan / task-board / task-graph paths | `{PLAN_LOCATION}` | `.codex/features/**`, `TASKS.md`, board files |
| Policy paths: root + nested `AGENTS.md`, rules, conventions | `{POLICY_LOCATION}` | `AGENTS.md`, `.codex/rules/**` |
| Planned scale / user count, testing policy, dependency policy, file-layout policy, architecture stance | `{PROJECT_INVARIANTS_TABLE}` | `AGENTS.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 |
### C2: Team Proposal (interactive)
Based on analysis + PROMPT (if provided), propose 3 variants via request_user_input.
**`intent-guard` is in EVERY team, always, and is NOT one of the counted slots.** It is a review-only
anti-drift check (asked-vs-delivered), not a domain agent, so the 5 / 10-12 / 15-20 counts describe
DOMAIN agents only. Show it as a fixed row in every variant table, never as an option the user picks
and never as something the user can drop:
```
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 request_user_input for free input; intent-guard stays regardless of what the user
specifies. Final confirmation of agent list before proceeding.
> If `.codex/agents/intent-guard.toml` 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):
```bash
for a in {PROPOSED_NAMES}; do
o=$(bash "<skill-directory>/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 (request_user_input)
"Default model for domain agents: high-reasoning model (most reliable)."
| Model | Best for | Cost |
|-------|----------|------|
| high-reasoning model | Complex domains, architecture, critical logic | High |
| balanced model | Standard domains, CRUD, testing, utilities | Medium |
| fast model | Simple utility agents, formatting, validation | Low |
Options: "high-reasoning model (recommended)" | "balanced model" | "fast model" | "Mixed -- I'll choose per agent"
If "Mixed" -- ask model per agent in C3. Store as `DEFAULT_MODEL` (default: high-reasoning model).
> `DEFAULT_MODEL` applies to DOMAIN agents only. `intent-guard` keeps the `model: balanced model` 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 `.codex/agents/{name}.toml` 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 `.codex/teams/{TEAM_NAME}/`.
2. Read `<skill-directory>/references/framework-files.md`; write `team.md` with substituted metadata,
the byte-faithful `## Shared Agent Contract`, the `## Agents` header, and only the 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 `<skill-directory>/references/agent-template.md`
1a. Confirm C2.6 completed. `.codex/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 `.codex/agents/{name}.toml.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 `Codex delegation brief (task_role="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 `.codex/agents/{name}.toml` 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 (~800 est-tokens), with exactly these ordered headings and no others: `## Mission`, `## Owned surfaces`, `## Exclusions`, `## Must-load references`, `## Unique invariants`, `## Unique verification`;
- `## Must-load references` names `.codex/teams/{TEAM_NAME}/team.md` first;
- profile contains only domain-unique facts. `sub-agent 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 <skill-directory>/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:
```
Codex delegation brief (task_role="brewtools:text-optimizer", message="Light-optimize .codex/agents/{agent-name}.toml; 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 `.codex/agents/intent-guard.toml`.** 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 (always, exactly once)
`.codex/agents/intent-guard.toml` 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 shell (substitute the C1 values first):
```bash
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 "<skill-directory>/../superreview-setup/scripts/generate.sh" emit-agent && echo "OK" || echo "FAILED"
```
It creates-or-reuses ONLY `.codex/agents/intent-guard.toml` (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.
```bash
f=.codex/agents/intent-guard.toml
[ -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 .codex/agents/intent-guard.toml`,
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
`Codex delegation brief (task_role="brewcode:agent-creator")`, alone (not batched with the domain agents), to replace
them with project-specific content:
```
Codex delegation brief (task_role="brewcode:agent-creator", message="
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 .codex/agents/intent-guard.toml:
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: balanced model, 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, sub-agent 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
.codex/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, `<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.
```bash
f=.codex/agents/intent-guard.toml
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 the file gets its `team.md` row.
### C4: Roster Finalization + Verification
1. Re-check the C2.6 bootstrap before editing the roster. Missing/malformed shared contract -> **STOP**;
never finalize discoverable agents against an absent authority.
2. Finalize `team.md` from `<skill-directory>/references/framework-files.md`: preserve the bootstrapped
Shared Agent Contract byte-faithful, add one domain row per successfully created agent, and retain the
fixed `intent-guard` row. Then `touch trace.jsonl`. No confirmed-but-unwritten agent enters the roster.
Then install the **project-local tracer** the generated agents call. A `.codex/agents/*.toml` file
is not plugin-owned, so `<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:
```bash
cp "<skill-directory>/scripts/trace-ops.sh" ".codex/teams/TEAM_NAME_HERE/trace-ops.sh" && \
chmod +x ".codex/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 an `intent-guard` row (trailing `Kind` column = `review-only`, trailing
`Version` column = `PLUGIN_VERSION:`), whether it was created in C3-IG or reused. `Agents | {N}`
counts DOMAIN agents; note intent-guard separately.
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:
```markdown
| 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.
3. Verify:
```bash
bash "<skill-directory>/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
```
> **STOP if FAIL** -- fix missing files before continuing.
4. request_user_input: final report + suggest `$brewcode:teams-setup status {TEAM_NAME}`
### C5: Quorum Review
Spawn 3 reviewer agents in ONE message via sub-agent collaboration tools. `REVIEWER` (here and in C7/C9) = the
project's reviewer agent from `.codex/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 |
|---|-------|
| 1 | Profile contract: body only (frontmatter excluded) <=3200 bytes (~800 est-tokens); exactly six ordered body headings (`Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification`); `.codex/teams/{TEAM_NAME}/team.md` loaded first; no repeated shared-contract heading/rule |
| 2 | Domain accuracy: correct scope, tool selection, model fit, description triggers |
| 3 | Architecture: no domain overlaps; owned surfaces/exclusions/routing agree with the roster; acceptance/tracing/returns/colleagues/scope-fit exist once in `team.md` |
`.codex/agents/intent-guard.toml` 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: balanced model`, 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 `.codex/agents/` and outputs:
```
FILE: .codex/agents/{name}.toml
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).
| Outcome | Action |
|---------|--------|
| 2/3+ confirm | Mark **confirmed**, keep severity from highest reporter |
| 1/3 only | Log as **unconfirmed**, skip |
| Minor severity (all reporters) | Log but skip fix |
### C7: Verification
```
Codex delegation brief (task_role=REVIEWER, message="
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.
After all intended agents validate, write the final roster. Declared `Agents` equals the number of unique domain rows; duplicate names fail. a new team defaults to `required`. Policy `required` has exactly one `intent-guard` row with fixed cells `--`, `Anti-drift check: what was ASKED vs what was DELIVERED`, `active`, team `Last update`, `review-only`, team `Version`. Policy `legacy-absent` has zero rows. the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters; `ceil(chars/4) <=700` estimated tokens. Measure the full substituted file, not the empty template.
### C8: Fix
For each verified critical/important issue:
```
Codex delegation brief (task_role="brewcode:agent-creator", message="
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,
AGENTS.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 `<skill-directory>/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 .codex/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 `.codex/agents/intent-guard.toml`, add to the ROLE: frontmatter is frozen —
> the description stays short and review-only, tools stay read-only, `model: balanced model` stays. Only
> placeholder content (project facts, invariants, drift examples, evidence commands) may be fixed.
Repair only failed owned artifacts. Domain agents come from `<skill-directory>/references/agent-template.md`; repair the shared contract before an agent rewrite. Preserve foreign agents and unrelated work. Re-run structural TOML, roster, policy, size, and shared-contract checks.
### C9: Re-verify
```
Codex delegation brief (task_role=REVIEWER, message="
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 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}
")
```
Run `scripts/verify-team.sh {TEAM_NAME}`, both test runners, and compatibility validation. Hard-gate `developer_instructions` only: <=3200 bytes and `ceil(chars/4) <=800`; `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`, `Unique verification` in order with no other headings. `intent-guard` is exempt from this six-heading gate, not structural TOML validation.
| Outcome | Action |
|---------|--------|
| All FIXED | Pipeline complete, proceed to Epilogue |
| REGRESSION found | Return to C8 for that file (max 2 cycles) |
| Still failing after 2 cycles | Log 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 `.codex/teams/{TEAM_NAME}/team.md`
2. Read trace data:
```bash
bash "<skill-directory>/scripts/trace-ops.sh" read ".codex/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:**
```markdown
# 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:
| Label | Criteria |
|-------|----------|
| Healthy | >70% success, active |
| Needs tuning | 30-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 request_user_input -- purely informational.
---
## Mode: UPGRADE (self-reflection)
### U1: Load & Parse
```bash
CURSOR=$(bash "<skill-directory>/scripts/trace-ops.sh" cursor ".codex/teams/{TEAM_NAME}")
bash "<skill-directory>/scripts/trace-ops.sh" read ".codex/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.
**Refuse to upgrade a PARKED member.** Every write in U4 targets `.codex/agents/{name}.toml`; 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:
```bash
for m in {AGENT_NAMES}; do
[ -f ".codex/agents/$m.toml" ] || { [ -f ".codex/agents/$m.toml.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.
> To skip review pipeline is not an acceptance path; unresolved checks remain failures.
### U1b: Shared Contract Migration Gate
Before U2 analysis or any U4 agent write, read
`<skill-directory>/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}` only and preserving Created, roster rows, statuses, and history. 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.
On upgrade, insert the canonical block before `## Agents` and validate it before touching agents. Record an existing intent-guard roster row -> `required`; no row -> `legacy-absent`. Never synthesize the row on the latter path. Legacy agent bodies remain byte-identical during this gate. **No agent may be tuned, regenerated, stripped, or reformatted until the shared contract passes.** absence migrates
to `legacy-absent`; `legacy-absent` forbids that row and MUST NOT add the role during upgrade.
### U2: Analyze Performance
Filter post-cursor trace: `k=track` for task stats, `k=issue` for problems, `k=insight` for patterns.
| Status | Criteria | Action |
|--------|----------|--------|
| Healthy | >70% success, active | No changes |
| Needs tuning | 30-70% success or many refusals | Update instructions |
| Underperforming | <30% success | AskUser: update or delete+create new |
| Inactive | 0 records | AskUser: delete or keep |
> `intent-guard` is EXCLUDED from this table. It does not trace and is invoked only during review, so
> 0 records is its normal state, never grounds for deletion or tuning. UNINSTALL enforces the same
> exclusion in `references/cleanup-flow.md` Step 3.
### U3: Present & Confirm
**ASK** using request_user_input 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" -> request_user_input per agent. If "Show detailed" -> output full stats, then re-ask.
Use trace evidence only to decide whether a domain profile needs role-specific adjustment. Never duplicate the shared contract.
### U4: Apply Changes
| Agent Status | Action |
|--------------|--------|
| Needs tuning | `Codex delegation brief (task_role="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 `.codex/agents/{name}.toml` + 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 "<skill-directory>/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.toml` is byte-untouchable.
Every domain agent touched here migrates to the current compact template: body only (frontmatter excluded)
<=3200 bytes (~800 est-tokens),
exactly the six ordered headings, `.codex/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.toml` remains byte-untouchable.
Set cursor:
```bash
bash "<skill-directory>/scripts/trace-ops.sh" cursor ".codex/teams/{TEAM_NAME}" set "$(date -u +%Y-%m-%dT%H:%M:%SZ)" && echo "✅" || echo "❌ FAILED"
```
---
## Mode: ENABLE
Un-parks a team that was previously `disable`d. 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
bash "<skill-directory>/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
bash "<skill-directory>/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
bash "<skill-directory>/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
bash "<skill-directory>/scripts/toggle-team.sh" "TEAM_NAME_HERE" disable --dry-run && echo "OK" || echo "FAILED"
```
3. **ASK** using request_user_input: "Disable team {TEAM_NAME}? {N} agent files are parked as
`.toml.disabled` — nothing is deleted, `enable` restores them. `intent-guard` stays live."
Options: "Yes, disable" | "Uninstall instead (deletes agents, keeps archive)" | "Cancel"
- anything but "Yes, disable" -> switch to UNINSTALL or **STOP**
4. Apply:
```bash
bash "<skill-directory>/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 `<skill-directory>/references/cleanup-flow.md` and execute step by step:
1. Overview scan -> show trace.jsonl entry counts by kind
2. request_user_input: what to clean (all / trace data / agents / step-by-step)
3. Trace cleanup (if selected) -- request_user_input with archive options
4. Agents review (if selected) -- request_user_input 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 `.codex/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 `<skill-directory>/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 request_user_input: "Purge team {TEAM_NAME}? This deletes {N} agent files and
`.codex/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 AGENTS.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 request_user_input: "Update team info in AGENTS.md?"
Options: "Yes, in project AGENTS.md" | "Yes, in .codex/AGENTS.local.md" | "No, skip"
Format to write:
```markdown
## Teams
Team: {TEAM_NAME} | Domain agents: {N} (+ `intent-guard`, review-only) | Status: active
| Agent | Domain | Mission |
|-------|--------|---------|
`intent-guard` -- review-only anti-drift check (asked vs delivered). Shared with
`$brewcode:superreview-setup`, invoked explicitly by name during review; never an implementation owner.
Protocol: agents self-select tasks, trace in `.codex/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
```markdown
# 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
| Condition | Action |
|-----------|--------|
| `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 started | Defect — **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 team | `toggle-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 `.toml` nor `.toml.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 `.codex/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 `.codex/agents/{a}.toml` and `{a}.toml.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, request_user_input: "Upgrade instead?" |
| verify-team.sh FAIL | Show 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>
Convert every touched Codex domain agent to the exact three-key TOML contract and six-heading `developer_instructions` shape. Parse before replacement, write atomically, parse again, and preserve untouched agents byte-identical.
For `enable` and `disable`, use `scripts/toggle-team.sh`; it parks/restores domain `.toml` files byte-identically and never parks `intent-guard`. For `uninstall` and `purge`, follow the shipped cleanup flow and explicit confirmation gates. Every mode ends with `verify-team.sh` and reports exact paths, counts, and failures.
@@ -73,12 +73,11 @@ echo "✅ Archived" || echo "❌ FAILED"
## Step 3: Agents Review
> **`intent-guard` is EXCLUDED from this step — never list it, never offer it, never delete it.**
> It is the team's fixed review-only member, shared with `$brewcode:superreview-setup`. It writes no trace
> entries by design, so 0 tasks and "no activity" are its NORMAL state, not inactivity. Filter it out
> of the inactive table BEFORE showing it, so "Delete all inactive" cannot reach it. If the user asks
> for it by name anyway, refuse: answer that removing it breaks `verify-team.sh` for this team, and
> keep the file. Its `team.md` row (`Kind` = `review-only`) also stays.
Read logical `intent_guard_policy=required|legacy-absent` from the single `Intent guard` field in
`team.md` before building the table. Under `required`,
the roster has exactly one review-only `intent-guard`; exclude it from this step, never list/offer/delete
it, and preserve its row. It writes no trace entries, so 0 tasks is normal. Under `legacy-absent`, the
roster has zero such rows and cleanup must not create a profile or row. Upgrade never changes that policy.
Show inactive/problematic agents (domain agents only):
@@ -106,7 +105,7 @@ request_user_input:
On delete:
0. If `{name}` is `intent-guard` -> **STOP, do not delete.** Report it as protected and move on.
0. If `{name}` is `intent-guard` under `required` -> **STOP, do not delete.** Report it as protected and move on. Under `legacy-absent`, seeing that name is a policy violation: delete nothing and report the inconsistent roster.
0b. **Validate `{name}` as an agent id BEFORE any `rm`.** Roster values are interpolated into the delete
path, so a row like `../../../outside/README` deletes a file outside the project. Same guard
`toggle-team.sh`/`verify-team.sh` apply — run it, and on a non-zero exit report the row as a corrupt
@@ -169,9 +168,10 @@ Nothing is archived — the archive itself is part of what goes.
ls -la ".codex/teams/{TEAM}" 2>/dev/null; du -sh ".codex/teams/{TEAM}" 2>/dev/null
```
2. Delete each domain agent listed in `team.md` (`## Agents` table, `Kind` != `review-only`).
**`intent-guard` is skipped** shared with `$brewcode:superreview-setup`; deleting it would break
an unrelated install. Report it as kept. **Every other `{name}` passes the Step 3 id guard first**
2. Delete each domain agent listed in `team.md` (`## Agents` table, `Kind` != `review-only`). Under
`required`, **`intent-guard` is skipped** because it is shared with `$brewcode:superreview-setup`;
report it as kept. Under `legacy-absent`, there is no row or profile to skip and purge must not add
one. **Every other `{name}` passes the Step 3 id guard first**
a roster value that is not `^[a-z0-9][a-z0-9-]*$` is a path, and purge would delete outside
`.codex/agents/`; report such a row as corrupt and delete nothing for it. **Every `{name}` also passes
the Step 3 ownership check (step 0c)** — purge is not a licence to take another team's agent with it:
@@ -1,56 +1,46 @@
# Framework files
Instantiate `.codex/teams/{TEAM_NAME}/`. Replace `{TEAM_NAME}`, `{DATE}`, `{LAST_UPDATED}`, `{PLUGIN_VERSION}`, `{CONTENT_VERSION}`, `{N}`, `{CWD}` from `detect-mode.sh`; `CONTENT_VERSION` self-locates from this skill's metadata, !=copied from `PLUGIN_VERSION`. `{DATE}` is creation date and upgrade never rewrites it. `team.md` uses Edit; `trace.jsonl` is append-only via `trace-ops.sh add`.
Instantiate `.codex/teams/{TEAM_NAME}/`. Replace `{TEAM_NAME}`, `{DATE}`, `{LAST_UPDATED}`, `{PLUGIN_VERSION}`, `{CONTENT_VERSION}`, `{N}`, `{CWD}`, `{INTENT_GUARD_POLICY}`, and `{INTENT_GUARD_ROW}`; scalar metadata comes from `detect-mode.sh`. `CONTENT_VERSION` self-locates from this skill's metadata, !=copied from `PLUGIN_VERSION`. `{DATE}` is creation date and upgrade never rewrites it. `team.md` uses Edit; `trace.jsonl` is append-only via `trace-ops.sh add`.
## team.md
```markdown
# Team: {TEAM_NAME}
| Field | Value |
|-------|-------|
| Created | {DATE} |
| Version | {PLUGIN_VERSION} |
| Content version | {CONTENT_VERSION} |
| Generated by | brewcode:teams-setup |
| Last update | {LAST_UPDATED} |
| Agents | {N} |
| Project | {CWD} |
|Field|Value|
|---|---|
|Created|{DATE}|
|Version|{PLUGIN_VERSION}|
|Content version|{CONTENT_VERSION}|
|Generated by|brewcode:teams-setup|
|Last update|{LAST_UPDATED}|
|Agents|{N}|
|Intent guard|{INTENT_GUARD_POLICY}|
|Project|{CWD}|
## Shared Agent Contract
Every domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.
### Acceptance + routing
Before any task evaluate `Domain`, `Duplicate`, `Best candidate`. Domain mismatch -> refuse + name the roster colleague; duplicate -> refuse + link the result; better candidate -> refuse + name that colleague. Refusal returns to the manager immediately. Acceptance -> trace `took`, execute only owned surfaces, honor exclusions/named owners. The `## Agents` roster routes; profile exclusions win on overlap.
### Tracing
Optional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing file/bash failure -> skip silently; plugin update/move/uninstall does not break it.
`bash ".codex/teams/{TEAM_NAME}/trace-ops.sh" add ".codex/teams/{TEAM_NAME}" "$SID" "{AGENT_NAME}" "<kind>" "<state>" "<text>"`
Track states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; if unset, pass any 8-char marker.
Before any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.
Optional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.
`T=".codex/teams/{TEAM_NAME}"; bash "$T/trace-ops.sh" add "$T" "$SID" "{AGENT_NAME}" "<kind>" "<state>" "<text>"`
Track states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.
A task traced `took` ends with exactly one terminal track: `completed` or `failed`.
### Return
Verdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed `path:line` + check verdict or one failing name. Bulk diffs/logs/dumps/reports -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, return path + verdict + <=3 lines.
### Shared implementation rules
Code/script/SQL/schema/infra/config owners build for actual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify last. Before class/module/test, find the closest well-built repo etalon (`.codex/convention/*` first); its principles add to rules/conventions/docs, !=replace them.
Verdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.
Actual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.codex/convention/*` first), additive to rules/conventions/docs, !=replace them.
## Agents
| Agent | Domain | Mission | Status | Updated | Kind | Version |
|-------|--------|---------|--------|---------|------|---------|
| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | {LAST_UPDATED} | review-only | {PLUGIN_VERSION} |
|Agent|Domain|Mission|Status|Updated|Kind|Version|
|---|---|---|---|---|---|---|
{INTENT_GUARD_ROW}
```
`Agent` stays column 1 (row field 2); `Kind`/`Version` trail, future columns append at end. Metadata quartet `Version` / `Content version` / `Generated by` / `Last update` stays adjacent and ordered; `Created`/`Agents`/`Project` stay outside it. Header `Version` = last `team.md` write; per-agent `Version` changes only for touched rows. Status: `active`, `inactive` (live, zero trace), `updating`, `disabled`, `removed` (file deleted); kind: `domain` (blank allowed), `review-only`. `disabled` parks `.codex/agents/{name}.toml.disabled` while body/team dir/history stay intact; `enable` restores byte-identical body. `intent-guard` is mandatory, shared with superreview, outside `{N}`, and never removed.
`Agent` stays column 1 (row field 2); `Kind`/`Version` trail, future columns append at end. Metadata quartet `Version` / `Content version` / `Generated by` / `Last update` stays adjacent and ordered; `Created`/`Agents`/`Intent guard`/`Project` stay outside it. Header `Version` = last `team.md` write; per-agent `Version` changes only for touched rows. Status: `active`, `inactive` (live, zero trace), `updating`, `disabled`, `removed` (file deleted); kind: `domain` (blank allowed), `review-only`. `disabled` parks `.codex/agents/{name}.toml.disabled` while body/team dir/history stay intact; `enable` restores byte-identical body.
`Intent guard` is explicit: `required` means `{INTENT_GUARD_ROW}` is exactly
`|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|{LAST_UPDATED}|review-only|{PLUGIN_VERSION}|`;
`legacy-absent` means the placeholder is empty and the roster MUST NOT contain `intent-guard`. New teams
default to `required`. Upgrade preserves an existing no-guard roster as `legacy-absent`; it never adds a
role merely to modernize the shared contract. `intent-guard` remains shared with superreview, outside
`{N}`, and never removed when policy is `required`.
## trace.jsonl
@@ -30,7 +30,7 @@ if [ -f "$PLUGIN_JSON" ]; then
fi
fi
# HARD FAIL, never a placeholder value. The repair row this prints is meant to be pasted back into an
# agent's frontmatter, so a documentation spelling like `X.Y.Z` reaches an artifact the moment anyone
# agent's TOML agent schema, so a documentation spelling like `X.Y.Z` reaches an artifact the moment anyone
# follows the advice. It carries no `{}<>`, so setup-status's PLACEHLD test cannot catch it and
# `sort -V` would print a confident `AHEAD X.Y.Z > 5.2.0`. The manifest ships with the plugin in the
# dev checkout and in the cache alike, so an unreadable one is a broken install - stop here.
@@ -57,77 +57,68 @@ case "$CV" in
*) printf 'ERROR:cannot resolve content_version (X.Y.Z) from %s - refusing to emit a repair row with a fake content_version\n' "$SKILL_MD"; exit 1 ;;
esac
# Artifact-metadata frontmatter gate for ONE generated agent. Same four keys, same D2 order and the same
# quoting `brewcode/skills/rules/scripts/rules.sh:140-146` enforces -- one dialect across the repo, not a
# second one invented here. Returns: 0 conforming, 1 malformed, 2 no metadata at all (pre-standard agent).
check_agent_meta() {
# BEGIN CLIENT AGENT VALIDATION
# Native Codex agents are TOML data, not renamed Markdown. Parse before contract validation.
check_native_agent() {
_f="$1"
_fm=$(awk 'NR == 1 && $0 == "---" { f = 1; next } f && $0 == "---" { exit } f { print }' "$_f")
_present=$(printf '%s\n' "$_fm" | grep -cE '^(doc_type|version|generated_by|last_updated):' || true)
[ "$_present" -eq 0 ] && return 2
_expected_name="$2"
_kind="$3"
python3 - "$_f" "$_expected_name" "$_kind" "$TEAM_NAME" <<'PY'
import pathlib
import re
import sys
import tomllib
_bad=0
for _k in doc_type version generated_by last_updated; do
printf '%s\n' "$_fm" | grep -q "^${_k}:" || { echo " FAIL: missing frontmatter key: $_k"; _bad=1; }
done
printf '%s\n' "$_fm" | grep -q '^doc_type: llm$' \
|| { echo " FAIL: doc_type must be exactly 'llm', UNQUOTED"; _bad=1; }
printf '%s\n' "$_fm" | grep -Eq '^version: "[0-9]+\.[0-9]+\.[0-9]+"$' \
|| { echo " FAIL: version must be a QUOTED X.Y.Z (a surviving {PLUGIN_VERSION} token fails here)"; _bad=1; }
printf '%s\n' "$_fm" | grep -Eq '^generated_by: "[^"]+"$' \
|| { echo " FAIL: generated_by must be a QUOTED <plugin>:<skill>"; _bad=1; }
printf '%s\n' "$_fm" | grep -Eq '^last_updated: "[0-9]{4}-[0-9]{2}-[0-9]{2}"$' \
|| { echo " FAIL: last_updated must be a QUOTED YYYY-MM-DD"; _bad=1; }
_order=$(printf '%s\n' "$_fm" | grep -oE '^(doc_type|version|generated_by|last_updated)' | tr '\n' ' ' || true)
[ "$_order" = "doc_type version generated_by last_updated " ] \
|| { echo " FAIL: metadata keys out of order [$_order] -- must be doc_type, version, generated_by, last_updated"; _bad=1; }
return "$_bad"
}
# Print only the body after the closing frontmatter fence. The 3200-byte contract excludes frontmatter:
# a rich trigger description or extra generator metadata must not consume domain-instruction budget.
profile_body() {
awk '
NR == 1 && $0 == "---" { in_fm = 1; next }
in_fm && $0 == "---" { in_fm = 0; body = 1; next }
body { print }
' "$1"
}
# Current teams-setup domain profiles have one compact, machine-checkable body. A body with no
# `## Mission` is legacy and stays runnable with an upgrade warning; a partial current profile is a
# writer defect. intent-guard is exempt because superreview-setup owns its independent template.
check_compact_profile() {
_f="$1"
profile_body "$_f" | grep -qF '## Mission' || return 2
_bad=0
_headings=$(profile_body "$_f" | grep -E '^#{1,6}[[:space:]]' || true)
_expected=$(printf '%s\n' \
'## Mission' \
'## Owned surfaces' \
'## Exclusions' \
'## Must-load references' \
'## Unique invariants' \
'## Unique verification')
[ "$_headings" = "$_expected" ] \
|| { echo " FAIL: body headings must be exactly the six ordered teams-setup headings"; _bad=1; }
_first_ref=$(profile_body "$_f" | awk '
/^## Must-load references$/ { refs = 1; next }
refs && /^## / { exit }
refs && /^-/ { print; exit }
')
printf '%s\n' "$_first_ref" | grep -qF ".codex/teams/$TEAM_NAME/team.md" \
|| { echo " FAIL: Must-load references must name .codex/teams/$TEAM_NAME/team.md"; _bad=1; }
_bytes=$(profile_body "$_f" | wc -c | tr -d '[:space:]')
[ "$_bytes" -le 3200 ] \
|| { echo " FAIL: compact profile body is $_bytes bytes; ceiling is 3200 (~800 est-tokens), frontmatter excluded"; _bad=1; }
if profile_body "$_f" | grep -Eq '^## (sub-agent task Acceptance Protocol|Return Contract|Trace Instructions|Colleagues|Scope Fit|Domain Instructions|Immutable Traits|Update Protocol)$'; then
echo " FAIL: shared acceptance/tracing/routing/return/colleague/scope-fit contract belongs only in team.md"
_bad=1
fi
return "$_bad"
path = pathlib.Path(sys.argv[1])
expected_name, kind, team = sys.argv[2:5]
try:
data = tomllib.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, tomllib.TOMLDecodeError) as exc:
print(f" FAIL: invalid TOML: {exc}")
raise SystemExit(1)
required = {"name", "description", "developer_instructions"}
if set(data) != required:
print(" FAIL: TOML keys must be exactly name, description, developer_instructions")
raise SystemExit(1)
if any(type(data[key]) is not str for key in required):
print(" FAIL: name, description, and developer_instructions must all be strings")
raise SystemExit(1)
if data["name"] != expected_name:
print(f" FAIL: TOML name {data['name']!r} must equal roster/file name {expected_name!r}")
raise SystemExit(1)
if "\n" in data["description"]:
print(" FAIL: description must be one line")
raise SystemExit(1)
if kind == "review-only":
raise SystemExit(0)
body = data["developer_instructions"]
expected_headings = [
"Mission", "Owned surfaces", "Exclusions", "Must-load references",
"Unique invariants", "Unique verification",
]
actual_headings = re.findall(r"^#{1,6}[ ]+(.+)$", body, flags=re.MULTILINE)
if actual_headings != expected_headings:
print(" FAIL: body headings must be exactly the six ordered teams-setup headings in developer_instructions")
raise SystemExit(1)
reference = f".codex/teams/{team}/team.md"
if body.count(reference) != 1:
print(f" FAIL: Must-load references must name {reference} exactly once")
raise SystemExit(1)
must_load = body.split("## Must-load references\n", 1)[1].split("\n## ", 1)[0]
bullets = [line for line in must_load.splitlines() if line.startswith("- ")]
if not bullets or bullets[0] != "- " + chr(96) + reference + chr(96):
print(f" FAIL: {reference} must be the first Must-load references bullet")
raise SystemExit(1)
body_bytes = len(body.encode("utf-8"))
body_tokens = (len(body) + 3) // 4
if body_bytes > 3200 or body_tokens > 800:
print(f" FAIL: developer_instructions is {body_bytes} bytes/{body_tokens} est-tokens; ceilings are 3200 bytes and 800 ceil(chars/4) tokens")
raise SystemExit(1)
PY
}
# END CLIENT AGENT VALIDATION
# Roster values reach `-f` probes here and `mv`/`rm -f` in toggle-team.sh and cleanup-flow.md, so a row
# like `| ../../../outside/README |` is a path, not a name. An agent id is a bare `^[a-z0-9][a-z0-9-]*$`,
@@ -194,6 +185,25 @@ if [ ! -f "$TEAM_DIR/trace.jsonl" ]; then
fi
if [ -f "$TEAM_DIR/team.md" ]; then
team_chars=$(wc -m < "$TEAM_DIR/team.md" | tr -d '[:space:]')
team_tokens=$(( (team_chars + 3) / 4 ))
if [ "$team_chars" -le 2800 ] && [ "$team_tokens" -le 700 ]; then
echo "CHECK: full team.md ceiling ... OK ($team_chars chars, $team_tokens est-tokens)"
else
echo "CHECK: full team.md ceiling ... FAIL ($team_chars chars, $team_tokens est-tokens; maximum 2800 chars and 700 ceil(chars/4) tokens)"
FAIL=1
fi
declared_agents_count=$(grep -cE '^\|[[:space:]]*Agents[[:space:]]*\|' "$TEAM_DIR/team.md" || true)
declared_agents=""
if [ "$declared_agents_count" -eq 1 ]; then
declared_agents=$(sed -n 's/^|[[:space:]]*Agents[[:space:]]*|[[:space:]]*\([0-9][0-9]*\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
fi
if [ "$declared_agents_count" -ne 1 ] || [ -z "$declared_agents" ]; then
echo "CHECK: declared Agents count ... FAIL (requires exactly one numeric | Agents | N | row)"
FAIL=1
fi
# Artifact-metadata header rows -- all FOUR, adjacent, in the order Version / Content version /
# Generated by / Last update. ABSENT ALL FOUR = a team.md written before the standard existed: WARN
# with the fix, an old team must upgrade cleanly. Anything else -- a subset, a wrong order, a
@@ -241,6 +251,15 @@ if [ -f "$TEAM_DIR/team.md" ]; then
;;
esac
# Current teams declare whether the shared review-only role is required or intentionally absent.
# An old team without the field remains migratable; once the shared contract is present the policy
# is mandatory and the roster must match it exactly.
intent_guard_policy=""
intent_guard_policy_count=$(grep -cE '^\|[[:space:]]*Intent guard[[:space:]]*\|' "$TEAM_DIR/team.md" || true)
if [ "$intent_guard_policy_count" -eq 1 ]; then
intent_guard_policy=$(sed -n 's/^|[[:space:]]*Intent guard[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
fi
# New teams centralize the repeated member contract once. Absence remains safe only for a fully
# legacy roster; a compact profile with no destination contract is an interrupted-install defect.
shared_contract_present=0
@@ -249,6 +268,15 @@ if [ -f "$TEAM_DIR/team.md" ]; then
else
shared_contract_present=1
shared_bad=0
if [ "$intent_guard_policy_count" -ne 1 ]; then
echo "CHECK: Intent guard policy ... FAIL (current team.md requires exactly one policy row)"
shared_bad=1
else
case "$intent_guard_policy" in
required|legacy-absent) echo "CHECK: Intent guard policy ($intent_guard_policy) ... OK" ;;
*) echo "CHECK: Intent guard policy ... FAIL (expected required or legacy-absent; found '$intent_guard_policy')"; shared_bad=1 ;;
esac
fi
shared_count=$(grep -cF '## Shared Agent Contract' "$TEAM_DIR/team.md" || true)
[ "$shared_count" -eq 1 ] \
|| { echo "CHECK: Shared Agent Contract ... FAIL (must occur exactly once; found $shared_count)"; shared_bad=1; }
@@ -286,7 +314,12 @@ if [ -f "$TEAM_DIR/team.md" ]; then
in_agents=0
past_header=0
found_agents=0
found_intent_guard=0
intent_guard_count=0
intent_guard_cells_ok=1
unique_domain_rows=0
seen_agent_ids="|"
team_version=$(sed -n 's/^|[[:space:]]*Version[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
team_last_update=$(sed -n 's/^|[[:space:]]*Last update[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
while IFS= read -r line; do
case "$line" in
"## Agents"*) in_agents=1; past_header=0; continue ;;
@@ -307,7 +340,39 @@ if [ -f "$TEAM_DIR/team.md" ]; then
FAIL=1
continue
fi
[ "$agent" = "intent-guard" ] && found_intent_guard=1
case "$seen_agent_ids" in
*"|$agent|"*)
echo "CHECK: roster name '$agent' ... FAIL (duplicate roster name)"
FAIL=1
;;
*)
seen_agent_ids="${seen_agent_ids}${agent}|"
if [ "$agent" != "intent-guard" ]; then
agent_kind=$(printf '%s' "$line" | cut -d'|' -f7 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
case "$agent_kind" in
''|domain) unique_domain_rows=$((unique_domain_rows + 1)) ;;
*) echo "CHECK: agent '$agent' kind ... FAIL (domain rows require Kind domain or blank)"; FAIL=1 ;;
esac
fi
;;
esac
if [ "$agent" = "intent-guard" ]; then
intent_guard_count=$((intent_guard_count + 1))
agent_domain=$(printf '%s' "$line" | cut -d'|' -f3 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_mission=$(printf '%s' "$line" | cut -d'|' -f4 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_status=$(printf '%s' "$line" | cut -d'|' -f5 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_updated=$(printf '%s' "$line" | cut -d'|' -f6 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_kind=$(printf '%s' "$line" | cut -d'|' -f7 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_version=$(printf '%s' "$line" | cut -d'|' -f8 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [ "$agent_domain" != "--" ] \
|| [ "$agent_mission" != "Anti-drift check: what was ASKED vs what was DELIVERED" ] \
|| [ "$agent_status" != "active" ] \
|| [ "$agent_updated" != "$team_last_update" ] \
|| [ "$agent_kind" != "review-only" ] \
|| [ "$agent_version" != "$team_version" ]; then
intent_guard_cells_ok=0
fi
fi
printf "CHECK: agent %s ... " "$agent"
# BOTH copies present is checked FIRST: a live-first if/parked-elif chain reads a dual copy
# as a healthy live agent and hides the collision. `.codex/agents/` is project-global, so the
@@ -320,36 +385,28 @@ if [ -f "$TEAM_DIR/team.md" ]; then
CONFLICT=$((CONFLICT + 1))
FAIL=1
elif [ -f ".codex/agents/${agent}.toml" ]; then
# The roster row proves the file exists; the frontmatter proves the generator stamped it.
# A generated agent with no metadata at all predates the standard -> WARN + the upgrade fix.
# Metadata that IS there but malformed is a generator defect -> FAIL.
# BEGIN LIVE CLIENT AGENT CHECK
native_kind=domain
[ "$agent" = "intent-guard" ] && native_kind=review-only
set +e
meta_out=$(check_agent_meta ".codex/agents/${agent}.toml")
meta_rc=$?
native_out=$(check_native_agent ".codex/agents/${agent}.toml" "$agent" "$native_kind")
native_rc=$?
set -e
case "$meta_rc" in
0) echo "OK" ;;
2) echo "OK (no artifact metadata -- agent predates the standard; \$brewcode:teams-setup upgrade restamps it)" ;;
*) echo "FAIL"; printf '%s\n' "$meta_out"; FAIL=1 ;;
esac
if [ "$agent" != "intent-guard" ]; then
set +e
profile_out=$(check_compact_profile ".codex/agents/${agent}.toml")
profile_rc=$?
set -e
case "$profile_rc" in
0)
if [ "$shared_contract_present" -eq 1 ]; then
echo " CHECK: compact six-heading profile ... OK"
else
echo " CHECK: compact six-heading profile ... FAIL (shared team contract missing; interrupted install/unsafe migration)"
FAIL=1
fi
;;
2) echo " WARN: legacy repeated/unknown profile shape. Fix: \$brewcode:teams-setup upgrade" ;;
*) printf '%s\n' "$profile_out"; FAIL=1 ;;
esac
if [ "$native_rc" -eq 0 ]; then
echo "OK"
if [ "$native_kind" = "domain" ] && [ "$shared_contract_present" -ne 1 ]; then
echo " CHECK: compact six-heading profile ... FAIL (shared team contract missing; interrupted install/unsafe migration)"
FAIL=1
elif [ "$native_kind" = "domain" ]; then
echo " CHECK: structurally parsed six-heading developer_instructions ... OK"
fi
else
echo "FAIL"
printf '%s
' "$native_out"
FAIL=1
fi
# END LIVE CLIENT AGENT CHECK
elif [ -f ".codex/agents/${agent}.toml.disabled" ]; then
# Parked by `disable`: the body is intact, only the .md extension that
# Codex discovers on is withheld. A reversible state, not a defect.
@@ -368,21 +425,40 @@ if [ -f "$TEAM_DIR/team.md" ]; then
if [ "$in_agents" -eq 0 ]; then
echo "WARN: no ## Agents section in team.md"
fi
# intent-guard is a fixed review-only member of every team, outside the domain-agent count.
# Teams created before it existed simply lack the row -- warn with the fix, never fail them.
# Teams that DO list it are covered by the per-agent -f check above.
if [ "$found_intent_guard" -eq 0 ]; then
echo "WARN: team.md has no intent-guard row (team predates it). Fix:"
echo " bash \"$SCRIPT_DIR/../../superreview-setup/scripts/generate.sh\" emit-agent"
echo " then add this row to the ## Agents table (all 7 columns: Agent, Domain, Mission, Status,"
echo " Updated, Kind, Version):"
echo " | intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | $TODAY | review-only | $PV |"
elif [ "$shared_contract_present" -eq 0 ]; then
echo "WARN: legacy intent-guard roster row predates the review-only scope contract. Fix: \$brewcode:teams-setup upgrade"
elif ! grep -Eq '^\|[[:space:]]*intent-guard[[:space:]]*\|[[:space:]]*--[[:space:]]*\|[[:space:]]*Anti-drift check: what was ASKED vs what was DELIVERED[[:space:]]*\|[^|]*\|[^|]*\|[[:space:]]*review-only[[:space:]]*\|' "$TEAM_DIR/team.md"; then
echo "CHECK: intent-guard roster contract ... FAIL (domain '--', fixed anti-drift mission, and kind review-only are required)"
if [ -n "$declared_agents" ] && [ "$declared_agents" -eq "$unique_domain_rows" ]; then
echo "CHECK: declared Agents count ... OK ($declared_agents unique domain rows)"
elif [ -n "$declared_agents" ]; then
echo "CHECK: declared Agents count ... FAIL (declared $declared_agents, found $unique_domain_rows unique domain rows)"
FAIL=1
fi
case "$intent_guard_policy" in
required)
if [ "$intent_guard_count" -ne 1 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (policy required needs exactly one row; found $intent_guard_count)"
FAIL=1
elif [ "$intent_guard_cells_ok" -ne 1 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (fixed cells require --, anti-drift mission, active, team Last update, review-only, and team Version)"
FAIL=1
else
echo "CHECK: intent-guard roster contract ... OK"
fi
;;
legacy-absent)
if [ "$intent_guard_count" -ne 0 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (policy legacy-absent requires zero rows; found $intent_guard_count)"
FAIL=1
fi
;;
"")
if [ "$shared_contract_present" -eq 0 ]; then
if [ "$intent_guard_count" -eq 0 ]; then
echo "WARN: legacy team has no intent-guard row; upgrade records policy legacy-absent without adding a role"
else
echo "WARN: legacy intent-guard roster row predates the explicit required policy. Fix: \$brewcode:teams-setup upgrade"
fi
fi
;;
esac
fi
printf 'DISABLED_AGENTS:%s\n' "$DISABLED"
@@ -31,6 +31,24 @@ const LEGACY_HEADINGS = [
const SOURCE_CLIENT_DIR = ['.', 'claude'].join('');
const SOURCE_TEAM_REF = `${SOURCE_CLIENT_DIR}/teams/{TEAM_NAME}/team.md`;
const NATIVE_TEAM_REF = '.codex/teams/{TEAM_NAME}/team.md';
const SOURCE_PLUGIN_ROOT = `${['CL', 'AUDE'].join('')}_PLUGIN_ROOT`;
const SOURCE_PLUGIN_ROOT_NEGATION = `!=\`\${${SOURCE_PLUGIN_ROOT}}\` substitution`;
const DUSK_ROSTER = [
['game-designer', 'design', 'pillars'],
['combat-dev', 'combat', 'loop'],
['physics-dev', 'physics', 'Jolt'],
['destruction-dev', 'destruct', 'fracture'],
['scenario-dev', 'scenarios', 'lab'],
['vfx-dev', 'VFX', 'impacts'],
['texture-artist', 'materials', 'textures'],
['modeller-3d', 'models', 'rigs'],
['sound-designer', 'audio', 'SFX'],
['feel-dev', 'feel', 'camera'],
['qa-tester', 'QA', 'tests'],
['docs-keeper', 'docs', 'sync'],
['build-eng', 'build', 'toolchain'],
];
const DUSK_NON_MEMBERS = ['task-tracker', 'intent-guard'];
let passed = 0;
let failed = 0;
@@ -93,6 +111,37 @@ function section(text, start, end) {
return text.slice(a, b < 0 ? text.length : b);
}
function rosterNames(team) {
return section(team, '## Agents', '\n## ')
.split('\n')
.filter((line) => /^\|[a-z0-9]/.test(line) && !line.startsWith('|Agent|'))
.map((line) => line.split('|')[1]);
}
function instantiateTeamTemplate(template, {
projectRoot,
roster,
policy,
version = '6.1.4',
contentVersion = '6.1.0',
}) {
const intentRow = policy === 'required'
? `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|${version}|`
: '';
const domainRows = roster.map(([name, domain, mission]) =>
`|${name}|${domain}|${mission}|active|2026-08-27|domain|${version}|`).join('\n');
return `${template
.replaceAll('{TEAM_NAME}', 'dusk')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', version)
.replaceAll('{CONTENT_VERSION}', contentVersion)
.replaceAll('{N}', String(roster.length))
.replaceAll('{CWD}', projectRoot)
.replaceAll('{INTENT_GUARD_POLICY}', policy)
.replaceAll('{INTENT_GUARD_ROW}', [intentRow, domainRows].filter(Boolean).join('\n'))}\n`;
}
const repo = findRepoRoot(dirname(fileURLToPath(import.meta.url)));
const canonicalTemplatePath = join(repo, 'brewcode', 'skills', 'teams-setup', 'references', 'agent-template.md');
const canonicalFrameworkPath = join(repo, 'brewcode', 'skills', 'teams-setup', 'references', 'framework-files.md');
@@ -183,6 +232,7 @@ const sharedSourceLiterals = [
'no retry, Bash only',
'versionless project-local',
sourceTracePath,
SOURCE_PLUGIN_ROOT_NEGATION,
'no `*_PLUGIN_ROOT` env',
'plugin update/move/uninstall does not break it',
'`took` / `refused` / `completed` / `failed`',
@@ -195,6 +245,7 @@ const sharedSourceLiterals = [
'>~2500',
'<=3 lines',
'!=imagined load/speculative abstraction',
'10-user app !=lock-contention hardening',
'!=replace them',
'## Agents',
];
@@ -218,6 +269,60 @@ check(
true,
'generated team.md fenced template is at most 700 estimated tokens',
);
check(
'shared.intentPolicyPlaceholder',
occurrences(canonicalTeam, '{INTENT_GUARD_POLICY}'),
1,
'team template carries exactly one explicit intent-guard policy field',
);
check(
'shared.intentRowPlaceholder',
occurrences(canonicalTeam, '{INTENT_GUARD_ROW}'),
1,
'team template carries exactly one policy-controlled intent-guard row slot',
);
const fullDuskTeam = instantiateTeamTemplate(canonicalTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk',
roster: DUSK_ROSTER,
policy: 'legacy-absent',
});
check(
'shared.fullDuskRosterCount',
rosterNames(fullDuskTeam).length,
13,
'the representative full Dusk roster contains exactly 13 members',
);
check(
'shared.fullDuskRosterNames',
rosterNames(fullDuskTeam).join('|'),
DUSK_ROSTER.map(([name]) => name).join('|'),
'the full Dusk roster preserves the exact ordered member boundary',
);
check(
'shared.fullDuskNonMembers',
DUSK_NON_MEMBERS.filter((name) => rosterNames(fullDuskTeam).includes(name)).join('|'),
'',
'task-tracker and intent-guard stay outside the legacy-absent Dusk roster',
);
check(
'shared.fullDuskPolicy',
fullDuskTeam.includes('|Intent guard|legacy-absent|'),
true,
'the no-intent-guard roster carries an explicit legacy-absent policy',
);
check(
'shared.fullDuskCharsWithinCeiling',
fullDuskTeam.length <= 2800,
true,
'the complete 13-member Dusk team.md is at most 2800 characters',
);
check(
'shared.fullDuskTokensWithinCeiling',
Math.ceil(fullDuskTeam.length / 4) <= 700,
true,
'the complete 13-member Dusk team.md is at most 700 estimated tokens',
);
check(
'codex.headings',
@@ -264,7 +369,8 @@ check(
for (const literal of sharedSourceLiterals) {
const nativeLiteral = literal
.replaceAll(SOURCE_CLIENT_DIR, '.codex');
.replaceAll(SOURCE_CLIENT_DIR, '.codex')
.replaceAll(`\`\${${SOURCE_PLUGIN_ROOT}}\``, '`<plugin-root>`');
check(
`codex.sharedLiteral.${sharedSourceLiterals.indexOf(literal) + 1}`,
projectedTeam.includes(nativeLiteral),
@@ -278,6 +384,23 @@ check(
true,
'Codex path projection does not grow the shared contract',
);
const fullNativeDuskTeam = instantiateTeamTemplate(projectedTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk',
roster: DUSK_ROSTER,
policy: 'legacy-absent',
});
check(
'codex.fullDuskRosterNames',
rosterNames(fullNativeDuskTeam).join('|'),
DUSK_ROSTER.map(([name]) => name).join('|'),
'native Codex projection preserves the exact full Dusk member boundary',
);
check(
'codex.fullDuskTokensWithinCeiling',
Math.ceil(fullNativeDuskTeam.length / 4) <= 700,
true,
'native Codex full Dusk team remains at most 700 estimated tokens',
);
check(
'codex.distributedTemplateParity',
distributedTemplate,
@@ -333,6 +456,8 @@ check(
const migration = section(canonicalSkill, '### U1b: Shared Contract Migration Gate', '### U2: Analyze Performance');
for (const literal of [
'insert the canonical block before `## Agents`',
'an existing intent-guard roster row -> `required`; no row',
'-> `legacy-absent`. Never synthesize the row on the latter path.',
'Legacy agent bodies remain byte-identical during this gate.',
'**No agent may be tuned, regenerated, stripped,',
'until the shared contract passes.',
@@ -344,6 +469,20 @@ for (const literal of [
`legacy-upgrade ordering preserves ${JSON.stringify(literal)}`,
);
}
for (const literal of [
'a new team defaults to `required`',
'absence migrates\nto `legacy-absent`',
'`legacy-absent` forbids that row and MUST NOT add the role during upgrade',
'the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters',
'`ceil(chars/4) <=700` estimated tokens',
]) {
check(
`policy.workflow.${literal.slice(0, 16)}`,
canonicalSkill.includes(literal),
true,
`generator workflow preserves ${JSON.stringify(literal)}`,
);
}
const c8 = section(canonicalSkill, '### C8: Fix', '### C9: Re-verify');
check(
@@ -354,7 +493,7 @@ check(
);
const c9 = section(canonicalSkill, '### C9: Re-verify', '> To skip review pipeline');
for (const literal of [
'body only (frontmatter excluded): <=3200 bytes',
'`developer_instructions` only: <=3200 bytes',
'`Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique invariants`,',
'`Unique verification` in order with no other headings',
'`intent-guard` is exempt from this six-heading gate',
@@ -403,60 +542,48 @@ check(
const pluginVersion = (/brewcode-meta: version=([0-9]+\.[0-9]+\.[0-9]+)/.exec(canonicalSkill) || [])[1];
const contentVersion = (/content_version=([0-9]+\.[0-9]+\.[0-9]+)/.exec(canonicalSkill) || [])[1];
const today = '2026-08-27';
const BUILD_ROSTER = [['build-eng', 'Build', 'deterministic builds']];
function instantiateTeam(projectRoot) {
const intentRow = `| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | ${today} | review-only | ${pluginVersion} |`;
return `${projectedTeam
.replaceAll('{TEAM_NAME}', 'dusk')
.replaceAll('{DATE}', today)
.replaceAll('{LAST_UPDATED}', today)
.replaceAll('{PLUGIN_VERSION}', pluginVersion)
.replaceAll('{CONTENT_VERSION}', contentVersion)
.replaceAll('{N}', '1')
.replaceAll('{CWD}', projectRoot)
.replace(intentRow, `${intentRow}\n| build-eng | Build | Own deterministic build surfaces | active | ${today} | domain | ${pluginVersion} |`)}\n`;
function instantiateTeam(projectRoot, { policy = 'required', roster = BUILD_ROSTER } = {}) {
return instantiateTeamTemplate(projectedTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk', roster, policy, version: pluginVersion, contentVersion,
});
}
function agentFile({ body = runtimeRepresentativeBody, frontmatterPadding = '' } = {}) {
return `---
name: build-eng
description: Build owner. Triggers: build, release, toolchain.
${frontmatterPadding}doc_type: llm
version: "${pluginVersion}"
generated_by: "brewcode:teams-setup"
last_updated: "${today}"
---
// BEGIN RUNTIME AGENT FIXTURES
function tomlString(value) {
return JSON.stringify(value);
}
${body}`;
function agentFile({ name = 'build-eng', body = runtimeRepresentativeBody, extraField = '' } = {}) {
return `name = ${tomlString(name)}\ndescription = "Domain owner. Triggers: domain, review, verification."\ndeveloper_instructions = ${tomlString(body)}\n${extraField}`;
}
function intentGuardFile() {
return `---
name: intent-guard
description: Review-only anti-drift check.
doc_type: llm
version: "${pluginVersion}"
generated_by: "brewcode:superreview-setup"
last_updated: "${today}"
---
# Intent guard
Review only.
`;
return `name = "intent-guard"\ndescription = "Review-only anti-drift check."\ndeveloper_instructions = "Review only; never implement or mutate project files."\n`;
}
// END RUNTIME AGENT FIXTURES
function makeWorld({ teamText, agentText = agentFile(), intent = true } = {}) {
function makeWorld({
teamText,
agentText,
policy = 'required',
roster = BUILD_ROSTER,
intent = policy === 'required',
} = {}) {
const world = mkdtempSync(join(tmpdir(), 'team-profile-contract-'));
const teamDir = join(world, '.codex', 'teams', 'dusk');
const agentsDir = join(world, '.codex', 'agents');
mkdirSync(teamDir, { recursive: true });
mkdirSync(agentsDir, { recursive: true });
writeFileSync(join(teamDir, 'team.md'), teamText ?? instantiateTeam(world));
writeFileSync(join(teamDir, 'team.md'), teamText ?? instantiateTeam(world, { policy, roster }));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
writeFileSync(join(teamDir, 'trace-ops.sh'), '#!/bin/sh\nexit 0\n');
chmodSync(join(teamDir, 'trace-ops.sh'), 0o755);
writeFileSync(join(agentsDir, 'build-eng.toml'), agentText);
for (const [name] of roster) {
writeFileSync(join(agentsDir, `${name}.toml`),
name === 'build-eng' && agentText ? agentText : agentFile({ name }));
}
if (intent) writeFileSync(join(agentsDir, 'intent-guard.toml'), intentGuardFile());
return world;
}
@@ -484,24 +611,141 @@ function removeWorld(world) {
}
{
const padding = `notes: "${'x'.repeat(5000)}"\n`;
const world = makeWorld({ agentText: agentFile({ frontmatterPadding: padding }) });
const world = makeWorld({ policy: 'legacy-absent', roster: DUSK_ROSTER });
const result = runVerifier(world);
check('verifier.frontmatterExcluded', result.status, 0,
'large valid frontmatter does not consume the 3200-byte body budget');
check('verifier.frontmatterTotalOverCeiling',
Buffer.byteLength(readFileSync(join(world, '.codex', 'agents', 'build-eng.toml'))) > 3200,
true,
'the fixture proves the full file itself exceeds 3200 bytes');
check('verifier.fullDuskLegacyAbsent.exit', result.status, 0,
'the full 13-member Dusk roster passes without adding intent-guard');
check('verifier.fullDuskLegacyAbsent.policy',
result.output.includes('CHECK: Intent guard policy (legacy-absent) ... OK'), true,
'the verifier accepts the explicit no-intent-guard policy');
check('verifier.fullDuskLegacyAbsent.memberChecks',
DUSK_ROSTER.every(([name]) => result.output.includes(`CHECK: agent ${name} ... OK`)), true,
'the verifier checks every exact Dusk member');
removeWorld(world);
}
{
const world = makeWorld({ policy: 'required', intent: false });
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(/^\|intent-guard\|.*\n/m, ''));
const result = runVerifier(world);
check('verifier.requiredMissing.exit', result.status, 1,
'required policy fails when the intent-guard row is absent');
check('verifier.requiredMissing.reason',
result.output.includes('policy required needs exactly one row; found 0'), true,
'required-policy failure names the missing row');
removeWorld(world);
}
{
const world = makeWorld({ policy: 'legacy-absent', intent: true });
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const team = readFileSync(teamPath, 'utf8');
const forbiddenRow = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|`;
writeFileSync(teamPath, `${team.trim()}\n${forbiddenRow}\n`);
const result = runVerifier(world);
check('verifier.legacyAbsentRow.exit', result.status, 1,
'legacy-absent policy fails when an intent-guard row is introduced');
check('verifier.legacyAbsentRow.reason',
result.output.includes('policy legacy-absent requires zero rows; found 1'), true,
'legacy-absent failure names the forbidden roster expansion');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(
'|Intent guard|required|', '|Intent guard|optional|'));
const result = runVerifier(world);
check('verifier.invalidPolicy.exit', result.status, 1,
'an unsupported intent-guard policy fails');
check('verifier.invalidPolicy.reason',
result.output.includes("expected required or legacy-absent; found 'optional'"), true,
'the verifier enumerates the only valid policy values');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${'x'.repeat(900)}\n`);
const result = runVerifier(world);
check('verifier.teamCeiling.exit', result.status, 1,
'an oversized fully substituted team.md fails');
check('verifier.teamCeiling.reason',
result.output.includes('maximum 2800 chars and 700 ceil(chars/4) tokens'), true,
'the runtime verifier names both complete-file ceilings');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace('|Agents|1|', '|Agents|2|'));
const result = runVerifier(world);
check('verifier.agentCountMismatch.exit', result.status, 1,
'declared Agents count must equal unique domain rows');
check('verifier.agentCountMismatch.reason',
result.output.includes('declared 2, found 1 unique domain rows'), true,
'the mismatch reports declared and observed unique-domain counts');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const duplicate = `|build-eng|Build|deterministic builds|active|${today}|domain|${pluginVersion}|\n`;
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${duplicate}`);
const result = runVerifier(world);
check('verifier.duplicateDomain.exit', result.status, 1,
'duplicate domain roster names fail');
check('verifier.duplicateDomain.reason',
result.output.includes("duplicate roster name"), true,
'the verifier identifies duplicate roster identity');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const duplicate = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|\n`;
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${duplicate}`);
const result = runVerifier(world);
check('verifier.duplicateIntentGuard.exit', result.status, 1,
'required policy rejects duplicate intent-guard rows');
check('verifier.duplicateIntentGuard.reason',
result.output.includes('policy required needs exactly one row; found 2'), true,
'the verifier enforces exactly one review-only row');
removeWorld(world);
}
// BEGIN SOURCE FRONTMATTER BUDGET FIXTURE
{
const world = makeWorld({ agentText: agentFile({ extraField: 'model = "legacy"\n' }) });
const result = runVerifier(world);
check('verifier.exactTomlKeys.exit', result.status, 1, 'an unsupported fourth TOML key fails');
check('verifier.exactTomlKeys.reason', result.output.includes('TOML keys must be exactly name, description, developer_instructions'), true,
'the verifier enforces the exact native schema structurally');
removeWorld(world);
}
{
const world = makeWorld({ agentText: '---\nname: build-eng\n---\n' });
const result = runVerifier(world);
check('verifier.renamedMarkdown.exit', result.status, 1, 'renamed Markdown is not accepted as TOML');
check('verifier.renamedMarkdown.reason', result.output.includes('invalid TOML'), true,
'the verifier parses the native fixture instead of scanning YAML text');
removeWorld(world);
}
// END SOURCE FRONTMATTER BUDGET FIXTURE
{
const oversized = `${runtimeRepresentativeBody}\n${'x'.repeat(3300)}\n`;
const world = makeWorld({ agentText: agentFile({ body: oversized }) });
const result = runVerifier(world);
check('verifier.bodyCeiling.exit', result.status, 1, 'an oversized body fails even with small frontmatter');
check('verifier.bodyCeiling.reason', result.output.includes('ceiling is 3200 (~800 est-tokens), frontmatter excluded'), true,
check('verifier.bodyCeiling.exit', result.status, 1, 'an oversized developer_instructions value fails');
check('verifier.bodyCeiling.reason', result.output.includes('ceilings are 3200 bytes and 800 ceil(chars/4) tokens'), true,
'the failure names the body-only contract');
removeWorld(world);
}
@@ -530,6 +774,7 @@ for (const [index, literal] of instantiatedLosses.entries()) {
removeWorld(world);
}
// BEGIN SOURCE LEGACY AGENT FIXTURE
{
const legacyTeam = `# Team: dusk
@@ -552,11 +797,10 @@ for (const [index, literal] of instantiatedLosses.entries()) {
const legacyBody = '## Domain Instructions\n\nLegacy acceptance and trace rules remain local until upgrade.\n';
const world = makeWorld({ teamText: legacyTeam, agentText: agentFile({ body: legacyBody }), intent: false });
const result = runVerifier(world);
check('verifier.legacyMigrationSafe.exit', result.status, 0,
'a fully legacy team remains runnable while upgrade is required');
check('verifier.legacyMigrationSafe.exit', result.status, 1,
'a structurally parsed native agent without six headings fails');
check('verifier.legacyMigrationSafe.warning',
result.output.includes('has no Shared Agent Contract (legacy team)')
&& result.output.includes('legacy repeated/unknown profile shape'),
result.output.includes('body headings must be exactly the six ordered teams-setup headings in developer_instructions'),
true,
'legacy authority and legacy profile produce migration warnings without destructive failure');
removeWorld(world);
@@ -569,6 +813,7 @@ for (const [index, literal] of instantiatedLosses.entries()) {
'the verifier directs repair of the shared authority before profile stripping');
removeWorld(interrupted);
}
// END SOURCE LEGACY AGENT FIXTURE
for (const [name, mutate, reason] of [
['firstReference', (text) => text.replace('.codex/teams/dusk/team.md', '.codex/teams/other/team.md'),
@@ -584,22 +829,36 @@ for (const [name, mutate, reason] of [
removeWorld(world);
}
{
for (const [name, mutate] of [
['domain', (row) => row.replace('|--|', '|code|')],
['mission', (row) => row.replace('Anti-drift check: what was ASKED vs what was DELIVERED', 'Implementation owner')],
['status', (row) => row.replace('|active|', '|inactive|')],
['updated', (row) => row.replace(`|${today}|review-only|`, '|2026-08-26|review-only|')],
['kind', (row) => row.replace('|review-only|', '|domain|')],
['version', (row) => row.replace(`|${pluginVersion}|`, '|0.0.0|')],
]) {
const world = makeWorld();
const teamPath = join(world, '.codex', 'teams', 'dusk', 'team.md');
const team = readFileSync(teamPath, 'utf8');
writeFileSync(teamPath, team.replace(
`| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | ${today} | review-only | ${pluginVersion} |`,
`| intent-guard | code | Implementation owner | active | ${today} | domain | ${pluginVersion} |`,
));
const fixedRow = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|`;
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(fixedRow, mutate(fixedRow)));
const result = runVerifier(world);
check('verifier.intentGuardScope.exit', result.status, 1,
'changing the fixed intent-guard scope/kind fails');
check('verifier.intentGuardScope.reason', result.output.includes('intent-guard roster contract ... FAIL'), true,
'the verifier protects the review-only exemption in the instantiated roster');
check(`verifier.intentGuardFixed.${name}.exit`, result.status, 1,
`changing fixed intent-guard ${name} fails`);
check(`verifier.intentGuardFixed.${name}.reason`,
result.output.includes('fixed cells require --, anti-drift mission, active, team Last update, review-only, and team Version'), true,
'the verifier protects every fixed review-only cell');
removeWorld(world);
}
const nativeVerifier = readFileSync(verifierPath, 'utf8');
check('codex.verifier.tomllib', nativeVerifier.includes('import tomllib'), true,
'native verifier parses TOML structurally');
check('codex.verifier.noYamlParser', nativeVerifier.includes('NR == 1 && $0 == "---"'), false,
'native verifier has no YAML fence parser');
check('codex.verifier.exactKeys',
nativeVerifier.includes('required = {"name", "description", "developer_instructions"}'), true,
'native verifier pins the exact supported top-level schema');
console.log('suite-agent-profile-contract.mjs');
for (const line of results) console.log(line);
console.log(` ${passed} passed, ${failed} failed`);
+52 -158
View File
@@ -1,190 +1,84 @@
#!/usr/bin/env node
/**
* Suite B intent-guard provenance (superreview-setup/scripts/generate.sh emit-agent), the ONE writer
* of .codex/agents/intent-guard.toml that $brewcode:teams-setup Phase 3 calls.
* Covers BCOP09: the runnability tests used to run before the provenance probes, so a hand-written
* agent that merely mentioned a `{TOKEN}` was classified BROKEN and overwritten with no backup.
* Runs entirely inside an isolated temp base; never touches the real ~/.codex or the repo tree.
* Assertion policy: unconditional exact-equality checks with a description.
*/
import { spawnSync } from 'node:child_process';
import {
mkdtempSync, mkdirSync, writeFileSync, readFileSync, readdirSync, rmSync, realpathSync,
} from 'node:fs';
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { fileURLToPath } from 'node:url';
const HERE = join(fileURLToPath(import.meta.url), '..');
const GENERATE = join(HERE, '..', '..', 'superreview-setup', 'scripts', 'generate.sh');
const BASE = realpathSync(mkdtempSync(join(tmpdir(), 'teams-intent-guard-')));
const IG_REL = '.codex/agents/intent-guard.toml';
const STAMP = '<!-- generated_by: brewcode:superreview-setup v9.9.9 -->';
const LEGACY_STAMP = '<!-- intent-guard template v2 - emitted 2025-01-01 - source: fixture -->';
const EMIT = join(HERE, '..', '..', 'superreview-setup', 'scripts', 'emit-intent-guard.sh');
const TEMPLATE = join(HERE, '..', '..', 'superreview-setup', 'references', 'intent-guard.toml.template');
let passed = 0;
let failed = 0;
const results = [];
function check(name, actual, expected, message) {
function check(name, actual, expected, description) {
if (actual === expected) {
passed++;
results.push(` PASS ${name} (${message})`);
passed += 1;
results.push(' PASS ' + name + ' (' + description + ')');
} else {
failed++;
results.push(
` FAIL ${name} (${message} | actual=${JSON.stringify(actual)} expected=${JSON.stringify(expected)})`,
);
failed += 1;
results.push(' FAIL ' + name + ' (' + description + ' | actual=' + JSON.stringify(actual) + ' expected=' + JSON.stringify(expected) + ')');
}
}
/** A project root with an optional pre-existing intent-guard.toml. */
function makeProject(label, body) {
const root = join(BASE, label);
mkdirSync(join(root, '.codex', 'agents'), { recursive: true });
if (body !== null) writeFileSync(join(root, IG_REL), body);
return root;
function run(root) {
const result = spawnSync('bash', [EMIT, root], { encoding: 'utf8', timeout: 30000 });
return { status: result.status, output: (result.stdout || '') + (result.stderr || '') };
}
function emitAgent(root) {
const r = spawnSync('bash', [GENERATE, 'emit-agent'], { cwd: root, encoding: 'utf8', timeout: 30000 });
return { stdout: (r.stdout || '').trim(), stderr: r.stderr || '', status: r.status };
function parse(path) {
const result = spawnSync('python3', ['-c', 'import json,pathlib,sys,tomllib; print(json.dumps(tomllib.loads(pathlib.Path(sys.argv[1]).read_text()), sort_keys=True))', path], { encoding: 'utf8' });
return { status: result.status, data: result.status === 0 ? JSON.parse(result.stdout) : null };
}
const agentNames = (root) => readdirSync(join(root, '.codex', 'agents')).sort();
const backups = (root) =>
agentNames(root).filter((n) => /^intent-guard\.toml\.bak-[0-9]{8}-[0-9]{6}$/.test(n));
const read = (root, rel) => readFileSync(join(root, rel), 'utf8');
const template = parse(TEMPLATE);
check('template.parse', template.status, 0, 'shared native template is valid TOML');
check('template.keys', Object.keys(template.data).sort().join(','), 'description,developer_instructions,name', 'template has exactly three keys');
check('template.name', template.data.name, 'intent-guard', 'template name is fixed');
const FOREIGN_WITH_TOKEN = [
'---',
'name: intent-guard',
'description: our own hand-written drift check',
'---',
'',
'# intent-guard',
'',
'Use {REQUEST_ID} to correlate the review with the ticket.',
'',
].join('\n');
// ────────────────────────────────────────────────────────────────────────────
// B1 — BCOP09: an UNSTAMPED file carrying a {TOKEN} is the project's own agent.
// REUSE, byte-identical, no backup, tokens reported as a conflict.
// ────────────────────────────────────────────────────────────────────────────
{
const root = makeProject('b1', FOREIGN_WITH_TOKEN);
const r = emitAgent(root);
check('b1.status', r.status, 0, 'emit-agent succeeds on a foreign agent');
check('b1.stdout', r.stdout, `INTENT_GUARD: REUSE ${IG_REL}`, 'exactly one status line, and it is REUSE');
check('b1.bytes', read(root, IG_REL), FOREIGN_WITH_TOKEN, 'the hand-written file is byte-identical');
check('b1.backupCount', backups(root).length, 0, 'nothing was backed up because nothing was rewritten');
check('b1.tree', agentNames(root).join(','), 'intent-guard.toml', 'no extra file was created');
check(
'b1.conflictReported',
r.stderr.includes('{REQUEST_ID}'),
true,
'the token is reported on stderr as a conflict',
);
const root = mkdtempSync(join(tmpdir(), 'native-intent-create-'));
const result = run(root);
const target = join(root, '.codex', 'agents', 'intent-guard.toml');
check('create.exit', result.status, 0, 'first run succeeds');
check('create.verdict', result.output.trim(), 'INTENT_GUARD: CREATED .codex/agents/intent-guard.toml', 'first run reports creation');
check('create.bytes', readFileSync(target, 'utf8'), readFileSync(TEMPLATE, 'utf8'), 'created file equals shared authority byte-for-byte');
check('create.parse', parse(target).status, 0, 'created file remains structurally valid TOML');
rmSync(root, { recursive: true, force: true });
}
// ────────────────────────────────────────────────────────────────────────────
// B2 — an unstamped file WITHOUT `name: intent-guard` frontmatter is still
// foreign: unrunnable by our rules, but not ours to overwrite.
// ────────────────────────────────────────────────────────────────────────────
{
const body = '# somebody else\n\nnotes about {TICKET_ID}\n';
const root = makeProject('b2', body);
const r = emitAgent(root);
check('b2.stdout', r.stdout, `INTENT_GUARD: REUSE ${IG_REL}`, 'REUSE, not RECREATE');
check('b2.bytes', read(root, IG_REL), body, 'a foreign file without our frontmatter survives byte-identical');
check('b2.backupCount', backups(root).length, 0, 'no backup, because no write');
const root = mkdtempSync(join(tmpdir(), 'native-intent-reuse-'));
const agents = join(root, '.codex', 'agents');
mkdirSync(agents, { recursive: true });
const target = join(agents, 'intent-guard.toml');
const foreign = 'name = "intent-guard"\ndescription = "Foreign review-only agent."\ndeveloper_instructions = "Review only; preserve these bytes."\n';
writeFileSync(target, foreign);
const result = run(root);
check('reuse.exit', result.status, 0, 'valid existing native agent is reused');
check('reuse.verdict', result.output.trim(), 'INTENT_GUARD: REUSE .codex/agents/intent-guard.toml', 'reuse is explicit');
check('reuse.bytes', readFileSync(target, 'utf8'), foreign, 'reuse preserves foreign bytes');
rmSync(root, { recursive: true, force: true });
}
// ────────────────────────────────────────────────────────────────────────────
// B3 — control: the same foreign file with no token at all also REUSEs. This is
// the pre-fix behaviour and must not change.
// ────────────────────────────────────────────────────────────────────────────
{
const body = FOREIGN_WITH_TOKEN.replace('{REQUEST_ID}', 'the ticket id');
const root = makeProject('b3', body);
const r = emitAgent(root);
check('b3.stdout', r.stdout, `INTENT_GUARD: REUSE ${IG_REL}`, 'token-free foreign file reuses too');
check('b3.bytes', read(root, IG_REL), body, 'byte-identical');
check('b3.stderrEmpty', r.stderr, '', 'no conflict to report, so stderr stays silent');
for (const [name, body, reason] of [
['renamedMarkdown', '---\nname: intent-guard\n---\n', 'invalid TOML'],
['extraKey', 'name = "intent-guard"\ndescription = "Review."\ndeveloper_instructions = "Review."\nmodel = "legacy"\n', 'keys must be exactly'],
]) {
const root = mkdtempSync(join(tmpdir(), 'native-intent-' + name + '-'));
const agents = join(root, '.codex', 'agents');
mkdirSync(agents, { recursive: true });
const target = join(agents, 'intent-guard.toml');
writeFileSync(target, body);
const result = run(root);
check(name + '.exit', result.status, 1, 'invalid existing artifact fails closed');
check(name + '.reason', result.output.includes(reason), true, 'failure names the structural defect');
check(name + '.bytes', readFileSync(target, 'utf8'), body, 'failure never overwrites existing bytes');
rmSync(root, { recursive: true, force: true });
}
// ────────────────────────────────────────────────────────────────────────────
// B4 — OUR OWN stamped file with an unresolved token is BROKEN: recreated, but
// only after its bytes are copied to <path>.bak-<ts>.
// ────────────────────────────────────────────────────────────────────────────
{
const body = ['---', 'name: intent-guard', '---', '', 'half-substituted {PROJECT_NAME}', '', STAMP, ''].join('\n');
const root = makeProject('b4', body);
const r = emitAgent(root);
const bak = backups(root);
check('b4.stdout', r.stdout, `INTENT_GUARD: CREATED ${IG_REL}`, 'our own broken file is recreated');
check('b4.backupCount', bak.length, 1, 'exactly one backup was written');
check(
'b4.backupBytes',
// concatenation, not indexing: zero backups yields '' and fails the check instead of throwing
bak.map((n) => read(root, join('.codex', 'agents', n))).join(''),
body,
'the backup holds the original bytes verbatim',
);
check(
'b4.recreated',
read(root, IG_REL).includes('<!-- generated_by: brewcode:superreview-setup'),
true,
'the live file now carries the current tail anchor',
);
}
// ────────────────────────────────────────────────────────────────────────────
// B5 — an EMPTY file is BROKEN with nothing to lose: recreated, no backup.
// ────────────────────────────────────────────────────────────────────────────
{
const root = makeProject('b5', '');
const r = emitAgent(root);
check('b5.stdout', r.stdout, `INTENT_GUARD: CREATED ${IG_REL}`, 'an empty file is recreated');
check('b5.backupCount', backups(root).length, 0, 'an empty file has no bytes worth backing up');
}
// ────────────────────────────────────────────────────────────────────────────
// B6 — a pre-standard file OF OURS still MIGRATEs: metadata only, body kept.
// ────────────────────────────────────────────────────────────────────────────
{
const marker = 'TAILORED-LINE-KEEP-ME';
const body = ['---', 'name: intent-guard', '---', '', `## 1. Scope`, '', marker, '', LEGACY_STAMP, ''].join('\n');
const root = makeProject('b6', body);
const r = emitAgent(root);
check('b6.stdout', r.stdout, `INTENT_GUARD: MIGRATED ${IG_REL}`, 'the retired stamp triggers a restamp');
check('b6.bodyKept', read(root, IG_REL).includes(marker), true, 'the tailored body line survived the migration');
check('b6.backupCount', backups(root).length, 0, 'a migration rewrites metadata only, so no backup is needed');
}
// ────────────────────────────────────────────────────────────────────────────
// B7 — no file at all: CREATE, the ordinary first-run path.
// ────────────────────────────────────────────────────────────────────────────
{
const root = makeProject('b7', null);
const r = emitAgent(root);
check('b7.status', r.status, 0, 'first run succeeds');
check('b7.stdout', r.stdout, `INTENT_GUARD: CREATED ${IG_REL}`, 'the agent is created from the template');
check('b7.tree', agentNames(root).join(','), 'intent-guard.toml', 'exactly one file, no backups');
}
// ── report ──────────────────────────────────────────────────────────────────
rmSync(BASE, { recursive: true, force: true });
console.log('suite-intent-guard.mjs');
for (const line of results) console.log(line);
console.log(` ${passed} passed, ${failed} failed`);
console.log(' ' + passed + ' passed, ' + failed + ' failed');
process.exit(failed === 0 ? 0 : 1);
+25 -24
View File
@@ -77,7 +77,10 @@ function summary(stdout) {
const linesStartingWith = (stdout, prefix) =>
stdout.split('\n').filter((l) => l.startsWith(prefix));
const AGENT_BODY = (name) => `---\nname: ${name}\ndescription: fixture agent\n---\n\n# ${name}\n`;
const DOMAIN_INSTRUCTIONS = '## Mission\nOwn fixture behavior.\n\n## Owned surfaces\nFixture files.\n\n## Exclusions\nNo neighboring work.\n\n## Must-load references\n- `.codex/teams/t1/team.md`\n\n## Unique invariants\nPreserve bytes.\n\n## Unique verification\nRun the fixture suite.\n';
const AGENT_BODY = (name) => name === 'intent-guard'
? `name = "intent-guard"\ndescription = "Review-only fixture."\ndeveloper_instructions = "Review only; never implement."\n`
: `name = ${JSON.stringify(name)}\ndescription = "Domain fixture agent."\ndeveloper_instructions = ${JSON.stringify(DOMAIN_INSTRUCTIONS)}\n`;
/**
* The `## Agents` header separator, in the three spellings the parser must tell apart: the compact
@@ -93,6 +96,26 @@ const SEPARATORS = {
* A project root with one team. `rows` are `## Agents` Agent-column values, in table order;
* `agentFiles` are the names actually written to .codex/agents/.
*/
const NATIVE_TEAM_TEMPLATE = "# Team: {TEAM_NAME}\n|Field|Value|\n|---|---|\n|Created|{DATE}|\n|Version|{PLUGIN_VERSION}|\n|Content version|{CONTENT_VERSION}|\n|Generated by|brewcode:teams-setup|\n|Last update|{LAST_UPDATED}|\n|Agents|{N}|\n|Intent guard|{INTENT_GUARD_POLICY}|\n|Project|{CWD}|\n\n## Shared Agent Contract\nEvery domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.\nBefore any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.\nOptional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.\n`T=\".codex/teams/{TEAM_NAME}\"; bash \"$T/trace-ops.sh\" add \"$T\" \"$SID\" \"{AGENT_NAME}\" \"<kind>\" \"<state>\" \"<text>\"`\nTrack states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.\nA task traced `took` ends with exactly one terminal track: `completed` or `failed`.\nVerdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.\nActual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.codex/convention/*` first), additive to rules/conventions/docs, !=replace them.\n\n## Agents\n|Agent|Domain|Mission|Status|Updated|Kind|Version|\n|---|---|---|---|---|---|---|\n{INTENT_GUARD_ROW}";
function nativeTeam(root, rows, separator = 'compact') {
const intent = rows.includes('intent-guard');
const domainRows = rows.filter((name) => name !== 'intent-guard');
const intentRow = intent ? '|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|6.1.4|' : '';
const roster = rows.map((name) => name === 'intent-guard' ? intentRow : `|${name}|api|fixture mission|active|2026-08-27|domain|6.1.4|`).join('\n');
const rendered = `${NATIVE_TEAM_TEMPLATE
.replaceAll('{TEAM_NAME}', 't1')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', '6.1.4')
.replaceAll('{CONTENT_VERSION}', '6.1.0')
.replaceAll('{N}', String(domainRows.length))
.replaceAll('{CWD}', root)
.replaceAll('{INTENT_GUARD_POLICY}', intent ? 'required' : 'legacy-absent')
.replaceAll('{INTENT_GUARD_ROW}', roster)}\n`;
const separators = { compact: '|---|---|---|---|---|---|---|', padded: '| --- | --- | --- | --- | --- | --- | --- |', none: '' };
return rendered.replace('|---|---|---|---|---|---|---|', separators[separator]);
}
function makeProject(label, rows, agentFiles, separator = 'compact') {
const root = join(BASE, label, 'proj');
const teamDir = join(root, '.codex', 'teams', 't1');
@@ -101,29 +124,7 @@ function makeProject(label, rows, agentFiles, separator = 'compact') {
const rosterRows = rows
.map((a) => `| ${a} | api | fixture mission | active | 2026-08-16 | domain | 6.0.0 |`)
.join('\n');
writeFileSync(
join(teamDir, 'team.md'),
[
'# Team: t1',
'',
'| Field | Value |',
'|-------|-------|',
'| Created | 2026-08-16 |',
'| Version | 6.0.0 |',
'| Content version | 6.0.0 |',
'| Generated by | brewcode:teams-setup |',
'| Last update | 2026-08-16 |',
`| Agents | ${rows.length} |`,
`| Project | ${root} |`,
'',
'## Agents',
'',
'| Agent | Domain | Mission | Status | Updated | Kind | Version |',
SEPARATORS[separator],
rosterRows,
'',
].filter((l) => l !== null).join('\n'),
);
writeFileSync(join(teamDir, 'team.md'), nativeTeam(root, rows, separator));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
for (const f of agentFiles) writeFileSync(join(root, '.codex', 'agents', `${f}.toml`), AGENT_BODY(f));
return root;
+26 -25
View File
@@ -88,39 +88,40 @@ function verifyCounts(stdout) {
return out;
}
const AGENT_BODY = (name) => `---\nname: ${name}\ndescription: fixture agent\n---\n\n# ${name}\n`;
const FOREIGN_BODY = '---\nname: worker-one\ndescription: written by SOMEONE ELSE\n---\n\n# hands off\n';
const DOMAIN_INSTRUCTIONS = '## Mission\nOwn fixture behavior.\n\n## Owned surfaces\nFixture files.\n\n## Exclusions\nNo neighboring work.\n\n## Must-load references\n- `.codex/teams/t1/team.md`\n\n## Unique invariants\nPreserve bytes.\n\n## Unique verification\nRun the fixture suite.\n';
const AGENT_BODY = (name) => name === 'intent-guard'
? `name = "intent-guard"\ndescription = "Review-only fixture."\ndeveloper_instructions = "Review only; never implement."\n`
: `name = ${JSON.stringify(name)}\ndescription = "Domain fixture agent."\ndeveloper_instructions = ${JSON.stringify(DOMAIN_INSTRUCTIONS)}\n`;
const FOREIGN_BODY = `name = "worker-one"\ndescription = "Foreign fixture."\ndeveloper_instructions = "Foreign bytes; not team-owned."\n`;
const SEP = '|-------|--------|---------|--------|---------|------|---------|';
/** A project root with one team whose roster is `rows`; every row also gets a live agent file. */
const NATIVE_TEAM_TEMPLATE = "# Team: {TEAM_NAME}\n|Field|Value|\n|---|---|\n|Created|{DATE}|\n|Version|{PLUGIN_VERSION}|\n|Content version|{CONTENT_VERSION}|\n|Generated by|brewcode:teams-setup|\n|Last update|{LAST_UPDATED}|\n|Agents|{N}|\n|Intent guard|{INTENT_GUARD_POLICY}|\n|Project|{CWD}|\n\n## Shared Agent Contract\nEvery domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.\nBefore any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.\nOptional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.codex/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`<plugin-root>` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.\n`T=\".codex/teams/{TEAM_NAME}\"; bash \"$T/trace-ops.sh\" add \"$T\" \"$SID\" \"{AGENT_NAME}\" \"<kind>\" \"<state>\" \"<text>\"`\nTrack states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.\nA task traced `took` ends with exactly one terminal track: `completed` or `failed`.\nVerdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.codex/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.\nActual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.codex/convention/*` first), additive to rules/conventions/docs, !=replace them.\n\n## Agents\n|Agent|Domain|Mission|Status|Updated|Kind|Version|\n|---|---|---|---|---|---|---|\n{INTENT_GUARD_ROW}";
function nativeTeam(root, rows, separator = 'compact') {
const intent = rows.includes('intent-guard');
const domainRows = rows.filter((name) => name !== 'intent-guard');
const intentRow = intent ? '|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|6.1.4|' : '';
const roster = rows.map((name) => name === 'intent-guard' ? intentRow : `|${name}|api|fixture mission|active|2026-08-27|domain|6.1.4|`).join('\n');
const rendered = `${NATIVE_TEAM_TEMPLATE
.replaceAll('{TEAM_NAME}', 't1')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', '6.1.4')
.replaceAll('{CONTENT_VERSION}', '6.1.0')
.replaceAll('{N}', String(domainRows.length))
.replaceAll('{CWD}', root)
.replaceAll('{INTENT_GUARD_POLICY}', intent ? 'required' : 'legacy-absent')
.replaceAll('{INTENT_GUARD_ROW}', roster)}\n`;
const separators = { compact: '|---|---|---|---|---|---|---|', padded: '| --- | --- | --- | --- | --- | --- | --- |', none: '' };
return rendered.replace('|---|---|---|---|---|---|---|', separators[separator]);
}
function makeProject(label, rows) {
const root = join(BASE, label, 'proj');
const teamDir = join(root, '.codex', 'teams', 't1');
mkdirSync(join(root, '.codex', 'agents'), { recursive: true });
mkdirSync(teamDir, { recursive: true });
writeFileSync(
join(teamDir, 'team.md'),
[
'# Team: t1',
'',
'| Field | Value |',
'|-------|-------|',
'| Created | 2026-08-16 |',
'| Version | 6.0.0 |',
'| Content version | 6.0.0 |',
'| Generated by | brewcode:teams-setup |',
'| Last update | 2026-08-16 |',
`| Agents | ${rows.length} |`,
`| Project | ${root} |`,
'',
'## Agents',
'',
'| Agent | Domain | Mission | Status | Updated | Kind | Version |',
SEP,
...rows.map((a) => `| ${a} | api | fixture mission | active | 2026-08-16 | domain | 6.0.0 |`),
'',
].join('\n'),
);
writeFileSync(join(teamDir, 'team.md'), nativeTeam(root, rows));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
for (const a of rows) writeFileSync(join(root, '.codex', 'agents', `${a}.toml`), AGENT_BODY(a));
return root;
+12 -3
View File
@@ -94,7 +94,7 @@ optimize | resume`; `/brewcode:teams-setup` keeps a `[name]` positional after th
|-------|---------|
| [`/brewcode:setup-status`](skills/setup-status/README.md) | Read-only cross-plugin dashboard: which setup skills are installed, stale, partial or missing here, with the exact command to run for each. Runs no setup itself |
| [`/brewcode:superreview-setup`](skills/superreview-setup/README.md) | Generate a project-tailored deep-review skill: `QUICK` (default, `intent-guard` + mechanical gates) or `EXTENDED` (adds domain-expert fan-out, scope discipline, adversarial validation) depth, read from your prompt |
| [`/brewcode:teams-setup`](skills/teams-setup/README.md) | Dynamic agent team creation, management, and performance tracking -- every team also gets a fixed review-only `intent-guard` member (not counted in team size) |
| [`/brewcode:teams-setup`](skills/teams-setup/README.md) | Dynamic agent team creation, management, and tracking. New teams get one review-only `intent-guard`; upgrades preserve a legacy roster with none instead of adding it |
| [`/brewcode:semble-setup`](skills/semble-setup/README.md) | Semantic code search setup: installs the pinned semble_code MCP, shared content-variant cache, semble-first rule + hooks, agent migration |
| [`/brewcode:convention`](skills/convention/README.md) | Extract etalon classes, patterns, architecture into convention docs and rules |
| [`/brewcode:rules`](skills/rules/README.md) | Prompt-driven rules management: status, create, improve, review |
@@ -123,9 +123,18 @@ optimize | resume`; `/brewcode:teams-setup` keeps a `[name]` positional after th
| [bash-expert](agents/bash-expert.md) | inherit | Creates sh/bash scripts for Mac/Linux |
| bc-rules-organizer | haiku | Internal: spawned by /brewcode:rules |
> **No generic agents:** brewcode ships specialists only. Implementation, testing, review and architecture work goes to project-specific agents in `.claude/agents/` — generate them with `/brewcode:teams-setup install` (5-20 domain agents with self-selection protocol and performance tracking, plus one fixed review-only `intent-guard`).
> **No generic agents:** brewcode ships specialists only. Implementation, testing, review and architecture
> work goes to project-specific agents generated with `/brewcode:teams-setup install`. New teams add exactly
> one review-only `intent-guard` outside the 5-20 domain count. Existing teams without that role retain an
> explicit `intent_guard_policy=required|legacy-absent`: new teams use `required`, while upgrade preserves
> `legacy-absent` and never adds the role.
> **Scope guard:** every agent carries a `## Scope guard` -- if a task exceeds one bounded unit (one deliverable, ~5 files), the agent stops and proposes a split instead of running for an hour.
> **Generated profiles:** shared acceptance, routing, tracing, return, scope-fit and colleague rules live
> once in `team.md`. Each domain agent contains exactly six ordered sections: Mission, Owned surfaces,
> Exclusions, Must-load references, Unique invariants and Unique verification. Claude Code discovers
> `.claude/agents/*.md`; Codex uses native `.codex/agents/*.toml`, with no YAML-in-TOML guidance. Project
> Dusk deliberately remains 13 members: `task-tracker` is not a team member and
> `Intent guard: legacy-absent` means no `intent-guard` row or profile.
## Architecture
+42 -19
View File
@@ -1,6 +1,6 @@
# Teams
Create and manage dynamic teams of domain-specific agents with a tracking framework. Analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking. Every team also gets one fixed review-only member, `intent-guard`.
Create and manage dynamic teams of domain-specific agents with a tracking framework. The skill analyzes your project, proposes 5-20 specialized agents, creates them, and sets up performance tracking. A new team also gets exactly one review-only `intent-guard`; an upgraded legacy team with none stays that way.
## Quick Start
@@ -28,7 +28,7 @@ The verb always comes first and the optional `<name>` after it. That parser guar
`disable` is a rename, not a deletion — the roster rows stay in `team.md` with `Status: disabled`, and `verify-team.sh` reports `DISABLED` per parked member and still exits PASS. `enable` puts it all back. Both take effect for the NEXT session: agent discovery is read at session start.
`purge` keeps exactly one thing: `.claude/agents/intent-guard.md`, shared with `/brewcode:superreview-setup`. It removes both `<agent>.md` and `<agent>.md.disabled`, so purging a disabled team leaves nothing behind.
`purge` removes both `<agent>.md` and `<agent>.md.disabled`, so purging a disabled team leaves no owned domain profile behind. When `Intent guard` is `required`, it keeps `.claude/agents/intent-guard.md` because that file is shared with `/brewcode:superreview-setup`; `legacy-absent` has no guard to keep.
## Examples
@@ -83,7 +83,7 @@ After `/brewcode:teams-setup install my-team`:
agents/
agent-one.md # Domain agents (5-20 depending on variant)
agent-two.md
intent-guard.md # Fixed review-only member, every team, not counted
intent-guard.md # One review-only member for policy `required`; not counted
teams/
my-team/
team.md # Roster: agent list, domains, missions, status
@@ -91,11 +91,20 @@ After `/brewcode:teams-setup install my-team`:
trace-ops.sh # Tracer, copied from the plugin at install -- agents call THIS path
```
`team.md` stores logical `intent_guard_policy=required|legacy-absent` in its `Intent guard` field.
`required` means the roster contains exactly one `intent-guard` row. `legacy-absent` means it contains
zero such rows; upgrade preserves that state and never creates the role. New installs default to
`required`.
Claude Code domain profiles are Markdown files under `.claude/agents/`. The Codex projection uses native
TOML files under `.codex/agents/`; it carries no YAML-in-TOML guidance.
## How Agents Work
Created agents follow the **Task Acceptance Protocol** -- they self-select tasks based on domain fit, record acceptance/refusal in `trace.jsonl`, and log issues and insights as they work.
Every generated domain agent is also born with a **Return Contract**: verdict first, <=30 lines, `path:line`, no file bodies, no command output, no logs, no preamble -- bulk material goes to `.claude/reports/` and only the path comes back. It holds whether or not `/brewtools:agent-return-setup` is installed; the guard only adds mechanical thresholds. `verify-team.sh` warns on an older agent that lacks the section, and `upgrade` re-adds it.
Created agents load `team.md`, whose single **Shared Agent Contract** owns acceptance, routing, tracing,
return, scope-fit and colleague rules. Domain profiles do not repeat those contracts. Their bodies have
exactly six ordered headings: `Mission`, `Owned surfaces`, `Exclusions`, `Must-load references`, `Unique
invariants`, and `Unique verification`.
They write through the project-local copy of the tracer:
@@ -125,7 +134,7 @@ The `upgrade` mode uses this data to tune agent instructions, replace underperfo
|
v
[C2] Team Proposal ------ 3 variants + user confirmation
(+ intent-guard, fixed, not counted)
(+ one intent-guard for new teams, not counted)
|
v
[C2.5] Model Selection -- opus / sonnet / haiku / mixed (domain agents only)
@@ -134,7 +143,7 @@ The `upgrade` mode uses this data to tune agent instructions, replace underperfo
[C3] Agent Creation ----- agent-creator x N (batches of 3-4)
|
v
[C3-IG] intent-guard ---- generate.sh emit-agent (create or reuse), then adapt if created
[C3-IG] intent-guard ---- required: emit/reuse; legacy-absent: do nothing
|
v
[C4] Framework Setup ---- team.md + trace.jsonl + trace-ops.sh + verification
@@ -171,22 +180,32 @@ After agent creation, a quality pipeline validates the team:
> Skip with `--skip-review`. Run separately: `/brewcode:teams-setup upgrade <name> --review`
> `intent-guard` is never used as a reviewer in this pipeline, and it is judged by different criteria than domain agents: placeholders resolved, template header stripped, frontmatter untouched (short review-only description, read-only tools). "Missing domain sections" is a false positive for it.
> When policy is `required`, `intent-guard` is not a reviewer in this pipeline and is judged by its own
> review-only contract. The six-heading domain-profile gate does not apply to it. Under `legacy-absent`,
> there is no guard to review.
## intent-guard (always in the team)
## intent-guard policy
Every team gets `intent-guard` in addition to its domain agents. It is an **anti-drift check**: it compares what was **ASKED** (the original request, ticket, spec, plan, project policy) against what was **DELIVERED**, and reports the delta.
`team.md` has exactly one `Intent guard` policy field:
| Policy | Roster contract | Upgrade behavior |
|--------|-----------------|------------------|
| `required` | Exactly one review-only `intent-guard` row, outside the domain-agent count | Preserve the row; never duplicate it |
| `legacy-absent` | Zero `intent-guard` rows | Preserve absence; never create the role |
New installs use `required`. The role is an **anti-drift check**: it compares what was **ASKED** (the
original request, ticket, spec, plan, project policy) against what was **DELIVERED**, and reports the delta.
| Property | Value |
|----------|-------|
| Counted in the 5 / 10-12 / 15-20 roster? | No -- it is outside the domain-agent count and cannot be dropped |
| Counted in the 5 / 10-12 / 15-20 roster? | No -- when required, it is outside the domain-agent count |
| Tools | Read-only (`Read`, `Glob`, `Grep`, `Bash`). Never edits, builds, or runs tests |
| Model | `sonnet`, fixed by its template -- not affected by the C2.5 model choice |
| Invocation | Explicit, by name, during review only -- never during development, never an implementation owner |
| Source | Emitted by `skills/superreview-setup/scripts/generate.sh emit-agent` from the shared template -- the single writer of this file, used by both skills |
| Output | Verdict `ALIGNED` / `MINOR DRIFT` / `MAJOR DRIFT` plus <=10 findings, each with ASKED / SOURCE+tier / DELIVERED evidence / severity / minimal correction |
**Single writer (idempotent):** `teams` never authors this file. It runs
**Single writer (idempotent, `required` only):** `teams` never authors this file. It runs
`superreview-setup/scripts/generate.sh emit-agent`, which creates it from the shared template or reuses an
existing one and prints `INTENT_GUARD: CREATED|REUSE|MIGRATED <path>`. On `REUSE` -- typically because
`/brewcode:superreview-setup` ran first -- the file is left exactly as is and only the `team.md` roster row is
@@ -196,14 +215,16 @@ invariants, drift examples, evidence commands) and touches nothing else -- front
as emitted. Both skills therefore converge on one shared file produced by one pipeline, never two
variants.
`intent-guard` is also excluded from `upgrade` and `uninstall` agent pruning (enforced in the cleanup flow
itself, Step 3, including a refusal if it is named explicitly): it does not write trace entries, so zero
activity is its normal state, not a reason to delete it. Teams created before `intent-guard` existed are
not broken by this -- `verify-team.sh` only WARNs, with the command to add it.
When policy is `required`, `intent-guard` is excluded from `upgrade` and `uninstall` pruning. It does not
write trace entries, so zero activity is normal. Teams created before the role existed can be upgraded
without it: the migration writes `legacy-absent`, retains zero rows, and does not emit a profile.
Project Dusk is the compatibility baseline for this path: its roster stays at 13 members;
`task-tracker` remains a non-member owner, and `Intent guard: legacy-absent` keeps `intent-guard` absent.
## Task Acceptance Protocol
Each agent follows a 3-step self-selection before accepting a task:
The shared contract in `team.md` gives every domain agent the same 3-step self-selection before accepting a task:
| # | Check | Question | If No |
|---|-------|----------|-------|
@@ -228,7 +249,9 @@ When other skills (convention, superreview, e2e) spawn agents, they check for te
> If a team agent refuses a task (Task Acceptance Protocol), the skill re-delegates to the next priority level. Max 2 retries before falling back to system agents.
> `intent-guard` is outside this resolution chain -- it is never selected as an implementation or review owner by domain fit. It runs only when a review flow invokes it explicitly by name.
> Under `required`, `intent-guard` is outside this resolution chain -- it is never selected as an
> implementation or review owner by domain fit and runs only when a review flow invokes it explicitly.
> Under `legacy-absent`, there is no role to resolve.
## Related Skills
+51 -29
View File
@@ -85,6 +85,12 @@ Output: `MODE:`, `TEAM_NAME:`, `PROMPT:` (optional), plus the artifact-metadata
> `.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.
`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
@@ -94,8 +100,9 @@ verb always comes first and the optional `[name]` positional after it.
> `.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. `intent-guard` is never parked — it is shared with
> `/brewcode:superreview-setup`, exactly as in UNINSTALL and PURGE.
> 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.
---
@@ -170,7 +177,8 @@ Spawn 3-5 Explore agents in ONE message via Task tool:
All via `Task(subagent_type="Explore")`. Consolidate into single analysis document.
**Also harvest the intent-guard facts** (agent #1 and #4 cover most of these; add explicit asks to their prompts).
**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:
@@ -189,10 +197,9 @@ as `none` / `not present in this project`, never invented:
Based on analysis + PROMPT (if provided), propose 3 variants via AskUserQuestion.
**`intent-guard` is in EVERY team, always, and is NOT one of the counted slots.** It is a review-only
anti-drift check (asked-vs-delivered), not a domain agent, so the 5 / 10-12 / 15-20 counts describe
DOMAIN agents only. Show it as a fixed row in every variant table, never as an option the user picks
and never as something the user can drop:
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):
@@ -211,8 +218,9 @@ Maximum (15-20 domain agents + intent-guard):
Options: "Minimal (5)" | "Balanced (recommended)" | "Maximum (15-20)" | "Custom -- I'll specify"
If "Custom" -- second AskUserQuestion for free input; intent-guard stays regardless of what the user
specifies. Final confirmation of agent list before proceeding.
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
@@ -263,8 +271,9 @@ may leave a partial roster, but no discoverable compact profile may ever point a
1. Create `.claude/teams/{TEAM_NAME}/`.
2. Read `${CLAUDE_SKILL_DIR}/references/framework-files.md`; write `team.md` with substituted metadata,
the byte-faithful `## Shared Agent Contract`, the `## Agents` header, and only the fixed
`intent-guard` row. Do not add domain-agent rows yet; C4 finalizes the successfully created roster.
`INTENT_GUARD_POLICY=required`, the byte-faithful `## Shared Agent Contract`, 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\`.`
@@ -318,7 +327,7 @@ strip shared rules from a profile until its target `team.md` passes the gate.
> 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 (always, exactly once)
#### 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
@@ -431,7 +440,8 @@ 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 the file gets its `team.md` row.
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
@@ -439,8 +449,9 @@ C4. Either way the file gets its `team.md` row.
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 domain row per successfully created agent, and retain the
fixed `intent-guard` row. Then `touch trace.jsonl`. No confirmed-but-unwritten agent enters the roster.
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
@@ -454,9 +465,10 @@ C4. Either way the file gets its `team.md` row.
> 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 an `intent-guard` row (trailing `Kind` column = `review-only`, trailing
`Version` column = `PLUGIN_VERSION:`), whether it was created in C3-IG or reused. `Agents | {N}`
counts DOMAIN agents; note intent-guard separately.
`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:
@@ -470,6 +482,11 @@ C4. Either way the file gets its `team.md` row.
No placeholder token may survive into the written file — a literal `{PLUGIN_VERSION}` in `team.md`
means substitution never happened.
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,
i.e. `ceil(chars/4) <=700` estimated tokens. 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
bash "${CLAUDE_SKILL_DIR}/scripts/verify-team.sh" "TEAM_NAME_HERE" && echo "PASS" || echo "FAIL"
@@ -671,9 +688,11 @@ done; echo "OK"
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}` only and preserving Created, roster rows, statuses, and history. 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`.
substituting `{TEAM_NAME}` only and preserving Created, roster rows, statuses, and history. Resolve and
write the explicit `Intent guard` field first: an existing intent-guard roster row -> `required`; no row
-> `legacy-absent`. 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
@@ -690,9 +709,10 @@ Filter post-cursor trace: `k=track` for task stats, `k=issue` for problems, `k=i
| Underperforming | <30% success | AskUser: update or delete+create new |
| Inactive | 0 records | AskUser: delete or keep |
> `intent-guard` is EXCLUDED from this table. It does not trace and is invoked only during review, so
> 0 records is its normal state, never grounds for deletion or tuning. UNINSTALL enforces the same
> exclusion in `references/cleanup-flow.md` Step 3.
> 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
@@ -783,8 +803,9 @@ team, not a removed one. `uninstall`/`purge` delete; `disable` does not.
```bash
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} agent files are parked as
`.md.disabled` — nothing is deleted, `enable` restores them. `intent-guard` stays live."
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:
@@ -855,13 +876,14 @@ Format to write:
```markdown
## Teams
Team: {TEAM_NAME} | Domain agents: {N} (+ `intent-guard`, review-only) | Status: active
Team: {TEAM_NAME} | Domain agents: {N} | Intent guard: {required (review-only) | legacy-absent} | Status: active
| Agent | Domain | Mission |
|-------|--------|---------|
`intent-guard` -- review-only anti-drift check (asked vs delivered). Shared with
`/brewcode:superreview-setup`, invoked explicitly by name during review; never an implementation owner.
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]`
@@ -73,12 +73,11 @@ echo "✅ Archived" || echo "❌ FAILED"
## Step 3: Agents Review
> **`intent-guard` is EXCLUDED from this step — never list it, never offer it, never delete it.**
> It is the team's fixed review-only member, shared with `/brewcode:superreview-setup`. It writes no trace
> entries by design, so 0 tasks and "no activity" are its NORMAL state, not inactivity. Filter it out
> of the inactive table BEFORE showing it, so "Delete all inactive" cannot reach it. If the user asks
> for it by name anyway, refuse: answer that removing it breaks `verify-team.sh` for this team, and
> keep the file. Its `team.md` row (`Kind` = `review-only`) also stays.
Read logical `intent_guard_policy=required|legacy-absent` from the single `Intent guard` field in
`team.md` before building the table. Under `required`,
the roster has exactly one review-only `intent-guard`; exclude it from this step, never list/offer/delete
it, and preserve its row. It writes no trace entries, so 0 tasks is normal. Under `legacy-absent`, the
roster has zero such rows and cleanup must not create a profile or row. Upgrade never changes that policy.
Show inactive/problematic agents (domain agents only):
@@ -106,7 +105,7 @@ AskUserQuestion:
On delete:
0. If `{name}` is `intent-guard` -> **STOP, do not delete.** Report it as protected and move on.
0. If `{name}` is `intent-guard` under `required` -> **STOP, do not delete.** Report it as protected and move on. Under `legacy-absent`, seeing that name is a policy violation: delete nothing and report the inconsistent roster.
0b. **Validate `{name}` as an agent id BEFORE any `rm`.** Roster values are interpolated into the delete
path, so a row like `../../../outside/README` deletes a file outside the project. Same guard
`toggle-team.sh`/`verify-team.sh` apply — run it, and on a non-zero exit report the row as a corrupt
@@ -169,9 +168,10 @@ Nothing is archived — the archive itself is part of what goes.
ls -la ".claude/teams/{TEAM}" 2>/dev/null; du -sh ".claude/teams/{TEAM}" 2>/dev/null
```
2. Delete each domain agent listed in `team.md` (`## Agents` table, `Kind` != `review-only`).
**`intent-guard` is skipped** shared with `/brewcode:superreview-setup`; deleting it would break
an unrelated install. Report it as kept. **Every other `{name}` passes the Step 3 id guard first**
2. Delete each domain agent listed in `team.md` (`## Agents` table, `Kind` != `review-only`). Under
`required`, **`intent-guard` is skipped** because it is shared with `/brewcode:superreview-setup`;
report it as kept. Under `legacy-absent`, there is no row or profile to skip and purge must not add
one. **Every other `{name}` passes the Step 3 id guard first**
a roster value that is not `^[a-z0-9][a-z0-9-]*$` is a path, and purge would delete outside
`.claude/agents/`; report such a row as corrupt and delete nothing for it. **Every `{name}` also passes
the Step 3 ownership check (step 0c)** — purge is not a licence to take another team's agent with it:
@@ -1,56 +1,46 @@
# Framework files
Instantiate `.claude/teams/{TEAM_NAME}/`. Replace `{TEAM_NAME}`, `{DATE}`, `{LAST_UPDATED}`, `{PLUGIN_VERSION}`, `{CONTENT_VERSION}`, `{N}`, `{CWD}` from `detect-mode.sh`; `CONTENT_VERSION` self-locates from this skill's metadata, !=copied from `PLUGIN_VERSION`. `{DATE}` is creation date and upgrade never rewrites it. `team.md` uses Edit; `trace.jsonl` is append-only via `trace-ops.sh add`.
Instantiate `.claude/teams/{TEAM_NAME}/`. Replace `{TEAM_NAME}`, `{DATE}`, `{LAST_UPDATED}`, `{PLUGIN_VERSION}`, `{CONTENT_VERSION}`, `{N}`, `{CWD}`, `{INTENT_GUARD_POLICY}`, and `{INTENT_GUARD_ROW}`; scalar metadata comes from `detect-mode.sh`. `CONTENT_VERSION` self-locates from this skill's metadata, !=copied from `PLUGIN_VERSION`. `{DATE}` is creation date and upgrade never rewrites it. `team.md` uses Edit; `trace.jsonl` is append-only via `trace-ops.sh add`.
## team.md
```markdown
# Team: {TEAM_NAME}
| Field | Value |
|-------|-------|
| Created | {DATE} |
| Version | {PLUGIN_VERSION} |
| Content version | {CONTENT_VERSION} |
| Generated by | brewcode:teams-setup |
| Last update | {LAST_UPDATED} |
| Agents | {N} |
| Project | {CWD} |
|Field|Value|
|---|---|
|Created|{DATE}|
|Version|{PLUGIN_VERSION}|
|Content version|{CONTENT_VERSION}|
|Generated by|brewcode:teams-setup|
|Last update|{LAST_UPDATED}|
|Agents|{N}|
|Intent guard|{INTENT_GUARD_POLICY}|
|Project|{CWD}|
## Shared Agent Contract
Every domain agent loads this file before task acceptance. `intent-guard` is exempt: it keeps its review-only output contract and never implements.
### Acceptance + routing
Before any task evaluate `Domain`, `Duplicate`, `Best candidate`. Domain mismatch -> refuse + name the roster colleague; duplicate -> refuse + link the result; better candidate -> refuse + name that colleague. Refusal returns to the manager immediately. Acceptance -> trace `took`, execute only owned surfaces, honor exclusions/named owners. The `## Agents` roster routes; profile exclusions win on overlap.
### Tracing
Optional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.claude/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`${CLAUDE_PLUGIN_ROOT}` substitution and no `*_PLUGIN_ROOT` env. Missing file/bash failure -> skip silently; plugin update/move/uninstall does not break it.
`bash ".claude/teams/{TEAM_NAME}/trace-ops.sh" add ".claude/teams/{TEAM_NAME}" "$SID" "{AGENT_NAME}" "<kind>" "<state>" "<text>"`
Track states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; if unset, pass any 8-char marker.
Before any task evaluate `Domain`, `Duplicate`, `Best candidate`. Mismatch/duplicate/better -> refuse+owner/link+return; accept -> trace `took`, execute only owned surfaces; profile exclusions win on overlap.
Optional best effort, `1 attempt max`, no retry, Bash only. Use versionless project-local `.claude/teams/{TEAM_NAME}/trace-ops.sh`; project agents get !=`${CLAUDE_PLUGIN_ROOT}` substitution and no `*_PLUGIN_ROOT` env. Missing/fail -> skip; plugin update/move/uninstall does not break it.
`T=".claude/teams/{TEAM_NAME}"; bash "$T/trace-ops.sh" add "$T" "$SID" "{AGENT_NAME}" "<kind>" "<state>" "<text>"`
Track states: `took` / `refused` / `completed` / `failed`. Issue severity: `low` / `medium` / `high` / `critical`. Insight category (max 1-3): `pattern` / `architecture` / `performance` / `security` / `convention` / `debt`. `$SID` is 8 chars; else any 8-char marker.
A task traced `took` ends with exactly one terminal track: `completed` or `failed`.
### Return
Verdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed `path:line` + check verdict or one failing name. Bulk diffs/logs/dumps/reports -> `.claude/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, return path + verdict + <=3 lines.
### Shared implementation rules
Code/script/SQL/schema/infra/config owners build for actual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify last. Before class/module/test, find the closest well-built repo etalon (`.claude/convention/*` first); its principles add to rules/conventions/docs, !=replace them.
Verdict first, <=30 lines, `path:line`. !=bodies/output/log/preamble. This holds with or without agent-return. Return changed path/check only. Bulk -> `.claude/reports/YYYYMMDD-HHMMSS_{AGENT_NAME}/`; return path, !=content. With agent-return: >~1000 est-tokens (`chars/4`) -> compress; >~2500 -> file detail, path + verdict + <=3 lines.
Actual scale; !=imagined load/speculative abstraction (EX: 10-user app !=lock-contention hardening). Simplify. Class/module/test -> nearest repo etalon (`.claude/convention/*` first), additive to rules/conventions/docs, !=replace them.
## Agents
| Agent | Domain | Mission | Status | Updated | Kind | Version |
|-------|--------|---------|--------|---------|------|---------|
| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | {LAST_UPDATED} | review-only | {PLUGIN_VERSION} |
|Agent|Domain|Mission|Status|Updated|Kind|Version|
|---|---|---|---|---|---|---|
{INTENT_GUARD_ROW}
```
`Agent` stays column 1 (row field 2); `Kind`/`Version` trail, future columns append at end. Metadata quartet `Version` / `Content version` / `Generated by` / `Last update` stays adjacent and ordered; `Created`/`Agents`/`Project` stay outside it. Header `Version` = last `team.md` write; per-agent `Version` changes only for touched rows. Status: `active`, `inactive` (live, zero trace), `updating`, `disabled`, `removed` (file deleted); kind: `domain` (blank allowed), `review-only`. `disabled` parks `.claude/agents/{name}.md.disabled` while body/team dir/history stay intact; `enable` restores byte-identical body. `intent-guard` is mandatory, shared with superreview, outside `{N}`, and never removed.
`Agent` stays column 1 (row field 2); `Kind`/`Version` trail, future columns append at end. Metadata quartet `Version` / `Content version` / `Generated by` / `Last update` stays adjacent and ordered; `Created`/`Agents`/`Intent guard`/`Project` stay outside it. Header `Version` = last `team.md` write; per-agent `Version` changes only for touched rows. Status: `active`, `inactive` (live, zero trace), `updating`, `disabled`, `removed` (file deleted); kind: `domain` (blank allowed), `review-only`. `disabled` parks `.claude/agents/{name}.md.disabled` while body/team dir/history stay intact; `enable` restores byte-identical body.
`Intent guard` is explicit: `required` means `{INTENT_GUARD_ROW}` is exactly
`|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|{LAST_UPDATED}|review-only|{PLUGIN_VERSION}|`;
`legacy-absent` means the placeholder is empty and the roster MUST NOT contain `intent-guard`. New teams
default to `required`. Upgrade preserves an existing no-guard roster as `legacy-absent`; it never adds a
role merely to modernize the shared contract. `intent-guard` remains shared with superreview, outside
`{N}`, and never removed when policy is `required`.
## trace.jsonl
@@ -51,6 +51,7 @@ case "$CV" in
*) printf 'ERROR:cannot resolve content_version (X.Y.Z) from %s - refusing to emit a repair row with a fake content_version\n' "$SKILL_MD"; exit 1 ;;
esac
# BEGIN CLIENT AGENT VALIDATION
# Artifact-metadata frontmatter gate for ONE generated agent. Same four keys, same D2 order and the same
# quoting `brewcode/skills/rules/scripts/rules.sh:140-146` enforces -- one dialect across the repo, not a
# second one invented here. Returns: 0 conforming, 1 malformed, 2 no metadata at all (pre-standard agent).
@@ -122,6 +123,7 @@ check_compact_profile() {
fi
return "$_bad"
}
# END CLIENT AGENT VALIDATION
# Roster values reach `-f` probes here and `mv`/`rm -f` in toggle-team.sh and cleanup-flow.md, so a row
# like `| ../../../outside/README |` is a path, not a name. An agent id is a bare `^[a-z0-9][a-z0-9-]*$`,
@@ -188,6 +190,25 @@ if [ ! -f "$TEAM_DIR/trace.jsonl" ]; then
fi
if [ -f "$TEAM_DIR/team.md" ]; then
team_chars=$(wc -m < "$TEAM_DIR/team.md" | tr -d '[:space:]')
team_tokens=$(( (team_chars + 3) / 4 ))
if [ "$team_chars" -le 2800 ] && [ "$team_tokens" -le 700 ]; then
echo "CHECK: full team.md ceiling ... OK ($team_chars chars, $team_tokens est-tokens)"
else
echo "CHECK: full team.md ceiling ... FAIL ($team_chars chars, $team_tokens est-tokens; maximum 2800 chars and 700 ceil(chars/4) tokens)"
FAIL=1
fi
declared_agents_count=$(grep -cE '^\|[[:space:]]*Agents[[:space:]]*\|' "$TEAM_DIR/team.md" || true)
declared_agents=""
if [ "$declared_agents_count" -eq 1 ]; then
declared_agents=$(sed -n 's/^|[[:space:]]*Agents[[:space:]]*|[[:space:]]*\([0-9][0-9]*\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
fi
if [ "$declared_agents_count" -ne 1 ] || [ -z "$declared_agents" ]; then
echo "CHECK: declared Agents count ... FAIL (requires exactly one numeric | Agents | N | row)"
FAIL=1
fi
# Artifact-metadata header rows -- all FOUR, adjacent, in the order Version / Content version /
# Generated by / Last update. ABSENT ALL FOUR = a team.md written before the standard existed: WARN
# with the fix, an old team must upgrade cleanly. Anything else -- a subset, a wrong order, a
@@ -235,6 +256,15 @@ if [ -f "$TEAM_DIR/team.md" ]; then
;;
esac
# Current teams declare whether the shared review-only role is required or intentionally absent.
# An old team without the field remains migratable; once the shared contract is present the policy
# is mandatory and the roster must match it exactly.
intent_guard_policy=""
intent_guard_policy_count=$(grep -cE '^\|[[:space:]]*Intent guard[[:space:]]*\|' "$TEAM_DIR/team.md" || true)
if [ "$intent_guard_policy_count" -eq 1 ]; then
intent_guard_policy=$(sed -n 's/^|[[:space:]]*Intent guard[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
fi
# New teams centralize the repeated member contract once. Absence remains safe only for a fully
# legacy roster; a compact profile with no destination contract is an interrupted-install defect.
shared_contract_present=0
@@ -243,6 +273,15 @@ if [ -f "$TEAM_DIR/team.md" ]; then
else
shared_contract_present=1
shared_bad=0
if [ "$intent_guard_policy_count" -ne 1 ]; then
echo "CHECK: Intent guard policy ... FAIL (current team.md requires exactly one policy row)"
shared_bad=1
else
case "$intent_guard_policy" in
required|legacy-absent) echo "CHECK: Intent guard policy ($intent_guard_policy) ... OK" ;;
*) echo "CHECK: Intent guard policy ... FAIL (expected required or legacy-absent; found '$intent_guard_policy')"; shared_bad=1 ;;
esac
fi
shared_count=$(grep -cF '## Shared Agent Contract' "$TEAM_DIR/team.md" || true)
[ "$shared_count" -eq 1 ] \
|| { echo "CHECK: Shared Agent Contract ... FAIL (must occur exactly once; found $shared_count)"; shared_bad=1; }
@@ -280,7 +319,12 @@ if [ -f "$TEAM_DIR/team.md" ]; then
in_agents=0
past_header=0
found_agents=0
found_intent_guard=0
intent_guard_count=0
intent_guard_cells_ok=1
unique_domain_rows=0
seen_agent_ids="|"
team_version=$(sed -n 's/^|[[:space:]]*Version[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
team_last_update=$(sed -n 's/^|[[:space:]]*Last update[[:space:]]*|[[:space:]]*\([^|]*[^|[:space:]]\)[[:space:]]*|.*/\1/p' "$TEAM_DIR/team.md")
while IFS= read -r line; do
case "$line" in
"## Agents"*) in_agents=1; past_header=0; continue ;;
@@ -301,7 +345,39 @@ if [ -f "$TEAM_DIR/team.md" ]; then
FAIL=1
continue
fi
[ "$agent" = "intent-guard" ] && found_intent_guard=1
case "$seen_agent_ids" in
*"|$agent|"*)
echo "CHECK: roster name '$agent' ... FAIL (duplicate roster name)"
FAIL=1
;;
*)
seen_agent_ids="${seen_agent_ids}${agent}|"
if [ "$agent" != "intent-guard" ]; then
agent_kind=$(printf '%s' "$line" | cut -d'|' -f7 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
case "$agent_kind" in
''|domain) unique_domain_rows=$((unique_domain_rows + 1)) ;;
*) echo "CHECK: agent '$agent' kind ... FAIL (domain rows require Kind domain or blank)"; FAIL=1 ;;
esac
fi
;;
esac
if [ "$agent" = "intent-guard" ]; then
intent_guard_count=$((intent_guard_count + 1))
agent_domain=$(printf '%s' "$line" | cut -d'|' -f3 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_mission=$(printf '%s' "$line" | cut -d'|' -f4 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_status=$(printf '%s' "$line" | cut -d'|' -f5 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_updated=$(printf '%s' "$line" | cut -d'|' -f6 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_kind=$(printf '%s' "$line" | cut -d'|' -f7 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
agent_version=$(printf '%s' "$line" | cut -d'|' -f8 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [ "$agent_domain" != "--" ] \
|| [ "$agent_mission" != "Anti-drift check: what was ASKED vs what was DELIVERED" ] \
|| [ "$agent_status" != "active" ] \
|| [ "$agent_updated" != "$team_last_update" ] \
|| [ "$agent_kind" != "review-only" ] \
|| [ "$agent_version" != "$team_version" ]; then
intent_guard_cells_ok=0
fi
fi
printf "CHECK: agent %s ... " "$agent"
# BOTH copies present is checked FIRST: a live-first if/parked-elif chain reads a dual copy
# as a healthy live agent and hides the collision. `.claude/agents/` is project-global, so the
@@ -314,6 +390,7 @@ if [ -f "$TEAM_DIR/team.md" ]; then
CONFLICT=$((CONFLICT + 1))
FAIL=1
elif [ -f ".claude/agents/${agent}.md" ]; then
# BEGIN LIVE CLIENT AGENT CHECK
# The roster row proves the file exists; the frontmatter proves the generator stamped it.
# A generated agent with no metadata at all predates the standard -> WARN + the upgrade fix.
# Metadata that IS there but malformed is a generator defect -> FAIL.
@@ -344,6 +421,7 @@ if [ -f "$TEAM_DIR/team.md" ]; then
*) printf '%s\n' "$profile_out"; FAIL=1 ;;
esac
fi
# END LIVE CLIENT AGENT CHECK
elif [ -f ".claude/agents/${agent}.md.disabled" ]; then
# Parked by `disable`: the body is intact, only the .md extension that
# Claude Code discovers on is withheld. A reversible state, not a defect.
@@ -362,21 +440,40 @@ if [ -f "$TEAM_DIR/team.md" ]; then
if [ "$in_agents" -eq 0 ]; then
echo "WARN: no ## Agents section in team.md"
fi
# intent-guard is a fixed review-only member of every team, outside the domain-agent count.
# Teams created before it existed simply lack the row -- warn with the fix, never fail them.
# Teams that DO list it are covered by the per-agent -f check above.
if [ "$found_intent_guard" -eq 0 ]; then
echo "WARN: team.md has no intent-guard row (team predates it). Fix:"
echo " bash \"$SCRIPT_DIR/../../superreview-setup/scripts/generate.sh\" emit-agent"
echo " then add this row to the ## Agents table (all 7 columns: Agent, Domain, Mission, Status,"
echo " Updated, Kind, Version):"
echo " | intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | $TODAY | review-only | $PV |"
elif [ "$shared_contract_present" -eq 0 ]; then
echo "WARN: legacy intent-guard roster row predates the review-only scope contract. Fix: /brewcode:teams-setup upgrade"
elif ! grep -Eq '^\|[[:space:]]*intent-guard[[:space:]]*\|[[:space:]]*--[[:space:]]*\|[[:space:]]*Anti-drift check: what was ASKED vs what was DELIVERED[[:space:]]*\|[^|]*\|[^|]*\|[[:space:]]*review-only[[:space:]]*\|' "$TEAM_DIR/team.md"; then
echo "CHECK: intent-guard roster contract ... FAIL (domain '--', fixed anti-drift mission, and kind review-only are required)"
if [ -n "$declared_agents" ] && [ "$declared_agents" -eq "$unique_domain_rows" ]; then
echo "CHECK: declared Agents count ... OK ($declared_agents unique domain rows)"
elif [ -n "$declared_agents" ]; then
echo "CHECK: declared Agents count ... FAIL (declared $declared_agents, found $unique_domain_rows unique domain rows)"
FAIL=1
fi
case "$intent_guard_policy" in
required)
if [ "$intent_guard_count" -ne 1 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (policy required needs exactly one row; found $intent_guard_count)"
FAIL=1
elif [ "$intent_guard_cells_ok" -ne 1 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (fixed cells require --, anti-drift mission, active, team Last update, review-only, and team Version)"
FAIL=1
else
echo "CHECK: intent-guard roster contract ... OK"
fi
;;
legacy-absent)
if [ "$intent_guard_count" -ne 0 ]; then
echo "CHECK: intent-guard roster contract ... FAIL (policy legacy-absent requires zero rows; found $intent_guard_count)"
FAIL=1
fi
;;
"")
if [ "$shared_contract_present" -eq 0 ]; then
if [ "$intent_guard_count" -eq 0 ]; then
echo "WARN: legacy team has no intent-guard row; upgrade records policy legacy-absent without adding a role"
else
echo "WARN: legacy intent-guard roster row predates the explicit required policy. Fix: /brewcode:teams-setup upgrade"
fi
fi
;;
esac
fi
printf 'DISABLED_AGENTS:%s\n' "$DISABLED"
@@ -31,6 +31,24 @@ const LEGACY_HEADINGS = [
const SOURCE_CLIENT_DIR = ['.', 'claude'].join('');
const SOURCE_TEAM_REF = `${SOURCE_CLIENT_DIR}/teams/{TEAM_NAME}/team.md`;
const NATIVE_TEAM_REF = '.codex/teams/{TEAM_NAME}/team.md';
const SOURCE_PLUGIN_ROOT = `${['CL', 'AUDE'].join('')}_PLUGIN_ROOT`;
const SOURCE_PLUGIN_ROOT_NEGATION = `!=\`\${${SOURCE_PLUGIN_ROOT}}\` substitution`;
const DUSK_ROSTER = [
['game-designer', 'design', 'pillars'],
['combat-dev', 'combat', 'loop'],
['physics-dev', 'physics', 'Jolt'],
['destruction-dev', 'destruct', 'fracture'],
['scenario-dev', 'scenarios', 'lab'],
['vfx-dev', 'VFX', 'impacts'],
['texture-artist', 'materials', 'textures'],
['modeller-3d', 'models', 'rigs'],
['sound-designer', 'audio', 'SFX'],
['feel-dev', 'feel', 'camera'],
['qa-tester', 'QA', 'tests'],
['docs-keeper', 'docs', 'sync'],
['build-eng', 'build', 'toolchain'],
];
const DUSK_NON_MEMBERS = ['task-tracker', 'intent-guard'];
let passed = 0;
let failed = 0;
@@ -93,6 +111,37 @@ function section(text, start, end) {
return text.slice(a, b < 0 ? text.length : b);
}
function rosterNames(team) {
return section(team, '## Agents', '\n## ')
.split('\n')
.filter((line) => /^\|[a-z0-9]/.test(line) && !line.startsWith('|Agent|'))
.map((line) => line.split('|')[1]);
}
function instantiateTeamTemplate(template, {
projectRoot,
roster,
policy,
version = '6.1.4',
contentVersion = '6.1.0',
}) {
const intentRow = policy === 'required'
? `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|2026-08-27|review-only|${version}|`
: '';
const domainRows = roster.map(([name, domain, mission]) =>
`|${name}|${domain}|${mission}|active|2026-08-27|domain|${version}|`).join('\n');
return `${template
.replaceAll('{TEAM_NAME}', 'dusk')
.replaceAll('{DATE}', '2026-08-27')
.replaceAll('{LAST_UPDATED}', '2026-08-27')
.replaceAll('{PLUGIN_VERSION}', version)
.replaceAll('{CONTENT_VERSION}', contentVersion)
.replaceAll('{N}', String(roster.length))
.replaceAll('{CWD}', projectRoot)
.replaceAll('{INTENT_GUARD_POLICY}', policy)
.replaceAll('{INTENT_GUARD_ROW}', [intentRow, domainRows].filter(Boolean).join('\n'))}\n`;
}
const repo = findRepoRoot(dirname(fileURLToPath(import.meta.url)));
const canonicalTemplatePath = join(repo, 'brewcode', 'skills', 'teams-setup', 'references', 'agent-template.md');
const canonicalFrameworkPath = join(repo, 'brewcode', 'skills', 'teams-setup', 'references', 'framework-files.md');
@@ -182,6 +231,7 @@ const sharedSourceLiterals = [
'no retry, Bash only',
'versionless project-local',
sourceTracePath,
SOURCE_PLUGIN_ROOT_NEGATION,
'no `*_PLUGIN_ROOT` env',
'plugin update/move/uninstall does not break it',
'`took` / `refused` / `completed` / `failed`',
@@ -194,6 +244,7 @@ const sharedSourceLiterals = [
'>~2500',
'<=3 lines',
'!=imagined load/speculative abstraction',
'10-user app !=lock-contention hardening',
'!=replace them',
'## Agents',
];
@@ -217,6 +268,60 @@ check(
true,
'generated team.md fenced template is at most 700 estimated tokens',
);
check(
'shared.intentPolicyPlaceholder',
occurrences(canonicalTeam, '{INTENT_GUARD_POLICY}'),
1,
'team template carries exactly one explicit intent-guard policy field',
);
check(
'shared.intentRowPlaceholder',
occurrences(canonicalTeam, '{INTENT_GUARD_ROW}'),
1,
'team template carries exactly one policy-controlled intent-guard row slot',
);
const fullDuskTeam = instantiateTeamTemplate(canonicalTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk',
roster: DUSK_ROSTER,
policy: 'legacy-absent',
});
check(
'shared.fullDuskRosterCount',
rosterNames(fullDuskTeam).length,
13,
'the representative full Dusk roster contains exactly 13 members',
);
check(
'shared.fullDuskRosterNames',
rosterNames(fullDuskTeam).join('|'),
DUSK_ROSTER.map(([name]) => name).join('|'),
'the full Dusk roster preserves the exact ordered member boundary',
);
check(
'shared.fullDuskNonMembers',
DUSK_NON_MEMBERS.filter((name) => rosterNames(fullDuskTeam).includes(name)).join('|'),
'',
'task-tracker and intent-guard stay outside the legacy-absent Dusk roster',
);
check(
'shared.fullDuskPolicy',
fullDuskTeam.includes('|Intent guard|legacy-absent|'),
true,
'the no-intent-guard roster carries an explicit legacy-absent policy',
);
check(
'shared.fullDuskCharsWithinCeiling',
fullDuskTeam.length <= 2800,
true,
'the complete 13-member Dusk team.md is at most 2800 characters',
);
check(
'shared.fullDuskTokensWithinCeiling',
Math.ceil(fullDuskTeam.length / 4) <= 700,
true,
'the complete 13-member Dusk team.md is at most 700 estimated tokens',
);
check(
'codex.headings',
@@ -263,7 +368,8 @@ check(
for (const literal of sharedSourceLiterals) {
const nativeLiteral = literal
.replaceAll(SOURCE_CLIENT_DIR, '.codex');
.replaceAll(SOURCE_CLIENT_DIR, '.codex')
.replaceAll(`\`\${${SOURCE_PLUGIN_ROOT}}\``, '`<plugin-root>`');
check(
`codex.sharedLiteral.${sharedSourceLiterals.indexOf(literal) + 1}`,
projectedTeam.includes(nativeLiteral),
@@ -277,6 +383,23 @@ check(
true,
'Codex path projection does not grow the shared contract',
);
const fullNativeDuskTeam = instantiateTeamTemplate(projectedTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk',
roster: DUSK_ROSTER,
policy: 'legacy-absent',
});
check(
'codex.fullDuskRosterNames',
rosterNames(fullNativeDuskTeam).join('|'),
DUSK_ROSTER.map(([name]) => name).join('|'),
'native Codex projection preserves the exact full Dusk member boundary',
);
check(
'codex.fullDuskTokensWithinCeiling',
Math.ceil(fullNativeDuskTeam.length / 4) <= 700,
true,
'native Codex full Dusk team remains at most 700 estimated tokens',
);
check(
'codex.distributedTemplateParity',
distributedTemplate,
@@ -332,6 +455,8 @@ check(
const migration = section(canonicalSkill, '### U1b: Shared Contract Migration Gate', '### U2: Analyze Performance');
for (const literal of [
'insert the canonical block before `## Agents`',
'an existing intent-guard roster row -> `required`; no row',
'-> `legacy-absent`. Never synthesize the row on the latter path.',
'Legacy agent bodies remain byte-identical during this gate.',
'**No agent may be tuned, regenerated, stripped,',
'until the shared contract passes.',
@@ -343,6 +468,20 @@ for (const literal of [
`legacy-upgrade ordering preserves ${JSON.stringify(literal)}`,
);
}
for (const literal of [
'a new team defaults to `required`',
'absence migrates\nto `legacy-absent`',
'`legacy-absent` forbids that row and MUST NOT add the role during upgrade',
'the complete written `team.md` (metadata + shared contract + every row) MUST be <=2800 characters',
'`ceil(chars/4) <=700` estimated tokens',
]) {
check(
`policy.workflow.${literal.slice(0, 16)}`,
canonicalSkill.includes(literal),
true,
`generator workflow preserves ${JSON.stringify(literal)}`,
);
}
const c8 = section(canonicalSkill, '### C8: Fix', '### C9: Re-verify');
check(
@@ -404,24 +543,19 @@ const pluginVersion = JSON.parse(readFileSync(
)).version;
const contentVersion = (/content_version=([0-9]+\.[0-9]+\.[0-9]+)/.exec(canonicalSkill) || [])[1];
const today = '2026-08-27';
const BUILD_ROSTER = [['build-eng', 'Build', 'deterministic builds']];
function instantiateTeam(projectRoot) {
const intentRow = `| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | ${today} | review-only | ${pluginVersion} |`;
return `${canonicalTeam
.replaceAll('{TEAM_NAME}', 'dusk')
.replaceAll('{DATE}', today)
.replaceAll('{LAST_UPDATED}', today)
.replaceAll('{PLUGIN_VERSION}', pluginVersion)
.replaceAll('{CONTENT_VERSION}', contentVersion)
.replaceAll('{N}', '1')
.replaceAll('{CWD}', projectRoot)
.replace(intentRow, `${intentRow}\n| build-eng | Build | Own deterministic build surfaces | active | ${today} | domain | ${pluginVersion} |`)}\n`;
function instantiateTeam(projectRoot, { policy = 'required', roster = BUILD_ROSTER } = {}) {
return instantiateTeamTemplate(canonicalTeam, {
projectRoot: '/Users/maximus/IdeaProjects/project-dusk', roster, policy, version: pluginVersion, contentVersion,
});
}
function agentFile({ body = representativeBody, frontmatterPadding = '' } = {}) {
// BEGIN RUNTIME AGENT FIXTURES
function agentFile({ name = 'build-eng', body = representativeBody, frontmatterPadding = '' } = {}) {
return `---
name: build-eng
description: Build owner. Triggers: build, release, toolchain.
name: ${name}
description: Domain owner. Triggers: domain, review, verification.
model: opus
tools: Read, Bash
${frontmatterPadding}doc_type: llm
@@ -450,18 +584,28 @@ last_updated: "${today}"
Review only.
`;
}
// END RUNTIME AGENT FIXTURES
function makeWorld({ teamText, agentText = agentFile(), intent = true } = {}) {
function makeWorld({
teamText,
agentText,
policy = 'required',
roster = BUILD_ROSTER,
intent = policy === 'required',
} = {}) {
const world = mkdtempSync(join(tmpdir(), 'team-profile-contract-'));
const teamDir = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk');
const agentsDir = join(world, SOURCE_CLIENT_DIR, 'agents');
mkdirSync(teamDir, { recursive: true });
mkdirSync(agentsDir, { recursive: true });
writeFileSync(join(teamDir, 'team.md'), teamText ?? instantiateTeam(world));
writeFileSync(join(teamDir, 'team.md'), teamText ?? instantiateTeam(world, { policy, roster }));
writeFileSync(join(teamDir, 'trace.jsonl'), '');
writeFileSync(join(teamDir, 'trace-ops.sh'), '#!/bin/sh\nexit 0\n');
chmodSync(join(teamDir, 'trace-ops.sh'), 0o755);
writeFileSync(join(agentsDir, 'build-eng.md'), agentText);
for (const [name] of roster) {
writeFileSync(join(agentsDir, `${name}.md`),
name === 'build-eng' && agentText ? agentText : agentFile({ name }));
}
if (intent) writeFileSync(join(agentsDir, 'intent-guard.md'), intentGuardFile());
return world;
}
@@ -488,6 +632,117 @@ function removeWorld(world) {
removeWorld(world);
}
{
const world = makeWorld({ policy: 'legacy-absent', roster: DUSK_ROSTER });
const result = runVerifier(world);
check('verifier.fullDuskLegacyAbsent.exit', result.status, 0,
'the full 13-member Dusk roster passes without adding intent-guard');
check('verifier.fullDuskLegacyAbsent.policy',
result.output.includes('CHECK: Intent guard policy (legacy-absent) ... OK'), true,
'the verifier accepts the explicit no-intent-guard policy');
check('verifier.fullDuskLegacyAbsent.memberChecks',
DUSK_ROSTER.every(([name]) => result.output.includes(`CHECK: agent ${name} ... OK`)), true,
'the verifier checks every exact Dusk member');
removeWorld(world);
}
{
const world = makeWorld({ policy: 'required', intent: false });
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(/^\|intent-guard\|.*\n/m, ''));
const result = runVerifier(world);
check('verifier.requiredMissing.exit', result.status, 1,
'required policy fails when the intent-guard row is absent');
check('verifier.requiredMissing.reason',
result.output.includes('policy required needs exactly one row; found 0'), true,
'required-policy failure names the missing row');
removeWorld(world);
}
{
const world = makeWorld({ policy: 'legacy-absent', intent: true });
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
const team = readFileSync(teamPath, 'utf8');
const forbiddenRow = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|`;
writeFileSync(teamPath, `${team.trim()}\n${forbiddenRow}\n`);
const result = runVerifier(world);
check('verifier.legacyAbsentRow.exit', result.status, 1,
'legacy-absent policy fails when an intent-guard row is introduced');
check('verifier.legacyAbsentRow.reason',
result.output.includes('policy legacy-absent requires zero rows; found 1'), true,
'legacy-absent failure names the forbidden roster expansion');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(
'|Intent guard|required|', '|Intent guard|optional|'));
const result = runVerifier(world);
check('verifier.invalidPolicy.exit', result.status, 1,
'an unsupported intent-guard policy fails');
check('verifier.invalidPolicy.reason',
result.output.includes("expected required or legacy-absent; found 'optional'"), true,
'the verifier enumerates the only valid policy values');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${'x'.repeat(900)}\n`);
const result = runVerifier(world);
check('verifier.teamCeiling.exit', result.status, 1,
'an oversized fully substituted team.md fails');
check('verifier.teamCeiling.reason',
result.output.includes('maximum 2800 chars and 700 ceil(chars/4) tokens'), true,
'the runtime verifier names both complete-file ceilings');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace('|Agents|1|', '|Agents|2|'));
const result = runVerifier(world);
check('verifier.agentCountMismatch.exit', result.status, 1,
'declared Agents count must equal unique domain rows');
check('verifier.agentCountMismatch.reason',
result.output.includes('declared 2, found 1 unique domain rows'), true,
'the mismatch reports declared and observed unique-domain counts');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
const duplicate = `|build-eng|Build|deterministic builds|active|${today}|domain|${pluginVersion}|\n`;
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${duplicate}`);
const result = runVerifier(world);
check('verifier.duplicateDomain.exit', result.status, 1,
'duplicate domain roster names fail');
check('verifier.duplicateDomain.reason',
result.output.includes("duplicate roster name"), true,
'the verifier identifies duplicate roster identity');
removeWorld(world);
}
{
const world = makeWorld();
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
const duplicate = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|\n`;
writeFileSync(teamPath, `${readFileSync(teamPath, 'utf8')}${duplicate}`);
const result = runVerifier(world);
check('verifier.duplicateIntentGuard.exit', result.status, 1,
'required policy rejects duplicate intent-guard rows');
check('verifier.duplicateIntentGuard.reason',
result.output.includes('policy required needs exactly one row; found 2'), true,
'the verifier enforces exactly one review-only row');
removeWorld(world);
}
// BEGIN SOURCE FRONTMATTER BUDGET FIXTURE
{
const padding = `notes: "${'x'.repeat(5000)}"\n`;
const world = makeWorld({ agentText: agentFile({ frontmatterPadding: padding }) });
@@ -500,6 +755,7 @@ function removeWorld(world) {
'the fixture proves the full file itself exceeds 3200 bytes');
removeWorld(world);
}
// END SOURCE FRONTMATTER BUDGET FIXTURE
{
const oversized = `${representativeBody}\n${'x'.repeat(3300)}\n`;
@@ -535,6 +791,7 @@ for (const [index, literal] of instantiatedLosses.entries()) {
removeWorld(world);
}
// BEGIN SOURCE LEGACY AGENT FIXTURE
{
const legacyTeam = `# Team: dusk
@@ -574,6 +831,7 @@ for (const [index, literal] of instantiatedLosses.entries()) {
'the verifier directs repair of the shared authority before profile stripping');
removeWorld(interrupted);
}
// END SOURCE LEGACY AGENT FIXTURE
for (const [name, mutate, reason] of [
['firstReference', (text) => text.replace('.claude/teams/dusk/team.md', '.claude/teams/other/team.md'),
@@ -589,19 +847,24 @@ for (const [name, mutate, reason] of [
removeWorld(world);
}
{
for (const [name, mutate] of [
['domain', (row) => row.replace('|--|', '|code|')],
['mission', (row) => row.replace('Anti-drift check: what was ASKED vs what was DELIVERED', 'Implementation owner')],
['status', (row) => row.replace('|active|', '|inactive|')],
['updated', (row) => row.replace(`|${today}|review-only|`, '|2026-08-26|review-only|')],
['kind', (row) => row.replace('|review-only|', '|domain|')],
['version', (row) => row.replace(`|${pluginVersion}|`, '|0.0.0|')],
]) {
const world = makeWorld();
const teamPath = join(world, SOURCE_CLIENT_DIR, 'teams', 'dusk', 'team.md');
const team = readFileSync(teamPath, 'utf8');
writeFileSync(teamPath, team.replace(
`| intent-guard | -- | Anti-drift check: what was ASKED vs what was DELIVERED | active | ${today} | review-only | ${pluginVersion} |`,
`| intent-guard | code | Implementation owner | active | ${today} | domain | ${pluginVersion} |`,
));
const fixedRow = `|intent-guard|--|Anti-drift check: what was ASKED vs what was DELIVERED|active|${today}|review-only|${pluginVersion}|`;
writeFileSync(teamPath, readFileSync(teamPath, 'utf8').replace(fixedRow, mutate(fixedRow)));
const result = runVerifier(world);
check('verifier.intentGuardScope.exit', result.status, 1,
'changing the fixed intent-guard scope/kind fails');
check('verifier.intentGuardScope.reason', result.output.includes('intent-guard roster contract ... FAIL'), true,
'the verifier protects the review-only exemption in the instantiated roster');
check(`verifier.intentGuardFixed.${name}.exit`, result.status, 1,
`changing fixed intent-guard ${name} fails`);
check(`verifier.intentGuardFixed.${name}.reason`,
result.output.includes('fixed cells require --, anti-drift mission, active, team Last update, review-only, and team Version'), true,
'the verifier protects every fixed review-only cell');
removeWorld(world);
}
@@ -113,7 +113,7 @@ function makeProject(label, rows, agentFiles, separator = 'compact') {
'| Content version | 6.0.0 |',
'| Generated by | brewcode:teams-setup |',
'| Last update | 2026-08-16 |',
`| Agents | ${rows.length} |`,
`| Agents | ${rows.filter((name) => name !== 'intent-guard').length} |`,
`| Project | ${root} |`,
'',
'## Agents',
@@ -110,7 +110,7 @@ function makeProject(label, rows) {
'| Content version | 6.0.0 |',
'| Generated by | brewcode:teams-setup |',
'| Last update | 2026-08-16 |',
`| Agents | ${rows.length} |`,
`| Agents | ${rows.filter((name) => name !== 'intent-guard').length} |`,
`| Project | ${root} |`,
'',
'## Agents',