devto 2026-10-02 원문 보기 ↗
This is a submission for the Sanity Challenge, Path Two: Vibe-Code Something Strange
The Bureau of Imaginary Permits: a pixel-art inspection-booth game about bureaucracy for things that don't exist, running on real Sanity Workflows.
You take the window. Applicants step up one at a time, wanting a Licence to Whistle on Tuesdays, a Permit to Keep a Small Dragon (Indoor), or the Deed to a Medium-Sized Cloud. They slide over their papers: an application, a Citizen Card with a photo, sometimes a licence they already hold.
Every file arrives already passed by Clerk Third Class, an AI. Its memo sits on your desk: "Named dragon, licensed puddle on file, fire plan mentions water. In order." The clerk is tired, though. The dragon is 41 cm, and the Rulebook says 35. You pull out the stamp tray, slam DENIED into the box, and hand the papers back.
That is the Workflows bonus prompt played straight: "an agent can move a draft forward and a person can approve it." Here the agent always moves it forward, and the person is the only thing standing between a forged Citizen Card and a Licence to Look Up.
Behind the window there is a real citizen side. Anyone can file a permit:
Play: https://bureau-of-imaginary-permits.vercel.app/shift (no account; seven applicants a day, two days)
The citizen side: a real file that went through both AIs and two human signatures, with the GROQ rule behind every move.
A pixel-art inspection-booth game about bureaucracy for things that don't exist, built on Sanity Workflows.
Play: https://bureau-of-imaginary-permits.vercel.app/shift (no account needed)
You take the window. Applicants step up one by one, wanting a Licence to Whistle on Tuesdays, a Permit to Keep a Small Dragon (Indoor), or the Deed to a Medium-Sized Cloud. Each hands over a Citizen Card, an application, and sometimes a licence they already hold.
The AI clerk has already passed every file. The clerk is tired. Your job is to compare the papers against the Rulebook and the day's bulletin, stamp APPROVED or DENIED, and hand them back. Wrong stamps print a citation. Day 2 changes the rules.
There is also a real citizen side. Anyone can file a permit: a real AI clerk (Gemini) reads it, a second AI (the Ministry of Weather) rules on anything in the sky, and human…
IDE: Claude Code (Opus 5.5) in a Windows terminal. I typed very little, and that's the honest shape of this build. Claude wrote, ran and tested everything, and kept a BUILD-LOG.md as it went. This section comes from that log.
That's it. Everything else below is what an agent did with those sentences, including where it went wrong.
The first build was a tasteful government-forms site: paper colours, a serif, rubber-stamp CSS. It worked end to end, but it looked like every other "nice" AI-built site. That was my second "too vibecoded" across two challenge entries, so the brief became: commit to a world.
Claude's first plan was to model the process itself, with a workflow type holding stages[] and transitions[]. Before writing it, it followed the "Workflows" link in the challenge post and found @sanity/workflow-engine (early access, on npm):
sanity.workflow.instance with its stage, fields and full history.The hand-rolled schema was dropped. There are now four chains, all data:
| Chain | Steps |
|---|---|
express-permit |
AI clerk only |
standard-permit |
AI clerk, then one human stamp |
sky-permit |
AI clerk, Ministry of Weather AI, Under-Secretary, Minister |
booth-inspection |
Straight to the window: the game |
Starting a shift turns the day's scripted case documents into real applications, each governed by a booth-inspection instance. Your stamp is a real fireAction. The server then scores it from the decision the engine recorded on the instance, checked against case.truth. The browser never reports its own score. Day sheets are shift documents, which is the leaderboard.
Honesty note: the clerk memos on scripted applicants are authored, not generated. Every file at the window arrives "passed" because that's the premise. If the real clerk saw those files, it would reject them, and they'd never reach you. The citizen side uses the real AI clerk.
denied stage that no transition could reach, and sanity-workflows deploy --check refuses that.After the fix, it quotes the answer that fails ("'Any time she fancies' fails the rule…") and accepts a correct reply.
windowDecision is declared on the stage, so it lives on the stage entry, not the instance's fields. The first scripted shift threw "The stamp was not recorded" until that was fixed.after() while you read the bulletin. A stamp takes about 3.5 s on the server, so the animation and sound fire at once and the citation prints when the verdict lands.started ref fixed it./v9/projects/… into a Windows path, so vercel api silently created the project with default settings. A shell heredoc also choked on curly apostrophes in Day 2's dialogue.steps(), so it moves like sprites.Citizen files that reach a human desk land in the Stamp Desk, a React app deployed into the Sanity dashboard and built on @sanity/workflow-sdk:
useWorkflowInstances({filter: {stage: 'stamping'}}) is the live in-tray.useWorkflowSession drives one file. Its evaluation decides whether the stamp buttons are enabled.I checked a real stamp on the instance. The approve row is signed by my own Sanity user with executionContext: {kind: "sdk", runtime: "browser"}. The website's server token signs its rows as bureau-web. The move to issued was committed by the same browser session: the engine runs the cascade inside fireAction, so a human stamp needs no server.
e23lrcxv
production: departments, forms, permit types, applications, scripted applicants, bulletins, shifts.workflows: the engine's definitions and instances. Their dotted IDs keep them out of anonymous reads, so the site renders them on How it works.truth field is on those documents too. Play first.permitType: requirements[], each with a clerkCheck rule (the Rulebook); prerequisites[] pointing to other permit types; the forms[] the clerk may request; and workflow naming its chain.case: the papers handed over (cards and licences with photo seeds), the authored clerk memo, truth and reason.bulletin: the day's rules and in-game date.shift: results written only by the server.application: holds answers and agent memos. Its progress lives in the workflow instance.