Context: I keep a small fleet of apps that share one template, Spernakit. Rolling a new template version out to every app in one pass is a “dance.”
An earlier template upgrade had unmounted the /api/v1/admin router. It had passed the entire smoke:qc chain
anyway, because the integration check scanned route barrels under
backend/src/routes/**/index.ts and this router lived in a flat module. So the check never saw it.
The file looked complete and no user could reach it. I had just written
Green Is Not Evidence about this exact kind of failure, which did not
improve my mood.
I found it while working through two template rollouts across eleven apps.
After clearing old public history and the last PowerShell entrypoints, I went back to the fleet. The July upgrade pass had caught the derived apps up to Spernakit 3.24 after a long break. This week I ran the process twice more. Monday took all eleven applications to v3.31.2. On Wednesday, seven of them moved again to v3.33.0 and four stayed behind.
I expected the template changes to cause most of the trouble. Nearly all of it was already sitting in the applications.
Docker
The first pass found seven branded Dockerfiles missing a required line:
COPY scripts/require-bun.ts scripts/
The template had it. The branded copies had drifted, and their image builds failed. Most also
carried stale template workspace entries in bun.lock, so a frozen install failed after
smoke:reset had already removed node_modules.
The second pass exposed eight apps with the same sixty-second readiness timeout. From outside the container they looked slow: the port accepted a connection and nothing answered.
The backend was rejecting security.backupEncryptionKey because it still held a placeholder. After
four tries, supervisord gave up. Nginx stayed alive and kept serving the closed backend socket.
Generating keys in the apps still carrying the placeholder fixed that. That was part of the second pass.
Four stayed behind
I released seven and stopped on four rather than trying to repair them automatically. One had a schema assertion, a bundle-budget failure, and a pile of unused exports. Another was missing named domain constraints. The third had an unused wrapper and an import Knip could not resolve. The last had crossed the file-size limits in several places and still carried an old set of theme files.
Those theme files belonged to a BBS-and-terminal experiment with no route into the product. The setting had disappeared from Spernakit several releases earlier. I considered wiring it back in, then deleted it and amended the feature specification in the same commit.
The unmounted admin router came out of the rest of that same report. The Knip problem was smaller:
it resolved a bare scripts/... import relative to the script directory and went looking for
scripts/scripts/generate-config-schema.ts. Resolving from the repository root fixed the report
without changing the working script.
I cleared the findings in two of the four on Wednesday morning. The other two still had their own blockers, and all four stayed unreleased.
What the rebuilds became
Two weeks earlier, six Spernakit applications had been recreated from fresh scaffolds. A seventh rebuild used a separate scaffold. The two dances kept the six template foundations current.
Five are still maintained scaffolds with product blueprints and feature backlogs waiting for implementation. The sixth had already started implementing its timeline core and event exploration on July 18. The seventh, the play-by-mail game, had already opted out of the Spernakit shell, and on July 31 it went further - I recast it as a game definition for a separate PBM platform, so the engine and the individual game rules are separate things now. I think that is the right home for it. It is still not a playable game.
I moved on to template and aidd work before starting the five scaffolds’ feature queues. The blueprints are still there when I get back to them.