Plan · Code Raven · 2 September 2026

The Rookery

Nineteen named seats in the Personal workspace, with non-overlapping lexicons, a summoning grammar, enforced room order and standing tensions, and a meeting format that ends in a stated disagreement rather than a recommendation.

19Seats
55Tasks
9Phases
12Standing tensions
The gist

Three things have to be built. A cohort mechanism so nineteen personal seats do not land in every code project's expert catalog. A seat model carrying the structured fields the roster depends on — room order, standing tensions, length ceilings, fails-by — because those are enforcement mechanics rather than prose. And a Rookery meeting format that lifts the four-agent cap, skips the handoff step, and concludes with the disagreement instead of a synthesis.

The problem

Code Raven's meetings exist to produce work. ConclusionStep runs handoff first, then summary, then chronicle. MeetingSummaryResult carries summary, keyInsights and actionItems. The whole apparatus converts a conversation into something you can do.

The Rookery is designed to do the opposite. "No seat closes a question." "A session ends with the disagreement stated sharply, not resolved." "Never a recommendation." "No host summary, no synthesis paragraph, no 'in short.'" Run the roster through the existing conclusion pipeline and the machinery fights it every session — generating action items the roster forbids and a synthesis the roster names as failure.

Three concrete blockers on top of that: StandupMeeting.init enforces 2...4 agents while Bench: wants 3–5 and Full bench: wants more; AgentDefinition has no field for register, terms, room order or fails-by; and AgentCatalog.allAgents is a flat bundled list handed to every project.

Approach

Cohorts, so Personal seats stay in Personal

AgentDefinition gains cohort, defaulting to .core, with .rookery as the second case. Every catalog surface filters by the active project's kind. Nineteen seats appearing in Press Raven's expert list would be the same failure shape as the blueprint vocabulary leak, and this is the general mechanism that prevents it for any future set.

A seat model beside the agent model, not inside it

RookerySeat carries what the roster actually specifies — owns, refuses, opensWith, register, terms, roomOrder, maxWords, failsBy. The prompt file carries voice; the model carries the mechanics that get enforced in code. Splitting them is what lets room order and standing tensions be real rather than advisory.

Enforce what erodes, prompt what doesn't

The roster's own thesis is that uniform output means the bench has collapsed. Room order becomes a sort. Standing tensions become a pair table that injects a mandatory-disagreement directive. Length ceilings become maxWords. Presets become a picker. Register, Terms and Tell stay in the prompt, where they belong.

Conclusion produces a disagreement, not a summary

MeetingSummaryResult already carries dissenting: [String]. The Rookery conclusion fills that, keeps summary short and neutral, and leaves keyInsights and actionItems empty. No handoff step runs.

Decisions made for you

Judgment call

The nineteen seats are bundled, not authored through Craft Expert

That builder is designed for interviewing one expert into existence. Nineteen seats already fully specified in the roster should be written directly as prompt files plus catalog entries plus agents.yaml rows in the Personal workspace (not this repo's), following the same wiring the Craft Expert checklist describes. A seat can still be edited afterwards through prompt customization.

Judgment call

Full bench is capped at nine

"Everyone with standing" is the roster's language, but each agent holds its own CLI session and this codebase has a documented failure where agent runs wedge in an uninterruptible IPC wait. Nine feels full and is recoverable. One constant to change.

Judgment call

The roster file moves into the repo

It currently sits untracked at the repo root. It belongs at docs/rookery/roster.md as the source of truth, with the per-seat prompts generated beside it.

Judgment call

Rookery output never reaches the editorial triage queue

These seats produce judgment about a kitchen renovation, not findings with a file:line anchor. They surface in Personal and in the meeting record only.

The work

Phase 1 — Cohort scoping

4 tasksNineteen personal seats must not reach any code project.
  • Add an AgentCohort enum with core and rookery cases to AgentDefinition
  • Default every existing AgentDefinition to the core cohort
  • Filter the agent catalog by cohort so rookery seats appear only in Personal
  • Verify no rookery seat appears in another project's expert list

Phase 2 — The seat model

5 tasksThe mechanics the roster depends on, as data.
  • Add the RookerySeat model with roomOrder, maxWords, failsBy and the roster fields
  • Add the standing-tensions table as seat-id pairs with an axis label
  • Add the presets table mapping a question shape to a seat list
  • Move rookery-roster.md to docs/rookery/roster.md as the tracked source of truth
  • Build RookerySeatCatalog holding all nineteen seats as structured data

Phase 3 — The nineteen prompts

8 tasksWrite in batches. Uniformity here is the failure mode.
  • Write the five People and Institutions seat prompts
  • Write the four Time, Money and Direction seat prompts
  • Write the three Body, Mind and Memory seat prompts
  • Write the three Place and Form seat prompts
  • Write the four procedural seat prompts
  • Register all nineteen in AgentCatalog with the rookery cohort
  • Install the nineteen seats into the Personal workspace agents.yaml and prompts directory
  • Cross-check every prompt for vocabulary borrowed from another seat

Phase 4 — The Rookery meeting format

8 tasksWhere the roster and the existing pipeline diverge.
  • Add a rookery case to MeetingFormat
  • Lift the 2...4 agent validation for rookery meetings and cap the bench at nine
  • Sort speaking order by roomOrder with Devil's Advocate always last
  • Inject a mandatory-disagreement directive when both poles of a tension are present
  • Enforce each seat's maxWords ceiling in its turn directive
  • Skip the handoff conclusion step entirely for rookery meetings
  • Conclude with a disagreement block that fills dissenting and leaves actionItems empty
  • Keep rookery findings out of the editorial triage queue

Phase 5 — Summoning and stances

7 tasks
  • Build RookeryCommandParser covering seat, Bench, Full bench, Route and Drift check
  • Support +Empty Chair with a named subject bound per invocation
  • Implement Route as a Mira reply that names the room without convening it
  • Implement Drift check as a self-audit pass against each seat's failsBy line
  • Never let the Oblique Strategist and the Devil's Advocate sit in the same session
  • Add the Rookery convene sheet as the Personal-only entry point in the Meetings tab
  • Accept an optional pursuitId so a convened room can be told what it is about

Phase 6 — Probation and verification

3 tasks
  • Track per-seat session counts so the Ethicist's probation can be reviewed
  • Surface a probation prompt once the Ethicist has sat in ten sessions
  • Build the macOS target and verify the product with scripts/verify-build-product.sh

Phase 7 — The room

5 tasksFrom the first review: the Rookery becomes the inline core of Personal's Meetings tab.
  • Make the Rookery the inline core of Personal's Meetings tab with the developer experts collapsed beneath it
  • Replace the grammar chips with a who-sits choice: I choose, the host chooses, everyone with standing, ask only
  • Add a seating chart so the chair can choose seats by hand, with tensions and the cap shown at the table
  • Demote presets to a menu that fills the question and pre-seats the room
  • Attach files, records and pasted images to a Rookery session

Phase 8 — The record

3 tasksSecond review: the ending must be actionable. Seats still never recommend; the record distills.
  • Replace the disagreement-only conclusion with a five-part record: agreement, recommendations, ideas, cautions, the disagreement
  • Add a cautions field to the meeting summary model with defensive decoding for stored meetings
  • Relabel the transcript view, summary editor and copied notes for a Rookery record

Phase 9 — Mira as counsel

6 tasksThird review: synthesis needs a subjective voice with the whole table in view.
  • Seat Mira as the Rookery's lead on the Meeting Lead machinery with her own voice and color
  • Keep a living brief through the sitting via the document protocol, organized by the object being designed
  • Give Mira three speaking rights: unanswered openers, two versions of one thing, the chair's direction
  • Enable the chair's directives in a sitting: advance, where things stand, recommendations so far, assign work
  • Write Mira's closing brief above the clerk's record and into Chronicle
  • Add a Rewrite Record & Brief action so a concluded sitting can be re-run

Manual Testing

6 tasksYours — whether the bench sounds like nineteen people is not a thing a build can check.
  • Convene a bench on a real question and confirm the seats sound like different peopleyou
  • Confirm two seats in a standing tension actually disagree by nameyou
  • Confirm The Eye stays under sixty words and the Oblique Strategist says one sentenceyou
  • Confirm a session ends with a disagreement and produces no action itemsyou
  • Confirm none of the nineteen appear in Code Raven's own expert listyou
  • Rewrite the SAT detective sitting and judge whether Mira's brief organizes the games and their optionsyou

Risks & edge cases

The main risk

Nineteen prompts written in one pass will drift toward each other

This is the roster's own named failure: "if every seat is producing the same 80 words, you have failed." A single generation session converges on a house voice. Write them in the five thematic batches, restate the anti-collapse rules at the head of each, and treat the cross-check as real work. Read three prompts side by side before calling the phase done.

Load

Nine concurrent agent sessions is past anything tested

Each agent holds its own CLI session, and there is a documented failure where runs wedge in mach_msg2_trap and survive kill -9. Run seats sequentially with the existing pacing delays, and treat the first nine-seat session as a load test.

Subtle

The disagreement block is generated, and generation smooths

Asking a model to state where seats split tends to produce a balanced both-sides paragraph — the synthesis the roster forbids, wearing a different hat. The conclusion prompt must name that trap and require the block to quote seats rather than paraphrase them.

Known flattening

Room order is a partial order, not a total one

The roster gives positions like "early," "quiet then reframes once," and "interrupts." An integer sort flattens that, and the Empty Chair in particular is specified to interrupt, which no ordering expresses. Accept the flattening and let the Empty Chair be inserted at a caller-chosen point.

Wiring gap

Nothing connects a bench to a pursuit yet

Personal experts finally have an anchor now that Pursuits shipped, but the wiring does not exist. A rookery meeting should accept an optional pursuitId so the room can be told what it is about.

Out of scope

Final review

The strongest part of this plan is that it takes the roster seriously as an engineering document rather than a prompt. Room order, standing tensions and length ceilings become code, which is the only way they survive contact with a model that wants to be helpful and even-handed.

The weakest part is unavoidable: whether nineteen seats actually sound like nineteen people cannot be verified by a build. The cross-check task and the manual testing section carry that weight, and the prompts are where the quality of this whole feature lives.

If one thing gets cut for time, cut Phase 6. Probation tracking is charming and it is the least load-bearing thing here.

79/100

High on the architecture — the cohort split, the seat model and the diverging meeting format each address a specific blocker in existing code, and the roster is unusually complete as a source document. Held down by two things: the nine-seat load is past anything the meeting service has been exercised at, and the nineteen prompts are the kind of work that looks finished while being subtly homogenous.