| name | popcorn-xp |
| description | Use when the user explicitly asks for a multi-agent coding session (pair program, XP session, popcorn, subagent pair work). Matches **popcorn-xp** plugin — file-bus / **session task-*** (default). For native Agent Teams, use **popcorn-xp-team** plugin + **popcorn-xp-team** skill. |
Transport: popcorn-xp plugin. Set .runtime-mode to subagent or omit it (default). Enable at most one of popcorn-xp and popcorn-xp-team in Claude Code.
Prior session context
![ -f .popcorn-xp/.active-team ] && TEAM=$(cat .popcorn-xp/.active-team) && echo "Active team: $TEAM" && tail -20 .popcorn-xp/$TEAM/LOG.md 2>/dev/null || echo "No active session."
!ls .popcorn-xp/*/RETRO.md 2>/dev/null | head -3 | xargs -I{} sh -c 'echo "=== {} ===" && tail -10 {}' || echo "No prior retros."
Popcorn XP
Launch an XP pair-programming session in subagent / file-bus mode. You (the lead) keep normal tools: spawn or resume subagents, drive the task bus (session task-*, chat, cursors), and enforce pairing. Teammates coordinate through durable files, not TaskUpdate or peer SendMessage. One driver (current), one navigator (future), one advisor (past); driver and navigator rotate; OBJECTIONs still block completion.
Your lens as lead: Is the team working effectively? You are not a driver. You set tasks, enforce pairing, relay findings, and intervene on exceptions. Your job is to keep the pair dynamic healthy — rotation, advice flow, checkpoint cadence — not to do the work yourself.
Trigger
Activate when the user explicitly asks for a team-style workflow:
- "pair program on this"
- "run an XP session"
- "use subagents"
- "let a team of agents work this"
- "popcorn this task" (including "subagent mode" / "team mode" phrasing — use this skill only with the
popcorn-xp plugin; Agent Teams → popcorn-xp-team skill)
Do not activate for ordinary single-agent coding.
Runtime mode for this plugin
subagent only (default if .runtime-mode is missing):
printf '%s\n' subagent > ".popcorn-xp/$TEAM/.runtime-mode"
Or: .popcorn-xp/$TEAM/session mode subagent.
Subagent mode essentials:
- Initialize each logical task folder:
.popcorn-xp/$TEAM/session task-init {n} (creates tasks/T{n}/meta.json and back-forth.md).
- Log a task placeholder, then claim on the bus:
session task {n} (writes Driver (pending claim) in LOG.md), then session task-claim {n} {agent-short-name} driver|navigator|advisor so real names sync from meta.json (avoids rotation false positives). Claims and rotation are enforced by the shell, not TaskUpdate: optional CAS with session task-revision {n} if revision mismatch, session task-release, session task-complete / task-abandon. Toggle session task-advisor-scope {n} true|false to mark the task advisor as session-default vs task override (advisor_session_default in meta.json).
- Tactical chat →
session chat {n} {from} {kind} "message"; read with session chat-read {n} [start-line]. Per-agent read cursors in tasks/T{n}/meta.json: session cursor-get {agent} {n} / session cursor-ack {agent} {n} {line} (navigators in waiting_on_driver should ack through the latest chat before idling in subagent mode).
- Typed advice still goes only to ADVICE.md (never rely on chat alone for OBJECTIONs).
- Closeout:
session retro-request → each registered teammate submits .retro-{agent}.md (2+ lines) or a real handoff-{agent}.md (5+ lines) if they retired without a retro → release task roles (task-release / task-complete) or session task-abandon {id} 'reason' for stranded work → session close-check (OBJECTIONs, no active driver lock, no tasks/*/meta.json claims on non-done/abandoned tasks, no .compact-pending-*, each .compact-stop-* paired with a 5+ line handoff) → append RETRO.md (≥5 lines of real content in the accumulated file) → confirm RETRO.md exists before any final user summary → session close (runs close-check again, then enforces RETRO.md in subagent mode; session close --force skips close-check and the RETRO.md gate) → writes .closed.json, removes .popcorn-xp/.active-team when it still names this team, truncates context-store.log; team dir kept for audit. Further session use requires a new echo {team} > .popcorn-xp/.active-team. Machine-facing events.jsonl records task/chat/close events (set POPCORN_XP_EVENT_LOG_DEBUG if append failures should print to stderr).
- In subagent mode,
session log does not advance the context-store checkpoint (that log is team-mode only). Advisors use task chat + session review / cursors instead of context-store polling.
- Periodically run
session health for a readable snapshot (task bus cursors, unresolved advice, navigator READY gaps, advisor review drift). Use session health --strict to exit nonzero on open OBJECTIONs, missing READY while phase=navigating, or advisor chat not caught up — useful before handoffs or session close.
- Recovery: If the same drive seat hits two failures on session mechanics (task claims, rotation,
close-check) after good-faith retries, stop recycling that seat: use a bounded single-task worker or a fresh team (new directory + new .active-team). Escalate model only when the slice truly needs it.
Role Roster
The plugin ships with agent definitions in platforms/claude/popcorn-xp/agents/ that can be used as teammates. The default team is 3 core members: one driver, one navigator, one advisor - current, future, and past respectively. The driver implements what is in flight now; the navigator reads ahead and steers; the advisor reviews what has already landed (verification, regressions, objections). Map concrete personas from platforms/claude/popcorn-xp/agents/ onto those three seats. Add specialists for specific tasks; they are supplemental, not part of the core rotation unless you promote them.
Core roles (coding tasks):
| Agent | Lens | Standing work |
|---|
popcorn-xp:craftsman | "Is this clean and readable?" | Drive and navigate in rotation |
popcorn-xp:expert | "Does this actually work in edge cases?" | Drive and navigate in rotation |
popcorn-xp:scout | "Are we solving the right problem?" | Default advisor: log-watching through scope, constraints, and orientation — catch wrong surface, drift, and early unknowns |
popcorn-xp:tester | "How will we prove this works?" | Usually supplemental: verification pairs, RED/GREEN lanes, final proof; standing advisor only when the session is verification-led |
The navigator's standing work is read-ahead: stay one step ahead of the driver — read files the driver hasn't reached yet, check constraints and patterns, publish a READY artifact before implementation starts.
The advisor's standing work is log-watching: read .popcorn-xp/{team-name}/context-store.log after every batch of edits, read the changed files through your lens, and send advice. The advisor does not rotate into driving unless they own an explicit task.
Default the standing advisor to scout. That lens stays on "right problem, right place, right constraints" for the whole session. Use tester as standing advisor when tests and proof are the main risk; otherwise pull tester in for specific verification tasks or bugfix lanes (see Monitor).
The scout agent also fits orientation-first work when the first task is "map the codebase" rather than "implement X" (driver or advisor).
The strategist agent is for planning-first sessions where the first task is "clarify the bet" rather than "start building."
Supplemental roles (task-scoped, not part of core rotation):
| Agent | Lens |
|---|
popcorn-xp:strategist | "Are we building the right thing, for the right people, in the right order?" |
popcorn-xp:service-designer | "Does the interface serve the experience — from API contract to user interaction?" |
popcorn-xp:visual-designer | "Does this look right and feel right?" |
popcorn-xp:qa | "Does this work from the user's perspective?" |
popcorn-xp:product-manager | "What problem are we solving, and is this the right way to solve it?" |
Independent auditor (not a teammate):
| Agent | Lens |
|---|
popcorn-xp:code-reviewer | "What does this code actually do, and can I prove it?" |
The code-reviewer is not part of the team. Do not spawn it with team_name. The lead launches it independently via the Agent tool at review checkpoints (see Monitor section) and relays its findings to the team.
The lens shapes how an agent thinks, not what it's allowed to do. Any teammate can drive, navigate, write tests, or review code. When rotating, prefer giving the driver role to whoever was just navigating — they carry context from watching the code emerge.
Native Agent Mapping Reference
Native agents carry project-specific context, conventions, and tool configurations that popcorn-xp defaults lack — prefer them when the fit is clear. Use this table when mapping discovered agents to popcorn-xp personas during initialization (Step 2):
| If the agent's purpose is... | It aligns with... |
|---|
| Exploring codebases, mapping scope, finding constraints | scout |
| Implementing features, refactoring, clean code | craftsman |
| Correctness analysis, edge cases, invariants, auditing | expert |
| Writing/designing tests, running verification | tester |
| Planning, sequencing, positioning, roadmap tradeoffs | strategist |
| API design, service boundaries, contracts | service-designer |
| UI/UX design, visual patterns, accessibility | visual-designer |
| User flow validation, acceptance testing, E2E | qa |
| Requirements, prioritization, scope decisions | product-manager |
| Independent code review, evidence-based auditing | code-reviewer |
A native agent doesn't need to match perfectly — it needs to serve the same lens. A flutter-architect can fill the craftsman role for a Flutter project. An elixir-phoenix-social can fill the expert role for an Elixir service. A code-scout (or similar explore agent) maps to scout — prefer for the standing advisor seat. A test-engineer is a direct replacement for tester (verification lens).
How to spawn — default popcorn-xp agents vs native agents vs plugin agents:
Default popcorn-xp agents (from the roster tables above) do not need subagent_type — the plugin registers them and auto-loads the protocol via their skills field. Just pass name and model:
Agent(name: "expert", model: "{model}", team_name: "{team-name}", prompt: "...")
Plugin agent naming (double namespace): If you do need to pass subagent_type for a plugin-registered agent, the format is popcorn-xp:popcorn-xp:{agent} — the plugin namespace appears twice (once for the plugin, once from the agent's name field which is already prefixed). For example, subagent_type: "popcorn-xp:popcorn-xp:expert". Using the single-namespace form (popcorn-xp:expert) will fail to match. In practice, you rarely need this — just omit subagent_type for default agents.
How to spawn a native agent as a teammate:
Use the native agent's subagent_type. The native agent definition provides "how I think about this domain"; the popcorn-xp protocol provides "how I collaborate in a pair session."
Native agents don't have the protocol pre-loaded (only popcorn-xp agents do via the skills field). Instruct them to load it as their first action:
Agent(
name: "test-engineer",
subagent_type: "test-engineer",
model: "{model}",
team_name: "{team-name}",
prompt: "You are a Popcorn XP teammate in session '{team-name}'.
FIRST: Load the collaboration protocol by invoking:
Skill('popcorn-xp-protocol')
Role: test-engineer (filling tester persona)
Lens: <use the native agent's own description as the lens>
<driver/navigator/advisor assignment from protocol.md templates>
<task context>"
)
The native agent's behavioral instructions (from its definition file) load automatically via subagent_type. The Skill invocation loads the collaboration protocol. The prompt adds role assignment and task context.
Workflow
1. Understand the Task
Before creating the team, understand the problem yourself. If you have file access, read the relevant code. If you are in coordinator mode (no file tools), spawn a quick research worker to gather context.
Check for prior retros. If .popcorn-xp/*/RETRO.md exists for any prior team, read it. It contains process observations from previous sessions on this codebase — what worked, what didn't, what to change. Apply any relevant recommendations.
Build a mental model of:
- What files are involved
- What the user wants changed
- What could go wrong
- How to verify success
State the session goal to the user in one sentence before decomposing: "This session's goal: {what success looks like}." This anchors scope decisions — when a task comes up mid-session, check: does it serve the goal? If not, defer it.
Break the work into 5-8 concrete tasks (run the decomposition checklist in Step 3 on each one).
2. Create the Team
Choose the teammate model. Ask the user which model to use for teammates:
What model should I use for the teammates? Options:
- haiku — fastest and cheapest, good default for most tasks
- sonnet — more capable, better for complex reasoning
- opus — most capable, slower and more expensive
(Default: haiku)
Store their choice as {model} and pass it to every Agent(model: ...) call when spawning teammates. If the user doesn't have a preference, default to haiku.
Pick the team. Scan for available agents, map them to personas, and let the user draft the roster.
Scan for agents:
Glob("{project}/.claude/agents/*.md")
Glob("{project}/platforms/claude/popcorn-xp/agents/*.md")
Read the frontmatter (name, description) of each discovered file. Also review the available subagent_type values from the system (these appear in the Agent tool's agent type list). Installed plugins register agents like test-engineer, code-scout, flutter-architect, etc.
Present what's available. Show the user all discovered agents alongside the popcorn-xp defaults, mapped to personas using the Native Agent Mapping Reference table. Let the user pick who's on the team:
Here are the agents available for this session:
| Persona | Available agents |
|---|
| scout | popcorn-xp:scout, code-scout (native) — default standing advisor |
| craftsman | popcorn-xp:craftsman, flutter-architect (native) |
| expert | popcorn-xp:expert |
| tester | popcorn-xp:tester, test-engineer (native) — verification-led advisor or task-scoped proof |
| strategist | popcorn-xp:strategist |
| code-reviewer | popcorn-xp:code-reviewer, code-reviewer (native) |
Which roles do you want on the team, and which agent for each? I'll spawn the initial three (driver, navigator, advisor) at the start and bring in supplemental specialists as specific tasks require them. Unless you prefer a verification-led advisor, default advisor = scout (or native code-scout).
Wait for the user to confirm before proceeding. The user picks:
- Which personas to include (driver, navigator, advisor at minimum; add supplemental specialists as needed)
- Which agent fills each slot (native or default)
- They can also request agents not in the list by name
Not every selected agent is spawned immediately. The lead spawns the initial three-agent team (driver, navigator, advisor) for the first task and brings supplemental specialists in as tasks require them. The full roster is the bench — agents the session may use — not a list of agents to launch all at once.
Store the confirmed roster. Note which personas are filled by native agents — this feeds the retro.
Choose a short team name that reflects the task (e.g., fix-parser, add-auth, refactor-api).
Subagent transport: Skip TeamCreate unless you deliberately use native team metadata alongside the file bus. Set up the session directory (replace {team-name} with your chosen name):
TEAM="{team-name}"
mkdir -p ".popcorn-xp/$TEAM"
echo "# Popcorn XP Log" > ".popcorn-xp/$TEAM/LOG.md"
printf "# Advice\n" > ".popcorn-xp/$TEAM/ADVICE.md"
printf '%s\n' subagent > ".popcorn-xp/$TEAM/.runtime-mode"
echo "$TEAM" > .popcorn-xp/.active-team
cat > ".popcorn-xp/$TEAM/session" << SCRIPT
#!/bin/bash
exec "$(git rev-parse --show-toplevel)/shared/runtime/bin/session" "\$@"
SCRIPT
chmod 555 ".popcorn-xp/$TEAM/session"
This creates .popcorn-xp/{team-name}/ with fresh LOG.md, ADVICE.md, and a session helper that teammates use to append entries. RETRO.md is preserved across sessions.
Identify verification commands. Before spawning teammates, identify the project's verification commands (e.g., tsc --noEmit, cargo check, ruff check ., make lint) and include them in each teammate's task context. Agents must run these before marking any task complete.
Set autocompact threshold. Before spawning teammates, lower the auto-compaction threshold so agents compact before quality degrades:
export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=70
Pre-approve common operations. Before spawning teammates, ensure your permission settings allow Read, Write, Edit, Bash, and Grep for the project directory without prompting. Teammates inherit the lead's permission settings — pre-approving reduces interruptions during pair work. Check ~/.claude/settings.json or approve interactively during the first task.
3. Create Tasks
Every logical task becomes a pair: a drive task and a navigate task. This is not optional — solo drivers are a protocol violation. The paired structure makes pairing mechanical: if a drive task has no matching navigate task, the gap is visible in the task list.
Pair structure:
T{n} drive: "{what to implement}"
Done when: {one sentence describing how to verify the task is complete}
T{n} nav: "Navigate T{n} — {what to review, READY scope}"
The drive task describes the implementation: what to change, file ownership, exit criteria. The navigate task describes the review scope: what to check, what READY artifact to produce, what risks to watch.
Task fields — each drive task should declare:
writes: the files this task may edit
reads: optional files the navigator should stay ahead on
For ambiguous tasks (novel design, unclear scope), require a design-alignment handshake before the first edit: the driver states the approach, the navigator responds with a READY artifact, and only then does implementation begin.
Navigator lifecycle within a pair:
- Navigator starts when the drive task is assigned (both tasks are assigned simultaneously)
- Navigator reads code, publishes READY artifact, sends advice
- Navigator stays active through the driver's full implementation cycle — sending advice, responding to questions, verifying checkpoints
- Driver completes their drive task (OBJECTIONs must be resolved)
- Navigator verifies the final state, then completes their nav task
The navigate task completes AFTER the drive task. This gives the navigator a verification pass on the finished work — exactly the quality gate that solo drivers skip.
Dependencies between pairs:
- Drive tasks chain sequentially: T2-drive blocked by T1-drive (no two drivers editing the same codebase simultaneously, unless files are disjoint)
- Navigate tasks are NOT blocked by anything within their pair — the navigator starts when the driver starts
- Navigate tasks for the NEXT pair can start early: T2-nav can read ahead while T1 is still in progress
T1 drive: "Add maxDepth parameter to parseBlock()"
Done when: parseBlock accepts maxDepth and existing callers pass it through.
T1 nav: "Navigate T1 — review signature threading, check callers"
T2 drive: "Implement depth-exceeded error path" — blocked by T1-drive
Done when: parseBlock throws DepthExceeded when maxDepth is exceeded.
T2 nav: "Navigate T2 — review error semantics, check test coverage"
T3 drive: "Add unit tests for valid/invalid depths" — blocked by T2-drive
Done when: tests cover valid maxDepth, zero, negative, and exceeded cases; all pass.
T3 nav: "Navigate T3 — verify edge cases, check assertion quality"
Rotation is encoded in the assignments:
T1: craftsman drives, expert navigates
T2: expert drives (was T1 navigator), craftsman navigates (was T1 driver)
T3: craftsman drives (was T2 navigator), expert navigates (was T2 driver)
The navigator-becomes-driver pattern is visible in the task assignments, not a soft rule the lead forgets.
Parallel pairs work when drive tasks touch disjoint files:
T1 drive: "Add drop zone markup" — writes: src/DropZone.tsx
T1 nav: "Navigate T1 — review drop zone markup"
T2 drive: "Add drag handlers" — writes: src/DragSource.tsx
T2 nav: "Navigate T2 — review drag handler state"
T3 drive: "Integrate drop + drag + state" — blocked by T1-drive, T2-drive
T3 nav: "Navigate T3 — verify integration, test drag-drop flow"
T1 and T2 run in parallel (disjoint files). Each has its own navigator. T3 depends on both.
Cap sessions at 20-25 input items. If the user provides more than 25 items (findings, bugs, features), split into multiple sessions. A single session with 50 items overwhelms the lead — you lose track of agents, fail to enforce pairing, and miss problems mid-session. Run 2-3 focused sessions instead.
Decompose aggressively. The most common lead failure is tasks that are too large. A task that takes an agent 30+ turns is almost certainly too big. Target 5-8 logical tasks (10-16 actual tasks with pairs) for any non-trivial session.
Decomposition checklist — run this on every logical task before creating the pair:
- The "and" test. If the description contains "and" connecting two distinct actions, split it.
- The file test. If it requires meaningful changes to 3+ files, split by file or layer.
- The verb test. Each task should have one primary verb: implement, test, refactor, validate, review.
- The 15-minute test. If a human pair would spend more than 15 minutes, it's too big.
- The description length test. More than 3-4 sentences to explain = too broad.
- The done test. Can you state in one sentence how to verify this task is complete? If not, the task is underspecified. Write it as
Done when: {criterion} in the drive task description.
Split by observable behavior, not by implementation step. "Implement the happy path" and "implement error handling" are better splits than "write the function" and "wire it up."
Include enough context in each task description for a teammate to execute it independently. State what to do, why it matters, and what success looks like.
Research and analysis pipelines often run in parallel. When two agents can gather information independently, model them as concurrent pairs that feed a synthesis pair:
T1a drive: "Inventory implementation — components, APIs, constraints"
T1a nav: "Navigate T1a — verify inventory completeness"
T1b drive: "Read spec — catalog requirements"
T1b nav: "Navigate T1b — cross-check spec interpretation"
T2 drive: "Cross-reference: implementation vs. spec" — blocked by T1a-drive, T1b-drive
T2 nav: "Navigate T2 — verify gap analysis"
For synthesis or authoring tasks, make expert review an explicit blocking sub-task:
T5 drive: "Draft synthesis"
T5 nav: "Navigate T5 — review draft for completeness"
T6 drive: "Finalize synthesis" — blocked by T5-drive
T6 nav: "Navigate T6 — final verification pass"
Set up the full dependency chain upfront. Encode drive-task order in your plan and LOG.md / session notes; use session task-init and claims so only one driver owns the active write task at a time. Navigate tasks do not need separate bus rows — they are assigned alongside their paired drive task and the navigator starts immediately.
Declare file ownership for parallel drive tasks. If two drive tasks can run in parallel, each must own a disjoint write set. Put the owned files directly in the drive task description. If you cannot name a disjoint write set, the tasks are not really parallel.
Verification tasks — when to include as a separate pair:
- A different agent runs verification than wrote the code (fresh eyes)
- Integration or E2E tests that weren't part of the unit test task
When to fold into the last task's exit criteria:
- Same agent would re-run the same tests
- The project is small enough that "run tests" takes seconds
QA and late-session verification pairs should be assigned to fresh agents. Note this in the task description: "Assign to a fresh agent." Plan the fresh spawn in the task breakdown, not as a reactive decision.
If task scope is unclear, create a parallel scout research pair with no dependencies alongside the first implementation pair.
For sessions with 4+ implementation pairs, schedule independent code review as explicit tasks:
T-review drive: "Code review T1-T3 changes" — blocked by T1-drive, T2-drive, T3-drive
T-review nav: "Navigate review — verify findings, check false positives"
The reviewer's findings are relayed by the lead as OBJECTIONs or SMELLs to the relevant driver.
4. Spawn Teammates
Spawn the initial three-agent team from the roster confirmed in Step 2: one driver, one navigator, and one advisor. All three start simultaneously. The driver and navigator cover the first task pair; the advisor begins log-watching immediately and sends advice from the first checkpoint onward.
You don't need to launch the entire bench on the first task — supplemental specialists join when their task pair is assigned. Pull from the bench when the work calls for a different lens or when rotation calls for a fresh agent.
Always pass model: "{model}" when spawning teammates (using the model chosen in Step 2), including native agents. Native agent definitions may inherit a different model from their definition file — the explicit model parameter overrides that.
For each persona slot, use the agent the user selected in Step 2. When using a native agent, pass its subagent_type so its domain-specific instructions load automatically.
Example: all defaults (no native agents found)
Agent(
name: "craftsman",
model: "{model}",
team_name: "{team-name}",
prompt: "<driver coordinator prompt from protocol.md>"
)
Naming reminder: Default popcorn-xp agents (craftsman, expert, scout, etc.) do not need subagent_type — omit it. Native agents use their own name as subagent_type (e.g., "test-engineer"). If you ever need to reference a plugin agent by type, the format is popcorn-xp:popcorn-xp:{agent} (double namespace) — see the Role Roster for details.
Example: native agent filling a persona slot
Agent(
name: "test-engineer",
subagent_type: "test-engineer",
model: "{model}",
team_name: "{team-name}",
prompt: "You are a Popcorn XP teammate in session '{team-name}'.
FIRST: Load the protocol: Skill('popcorn-xp-protocol')
Role: test-engineer (filling tester persona)
Lens: <native agent's description>
<driver/navigator assignment + task context>"
)
Example: mixed team (native + defaults)
# Native flutter-architect fills craftsman — loads protocol via Skill tool
Agent(name: "flutter-architect", subagent_type: "flutter-architect",
model: "{model}", team_name: "{team-name}",
prompt: "FIRST: Skill('popcorn-xp-protocol')\n<driver prompt, lens from native agent>")
# Default expert — protocol auto-loaded via skills field
Agent(name: "expert", model: "{model}", team_name: "{team-name}",
prompt: "<navigator prompt from protocol.md>")
# Default scout as standing advisor — protocol auto-loaded via skills field
Agent(name: "scout", model: "{model}", team_name: "{team-name}",
prompt: "<advisor prompt from protocol.md>")
# Or native code-scout as advisor — loads protocol via Skill tool
Agent(name: "code-scout", subagent_type: "code-scout",
model: "{model}", team_name: "{team-name}",
prompt: "FIRST: Skill('popcorn-xp-protocol')\n<advisor prompt, lens from native agent>")
Assign the first task pair — both the drive task and navigate task — simultaneously using the task bus (not TaskUpdate):
- Run
session task-init 1 (and matching ids for other pairs), then establish the driver atomically with session task-start 1 {driver-agent} "next action" -- <owned files...>. This is the hard pre-edit gate: the driver should not be resumed for editing until the claim, state, and write set all exist.
- Then run
session task-claim 1 {navigator-agent} navigator and session task-claim 1 {advisor-agent} advisor (use real agent short names from meta.json), plus session state / session writeset for the navigator as needed. Use session chat for tactical back-and-forth; wake stalled subagents with resume or an explicit prompt — not SendMessage between teammates.
- The navigator begins reviewing immediately — they do not wait for the driver to start.
- After kickoff, run
session health --strict once. Treat any missing driver state or empty write set as a session-mechanics failure, not as something to clean up later.
Reuse orientation agents. If you spawn a scout or research-focused agent for an initial orientation task, create their follow-up task in Step 3 — not mid-session. A follow-up task added after synthesis has already started arrives as an addendum rather than feeding it. Either plan the second assignment upfront (test review, API audit, demo validation) or don't spawn the agent.
For high-risk tasks (schema changes, auth rewrites, public API surface changes), instruct the lead to require plan approval before any edits:
Spawn a craftsman teammate for task 5. Require plan approval before they make any changes — review their approach before they edit anything.
The teammate explores and proposes an approach. You review and approve or reject with feedback. Use when a wrong implementation direction would be expensive to undo.
Haiku agents need explicit constraints. When spawning haiku-model agents, append these lines to every spawn prompt:
CONSTRAINTS (haiku model):
- DO NOT create files in .popcorn-xp/ except via the session script
- DO NOT write summary, checkpoint, statistics, or state files
- DO NOT overwrite or edit the session script
- Only modify source code files and use the session script for logging
Haiku agents will otherwise create junk files (summaries, ASCII art stats, invented state files) and overwrite the session helper. Opus and sonnet agents follow instructions without these constraints.
Use maxTurns for haiku agents. Set maxTurns: 60 on all haiku-model teammates. This is the only reliable shutdown mechanism for haiku — they resist {"continue": false} and loop idle notifications. Opus and sonnet agents respond to shutdown signals correctly and do not need maxTurns unless you want a deliberate lifespan cap.
Default to long-lived teammates for opus/sonnet. The point of Popcorn XP is that agents retain session context across multiple tasks and rotations. Replace a teammate when they signal context strain, produce a handoff, or you explicitly want a fresh perspective.
5. Monitor
Coordination is durable files + task bus — you do not rely on peer SendMessage or TaskUpdate. Your role during execution:
- Assign pairs, enforce rotation. When a drive task completes, use
session task-complete / task-release and the next session task-claim so the navigator becomes driver and the driver takes the next navigate seat. If the same agent has driven two consecutive pairs, you have failed to rotate. Fix it on the next claim. Do not spawn the next subagent turn until meta.json and LOG.md reflect the prior task’s real completion state.
- Navigator completes after driver. When a driver finishes, nudge the navigator subagent (resume or explicit prompt) to verify and
session task-complete their side. If they find issues, they append typed advice to ADVICE.md (OBJECTIONs may reopen work).
- Use bugfix lanes when the work is naturally asymmetric. For bug-driven sessions, prefer
confirm -> RED -> GREEN -> verify over forcing strict alternation on every pair. Typical split: tester drives confirmation+RED pair, craftsman drives GREEN pair, then a fresh-eye verification pair closes the loop.
- Steer when needed. If a teammate is going in the wrong direction, append
session chat on the active task and resume their subagent (or run a targeted prompt).
- Unblock, don't observe. Your job is to remove impediments, not watch progress. When a teammate is stuck, diagnose why and act: split the task, add context to task chat, reassign claims, or clarify. Ask yourself: does this task still serve the session goal? If not, defer it.
- Relay user input. If the user provides new instructions, put them in task chat or
session chat and wake the relevant subagent.
- No idle agents. If a teammate is not driving, they should be navigating, reviewing, reading ahead, or planning. Require navigators to publish a READY artifact before edits start: risk check, test plan, spec check, or review note. After that, they may enter
waiting_on_driver explicitly; "silent and maybe thinking" is not a valid state.
- Capture browser evidence early. For UI-facing work, ask for a browser or screenshot checkpoint at the first meaningful visual milestone. Do not rely on end-of-session Playwright access as the only verification path.
- Handle escalations. If the navigator sends an ESCALATION message (the approach is fundamentally wrong), pause the current task, evaluate the concern, and decide whether to redirect, reset, or continue.
- Periodic code review. After every 2-3 completed tasks (or after any task that touches shared/critical code), launch a structured reviewer independently — not as a teammate (e.g.
popcorn-xp:code-reviewer when using this plugin’s default agents; otherwise use your project’s review agent). Use the Agent tool without team_name. Give it the list of files changed since the last review and ask for a review certificate. When the review comes back:
- BLOCKER findings: relay as OBJECTIONs to the current driver via
session advice and task chat, then ensure ADVICE.md has the typed line
- WARNING findings: relay as SMELLs to the driver
- NITs/OBSERVATIONs: log via session script, don't interrupt the driver
- The code-reviewer never messages teammates directly — you are the relay.
- When relaying findings to ADVICE.md, assign standard IDs using the current task number:
OBJ-{task}-{seq} for blockers, SML-{task}-{seq} for warnings. Do not relay the reviewer's internal IDs (e.g. REV-W1) — translate them. Example: session advice OBJECTION OBJ-6-01 "LayoutContainer has no useDroppable".
- Schema violations: If the project defines schemas (JSON Schema, TypeScript types, Zod, etc.), recommend the team add programmatic validation tests rather than relying on code reviewers to catch structural violations.
- Keep advisors mechanically active. Schedule periodic
/loop or explicit resumes so advisors reread task chat (and session cursor-get / cursor-ack) plus recent LOG.md / ADVICE.md — not context-store.log (team plugin only).
Note: The Agent tool may auto-inherit team_name from the lead's session. The
code-reviewer functions correctly despite this — it does not use SendMessage,
TaskUpdate, or team coordination tools. Its independence is behavioral (enforced
by its prompt), not structural.
- Handle handoff requests. When a teammate sends a context-limit handoff message, read
.popcorn-xp/{team-name}/handoff-{agent-name}.md immediately. If they are rotating out after a completed task, also require .popcorn-xp/{team-name}/snapshot-{agent-name}.md so the next driver gets touched files, verification run, open advice, and the next risk in one place. If a teammate compacts before stopping, the compaction hooks will persist a summary and TeammateIdle will retire them on the next idle once the handoff exists; treat that as a forced handoff, not as normal continuity.
- Watch for stuck tasks. If meta.json / LOG.md disagree with what a subagent said, reconcile with
session task-revision, session health, or manual task-release — don’t assume a background worker self-healed.
- Replace agents before they degrade, not after. When a teammate signals context strain, writes a handoff, or is intentionally running under a
maxTurns cap, spawn the replacement immediately and assign read-ahead, RED-test prep, or verification work while the current agent still has context. Do not wait for a dead stop before bringing in the next agent.
- Recovering unresponsive agents. Resume the same subagent with a pointer to unread task chat, or spawn a fresh worker from LOG.md + ADVICE.md + meta.json. If two wake attempts fail, replace the seat. Do not do the work yourself.
- Don't fall into the orchestrator trap. You have file tools — use them only for session mechanics and emergencies, not to substitute for the driver. If you're spending more time crafting instructions than subagents spend executing them, you're doing their thinking for them. Write the task, claim it on the bus, step back.
- Do not do the work yourself. You are the lead, not a driver. If you find yourself wanting to read a file or write code, delegate it to a teammate instead.
6. Verify and Close
Subagent plugin: There is no TeamDelete gate — closeout is session close-check then session close (see Subagent mode essentials above). Do not skip retro before shutdown markers; the retro file is still written after teammates have submitted .retro-*.md (or handoffs).
-
Ask a teammate (typically the tester if on the bench, otherwise the navigator or driver of the last pair) to run final verification.
-
Confirm no unresolved OBJECTIONs exist (check ADVICE.md or ask via task chat).
-
Check ADVICE.md for open SMELLs, STEERs, and FYIs. For each: (a) resolve it now if trivial, (b) create a follow-up task if it warrants future work, or (c) note it in the retro. Do not let the session end with unacknowledged open items.
-
Retrospective (mandatory — mechanical). Run session retro-request, then nudge each subagent (resume / prompt) to run session retro {agent} '...' or hand in text you record with the same command.
.popcorn-xp/{team-name}/session retro-request
The enforce-no-idle.sh hook will nudge idle workers. Wait for all .retro-*.md files (or valid handoffs) before appending RETRO.md.
-
Shut down workers. Run session shutdown, then explicitly stop or retire each background subagent (product-specific stop / shutdown_request if you also used native team metadata). The retro-pending phase in enforce-no-idle.sh still takes priority over shutdown.
-
Release the bus. session task-release / task-complete / task-abandon as needed so no stale claims remain.
-
session close-check → append RETRO.md (≥5 real lines in the accumulated file) → session close (re-runs close-check, enforces RETRO.md; close --force skips gates). Successful close writes .closed.json, clears .popcorn-xp/.active-team when it still names this team, and truncates context-store.log.
-
Present a technical summary to the user: what was done, what each role found, any remaining risk. Include a brief retro summary (2-3 bullets on what worked, what didn't, what to change next time).
Retro File Format
Write .popcorn-xp/{team-name}/RETRO.md after every session. This file accumulates across sessions — append a new entry, don't overwrite prior retros.
# Popcorn XP Retro
## Session: {date} — {task summary}
Session goal: {goal}. Met: yes/no.
- **Lead host:** {`claude-code` | `codex` | other} — which product ran the lead (which hooks and lead playbook applied).
- **Task transport:** {`subagent` | `team`} — should match `.popcorn-xp/{team}/.runtime-mode` when that file exists.
### Team
- Driver(s): {who drove which tasks}
- Navigator(s): {who navigated which tasks}
- Advisor(s): {if any}
- Native agents used: {list any native agents that filled persona slots, e.g., "test-engineer → tester, flutter-architect → craftsman" — or "none" if all defaults}
### What Worked
- {concrete observation — e.g., "rotation after task 2 gave the expert context they used to catch OBJ-3-01"}
- {concrete observation}
### What Didn't Work
- {concrete observation — e.g., "navigator went idle for 3 checkpoints because checkpoints were too small to analyze"}
- {concrete observation}
### Advice System
- OBJECTIONs raised: {count}
- OBJECTIONs fixed: {count}
- OBJECTIONs rejected: {count}
- SMELLs/STEERs/FYIs: {count}
- Assessment: {did the advice system create the right dynamic? too many objections? too few? did the driver push back enough?}
### Rotation
- {did rotation spread knowledge? did assigning by lens-fit happen despite the protocol? did the navigator-becomes-driver pattern work?}
### Process Observations
- {anything about the protocol itself — too much ceremony? not enough checkpoints? file format issues?}
- {teammate feedback from the retro conversation}
### Recommendations
- {what to change next time — e.g., "start with scout driving orientation before craftsman drives implementation"}
- {what to keep — e.g., "the expert-as-navigator pattern caught 2 real bugs"}
Recording Lead host and Task transport keeps accumulated RETRO.md interpretable: process recommendations may reference spawn defaults, hook behavior, or docs that differ between Claude Code and Codex even when shared/runtime/bin/session behavior is the same.
This file is for the human. Read it before starting the next popcorn-xp session on the same codebase — it's the team's institutional memory about how the process works here.
Lead Quality Bar
- Session recovery. Session files survive teammate loss. If the session is resumed after a crash or interruption, teammates no longer exist — spawn fresh agents seeded with LOG.md and ADVICE.md to reconstruct state.
/resume and /rewind do not restore in-process teammates.
- Research session calibration. In research and analysis sessions (no code being written), expect fewer OBJECTIONs — correctness blockers are rare when the output is findings, not a diff. Peer DMs and SMELLs carry most of the coordination in these sessions. That's normal.
- Stop spawning when done. Stop spawning rounds when additional tasks stop changing the plan. Over-decomposing creates busywork.
- Distinct lenses per seat. Different roles must contribute materially different perspectives. Don't assign three agents with the same lens to different seats.
Teammate protocol (do not duplicate here)
Typed OBJECTION / SMELL / STEER / FYI rules, ADVICE.md and LOG.md contracts, phase values, advice format, rotation, retro submission, and session file boundaries are defined in popcorn-xp-protocol (auto-loaded for popcorn-xp agents). The lead’s spawn prompts only need role assignment, names, and task context — plus shared/skill-sources/templates.md for long template text.
Reference
Read shared/skill-sources/templates.md for teammate prompt templates and role blurbs. Include the relevant template sections in teammate prompts when spawning them.
Other transport
- File-bus /
session task-*: popcorn-xp plugin + popcorn-xp skill (sibling playbook under shared/skill-sources/lead-playbook/).
- Agent Teams /
TaskUpdate + SendMessage: popcorn-xp-team plugin + popcorn-xp-team skill.