Classified · Production OS

Red Rabbit
Production OS

A canonical source of truth for an alternate-history espionage franchise — screenplay extraction, relationship mapping, writer management, and a web CMS, with every canon mutation flowing through a reviewable PR.

Status · v1.1 ontology · episode authoring · script extraction live
Repo · github.com/Blue-Crest-Pictures/operation_red_rabbit
Hosted MCP · operation-red-rabbit-cms.vercel.app

§ 01Mission

A creator builds the Red Rabbit universe. An infrastructure engineer builds the production OS that lets them do it without ever touching a terminal, a JSON file, or a schema definition. Constitution Principle II is load-bearing: creative users live behind a writer-friendly surface; engineering ugliness stays on the engineering side of the boundary.

The system is opinionated about how canon evolves: AI proposes, humans dispose. Every mutation — a new character, an edited story arc, a role grant — opens a pull request against the canon repo. Merges are explicit. Rollback is a single revert.

P · I

Canon is the source of truth

Every agent and product derives from a single, versioned canon. Deprecated ideas are archived, not deleted.

P · II

Writer UX is non-negotiable

Zero terminal, zero JSON, zero schema. Engineering ugliness lives behind a writer-friendly surface.

P · III

Grounded realism over confident recall

Real-world claims must trace to a retrieval source. Ungrounded "training data advice" is a failure mode.

P · IV

Human-in-the-loop on consequential acts

Major canon changes, access grants, outreach sends, and schedule commits all require explicit confirmation.

P · V

Ship lightest viable first

Commoditized backends (Drive, Obsidian, Claude Desktop) before custom code. Every spec must justify deviation.

§ 02Architecture

The system has two write surfaces and two MCP transports, all terminating in a single canon-core write engine. The architecture is symmetric on purpose: contract drift between advertisement and enforcement is impossible by construction.

flowchart TB
  subgraph mike["Mike's Mac"]
    desktop["Claude Desktop"]
    stdio["stdio MCP server
packages/mcp-server"] desktop -->|local Node| stdio end subgraph browser["Browser (Mike or Justin)"] cms_form["CMS form harness
/canon/[type]/new + /edit
/admin/writers"] end subgraph vercel["Vercel — operation-red-rabbit-cms"] cms_app["Next.js CMS
apps/cms"] api_propose["/api/canon/propose-change
Pages Router"] server_action["proposeChangeAction
Server Action"] hosted_mcp["Hosted MCP
/api/mcp
OAuth + bearer"] kv[("Upstash KV
roles · audit · rate-limit · sessions")] cms_app -.-> api_propose cms_app -.-> server_action api_propose --> kv hosted_mcp --> kv end subgraph engine["Canon engine — packages/"] schema["@redrabbit/schema
zod + .describe()"] canon_core["@redrabbit/canon-core
proposeChange + find_conflicts"] mcp_server["@redrabbit/mcp-server
tools + RBAC + roles cache"] indexer["@redrabbit/index
SQLite mirror"] schema --> canon_core schema --> mcp_server canon_core --> mcp_server end subgraph github["GitHub"] canon_repo[("operation_red_rabbit
canon/ + .mcp/roles.yml")] gh_app["GitHub App
write credential"] end cms_form -->|HTTPS · cookie + CSRF| api_propose cms_form -.->|RSC form action| server_action desktop -.->|claude.ai web| hosted_mcp stdio --> mcp_server hosted_mcp --> mcp_server api_propose --> canon_core server_action --> canon_core canon_core -->|Octokit + GH App| gh_app gh_app -->|writes branch + PR| canon_repo canon_repo -->|reads .md| canon_core canon_repo -->|nightly index| indexer indexer -.->|local lookups| mcp_server classDef writer fill:#1e1a17,stroke:#c14a36,color:#f4ebd9 classDef cloud fill:#1c1815,stroke:#8a847a,color:#f4ebd9 classDef code fill:#1a1817,stroke:#d6cdb8,color:#f4ebd9 classDef store fill:#1a1614,stroke:#c14a36,color:#f4ebd9 class mike,browser writer class vercel cloud class engine code class github store

Two write surfaces, one engine

Both /api/canon/propose-change (Pages Router, called from the form harness) and proposeChangeAction (App Router Server Action) compose the same proposeChange() in @redrabbit/canon-core. They differ in caller fit:

Two MCP transports, one server package

The NEW_V1_1_ENTITY_TYPES Set in packages/mcp-server/src/tools/write.ts is the single source of truth for which entity types are blocked from chat-based writes. Both transports inherit; server_info advertises the same Set so the contract cannot drift from runtime enforcement.

Standing automation

Two always-on systems run without human intervention between canon edits and PR merge.

Structural conflict detection — every proposed canon change runs findStructuralConflicts() in @redrabbit/canon-core before the PR is openable. Six check categories:

Both the hosted MCP and the CMS Server Action invoke the same engine — what chat warns about and what the form warns about cannot diverge.

60-second canon pulse — a Vercel cron polls the canon repo's HEAD SHA every minute. On mismatch it increments a KV generation counter. All relationship-map clients key cache reads to mcp:relmap:g<N> — the moment a PR merges, the next cron tick invalidates the stale map and forces a fresh compute on the following request. Sub-90-second freshness with no webhook surface.

§ 03Pipeline

Specs land before code lands. The pipeline is six stages from intent to merged PR, with explicit review gates between each. Artifacts persist at docs/specs/<feature>/{spec,review,plan,check}.md.

flowchart LR
  spec["/spec
Q&A → spec.md"] --> review["/spec-review
6 PRD agents → review.md"] review --> plan["/plan
6 design agents → plan.md"] plan --> check["/check
5 plan reviewers → check.md"] check --> build["/build
parallel agents
wave-based execution"] build --> codereview["/code-review
5 Sonnet + Codex
→ PR comment"] classDef stage fill:#1e1a17,stroke:#c14a36,color:#f4ebd9 class spec,review,plan,check,build,codereview stage

§ 04Status

LayerStateReference
Canon ontology v1.1ShippedPRs #22 – #25
MCP-on-Vercel — Phase A + BShippedPRs #4 – #21
Writer-management — Phase 1ShippedPR #27
Canon relationship mapShippedPR #33
Episode / feature authoringShippedPR #35 + main
Script extraction + MCP setup pageShippedmain
Canon ontology v1.2 (required-flip)Gated≥ 80 % authoring threshold

§ 05IP boundary

The repository is a single tree with two ownership boundaries. Toolkit code is portable consultant IP; canon content is the creator's IP under all rights reserved.

Toolkit · MIT

Reusable infrastructure toolkit, with extract-to-separate-repo rights.

  • packages/
  • apps/

Canon · All Rights Reserved

Creator's creative IP. Stays with the creator if the toolkit is ever extracted.

  • canon/
  • inbox/
  • tests/fixtures/
  • cms-config.yml

§ 06Stack

operation_red_rabbit/
├── packages/                   Toolkit (MIT)
│   ├── schema/                 zod entity schemas + .describe() registry
│   ├── canon-core/             octokit-backed read/write + find_conflicts
│   ├── mcp-server/             MCP SDK transport + hosted-server.ts + KV cache
│   ├── index/                  SQLite indexer + ALL_ENTITY_TYPES + edge classes
│   ├── extractor/              AI script-extraction (Anthropic-backed)
│   ├── fountain/               Fountain-format script parser
│   ├── actions/                GitHub Actions integrations
│   ├── pr-body/                PR humanizer (one title per entity type)
│   ├── demo/                   Stub canon for tests + dev
│   └── testing/                Shared vitest helpers
├── apps/
│   ├── cms/                    Next.js 14 — CMS + hosted MCP route
│   └── cli/                    Local dev CLIs
├── canon/                      Mike's IP — markdown one-file-per-entity
├── docs/specs/                 Pipeline artifacts per feature
└── docs/runbooks/              Operational procedures

§ 07References