Archived — Superseded — it still calls the per-room cast “planned” and the panel turn “not streamed”, and it diagrams the frozen AI↔AI (exp-010) pipeline. The live architecture is the function map. Kept for provenance; no longer maintained. See the function map for current docs.
Topology — how the browser and the local backend fit together
megaprompt only, for now. The live panel is built on the single-model engine — more efficient, and far easier to change the format, the cast size, or the depth of the deliberation. The python (isolated) engine + self-election bids remain the project's batch research thesis; they're deferred here.
A local Python server (lib/run_room.py — FastAPI on localhost; it can't live on Cloudflare Pages, it's a stateful process holding live conversations). A RoomManager holds many independent rooms; each is one running megaprompt context with its own memory, persisted to rooms/<id>/ and resumed on restart. Per turn it assembles the prompt, makes one non-streaming API call, parses the output into the confer + the replies, and returns JSON — the browser animates the egg-hatch client-side (it is not streamed). Freezing a room writes the same artefacts the batch schemes emit, so viewer, index, and audit are untouched.
One human turn, step by step
Two visible layers — there's no private <think>; the one model stages everything. Confer (the panel's internal back-and-forth → side drawer) → respond (one message per host → main chat). The whole turn comes back as one JSON reply; the browser reveals it with the egg-hatch.
The human types (optionally @-addressing a host). The server appends their message verbatim to that room's running transcript — no wrapper, the dumb-pipe rule — and logs a guest speak event. @addressed → the model answers as that one host, confer skipped. Otherwise:
megaprompt · confer, then respond
The single model, holding the whole cast, writes the internal deliberation — the hosts reacting to each other, a short back-and-forth (at most 4 turns per host, no fixed rounds).
It settles a relevance-led order in that confer (the host the turn most implicates leads), then writes one spoken reply per host — lead in full, a distinct point added, a bare concur where someone would only agree.
The response parser splits the raw output: <speak> inside <confer> → the side drawer; <speak> after it → the main chat.
The server returns the whole turn as one JSON reply; the browser reveals it with the egg-hatch (a confer capsule + one bubble per host). Not streamed.
Floor returns to the human. A host can hold — say nothing this turn — so it never forces a flat chorus.
Why megaprompt for this: one model staging the confer + responses makes it trivial to change the format, add or drop a character, or dial the depth of the deliberation — all prompt edits, no routing or per-context plumbing.
Adding / removing a voice — the per-room-cast port
Planned, not yet in the running app. Today every room runs a fixed 2-host cast (Li · Doronin) from a global ROSTER. The next step makes the cast per-room: chosen at creation, add/retire mid-chat. Two engine decisions are still open (below).
A chat starts from a picker (POST /api/rooms { cast }); build_system_blocks(cast) builds that room's cached system prefix. The user can add or retire hosts live — changes land at the next turn boundary, never mid-volley, and are shaped to respect the cache.
cast changes, cache-aware
Add → the joiner is omniscient (the one model already holds the thread); it greets in one line, caught up. Open decision:append the new profile to the tail so only the new tail is a cache write (cheap join), vs. rebuild the whole materials block (simpler, but a full cache write). Today's single cache breakpoint forces the rebuild — cheap joins need per-profile breakpoints.
Retire → keep ≥1. Open decision: leave their materials dormant + append "stop voicing X" (preserves the prefix, cheap reads), vs. rebuild the smaller prefix (a cache write next turn). The current mock shows the rebuild path.
Logged as join / leave events; the log generalizes charA/charB → participants[].
confer / deliberation — the back-and-forth among the hosts, logged as first-class confer events: how each turn's responses were formed. Shown in the slide-out drawer, never in the main chat.
relevance-led order — the host the turn most implicates leads; the others react to the delivered line (not the backstage draft), so going first actually matters.
@-address — the override: skips the confer and answers as the one named host.
per-turn cost — every turn records its tokens + API price as a cost on the coordinator event (the dear cache-write on turn 1, cheap reads after); shown on the turn's boundary in the chat, totalled per chat.
keep-confer — the model's raw output (incl. <confer>) is stored verbatim in the room's history, so the hosts remember how they reasoned across turns.
local-only backend — the server is a researcher tool on localhost; only a frozen session is committed and published to the CF-Pages viewer.