Repository-cleanup / DX pass folding three tracker items into one coherent
change, verified green end to end (`bin/x test` 49/0, `bin/x selfhost-test`
29/0, `bin/x test-tools` 29/0).
#28 — curate & categorise examples/
- 42 flat entries regrouped into intent-revealing subdirs: games/, rendering/,
ecs/, events/, networking/, lang/, library/ (was lib/).
- chronorift dir-vs-file duplication resolved: the entry file and its import
modules now live together under games/chronorift(.ludic).
- Every path reference updated repo-wide (test runner, editor-tool drivers,
docs/site, design docs).
- New examples/README.md indexes the whole set with run commands.
- Showcase examples without a self-asserting entry (hello, events, net_rt) now
get a compile-only rot guard in `bin/x test`, so nothing here rots silently.
#30 — text-diffable golden baseline
- The 4 binary selfhost/golden/*.ppm blobs are replaced by a single
selfhost/golden/renders.sha256 manifest (SHA-256 per render). Hashes are
byte-identical to the old PPMs, so the baseline is unchanged — only its form.
- game_case now compares framebuffer hashes; a regression shows as a changed
hex line in review, not "binary files differ".
- New `bin/x golden` regenerates the manifest deliberately (review with
`git diff selfhost/golden/renders.sha256`).
#27 — PPM & asset handling
- Headless renders now write build/out.ppm, never the repo root; `x app`,
`x clean`, messaging and .gitignore updated to match. Nothing is written to
the working root any more.
- Redundant local Kenney .zip archives removed (the art ships extracted;
.gitignore already excludes *.zip). CC0 License.txt files retained.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Finish issue #9 by adding the two remaining acceptance items on top of the
calendar/clock core, still pure-integer and deterministic:
DateTime.format(dt, pattern) -> string render an instant via a token
pattern (YYYY/YY/MM/DD/HH/mm/ss;
other chars pass through)
DateTime.parse(text, pattern) -> int read an instant back; -1 on a
non-digit where one is expected
Clock.now/set/advance/reset a game-controlled simulated clock
(the @L_clock global) that never
touches the wall clock, so gameplay
reading Clock.now() is replay-safe
format/parse take a string-LITERAL pattern and are expanded at compile time
(field offsets are then constant), folding @fn_str_concat over literal runs and
two small runtime helpers: @fn_dt_pad0 (zero-padded field) and @fn_dt_rd
(fixed-width digit reader that stops at the terminator and flags malformed
input). Clock is a universal i32 global declared in emit_head, so it works in
entry and game programs alike.
Adds examples/offline_rewards.ludic — the issue's worked "you were away N hours"
example, driven from its own entry and asserted in the regression suite — plus
selfhost/tests/datetime2.ludic (format/parse round-trip, parse failure, clock),
docs (Clock section + 4 pages, DateTime.format/parse pages), inventory and LSP
hover. Reseeded; C-free fixpoint holds; all suites green (27 self-host / 46
regression / 29 tools); check.py (366 symbols), check-impl.py (218 ns-methods)
and validate.py OK.
With this, #9's scope is fully delivered: DateTime/Date/Duration + core ops,
format/parse, a deterministic simulated clock, docs + offline-rewards example,
and tests. (v1 stays UTC-only, no leap seconds, i32 epoch valid through 2038.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>