# Crumb
<p align="center">
<img src="docs/assets/crumb-logo.png" alt="Crumb 로고 — 베이글 부스러기 마스코트와 CRUMB 워드마크" width="520">
</p>
> 캐주얼 게임 prototype 을 위한 **멀티 에이전트 스튜디오형 하네스**. 한 줄 피치 → multi-host AI 코딩 에이전트가 Planner → Builder → deterministic QA check → Verifier (CourtEval) 로 협업하고, 사용자는 라이브 Studio 에서 진행과정·이벤트·로그·산출물을 한 화면에서 관찰하며 자연어로 언제든 개입.
[](https://github.com/mangowhoiscloud/crumb/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
ENG: [README.eng.md](./README.eng.md).
## 개발 과정과 라이브 시연
Crumb + Crumb Studio 의 설계 발전 과정과 실제 세션 라이브 walkthrough.
[](https://youtu.be/WbGNpE9TClI)
▶️ **[YouTube 에서 보기](https://youtu.be/WbGNpE9TClI)**
## 이름의 의미
Crumb 이라는 이름은 한 가지 개발 패턴에 대한 오마주에서 출발합니다. LLM 위에 시스템을 쌓아 올릴 때, 로그와 이벤트 스키마, 그리고 도구 description 은 모델이 곧 결정할 다음 Action 을 조용히 인도합니다 — 모델은 자신이 남긴 부스러기를 따라가며 다음 발걸음을 고르고, 그 작은 흔적들이 모여 결국 하나의 경로가 됩니다. 이 패턴이 이름의 첫 출처입니다.
이러한 개발 방식은 자연스럽게 다음 메타포로 이어집니다. 숲에서 길을 잃지 않으려 빵 부스러기를 흘려두던 *헨젤과 그레텔*의 이미지는 한 줄 한 줄의 transcript 가 다음 actor 의 발판이 되는 본 시스템의 형태와 거의 그대로 겹칩니다. 35 종의 kind 와 8 명의 actor 가 `transcript.jsonl` 위에 차곡차곡 부스러기를 떨어뜨리고, 그 위에서 다음 spawn 의 sandwich 가 조립됩니다.
이름 하나가 에이전트 시스템이 어떤 모양으로 구성되는지에 관한 힌트를 함께 전해 주기를 바랐습니다.
## 핵심 메시지
이 도구는 멀티 에이전트 협업을 단순 채팅이 아니라 **관찰·개입·평가·재현 가능한 실행 프로토콜**로 다룹니다. 모든 메시지·도구 호출·산출물·사용자 개입·deterministic QA 결과·judge 점수가 **35 kind × 11 field × 13 specialist step × 8 actor** transcript 한 줄로 영속.
### 설계 목표 매트릭스
| GOAL | 충족 위치 |
|---|---|
| 다양한 호스트 에이전트 동시 사용 (Claude Code / Codex / Gemini CLI) | 4 entry path (Claude Code / Codex / Gemini / headless) + per-actor `--bind <actor>=<harness>:<model>` 으로 자유 조합. 예: `--bind verifier=gemini-cli:gemini-3.1-pro-preview` 로 cross-vendor verifier. |
| 에이전트 간 상호 통신 | 8 actor × 35 transcript kind, actor 간 `kind=handoff.{requested,rollback}`. |
| 사용자 개입 + 관찰 | 5 user.* event × 4 host = 20-cell matrix. 자연어 → `kind=user.intervene`. |
| 통신 방식 / 프로토콜 / UI 자유 | JSONL transcript + 4 entry path (Claude Code / Codex / Gemini / headless). |
| AI 코딩 에이전트로 직접 개발 | Claude Code + Codex 로 구현 — commits, sandwich, helpers, OTel exporter 가 흔적. |
| README 그대로 재현 동작 | `git clone … && npm run setup && npx crumb run --goal "…" --adapter mock` — 인증 0, 결정론. |
| `.md` 산출물 포함 | agents/*.md (5) + skills/*.md (5) + specialists/*.md (3) + .{claude,codex,gemini}/ entries (5). |
| JSONL 로그 또는 시연 녹화 | `transcript.jsonl` 35 kind + 라이브 시연 영상 (상단 임베드). |
## 빠른 시작
**두 줄, 심링크 없음, 글로벌 설치 없음:**
```bash
git clone https://github.com/mangowhoiscloud/crumb.git && cd crumb
npm run setup
```
`npm run setup` 은 클론 디렉터리 안에서 idempotent 한 3단계를 실행:
1. `npm install` — 의존성 + `postinstall` hook 으로 Playwright Chromium 사전 캐시 (D6 portability 첫 실행부터 동작).
2. `npm run build` — 루트 + `@crumb/studio` workspace TypeScript 컴파일.
3. `crumb doctor` — 환경 probe (3 host CLI / adapter / 추천 preset). best-effort — 첫 설치 시 부분 인증은 정상.
전역 PATH 에 아무 것도 등록하지 않고 양쪽 bin 을 `npx` 로 직접 호출:
```bash
npx crumb run --goal "60-second match-3 with combo bonus" --adapter mock --idle-timeout 5000
npx crumb-studio # http://127.0.0.1:7321/ — 브라우저 자동 오픈
```
`--adapter mock` 한 줄이 **결정론 happy-path smoke** — 인증 0, 약 1 초 만에 26-event transcript + PASS verdict 으로 종료. 평가자가 처음 실행해 install 건강성을 확인하기에 가장 적합. `npx crumb replay <session-id>` 로 동일 상태 재현 가능.
> **왜 `npm link` / 글로벌 install 안 쓰나?** 글로벌 symlink 는 monorepo workspace 의 Node resolution 을 꼬이게 만들고, 공유 머신에서 사용자 계정을 넘어 leak 되며, 깨끗한 uninstall 을 위해 수동 추적이 필요합니다. `npx <bin>` 은 workspace `bin` 을 zero global state 로 resolve — `git clone`-and-delete 만으로 모든 Crumb 파일이 사라집니다.
> **npm 의 `crumb` 는 무관 패키지입니다.** npm 에 등록된 `crumb` (v7.x) 은 이 저장소와 관련 없는 다른 프로젝트입니다. Crumb 은 현재 **clone-only** (채용 평가 전 npm publish 보류). `npm i -g crumb` 하지 마세요 — 이 코드베이스가 설치되지 않습니다.
> **Chromium 다운로드 건너뛰기** (CI / air-gapped 환경): `CRUMB_SKIP_PLAYWRIGHT_INSTALL=1 npm run setup`. qa-check D6 portability gate 는 signal-only 로 남고, D2 lint + size gate 는 그대로 동작.
### 업데이트
```bash
cd crumb && npm run update # git pull --ff-only 후 setup 재실행
```
작업 트리가 dirty 면 실행을 거부 — 로컬 수정이 침묵 속에 덮이지 않습니다.
### 언인스톨
Crumb 은 PATH 에 어떤 것도 symlink 하지 않으므로 제거 = 파일 삭제:
```bash
npm run uninstall # 빌드 산출물 제거 (dist/, node_modules/)
npm run uninstall -- --purge-data # ~/.crumb (sessions, projects) 도 제거
npm run uninstall -- --purge-browsers # Playwright chromium 캐시도 제거
rm -rf "$(pwd)" # 마지막으로 클론 디렉터리 자체 제거
```
### 리셋
```bash
npm run reset # dist/ + node_modules/ 만 삭제. ~/.crumb / chromium 캐시는 보존
npm run setup # clean slate 에서 재빌드
```
빌드가 망가졌거나 "fresh-clone 상태 재현" 이 필요할 때 (재클론 없이) 사용.
### 실 에이전트로 실행 (`claude login` / `codex login` / `gemini login` 후)
```bash
# 가지고 있는 provider 만 인증:
claude login # Anthropic Claude Max
codex login # OpenAI Codex Plus
gemini login # Google Gemini Advanced
# 임의 작업 디렉터리에서 프로젝트 pin + 실행:
mkdir -p ~/projects/match3 && cd ~/projects/match3
npx --prefix /path/to/crumb crumb init --pin --label "match3"
npx --prefix /path/to/crumb crumb run --goal "60-second match-3 with combo bonus"
# 결과 promote + checkable 폴더로 export:
npx --prefix /path/to/crumb crumb release <session-ulid> --as v1 --label "demo"
npx --prefix /path/to/crumb crumb copy-artifacts v1 --to ./demo
```
`--prefix` 는 npx 가 글로벌 symlink 없이 클론된 repo 의 workspace bin 을 가리키도록 합니다. 짧게 쓰려면 shell rc 에 `alias crumb='npx --prefix /path/to/crumb crumb'` 추가. `provider × harness × model` 결정은 **사용자 통제권** — Crumb 은 강제 default 박지 않음. `npx crumb doctor` 로 환경에서 어떤 preset 이 실 동작 가능한지 확인.
### Claude Code 안에서 자연어로 실행
```text
$ claude
> /crumb 60초 매치-3 콤보 보너스 게임 만들어줘
```
`.claude/skills/crumb/SKILL.md` skill 이 피치를 받아 클론된 repo 의 headless `crumb run` 을 호출하고 transcript 이벤트를 스트리밍. 자연어 추가 발화 ("이 부분 다르게", "콤보 보너스 좀 더 짧게") 도 `kind=user.intervene` 으로 자동 라우팅.
## 세션 검사
```bash
npx crumb ls # ~/.crumb/projects/*/sessions/ 모든 세션
jq -r '"\(.kind)\t\(.from)"' \
~/.crumb/projects/<project-id>/sessions/<ulid>/transcript.jsonl
npx crumb replay <ulid> # 결정론 재실행
npx crumb status <ulid> # 진행 상황 + last 10 events + 점수
npx crumb explain <kind> # transcript kind schema lookup
```
## 라이브 Studio
Crumb Studio 는 인터랙션 가능한 관찰 + 개입 surface — **Android Studio** (running build drill-down), **n8n** (mid-flight 워크플로 컨트롤), **Google AI Studio** (라이브 에이전트 + artifact preview), **Upstage Studio** (per-actor lane + scorecard + transcript co-located) 의 계보에 있음.
사용자는 파이프라인 전 진행과정 (Planner → Researcher → Builder → deterministic QA → Verifier), Actor 별 실시간 이벤트 (swimlane chip), 라이브 transcript + per-actor logs, 산출물 미리보기 (`game.html` / `spec.md` / `DESIGN.md` / `tuning.json` 을 sandboxed iframe), scorecard (anti-deception source-of-truth chip 포함) 모두 한 화면에서 확인하고, slash bar (`/approve`, `/veto`, `/pause`, `/redo`, `@actor …`) 로 mid-run 개입 가능 — 모든 액션이 transcript event 로 박혀서 actor 의 다음 spawn 에 그대로 흘러감.
Studio 는 단일 바이너리 Node HTTP + SSE 서버. **기본 포트 `7321`, `127.0.0.1` 만 바인드** — 새 체크아웃 + 새 브라우저 탭이 macOS / Windows 방화벽 prompt 없이 즉시 동작. Cross-platform (chokidar + WSL/NFS polling fallback, 플랫폼-특화 syscall 0).
```bash
# `npm run setup` (빠른 시작 단계) 후, 클론된 repo 안에서:
npx crumb-studio # http://127.0.0.1:7321/ (브라우저 자동 오픈)
npx crumb-studio --no-open # 헤드리스 / SSH / CI (URL 만 출력)
npx crumb-studio --port 8080 # 다른 포트
npx crumb-studio --bind 0.0.0.0 # LAN / SSH 터널 노출 (방화벽 prompt)
```
브라우저에서 보이는 것:
| 영역 | 내용 |
|---|---|
| **사이드바 (좌측)** | 프로젝트별 세션 그룹 + + 버튼 (새 `crumb run` form: goal + preset). 행 hover 시 × 로 studio 에서 dismiss (디스크 transcript 는 보존). |
| **헤더 strip** | D1–D6 source-of-truth scorecard, 항상 보임, `kind=judge.score` 마다 갱신. |
| **Pipeline 탭** | 9-actor DAG topology (활성 actor 라임 펄스, 모든 transcript event 마다 sender → next-likely target 으로 lavender 리플 "weaving") + actor 별 swimlane chip 타임라인. |
| **Logs 탭** (ArgoCD-inspired) | actor 별 `<session>/agent-workspace/<actor>/spawn-*.log` 라이브 tail (모든 adapter spawn 의 stdout / stderr). filter / follow / clear / copy. DAG 노드 click 시 자동 점프. |
| **Output 탭** | sandboxed iframe 으로 `artifacts/game/index.html` (multi-file profile) 또는 `artifacts/game.html` (single-file fallback) 라이브 렌더. reload + open-in-new-tab. 즉석에서 플레이. |
| **Live execution feed** (입력창 위) | 활성 세션의 모든 transcript event **+** 모든 actor spawn log chunk 가 한 줄씩, kind 별 color-code 된 터미널-스타일 stream. |
| **Console input** (하단) | 슬래시 명령 (`/approve` `/veto <reason>` `/pause [@actor]` `/goto <actor>` `/note <text>`), `@actor` 멘션, plain-text user.intervene. **`/crumb <goal>`** 은 새 세션 spawn. |
| **Detail panel** (우측, 이벤트 클릭) | 파이프라인 위치 narrative ("PHASE B → C — Spec sealed"), parent → this → children thread, actor 별 sandwich preview, actor 별 mini-console. |
Cross-platform 환경 변수:
| 변수 | 효과 |
|---|---|
| `CRUMB_HOME` | `~/.crumb` 오버라이드 (sandbox / CI / 멀티유저 셋업) |
| `CRUMB_POLL=1` | chokidar polling 강제 (WSL2 / Docker / NFS / SMB) |
| `CRUMB_NO_OPEN=1` | 브라우저 자동 오픈 안 함 (`--no-open` 와 동일) |
### Slash bar — 사용자 개입 grammar
브라우저 하단 슬래시 바와 헤드리스 `inbox.txt` watcher 가 동일 grammar 공유. 두 표면 모두 한 줄을 append; 활성 세션의 inbox watcher 가 `src/inbox/parser.ts` 로 파싱하고 `kind=user.*` (또는 `kind=note`) 이벤트를 transcript 에 기록. coordinator 가 이 이벤트를 보고 라우팅 — 브라우저든 TUI든 스크립트로 `echo` 했든 동일한 흐름.
| 명령 | 동작 | Transcript kind |
|---|---|---|
| `/approve` | 최신 verifier `PARTIAL` 판정을 `PASS` 로 promote — 부드러운 기준이 운영자 수동 검증으로 만족됐을 때 세션 종료 가능 | `user.approve` |
| `/veto <reason>` | 최신 판정 거부. reducer 가 artifact 폐기 + builder 재spawn (Critical 이면 planner-lead Phase B) 라우팅, 이벤트에 `reason` 캡처 | `user.veto` |
| `/pause [@<actor>] [reason]` | 글로벌 또는 actor 별 pause. `/pause` 는 모든 spawn 정지 후 `/resume` 대기; `/pause @builder waiting` 은 builder 만 정지하고 나머지 진행 | `user.pause` (`data.actor` if scoped) |
| `/resume [@<actor>]` | `/pause` 의 역. 글로벌 큐 또는 명시 actor 재개 | `user.resume` |
| `/goto <actor> [body]` | `next_speaker = <actor>` 강제 + 즉시 spawn — LangGraph `Command(goto)` analogue. 단계 건너뛰기 (verifier 직행) 또는 멈춘 actor 재spawn 용 | `user.intervene` (`data.goto`) |
| `/swap <from>=<adapter>` | actor adapter binding 라이브 swap (Paperclip BYO 스타일). 예: `/swap builder=mock` 으로 결정적 build 재현. override 는 세션 종료까지 `progress_ledger.adapter_override[<actor>]` 에 보존 | `user.intervene` (`data.swap`) |
| `/append [@<actor>] <text>` | 다음 spawn 들에 sandwich-append 주입. `data.sandwich_append` 가 시스템 프롬프트에 concatenate — actor 재시작 없이 nudge. Codex `APPEND_SYSTEM.md` analogue | `user.intervene` (`data.sandwich_append`) |
| `/note <text>` | 자유 형식 제약 / 코멘트를 timeline 에 기록. 라우팅 변경 X — 향후 actor 들이 transcript 히스토리에서 볼 수 있는 어노테이션 | `note` (from `user`) |
| `/redo [body]` | 마지막 actor 의 spawn 을 optional override body 로 재emit. adapter 일시적 실패로 응답 불완전 시 유용 | `user.intervene` |
| `/reset-circuit <actor\|all>` | 트립된 circuit-breaker 클리어. dispatcher 가 연속 실패로 actor 차단 후 재시도 원할 때 | `user.intervene` (`data.reset_circuit`) |
| `@<actor> <body>` | 자유 텍스트 멘션 — body 가 `data.target_actor` 태그된 `user.intervene` 로 들어가서 그 actor 의 다음 sandwich 에 노출. 예: `@builder use red palette` | `user.intervene` (`data.target_actor`) |
| `<plain text>` | `/` 또는 `@` 로 시작 안 하는 모든 것. generic intervention — transcript 에 보이고 라우팅 변경 X | `user.intervene` |
헤드리스 표면도 같은 라인이 동작:
```bash
echo "/pause @builder waiting" >> ~/.crumb/projects/<id>/sessions/<sid>/inbox.txt
echo "@builder use red palette" >> ~/.crumb/projects/<id>/sessions/<sid>/inbox.txt
echo "/note hold off until I review the spec" >> ~/.crumb/projects/<id>/sessions/<sid>/inbox.txt
```
제약:
- 세션이 **live** (`status: "running"`) 여야 함 — `done` / `errored` 세션은 inbox watcher 가 떠있지 않아 라인이 파일엔 추가되지만 파싱되지 않음. Studio 슬래시 바는 활성 세션이 terminal 일 때 비활성화
- reducer 가 단일 진실 — 슬래시 바는 transcript 를 **직접** 쓰지 않음. AGENTS.md read-only invariant 모든 표면에서 보존
- 라인은 strict 순서로 처리; `/pause` 직후 `/resume` 1ms 후도 OK
## CLI
모든 명령은 클론된 repo 안에서 `npx crumb …` (또는 다른 디렉터리에서 `npx --prefix /path/to/crumb crumb …`) 로 호출. `--version` / `-v` 는 패키지 버전 출력. `npx crumb --help` 가 동일한 표를 출력합니다.
| 명령 | 동작 |
|---|---|
| `crumb run --goal "<피치>" [--preset <name>] [--adapter <id>]` | 세션 시작 |
| `crumb event` | 서브프로세스 에이전트가 stdin JSON 으로 transcript append |
| `crumb event tail [--all] [--kinds ...]` | transcript 이벤트 스트림 (private 기본 필터) |
| `crumb replay <session-dir>` | transcript 에서 상태 재구성 (결정론 검증) |
| `crumb resume <session-id\|dir>` | 상태 재구성 + mid-flight 재개 명령 출력 |
| `crumb status <session-id\|dir>` | 진행 상황 + last 10 events + D1-D6 점수 |
| `crumb explain <kind>` | transcript-kind schema lookup |
| `crumb suggest <session-id\|dir>` | 다음 사용자 액션 추천 (approve/veto/pause/wait) |
| `crumb tui <session-id\|dir>` | blessed-기반 라이브 옵저버 (터미널) |
| `crumb model [--show \| --apply "NL"]` | 액터별 model + effort + provider 활성화 |
| `crumb doctor` | 환경 종합 점검 (3 host OAuth + adapter health + preset gating) |
| `crumb config <자연어>` | 자연어 설명에서 preset 추천 |
| `crumb debug <session-id\|dir>` | F1-F7 routing 장애 진단 |
| `crumb export <session-id\|dir> [--format ...]` | OTel GenAI / Anthropic / chrome://tracing export |
| `crumb init [--host <name>] [--pin]` | host entry 점검 / cwd 를 안정 ULID 로 pin |
| `crumb ls` | `~/.crumb/projects/*/sessions/` 모든 세션 + 이벤트 수 |
| `crumb release <session-id> [--as vN]` | 산출물 스냅샷을 versions/ 로 + `kind=version.released` |
| `crumb versions` | 릴리스 마일스톤 + parent chain |
| `crumb copy-artifacts <session-id\|vN> --to <dest>` | frozen 산출물 복사 (제출용) |
| `crumb migrate [--dry-run]` | 레거시 `<cwd>/sessions/` 를 `~/.crumb/projects/<id>/sessions/` 로 이동 |
| `crumb studio [--port ...] [--bind ...]` | 웹 콘솔 (= `crumb-studio`) |
| `crumb --version` / `-v` | 패키지 버전 출력 |
| `npx crumb-studio [--port 7321] [--bind 127.0.0.1] [--no-open]` | 라이브 Studio (HTTP + SSE) — 위 "라이브 Studio" 섹션 참조 |
라이프사이클 (클론된 repo 의 npm scripts):
| 명령 | 동작 |
|---|---|
| `npm run setup` | install + build + doctor (idempotent — update 경로 동일) |
| `npm run update` | `git pull --ff-only` 후 setup 재실행. dirty tree 거부 |
| `npm run uninstall [-- --purge-data] [-- --purge-browsers]` | 빌드 산출물 제거. 옵션 플래그로 `~/.crumb` / Playwright 캐시 추가 제거 |
| `npm run reset` | `dist/` + `node_modules/` 제거. `~/.crumb` 와 chromium 캐시는 보존 |
## 아키텍처 (v0.4, 한 화면)
<p align="center">
<img src="docs/assets/architecture-pipeline.png" alt="Crumb v0.4 아키텍처 — user → coordinator → planner-lead → researcher → builder → verifier → validator → done. qa_check (rule-based) 가 결정론 ground truth, system 이 done(budget/error) 으로 합류, validator audit 후 rollback (Critical / audit) 경로 분기" width="100%">
</p>
**그래프 읽기**: `user` → `coordinator` 가 `goal` 을 받음 → `planner-lead` 가 `spec` 발행 → `researcher` 로 `evidence` handoff → `planner-lead` 가 `synth` 로 resume → `builder` 가 `build` → 결정론 `qa_check (rule-based)` → `verifier` 가 LLM `verify` (CourtEval 4 sub-step) → `validator` 가 `audit` → `done`. 두 종류 rollback 경로: **Critical** (verifier → planner-lead 재spec) 과 **audit** (validator → planner-lead 재spec). 시스템 내부 `system` 노드는 `qa.result (rule)` / `done (budget/error)` deterministic 출구를 통합.
- **5 actor** (planner-lead / researcher / builder / verifier / coordinator) + **2 specialist** (planner inline: concept-designer / visual-designer) + **1 contract** (`agents/specialists/game-design.md`, 4 actor inline-read) + **5 procedural skill** (sandwich-loaded)
- **Multi-host 4 entry**: Claude Code skill / Codex CLI / Gemini CLI / headless `crumb run`
- **스키마**: 35 kind × 11 field × 13 specialist step × 8 actor × OTel GenAI alias
- **3-layer scoring (D1–D6 source-of-truth matrix)**: reducer-auto (D4 + D3/D5 의 auto 성분) + qa-check-effect (D2 / D6, deterministic ground truth) + verifier-llm (D1 + D3/D5 의 LLM 성분). D3 / D5 는 LLM + auto 두 성분을 `combineDimScore()` 가 결정론적으로 평균.
- **v0.4 강화**: AC predicates 명문화 / judge-input.jsonl 번들 (verifier hard input isolation, prompt-only enforcement 의 ~50% 한계 보강) / 수치적 self-bias discount (D1 −0.5 when `cross_provider=false`)
- **PR-Prune-2 (제거됨)**: 이전 다이어그램의 `builder-fallback` actor 는 폐기. circuit-OPEN 처리는 이제 같은 builder actor 의 **adapter swap** 으로 단순화 (production 세션 0 spawn 누적 → 가지치기)
- **비용**: $0/session (Claude Max + Codex Plus + Gemini Advanced 구독) 또는 `--adapter mock` (무료)
- **설정 자유도**: actor 별 `(harness × provider × model)` 3-tuple, 사용자가 preset 으로 선택, 명시 없으면 ambient (entry host 따라감)
전체 canonical spec: [wiki/concepts/bagelcode-system-architecture-v0.1.md](./wiki/concepts/bagelcode-system-architecture-v0.1.md).
## Preset 옵션
actor 별 `(harness × provider × model)` 결정은 **사용자가** 선택. Crumb 은 강제 X. `crumb doctor` 로 환경에서 어떤 preset 이 가능한지 확인.
| Preset | Binding | 사용 사례 |
|---|---|---|
| **(no preset)** ambient ★ | 모든 actor 가 entry host 따라감 (Claude Code → Opus 4.7) | **권장 default**. 단일 인증으로 가장 강한 모델이 모든 actor 담당. |
| **`video-research`** | researcher=gemini-sdk (Gemini 3.1 Pro 비디오) / 나머지 ambient | gameplay 비디오가 핵심 input — researcher 만 Gemini 로 명시 binding |
| **`mock`** | 모든 actor = mock adapter | CI / 인증 없음 / 결정론 데모 |
Preset 파일: `.crumb/presets/*.toml`.
**Cross-vendor verifier (self-bias 완화)** — 더 이상 별도 named preset 이 아니라 per-actor binding 으로 처리:
```bash
crumb run --goal "..." --bind verifier=gemini-cli:gemini-3.1-pro-preview
```
verifier 만 Gemini 로 묶어 multimodal screenshot grading + cross-provider self-bias 회피 (NeurIPS 2024). 다른 actor 는 entry host 의 강한 default model 유지.
> PR-DropSoloSdk (2026-05-05) 로 `solo` / `sdk-enterprise` 제거. PR-DropCross3Way (2026-05-07) 로 `cross-3way` 도 제거 — `builder=codex / verifier=gemini-cli` 를 default 경로에 박아넣어 Claude Code 사용자 (Opus 4.7 사용 가능) 의 output quality 를 강제로 떨어뜨렸기 때문 (Codex 의 HTML/CSS prior < Opus 4.7). cross-vendor verifier 는 `--bind verifier=...`, "builder 에 Codex 쓰고 싶다" 는 `--bind builder=codex:gpt-5.5-codex` — 명시적 opt-in, default 침범 없음.
## Frontier 레퍼런스
모든 설계 결정은 특정 frontier 사료에 1:1 매핑됩니다. 아래 매트릭스는 Crumb 의 한 design point 에서 그것을 정당화하는 논문 / OSS / 케이스 스터디로 가는 일방향 티켓입니다. 전체 인용 chain 은 wiki 가 보관하며, 우측 컬럼의 링크가 canonical synthesis 또는 reference 페이지로 이어집니다.
| Crumb design point | Frontier 출처 | Wiki page |
|---|---|---|
| Multi-host × `(harness × provider × model)` 3-tuple | Claude Code / Codex / Gemini / OpenCode CLI 의 2026-04 convergence (7 공통 primitive) | [references/bagelcode-frontier-cli-convergence-2026.md](./wiki/references/bagelcode-frontier-cli-convergence-2026.md) |
| Actor split (builder ⫶ verifier) | 20 사료 × 4 차원 isolation matrix; 진짜 cross-assemble 의 전제는 actor-level boundary | [concepts/bagelcode-verifier-isolation-matrix.md](./wiki/concepts/bagelcode-verifier-isolation-matrix.md) |
| 3-layer scoring (verifier-llm / qa-check-effect / reducer-auto) | CourtEval ACL 2025 + G-Eval + position-bias IJCNLP 2025 + self-bias NeurIPS 2024 + multi-judge consensus 97–98% F1 | [references/bagelcode-llm-judge-frontier-2026.md](./wiki/references/bagelcode-llm-judge-frontier-2026.md) |
| Verifier 직전 deterministic `qa_check` (pre-verifier LLM scoring 거부) | DeepSeek-R1 (PRM saturation → rule-based reward), Cognition multi-agent debate retreat, Eisenstein 2024 Goodhart-on-LLM-judge | [synthesis/bagelcode-pre-verifier-no-scoring-frontier-2026-05-03.md](./wiki/synthesis/bagelcode-pre-verifier-no-scoring-frontier-2026-05-03.md) |
| Hub-Ledger-Spoke 토폴로지 (single coordinator + spoke) | Lanham 2026-04: centralized 4.4× error containment vs independent 17.2× amp | [concepts/bagelcode-orchestration-topology.md](./wiki/concepts/bagelcode-orchestration-topology.md) |
| 3 surface 사용자 개입 (TUI 슬래시 / `inbox.txt` / JSON event) | LangGraph `Command(goto/update={...})` + AutoGen UserProxy + Codex `APPEND_SYSTEM.md` (12-system survey) | [synthesis/bagelcode-user-intervention-frontier-2026-05-02.md](./wiki/synthesis/bagelcode-user-intervention-frontier-2026-05-02.md) |
| Subprocess injection (CLAUDE.md auto-load 회피) | Karpathy LLM.txt + AGENTS.md (Linux Foundation Agentic AI Foundation 표준) | [synthesis/bagelcode-identity-files-decomposition-2026-05-02.md](./wiki/synthesis/bagelcode-identity-files-decomposition-2026-05-02.md) |
| OTel GenAI semantic conventions | Datadog APM / Vertex / Anthropic Console / Phoenix / Langfuse export 호환 | [references/bagelcode-observability-frontier-2026.md](./wiki/references/bagelcode-observability-frontier-2026.md) |
| Verifier hard input isolation (judge-input.jsonl 번들) | Anthropic 2026 Hybrid Normalization — prompt-only mitigation ≈ 50%, file-level enforcement 으로 보강 | [synthesis/bagelcode-verifier-context-isolation-2026-05-03.md](./wiki/synthesis/bagelcode-verifier-context-isolation-2026-05-03.md) |
| pass@N 거부 | DeepSeek-R1 + outcome-level deterministic AC8 이 multi-sample gate 역할 | [synthesis/bagelcode-no-pass-n-decision-2026-05-03.md](./wiki/synthesis/bagelcode-no-pass-n-decision-2026-05-03.md) |
| 사용자 통제 preset (강제 default 금지) | Anthropic 2026-03 "wrong tradeoff" 자인 — `provider × harness × model` 은 사용자 결정 | [synthesis/bagelcode-paperclip-vs-alternatives.md](./wiki/synthesis/bagelcode-paperclip-vs-alternatives.md) |
| CourtEval inline 4-step (Grader → Critic → Defender → Re-grader) | ACL 2025 paper, judge-bias 완화 | [references/bagelcode-llm-judge-frontier-2026.md](./wiki/references/bagelcode-llm-judge-frontier-2026.md) |
| Multi-agent communication protocol (transcript-as-SOT) | TradingAgents (arXiv 2412.20138) | [references/bagelcode-tradingagents-paper.md](./wiki/references/bagelcode-tradingagents-paper.md) |
README 전 statement 별 인용은 [synthesis/bagelcode-frontier-rationale-5-claims.md](./wiki/synthesis/bagelcode-frontier-rationale-5-claims.md) 가 한 번에 펼쳐 보여줍니다.
## 결정 타임라인
3 일 동안 일어난 lock 들을 시간순으로 정리한 매트릭스. 우측 컬럼은 그 결정이 검토된 대안과 함께 어떻게 잠겼는지 기록한 synthesis 페이지로 이어집니다.
| Phase | 날짜 | Lock | Wiki page |
|---|---|---|---|
| **1 — 방향** | 2026-05-01 | 커스텀 transcript JSONL + reducer 채택 (Paperclip / LangGraph / CrewAI / Mastra 5-안 비교) | [synthesis/bagelcode-paperclip-vs-alternatives.md](./wiki/synthesis/bagelcode-paperclip-vs-alternatives.md) |
| 1 | 2026-05-01 | PDCA 거부 → Hierarchical Hybrid (Hub-Ledger-Spoke) | [concepts/bagelcode-orchestration-topology.md](./wiki/concepts/bagelcode-orchestration-topology.md) |
| 1 | 2026-05-01 | 이름 — bagel crumb + breadcrumb pattern + transcript trail (3 중 메타포) | [synthesis/bagelcode-naming-crumb.md](./wiki/synthesis/bagelcode-naming-crumb.md) |
| 1 | 2026-05-01 | F1–F5 fault 분류 + 3-tier caching 전략 lock | [concepts/bagelcode-fault-tolerance-design.md](./wiki/concepts/bagelcode-fault-tolerance-design.md) · [concepts/bagelcode-caching-strategy.md](./wiki/concepts/bagelcode-caching-strategy.md) |
| **2 — Architecture lock** | 2026-05-02 | Hybrid host harness — Claude Code skill (default) + headless `crumb run` | [synthesis/bagelcode-host-harness-decision.md](./wiki/synthesis/bagelcode-host-harness-decision.md) |
| 2 | 2026-05-02 | 5 actor 고정; Engineering Lead → builder + verifier actor split | [synthesis/bagelcode-agents-fixed.md](./wiki/synthesis/bagelcode-agents-fixed.md) |
| 2 | 2026-05-02 | Identity files — AGENTS.md + CLAUDE.md + GEMINI.md 분해 (universal + host-specific) | [synthesis/bagelcode-identity-files-decomposition-2026-05-02.md](./wiki/synthesis/bagelcode-identity-files-decomposition-2026-05-02.md) |
| 2 | 2026-05-02 | 3-surface NL intervention (TUI / inbox / JSON) — frontier 12-system survey synthesis | [synthesis/bagelcode-user-intervention-frontier-2026-05-02.md](./wiki/synthesis/bagelcode-user-intervention-frontier-2026-05-02.md) |
| 2 | 2026-05-02 | Verifier isolation matrix (13 사료 × 2 차원) → actor-level cross-provider opt-in | [concepts/bagelcode-verifier-isolation-matrix.md](./wiki/concepts/bagelcode-verifier-isolation-matrix.md) |
| 2 | 2026-05-02 | System architecture v0.1 — multi-host × 3-tuple + 3-layer scoring | [concepts/bagelcode-system-architecture-v0.1.md](./wiki/concepts/bagelcode-system-architecture-v0.1.md) |
| **3 — Frontier alignment + pruning** | 2026-05-03 | Pre-verifier LLM scoring 거부 — `qa_check` 가 ratchet 자리 | [synthesis/bagelcode-pre-verifier-no-scoring-frontier-2026-05-03.md](./wiki/synthesis/bagelcode-pre-verifier-no-scoring-frontier-2026-05-03.md) |
| 3 | 2026-05-03 | pass@N 거부 — deterministic ground truth × 4 layer + single-shot CourtEval + Reflexion respawn | [synthesis/bagelcode-no-pass-n-decision-2026-05-03.md](./wiki/synthesis/bagelcode-no-pass-n-decision-2026-05-03.md) |
| 3 | 2026-05-03 | Verifier hard isolation — judge-input.jsonl 번들, prompt-only 폐기 | [synthesis/bagelcode-verifier-context-isolation-2026-05-03.md](./wiki/synthesis/bagelcode-verifier-context-isolation-2026-05-03.md) |
| 3 | 2026-05-03 | Same-provider 수치적 self-bias discount (D1 −0.5 when `cross_provider=false`) | [synthesis/bagelcode-same-provider-discount-2026-05-03.md](./wiki/synthesis/bagelcode-same-provider-discount-2026-05-03.md) |
| 3 | 2026-05-03 | 4×4 genre × persistence profile matrix; default `casual-portrait` × `local-only` | [synthesis/bagelcode-genre-profile-decision-2026-05-03.md](./wiki/synthesis/bagelcode-genre-profile-decision-2026-05-03.md) |
| 3 | 2026-05-03 | Pipeline pruning — 9 schema kind 제거 + reducer 라우팅 단순화 | [synthesis/bagelcode-pipeline-pruning-handoff-2026-05-03.md](./wiki/synthesis/bagelcode-pipeline-pruning-handoff-2026-05-03.md) |
| 3 | 2026-05-03 | Studio big-bang — vanilla JS → React + dockview 마이그레이션 | [synthesis/bagelcode-studio-big-bang-update-2026-05-03.md](./wiki/synthesis/bagelcode-studio-big-bang-update-2026-05-03.md) |
| 3 | 2026-05-03 | Studio Datadog-grade redesign — new-session form + pipeline visualization spec | [synthesis/bagelcode-studio-datadog-grade-redesign-2026-05-03.md](./wiki/synthesis/bagelcode-studio-datadog-grade-redesign-2026-05-03.md) |
| 3 | 2026-05-03 | System architecture v0.4 — AC predicates + judge-input isolation + self-bias discount 통합 | [concepts/bagelcode-system-architecture-v0.4.md](./wiki/concepts/bagelcode-system-architecture-v0.4.md) |
## Wiki 사용법
`wiki/` 는 Karpathy 스타일의 compiled knowledge base 입니다 — 한 번 distill 한 뒤 keep current. 모든 페이지는 YAML frontmatter 와 Obsidian 호환 `[[wikilinks]]` 를 갖고 있고, 첫 독자에게 의미 있는 카테고리는 다음 다섯 개입니다.
| 디렉토리 | 용도 | 언제 읽으면 좋은가 |
|---|---|---|
| `concepts/` | 시스템 아키텍처, 스키마 spec, 멘탈 모델 | "Crumb 가 어떻게 만들어졌는가" 의 canonical 답이 필요할 때 |
| `synthesis/` | 결정 페이지 — 대안 비교, lock 기록, rationale 인용 | 특정 결정이 *왜* 그렇게 잠겼는지 (그리고 무엇이 거부됐는지) 확인할 때 |
| `references/` | 단일 사료 요약 (논문 / OSS / CLI doc / 케이스 스터디) | 한 design point 의 frontier 1차 사료가 필요할 때 |
| `findings/` | 실증 조사 (벤치 / 실 세션 evidence) | 구체적인 숫자나 측정된 행동을 보고 싶을 때 |
| `diagrams/` | Mermaid + .mmd 소스 | 다이어그램을 렌더링하거나 remix 하고 싶을 때 |
**읽기 primitive — 가장 가벼운 것부터 escalate:**
1. `wiki/index.md` (있다면) — 카테고리별 한 줄 요약
2. 페이지 frontmatter 의 `summary:` 필드 — 1–2 문장 미리보기
3. `grep -A 10 -B 2 "<term>" wiki/**/*.md` — 특정 claim 을 주변 컨텍스트와 함께
4. 전체 Read 는 위 셋이 답을 못 줄 때만
200 페이지 vault 는 full-vault scan 으로 버틸 수 없습니다 — 위 primitive 가 wiki 의 scaling 방식입니다. 같은 가이드는 [.skills/llm-wiki/SKILL.md](./.skills/llm-wiki/SKILL.md) 에도 (gitignored — maintainer runtime).
**가장 ROI 높은 두 진입점:**
1. [concepts/bagelcode-system-architecture-v0.1.md](./wiki/concepts/bagelcode-system-architecture-v0.1.md) — canonical v0.1 스펙
2. [synthesis/bagelcode-frontier-rationale-5-claims.md](./wiki/synthesis/bagelcode-frontier-rationale-5-claims.md) — 모든 README claim 을 frontier 사료로 cite
## 산출물
### 디스크 계층
```
~/.crumb/ # CRUMB_HOME (env override / CRUMB_HOMES 멀티-홈)
└── projects/
└── <project-id>/ # 프로젝트 — 라이브 세션 + frozen 릴리스 모두 소유
├── sessions/
│ └── <session-ulid>/ # WIP 시도 (가변 lifecycle)
│ ├── transcript.jsonl # Replay-deterministic 이벤트 로그 (35 × 11)
│ ├── meta.json # 라이프사이클 상태 (running/paused/done/error)
│ ├── inbox.txt # 슬래시 명령 + 자유 텍스트 user 입력 (단일 writer)
│ ├── ledgers/
│ │ ├── task.json # 누적 facts (transcript 에서 도출)
│ │ └── progress.json # turn 별 상태 (transcript 에서 도출)
│ ├── agent-workspace/ # 액터별 sandbox + 조립된 sandwich
│ │ └── <actor>/
│ │ └── sandwich.assembled.md # host CLI 가 --append-system-prompt 로 받은
│ │ # 시스템 프롬프트 (envelope XML + 액터 sandwich +
│ │ # 절차 skill + sandwich_append).
│ │ # AGENTS.md §"Subprocess injection over CLAUDE.md
│ │ # auto-load" 가 여기서 구현됨.
│ ├── artifacts/
│ │ ├── game/ # Phaser 3.80 multi-file PWA — game/index.html
│ │ │ ├── index.html
│ │ │ ├── manifest.webmanifest
│ │ │ ├── sw.js # cache-first service worker (offline)
│ │ │ ├── icon-192.svg / icon-512.svg
│ │ │ └── src/main.js + src/{config,scenes,entities,systems}/
│ │ ├── spec.md # 수락 기준 + 룰북
│ │ ├── DESIGN.md # 색감 / 메커닉 / 모션 spec
│ │ └── tuning.json # 밸런스 수치
│ ├── exports/
│ │ ├── otel.jsonl # OpenTelemetry GenAI Semantic Conventions
│ │ ├── anthropic-trace.json
│ │ └── chrome-trace.json # chrome://tracing 시각화
│ └── index.html # 자동 생성 post-session HTML 요약
└── versions/
└── <vN>[-<label>]/ # 릴리스된 마일스톤 (immutable)
├── manifest.toml # 스코어카드 + parent_version + artifacts_sha256
└── artifacts/ # 소스 세션 artifacts/ 의 frozen 사본
```
### `<project-id>` 계산 (자주 묻는 질문)
```
1. <cwd>/.crumb/project.toml 이 있으면 → 그 안의 `id` 필드 사용 (ULID).
2. 없으면 (ambient) → sha256(path.resolve(cwd))[:16]
```
**두 모드 — 의도 가지고 선택:**
| 모드 | 사용 시점 | 머신 간 일관성 |
|---|---|---|
| **Ambient** (기본) | 한 머신에서 끝나는 작업 | ❌ 다른 머신/다른 cwd → 다른 `<project-id>`. 16-hex prefix 는 로컬 캐시 키일 뿐. |
| **Pinned** (`crumb init --pin`) | 평가자 제출 / 평가자 데모 / 재현이 필요한 모든 작업 | ✅ `<cwd>/.crumb/project.toml` 에 stable ULID 박힘. **그 파일을 git 에 commit** 하면 어느 머신에서 clone 하든 같은 `<project-id>` 로 풀려서 모든 머신이 같은 `~/.crumb/projects/<id>/sessions/` 버킷에 모임. |
```bash
mkdir -p ~/projects/match3 && cd ~/projects/match3
crumb init --pin --label "match3" # .crumb/project.toml 생성
git add .crumb/project.toml && git commit -m "chore: pin project id"
```
이후 어느 clone 에서 `crumb run` 하든 같은 프로젝트 버킷에 들어감. `<session-ulid>` 는 매 실행마다 새로 (ULID 는 시간 정렬, 새 run = 새 ulid).
### 세션 → 버전 흐름
`crumb release <session-ulid> --as v1 [--label "demo"]` 가 소스 세션의 `artifacts/` 트리를 `~/.crumb/projects/<project-id>/versions/v1[-demo]/` 로 스냅샷하고, `manifest.toml` (가장 최근 `judge.score` 의 스코어카드 + 파일별 sha256) 작성, 소스 세션 `transcript.jsonl` 에 `kind=version.released` append. 소스 세션을 지워도 버전은 동결 상태 그대로.
`crumb copy-artifacts <session|vN> --to <dest>` 는 제출 라인 — 선택한 artifacts/ 트리를 `~/.crumb/...` 밖의 일반 폴더로 복사 (zip 가능).
이 산출물은 **Unity 신작팀의 input asset** — Crumb 는 production Unity workflow **앞 단계**의 prototype 검증 도구.
## 상태
```
✅ 스키마 v0.1 — 35 kind × 11 field × 13 step × 9 from + D1-D6 source-of-truth scoring
✅ Pure reducer — circuit breaker / adaptive stop / rollback / user.veto rebound (vitest)
✅ Adapter — claude-local / codex-local / gemini-local / mock
✅ Live dispatcher — spawn / append / hook / rollback / stop / done / qa_check
✅ qa_check effect — deterministic ground truth (LLM 없음, htmlhint + playwright headless smoke)
✅ Preset loader — (harness × provider × model) 3-tuple binding + ambient fallback
✅ CLI — run / event / replay / resume / doctor / config / debug / ls
✅ Skill — .claude/skills/crumb/SKILL.md (Claude Code 자연어 진입점)
✅ Summary — 자동 생성 index.html + OTel/Anthropic/Chrome trace exports
✅ CI — lint + typecheck + format + test (Node 18/20/22) + 스키마 검증
🟡 claude-local + codex-local + gemini-local 실제 end-to-end (env propagation spike 진행 중)
🟡 Persistence boost — flock + adapter_session_id 메타 ('crumb resume' live re-entry, P1)
🟡 MCP Provider — localhost:8765 cross-host fan-in (P1)
🟡 --strict-cross-provider — Builder=OpenAI / Verifier=Anthropic 진짜 cross-assemble (P1)
🟡 데모 스크린캐스트
```
## 문서
- [AGENTS.md](./AGENTS.md) — 이 repo 에서 작업하는 에이전트/기여자용 (Linux Foundation Agentic AI Foundation 표준)
- [agents/_event-protocol.md](./agents/_event-protocol.md) — 서브프로세스 에이전트가 `crumb event` 로 이벤트 emit 하는 방법
- [protocol/schema.md](./protocol/schema.md) — 1-page transcript spec
- [protocol/schemas/message.schema.json](./protocol/schemas/message.schema.json) — JSON Schema (draft 2020-12)
- [.claude/skills/crumb/SKILL.md](./.claude/skills/crumb/SKILL.md) — Claude Code host harness 진입점
- [.crumb/presets/](./.crumb/presets/) — `video-research` / `mock` (ambient default = no preset)
- [wiki/](./wiki/) — 설계 rationale (mango-wiki subset, 35 page)
- [bagelcode-system-architecture-v0.1.md](./wiki/concepts/bagelcode-system-architecture-v0.1.md) — ★ canonical v0.1 시스템 구조
- [bagelcode-host-harness-decision.md](./wiki/synthesis/bagelcode-host-harness-decision.md) — Hybrid (Skill + headless CLI) lock
- [bagelcode-verifier-isolation-matrix.md](./wiki/concepts/bagelcode-verifier-isolation-matrix.md) — 20-사료 매트릭스
- [bagelcode-final-design-2026.md](./wiki/concepts/bagelcode-final-design-2026.md) — §3-§9 (envelope / cache / OTel) v0.1 에서도 유효
## License
MIT