Claude Fable 5 conducts · Grok 4.5 Heavy types · React Native / Expo ready
Combat-hardened Claude Code plugin for long multi-agent chains.
Architect stays lean. Volume runs on a separate vendor quota. UI smoke via Argent.
Русский · Upstream pattern: fable-advisor · vs upstream · combat bugs · install
┌─────────────────────────────────────┐
│ FABLE 5 · session architect │
│ specs · routing · STATUS accept/reject │
│ ledger · fable-advisor (rare) │
└──────────────────┬──────────────────┘
│ five-part + MODE
│ (no product Write/Edit)
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
MODE: explore MODE: implement MODE: verify
map / impact type the change tsc · jest · Argent
│ │ │
└────────────────────────┴────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ GROK 4.5 HEAVY · headless CLI │
│ + Level B explore subagents │
│ + Level R research (no reinvent) │
│ + Level C Critic (opt-in) │
│ STATUS: pass | fail | … │
└─────────────────────────────────────┘
Tokens route by role, not by habit: Fable emits judgment; Grok emits volume; Argent evidence comes back as paths, not screenshot dumps into the architect transcript.
Level U Self-routing (v1.4.0): Grok is a universal volume agent. It self-selects explore / research / critic / device phases for any scenario (not UX-only). Architect defaults to ROUTING: auto. Doctrine: docs/ROUTING.md.
Level R Research: when the worker (or a force override) enables it — survey docs/registry/GitHub before inventing. docs/RESEARCH.md.
Level C Critic: self-selected (or force); not a tax on every ticket. docs/CRITIC.md.
DannyMac180/fable-advisor introduced the elegant architect pattern: smartest model runs the show, cheaper cross-vendor lanes type. That design is sound.
This repo is what happened after running that pattern for real on a production Expo / React Native app with SuperGrok Heavy, parallel lanes, Argent device QA, and multi-hour autonomous chains.
Upstream is a clean doctrine.
This fork is the field manual + hard gates that doctrine needed when things broke.
Upstream fable-advisor |
This repo fable-orchestrator |
|
|---|---|---|
| Goal | Cost-aware multi-vendor routing | Survive combat RN sessions |
| Default typing | Grok (+ optional Codex race) | Grok Heavy only (Codex optional later) |
| Enforcement | Skill prose | Hooks that deny bad paths |
| Headless launch | Inline flags in agent doc | Classifier-safe shell launcher |
| Completion signal | Report + re-verify | STATUS: contract + incomplete stamp |
| Parallelism | Independent agents | Level A + B + R (research) + C (opt-in critic) |
| Long chains | Implied | Ledger · soft Stop tsc · orphan cleanup · metrics |
| RN / device UI | Not a focus | Argent on Grok lane; architect no-touch |
- Fable as architect, not typist
- Five-part spec contract (objective · files · interfaces · constraints · verification)
fable-advisorfor commitment boundaries- Grok as default non-Anthropic typing lane
- No silent “lane became Claude” substitution
| Choice | Why |
|---|---|
| No Codex lane by default | Many setups only have SuperGrok Heavy; a dead lane adds noise. Race/failover can return later if Codex CLI exists. |
| Hard product-write deny | Prose (“don’t implement yourself”) is ignored under pressure. Hooks deny src/, lockfiles, app.config, etc. |
| Named-spawn deny | Claude Code: spawning grok-implementer with name can strip the agent tool whitelist → Sonnet silently self-implements and fakes a Grok report. |
| Modes: explore / implement / verify | One agent, three contracts — explore must not edit; verify must not redesign. |
| Argent / RN verify path | Mobile UI is not tsc green. Device loops belong on the cheap volume lane. |
| STATUS-driven completion | ps, Metro :8081, and orphan processes are not “still working”. |
| Combat docs & stress prompts | Real multi-wave backlog drives, not only README examples. |
| Mechanism | Role |
|---|---|
hooks/block-architect-product-write.py |
Architect cannot edit product trees |
hooks/block-named-cli-lane.py |
Named Grok spawn blocked |
scripts/run-grok-headless.sh |
Headless invoke + pidfile + wall/stall watchdog |
scripts/lane-health.sh |
STATE=status|running|stale|dead for one final.txt |
scripts/wait-for-status.sh |
Poll STATUS + pidfile only (no ps|grep grok) |
scripts/stop-tsc-soft.sh |
Stop hook warns; does not freeze parallel waves |
scripts/cleanup-orphans.sh |
SessionEnd reports zombie grok (ppid=1) |
docs/LEDGER.md |
Multi-unit checkbox truth across compaction |
Level A — Claude → N× grok-implementer (one message, independent paths)
Level B — Grok → its explore/plan kids (depth 1, report SUBAGENTS: N)
Level R — Grok → research before edit (Expo/npm/GitHub; default auto)
Level C — Grok → Critic phase (opt-in only; default off)
Independent product units → Level A.
One unit spanning many folders → Level B inside one headless session.
Non-trivial implement → Level R research first (docs/RESEARCH.md).
Critic only when Constraints set CRITIC: on|hard.
| Done | Not done |
|---|---|
Report body has STATUS: … |
Empty narrative / “waiting for notification” |
| Launcher returned (or stamped timeout/incomplete) | Metro still on :8081 |
| Evidence: command exit / Argent paths | “Grok said it works” |
If the model exits without STATUS:, the launcher stamps STATUS: incomplete — never auto-complete.
- Deny lists include
src/,ios/,android/,app.config.*,eas.json, lockfiles,locales/,assets/ - Always-allow docs:
CLAUDE.md,AGENTS.md,docs/TODO.md,docs/LEDGER.md, agent config - UI acceptance → Argent on Grok (
MODE: verify/ implement Verification) - Architect: at most
list-devices— no screenshot/tap chains - Shared tree: no
git stash/reset; partition writes; final verify after a wave
Each headless run appends one JSON line to:
~/.claude/fable-orch/metrics.jsonl
Fields: timestamp, rc, wall clock, optional best-of-n, STATUS — no prompt text.
Disable: FABLE_ORCH_METRICS=0.
Optional quality race for hard implement only:
bash run-grok-headless.sh spec.txt final.txt "$(pwd)" 900 3
# or GROK_BEST_OF_N=3These are not theoretical. They showed up in real Fable + Grok + RN sessions.
| Symptom | “Grok report” appears, but Claude/Sonnet typed the code |
| Cause | Spawning the lane with a name routes to a teammate path that can drop the agent tool whitelist (Write/Edit come back) |
| Fix | Hook denies named grok-implementer; agent doc: spawn without name |
| Symptom | Lane “succeeds”, working tree clean, no edits |
| Cause | Upstream-style --permission-mode acceptEdits (or interactive defaults) weak in headless; positional prompt can open TUI instead of one-shot |
| Fix | Launcher always: --prompt-file · -m grok-4.5 · --always-approve · --output-format plain · --cwd · stdin /dev/null |
| Symptom | denied by the Claude Code auto mode classifier on Bash |
| Cause | Long inline wrappers + --allow 'Bash(*)' look like privilege escalation soup |
| Fix | One short bash "$LAUNCH" … line; no --allow 'Bash(*)'; rely on Grok permission_mode=always-approve in ~/.grok/config.toml; one retry then STATUS: blocked_by_claude_classifier — no grok -p "OK" bisect storms |
| Symptom | Architect waits forever; human babysits ps |
| Cause | Metro left up for the user; orphan grok (ppid=1, 100% CPU, hours); agent ends with “background waiting for notification” without STATUS |
| Fix | Done ⇔ STATUS: only; launcher stamps timeout / incomplete; skill forbids ps/Metro as completion; SessionEnd orphan report |
| Symptom | Headless process hangs past useful work |
| Fix | gtimeout/timeout wall clock (default 540s; 3600–5400 for rebuild+Argent); require brew install coreutils on macOS |
| Symptom | Lane returns unavailable while grok login is fine |
| Cause | Transient token / grok models flake |
| Fix | Retry auth probe once before failing closed |
| Symptom | Parallel lanes mid-edit → red tsc → every architect Stop blocked |
| Cause | Project Stop ran hard tsc --noEmit always |
| Fix | Soft Stop helper: skip if no dirty TS; on red warn only; hard gate = MODE: verify / CI |
| Symptom | Long chain forgets what was already accepted |
| Fix | docs/LEDGER.md — open before 2nd spawn; tick [x] only with STATUS + evidence |
| Symptom | Bash fails when agents find / for the launcher |
| Fix | Resolve launcher only from CLAUDE_PLUGIN_ROOT, ~/fable-orchestrator, or sibling path — never filesystem-wide search |
| Policy | Loud `STATUS: unavailable |
| Never | Silent Claude re-implement of product code |
Why it exists: Without a single skill, Fable re-derives “should I type this?” every turn and burns the scarce quota.
What it encodes:
- Cost discipline (judgment ≠ volume)
- MODE table + no-touch table
- Spec contract + report shapes
- Level A / B / R (research) / C (opt-in critic) parallelism
- STATUS anti-hang + long-chain loop
- Ledger, metrics, best-of-n, orphan policy
Why not only CLAUDE.md: Always-on project docs stay thin (~one screen). Full doctrine loads when orchestration is relevant — less permanent context tax.
Why Sonnet drives the CLI (not Fable):
The subagent’s job is supervise headless Grok, not redesign the app. Fable should not spend Mythos tokens on shell choreography.
Why tools are only Bash, Read, Grep, Glob:
No Write/Edit on purpose. If Write appears, the spawn is wrong — stop and report.
Why MODE + independent re-verify:
Grok’s claim is not evidence. Driver re-runs verification and returns compressed reports the architect can accept without re-reading the tree.
Why a second Fable call:
Same model family, fresh context — reads code without the conversation’s sunk-cost bias. ≤300 words, never implements.
When: architecture, migrations, API shape, two failed attempts, “are we done?”
Used with this plugin on RN apps:
| Piece | Why |
|---|---|
Thin CLAUDE.md |
Always-on architect role |
AGENTS.md |
Stack, design tokens, shared-tree rules for all agents |
GROK.md |
PROCESS EXIT + STATUS for headless workers |
Slim .claude/rules/argent.md |
Always-on safety; full Argent skills on demand |
| Argent skill pack | Device/UI only when verify needs it — not loaded “just in case” |
Why Argent skills are on-demand:
Fourteen full device skill bodies would drown the architect. Slim rule + load device-interact / test-ui-flow only when Grok runs UI.
fable-orchestrator/
├── agents/
│ ├── fable-advisor.md # commitment skeptic (Fable, read-only)
│ └── grok-implementer.md # headless Grok driver (Sonnet, no product Write)
├── skills/orchestration/
│ └── SKILL.md # full routing doctrine
├── hooks/
│ ├── block-named-cli-lane.py
│ ├── block-architect-product-write.py
│ └── hooks.json # PreToolUse + SessionEnd
├── scripts/
│ ├── run-grok-headless.sh # launcher · metrics · best-of-n · STATUS stamps
│ ├── cleanup-orphans.sh # zombie grok report (optional kill)
│ └── stop-tsc-soft.sh # project Stop helper
├── docs/
│ ├── RESEARCH.md # Level R pre-implement no-reinvent research
│ ├── CRITIC.md # Level C critic (opt-in)
│ ├── LEDGER.md # multi-unit template
│ ├── LONG_CHAIN_STARTER.md # paste-ready long session
│ ├── COMBAT_TODO_MULTIWAVE.md # real multi-wave stress prompt
│ └── TODO_CHAIN_STRESS_TEST.md # Level A + B exercise
├── README.md # English (this file)
├── README.ru.md # Russian
└── .claude-plugin/
├── plugin.json # v1.2.0
└── marketplace.json
claude plugin marketplace add BuildContext/fable-orchestrator
claude plugin install fable-orchestrator@fable-orchestratorFrom a local clone:
claude plugin marketplace add /absolute/path/to/fable-orchestrator
claude plugin install fable-orchestrator@fable-orchestratorUpdate:
claude plugin marketplace update fable-orchestrator
claude plugin update fable-orchestrator@fable-orchestratorclaude
# /model fable| Need | Notes |
|---|---|
| Claude Code + Fable 5 | Architect chair |
| Grok CLI | grok login · SuperGrok Heavy recommended |
python3 |
Hooks (shell fallback still blocks named spawns) |
gtimeout |
brew install coreutils — wall clocks for long lanes |
| Argent (optional, RN) | Device smoke on Grok; dev-client, not Expo Go |
Allow in Claude settings:
Bash(grok *)
Bash(bash *run-grok-headless*)
<!-- CLAUDE.md -->
You are the Fable Architect. Product code and Argent loops → grok-implementer
(without name) only. Multi-unit → docs/LEDGER.md. Done ⇔ STATUS in reports.
Full doctrine: skill orchestration (fable-orchestrator).Point Stop at soft tsc if you previously hard-failed every turn:
bash "$HOME/fable-orchestrator/scripts/stop-tsc-soft.sh"
# hard gate remains MODE: verify| MODE | Product edits | Primary report |
|---|---|---|
explore |
❌ | EXPLORE REPORT |
implement |
✅ | GROK REPORT |
verify |
❌* | VERIFY REPORT + optional ARGENT REPORT |
* minimal fix only if the verify spec allows it.
Every spawn: Objective (with MODE) · Files · Interfaces · Constraints · Verification.
Open docs/LEDGER.md for this goal.
In one message, spawn three grok-implementer MODE: explore (no name):
A — SegmentedTabs / liquid glass under src/
B — TextInput focus cold-start (PIN / business name)
C — bank scheme registry (report only, no product decision)
Merge maps. Implement only if Interfaces are unambiguous and scope is bounded.
Finish with MODE: verify (tsc + short Argent if UI).
Tick ledger only with STATUS + evidence.
Stress prompts with full multi-wave structure: docs/COMBAT_TODO_MULTIWAVE.md, docs/TODO_CHAIN_STRESS_TEST.md, docs/LONG_CHAIN_STARTER.md.
| Version | What landed |
|---|---|
| 1.4.1 | STATUS exit-first (no mid-stream kill); trailing full-line STATUS:; enum aliases; fail-closed product hooks; bash best-effort; sync-plugin-cache.sh single-root; metrics-summary.sh; implement NO_DIFF gate; fast path force patch |
| 1.4.0 | Universal self-routing (Level U): worker classifies patch/standard/deep and opens only needed phases; STATUS+SCOPE+ROUTING+SUBAGENTS; architect stops micromanaging RESEARCH/CRITIC; compact ledger; domain-agnostic personas |
| 1.3.x | Level R research + Level C critic docs; combat RN defaults |
| 1.0.0 | Lean fork: Grok lane, advisor, orchestration skill, product-write + named-spawn hooks, headless script |
| 1.1.x | STATUS anti-hang, timeout/incomplete stamps, long-chain docs, Grok-internal subagents policy |
| 1.2.0 | Session ledger, soft Stop tsc, metrics.jsonl, optional --best-of-n, SessionEnd orphan cleanup |
| 1.2.1 | Launcher: bash 3.2-safe (no empty-array under set -u); STATUS detect accepts **STATUS:** markdown; driver anti-yield contract hardened; scripts/test-launcher-status.sh |
| 1.2.2 | Stall + wall watchdog in launcher (no gtimeout required); ${FINAL}.pid lane identity; lane-health.sh / wait-for-status.sh; kill silent headless; forbid ps|grep grok false-alive |
Pattern inspired by DannyMac180/fable-advisor (MIT) — read that first if you want the pure cost/routing essay.
This repository is a separate combat fork: fewer lanes, more hard gates, RN/Argent ops, and fixes for bugs discovered in production agent runs.
MIT — see LICENSE.
Fable thinks. Grok types. STATUS decides. Ledger remembers.