# 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>")`. 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="<task-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<TapAudioPipe>` 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<n>, 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<n> — <one-line title>
EXPECTED OUTCOME: <files touched + tests added + commit message>
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<n>
- Read the spec section: docs/superpowers/specs/2026-07-05-slice-5-rented-transport-design.md -- §<relevant>
- 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 '<message from plan>'
- 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<TapAudioPipe>` + `LocalVadReflex<Reflex<TapAudioPipe>>` 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<TapAudioPipe>` + `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<P>` 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<TapAudioPipe> + 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<SpendToken> 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.
