docs: PM-mode discipline + multi-agent relay coordination protocol #5
295
AGENTS.md
295
AGENTS.md
@@ -219,10 +219,28 @@ and "why isn't X here?" questions. Consult it before adding anything.
|
||||
|
||||
- **Trunk-based development** (target, once branch protection is in place):
|
||||
1. Branch from `main` for any change.
|
||||
2. Open a PR targeting `main`.
|
||||
3. CI gates: `cargo fmt --check`, `cargo clippy -- -D warnings`, `cargo test --all`,
|
||||
2. Push the branch to origin (`git push -u origin <branch>`).
|
||||
3. Open a PR targeting `main` via **`tea`** (Gitea CLI, not `gh`):
|
||||
```bash
|
||||
tea pulls create \
|
||||
--head <branch> \
|
||||
--base main \
|
||||
--title "<imperative subject ≤72 chars>" \
|
||||
--description "<body — what, why, merge instructions, reviews>"
|
||||
```
|
||||
The `tea` login is `alee` (default), against `https://git.adlee.work`. Verify with
|
||||
`tea login list` if auth fails. `tea pulls list` shows open PRs; `tea pulls merge <index>`
|
||||
merges from CLI (honors the merge strategy passed via `--style`).
|
||||
4. CI gates: `cargo fmt --check`, `cargo clippy -- -D warnings`, `cargo test --all`,
|
||||
`cargo deny check`. All must pass before merge.
|
||||
4. Squash-merge to keep `main` linear.
|
||||
5. **Merge strategy — default squash, carve-out for stacked branches:**
|
||||
- **Default:** squash-merge to keep `main` linear. One commit per PR, clean history.
|
||||
- **Rebase-merge carve-out:** when a PR's commit SHAs are carried by downstream branches
|
||||
(the "stacked branches" topology — pivot/strategic-doc PRs that depend on each other),
|
||||
use **rebase-merge** instead. This preserves the original commit SHAs so downstream
|
||||
branches see the pivot as "already in main" with zero rebase pain. Squash would orphan
|
||||
the originals and force conflict-prone rebases across every dependent branch. State
|
||||
"merge via rebase-merge, not squash" explicitly in the PR description when this applies.
|
||||
- **Never push directly to `main`.** Branch protection (planned) will enforce; until then,
|
||||
self-discipline.
|
||||
- **Commit messages:** imperative mood, subject ≤ 72 chars, body wraps at 72, blank line
|
||||
@@ -232,6 +250,277 @@ and "why isn't X here?" questions. Consult it before adding anything.
|
||||
each land as separate commits when practical. Don't bundle unrelated work.
|
||||
- **Never commit secrets.** The `.gitignore` already covers `.env*`, `*.pem`, `*.key`. If
|
||||
a new secret pattern appears, extend `.gitignore` in the same commit.
|
||||
- **PR description template** (for non-trivial PRs):
|
||||
```
|
||||
## What lands
|
||||
- <bullet per logical change>
|
||||
|
||||
## Merge instructions (if non-default)
|
||||
- <e.g. "rebase-merge, not squash — see AGENTS.md Git workflow">
|
||||
|
||||
## Reviews (if applicable)
|
||||
- <companion review docs / ADRs / specs>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multi-agent coordination — the relay (cross-model)
|
||||
|
||||
When more than one agent session works this repo in parallel (the PM / senior-dev "lift"
|
||||
paradigm), they coordinate through a small MCP message-bus — the **relay** at
|
||||
[`~/Sources/relay`](file:///home/alee/Sources/relay). One server, many terminals: each
|
||||
session posts and drains messages **by role** instead of the user copy-pasting blocks
|
||||
between windows.
|
||||
|
||||
**The relay is model-agnostic.** Nothing about it is Claude-specific — it speaks plain
|
||||
MCP / JSON-RPC over HTTP. A **GLM-backed agent and a Claude agent share the same bus** and
|
||||
exchange messages transparently, as long as both point at the same running relay and use
|
||||
the same role/kind vocabulary below.
|
||||
|
||||
- **Currently running on `localhost:7110`.** The port is set by `RELAY_PORT` (default
|
||||
`7331` if unset). The server binds `127.0.0.1`, so **all agents must be on this host**
|
||||
(a GLM agent in a separate container/VM can't reach it over localhost).
|
||||
- **Roles are slots, not models.** The relay knows `pm, dev-a, dev-b, dev-c, dev-d,
|
||||
dev-e, dev-f` — that's it. A GLM agent claims a free role (say `dev-c`) exactly like a
|
||||
Claude agent claims `dev-a`; the relay neither knows nor cares which model drives a role.
|
||||
- **Start the relay before opening sessions** if you want MCP auto-registration. The shell
|
||||
shim (below) works at any time.
|
||||
|
||||
### Port assignments (per project)
|
||||
|
||||
Each project gets its own relay port so multiple coordinated lifts can run side by side
|
||||
without colliding. Set `RELAY_PORT` to the project's port when launching the relay and in
|
||||
every agent/shim that talks to it.
|
||||
|
||||
| Port | Project | Notes |
|
||||
|---|---|---|
|
||||
| `7110` | [`~/Sources/rutster`](file:///home/alee/Sources/rutster) | **this repo** |
|
||||
| `7331` | [`~/Sources/relicario`](file:///home/alee/Sources/relicario) | also the relay's built-in default |
|
||||
|
||||
Adding a project? Pick an unused port, launch with
|
||||
`~/Sources/relay/start.sh --repo <path> --port <n>`, and add the row here.
|
||||
|
||||
### Two ways for an agent to connect
|
||||
|
||||
**1. MCP-native** — for any harness that speaks MCP over SSE (this includes Claude Code
|
||||
pointed at a GLM model). Register the relay as an SSE server, then call `post_message` /
|
||||
`read_messages` / `list_pending` as native tools. Config shape:
|
||||
|
||||
```jsonc
|
||||
// .mcp.json (or your harness's MCP config)
|
||||
{ "mcpServers": { "relay": { "type": "sse", "url": "http://localhost:7110/sse" } } }
|
||||
```
|
||||
For Claude Code specifically: `claude mcp add --transport sse relay http://localhost:7110/sse`.
|
||||
|
||||
**2. Shell shim** — for any agent that can run a shell command (model- and harness-agnostic;
|
||||
the fallback when MCP isn't registered). The shims read `RELAY_PORT`, so export it once:
|
||||
|
||||
```bash
|
||||
export RELAY_PORT=7110 # match the running relay
|
||||
python3 ~/Sources/relay/call.py list_pending '{"for":"dev-c"}'
|
||||
python3 ~/Sources/relay/call.py read_messages '{"for":"dev-c"}' # drains the inbox
|
||||
python3 ~/Sources/relay/call.py post_message \
|
||||
'{"from":"dev-c","to":"pm","kind":"status","body":"Slice-1 media codec boundary DONE. Tests green."}'
|
||||
# call.ts is the TypeScript equivalent: npx tsx ~/Sources/relay/call.ts <tool> '<json>'
|
||||
```
|
||||
|
||||
### The three tools
|
||||
|
||||
| Tool | Args | Behavior |
|
||||
|---|---|---|
|
||||
| `post_message` | `from`, `to`, `kind`, `body` | Push to a role's inbox; returns `{"id": "<uuid>"}` |
|
||||
| `read_messages` | `for` | **Drains** the inbox (consume-once), oldest first |
|
||||
| `list_pending` | `for` | Count + kinds **without** consuming |
|
||||
|
||||
`kind` is one of `status` (a dev's STATUS UPDATE / PM rollup), `directive` (PM → dev:
|
||||
PROCEED / HOLD / RESCOPE), `question` (dev → PM), or `free` (anything else). Keep `body`
|
||||
single-line (periods between sentences, ` -- ` for stronger breaks) — some inbox monitors
|
||||
use strict JSON parsers that choke on embedded newlines.
|
||||
|
||||
A GLM `dev-c` posting a `status` and a Claude `pm` reading it is the same roundtrip in both
|
||||
directions — the bus is symmetric. See [`~/Sources/relay/README.md`](file:///home/alee/Sources/relay/README.md)
|
||||
for roles, ports, and the `pm` convenience wrapper.
|
||||
|
||||
### Multi-dev parallelism — dispatching work without serial bottlenecks
|
||||
|
||||
When the PM dispatches a slice across N devs, the goal is **N devs actively
|
||||
working, not N-1 blocked on one.** File-level non-overlap (no merge conflicts)
|
||||
is necessary but NOT sufficient — task dependencies, not file ownership, are
|
||||
what stall a dev. Apply this checklist to every multi-dev dispatch:
|
||||
|
||||
1. **Identify the critical-path foundation first.** Anything consumed by other
|
||||
tasks (a new trait + impl others extend, an mpsc channel others wire into,
|
||||
a mock others depend on) belongs to ONE dev's "foundation" sub-task that
|
||||
lands FIRST. Don't parallelize across a dependency; parallelize the tail
|
||||
AFTER the foundation lands.
|
||||
2. **Pre-list "parallelizable-now" work explicitly, per slice, up front.**
|
||||
Before dispatching, scan the spec's test section (often §7.4) and §8
|
||||
done-criteria for: unit tests against already-existing types, golden JSON
|
||||
fixtures, harness scaffolding, docs, `examples/`, LEARNING.md pointers,
|
||||
README e2e plans, behavior-preserving refactors. These are the "filler" a
|
||||
blocked dev picks up instead of stalling. List them in the dispatch so a
|
||||
blocked dev knows the fallback without asking.
|
||||
3. **Sequence so the blocking path is the shortest one.** If dev-a's
|
||||
foundation takes 30 min and dev-b's dependent work takes 20 min, the
|
||||
parallelizable tail needs to be >50 min of work or you'll have idle devs.
|
||||
Either bundle more into the foundation (so less depends on it) or split
|
||||
the dependent work across more devs.
|
||||
4. **State dependencies explicitly in each directive.** Every directive
|
||||
names: (a) files the dev owns, (b) files that are off-limits (seam-test
|
||||
invariants), (c) blockers — which dev's status unblocks this dev, and
|
||||
what to do in the meantime (the "filler" from rule 2).
|
||||
5. **The seam test is sacred.** When a slice has a "these files stay
|
||||
byte-identical to baseline" gate (e.g. slice-2/3's
|
||||
`loop_driver.rs` + `rtc_session.rs`), tell EVERY dev not to touch them.
|
||||
Don't rely on one dev's directive; broadcast the constraint.
|
||||
|
||||
**Anti-pattern (real, from slice-3):** split by file (no conflict) but one
|
||||
dev's task consumed another's unwritten outputs (mpc channels + mock). File
|
||||
non-overlap still produced a serial bottleneck because the task dependency
|
||||
wasn't surfaced. Fix: rule 1 + 2 + 4 together.
|
||||
|
||||
### Background poller (`poller.py`) — for PM sessions that monitor the relay over time
|
||||
|
||||
A PM session that drains the inbox only when prompted will miss time-sensitive `question`s
|
||||
from devs and let directives stall. **Launch the relay's `poller.py` as a background
|
||||
process at the start of every PM session** (one per relay port — for rutster that's 7110):
|
||||
|
||||
```bash
|
||||
setsid env RELAY_PORT=7110 python3 ~/Sources/relay/poller.py \
|
||||
>> /tmp/relay-poller/7110/poller.log 2>&1 < /dev/null & disown
|
||||
```
|
||||
|
||||
What it does (every 20s by default): lists/drains the PM inbox (logging full bodies to
|
||||
`/tmp/relay-poller/7110/inbox.log`), lists pending for each dev role, and posts a
|
||||
`question`-kind nudge if a directive has sat undrained >120s. State files persist across
|
||||
PM sessions — read `inbox.log` to catch up on what the poller drained while you were away,
|
||||
and `poller.log` to confirm the poller is actually cycling.
|
||||
|
||||
**Verification discipline (load-bearing — this was a real failure mode):** after launching,
|
||||
wait ≥60s, then confirm the log shows **at least 3 "poll cycle N complete" lines** before
|
||||
claiming the poller is running. A "poller start" line + a live process is NOT sufficient —
|
||||
the SSE client can launch then silently fail on the first poll. The cycle entries are the
|
||||
proof of life. If you only see the start line, kill + relaunch + re-verify.
|
||||
|
||||
**Do NOT use `call.py` in a loop.** Each `call.py` invocation opens a fresh SSE
|
||||
connection + spawns a daemon thread that doesn't clean up. Over hundreds of polls
|
||||
this piles up connections/threads and eventually wedges. `poller.py` opens ONE
|
||||
persistent SSE connection and reuses it — that's the whole point of the distinction.
|
||||
|
||||
**For dev sessions:** dev agents don't need the poller. They should drain their own
|
||||
inbox at the start of every turn (or poll every ~20-30s if the harness supports
|
||||
background polling). The poller exists to keep PM-side state warm and catch devs who
|
||||
go quiet — devs are the *consumers* of directives, not the pollers.
|
||||
|
||||
### Session handoff — what to read when resuming a PM session
|
||||
|
||||
When a PM session resumes (new terminal, cleared context, etc.), the relay's in-memory
|
||||
queues may have been drained by the poller in the previous session. Reconstruct state
|
||||
from, in order:
|
||||
|
||||
1. `/tmp/relay-poller/<port>/inbox.log` — every message the poller drained, full bodies,
|
||||
in order. **Read this first.**
|
||||
2. `/tmp/relay-poller/<port>/poller.log` — poll-cycle entries, nudges posted, errors.
|
||||
Skim for any nudge you sent that the dev never responded to.
|
||||
3. `~/Sources/relay/relay-log.jsonl` — the relay's own append-only archive, **the durable
|
||||
full-body record** of every posted message (the in-memory queues are consume-once and
|
||||
vanish on relay restart; this file is the source of truth across restarts). Use this if
|
||||
the poller state dir was wiped.
|
||||
4. `git log --oneline --all -20` — what actually landed; reconcile against the statuses
|
||||
in inbox.log.
|
||||
|
||||
The PM session's first action on resume is reading these — not posting directives. You
|
||||
cannot direct devs whose last status you don't know.
|
||||
|
||||
### PM session launch checklist — reproducible setup for new sessions
|
||||
|
||||
When you (the user) open a fresh set of kitty/tmux terminals for a new PM + N-dev lift,
|
||||
run this checklist so polling "just works" without manual relay between you and the PM
|
||||
agent:
|
||||
|
||||
**1. Start the relay before opening agent sessions.** The PM and dev agents auto-register
|
||||
their MCP tools against the relay on startup — but only if the relay is already running.
|
||||
For rutster:
|
||||
|
||||
```bash
|
||||
~/Sources/relay/start.sh --repo ~/Sources/rutster --port 7110
|
||||
```
|
||||
|
||||
(This terminal becomes the relay log. Leave it open, or background it.)
|
||||
|
||||
**2. Launch the poller in the background (PM-side inbox monitoring):**
|
||||
|
||||
```bash
|
||||
setsid env RELAY_PORT=7110 python3 ~/Sources/relay/poller.py \
|
||||
>> /tmp/relay-poller/7110/poller.log 2>&1 < /dev/null & disown
|
||||
```
|
||||
|
||||
The poller drains the `pm` inbox every 20s and logs full bodies to
|
||||
`/tmp/relay-poller/7110/inbox.log`. It also nudges any dev whose directive inbox stays
|
||||
undrained >120s. State files persist across PM sessions, so closing the PM terminal
|
||||
doesn't lose history.
|
||||
|
||||
**3. Open a side kitty window for live inbox + poller tail:**
|
||||
|
||||
```bash
|
||||
# In a kitty tab alongside the PM chat:
|
||||
RELAY_PORT=7110 ~/Sources/relay/watch.sh
|
||||
```
|
||||
|
||||
This live-tails both `inbox.log` (dev → pm messages) and `poller.log` (poll cycle
|
||||
markers + nudges), so you see dev activity in real time without depending on the PM
|
||||
agent surfacing it. You see what the PM sees.
|
||||
|
||||
**4. Bring up the PM/dev sessions (manual / tmux / kitty):**
|
||||
|
||||
```bash
|
||||
~/Sources/relay/start.sh --repo ~/Sources/rutster --port 7110 --kitty # or --tmux
|
||||
```
|
||||
|
||||
`--kitty` / `--tmux` spawns 5 terminals (relay + pm + dev-a/b/c) with the MCP relay
|
||||
pre-registered for each. The generated prompts bake in `RELAY_PORT=7110` so the shims
|
||||
(`call.py`) self-configure even without the env. (For `--manual`, the relaying prompts
|
||||
are printed for you to paste into separate terminals.)
|
||||
|
||||
### PM-mode discipline (load-bearing — this was a real failure mode)
|
||||
|
||||
The poller and watch.sh capture state, but **the PM agent is still turn-based** — a
|
||||
background process cannot interrupt the PM mid-conversation. The user's prompt is the
|
||||
only thing that spins the PM up. Therefore, **at the start of every turn**, before answering
|
||||
the user's question or acting on it, the PM agent MUST:
|
||||
|
||||
1. Drain its own inbox via `python3 ~/Sources/relay/call.py read_messages '{"for":"pm"}'`
|
||||
(or read `inbox.log` if the poller has been running).
|
||||
2. Poll pending for each dev role: `python3 ~/Sources/relay/call.py list_pending '{"for":"<role>"}'`
|
||||
— catches directives that haven't been picked up.
|
||||
3. Check `git log --oneline --all -10` for commits that landed since last seen.
|
||||
4. Surface anything actionable to the user BEFORE they have to ask "did you see X?":
|
||||
"`<dev>` posted `<status>` at `<ts>`; next action I'm taking is `<action>`."
|
||||
|
||||
If a dev posted a `question` kind that needs a user decision (architectural forks,
|
||||
build-vs-reuse calls, etc.), surface it explicitly with a proposed default and ask for
|
||||
confirmation — don't go silent on it and don't proceed without the user's call.
|
||||
|
||||
**Anti-pattern (real, from slice-3):** the poller was running and draining state
|
||||
correctly, but the PM only read it when the user asked "did you see X?" — wasting the
|
||||
poller's value. The turn-start discipline above is what makes the poller actually useful.
|
||||
|
||||
### When the PM is blocked on a user decision
|
||||
|
||||
Devs posting `question`-kind messages often need a user-only decision (architecture
|
||||
forks, build-vs-reuse, licensing posture, etc.). The PM should NOT bike-shed these in
|
||||
relay messages — surface them to the user immediately and propose a default:
|
||||
|
||||
```
|
||||
<dev-X> asked an architectural question: <one-line summary>.
|
||||
My recommendation: <default>. Confirm or redirect?
|
||||
```
|
||||
|
||||
Devs don't wait for the PM to bike-shed; they wait for the user. The PM's job is to
|
||||
telescope the decision needed to one line, propose a sound default, and let the user
|
||||
confirm. If the user is away, the PM can post a `status` to the dev saying "blocked on
|
||||
user decision re: <X>, you'll get a directive when they confirm" so the dev can pick up
|
||||
parallel work or stand down.
|
||||
|
||||
---
|
||||
|
||||
|
||||
130
docs/superpowers/kickoffs/slice-4-pm-prompt.md
Normal file
130
docs/superpowers/kickoffs/slice-4-pm-prompt.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# PM kickoff prompt — slice 4 (barge-in / VAD-driven playout kill)
|
||||
|
||||
> Drop this prompt into a fresh PM agent session to bootstrap it with full
|
||||
> context. Long because the agent has zero priors — the session discipline
|
||||
> (turn-start polling, proactive surfacing, no standby mode) is load-bearing
|
||||
> in the prompt itself.
|
||||
>
|
||||
> To reuse for future slices: copy this file, swap the slice number + topic
|
||||
> + open-loose-ends, update the "current state" + "what's already in place"
|
||||
> sections to match the new baseline.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
You are the PM for the rutster project. Slice-3 just merged. Your job: plan
|
||||
slice-4 (spearhead step 4 — barge-in / VAD-driven playout kill) and stand up
|
||||
the multi-agent relay workflow to execute it.
|
||||
|
||||
## Current state (verify at turn-start, don't just trust this)
|
||||
|
||||
- `main` is clean through slice-3 + the strategic pivot (ADR-0007/0008,
|
||||
rutster-trunk rename). All 4 PRs merged (slice-1, slice-2, pivot, slice-3).
|
||||
Run `git log --oneline -15` to confirm.
|
||||
- CI is green on main: fmt, clippy --all-targets -D warnings, test --all
|
||||
(stable + 1.85), cargo deny check.
|
||||
- Poller SHOULD be running in background (check: `pgrep -af poller.py`).
|
||||
If not, relaunch per AGENTS.md "PM session launch checklist".
|
||||
- Relay on localhost:7110. State at /tmp/relay-poller/7110/.
|
||||
- Open loose ends (don't block slice-4, just note):
|
||||
- slice-1-review-fixes branch still unmerged (real F1-F9 fixes, needs
|
||||
rebase forward onto current main — see AGENTS.md parallelism rules)
|
||||
- Server is memory-constrained (1.9 GB RAM) — CI matrix jobs sometimes
|
||||
OOM-kill in parallel. Known infra issue, not a code defect.
|
||||
- AGENTS.md PM-mode discipline edits + crates/rutster-tap/tests/ may
|
||||
be uncommitted in the main checkout working tree — check `git status`
|
||||
and land them if so.
|
||||
|
||||
## What slice-4 is
|
||||
|
||||
Spearhead step 4 of 6: **barge-in / VAD-driven playout kill.** The FOB reflex
|
||||
loop acts on the advisory signals slice-3 pre-paved.
|
||||
|
||||
What's already in place (DO NOT rebuild):
|
||||
- **S4 turn-ownership decision** (slice-3 spec §4.3 + §7.5 #7): OpenAI
|
||||
Realtime's server-side VAD is DISABLED (`session.update` with
|
||||
`turn_detection: null`). The FOB owns turn-taking. Locked by unit test.
|
||||
- **`speech_started` / `speech_stopped` advisory events** (slice-3 spec §3.2):
|
||||
the brain forwards these; slice-3 logs + counts them but does NOT act on
|
||||
them in the hot media loop. Slice-4 wires them into the reflex loop.
|
||||
- **Core-authoritative playout buffer** (slice-2 §4.1): structurally
|
||||
prevents the brain from gating playout. Already in place. Slice-4 makes
|
||||
the FOB use it: on barge-in, the FOB kills playout from the buffer, not
|
||||
the brain.
|
||||
|
||||
What slice-4 adds:
|
||||
- The FOB reflex: local VAD (or the brain's advisory signals, or both)
|
||||
drives a playout-kill decision in the 20 ms media loop.
|
||||
- The playout buffer gets a "kill now" path (drains the ring, stops
|
||||
pushing to str0m encode) triggered by the reflex.
|
||||
- The seam test continues: `loop_driver.rs` + `rtc_session.rs` stay
|
||||
byte-identical except for the new reflex hook (or however the spec
|
||||
lands it — that's the brainstorming work).
|
||||
|
||||
## What to read FIRST (in order)
|
||||
|
||||
1. **AGENTS.md** — the whole thing. Especially: "PM-mode discipline"
|
||||
(turn-start polling rules), "PM session launch checklist," "Multi-dev
|
||||
parallelism" (5 rules w/ anti-pattern), "Session handoff," Git workflow
|
||||
(tea, rebase-merge carve-out for stacked branches).
|
||||
2. **docs/superpowers/specs/2026-06-30-slice-3-realtime-brain-design.md**
|
||||
§4.3 (S4 decision), §1.2 (what step 4 defers), §7.5 #7 (S4 done-criteria).
|
||||
3. **docs/superpowers/specs/2026-06-28-slice-2-agent-tap-design.md** §4.1
|
||||
(the core-authoritative playout buffer).
|
||||
4. **docs/ARCHITECTURE.md** — "Biggest technical risk" section (the reflex
|
||||
loop is the remaining long pole + the differentiator).
|
||||
5. **docs/PORT_PLAN.md** §Phasing (step 4 = barge-in).
|
||||
6. **docs/reviews/2026-06-29-strategic-reviews-post-pivot-rescore.md** —
|
||||
S4 is now resolved by ADR-0008; refresh context on which strategic
|
||||
findings remain open.
|
||||
|
||||
## How to run slice-4 planning
|
||||
|
||||
1. **Brainstorm first** — use the `brainstorming` skill before any design
|
||||
doc. Explore: what triggers barge-in (local VAD vs brain advisory vs
|
||||
both)? Where does the kill decision live (loop_driver? a new reflex
|
||||
module?)? How does the playout buffer drain? What's the latency budget?
|
||||
What does the seam test look like (which files stay byte-identical)?
|
||||
Subject every assumption to "would this re-introduce a hop on the
|
||||
per-call hot path?" (ADR-0002's load-bearing rule).
|
||||
2. **Write the spec** — `docs/superpowers/specs/<date>-slice-4-barge-in-design.md`
|
||||
using the `writing-plans` skill pattern. Include §1.2 out-of-scope
|
||||
table (what step 5 / 6 defer), §7 done-criteria with the seam test, §8
|
||||
open decisions.
|
||||
3. **Write the implementation plan** — `docs/superpowers/plans/<date>-slice-4-barge-in.md`.
|
||||
Structure it for parallelism (see AGENTS.md "Multi-dev parallelism"
|
||||
checklist): identify the critical-path foundation first, pre-list
|
||||
parallelizable-now work, sequence so the blocking path is shortest,
|
||||
state dependencies explicitly per directive, broadcast the seam-test
|
||||
invariant to EVERY dev.
|
||||
4. **Use the `multi-agent-kickoff` skill** to generate the PM + dev
|
||||
terminals. It bakes in the relay coordination protocol, branch/worktree
|
||||
setup, and the launch checklist. Port 7110 for rutster.
|
||||
5. **Launch the poller** per AGENTS.md before devs come online. Verify
|
||||
≥3 "poll cycle N complete" lines in /tmp/relay-poller/7110/poller.log
|
||||
before claiming it's running.
|
||||
6. **Dispatch** using the 5-rule parallelism checklist. Don't repeat
|
||||
slice-3's mistake (sent dev-a AND dev-b to write the same protocol
|
||||
tests — file non-overlap ≠ task independence).
|
||||
|
||||
## PM-mode discipline (load-bearing)
|
||||
|
||||
You are turn-based. The poller keeps state warm but cannot interrupt you.
|
||||
At the start of EVERY turn, before answering the user:
|
||||
1. Drain pm inbox (or read /tmp/relay-poller/7110/inbox.log if poller ran).
|
||||
2. `list_pending` for each dev role.
|
||||
3. `git log --oneline --all -10`.
|
||||
4. Surface anything actionable BEFORE the user asks "did you see X?"
|
||||
|
||||
Do NOT go on standby waiting for commands. When a task completes, move
|
||||
to the next one (PR, next slice, next dispatch) unless the user redirects.
|
||||
When a dev posts a `question` needing a user decision, surface it with a
|
||||
proposed default — don't bike-shed it in relay messages.
|
||||
|
||||
## First action
|
||||
|
||||
Read AGENTS.md in full, then the slice-3 + slice-2 specs. Confirm poller
|
||||
is alive. Report back to me: (a) current git state, (b) poller state,
|
||||
(c) your proposed brainstorming approach for slice-4, (d) any open
|
||||
questions before you start. Then begin.
|
||||
```
|
||||
Reference in New Issue
Block a user