plugins/coordinator/skills/staff-session/SKILL.md
PM-GATED: ask first; never from subagent. Agent Teams collaborative planning/review for architectural decisions only. Modes: plan, review.
npx skillsauth add oduffy-delphi/coordinator-claude staff-sessionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The EM scopes the work, selects the team, creates the team, spawns all teammates, and is freed. The team works autonomously:
Lightweight tier falls through to single-reviewer dispatch via /review (plan) or /review-code (code) — no team created.
$ARGUMENTS:
--mode plan|review — required. plan for crafting a new plan from objectives; review for critiquing an existing artifact--tier lightweight|standard|full — required. lightweight routes to single-reviewer dispatch (/review for plan artifacts, /review-code for code artifacts). standard = 2 debaters. full = 3-5 debaters--members "persona-a,persona-b,..." — optional. Override auto-selection with explicit persona slugs (e.g., "patrik,zoli")<input> — required. Plan mode: path to objectives document or free-text objectives. Review mode: path to the artifact to reviewParse $ARGUMENTS:
--mode (plan|review) — required; fail with usage message if missing--tier (lightweight|standard|full) — required; fail with usage message if missing--members (optional) — comma-separated persona slugs<input> — artifact path or objectivesGenerate run ID: YYYY-MM-DD-HHhMM (current timestamp, e.g., 2026-03-22-09h30)
Record spawn timestamp:
date +%s
Generate topic slug from input (e.g., camera-refactor-plan, pipeline-d-review).
Create scratch directory:
mkdir -p tasks/scratch/staff-session/{run-id}
Set output path based on mode:
docs/plans/YYYY-MM-DD-{topic-slug}.md (canonical output for /enrich-and-review)tasks/review-findings/YYYY-MM-DD-{topic-slug}-staff-review.mdSet advisory path: {scratch-dir}/advisory.md
Announce: "Running /staff-session --mode {mode} --tier {tier} on '{topic}'."
If --tier lightweight:
Do NOT create a team. Route directly to /review (plan artifacts) or /review-code (code artifacts) with the specified member (or patrik as default if --members not provided).
Announce: "Routing to single-reviewer dispatch (/review or /review-code) for single-reviewer gut-check."
STOP — the rest of this command does not execute.
If --tier standard or --tier full: Continue to Step 3.
Write {scratch-dir}/scope.md per the template in pipelines/staff-session/templates-and-fields.md § Step 3. Plan mode: EM writes objectives and constraints only — never the plan. Review mode: EM provides artifact path and focus areas only — never pre-formed findings.
If --members specified: Use those exact personas. Validate each slug maps to a known persona agent. Fail with a clear error if any slug is unknown.
If --members not specified: Auto-select based on domain signals from the input topic and scope.
Important: the Director of Engineering is the synthesizer, not a debater. the Director of Engineering cannot appear in the debater list — he reads all debater positions and produces the final output. If the user specifies --members "patrik,zoli", reject with: "the Director of Engineering is the staff session synthesizer — he can't also debate. Choose a different second debater, or I'll auto-select one."
| Domain Signal | Default Pair |
|---|---|
| Architecture / infrastructure | patrik + sid |
| Game dev / Unreal | sid + patrik |
| Frontend / UI | pali + fru |
| Data science / ML | camelia + patrik |
| Cross-cutting / unclear | patrik + sid |
For --tier full: add domain experts on top of the default pair. Use judgment based on the input topic to identify which additional personas are most relevant.
Determine debater count:
standard: 2 debatersfull: 3-5 debaters (determined by domain signals and persona relevance)Announce team composition to PM before creating the team:
"I'll run this with {Persona A} and {Persona B} [+ {Persona C}...] debating, plus a staff synthesizer. Proceeding."
Persona slug → agent file mapping:
| Slug | Agent File |
|---|---|
| patrik | coordinator/agents/staff-eng.md |
| sid | game-dev/agents/staff-game-dev.md |
| fru | web-dev/agents/staff-ux.md |
| pali | web-dev/agents/senior-front-end.md |
| camelia | data-science/agents/staff-data-sci.md |
| vp-product | coordinator/agents/vp-product.md |
Note: zoli is NOT a valid debater slug — he is the synthesizer. See Step 6.
Order matters. Task IDs from earlier steps are referenced in blocking chain setup.
TeamCreate(team_name: "staff-{topic-slug}")
1. Synthesizer task (created first — will be blocked by all debaters later):
TaskCreate(
subject: "Synthesize all debater positions into final {plan|findings}",
description: "Read all position documents from {scratch-dir}/. Cross-reference, resolve conflicts, write output to {output-path} and {scratch-dir}/synthesis.md. If advisory warranted, write to {scratch-dir}/advisory.md."
)
Save as {synthesizer-task-id}.
2. Debater tasks (one per persona — no blockers on creation): For each debater persona:
TaskCreate(
subject: "{Persona Name}: {mode} session on {topic}",
description: "Read scope from {scratch-dir}/scope.md. {Plan mode: Research codebase, form architectural position, debate peers, write consensus-ready plan contribution.} {Review mode: Review artifact at {input-path}, form findings, debate peers, write final position.} Output to {scratch-dir}/{persona-slug}-position.md. Send DONE to synthesizer when complete."
)
Collect all debater task IDs as [{debater-A-id}, {debater-B-id}, ...].
3. Block synthesizer on all debaters:
TaskUpdate(taskId: "{synthesizer-task-id}", addBlockedBy: [{debater-A-id}, {debater-B-id}, ...])
Read the planner / reviewer / synthesizer prompt templates from ${CLAUDE_PLUGIN_ROOT}/pipelines/staff-session/. For each debater, read the persona identity excerpt from its agent definition file (injected at [PERSONA_IDENTITY]). Fill ALL [BRACKETED_FIELD] placeholders before spawning — see pipelines/staff-session/templates-and-fields.md § Step 6 for the full common/debater/synthesizer field list.
Spawn ALL teammates in a single message (parallel):
Agent(
team_name: "staff-{topic-slug}",
name: "{persona-slug-A}",
model: "opus",
subagent_type: "coordinator:{persona-agent-name-A}",
prompt: <filled debater prompt for persona A>
)
TaskUpdate(taskId: "{debater-A-id}", owner: "{persona-slug-A}")
Agent(
team_name: "staff-{topic-slug}",
name: "{persona-slug-B}",
model: "opus",
subagent_type: "coordinator:{persona-agent-name-B}",
prompt: <filled debater prompt for persona B>
)
TaskUpdate(taskId: "{debater-B-id}", owner: "{persona-slug-B}")
[repeat for each additional debater in full tier]
Agent(
team_name: "staff-{topic-slug}",
name: "synthesizer",
model: "opus",
subagent_type: "coordinator:eng-director",
prompt: <filled synthesizer prompt>
)
TaskUpdate(taskId: "{synthesizer-task-id}", owner: "synthesizer")
Persona slug → subagent_type mapping:
| Slug | subagent_type |
|---|---|
| patrik | coordinator:staff-eng |
| sid | game-dev:staff-game-dev |
| fru | web-dev:staff-ux |
| pali | web-dev:senior-front-end |
| camelia | data-science:staff-data-sci |
| vp-product | coordinator:vp-product |
After spawning all teammates, announce:
"Staff session running on '{topic}' with {N} debaters ({names}) + 1 synthesizer.
- Debate phase: floor 3 min, ceiling {MAX_MINUTES} min. Debaters research independently, form positions, and challenge each other.
- Synthesizer unblocks when all debaters complete.
I'm available for other work — I'll be notified when the synthesizer completes."
You are now free to continue the conversation with the PM. Do not poll, do not monitor, do not send WRAP_UP. The team self-governs via the timing and convergence protocol in team-protocol.md.
When you receive a notification that the synthesizer task is complete:
Read the output at {output-path}. Verify it has substantive content (not just headers or a stub).
Mode-specific verification:
## Implementation Plan section with tasks, files, and steps in plan format (per docs/wiki/writing-plans.md). Verify **Review:** Staff session ({participants}) — debated and synthesized. Ready for enrichment. is present.## Verdict line is present.Check for advisory: test -f {scratch-dir}/advisory.md — if the file exists, read it.
Commit the output (plain-git scoped — SC-DR-008, lessons.md:207):
# Stage only the output files this session wrote (scratch dir contents + any plan/review artifact)
git add -- {output-paths} && git commit -m "staff-session: {mode} — {topic-slug}" -- {output-paths}
Archive the paper trail:
mkdir -p docs/research/archive/YYYY-MM-DD-staff-{topic-slug}
cp -r {scratch-dir}/* docs/research/archive/YYYY-MM-DD-staff-{topic-slug}/
Remove scratch directory:
rm -rf {scratch-dir}
Shut down the team:
TeamDelete(team_name: "staff-{topic-slug}")
Commit cleanup (plain-git scoped — SC-DR-008, lessons.md:207):
git add -- docs/research/archive/YYYY-MM-DD-staff-{topic-slug}/ && git commit -m "staff-session: archive + cleanup" -- docs/research/archive/YYYY-MM-DD-staff-{topic-slug}/
Present output to PM:
/enrich-and-review"; review mode → "Here are the synthesized findings"{scratch-dir} (archived at docs/research/archive/YYYY-MM-DD-staff-{topic-slug}/advisory.md)."See pipelines/staff-session/templates-and-fields.md § Error Handling Matrix for the full failure-mode → action table (debater crash, synthesizer failure, DONE-not-received, debate loops, unknown slug, missing output).
tools
Orient session — preflight, load context, choose work
documentation
Wrap up finished work — capture lessons, update docs
development
Triangulate plan-claim / code-reality / review oracles to classify each plan into DELIVERED+REVIEWED / DELIVERED-UNREVIEWED / PARTIAL / IN-FLIGHT / ABANDONED. Run after any crash or 'did we actually finish what we think we finished?' moment.
testing
Check for a published coordinator update and advise a preserve-by-default migration path — never a blind overwrite.