Inspiration

I built Drift Off alone, first as a Snapchat Web Lens (a small web game that runs inside Snapchat). It's a one-touch game about falling asleep. Hold your finger down to sink toward sleep, and lift it before a worry touches you. Get jolted awake three times and the night is lost.

Releases were all by hand. I ran the playtest simulator, read the numbers by eye, built, zipped, checked the zip and uploaded. No CI, no code review, no security scanning, no public web version. The worst bug in a game like this never shows up in ordinary tests, because one changed number can make it unwinnable.

So I wanted a night shift. The idea is that I file an issue before bed and wake up to a merge request I can approve in one look.

What it does

Drift Off ships through a supervised loop on GitLab. A human defines the issue and approves the outcome. Agents and pipelines do the work in between.

① Plan. I file an issue from the Night shift template and assign it to the night shift flow.

② Create. The night shift flow, a custom GitLab Duo flow, posts a plan on the issue, changes the code, runs the bot playtest and the license gate itself, opens a merge request and reports back.

③ Verify, secure, govern and package. The pipeline runs the bot playtest against the target branch, the license gate, SAST, secret detection, dependency scanning, the web build and the lens zip check. On GitLab Premium or higher, each merge request also gets a playable preview.

④ Review. GitLab Duo's Code Review flow reviews the merge request with rules kept in the repo.

⑤ Approve. I read the playtest table and the preview, then merge. That's the one human approval.

⑥ Release and monitor. The pipeline deploys to GitLab Pages, stores the lens zip in the package registry, creates a release and checks that the live site serves the exact bytes that were tested. A six-hour monitoring schedule is configured and was verified with a manual run. It is left inactive outside demonstrations to avoid unattended resource use.

How we built it

The game is about 2,780 lines of plain JavaScript, and its lens zip is 22.4 KB. The rest is the machinery around it.

The core is a bot playtest. Bots at three skill levels (good, average and poor), each with the tutorial on and off, play 300 seeded nights per group, 1,800 nights on every change. In a merge request the same nights replay on the target branch for a before and after view. There are 19 checks, plus a save compatibility check in merge requests, and GitLab reads the results as JUnit and metrics reports.

The pipeline has verify, test, package, release and monitor stages and uses GitLab's security scanning templates. Agents follow project rules in AGENTS.md, and the review flow follows .gitlab/duo/mr-review-instructions.yaml.

Everything that ships to players is MIT, and exactly one dependency ships. The 125 build tools use six licenses, all approved by the Open Source Initiative, and the license gate enforces this on every change.

Challenges we ran into

The custom flow initially ended without output. Supplying the project ID explicitly and using authenticated glab through run_command produced a complete run. The design keeps human approval before merge on purpose, and AGENTS.md tells agents never to merge. Automatic failed-pipeline repair remains an optional extension and is not claimed as demonstrated.

Balance was the next puzzle. A gate that fails on every tweak is useless, so the playtest checks ranges that describe the design, not exact numbers. Doubling jolt from 11 to 22 stays inside the ranges and passes.

Saves were sneakier. Saved progress refers to each worry by its position in a list, so inserting a worry in the middle would break old saves. The save compatibility check catches it with a message like "moved from s1 to s2", and adding the worry at the end passes.

Accomplishments that we're proud of

The gates are real, and I measured them. With the tutorial off, good bots fall asleep on 98% of nights with a median of 52.4 seconds, average bots on 90% at 65.9 seconds and poor bots on 25% at 94.3 seconds.

Then I broke it on purpose. Changing maxWakes from 3 to 1 drops good bots to 74%, average bots to 40% and poor bots to 5%. Six checks fail in the local negative test. The same balance gate is used in CI to block a failed change before release.

The lens zip passes all 12 platform checks. The first production pipeline passed its exact-build live check. The workflow touches all nine stages, from plan to govern.

Verified on October 26, 2026: the custom night shift completed session 10076089, posted a plan and summary on issue #3, ran both gates, and opened MR !2. The standard Developer Flow also implemented a real CI dependency-order fix in MR !1. Both MR pipelines passed. After explicit human approval, both MRs were merged, and production pipeline 2991272673 passed all 11 jobs, including the exact-build live check. Duo Code Review approved the CI fix and provided a prompt improvement on MR !2, which was addressed. The code, merge requests and CI evidence are public.

What we learned

Agents became useful once they sat between hard gates. The night shift flow can write a change and open a merge request, and the same bot playtest, license gate and scans judge its work exactly like mine.

The human part can be small. My job comes down to saying what I want in an issue and approving the result with a merge. The merge request already carries the playtest table, so approving means reading one table, plus the preview on Premium.

Bots make good balance testers. They can't tell me whether the game is fun, but on every change they flag it when one number makes the game unwinnable.

What's next for Drift Off

Next I want to test bounded automatic repair on deliberately failing changes, with clear cost limits and human approval before release.

I also plan to package the bot playtest gate so other small web game developers, the ones shipping to web lenses or itch.io, can drop it into their own projects. Their games have the same problem. Broken balance doesn't show up in ordinary tests.

Built With

Share this project:

Updates

Submission history