# Dev C Kickoff Prompt — spearhead-4half-and-5 — Plan C (step-5 FOB media + MediaThread wiring) You have been spawned by the PM as a long-running background `task(subagent_type="general", run_in_background=true, prompt="")`. This file IS your initial context — you inherit it verbatim. Your job: execute your tasks (T1, T3, T4, T5, T7, T8) of the step-5 plan + dispatch Kimi-worker subagents per task. --- You are a **senior developer** owning Plan C's FOB side for the `spearhead-4half-and-5` "benchmark + sim harness + rented transport" release. Your slice is **step-5 rented transport, FOB half** (`crates/rutster-trunk/src/{g711.rs, twilio_media_streams.rs, session.rs, loop_driver.rs}` + `crates/rutster-trunk/src/lib.rs` + `crates/rutster/src/media_thread.rs` `MediaLeg` enum + `MediaCmd::RegisterTrunk` variant + `crates/rutster/src/routes.rs` two new HTTP routes + `crates/rutster/src/main.rs` axum router mount). Per strategic plan §4.1: you own tasks **T1, T3, T4, T5, T7, T8**. A PM coordinates you with dev-a (slice-4½ sim harness — different slice, parallel work, no overlap) and dev-b (step-5 green-zone side — T2/T6/T9/T10; same slice, different file ownership). The relay server lives at `localhost:7110`. **Kimi-worker dispatch model:** same as dev-a / dev-b — you do NOT write the code yourself. Each of your tasks becomes ONE `task(subagent_type="kimi-worker", load_skills=["programming"], run_in_background=false, prompt="")` invocation. ## Setup (do this first) ```bash cd /home/alee/Sources/rutster git fetch && git checkout main && git pull git worktree add /home/alee/Sources/rutster.slice-5-trunk-b -b slice-5/rented-transport-dev-c ``` Then `cd /home/alee/Sources/rutster.slice-5-trunk-b && pwd` — should print `/home/alee/Sources/rutster.slice-5-trunk-b`. **ALL work happens in that worktree.** Every Kimi subagent prompt MUST begin with `cd /home/alee/Sources/rutster.slice-5-trunk-b`. Today: 2026-07-05. Project rules in `AGENTS.md` apply (read in full). ## Relay server + polling cadence Same shape as dev-a / dev-b: `post_message` / `read_messages` / `list_pending`, role = `"dev-c"`. Fallback shim `RELAY_PORT=7110 python3 ~/Sources/relay/call.py ...` if MCP tools aren't registered. Single-line `body` (no embedded newlines). **Relay polling cadence — MANDATORY:** before each Kimi subagent dispatch + again on return; before each commit; start+end of every task step; whenever heads-down for more than a few minutes. A `HOLD` or `RESCOPE` is an interrupt, not a suggestion. ## Required reading (in order) 1. `AGENTS.md` — full. Especially: "Architecture pre-reading" (ADR-0007 + ADR-0008 FOB classification for the WSS server + G711Codec + TrunkSession = FOB members; ADR-0009 credential isolation; ADR-0002 fused vertical — the trunk leg participates in the same 20 ms tick on the dedicated thread, no gRPC hop in the FOB), "Code style (Rust)" (learner-facing comments) + the µ-law formula's teachable-moment callout, "Slice-1 boundaries — what NOT to add" (no PSTN media first-party, etc.). 2. `docs/superpowers/specs/2026-07-05-slice-5-rented-transport-design.md` — the step-5 spec. Your tasks intersect §2 architecture delta + §3 components across all of §3.1 (G711Codec) + §3.2 (TwilioMediaStreamsServer) + §3.3 (TrunkSession + trunk_driver::drive) + §3.5 (MediaCmd::RegisterTrunk + MediaLeg enum) + §3.6 (HTTP routes) + §4 data flow + §5 (ADR- 0009 honoring isn't directly yours — dev-b's T6 holds the credential struct — but you must NOT pass `TwilioCredentials` through the brain's WS protocol). Read §6 (why-these- decisions; §6.1 REUSE of slice-4's `Reflex` is the architecture's load-bearing claim) + §7 done-criteria + §8 open decisions carefully. 3. `docs/superpowers/plans/2026-07-05-slice-5-rented-transport.md` — implementation plan. Your tasks: T1 (G711Codec + tables), T3 (TwilioMediaStreamsServer), T4 (TrunkSession + trunk_driver::drive), T5 (MediaCmd::RegisterTrunk + MediaLeg + 2 HTTP routes), T7 (reflex-on-trunk verification test), T8 (PSTN sim e2e). Other tasks (T2, T6, T9, T10) are dev-b's. 4. `.omo/plans/2026-07-05-spearhead-4half-and-step-5-strategic.md` — strategic plan. §3.2 is your task list with dependencies; §4.1 is your scope summary. 5. `crates/rutster/src/media_thread.rs` — the merged slice-4 + slice-5/seams `MediaThread` you extend. Read in full before T5. The `Connected` transition spawn seam (slice-4 Task 6) is the pattern T5's `RegisterTrunk` handler mirrors. 6. `crates/rutster-media/src/loop_driver.rs` + `rtc_session.rs` — read for shape reference only. DO NOT TOUCH. Your `trunk_driver::drive` parallels `loop_driver::drive` minus the str0m/Opus/RTP machinery. ## Execution mode — Kimi-worker dispatch shape Per task T, dispatch: ```text task( subagent_type="kimi-worker", load_skills=["programming"], run_in_background=false, prompt="cd /home/alee/Sources/rutster.slice-5-trunk-b TASK: T EXPECTED OUTCOME: REQUIRED TOOLS: Read, Edit, Write, Bash (cargo test, cargo fmt --check, cargo clippy -- -D warnings) MUST DO: - Read the plan section: docs/superpowers/plans/2026-07-05-slice-5-rented-transport.md -- Task T - Read the spec section: docs/superpowers/specs/2026-07-05-slice-5-rented-transport-design.md -- § - Read AGENTS.md 'Architecture pre-reading' + 'Code style (Rust)' (learner comments REQUIRED) - For T1: read the ITU-T G.711 µ-law formula reference (Wikipedia is sufficient; https://en.wikipedia.org/wiki/%CE%9C-law_algorithm). Cross-verify the table against the spec. - For T4: read crates/rutster-media/src/loop_driver.rs for shape reference only -- your trunk_driver::drive parallels it minus the str0m machinery. DO NOT modify that file. - DCO signoff: git commit -s -m '' - Tests: TDD -- failing test first, verify failure, implement, verify pass. - Run before commit: cargo fmt --all --check && cargo clippy --all --all-targets -- -D warnings && cargo test --all MUST NOT DO: - Do NOT touch crates/rutster-media/src/{loop_driver.rs,rtc_session.rs} -- seam invariant (sacred) - Do NOT touch crates/rutster-trunk/src/provider/* -- dev-b's files (CallControlClient trait, MockCallControlClient, TwilioCallControlClient, TwilioCredentials) - Do NOT touch crates/rutster/src/config.rs -- dev-b's territory for the env parser (T6) - Do NOT push --force, --reset --hard, branch -D, rm -rf - Do NOT start the next task in this subagent -- report STATUS only CONTEXT: - Branch: slice-5/rented-transport-dev-c - Plan path: docs/superpowers/plans/2026-07-05-slice-5-rented-transport.md - Spec path: docs/superpowers/specs/2026-07-05-slice-5-rented-transport-design.md - dev-b's sibling tasks may be landing in parallel; rebases forward to inherit T2's provider/ module are expected (dev-b's branch shares the lib.rs edit per the stacked-branches carve-out in AGENTS.md Git workflow). dev-b's T2 lands the pub mod provider; line, then you rebase forward + add pub mod g711; pub mod twilio_media_streams; pub mod session; pub mod loop_driver; lines as you go." ) ``` ## Your scope and boundaries **In scope:** step-5 FOB side (per spec §2.2): - **T1** — `G711Codec` + `mulaw_decode_table` (256 entries) + `mulaw_encode_table` (65536 entries). In-core µ-law codec (no dep — the table is ~30 lines of `const fn` generation per the ITU-T formula). 8 kHz↔24 kHz linear-interpolated resampling (3× upsample on decode, 3× decimation downsample on encode). Files: `crates/rutster-trunk/src/{g711.rs, mulaw_decode_table.rs, mulaw_encode_table.rs, lib.rs}` — first commit on this crate beyond the stub. CRITICAL-PATH FOUNDATION; T3 + T4 consume it. - **T3** — `TwilioMediaStreamsServer` (axum WSS handler) + `RegisterTrunkInboundChannel` type. Parses the JSON envelope (`connected` / `start` / `media` / `stop`), base64-decodes µ-law payload, `G711Codec::decode_mulaw_to_pcm` → push to inbound_from_twilio_tx; concurrently drains outbound_to_twilio_rx, `G711Codec::encode_pcm_to_mulaw` → wrap in JSON `media` envelope → send WS Text frame. File: `crates/rutster-trunk/src/twilio_media_streams.rs` (+ register it in lib.rs). - **T4** — `TrunkSession` (per-trunk-leg session struct) + `trunk_driver::drive` (the per-tick function — parallels `crates/rutster-media/src/loop_driver.rs` minus str0m). Files: `crates/rutster-trunk/src/{session.rs, loop_driver.rs}` (+ register both in lib.rs). REUSES slice-4's `Reflex` + `LocalVadReflex>` verbatim (spec §6.1 — the architectural load-bearing claim). The leg participates in the existing 20 ms MediaThread tick via the new MediaLeg enum (T5); the existing WebRTC leg code path is unchanged. - **T5** — `MediaCmd::RegisterTrunk` variant + `MediaLeg` enum (the session-map value type changes from `RtcSession` to `MediaLeg` in `crates/rutster/src/media_thread.rs`) + the `run_per_leg_tick` dispatch match (`WebRTC(s) => loop_driver::drive(s, now)` UNCHANGED, `Trunk(s) => trunk_driver::drive(s, now)` NEW) + `POST /v1/trunk/sessions` (originate handler) + `POST /v1/trunk/webhook` (Twilio inbound-call webhook receiver) in `crates/rutster/src/routes.rs` + mount `TwilioMediaStreamsServer::router` on the axum router in `crates/rutster/src/main.rs`. - **T7** — `crates/rutster-trunk/tests/reflex_on_trunk.rs` — proves slice-4's `Reflex` + `LocalVadReflex` decorate the trunk leg's TapAudioPipe identically; barge-in fires on PSTN caller speech through the same state machine as WebRTC caller speech. - **T8** — `crates/rutster-trunk/tests/sim_integ.rs` — PSTN-sim e2e integration test. `MockTwilioMediaStreamsServer` (in-process test double feeding synthetic `PcmFrame`s) + `MockRealtimeBrain` (slice-3 merged) drives a synthetic PSTN caller through the FOB reflex loop: loud PCM → local VAD trips → barge kills → brain yields → brain reply observed → un-mute → caller hangup → EventSink emits `ChannelEnded`. **Out of scope (dev-b's territory — file ownership non-overlapping):** - `crates/rutster-trunk/src/provider/{mod.rs, mock.rs, twilio.rs}` (CallControlClient trait + Mock + Twilio + TwilioCredentials) — dev-b - `crates/rutster/src/config.rs` (twilio_credentials env parser) — dev-b - `crates/rutster-trunk/Cargo.toml` deps (reqwest, async-trait, base64) — coordinate via PM if you need to add `axum` to dev-b's deps; the spec's Cargo.toml includes them all - `docs/QUICKSTART.md`, `README.md` — dev-b - `.github/workflows/ci.yml` re-pin verification + `deny.toml` recheck — dev-b's T10 **Cross-dev signals worth relaying to PM (dev-c → PM):** - If `MediaLeg::WebRTC(s) => loop_driver::drive(s, now)` requires ANY source change in `loop_driver.rs` or `rtc_session.rs` — that's a SEAM VIOLATION. STOP + emit `## QUESTION TO PM`. The intended dispatch is `loop_driver::drive(s, now)` UNCHANGED, called via the match arm; the existing call-site is the same code, just routed through the enum. No signature changes. No new code in the seam files. - If the µ-law formula's encode/decode round-trip tests fail beyond 12% energy drift (the spec §6.5 budget), STOP + emit `## QUESTION TO PM` with the drift number + a proposed resolution (use a `g711` crate dep OR use `rubato` for the resampler — both are post-spearhead refinements per spec §1.2 + §8.1, but a real regression breaks the wedge claim; the user must decide). - If T7 (reflex-on-trunk verification) reveals that slice-4's reflex stack DOESN'T compose symmetrically against the trunk leg (i.e. needs a "trunk-specific" barge code path), STOP + emit `## QUESTION TO PM`. That's a slice-4 architectural smell — the user + PM must decide if step-5 lands a slice-4 fix OR a step-5 carve-out. ## Hard rules (project + slice-specific) - Two seam files untouched (slice-4 Task 10 pinned-blob CI gate). Your `trunk_driver::drive` is in `crates/rutster-trunk/src/loop_driver.rs` — a DIFFERENT file in a DIFFERENT crate. Same name as the seam file by deliberate parallelism; they are distinct files. If your CI pinned-blob check fails on `loop_driver.rs` post-merge, it means you accidentally edited the WRONG file (the seam one in `rutster-media`). Run `git checkout main -- crates/rutster-media/src/{loop_driver.rs,rtc_session.rs}` to restore + re-commit. - **The seam invariant is sacred.** This task is the one most likely to be its first violator — broadcast this fact in every Kimi subagent prompt that touches `loop_driver.rs`. - **`Reflex

` REUSE is the architecture's load-bearing claim** (spec §6.1). If slice-4's reflex stack requires a "trunk-specific" barge code path, that contradicts §6.1 — surface as `## QUESTION TO PM` immediately. - DCO signoff every commit. - Learner-facing comments per AGENTS.md — the µ-law table the most teachable-moment in this slice; comment density earns the override of the no-comments convention. - Hot-path policy (you touch the 20 ms tick via `trunk_driver::drive`): never `?`-propagate; `try_recv`/`try_send`, drop + observe + continue. A malformed Twilio JSON envelope MUST NOT crash the std thread. - No destructive git ops without PM signoff. - Every Kimi subagent prompt starts with `cd /home/alee/Sources/rutster.slice-5-trunk-b`. ## Coordination protocol 4 terminals (PM + dev-a + dev-b + dev-c). You post to + receive from `dev-c`. STATUS UPDATE + QUESTION TO PM formats identical to dev-a's (substitute `DEV-C` and the dev-c branch). Print locally + post to relay. Narration discipline per AGENTS.md. ## 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 + spec. - Write tests, refactor your own code, fix bugs you introduce. - Push commits to your feature branch. You DO escalate to PM when: - A scope question outside the plan. - A test you can't make green after honest debugging (don't fudge — debug). - A discovered bug not in your plan. - A seam violation risk (the most likely escalation for this slice). - Before opening the PR for review. ## Final steps before REVIEW-READY Full validation from the worktree: ```bash cargo fmt --all --check cargo clippy --all --all-targets -- -D warnings cargo test --all cargo test --all --features=twilio-live # if dev-b's T6 is merged; manual run only cargo deny check cargo doc --no-deps ``` Then push + open the PR: ```bash git push -u origin slice-5/rented-transport-dev-c tea pulls create \ --head slice-5/rented-transport-dev-c \ --base main \ --title "slice-5 (rented transport, FOB half): G711Codec + TrunkSession + trunk_driver + MediaLeg enum + reflex-on-trunk verification (T1/T3/T4/T5/T7/T8)" \ --description "## What lands - G711Codec (in-core µ-law + 8kHz↔24kHz linear-interpolated resampling; ~30-line ITU-T formula; no dep). - TwilioMediaStreamsServer (axum WSS handler; JSON envelope; base64 µ-law decode; concurrent inbound/outbound mpsc drain). - TrunkSession + trunk_driver::drive (parallels loop_driver::drive minus str0m/-- REUSES slice-4's Reflex + LocalVadReflex verbatim per spec §6.1). - MediaCmd::RegisterTrunk + MediaLeg enum + run_per_leg_tick dispatch (MediaThread's existing WebRTC code path UNCHANGED; the trunk leg's tick is a NEW parallel sibling). - POST /v1/trunk/sessions (originate) + POST /v1/trunk/webhook (Twilio inbound-call receiver) routes. - Reflex-on-trunk-leg verification test (T7): proves slice-4's decorators compose symmetrically; barge-in fires on PSTN caller speech. - PSTN-sim e2e integration test (T8): MockTwilioMediaStreamsServer + MockCallControlClient + MockRealtimeBrain → 1 synthetic PSTN caller → barge-in → brain reply → CDR emission. ## ADR-0007 honored - Zero SIP bytes parsed. The wire surface is JSON (Media Streams envelope) + RTP (WebRTC, unchanged) + HTTP/REST (Twilio CallControl API, dev-b's green-zone path). ## Seam invariant - crates/rutster-media/src/{loop_driver.rs,rtc_session.rs} byte-identical. The trunk leg's tick function lives in crates/rutster-trunk/src/loop_driver.rs -- a separate file in a separate crate, parallel-titled by deliberate design. The slice-4 Task 10 pinned-blob CI gate stays green. ## ADR-0009 honored - TwilioCredentials lives in crates/rutster-trunk/src/provider/{mod.rs} (dev-b's territory); your trunk_driver.rs and trunk_session.rs NEVER reference TwilioCredentials directly -- only the CallControlClient trait's Option parameter (the trait lives in dev-b's provider/; you reference the trait, not the impl). ## Merge instructions - rebase-merge, NOT squash -- this branch shares lib.rs edits with dev-b's slice-5/rented-transport-dev-b (stacked branches per AGENTS.md Git workflow carve-out). - DCO signoff every commit. - after merge: maintainer tags main: slice-5-trunk-fob-merged" ``` Emit `## STATUS UPDATE` with `Status: REVIEW-READY` + tea PR URL. Do NOT merge the PR — after merge, the maintainer runs the live Twilio e2e validation manually. ## First action After the required reading: emit a `## STATUS UPDATE` confirming setup complete (worktree created, on `slice-5/rented-transport-dev-c`, spec + impl plan + ADRs absorbed), then start Task T1 (G711Codec — the critical-path foundation for your chain) by dispatching a Kimi-worker subagent with the per-task prompt shape above substituted for T1 (~30-50 LOC of const fn + table generation + tests; low risk; lands first per the plan's critical path). **On your lifecycle as a background subagent:** same as dev-a / dev-b's — the PM holds your `bg_...` task ID, polls your output via `background_output(task_id="bg_...")` between its own turns, and surfaces your STATUS reports + the eventual tea PR URL to the user. Drain your relay inbox at `for="dev-c"` before each Kimi-worker dispatch + after each commit. On REVIEW-READY emit a final STATUS + return; PM handles PR surface + user merge approval + the manual live Twilio e2e validation step.