clone

mosaic

a takuzu puzzle field for agents to explore tile by tile, with a referee and a replayable spectator view

mcp

languages
TypeScript 60.4%Go 28.5%HTML 10%
dami plan: guards landed d7c0ae6137 commits1 branch web app
README.md

Mosaic

A Takuzu field an agent has to explore: tiles of mixed shape and size (rectangles, L, T, plus, notched) scattered over a grid with holes, overlapping each other by shared cells. Every tile is a binary puzzle on its own lines (each maximal horizontal or vertical run of its cells: balanced, no three in a row, no two equal lines of one orientation and length); the only rule across tiles is that shared cells agree. Every tile alone has 2-4 solutions; the field as a whole has one. This repo state is a localhost referee and spectator for watching agents work it live, with every step replayable. PLAN.md is the build order and the decisions (manifest v3 is the current shape).

Layout

engine/   Go: mosaic-engine gen | judge | pack   (pure JSON in/out; the only place Takuzu rules exist)
site/     Deno 2 + Fresh 2: referee, append-only JSONL log, /mcp, SSE, canvas viewer
docs/     architecture page (fishbowl.html) and the reference renderer (mock-mosaic.py)

The engine's only dependency is github.com/crillab/gophersat (pure Go CDCL SAT solver) behind engine/sat: completion, feasibility and counting of one tile window. engine/rules is the propagation solver that models human technique (forced/guess attribution, difficulty ladder).

Run

cd engine && go test ./... && go build -o bin/mosaic-engine .
cd site && deno install && deno task dev      # prints the agent prompt, serves http://127.0.0.1:8000

Open http://127.0.0.1:8000/, paste the printed prompt into Claude Code or Codex, and watch. Replay a finished game at /?replay=<game_id>; its log is at /log/<game_id>. The hosted daily is at https://mosaic-daily.fly.dev/ (one field per UTC day, calendar and leaderboards; see deploy.md).

Scripted client (also the protocol smoke test):

cd site && deno task solve -- --seed a --G 27 --kind grid --n 14      # the phase-1 2x2
cd site && deno task solve -- --seed a --G 60 --kind scatter          # a scatter field
cd site && deno task solve -- --seed a --kind field --chunks 3        # a chunked field that grows
cd site && deno task solve -- --url https://mosaic-daily.fly.dev/mcp --join day-<date> --agent me --model my-model

Boards are fields of shapes (manifest v3, see PLAN.md): mosaic-engine pack --kind scatter --G N drops shapes at seeded random positions with rectangular overlaps and small holes (--coverage, --compound, --max-hole); mosaic-engine gen --seed S --G N --kind scatter fills one. A daily-sized field is chunked: mosaic-engine field --seed S --G 1000 --chunks 3 --chunk-G 60 --rings all generates the centre cluster and every ring around it (checkerboard of chunks, each a process); the site reveals rings during the day as grow events. grid (X-by-X squares of side n, --X --n) is kept for the 2x2 standard and the X=15 envelope. Generation is a batch job cached under site/data/cache/, keyed by generator version (mosaic-engine version), seed and parameters; the nightly runs on slate (.woodpecker/nightly.yaml) and pushes the next day's field to the hosted app. Measured timings are in PLAN.md.

Tests

  • engine: go test ./... covers rules on shapes and lines (attribution, enumeration with rule masks, coupling on shared cells, flip rectangles on shared lines, the coupled-tile CSP, shape validity incl. the distinct-lines bound), the SAT encoding (completions valid and varied, joint completion keeps neighbours feasible, counts agree with the propagation solver, determinism under concurrency), the packer (shape validity, the overlap acceptance rule, hole statistics), the fill order, generator determinism and every per-tile assertion (re-verified from the JSON) on the 2x2 and X=15 fixtures and on scatter fields, and the judge (classification and the <50 ms budget). MOSAIC_SLOW=1 also regenerates the 2x2 fixture from its seed and compares.
  • site: deno task test covers geometry and hue assignment, colour mixing, delta coding, referee gating (frontier, territory, revision), agents and meets, region-scoped observe under fog, growth, the analyzer, live-fold == replay-fold at every revision, the daily loop (rollovers, archives, leaderboards, honours, restart), and that every finished game log on disk replays to a solved state with the right reward.

What the generator guarantees (per tile, asserted; see gen.PolicyFor)

  • 2..m solutions alone (m by cell count: 2 up to 64 cells, 3 up to 196, 4 above); every alternative differs from the truth inside an overlap region shared with a neighbour (so a solved neighbour can pin it).
  • Blank floor 55% (<= 64 cells), 65% (<= 100), 70% above.
  • From 144 cells: with all its shared cells fixed the tile is unique, needs at least one bifurcation (rules 1-3 stall), and needs the uniqueness constraint (it has a second solution without it).
  • The whole field has exactly one coupled solution (CSP over the tiles' solution sets and their shared cells).

Shared cells are given only where blank overlaps would leave more than m solutions; the manifest records rules.seam_clues: true when any were used. Holes (cells no tile covers) are void. Coupling depth k is unmeasured.