Skip to content

FableForge Roadmap Audit — 2026-04-23

Scope: Document-level analysis of the FableForge End-to-End Roadmap (280 tasks, 14 phases). The FableForge codebase (TypeScript / Next.js / Convex) is a separate project and was not directly accessible during this audit. All findings are therefore grounded in the roadmap document itself — verified for internal consistency, logical dependency correctness, and prioritization quality. Items flagged under “Missing Context” require real-code verification before implementation.


These must be resolved before any team member picks up the affected tasks; they will cause confusion or implementation conflicts if left open.

1.1 Schema version collision (T-021 / T-022)

Section titled “1.1 Schema version collision (T-021 / T-022)”

T-021 body text bumps from "0.1.0""0.2.0" (and names the target “FFScript v0.2”). However, T-021’s own acceptance criteria reads:

“existing FFScriptV1 validates as 1.0; new format validates as 1.1

This mixes two incompatible version strings (0.2.0 in the task body; 1.0 / 1.1 in the acceptance criteria). T-022 reinforces 0.1.0 → 0.2.0. Whichever version naming scheme the team chooses must be consistent across both tasks and the migration runner.

Resolution: pick one scheme before starting T-021. Recommended: stay on semver 0.x until the Panel contract is battle-tested, then promote with a separate “v1.0 promotion” task. Delete the 1.0/1.1 references from T-021’s acceptance criteria.

1.2 Non-existent task reference T-268b (T-021)

Section titled “1.2 Non-existent task reference T-268b (T-021)”

T-021 notes: “A later task (T-268b) will promote to 1.0.0.” T-268b does not exist anywhere in the roadmap. T-268 is the FFScript fuzzer. Either create the task, or remove the reference.

  • T-002 renames StudioWizard.tsxWizardCreatePage.tsx.
  • T-102 says “Wizard is a ‘narrow’ storyboard — one implementation, two presets.”

If T-102 is implemented, the wizard is no longer a standalone component and the rename in T-002 becomes meaningless (or actively misleading). These two tasks need to be reconciled: either T-002 is a transitional rename that T-102 will later absorb, or T-002 should be skipped in favor of doing T-102 directly. Mark T-002 blocked by the T-101/T-102 design decision.

1.4 T-029 phase assignment (Phase 1, P1/L)

Section titled “1.4 T-029 phase assignment (Phase 1, P1/L)”

T-029 deprecates gameDrafts.beats in favor of panels and migrates all legacy drafts on open. This is a destructive migration of the primary authoring data model. Placing it in Phase 1 — before the storyboard GUI (Phase 3) and wizard integration (Phase 4) exist — means the migration runs against a UI that hasn’t been updated to consume panels yet. Move T-029 to Phase 4 or later.

1.5 T-040 — docs written before the feature exists (Phase 1, P1/S)

Section titled “1.5 T-040 — docs written before the feature exists (Phase 1, P1/S)”

T-040 writes docs/FFSCRIPT_PANELS.md in Phase 1, before panels are implemented in the compiler (T-023, Phase 1), validated (T-043, Phase 2), or used by any GUI (Phase 3+). Document the schema after it is stable. Move T-040 to Phase 3; lower to P2.

1.6 T-085 “Presence-aware cursor hook” in Phase 3 (P2/S)

Section titled “1.6 T-085 “Presence-aware cursor hook” in Phase 3 (P2/S)”

The note says it “ships the cursor broadcast hook now, activated later.” Shipping dead infrastructure ahead of its Phase 12 activation creates a maintenance burden with no near-term payoff. Move T-085 to Phase 12 where the collaboration work actually happens.


Each pair below should be explicitly linked in the tracker or merged into a single task.

PairIssue
T-003 + T-017Both address per-beat regeneration: T-003 is the UI, T-017 is the backend contract. They must land together in one PR or the UI calls a non-existent action. Mark T-003 blockedBy: T-017.
T-005 + T-006T-005 (structured error surfaces in wizard) and T-006 (remove silent catch blocks) are the same effort: one changes what errors look like, the other ensures errors are actually thrown. Merge into a single task.
T-013 + T-129T-013 routes the outline LLM call through selectModelForTask. T-129 builds the full cross-provider orchestrator. T-013 should be noted as “a temporary fix pending T-129; revisit when T-129 lands.”
T-106 + T-065 + T-179Character sheet (Phase 4), foreground layer editor (Phase 3), and character library panel (Phase 6) all build character UI. Three-phase character UI buildup risks inconsistent component structure. Consolidate design upfront even if implementation spans phases.
T-193 + T-205Auth mutation audit and siloing test suite are the same work. T-193 is the manual grep; T-205 is the automated coverage. They belong in one sprint.

3.1 P0 tasks buried in late phases (should move to Phase 0 or Phase 1)

Section titled “3.1 P0 tasks buried in late phases (should move to Phase 0 or Phase 1)”
TaskCurrent phaseIssue
T-191 — cascade deletePhase 8Data safety / orphan risk exists from day one. Every game created before this lands is a potential orphan liability. Move to Phase 0 alongside T-001.
T-193 — auth mutation auditPhase 8Security invariant. Should be enforced before any public-facing mutations are added. Move to Phase 0.
T-205 — siloing test suitePhase 8Same as T-193.
T-226 — server-side age gatePhase 10Tier-2 content is generated starting Phase 5. A client-only gate is bypassable from the moment tier-2 generation is wired. Move to Phase 5 as a precondition for T-149 (SFW/NSFW routing).

3.2 Tasks labeled P0 that are not functional blockers

Section titled “3.2 Tasks labeled P0 that are not functional blockers”
TaskLabelRecommendation
T-007 — unify provider/tier stampsP0/SData hygiene, not a blocker for any journey step. Lower to P1.
T-010 — audit log of wizard transitionsP0/SObservability, not functional. Lower to P2.
T-018 — structured generation progress feedP0/MUseful but the wizard ships working feedback today (however rough). Lower to P1.
T-030 — panel-level seed lockingP1/SStyle consistency feature. Lower to P2.
TaskLabelReason to elevate
T-191 / T-193 / T-205P0 label but Phase 8Already noted above — data safety.
T-031 — aspect ratio drives workflow dimsP0 noted, but buried in Phase 1Hardcoded dims break resolution switching for every user immediately. Confirmed P0, should be executed alongside T-021.
T-128 — resolution picker UIP0/M Phase 5This is the user-facing side of T-031 and should land at the same time.

4. Prunable Tasks (safe to defer past MVP)

Section titled “4. Prunable Tasks (safe to defer past MVP)”

These items have effort costs that outweigh their pre-launch value. None should block the critical path to a usable MVP.

TaskRecommendation
T-014 — migrate abandoned draftsScheduled job, not needed until user base exists. Defer to post-launch.
T-040 — FFScript Panel docs (Phase 1)Already noted; defer to Phase 3.
T-075 — zoom/pan state per panelP1/S in Phase 3; nice-to-have, not blocking. Defer to Phase 5.
T-083 — Panel templates libraryP2/M; only valuable after core editing is solid. Defer to Phase 5.
T-085 — presence cursor hookAlready noted; defer to Phase 12.
T-089 — rule-of-thirds guideP2/S; visual polish. Defer to Phase 14.
T-090 — safe-area overlayP2/S; only needed for CBZ export (Phase 11). Move there.
T-098 — saveable view stateP2/S; UX polish, not blocking authoring. Defer to Phase 14.
T-100 — command palette mutation logsP2/S; debugging aid, not user-facing. Defer to Phase 13.
T-134 — PuLID for FluxP2/M; third identity-preservation option. Defer until IP-Adapter FaceID Plus v2 is stable.
T-141 — SUPIR upscalerP2/L; luxury restoration pass. Defer until export pipeline exists.
T-148 — relight/re-tone passP2/M; advanced compositing. Defer to Phase 12+.
T-155 — lip-syncP2/L; cinematic mode only. Defer to Phase 11+.
T-239 — Electron desktop exportP3/XL; enormous effort, unclear demand. Defer indefinitely.
T-243 — share links with trackingP2/S; analytics feature. Defer to Phase 13.
T-244 — embed snippetP2/S; developer feature, low initial demand. Defer to Phase 11.
T-256 — CRDT fork/mergeP3/XL; overkill before multi-user editing (Phase 12) is even proven. Defer indefinitely.

The §10 graph omits several real dependencies that will cause integration pain if missed.

DependencyMissing from graph
T-226 (age gate) must land before T-149 (SFW/NSFW routing)Not shown
T-031 (aspect ratio in schema) must land before T-128 (resolution picker UI)Not shown
T-124 (SAM 2 auto-mask) must land before T-122 and T-123 (bg/fg inpaint)Listed in prose but not in the dependency graph
T-041 (mutation API) must land before T-061, T-062, T-063, T-065, T-067, T-069, T-071 (all storyboard GUI panels)Critical; not shown
T-055 (runtime part 1) must land before T-115 (pre-publish playtest)Not shown
T-199 (game versions) must land before T-204 (saves scoped by version)Implied but not explicit
T-191 (cascade delete) must land before T-192 (soft-delete), T-196 (R2 orphan sweep)Ordering implied but not stated

6. Missing Context — Requires Real-Code Verification

Section titled “6. Missing Context — Requires Real-Code Verification”

The following roadmap claims cite specific files and line numbers. None can be confirmed without the FableForge codebase. Block execution of dependent tasks until each is verified.

ClaimTasks affected
CreateWizardPage.tsx exists as a dead mock, linked from routesT-001
StudioWizard.tsx is wired to Convex gameDraftsT-002, T-003
catch (e) { /* ignore */ } at generation.ts:166, faceExtraction.ts:74, router.ts:54T-006
vnGeneratePanels.ts:31 hardcodes "fal"T-009
games/studio/actions.ts:101 pins LLM_MODELS.gpt4o directlyT-013
FFScript schema version regex is /^0\.\d+\.\d+$/ and current version is "0.1.0"T-021, T-022
gameDrafts.beats is the current SSOT for beat data (not panels)T-029
processBeatJob routes to FAL hardcoded regardless of selectedProviderT-004
timeline-save.ts uses localStorage only (no Convex writes)T-206, T-207
BrowseClientPage.tsx is a stub (~6 KB placeholder, no real filtering)T-231
deleteGame at convex/games/mutations.ts:212–299 skips saves, characterAnchors, etc.T-191
importJobs table exists but no mutation is wiredT-197
VACE is video-only; Lustify is full-image, not regional inpaintT-121, T-122, T-123
poseReferenceImage param exists in generation.ts:87 but is silently ignoredT-135
activeLoras accepted but not loaded in workflowsT-131

These tasks appear under-estimated relative to their described scope.

TaskStated effortConcern
T-041 — FFScript mutation APIM (½–2 days)Twelve public methods + Immer internals + post-mutation revalidation + type exports. More realistically L (3–7 days).
T-046 — Linter engineMA pluggable rule engine with 10+ default rules is realistically L.
T-087 — Bidirectional GUI ↔ Code syncL (3–7 days)Real-time JSON patch application into Monaco while Monaco is live-edited is notoriously hard to get right without race conditions. Closer to XL with proper conflict handling.
T-129 — Cross-provider fallback routerLThree providers, per-attempt analytics, circuit breaker state — this is likely XL when combined with T-130.
T-151 — Music generation runtimeLSuno V5 + Stable Audio 2.0 + MusicGen fallback chain, per-scene cues, baking — XL given the audio pipeline complexity.
T-197 — Import-from-ZIP pipelineLZIP extract → Ren’Py parse → FFScript transpile → linter pass → wizard integration. Historically transpiler work is XL.
T-237 — Ren’Py export actionLRound-tripping a complex game format through Ren’Py’s Python DSL reliably is XL.

Section titled “8. Open Questions from §12 — Recommended Decisions”

The roadmap lists six open questions. Recommended answers to unblock implementation:

  1. Panel-per-beat or beat-per-panel? Start 1:1 at wizard time; allow many panels per beat only when the storyboard editor is in place (Phase 3). Hard-coding 1:1 in the compiler (T-023) simplifies Phase 1 substantially.

  2. Branching in comics? Permit it in the schema (T-021) but do not render it in the Panel Grid until Phase 6 (T-072 branch visualization). Comics with branches become “split pages” visually; VNs get a choice node.

  3. Which LLMs for which stages? Set defaults now to unblock T-013 and stop the policy violation:

    • Story outline: Claude 3.7 Sonnet (best long-context coherence)
    • Character voices / dialogue: Gemini 2.5 Flash (fast, cheap, vision-capable)
    • Cheap refinement / batch: DeepSeek V3 Hard-code these in selectModelForTask until cost telemetry (T-259) can drive dynamic selection.
  4. Creator compute pricing? Minimum viable: credits per model call (already implied by T-016 refund logic). Decide on credit price points before Phase 10 publish goes live.

  5. Minimum viable moderation before public publish? Auto-classification (T-224) + trusted-creator allowlist is the right call. Build the queue (T-223) first; open allowlist to beta testers only at first publish.

  6. Fork policy? Default: not forkable. Owner opts in per game. Implement at Phase 11 (T-200) with explicit forkable: boolean field on games table.


This replaces §11 of the roadmap. Tasks are ranked by: (unblocks most downstream) × (P0 safety risk) ÷ (effort). Tasks that overlap are grouped into delivery units.

Delivery Unit 1 — Foundation (Phases 0–1, ~2 weeks)

RankTask(s)Why first
1T-001 — Kill CreateWizardPage.tsxEliminates a live user trap; zero-risk change
2T-191 + T-193 + T-205 — Cascade delete, auth audit, siloing testsData safety before anything else; parallelizable with the rest of this unit
3T-005 + T-006 — Structured errors + remove silent catchesCan’t debug any later work without this
4T-004 — Wire selectedProvider end-to-endEvery generation in every later phase uses this
5T-013 — Route outline through selectModelForTaskAGENTS.md compliance; 1-line fix once code is open
6T-017 then T-003 — Idempotent processBeatJob then per-beat regen UICritical UX: users can’t recover from partial failures without this

Delivery Unit 2 — Panel type + compiler (Phase 1, ~1.5 weeks)

RankTask(s)Why next
7T-021 + T-031 — Panel schema + aspect ratio fieldSchema foundation; must be stable before anything else
8T-022 — Migration to v0.2Ships with T-021
9T-023 — Compiler emits panelsDraft pipeline starts producing panels
10T-025 + T-026 + T-027 — Panel TS types, CRUD mutations, Convex tableGUI can now read/write panels

Delivery Unit 3 — Mutation API + Linter (Phase 2, ~1.5 weeks)

RankTask(s)Why next
11T-041 + T-042 — Mutation API package + Immer internalsAll GUI edits in Phase 3 depend on this
12T-043 + T-051 — Post-mutation revalidation + forgiving validatorCorrectness guarantee before GUI uses mutations
13T-044 — JSON Patch undo/redoMandatory for any serious editor
14T-046 + T-047 + T-048 — Linter engine + wizard integration + lint-on-publishQuality gate; linter must exist before publish opens

Delivery Unit 4 — Storyboard core (Phase 3, ~3 weeks)

RankTask(s)Why next
15T-061 + T-062 — Panel Grid + insert-betweenPrimary authoring surface
16T-063 + T-074 — Panel Detail canvas + toolbarPer-panel editing unlocked
17T-064 + T-065 — Background and foreground layer editorsCore composition
18T-067 + T-069 + T-070 — Bubble tool + inline editor + speaker pickerDialogue authoring
19T-086 + T-087 — Monaco code view + bidirectional syncPower-user escape hatch; also the safest integration test of the mutation API
20T-076 + T-077 — Keyboard shortcuts + multi-select moveProductivity baseline

Delivery Unit 5 — Model stack + inpaint (Phase 5, ~3 weeks)

RankTask(s)Why next
21T-226 — Server-side age gateMust land before tier-2 generation goes live
22T-124 — SAM 2 auto-maskPrerequisite for T-122 and T-123
23T-121 — Flux Fill Dev inpaintingCore missing generation feature
24T-122 + T-123 — bg-only / fg-only inpaintTop-2 user pain points; unlocked by T-121 + T-124
25T-128 + T-031 UI — Resolution pickerReplaces hardcoded dims; quick win
26T-129 + T-130 — Cross-provider fallback router + circuit breakerProvider independence
27T-158 — Hot-swap model per panelUser control; trivial once T-129 exists

Delivery Unit 6 — Publish + Play (Phases 9–10, ~2 weeks)

RankTask(s)Why next
28T-055 (runtime part 1) + T-057 (save state) — Basic interpreter + save serializationPlaytest and cloud saves both depend on this
29T-206 + T-207 — Convex cloud save mutations + runtime writesCloses the localStorage-only save gap
30T-115 + T-116 + T-117 — Pre-publish playtest + checklist + unreachable branch checkNo broken games ship

What comes after: T-194 (global slugs), T-199 (game versions), T-231 (real marketplace), T-235 (reviews), T-237 (Ren’Py export), then Phases 12–14.


10. Summary of Changes from Original Roadmap

Section titled “10. Summary of Changes from Original Roadmap”
Change typeCount
Critical consistency errors requiring resolution before execution6
Redundant task pairs to merge or explicitly link5
Tasks moved to an earlier phase for safety4
Tasks downgraded from P04
Tasks deferred / pruned from MVP critical path17
Effort estimates revised upward7
Missing-context flags (require real-code verification)15
Open-question decisions recommended6

The critical path to a usable, safe, publishable MVP compresses to approximately 14 weeks of focused execution across Delivery Units 1–6 above, assuming the FableForge codebase is otherwise in the state the roadmap’s audit describes.



11. Post-Spec Cross-Check Findings (2026-04-23)

Section titled “11. Post-Spec Cross-Check Findings (2026-04-23)”

After producing the Panel schema spec, mutation API spec, and linter design spec, three additional pruning and scoping decisions emerged.

T-059 (dry-run symbolic executor) is largely subsumed by the linter. The linter’s default ff/flow/unreachable-node rule (part of T-046) performs a BFS from the start node and reports any unreachable panel. The ff/flow/infinite-loop rule adds cycle detection. Together these cover the functional requirement stated for T-059. Prune T-059 as a standalone task; fold its publish-gate requirement (T-117) into the linter’s publish integration (T-048).

T-035 through T-039 (individual linter rules) are already sub-items of T-046. The roadmap lists them as five separate tasks in Phase 1. They are default rules in the linter catalogue — not independent engineering efforts. Consolidate T-035–T-039 into T-046’s acceptance criteria. Remove them from the Phase 1 task count. This saves ~5 days of apparent task overhead that was never real.

T-041 mutation API covers 15+ methods, not 12. The spec expanded the surface to include updatePanel, updatePlacement, removePlacement, movePanelToScene, setBubbleStyle, setBubbleReadingOrder, and batch(). The batch() method directly implements the core logic needed by T-077 (multi-select move) and T-078 (bulk regenerate) — both reduce to doc.batch(label, fn) calls. Those tasks require UI wiring but no new mutation primitives.

Minor schema addition: the linter’s ff/background/missing-background rule needs a buildType: "placeholder" | "draft" | "published" field at the FFScript document root to distinguish authoring-time placeholder panels from publishable panels with missing backgrounds. Add this field to T-021’s schema and the v0.1 → v0.2 migration.

Updated total pruned task count: 19 (was 17; adds T-059, and the 5 linter sub-tasks T-035–T-039 as standalone items are collapsed into T-046).


Audit conducted by Claude (Anthropic) on 2026-04-23. FableForge codebase was not directly accessible; all findings are grounded in the roadmap document’s internal evidence. Real-code verification is required for all items in §6 before implementation begins.