Ground-truth fact sheet for the v0 artifact schema
For: Fable 5's v0 artifact/trace schema draft
From: Claude (Opus 4.8), reading the actual flows/*.yaml
Date: 2026-07-01
Why: Fable 5's condition on the schema was "pin against two flows, not one — space_channel + austin_plumbing." Here's what those two flows actually are in the codebase, so v0 fits reality and isn't rebuilt in a month.
Node-type census (grep-level, from flows/*.yaml)
| Flow | Choose (locked_choice) | Collect (ask+update_slots) | Say (static/play_audio) | Do (required_tool) | books via | prerendered? |
|---|---|---|---|---|---|---|
| space_channel | 2 | 1 | 1 | 0* | — (info flow) | yes (all) |
| austin_plumbing | 0 | 5 | 1 | 0 | async post-call export | no (greeting only) |
| apartment_scheduler | 2 | 2 | 4 | 0 | live schedule_event mid-call |
partial |
| bellas_hair_salon | 0 | 1 | 0 | 0 | (thin) | no |
| serene_mobile_massage | 0 | 0 | 0 | 0 | (module-based) | no |
* Space Channel's fetch_* required_tool states still exist but we deliberately routed the flow around them; they're orphaned, not on the path.
The five findings that should shape v0
1. The two anchor flows are near-opposite shapes. Space Channel is Choose-heavy, fully prerendered — the "frozen menu" the compiler model fits perfectly. austin_plumbing is Collect-heavy (5 Collect, 0 Choose), ~all live TTS (1 Say of ~20 states) — almost no frozen skeleton. A schema whose center of gravity is "frozen route table + resolved WAVs" fits Space Channel and barely touches austin_plumbing. Pinning against both is exactly right; the risk is that v0 comes out Space-Channel-shaped.
2. Collect is the under-specified node, and it's the whole booking vertical. The reframe treats Do as the interesting typed hole. But no flow dispatches a tool from the FSM (see #3), while austin_plumbing is five Collect states. Collect is not Say (frozen), not Choose (deterministic), not Do (tool) — it's an LLM-owned sub-dialogue with a slot-schema contract. The artifact can pin {slot schema, prompt, model, max_turns, confirm/deny phrasing, extraction rules} but not the conversation. This is where cost/latency/quality (the LLM knobs) actually live — Space Channel has ~0 Collect, booking flows are mostly Collect, so the entire model-selection story is a Collect-node story. v0 must specify Collect as richly as Do.
3. No flow uses required_tool for booking — the FSM-dispatched typed-hole Do is a NEW pattern, not existing behavior. Today booking is either an LLM-called tool via allowed_tools (apartment_scheduler: schedule_event mid-call, mic open, model-driven) or deferred to post-call. The reframe's "Do = FSM dispatches the tool with a deadline, mic closed, model never sees it" is a good design that replaces apartment_scheduler's mic-open pattern — but the schema is introducing it, not codifying it. Justify the Do node against apartment_scheduler specifically; that's the flow it fixes.
4. Two distinct booking patterns — and austin's validates the pre/flow/post reframe. apartment_scheduler books live, in-flow (mid-call tool). austin_plumbing collects preferences in-flow and books async in post-flow (terminal-state export → provider matcher; the prompts literally say "do NOT call schedule_event... the post-call export sends the provider-matching data"). austin is already practicing "collect in flow, act in post-flow" — the exact discipline the reframe advocates. So "post-flow action" (async booking / provider-match / callback) should be a first-class artifact concept, not just eval+canary. The schema needs both: an in-flow typed-hole Do and a post-flow deferred action.
5. Prerendering is Space-Channel-only today. 1 of ~20 austin states is prerendered (the greeting). So "resolved WAV per Say" is nearly empty for booking flows unless we redesign them (as we just did for Space Channel — that was days of work). v0 should let a Say be either a prerendered-WAV or a live-TTS-with-frozen-prompt, and mark which — because live→prerendered is a per-flow migration project, and the manifest should show an operator which of their prompts are still live (slower, variable) vs. frozen.
Direct implications for the v0 units (in Fable 5's own priority order)
- Node types: keep the five, but promote Collect to a fully-specified node (slot schema, model, max_turns, confirm/deny phrasing, extraction contract) — it's the majority of the revenue flows and the entire LLM-cost surface. Keep Do as the typed hole (tool ref, deadline, hold asset, result frames: enumerable variants vs slot-TTS, failure→Say) — but tag it "new pattern, replaces mic-open
allowed_toolsbooking." - Say: must carry a discriminator —
{prerendered: wav_ref+hash+rendered_at+cadence}or{live_tts: frozen_prompt+voice}. Freshness dots only apply to the former; the latter is flagged "live" in the console. - Post-flow action: first-class (async booking, provider match, callback) — austin needs it; it's the honest home for "act after the call."
- Choose grammar block: tokens, aliases, DTMF map, thresholds, and a reject/garbage path (Fable 5's gotcha #1 — a constrained decoder with no escape forces babble onto the nearest token). Confidence = constrained-vs-unconstrained likelihood ratio.
- Degraded assets: the "temporarily unavailable" Say per state is a compiled asset present in every artifact, validated at build (gotcha #2 — the fallback is the one asset that can never 404).
- Trace schema (universal):
state_enter,audio_pushed,audio_done{source: client|watchdog},route_decision{source: dtmf|grammar|fallback, confidence},collect_turn{slot, model, latency},tool_start/result,postflow_action,stall_detected. This is the one contract shared by live calls, all sim tiers, the console, and the research-agent vertical (which has no compiled menu but still emits trace — trace is universal, the artifact schema is phone/booking-scoped).
Bottom line for v0
Pin against space_channel (all-frozen) AND apartment_scheduler (live-tool Do) AND austin_plumbing (Collect-heavy, post-flow booking) — three shapes, not two, because austin and apartment book differently and neither looks like Space Channel. If the schema spans those three, it spans the product. The single biggest correction to the reframe: Collect, not Do, is the node that carries the booking vertical and the entire cost-optimization story — spec it accordingly.