Skip to content

Multi-Agent Operating Model (Claude Code + Codex)

Status: Active Last reviewed: 2026-06-30

TwoMore is worked by two agent systems — Claude Code (planning / orchestration / verification) and Codex (frontier implementation editor). This doc is the contract that keeps them reading the same rules and prevents the two instruction systems from drifting apart. If this conflicts with AGENTS.md, AGENTS.md wins.

Why two agents

  • Claude Code — plans, designs, reviews, verifies, commits, and runs the OTA flow. Auto-loads CLAUDE.md + AGENTS.md every turn.
  • Codex (codex MCP server, registered user-scope; or codex exec via shell) — a frontier implementation model used as the editor for hard, self-contained, logic-heavy work, and as a second-model reviewer for risky surfaces. Auto-loads AGENTS.md only (capped by project_doc_max_bytes).

Model diversity is the prize: a different model catches different things and shoulders implementation load when Claude is rate-limited. The risk is drift — the two systems silently diverging on the rules. The three layers below exist to prevent that.

The three instruction layers

LayerBytes / budgetClaude readsCodex readsHolds
AGENTS.md≤ 28,672 (lint-enforced)referencedyes, nativelyHard, mechanically-enforced constraints (the ID | Rule | enforcement tables)
CLAUDE.mdthin (orchestration core)yes, auto every turnnoHow-I-Work, workflow, delegation, terminology, compaction invariants, + a pointer index to canon
docs/canon/*on-demandvia Read / doc-routervia injected task specThe soft canon (design + implementation conventions) — single source, loaded only when relevant

The rule that prevents drift: every rule lives in exactly one layer.

  • A mechanically-enforceable hard constraint → AGENTS.md (both agents auto-load it).
  • A soft convention (design judgment, IA, naming, patterns) → docs/canon/* (loaded on demand).
  • CLAUDE.md never restates canon — it only points to it. If you find yourself copying a canon rule into CLAUDE.md, stop: leave a pointer instead.
  • Never duplicate a rule across layers. Duplication is the drift.

How canon reaches Codex

Codex has no @import/include directive (verified against the Codex config reference — it loads AGENTS.md up to project_doc_max_bytes, with project_doc_fallback_filenames as the only extension). So canon does not auto-reach Codex. Two sanctioned mechanisms:

  1. Orchestrator injection (default). When Claude hands Codex a task, Claude pastes the relevant docs/canon/* file(s) into the task spec. The split-by-topic canon makes this precise — hand Codex status-and-recruitment.md, not all canon.
  2. Codex reads the file as a task step. For larger tasks, the spec instructs Codex to Read docs/canon/<topic>.md before editing.

Do not try to solve this by importing all canon into AGENTS.md — it would blow the 28,672-byte lint budget and bloat every Codex call.

Codex-as-editor handoff protocol

Claude (orchestrator)  → research → plan → write a scoped task spec
                         (inject the governing AGENTS.md IDs + relevant docs/canon/* slice)
Codex (editor)         → implement in a workspace-write sandbox → self-run `yarn check`
Claude (orchestrator)  → independently run `yarn check` + `yarn lint:strict`
                         → review the diff against canon → commit → push → OTA

Non-negotiables:

  • The verify + commit + OTA gates stay with Claude (AOR-7 / AOR-8). Claude never claims done on Codex's word.
  • Codex review is read-only (--sandbox read-only); the second-model reviewer is input, never an editor and never authority.
  • Codex-as-editor is scoped to hard, self-contained, logic-heavy work. Pattern-application and design-system-touching work stays with Claude Agent(model: "sonnet") subagents, which inherit CLAUDE.md automatically (no canon-injection gap).
  • Reach for a second-model review on risky surfaces: auth, RLS / SECURITY DEFINER migrations, payments (Portone / session_payments), PIPA / consent, concurrency, or 5+ file refactors.

Canon extraction recipe (proven by the pilot)

Use these exact steps to move a topic out of CLAUDE.md into docs/canon/ (validated on status-and-recruitment.md):

  1. Locate the topic's blocks in CLAUDE.md (exact line numbers; note interleaved bullets that belong to a different topic and must stay).
  2. Create docs/canon/<topic>.md — dual-audience: a # Title + **Status:** Active / **Last reviewed:** header (required by the doc-inventory audit), a one-paragraph intro for humans, ##/### sections for the VitePress outline, then the rules verbatim. Convert [text](packages/…) source links to code spans (preserving the path) — VitePress dead-link checking fails on links to non-page .ts files; this matches screen-blueprint.md.
  3. Thin CLAUDE.md — replace the moved blocks with a one-line pointer that keeps the single hardest invariant inline + links to the canon doc.
  4. Register in scripts/doc-state-config.mjs: add to CURRENT_ACTIVE_DOCS (tracked + stale-linted) and to the Conventions group in SITE_REFERENCE_GROUPS (VitePress sidebar).
  5. Wire the sidebar — the Conventions section already exists in docs/.vitepress/site-sidebar.mjs; new canon docs only need the SITE_REFERENCE_GROUPS entry from step 4.
  6. Verify: yarn docs:generateyarn docs:check (state + stale + rule-docs + vitepress build) → yarn lint:agents-mdyarn check.
  7. Commit (docs-only → no OTA; the OTA-after-change rule is for shipped app behavior, not docs).

Drift-prevention checklist (run when adding or changing a rule)

  • [ ] Is this a hard constraint? → AGENTS.md (with an enforcement value). Soft? → docs/canon/*.
  • [ ] Did I avoid restating it in CLAUDE.md? (pointer only)
  • [ ] Is it in exactly one layer? (no duplication)
  • [ ] If it's a new canon doc: Status header + registered in doc-state-config.mjs + docs:check green?
  • [ ] If Codex will touch the affected area: is the canon doc in the handoff spec?

Venue closeout coordination — 2026-09-07

Codex completed local venue closeout in the isolated /home/sungkyu08/Dev/twomore-v2-venue-pipeline worktree, starting from a024d5b4. The bounded source retries, completed collector connection, acceptance evidence and Claude release actions are tracked in docs/audits/venue-closure-2026-09-07.md in that worktree. Source completeness and live deployment are separate from local implementation acceptance. Wider backend work remains paused. This notice and the queue notice below are the only Codex changes to the main checkout; runtime work stays isolated. The final yarn check, focused strict lint and collector review pass. The exact Naver record still lacks evidence (2,324/2,325); the bulk refresh stays blocked. Claude owns the three venue-component merge conflicts and the subsequent release proof.

Active queue integration coordination — 2026-09-07

Codex has completed local implementation and verification of the account-switching/ offline-queue slice in the isolated /home/sungkyu08/Dev/twomore-v2-venue-pipeline worktree on codex/venue-pipeline-20260906, starting at 9e5d67c7. Its scope is session/auth ownership, mutation queue/replay, the 15 existing queue producers, scoped adapters, and their tests. Shared integration points are packages/app/src/{index,registry}.ts, ports/index.ts, apps/mobile/app/_layout.tsx, and apps/web/app/providers.tsx. Avoid concurrent edits to those points until the handoff is reviewed. Claude's current wireframe/UI work remains in the main checkout. No push, hosted migration, or deployment is part of this slice.

The live plan, acceptance evidence, remaining gaps and next owner action are in /home/sungkyu08/Dev/twomore-v2-venue-pipeline/docs/audits/account-queue-orchestration-2026-09-07.md. Codex self-verifies and hands the diff to Claude for independent orchestration and merge/release review. This notice is copied to both worktrees; it is the only Codex edit to the main checkout in this continuation.

Active session boundaries (2026-09-05, flat detail-page migration × venue integrity work)

Two agents edit this worktree at once. Ownership is by path; neither stages, reverts, or reformats the other's files, and neither runs supabase db push or an OTA while the other has uncommitted work.

OwnerPathsNotes
Codex (venue integrity verification)packages/app/src/domain/entities/venue*, adapters/supabase/venue*, packages/features/sessions/src/directory-venue-detail/**, venue-correction/**, venue-*, packages/features/clubs/src/club-venue*, scripts/audit/**, scripts/lib/**, supabase/functions/{enrich,ingest,corroborate}-venues/**, supabase/migrations/005[89]*+, docs/history/venue-*, docs/audits/venue-*, root package.json test scriptsThe 2,347-row legacy Naver Place refetch cohort stays here unless explicitly handed over.
Claude (flat detail pages, waves P→1→3)packages/ui/**, packages/eslint-plugin/**, packages/features/sessions/src/session-detail/** + session-detail-screen.tsx, packages/features/profile/**, packages/features/records/**, packages/features/clubs/src/{join-review-detail-screen,public-club-profile*,post-detail*}, docs/design/detail-pages-*, docs/twomore_design_system/wireframes/detail-flat-language.jsxWave 2 (venue detail screens) is deferred until Codex's venue pass lands; it will start from the then-current directory-venue-detail/**.

Shared files (packages/app/src/index.ts, domain/index.ts, docs/README.md, generated state docs): commit only your own hunks; regenerate with yarn docs:generate right before committing.

See also

Markdown remains the source of truth. Run yarn docs:check before handoff.