Kapitan Logbook
How TinkerDice is being built, in the open — the captain’s log.
Selection Over Repair — Generating Multiple Candidates and Picking the Best
Why we stopped trying to fix broken game graphs and started generating multiple candidates instead — letting the engine pick the winner.
Descriptive, Prescriptive, Historical — Adding Modality Labels to Project Documentation
How we stopped the docs-from-reality drift by labeling every document with its modality — and defined clear arbitration rules for when they disagree.
Devlog #0 — setting up the new site
A placeholder devlog entry so the content engine builds. Replace with real notes.
Game-Logic IR — Atomic Primitives Instead of Free-Form JavaScript
After zero playable games, we diagnosed the real problem: asking LLMs to write programs is the wrong abstraction. Here's what we're building instead.
The .td File — A Portable Game Format for Sharing and Distribution
How we defined a portable file format for Tinker Dice games — so you can save a game, send it to a friend, and play on any instance.
Event-Sourced Task Orchestrator — Killing the Two-Truths Problem
How we replaced two inconsistent sources of task state with an event-sourced orchestrator — and built parallel workers for independent tasks.
Splitting the Session Layer — From One God Plugin to Four Clean Modules
How we decomposed a 340-line plugin with 8 responsibilities into 4 focused modules — and why we did it before adding more features.
One Theme, One Canvas — Unifying Four Design Systems Into One
How we collapsed four incompatible design systems and three ReactFlow wrappers into a single theme provider and one universal GraphCanvas.
Loom Comes to Life — Visualization and Human-in-the-Loop Controls
Why we pulled Loom visualization and HITL controls out of the parking lot — and built the two-graph canvas the Captain always wanted.
Reviving Loom — The Second Take on Visualization and HITL
A companion ADR to 021: pulling LoomGraphCanvas and HITL controls out of parked, with explicit scope boundaries.
Prompt Lab — Building a Debugging Workbench Before Building a Product
Why we stopped rewriting the editor and started building a prompt debugging lab instead — and what that says about priorities.
Loom — Decomposing the Monolithic Builder Into a Pipeline of Specialists
Why we replaced one overloaded AI agent with five specialized roles — and named the whole thing after a weaving machine.
Splitting QA in Two — PipelineFSM and the Rules vs Graph Findings Separation
Why we separated 'the rules are wrong' from 'the graph is wrong' — and built a state machine to orchestrate the difference.
Surgery Instead of Sledgehammer — The graph_patch Tool
Why we gave AI a scalpel instead of a wrecking ball for fixing game graphs — and why JSON Patch wasn't the answer.
One Source of Truth Per Plugin — Killing the Three-File Desync
How we collapsed manifest.ts, definition.ts, and core.ts into a single SSOT descriptor — and eliminated an entire class of AI bugs.
Playing Games That Don't Exist Yet — Headless Runner and Inspector QA
How we built a headless game engine that runs test matches in memory — so the AI can verify its own work before a human ever sees it.
Rules Before Code — Splitting Game Design from Graph Assembly
Why we separated the AI pipeline into Designer (human-in-the-loop) and Builder (compiler) — and introduced Rules-Markdown as the bridge.
Game-First UX — From Web Forms to Tactile Interaction
Why we ripped out the Actions tab and made every game object a point of interaction.
JavaScript Nodes in ActionFlow — Giving AI a Escape Hatch
Why we let AI write JavaScript inside game graphs — and the controlled context that keeps it from blowing up.
The Server Becomes the Mediator — AI Pipeline Through MemoDb and SSE
How we restructured the AI generation pipeline so the server is the single writer, the AI is a background worker, and the editor just watches.
Who Owns the AI? — Expanding QC's Domain to Cover ai-service
When ai-service moved into the main repo, it needed an owner. QC was the natural fit.
Reasoning Models Are Different — Adapting Our Pipeline for DeepSeek Reasoner
What changed when we switched to a model that thinks before it speaks — and why we had to disable half our tool chain.
No More Direct Database Writes — Server Actions Through MemoDb Plugin
How we closed a security hole by routing every data mutation through server-side socket actions.
Killing the HTTP Roundtrip Loop — How AI Gateway Took Over Tool Calls
Why we moved AI tool resolution from the client to a server-side gateway — and cut the latency chain from N roundtrips to one.
The Plugin That Must Not Exist — Why We Banned Game-Specific Plugins
TurtlePlugin was the anti-pattern that taught us: plugins are universal mechanics, never game-specific hacks.
Plugins That Can Vanish Without a Trace — The Manifest/Definition/Core/UI Split
How we designed a plugin system where no part of the codebase knows any plugin by name — and why that matters.
Path C — AI Creates, Telegram Plays
The product bet: AI generates tabletop games, humans play them through a Telegram WebApp. Here's why.
One Library to Rule Them All — How MemoDb Became Our Data Backbone
Why we stopped juggling REST endpoints and WebSocket events — and replaced both with a single in-memory store that syncs itself.
Game Logic as JSON — The GraphDoc DSL and Visual Programming Through ActionFlow
Why we describe entire board games as state graphs in JSON — and how AI learned to generate them from plain text.
Break Everything — Why We Don't Have Backward Compatibility
The liberating (and terrifying) decision to never maintain backward compatibility during the design phase.