Skip to content

Follow the catalog's cursor - #23

Merged
nicodes merged 1 commit into
mainfrom
follow-the-catalog-cursor
Aug 4, 2026
Merged

Follow the catalog's cursor#23
nicodes merged 1 commit into
mainfrom
follow-the-catalog-cursor

Conversation

@nicodes

@nicodes nicodes commented Aug 4, 2026

Copy link
Copy Markdown
Member

Round 0.2's client half. Needs aviorstudio/termcade-be#22 deployed first, and a release after — see below.

Summary

  • Games() walks the paged catalog to the end instead of reading one array
  • browsing asks for releases this arcade can run (abi), which it always should have
  • CatalogPage/CatalogQuery for callers that want one page with a search or a sort
  • created_at / released_at on Game
  • contract/ — the API's own recorded examples, decoded by the tests

The failure this guards against is quiet

A client that stops at the first page shows a short marketplace and nothing anywhere says a game is missing. So the walk stops on an absent cursor, never on a short or empty page — the registry applies its compatibility filter after reading a page, so a page can legitimately be empty mid-walk. TestAnEmptyPageIsNotTheEnd is the guard.

It is bounded at twenty pages: the marketplace is a screen somebody scrolls, not an index anybody mirrors. A bound that is reached returns what it has rather than failing, and TestGamesStopsWalkingEventually proves a registry handing out cursors forever cannot hang the arcade.

Order

The API must deploy before this releases — v0.0.6 already cannot read the new shape, and this cannot read the old one. So: merge and deploy termcade-be#22, merge this, cut v0.0.7.

Nothing else in the arcade is affected: resolve, download, publish, the library and activity sync are untouched, so installing, releasing games and termcade-games CI keep working throughout.

contract/

Copied from termcade-be, which generates the examples from the API. A Go module cannot read files out of a sibling repository, and vendoring the backend to get four JSON files would be a dependency on the whole thing — so they are copied, and updating them is part of the change that follows an API response-model change. The README in that directory says so.

Verification

  • gofmt, go vet ./..., go vet ./sdk/...
  • go test -race -count=1 -timeout 10m ./... ./sdk/...
  • GOWORK=off go build ./... and GOWORK=off go vet ./...

🤖 Generated with Claude Code

The registry pages its catalog now, so browsing the marketplace is several
requests rather than one. `[...]` became `{"games": [...], "next": "..."}`,
and a client that reads only the first page shows a short marketplace with
nothing anywhere to say a game is missing.

Games() walks to the end. It stops on an ABSENT cursor and never on a short
or empty page: the registry applies its compatibility filter after reading a
page, so a page can be empty in the middle of a walk. The walk is bounded at
twenty pages — the marketplace is a screen somebody scrolls, not an index
anybody mirrors — and a bound that is reached returns what it has rather than
failing.

Browsing now asks for releases this arcade can actually run, which it always
should have: a marketplace listing games that refuse to install is worse than
a shorter one.

contract/ holds the API's own recorded examples, and the tests decode them
into these types. A renamed field otherwise arrives as a zero value, and a
zero value looks exactly like a game with no release rather than like a bug.

Needs aviorstudio/termcade-be#22 deployed first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nicodes
nicodes merged commit 53a599c into main Aug 4, 2026
2 checks passed
@nicodes
nicodes deleted the follow-the-catalog-cursor branch August 4, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant