cd /news/developer-tools/the-dailyprog-puzzle-safety-net · home topics developer-tools article
[ARTICLE · art-61353] src=blog.lvmbdv.dev ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

The dailyprog puzzle safety net

The dailyprog puzzle site now runs a nightly CI job that auto-generates a puzzle if tomorrow's is missing, using DeepSeek V4 Flash and validation gates, ensuring the site never goes dark. The workflow checks for an existing puzzle, generates one if absent, runs test suites, commits, and deploys, all with a two-hour lead time for human review.

read4 min views1 publishedJul 16, 2026
The dailyprog puzzle safety net
Image: source

dailyprog needs a new puzzle every day. I wrote the first few drafts by hand, then built a generator that writes them with an LLM and validates the output against real sandbox execution. The generator works, but it still needs someone to run it. Pick a pattern, kick off the script, review the result, commit. Fifteen minutes on a good day. More if the model gets stuck in a repair loop and I need to nudge it.

Some days I don’t have fifteen minutes. Some days I forget. Before last week, either of those meant the site went dark at midnight UTC and stayed dark until I woke up and fixed it. Now it doesn’t.

At 22:00 UTC every night, two hours before the puzzle day rolls over, a CI job runs on the Forgejo runner. It checks whether tomorrow’s puzzle exists in the catalogue. If it does, nothing happens. If it doesn’t, the job generates one, validates it, commits it, and deploys it. The site never goes dark.

The job is a single workflow file. The check step is four lines of bash:

TOMORROW=$(date -u -d '+1 day' +%Y-%m-%d)
if [ -f "workspaces/app/content/puzzles/$TOMORROW.json" ]; then
  echo "puzzle for $TOMORROW is already authored — nothing to do"
fi

If the file is missing, the rest of the job runs: install toolchain, install dependencies, call the same gen:puzzle

script I run manually. The model defaults to DeepSeek v4 Flash. Medium difficulty, no pattern hint. The diversity constraint (scan the last 7 puzzles’ technique tags, block repeats) keeps the model from producing three binary search puzzles in a row. It usually closes in 2 attempts.

The generation is the easy part. The interesting thing is what comes after.

The generator script only writes files to disk when it passes every gate: schema validation, reference solution against all test cases, brute-force collapse proof, technique diversity. That’s the first safety net. But the CI job runs a second one anyway. After the generator finishes, it fires the full catalogue test suite:

pnpm run check:ci
pnpm --filter @dailyprog/app exec vitest run lib/puzzles.test.ts lib/puzzle-quality.test.ts

puzzles.test.ts

loads every .solution.ts

file in the catalogue and runs the reference solution against every visible and hidden test case. If the generator produced a solution that doesn’t pass its own tests, this catches it. puzzle-quality.test.ts

runs the guardrails: no duplicate technique in the recent window, no back-to-back hard days, every language produces output within the runtime budget. These are the same tests that run on every push to main. The generated puzzle goes through them twice.

If the tests pass, the job commits as puzzle-bot and pushes straight to main:

feat: add puzzle 47 - staggered delivery
Auto-generated by the nightly safety-net workflow.
Co-Authored-By: DeepSeek V4 Flash <noreply@deepseek.com>

Forgejo skips CI on pushes made with the run’s own token (standard loop prevention), so the commit doesn’t trigger another build. The puzzle is in git but not on the site. One more step: the job POSTs to Forgejo’s API to dispatch the deploy workflow. The deploy workflow SSHes into the VPS, pulls the new commit, rebuilds the container image with --no-cache

, and brings it up. The new puzzle goes live about 10 minutes after generation started.

The two-hour lead time matters. I check the site most nights. If the model produced something weird (a puzzle where the English prompt is technically correct but the story doesn’t make sense, or one that passes every gate but just feels lazy), I have two hours to write a replacement. The safety net isn’t a substitute for human review. It’s a guarantee that the worst case is “a puzzle I didn’t author” rather than “no puzzle at all.”

The app doesn’t know any of this exists. It reads JSON files from content/puzzles/

. The CI runner lives on the same VPS as the site, as an unprivileged user with no special access. The Deepseek API key is a repo secret scoped to the workflow. If the runner goes down, the site still serves puzzles from whatever is already in the catalogue.

The manual path and the automatic path converge on the same checks. I author a puzzle, run the tests, commit, deploy. CI generates one, runs the same tests, commits, deploys. The tests don’t care who wrote the JSON. If CI can’t pass them, the puzzle doesn’t ship. If it can, the puzzle is safe to serve.

There’s no handoff. No separate “auto-generated” code path with weaker validation. No flag that marks a puzzle as machine-authored and lets it skip a gate. The safety net is just the manual workflow running unattended.

Most days I still write the puzzle myself. But the days I can’t, nobody notices :^)

── more in #developer-tools 4 stories · sorted by recency
── more on @dailyprog 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/the-dailyprog-puzzle…] indexed:0 read:4min 2026-07-16 ·