Files
rutster/docs/superpowers/kickoffs/2026-07-01-slice-4-dev-b-prompt.md
A.D.Lee 3f494cb919
All checks were successful
CI / fmt (push) Successful in 1m37s
CI / clippy (push) Successful in 2m34s
CI / test (1.85) (push) Successful in 5m19s
CI / test (stable) (push) Successful in 4m5s
CI / deny (push) Successful in 1m58s
spec+plan(slice-4): barge-in / VAD-driven playout kill on dedicated media thread (#6)
2026-07-03 03:06:58 +00:00

13 KiB

Dev B Kickoff Prompt — slice-4 Plan B (TapAudioPipe + advisory + MockRealtimeBrain)

Paste everything below the --- line into a fresh Claude Code terminal as the first user message.


You are a senior developer owning the tap + advisory chain for the slice-4 "barge-in / VAD-driven playout kill" release. A PM in another terminal coordinates you with dev-a. With the relay server running, you communicate via post_message / read_messages directly — no user copy-paste needed.

Your scope (the tap + advisory chain)

You own the brain↔FOB advisory plumbing + the mock brain's VAD schedule — the pieces that wire brain-side advisories into dev-a's Reflex. Tasks:

  • Task 3 (TapAudioPipe::barge_in_flush override + TapMetrics.barge_drained_inflight)
  • Task 4 (advisory_tx through run_tap_client + handle_brain_frame)
  • Task 5 (spawn_tap_engine signature change — takes advisory_tx as a parameter)
  • Task 8 (MockRealtimeBrain advisory schedule)
  • Possibly Task 9 + Task 10 (shared — PM assigns; likely dev-a since their chain finishes Task 7 first, but you might pick these up if your Task 8 lands before dev-a's Task 6 coordination point)

You HOLD until dev-a's Task 1 merges (the critical-path foundation — AdvisoryEvent enum + ReflexMetrics + barge_in_flush trait). Your Task 3 depends on Task 1's barge_in_flush trait method. While you wait, read the plan + the slice-2/3 code for context.

Your work wires the SECONDARY/confirmation trigger path (the brain's ASR-quality VAD). The PRIMARY trigger is dev-a's LocalVadReflex — but your advisory plumbing IS the path the wedge-#1 e2e test's secondary case exercises.

Setup (do this first)

cd /home/alee/Sources/rutster
git fetch
git checkout main
git pull
git worktree add /home/alee/Sources/rutster.slice-4-dev-b -b slice-4-dev-b-tap
cd /home/alee/Sources/rutster.slice-4-dev-b
pwd  # should print /home/alee/Sources/rutster.slice-4-dev-b

ALL subsequent work happens in /home/alee/Sources/rutster.slice-4-dev-b. Force-cd subagents into this directory.

Today: 2026-07-01. Project rules in AGENTS.md apply — READ THEM IN FULL, especially "Code style (Rust)" (learner-facing comments override the global no-comments rule), "Terminology policy" (inclusive language; ICE is kept verbatim per RFC convention), "Git workflow" (squash-merge default + DCO signoff REQUIRED on every commit via git commit -s), "Slice-1 boundaries — what NOT to add (yet)."

Relay server

A message-bus MCP server is running on localhost:7110. You have three native tools:

  • post_message(from, to, kind, body) — push a message; your from is always "dev-b"
  • read_messages(for) — drain your inbox; call with for="dev-b" before each task
  • list_pending(for) — check inbox count without consuming

Recipients: pm, dev-a, dev-b, dev-c, dev-d, dev-e, dev-f. Use these instead of asking the user to copy-paste. Before starting each task: read_messages(for="dev-b"). After emitting any status/question block: post_message(from="dev-b", to="pm", kind="status"|"question", body="...").

Fallback: If the relay MCP tools are not registered in your session, use the Python shim:

export RELAY_PORT=7110
cd ~/Sources/relay
python3 call.py post_message '{"from":"dev-b","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-b"}'

Common pitfalls:

  • Prefer single-line body content (strict JSON parsers reject embedded \n).
  • Use single quotes inside f-strings: {m.get('from')}.

Relay polling cadence — MANDATORY (do NOT go head-down)

The #1 failure mode is a dev going head-down on a long run and never checking the inbox — so a PM HOLD or RESCOPE is never seen. Do not be that dev.

Call read_messages(for="dev-b") (or list_pending(for="dev-b")) at ALL of these points:

  • Before dispatching EACH subagent — and again the moment it returns.
  • Before EACH commit, and at the start + end of every task/step.
  • Any time you've been heads-down for more than a few minutes.
  • Especially while you hold for Task 1: poll every few minutes so you see dev-a's REVIEW-READY the moment it lands + the PM clears you to start.

An inbound Action: HOLD or RESCOPE is an interrupt, not a suggestion: stop immediately, do NOT dispatch the next subagent, acknowledge with a STATUS UPDATE, and comply before resuming.

Required reading (in order — read this while holding for Task 1)

  1. AGENTS.md — the whole thing (code style, git workflow with DCO, slice boundaries)
  2. docs/superpowers/specs/2026-07-01-slice-4-barge-in-design.md — your scope is Tasks 3, 4, 5, 8 (+ possibly 9, 10)
  3. docs/superpowers/plans/2026-07-01-slice-4-barge-in.md — your plan, execute task by task
  4. crates/rutster-tap/src/tap_audio_pipe.rs — the seam object you'll extend in Task 3 (the barge_in_flush override)
  5. crates/rutster-tap/src/tap_client.rshandle_brain_frame (line 323-421) + run_tap_client (line 140-270); Task 4 threads advisory_tx through both
  6. crates/rutster-tap/src/metrics.rsTapMetrics struct (Task 3 adds barge_drained_inflight)
  7. crates/rutster-brain-realtime/src/mock.rsMockRealtimeBrain (Task 8 adds the advisory schedule)
  8. crates/rutster-tap/src/protocol.rs — the wire protocol (the encode_speech_started/encode_speech_stopped your code forwards in Task 4)
  9. crates/rutster/src/tap_engine.rsspawn_tap_engine (line 131-216) + run_engine_loop (line 240-356); Task 5 changes spawn_tap_engine's signature

Execution mode

Use subagent-driven-development. Invoke superpowers:subagent-driven-development and follow it: fresh subagent per task, two-stage review between tasks.

Every subagent prompt MUST start with:

cd /home/alee/Sources/rutster.slice-4-dev-b

…before any other instruction.

Between every subagent dispatch, poll the relay.

Your scope and boundaries

In scope: Task 3 (TapAudioPipe::barge_in_flush override + TapMetrics.barge_drained_inflight), Task 4 (advisory_tx through run_tap_client + handle_brain_frame), Task 5 (spawn_tap_engine signature change), Task 8 (MockRealtimeBrain advisory schedule). Possibly Task 9 (e2e secondary path) + Task 10 (shared).

Out of scope (dev-a owns): Task 1 (foundation — AdvisoryEvent + ReflexMetrics + the barge_in_flush trait method on AudioPipe), Task 2 (Reflex<P> state machine), Task 2b (LocalVadReflex<P>), Task 6 (MediaThread), Task 7 (session_map.rs rewire). If you trip over an out-of-scope issue, file a QUESTION TO PM and keep moving.

Hard rules:

  • The seam gate: crates/rutster-media/src/loop_driver.rs + crates/rutster-media/src/rtc_session.rs MUST stay byte-identical to slice-3. You probably won't touch them, but if you find yourself wanting to, STOP — file a QUESTION TO PM.
  • HOLD until dev-a's Task 1 merges. Task 3 depends on Task 1's barge_in_flush trait method. The PM will clear you to start.
  • DCO signoff: every commit MUST be git commit -s (or --signoff).
  • Task 5 signature revision (load-bearing): the plan originally sketched spawn_tap_engine returning a 3-tuple (TapAudioPipe, TapConn, Option<Receiver<AdvisoryEvent>>). The revised plan (after the slice-4 adversarial review + the user's "both, local VAD primary" decision) changed this: spawn_tap_engine TAKES advisory_tx: mpsc::Sender<AdvisoryEvent> as a parameter (the media thread owns the channel + clones the Sender; tokio::sync::mpsc::Sender is Clone). Follow the plan's Task 5 revision note, NOT the original 3-tuple sketch. The plan's Task 6 composition site (dev-a's MediaThread) constructs the (tx, rx) pair, clones tx for both spawn_tap_engine AND LocalVadReflex::new. This means your spawn_tap_engine signature is pub fn spawn_tap_engine(session_id, tap_url, app_state, advisory_tx) -> (TapAudioPipe, TapConn).
  • Do not merge your branch to main. The PM owns merges.
  • Do not push --force or run git reset --hard. Per AGENTS.md: ask first.

Coordination protocol

You are one of 3 terminals. The user's only window into your work is what flows through this terminal and the relay — silence reads as "stuck" even when you're cooking. Narrate.

Narration discipline. STATUS UPDATEs at task boundaries are the floor, not the ceiling. Also emit Status: IN-PROGRESS updates at meaningful in-flight moments:

  • When you dispatch a subagent
  • When a subagent returns with a decision worth flagging
  • When a sub-task within a phase completes
  • When you change direction or hit something unexpected
  • When you start a new phase

The Notes field should narrate WHAT happened and WHY — not just "Phase X done". Three sentences max.

Also print every STATUS UPDATE locally before/after sending it.

At every task boundary AND every meaningful in-flight moment: call read_messages(for="dev-b") first, then post your update via post_message(from="dev-b", to="pm", kind="status"|"question", body="...") and also print it here. Format:

## STATUS UPDATE — DEV-B
Time: <iso8601>
Branch: slice-4-dev-b-tap
Task: <number / short name>
Status: STARTED | IN-PROGRESS | DONE | BLOCKED | REVIEW-READY
Last commit: <short sha + first line of message>
Tests: <green | red (which failed) | N/A>
Notes: <3 sentences max>

When you need PM input mid-task: post via post_message(kind="question") with format:

## QUESTION TO PM — DEV-B
Time: <iso8601>
Context: <what task, what decision point>
Options: <A: ... / B: ... / C: ...>
Recommended: <your pick + one-sentence rationale>
Blocker: yes | no

Coordination point (load-bearing): dev-a's Task 6 (MediaThread) needs your Task 5 (spawn_tap_engine accepting advisory_tx). When dev-a posts a QUESTION TO PM about whether your Task 5 has merged, post a STATUS UPDATE confirming. If you're still mid-Task-5, surface an ETA.

You'll receive: ## DIRECTIVE TO DEV-B blocks from the PM via relay. Acknowledge and act.

Ship-it autonomy + simplify discipline

Hard guardrails: no rm / rmdir, no git push --force, no git reset --hard, no git branch -D, no git worktree remove, no git clean -f*, no git checkout -- *, no sudo, no chmod 777. If you genuinely need one of these, surface a QUESTION TO PM block.

Speed without spaghetti — required before every REVIEW-READY:

  • Invoke superpowers:simplify on the changed code.
  • Do not create parallel implementations of an existing helper.
  • Do not add error handling, fallbacks, or validation for scenarios that can't happen.
  • Default to learner-facing comments per AGENTS.md code style.
  • Half-finished implementations are forbidden. Either ship a complete sub-task or surface a QUESTION TO PM block.

Authority within the plan

You don't need PM permission to:

  • Execute task-to-task per the plan
  • Make implementation decisions consistent with the plan and spec
  • Write tests, refactor your own code, fix bugs you introduce
  • Push commits to your feature branch (with DCO signoff)

You do escalate to PM when:

  • A scope question outside the plan
  • A test you can't make green after honest debugging
  • A discovered bug not in your plan
  • Anything destructive
  • Before opening the PR for review

MockRealtimeBrain schedule API (Task 8 open decision)

The plan proposes set_advisory_schedule(Vec<AdvisoryTrigger>) where AdvisoryTrigger { after_audio_in_frames: u32, event: AdvisoryKind }. If a cleaner shape emerges during implementation (e.g., a free-form Vec<(trigger_frame_count, AdvisoryEvent)> queue), use it — but surface the deviation in the STATUS UPDATE Notes so the PM can sanity-check. The slice-4 e2e (Task 9) is the consumer of this API; if you change the shape, Task 9 (whoever picks it up) needs the new name.

Final steps before REVIEW-READY

Run the project's full validation:

cargo fmt --all --check
cargo clippy --all --all-targets -- -D warnings
cargo test --all

Then push and open the PR:

git push -u origin slice-4-dev-b-tap
tea pulls create \
  --head slice-4-dev-b-tap \
  --base main \
  --title "slice-4 (dev-b): TapAudioPipe::barge_in_flush + advisory_tx + MockRealtimeBrain schedule" \
  --description "## What lands
- Task 3: TapAudioPipe::barge_in_flush override + barge_drained_inflight metric
- Task 4: advisory_tx through run_tap_client + handle_brain_frame
- Task 5: spawn_tap_engine takes advisory_tx parameter (signature revision)
- Task 8: MockRealtimeBrain advisory schedule

## What this enables
The brain's speech_started/speech_stopped advisory reaches dev-a's Reflex via the dedicated advisory_tx side-channel. This is the SECONDARY/confirmation path (the PRIMARY is dev-a's LocalVadReflex). The slice-4 e2e's secondary case exercises this.

## Merge instructions
- squash-merge
- DCO signoff on every commit (AGENTS.md)"

Emit a ## STATUS UPDATE with Status: REVIEW-READY and the PR URL.

First action

After reading + setup: emit a ## STATUS UPDATE confirming setup complete (worktree created, plan absorbed, on slice-4-dev-b-tap, reading slice-2/3 code for context). State explicitly: "HOLD for dev-a Task 1 REVIEW-READY; polling pm inbox." Do NOT start Task 3 until the PM clears you (dev-a's Task 1 must merge first). Poll every few minutes while you read.