Counting games stopped being a useful metric
Early in a puzzle collection it is easy to measure progress by counting engines, folders or catalogue cards. That stops working once the games genuinely diverge. A simple Sudoku and a Dots and Boxes match against a CPU may occupy one card each, but the contracts they need are different. One must prove a unique solution; the other must preserve extra turns and record win, loss or draw.
The latest changes forced a different view of Blupoli Puzzles. Logic Matrix and Zebra Grid introduced candidate matrices and relational generation. Dots and Boxes introduced CPU search. Numberlink grew to 8×8, 10×10, 12×12 and 15×15. Streaks evolved from a daily-challenge counter into a complete analytics destination. All of that made a more important question visible: what does it mean for a game to be genuinely finished inside the platform?
Logic Matrix and Zebra Grid: similar foundations, different games
The starting point looked reusable: both games could share a matrix of categories, positions and candidates. Reusing the board model made sense. Reusing the clue language did not. Zebra Grid was meant to handle broad relationships on large matrices. Logic Matrix needed a much more compact graphical language with a small set of horizontal and vertical clues.
That forced a clearer boundary between shared foundations and game-specific behaviour. Zebra Grid expanded to 6×6, 8×8, 10×10 and 12×12 and moved clues into a desktop side column so they would not shrink the board. Logic Matrix stayed at 4×4 through 7×7 and separated horizontal and vertical clue groups. The code could share concepts while the interface respected each puzzle's rhythm.
Difficulty exposed an even deeper difference. Counting clues was not enough. Two boards with the same clue count can feel completely different when one is dominated by direct relations and the other requires chained “between”, negative and adjacency reasoning. Tests therefore moved toward structural difficulty rather than raw quantity.
“Can generate a board” is not the same as “generates a good puzzle”
Logic Matrix and Zebra Grid reinforced a rule that had already become important elsewhere: producing a known solution is only the beginning. Every clue must then be checked against that solution, a logical solver must finish without guessing, and a second valid solution must not exist.
The contract is explicit in tests. A fixed seed must produce deterministic output. The logical solver must complete. Solution counting must return exactly one. Logic Matrix also restricts visible clue families to the intended design; an internal relation useful during generation does not automatically belong in the player-facing clue set.
This distinction between an engine that can produce boards and an engine that can produce publishable games has become one of the project's most important ideas. It prevents randomness or superficial validation from masquerading as quality.
Numberlink exposed a different kind of boundary
Numberlink already worked, but the smaller boards no longer represented the desired experience. Moving to 8×8, 10×10, 12×12 and 15×15 changed the problem. Generation still had to complete reliably, difficulty bands still had to remain meaningful and startup could not point at a size that was no longer supported.
That final detail caused a revealing regression: after the size expansion, the default still referenced an older configuration. The generator could be correct and heavily tested yet the game could fail before play because configuration and catalogue were out of sync. The fix included a dedicated regression test so startup size became part of the contract.
It is a good reminder that platform verification must include the boring connections too. Testing only the sophisticated algorithm is not enough.
Dots and Boxes broke the assumption that every game is “solved”
Most previous engines ended in a solved state. Dots and Boxes does not. It ends in a win, loss or draw. Completing a box also keeps the same player's turn, so an AI that blindly alternated player after every edge would misunderstand the game even if the board rendered perfectly.
The engine now exposes four CPU levels. Stronger levels use alpha-beta search, chain and risk evaluation and larger search budgets. Tests cover easy-to-break invariants: captures preserve the current player, one edge may close two boxes and advanced search keeps tactical handout alternatives.
The platform consequence mattered even more. Shared results had to distinguish puzzle completion from competitive outcomes. A win can count as successful activity; a loss or draw must still be recorded without pretending it is equivalent to solving a puzzle.
A shared result began connecting games that used to finish alone
With a small set of independent engines, each one can display its own completion message and appear complete. Progress, statistics, streaks and daily challenges make that freedom expensive. The platform needs a uniform way to know when a session starts, when it ends, what the outcome was and which details belong to that result.
The result-coverage test scans every game whose status is available. Native puzzle engines must reach markSolved() or the shared solved callback. Competitive games must report through markCompetitiveResult(). The shared host also creates and abandons tracked sessions explicitly.
This kind of test does not improve one board. It improves the platform by turning an informal convention into a verifiable requirement.
Streaks stopped being a small widget
Streaks began around daily challenges, but the product needed a wider notion of activity. The feature evolved into full-screen analytics with calendar views, trends, heatmap, per-game breakdown and run history. It then moved into primary navigation and its semantics were corrected so ordinary completed games also counted.
The competitive distinction mattered again. A CPU win counts; a loss or draw should not inflate a success streak. Without a shared result model, that rule would need special handling inside every competitive engine.
The streak evolution is a good example of a supposedly visual feature pressuring architecture. The moment you want to aggregate activity across dozens of games is the moment you discover whether those games speak the same language.
The shared interface had to grow as well
New games challenged visual assumptions that seemed settled. Logic Matrix and Zebra Grid showed that text and board sizing could not remain hidden in local exceptions. A number inside a clue cannot be half the size of its icon and still function as information. A candidate matrix cannot shrink into decoration merely to fit beside a text column.
The answer was not to make every game identical. It was to strengthen a common base while letting each engine use space according to its nature. Zebra Grid can dedicate a desktop column to clues; Logic Matrix uses separate clue zones; Numberlink prioritises a large board. Mobile still needs readable touch targets and a consistent hierarchy across all of them.
Publishing a game also means documenting it
This Blog review exposed another inconsistency: six games marked available had no dedicated article. They were not development placeholders. Balance Loop, Battleship, Takuzu, Dots and Boxes, Logic Matrix and Zebra Grid were already playable while the editorial layer had not caught up.
The fix is not only six new pages. The relationship should become a gate: when a game becomes available, an associated guide must exist. Games marked coming-soon stay out. That mirrors the real product state and avoids confusing backlog with public content.
It is the same pattern seen in generation and results: a useful expectation stops depending on human memory and becomes testable.
The self-hosted runner is part of the product even when users never see it
As generation tests, E2E coverage and automations expanded, the runner stopped being incidental infrastructure. Overnight connectivity failures required network diagnosis, machine hardening and health tooling without turning every small change into a permanently noisy workflow.
The goal is not more workflows. It is confidence in the workflows that exist. A pull request waiting indefinitely for a runner does not provide a quality guarantee; it blocks the system meant to provide one.
The lesson matches the rest of the project: verification has value only when the verification system itself is reliable.
What actually changed
From the outside, new games, sizes, streaks and screens appeared. Internally, the larger change is that there is less room for an engine to be an island. Availability, localisation, onboarding, results, persistence, responsive behaviour, difficulty, unique-solution proof, Blog coverage and CI now form a set of contracts around a game.
That raises the bar for publishing something new, but lowers the cost of maintaining it. When requirements live in tests and sources of truth, there is less need to remember how thirty different engines were supposed to behave.
The next interesting problem is simplification
Growth has also accumulated scripts and publication layers from different eras of the project. The build chain now contains too many successive normalisation and repair stages. With the important contracts becoming clearer, the next step should not be another patch layer for every exception. It should be removing duplication and shortening the path from source to verification to deployment.
The paradox is healthy: after adding a lot of capability, the next job is reducing accidental complexity. The platform can keep expanding if a new game mostly contributes its own logic and inherits everything else.
A stricter definition of “finished”
A finished puzzle is no longer a board that opens and can be completed once. It should work on mobile and desktop, have clear controls, generate valid games, prove uniqueness when relevant, separate difficulty bands, persist state, report a shared result, integrate with progress, be localised and have coherent public documentation.
Future games will not all need identical pieces. A competitive game does not have a unique solution; a static puzzle may not generate anything. The important part is making those differences explicit so the platform knows which contract applies to each mode.
That is the change I find most interesting about this stage. Blupoli Puzzles is moving from a collection of implementations toward a system. The games remain the centre, but each one now arrives with tests, data and conventions that mean the next game does not have to start from zero.
Publishing started to need an explicit state model
Another consequence of this growth has been a clearer distinction between “exists in the repository” and “is published”. The games/ directory contains both available titles and work still in development. If an editorial audit simply loops over every game.json, it starts demanding public articles for prototypes that should not yet be presented as releases.
The useful criterion is status: available. That property already participates in other platform checks and can now define which games require public guides as well. The distinction sounds small, but it prevents the technical repository from accidentally becoming the editorial catalogue.
It also preserves freedom for future work. A manifest, test or engine skeleton can exist without the system treating it as launched. Changing a game to available becomes an explicit act with consequences: catalogue visibility, progress integration, result coverage and documentation.
The six editorial gaps showed why a gate matters
The audit found Balance Loop, Battleship, Takuzu, Dots and Boxes, Logic Matrix and Zebra Grid available without dedicated articles. The immediate reaction could have been to write six pages and consider the problem solved. That would have fixed the symptom while leaving the cause intact: nothing connected game availability to editorial coverage.
The new test scans published games and requires both Spanish and English source guides. coming-soon titles are ignored. It is a small test, but it matches the philosophy that has been spreading across the repository: if an expectation matters and can be verified deterministically, it should not live only in someone's memory.
It also makes documentation part of the definition of done. A game may be technically playable and still be poorly integrated if there is no clear explanation of its rules, difficulty or distinctive behaviour.
Blog and Devlog need different jobs
The six new game articles belong in the Blog because they are written for people who want to understand and play those puzzles. They explain rules, strategy, difficulty and player-facing implementation choices. They do not need to reproduce every internal iteration that produced the final experience.
This piece belongs in the Devlog because the interesting subject is the process: several apparently unrelated changes kept exposing the same architectural and product problem. Keeping the formats distinct prevents the Blog from becoming a changelog and the Devlog from repeating game manuals.
The separation improves internal linking too. A game guide can point to technical backstory when useful, while the Devlog can lead readers to concrete playable examples without forcing implementation detail into the learning path.
The cost of layered fixes
Development speed has revealed another pattern: the build contains many generations of normalisation, localisation, enrichment and repair steps created at different points in the project. Most had a reasonable reason when introduced, but together they make a simple editorial or catalogue change travel through too many phases before becoming final output.
This resembles the engine problem before common contracts existed. When every issue is solved locally, complexity grows by accumulation. Eventually simplifying the path creates more value than adding another layer.
The cleanup should not remove deterministic verification that protects real behaviour. Route generation, syntax validation, translation checks, solution proof and sitemap creation remain software jobs. What deserves scrutiny are chains that effectively perform “normalise, patch, normalise again” because several generations of editorial architecture now overlap.
What should be automated and what still needs editorial judgement
Recent work has clarified a useful boundary. Puzzle uniqueness, article existence, syntax validity and translation completeness are binary conditions a machine can check. Whether an explanation flows well, whether a story deserves publication or whether an infographic actually teaches something still requires editorial judgement.
Treating the second category like the first produces technically compliant but mediocre content. Leaving the first category to human memory creates preventable regressions. The system works best when each layer handles the kind of decision it is good at.
The Blog and Devlog skills reflect this separation: they define editorial standards and review loops, while scripts handle metadata, routes, localisation and technical gates. The goal is not substitution but complementarity.
Difficulty tests matter more as the catalogue grows
With a few games, badly calibrated difficulty can be noticed by manual play. With many engines, sizes and seeds, that approach does not scale. Structural tests in Logic Matrix, Zebra Grid and Numberlink do not replace human experience, but they provide a barrier against obvious regressions.
If Expert starts using the same proportion of direct clues as Easy, or a size expansion destroys a known quality threshold, a test can flag the change before release. Human playtesting still matters afterwards, but it no longer starts from zero.
The useful direction is to combine reproducible metrics with judgement. A solver score is not “true human difficulty”, and one subjective impression is not enough to guarantee a stable progression across hundreds of generated games.
The platform is developing invariants of its own
An invariant is something that should remain true even when implementation changes. Blupoli Puzzles now has several emerging examples: every available game must report a result; generated puzzles that require uniqueness must prove it; difficulty bands should preserve meaningful ordering; public routes must localise correctly; available games should have source-language editorial coverage.
These invariants matter more than many internal details because they make refactoring safer. Algorithms, components and directory structures can change while the contracts continue to pass.
The larger the catalogue becomes, the more valuable this layer is. The project depends less on remembering historical quirks of individual engines and more on explicit platform rules.
A better way to decide when an iteration is finished
Agent-assisted development makes it easy to keep improving indefinitely because another possible refinement is always visible. Verifiable contracts provide a stopping point: rules work, generation passes, difficulty behaves, responsive layouts are usable, results report correctly, localisation exists, documentation is present and CI is green. Improvements can continue later, but fundamental integration is complete.
This does not reduce quality to a checklist. Visual review and actual play remain essential. It simply prevents “looks finished” from replacing concrete evidence.
The same applies to editorial work. An article needs both languages, integration in its index, coherent metadata and a clean build before it makes sense to judge whether the story itself is worth publishing.
What this stage leaves behind
The most important outcome is not a feature list. It is that the next game can inherit more of the platform: shell, results, progress, streaks, onboarding, localisation, responsive patterns and gates. The more of that foundation is reusable, the more time can be spent on what actually makes a new puzzle distinctive.
It also leaves a clearer list of debt worth reducing: too many build phases, editorial conventions still distributed across several layers and systems that began as tactical patches but now deserve consolidation. That cleanup is easier precisely because the essential contracts are becoming explicit.
The ambition is not for every game to share the same internal code. It is for every game to share expectations about quality and product behaviour. An engine can be completely different inside and still belong to the same platform outside.
Editorial coverage is now another platform contract
The most useful part of adding the six missing guides is not the number of pages. It is the fact that editorial coverage can now be derived from the same publication state used elsewhere. A game marked available has crossed a product boundary, so the repository can require the public explanation that should accompany it.
This is deliberately narrower than requiring an article for every manifest. Development games should be free to exist, change name or disappear without creating public-facing obligations. The gate only activates when the product itself says the game is available.
That small alignment between code state and editorial state removes a category of drift. It also gives future agents a clear rule to follow instead of relying on historical knowledge about which games “really count” as launched.
Why this amount of work belongs in one Devlog entry
The recent changes could have been split into separate notes about candidate grids, larger Numberlink boards, streak analytics, CPU search, runner reliability and editorial gates. Technically they are separate changes. As a development story, however, they share one consequence: every new feature exposed another assumption that had previously lived inside individual games.
Putting them together makes that pattern visible. Candidate grids forced shared interaction decisions; competitive play forced richer result semantics; streaks forced cross-game aggregation; larger generators forced stronger quality contracts; publication gaps forced an explicit editorial gate. The story is the convergence, not any one commit.
That is also why the next phase is simplification. Once common expectations are visible, duplicated mechanisms can be removed without losing the behaviours they were originally created to protect.