Repository navigation
[M1-HEAD-01] Headless engine run (Engine + laige-run) - #31
Merged
Merged
Conversation
Headless engine run (M1-HEAD-01 scope, nothing else): - Engine (src/laige-sim/include/laige/sim/engine.h + engine.cpp): config -> world -> systems -> loop. EngineConfig (tickRateHz 20-120 default 60, entityCapacity 0-65536 default 0 = empty scene, churnPerFrameBudget default 256) + parseEngineConfig over the bounded JSON (unknown key -> warn config/unknown_key, ignored; rejections config/not_an_object, tick_rate_invalid, entity_budget_invalid, churn_budget_invalid - first failure wins, one rate-limited warn each, NFR-13.3 grammar). Engine::create pre-validates, creates the World, registers Position2DFpx16 FIRST (ARCH-010). - run_headless(maxTicks, frameBudgetTicks): schedule -> GameLoop (with the engine per-tick hook) -> first frame (0 ticks, start reference) -> PresentationSnapshot anchored on the loop's exact startReferenceNs (ARCH-009) -> wall-clock-paced frames (one steady_clock read + one bounded sleep per frame; exact integer due math, M1-LOOP-01). The run ALWAYS ends in the ordered shutdown (CONC-006: loop -> world clear -> snapshot -> world release -> logging flush); the shutdown is idempotent (double/triple safe, world() -> nullptr, second run -> InvalidArgument with no log); maxTicks == 0 = the server form. Lifecycle Info pair engine/run_started / engine/run_finished; no logging on the healthy frame path (PERF-003/LOG-003). Setup = exactly three one-shot allocations (loop object, snapshot object, 24 B/slot table); zero per-frame allocations (verified: identical count for 1/2/3/10 ticks - the engine-zeroalloc line). - laige-run binary (tools/run): --headless CONFIG (1 MiB bounded read), --ticks N, --replay LOG stub (warned replay/replay_deferred, M1-DET-02), --help. Exit codes 0 ok / 1 run failure / 2 usage-IO-config; stdout summary 'laige-run headless ticks=... status=ok'; the CLI exercises the double-shutdown idempotency. - CI: laige_run_smoke ctest entry (--ticks 1000 against the fixture, 60 Hz / 10000 slots; TIMEOUT 300, PASS_REGULAR_EXPRESSION status=ok, TSan halt_on_error=1). engine ctest entry (20 tests; TSan property list). - Docs: docs/api/engine.md (new, full contract + Performance), docs/README.md, docs/getting-started/building.md, tools/README.md, src/laige-sim/README.md. laige-api.json regenerated (555 -> 573 symbols; api-real-tree green). - Deviation: declared dependency M1-CFG-01 has not landed - the JSON config surface is PROVISIONAL (three unversioned keys), documented in engine.md, the header preamble, and the roadmap change log; M1-CFG-01 owns the final versioned schema. - Verified: zero-warning 47/47 ctest on all six local trees (build, build-asan, build-tsan, build-clang, build-release, build-shared); ctest -R engine green (20/20); ctest -R laige_run_smoke green (~16.7 s, status=ok); tools/laige-include-lint OK (33 source files, 1/10 vendored deps).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
M1-HEAD-01: the headless engine object + the
laige-runbinary.What
Engine(src/laige-sim/include/laige/sim/engine.h,engine.cpp): config → world → systems → loop.EngineConfig+parseEngineConfig(provisional JSON surface);run_headless(maxTicks, frameBudgetTicks)(bounded + server forms); always ends in the ordered idempotent CONC-006 shutdown (loop → world clear → snapshot → world release → logging flush); lifecycle Info pairengine/run_started/engine/run_finished.laige-run(tools/run):--headless CONFIG [--ticks N] [--replay LOG](replay = M1-DET-02 stub, warned); exit codes 0/1/2; machine-greppable stdout summary; the CLI exercises the double-shutdown idempotency.laige_run_smokectest entry —--ticks 1000@ 60 Hz againsttests/laige-sim/fixtures/headless_smoke.json(TIMEOUT 300, assertsstatus=ok; TSanhalt_on_error=1).enginectest entry: 20 unit tests incl. double-shutdown and the zero-allocation frame-path probe.docs/api/engine.md(full contract + Performance) + cross-refs;laige-api.jsonregenerated (555 → 573 symbols).Key properties
operator newcounter (identical count for 1/2/3/10 ticks —engine-zeroalloc ticks=… allocs=3).fpx16_16backend — ADR 0002); replay/hash tests land in M1-DET-02.Deviation (surfaced)
Declared dependency M1-CFG-01 has not landed — the JSON config surface is provisional (three unversioned keys:
tick_rate_hz,entity_budget,churn_per_frame_budget). M1-CFG-01 owns the final versioned schema and will foldparseEngineConfigin; documented indocs/api/engine.md, the header preamble, and the roadmap change-log line.Verification (local, all six trees)
Zero-warning
ctest47/47 onbuild(Debug g++),build-asan(ASan+UBSan, leak-free),build-tsan(TSAN_OPTIONS=halt_on_error=1on the engine entry),build-clang,build-release,build-shared;ctest -R engine20/20;ctest -R laige_run_smokegreen (~16.7 s,status=ok);tools/laige-include-lintOK (33 source files, 1/10 vendored deps);api-real-treegreen.