Repository navigation
[M1-CFG-01] Declarative game config - #45
Merged
Merged
Conversation
…ides, hot reload - New public header src/laige-sim/include/laige/sim/config.h (+ config.cpp): the FINAL version 1 declarative config schema — EngineConfig moved from engine.h (the five original members keep their order), the REQUIRED "version" key (gated before every other key, ARCH-007), the budgets / camera / asset_roots declared blocks, parseEngineConfig, loadGameConfig, EngineConfigOverride + applyConfigOverride (the FR-1.5 override merge), and the debug-only ConfigHotReloader (non-sim keys reload live; sim-affecting keys are refused with config/hot_reload_rejected). - engine.h/engine.cpp: the provisional config surface is folded into config.h (engine.h includes it; Engine::create re-validates the tick rate with the shared kConfigTickRateInvalidMessage); laige-run.cpp now uses loadGameConfig (exit codes unchanged). - The replay identity's configHash covers only the sim-affecting fields, so the encoding (tag 1) is unchanged and every committed baseline / replay log stays valid (replay.h/.cpp comments + docs updated). - docs/api/config.md (new): key table, versioning + migration, rejection table, override API, hot-reload contract, Performance, misuse warnings; engine.md / replay.md / determinism.md / testing.md / docs-README / sim-README cross-refs updated to the final surface. - Tests: new game_config CTest entry (38 tests: every rejection domain, the version gate, first-failure-wins, the file loader, the override merge, the hot-reload contract incl. the release-disabled path); engine_tests drops the migrated EngineConfigParse.*; determinism_tests' config docs gain "version": 1; fixtures gain "version": 1 (headless_smoke, samples/hello, the replay smoke fixtures). - laige-api.json regenerated (734 symbols; api-real-tree green). - Verify: ctest -R config green; full ctest 88/88 on build (Debug g++), build-asan, build-release (the hot_reload_disabled path), build-clang, build-tsan, build-shared; zero new warnings under NFR-8.10. Untested: the MSVC _fsopen branch (CI-only). - Roadmap: M1-CFG-01 box checked; board 20/25 (38 total); change log row + retroactive M1-DET-05 row (the M1-ECS-06 precedent). Closes roadmap/M1-heartbeat.md step M1-CFG-01.
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.
Closes roadmap/M1-heartbeat.md step M1-CFG-01 (FR-1.5, PRD §7.1/§10.2/§10.3, ARCH-007).
What this PR does
The declarative game config surface — the version 1
config.jsonschema, its loaders, the programmatic override merge, and the debug-build-only hot reload of non-simulation keys.src/laige-sim/include/laige/sim/config.h(+config.cpp):EngineConfigmoved fromengine.h— the five original members keep their order (existing aggregate initializers compile unchanged), gaining thebudgetsblock (system_time_default_ms, draw_calls_per_frame, particles_per_frame — declared values before their M2 consumers), thecamerablock (fov/zoom/follow-lerp — stored, consumed in M2), andasset_roots(non-empty strings; no existence check — the M2 asset pipeline owns it).versionkey is checked before any other key (missing →config/version_missing, non-integer →config/version_invalid, ≠ 1 →config/version_unsupported); the provisional M1-HEAD-01 documents migrate by adding"version": 1.config/unknown_keyand are ignored (forward-compat); first failure wins in document order; every rejection is a rate-limited warn with the NFR-13.3 5-field text +InvalidArgument.loadGameConfig(path)— bounded 1 MiB read + the M0-CORE-07 parse + schema validation;laige-runnow uses it (exit codes unchanged).EngineConfigOverride+applyConfigOverride— the FR-1.5 override-of-a-subset merge (per-leaf optionals, each set field validated, first set field that fails wins, value semantics).ConfigHotReloader— move-only, no thread, caller-driven poll; debug builds only (release rejects withconfig/hot_reload_disabled): non-sim changes apply in place +config/hot_reload_applied; sim-affecting changes are refused atomically +config/hot_reload_rejected(old/new fields, config untouched).configHashcovers only the sim-affecting fields, so the encoding (tag 1) is unchanged and every committed baseline / replay log stays valid (replay.h/.cpp comments + docs updated).docs/api/config.md(key table, versioning + migration, rejection table, override API, hot-reload contract, Performance, misuse warnings); engine.md / replay.md / determinism.md / testing.md / docs-README / sim-README cross-refs updated to the final surface.game_configCTest entry (38 tests: every rejection domain, the version gate, first-failure-wins, the file loader, the override merge, the hot-reload contract incl. the release-disabled path); engine_tests drops the migratedEngineConfigParse.*; fixtures gain"version": 1(headless_smoke, samples/hello, the replay smoke fixtures).laige-api.jsonregenerated (734 symbols).Verification
ctest -R configgreen (config_json + game_config + hello_config_valid)ctest88/88 onbuild(Debug g++),build-asan(leak-free),build-release(thehot_reload_disabledpath exercised),build-clang,build-tsan(config suites,halt_on_error=1),build-sharedtools/laige-include-lintOK,tools/laige-determinism-lintOK (24 sim sources, 0 violations),laige-api-scanner --checkcleanUntested paths
_fsopenread branch (CI-only; the M1-DET-02 precedent).Compatibility
No existing symbol or behavior changed: the provisional keys carry over unchanged under the version 1 schema, the
EngineConfigmember order is preserved, the replayconfigHashencoding is unchanged, and the CLI exit codes are unchanged.