Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,11 @@ jobs:
- name: Synthetic scenario self-check
run: ./build/bin/laige-detcheck --scenario=synthetic
- name: Real scenario (M1-SAMPLE-01)
# Skipped until M1-SAMPLE-01 lands the hello scenario binary;
# M1-DET-04 replaces this step with the two-configuration
# comparison, e.g.:
# The hello template (samples/hello) is always built in this
# job, so this step always executes: two no-arg runs of the
# scenario — both must exit 0 and print the 301-line per-tick
# hash stream (the guard is defensive only). M1-DET-04 replaces
# this step with the two-configuration comparison, e.g.:
# ./build/bin/laige-detcheck --run-a=build-asan/bin/hello
# --run-b=build/bin/hello
run: |
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ build-*/
Testing/
CMakeUserPresets.json

# Sample binaries (samples/hello builds into its own source-tree bin/ —
# the CI detcheck step invokes samples/hello/bin/hello from the repo
# root; M1-SAMPLE-01)
samples/*/bin/

# Compiled artifacts (in case they ever land outside build trees)
*.o
*.obj
Expand Down
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,13 @@ endfunction()
add_subdirectory(src/laige-core)
add_subdirectory(src/laige-sim)

# Samples (M1-SAMPLE-01): the hello.laige headless template game.
# Unconditional (not test-gated): the sample is a shipped project, and
# the CI detcheck step builds and runs it from the default tree. Its
# binary lands at the source-tree path samples/hello/bin/hello (its own
# CMakeLists sets RUNTIME_OUTPUT_DIRECTORY — see there why).
add_subdirectory(samples/hello)

# ---------------------------------------------------------------------------
# Tests (gated by LAIGE_BUILD_TESTS; conventions in tests/README.md)
# ---------------------------------------------------------------------------
Expand Down
10 changes: 9 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ temp+rename, size-bounded), `Engine::startReplayRecording`, and
`laige-run --replay`; M1-DET-03: replay execution —
`World::stateHash` (the deterministic state hash), `runReplay`
(the identity-checked re-run and its per-tick hash stream), and the
`laige-replay` runner).
`laige-replay` runner; M1-SAMPLE-01: `hello.laige` — the headless
template game (samples/hello: one component, one system, one entity,
the per-tick `World::stateHash` stream on stdout, record → replay
through the scenario's own binary, the PRD §9.4 line budget —
[samples/hello/README.md](../../samples/hello/README.md)).
Every section of the AGENTS §13 `docs/` tree exists; each entry below
links what is written and the "not yet written" section marks what is
still to land.
Expand All @@ -35,6 +39,10 @@ still to land.
status. Tool commands: `laige-run`, `laige-replay`, `laige-fuzz`, `laige-bench`,
`laige-detcheck`, the `laige-api` manifest target, and the
include-graph lint.
- [hello.laige](../../samples/hello/README.md) — the headless template
game (M1-SAMPLE-01): the canonical smallest-complete Laige game —
build it with the repository, run it headless, record and replay it,
and learn every component/system/tick mark a Laige game uses.

## Concepts

Expand Down
28 changes: 17 additions & 11 deletions docs/api/detcheck.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ state across configurations (NFR-8.3, FR-1.4). The engine state-hash API
landed with **M1-DET-03** (`World::stateHash`,
[api/entity.md](entity.md)); this tool works against the **hash-file
output contract** defined below and compares two such streams. The
current scenario fixture still prints its own ad-hoc hash stream; the
scenario wiring that switches it to the `World::stateHash` stream lands
with M1-SAMPLE-01 (the tool's line-by-line comparison is unchanged).
real scenario now exists: **M1-SAMPLE-01**'s `hello` (samples/hello)
prints exactly this contract — the tick-0 line plus one
`World::stateHash` line per completed tick — and the CI job's real-
scenario step runs it; **M1-DET-04** activates the two-configuration
comparison of it (the tool's line-by-line comparison is unchanged).

## Scenario contract

Expand Down Expand Up @@ -159,10 +161,9 @@ body index and a nudge in [-4, 3] applied to x. Per-tick hash: FNV-1a 64
and compiler by the language standard; no float anywhere in the workload.
**Hash scope (M0):** tick counter + seed + body words. The Prng position
is a pure function of (seed, nudge history) in this workload; the
definitive scope — including PRNG state and the exact hash function —
is M1-DET-03's `World::stateHash`
([api/entity.md](entity.md)), which the scenario wiring switches to
with M1-SAMPLE-01 (the tool's line-by-line comparison is unchanged).
definitive scope — including PRNG state and the exact hash function — is
M1-DET-03's `World::stateHash` ([api/entity.md](entity.md)), which the
`hello` scenario (M1-SAMPLE-01) prints directly on its stdout stream.

## Performance and bounds

Expand Down Expand Up @@ -190,7 +191,12 @@ script asserting both the exit code and the required output fragments
The `detcheck` CI job (`.github/workflows/ci.yml` and `ci-pull.yml`) runs
the built-in self-check on every PR and merge (like `include-lint` and
`api-manifest`, independent of the `ci:*` label selector — it is a
tooling check, not an additional P0 OS build). The real-scenario
comparison — two build configurations of M1-SAMPLE-01's `hello` — is
**skipped until that sample exists**; **M1-DET-04** activates it and
records the result per ARCH-010.
tooling check, not an additional P0 OS build). It also runs the **real
scenario** (M1-SAMPLE-01): both `--run-a` and `--run-b` point at
`samples/hello/bin/hello` (the no-arg 300-tick headless run — the step
activates once the sample binary exists, which it now does), so every
PR and merge executes the template game's detcheck contract: both runs
must complete (exit 0) and print the 301-line hash stream. **M1-DET-04**
replaces this same-configuration step with the two-configuration
comparison (`build-asan/bin/hello` vs `build/bin/hello`) and records the
result per ARCH-010.
11 changes: 7 additions & 4 deletions docs/api/replay.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,13 @@ laige-replay --log LOG --config CONFIG.json [--expect BASELINE]
(the ADR 0003 bounded-read precedent).
- **Scope:** `laige-replay` replays logs recorded by `laige-run
--headless --replay` (the engine's built-in registration). A
game-scenario log is replayed by the scenario binary itself through
the same `runReplay` library (the M1-SAMPLE-01 scenario wires it;
M1-DET-04's detcheck `--run-a/--run-b` compares two scenarios' hash
streams).
game-scenario log is replayed by the scenario binary itself: it loads
the log (`loadReplay`), checks the replay identity against its own
(world, config) (`replayIdentityDiff` — a mismatch is a rejected
replay, never a silent divergence), and re-runs the log's frame count
through the same tick loop `runReplay` drives (M1-SAMPLE-01's
`hello --log` wires this; M1-DET-04's detcheck `--run-a/--run-b`
compares two scenarios' hash streams).

## Performance (PERF-002/003, LOG-003)

Expand Down
13 changes: 12 additions & 1 deletion docs/getting-started/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ The canonical-commands table in [roadmap/README.md](../../roadmap/README.md)
| Benchmarks | `./build/bin/laige-bench --suite=<name>` |
| Determinism check | `./build/bin/laige-detcheck --scenario=<name>` |
| Replay runner | `./build/bin/laige-replay --log LOG --config CONFIG.json [--expect BASELINE]` |
| hello template (run) | `./samples/hello/bin/hello [--replay LOG]` |
| hello template (replay) | `./samples/hello/bin/hello --log LOG` |
| API manifest | `cmake --build build --target laige-api` |
| Include-graph lint + dependency count | `python3 tools/laige-include-lint` |
| Determinism source scan (sim module) | `python3 tools/laige-determinism-lint` |
Expand All @@ -58,7 +60,16 @@ Notes:
and exits 1 at the first diverging tick — contract in
[docs/api/replay.md](../api/replay.md)), and target `laige-api`
(M0-TOOL-01). Their command forms were fixed here when they were
reserved, so no step can drift them.
reserved, so no step can drift them. The `hello` rows are the
M1-SAMPLE-01 template game (samples/hello): it builds into the
source-tree path `samples/hello/bin/hello` (its own CMake target
property — the CI detcheck step invokes it from the repository
root with no arguments), prints the 301-line per-tick state-hash
stream on stdout (the detcheck scenario contract —
[docs/api/detcheck.md](../api/detcheck.md)), and exits 0/1/2; the
`hello_*` CTest entries (`tests/sample`) are its CI form, and
`--replay` is a debug-build feature. Contract:
[samples/hello/README.md](../../samples/hello/README.md).
Fuzz and randomized-test seeds: fixed default `0x1F055EED`,
overridable (`laige-fuzz --seed=…`; tests via the `LAIGE_TEST_SEED`
environment variable) — see [docs/testing.md](../testing.md).
Expand Down
2 changes: 1 addition & 1 deletion roadmap/M1-heartbeat.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ zero-allocation property (M1-ALLOC-01 enforces it once it exists; before that, A
- **Verify:** `laige-bench --suite=sim-tick` avg ≤ 3.0 ms and p99 ≤ 5 ms on both backends on the CI reference machine (if local machine differs, record measured value + CI is the gate); baseline file exists.
- **Size:** ~200 lines + baseline doc

- [ ] **M1-SAMPLE-01 · `hello.laige` (headless template)**
- [x] **M1-SAMPLE-01 · `hello.laige` (headless template)**
- **Refs:** NFR-13.5 (template < 100 lines), PRD §13
- **Depends:** M1-HEAD-01, M1-DET-03
- **Scope:**
Expand Down
Loading
Loading