Work / Games & Simulation
BLACKSITE: NULL
Co-op extraction-horror shooter for Roblox: 173 strict Luau modules from parallel AI agents, gated by written contracts.
- Luau (strict mode)
- Roblox Studio
- Rojo
- Aftman
- DataStoreService
- Node.js (conformance tooling)
- Claude Code workflows
TL;DR
- I directed a contract-first, multi-agent build of a 1–4 player co-op extraction-horror shooter for Roblox: 5 Claude Code workflows and 57 agent sessions produced 173 strict-mode Luau modules over four days.
- The interfaces came before the code. A dependency-free checker diffed what each contract promised against what each module exported, and gated the build from 39 failing modules to a clean pass in about 40 minutes.
- Then I installed Roblox Studio and played it, and my bug reports drove the next round of fixes.
The problem
Dozens of parallel AI agent sessions will each write plausible code. The question is whether it composes: whether module A calls module B the way B actually works. Without a shared contract, parallel agents build against their own guesses, and the game only fails when you finally press Play.
What I built
I set the scope, down to a 100-level campaign across 5 maps with a boss every 20th level, then directed the build.
- Contracts first. 2,050 lines of normative contracts pin the project layout, the file manifest, the network contract and 282 declared members across 56 module APIs. They assign files to named agents, so parallel sessions build against the same surfaces. House rules: strict mode on line one, one return value per file, no external packages.
- Conformance gate. A dependency-free Node checker parses every declared member in the contracts and diffs it against what each file exports. Its header states its own limit: methods on instances can’t be attributed to a file, so they are counted as unchecked rather than silently passed. A second checker catches missing requires, unbalanced blocks and leftover stubs.
- Server-authoritative combat. The client seeds shotgun spread from a single-use shot ID; the server re-derives the pellets, checks fire rate and aim, and rewinds enemies through 20 Hz ring-buffer lag compensation that interpolates but never extrapolates.
- Seeded maps. A depth-first spanning walk with backtracking, a uniform grid that keeps each overlap test constant-time in the number of placed rooms, and a loop pass that turns leftover doorways into flanking routes.
- Director. Spends a threat budget on authored wave shapes and rejects any spawn point a player could see.
- Persistence and store. Profiles persist through a DataStore layer that writes only through
UpdateAsync, with migrations. The store checks its catalogue at boot and fails closed if any item could touch a stat, so nothing for sale can be pay-to-win.
Key decisions
- Decision: write the interfaces before the code. Why: parallel agents need one shared surface to build against. Trade-off: the contracts are 2,000 lines to write and keep current.
- Decision: an automated conformance gate, not code review, decides when the modules fit. Why: no human can review 126,000 lines in four days. Trade-off: it checks that the pieces link up, not that the game plays.
- Decision: the store fails closed. Why: a monetization bug that sells a stat is worse than a store that doesn’t open. Trade-off: one bad catalogue entry takes the whole store down until it’s fixed.
The hard part
Making dozens of parallel agent sessions compose into one runnable game. The conformance gate’s first run reported 39 of 52 declared modules out of contract. Parallel workflows walked the count down (36, 30, 27, 26, 23, 17, 16, 11, 9, 5, 4, 2, 1) to “PASS — every declared module meets its contract” about 40 minutes later. The final runs covered 56 modules and 282 members, all conformant, with 10 instance methods reported as unchecked.
The second half is where static checks run out. A clean conformance diff shows the modules link up; only a Studio session shows whether the game plays. My first session surfaced interaction menus that didn’t respond, a hold-E deploy prompt that did nothing, and flickering, overlapping textures. I wrote each one up for the agents, asked for a gated loading screen so players never see a half-built hub, and gave the agent computer-use access to Studio so it could reproduce the bugs itself. It traced the hold-E failure to a lobby keybind that swallowed E ahead of the shared interaction system, and rerouted it.
Results
- 173 strict-mode Luau modules, 126,861 lines, zero external packages.
- A conformance gate that took the build from 39 failing modules to a full pass, and ended at 282 of 282 declared members conformant.
- One of five sites playable; menu clicks and textures are still on the punch list.
What I’d do next
- Re-test the hold-E fix and the menus by hand, then clear the rest of the punch list.
- Real art and a first multiplayer session beyond local Studio tests.
- Open the other four sites, each with the mechanic it is designed to introduce.
Links
- Code: local, walkthrough on request.
- The same agent-directed approach, with full git history: EXIT LIQUIDITY
Verified numbers
| Metric | Value | Source |
|---|---|---|
| Strict-mode Luau modules from parallel agent sessions (126,861 lines, 0 external packages) | 173 | local: BLACKSITE project, src/**/*.luau |
| Lines of normative interface contracts written before the code | 2,050 | local: BLACKSITE project, docs/CONTRACT*.md |
| Declared module members checked by the conformance gate, all conformant | 282 | local: BLACKSITE project, tools/contract-check.mjs |
| Campaign scope (1 of 5 sites playable so far) | 100 levels · 5 maps · 5 bosses | local: BLACKSITE project, src/shared/Config/Campaign.luau:31-33 |