From 972090d5ceaa835899a3ada847a23e3e9f798cfd Mon Sep 17 00:00:00 2001 From: Pascal Severin Date: Sun, 13 Sep 2026 11:25:28 +0200 Subject: [PATCH 1/3] =?UTF-8?q?[M0-DOC-01]=20docs/=20skeleton=20+=20index:?= =?UTF-8?q?=20full=20AGENTS=20=C2=A713=20tree=20+=20benchmark=20methodolog?= =?UTF-8?q?y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docs/README.md: rewritten as the single index — links every AGENTS §13 section (getting-started, concepts, api, guides, debugging, benchmarks, decisions, compatibility) plus the testing conventions and related documents; explicit 'not yet written' list (DOC-001 honest status). - New section indexes: concepts/ (planned docs + interim homes, incl. the ARCH-008 coordinates topic), guides/ (milestone mapping), debugging/ (usable today + AGENTS §15 status), compatibility/ (P0 platforms per PRD §6 + CI, current formats, no migration guides yet). - docs/benchmarks/: methodology.md (normative AGENTS §12 report fields, budgets.json field->report mapping, immutable baseline-file convention, PRD §8.1 regression policy) + baselines/ (empty; first baseline m0-synthetic.md lands with M0-EXIT-01). - decisions/README.md: stale 'arrives with M0-DOC-01' note replaced (ADRs 0001-0004 remain indexed). - Root README.md: docs pointer now links docs/README.md; ADR list corrected to 0001-0004 (DOC-003 stale-doc fix, same change). Verify: repo-wide dead-link check over all 49 *.md files — 104 internal links, zero dead; every section linked from docs/README.md; decisions index references ADR 0001-0003 (+0004); ctest 32/32 green on the existing build tree (docs-only change, no build impact). --- README.md | 6 +- docs/README.md | 102 +++++++++++++----- docs/benchmarks/README.md | 22 ++++ docs/benchmarks/baselines/README.md | 20 ++++ docs/benchmarks/methodology.md | 159 ++++++++++++++++++++++++++++ docs/compatibility/README.md | 47 ++++++++ docs/concepts/README.md | 18 ++++ docs/debugging/README.md | 19 ++++ docs/decisions/README.md | 6 +- docs/guides/README.md | 19 ++++ 10 files changed, 385 insertions(+), 33 deletions(-) create mode 100644 docs/benchmarks/README.md create mode 100644 docs/benchmarks/baselines/README.md create mode 100644 docs/benchmarks/methodology.md create mode 100644 docs/compatibility/README.md create mode 100644 docs/concepts/README.md create mode 100644 docs/debugging/README.md create mode 100644 docs/guides/README.md diff --git a/README.md b/README.md index 70f2a70..ab00d09 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ The AI-relevant hardware the model runs on: | `tests/` | Unit/integration tests, mirroring the `src/` module layout | | `tools/` | Engine tools and CI scripts (fuzz runner, API manifest, determinism checker, lints) | | `samples/` | Reference game projects (flagship isometric ARPG, platformer, lockstep arena, MMO demo zone) | -| `docs/` | Documentation; [decision index](docs/decisions/README.md) (full structure lands in M0-DOC-01) | +| `docs/` | Documentation; [index](docs/README.md) (full AGENTS §13 structure — getting started, concepts, API, guides, debugging, benchmarks, decisions, compatibility, testing) | ## Building @@ -109,4 +109,6 @@ benchmark command `./build/bin/laige-bench --suite=`). The test - [AGENTS.md](AGENTS.md) — engineering contract (normative) - [Roadmap](roadmap/README.md) — implementation checklist, progress board, canonical commands -- [Architecture decisions](docs/decisions/README.md) — ADRs 0001–0003 +- [Documentation index](docs/README.md) — getting started, concepts, API + contracts, guides, debugging, benchmarks, compatibility, testing +- [Architecture decisions](docs/decisions/README.md) — ADRs 0001–0004 diff --git a/docs/README.md b/docs/README.md index d278064..d2be645 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,16 +1,26 @@ # Laige documentation Documentation index and navigation (DOC-001). The engine is at **M0** -(foundations): `laige-core` is the only populated module, and the -sections below mark what exists and what is still to land. +(foundations): `laige-core` is the only populated module. 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. -## Build & tools +## Getting started -- [Building Laige](getting-started/building.md) — the source of truth for - the canonical build commands, build trees, options, compiler policy - (NFR-8.10), sanitizer builds (NFR-8.2), and the current M0 status. - Tool commands: `laige-fuzz`, `laige-bench`, `laige-detcheck`, the - `laige-api` manifest target, and the include-graph lint. +- [Building Laige](getting-started/building.md) — the source of truth + for the canonical build commands, build trees, options, compiler + policy (NFR-8.10), sanitizer builds (NFR-8.2), and the current M0 + status. Tool commands: `laige-fuzz`, `laige-bench`, `laige-detcheck`, + the `laige-api` manifest target, and the include-graph lint. + +## Concepts + +- [Concepts index](concepts/README.md) — architecture, coordinates + (ARCH-008), lifecycle, threading, and determinism scope. **Not yet + written** (M0 is foundations only); the index names each planned + document and its interim home today (the `Vec2`/`Vec3` comments in + `src/laige-core/include/laige/sim_math.h`, ADR 0002, the per-API + contracts). ## API contracts (per public header) @@ -28,19 +38,37 @@ sections below mark what exists and what is still to land. - [Budget harness](api/budget_harness.md) — `Histogram`, `TimeIt`, `budgetCheck`, the AGENTS §12 report format, and the `budgets.json` schema (M0-CORE-08). -- [PRNG](api/prng.md) — `laige::Prng`: the splitmix64/LCG64 hybrid, - period, and determinism contract (M0-CORE-06). +- [PRNG](api/prng.md) — `laige::Prng`: xorshift128+ with splitmix64 + seeding, substreams, period, and the determinism contract + (M0-CORE-06). - [Determinism checker](api/detcheck.md) — the `laige-detcheck` tool and the scenario hash-line contract (` ` lines, two build configurations) (M0-TOOL-02). -## Testing +## Guides -- [Testing conventions](testing.md) — test layout (module dirs mirror - `src/`, `_tests` executables), the `regress_` - regression-test convention, `laige-fuzz` target registration and CI - lane semantics, and the seed-handling convention for randomized tests - (M0-TEST-01). +- [Guides index](guides/README.md) — task-oriented usage and + optimization guides. **None yet**: they land with their milestones + (first headless project and determinism/replay in M1, profiling in + M1, rendering in M2, MMO server setup in M6/M7). + +## Debugging + +- [Debugging index](debugging/README.md) — what is usable today + (structured logging, the budget harness, `laige-detcheck`, sanitizer + builds, test seeds). The in-engine debug mode (AGENTS §15) lands with + the profiling work (M1-PROF-01, M2-PROF-01). + +## Benchmarks + +- [Benchmarks index](benchmarks/README.md) — methodology, baselines, + results, and the regression policy. +- [Benchmark methodology](benchmarks/methodology.md) — the AGENTS §12 + report fields, the `budgets.json` field mapping, the baseline-file + convention, and the PRD §8.1 regression policy (M0-DOC-01). +- [Baselines](benchmarks/baselines/README.md) — recorded baseline + reports. **Empty so far** (all `budgets.json` entries have + `measured: 0`); the first, `m0-synthetic.md`, lands with M0-EXIT-01. ## Architecture decisions (ADRs) @@ -48,27 +76,43 @@ sections below mark what exists and what is still to land. (deterministic math), 0003 (config JSON), 0004 (GoogleTest vendoring). +## Compatibility + +- [Compatibility](compatibility/README.md) — P0 platforms and + compilers (PRD §6; the CI matrix), the current machine-readable + formats (`budgets.json`, `laige-api.json`, `deps.lock`), and the + migration-guide status (none yet — pre-1.0, no breaking changes). + +## Testing + +- [Testing conventions](testing.md) — test layout (module dirs mirror + `src/`, `_tests` executables), the `regress_` + regression-test convention, `laige-fuzz` target registration and CI + lane semantics, and the seed-handling convention for randomized tests + (M0-TEST-01). + ## Not yet written (honest status) -- `concepts/` — architecture, coordinates (ARCH-008; lands as - `docs/concepts/coordinates.md` with M0-DOC-02 — until then the - coordinate system is documented in the `Vec2`/`Vec3` comments of - `src/laige-core/include/laige/sim_math.h`), lifecycle, threading. -- `guides/` — task-oriented usage (first game, profiling, determinism). -- `debugging/` — debug mode (AGENTS §15 lands in M3), logging in - production, troubleshooting. -- `benchmarks/` — method, baselines, and the regression policy - (the harness exists — `laige-bench`, M0-CORE-08 — but the recorded - baselines land with M1 workloads). -- `compatibility/` — platform/compilers/formats matrix (the P0 matrix - is in [building.md](getting-started/building.md) for now). +- `concepts/` — the architecture, coordinates, lifecycle, threading, and + determinism concept documents (the [index](concepts/README.md) names + each and its interim home). +- `guides/` — task-oriented usage (first game, profiling, determinism) + — see the [index](guides/README.md). +- `debugging/` — the in-engine debug mode (AGENTS §15; profiling + foundations land in M1, render observability in M2). +- `benchmarks/baselines/` — no measured baselines yet; the first lands + with M0-EXIT-01. +- `compatibility/` — no persistent data formats or migration guides yet + (they land with M1 replay and M6/M7 networking). - Per-module API docs for the M1+ modules (`laige-sim`, `laige-render`, `laige-assets`, `laige-net`, `laige-server`, `laige-script`, `laige-editor`) — they land with their modules. ## Related -- [Roadmap index](../roadmap/README.md) — the M0/M1/... step plan; +- [Roadmap index](../roadmap/README.md) — the M0/M1/… step plan, + progress board, and change log; [M0 foundations](../roadmap/M0-foundations.md) is the current milestone. - `AGENTS.md` — the engineering contract this documentation implements. +- `PRD.md` — the product requirements. diff --git a/docs/benchmarks/README.md b/docs/benchmarks/README.md new file mode 100644 index 0000000..db1927a --- /dev/null +++ b/docs/benchmarks/README.md @@ -0,0 +1,22 @@ +# Benchmarks + +Benchmark methodology, baselines, results, and the regression policy +(AGENTS §13). Performance claims are reproducible measurements +(CORE-001); this section is where they are recorded. + +- [methodology.md](methodology.md) — the **normative methodology** + (M0-DOC-01): the AGENTS §12 report fields, how `budgets.json` entries + map onto them, the baseline-file convention, the PRD §8.1 regression + policy, and workload discipline. +- [baselines/](baselines/README.md) — recorded baseline reports + (`-.md`). **Currently empty**: every + `budgets.json` entry has `measured: 0`. The first baseline, + `baselines/m0-synthetic.md`, lands with M0-EXIT-01, and + `baselines/m1-profiler-cost.md` with M1-PROF-01. +- Per-milestone performance results (M1 10k-entity tick, M2 50k-sprite + scene, M6/M7 zone server, …) land here as their milestones close — + see the [roadmap progress board](../../roadmap/README.md). + +The measurement tool is `laige-bench` (M0-CORE-08): API contract in +[api/budget_harness.md](../api/budget_harness.md), canonical command in +[building.md](../getting-started/building.md). diff --git a/docs/benchmarks/baselines/README.md b/docs/benchmarks/baselines/README.md new file mode 100644 index 0000000..88db3d0 --- /dev/null +++ b/docs/benchmarks/baselines/README.md @@ -0,0 +1,20 @@ +# Baselines + +Recorded baseline reports — the durable before/after history of the +`budgets.json` budgets (convention: +[../methodology.md](../methodology.md) §4). One file per recorded +measurement: + +```text +-.md e.g. m0-synthetic.md (M0-EXIT-01) +``` + +Each baseline file contains the full AGENTS §12 metadata (hardware, OS, +compiler + version, build type, flags, workload, warm-up, sample count, +summary statistics), the stable 4-line `budgetCheck` report verbatim, +and the exact command + commit that produced it. Baseline files are +**immutable**: superseding a baseline adds a new file and updates +`measured` in `budgets.json` — it never edits an existing baseline. + +No baselines are recorded yet (every `budgets.json` entry has +`measured: 0`); the first lands with M0-EXIT-01. diff --git a/docs/benchmarks/methodology.md b/docs/benchmarks/methodology.md new file mode 100644 index 0000000..c5fb8e6 --- /dev/null +++ b/docs/benchmarks/methodology.md @@ -0,0 +1,159 @@ +# Benchmark methodology + +The normative measurement methodology for Laige performance work +(M0-DOC-01; AGENTS §12 report requirements, CORE-001 "measure first", +PRD §8.1 budget policy). It defines what every performance report must +contain, how the `budgets.json` entries map onto it, the baseline-file +convention, and the regression policy that makes budgets CI-enforced. + +The measurement machinery is the budget harness +([api/budget_harness.md](../api/budget_harness.md)): `laige::Histogram`, +`laige::TimeIt`, `loadBudgets`, `budgetCheck`, and the operator tool +`laige-bench` (canonical command in +[building.md](../getting-started/building.md)). + +## 1. Required report fields (AGENTS §12) + +Every performance report — a baseline file under +[`baselines/`](baselines/README.md), a budget result archived with a +milestone, or a before/after pair for an architectural change +(TEST-009) — MUST record: + +| # | Field | What it records | +|---|---|---| +| 1 | Hardware | CPU model/class, RAM, GPU where relevant | +| 2 | OS | Name and version, architecture (x64 / arm64) | +| 3 | Compiler and version | e.g. `g++ 16.2.1`, `MSVC 2022` | +| 4 | Build type | `Debug` (canonical) or `Release`; sanitizer trees named explicitly (`build-asan`, `build-tsan`) | +| 5 | Relevant flags | The engine policy (NFR-8.10) always applies; record any additional flags (e.g. the SimMath pinned set, a sanitizer flag set) | +| 6 | Dataset / workload | The named workload and its defining parameters — the `workload` text of the budget entry is the reference | +| 7 | Warm-up | Iterations discarded before sampling (`--warmup`) | +| 8 | Sample count | `n` — the number of recorded samples (the `n=` of the stats line) | +| 9 | Summary statistics | min / mean / p50 / p95 / p99 / max over the stored window (the `stats:` line) | +| 10 | Before / after | The checked budget's `before=` (last recorded — the entry's `measured`) and `after=` (this run) values | + +Reporting rules (AGENTS §12, PERF-009, PERF-010): + +- **Percentiles, not just averages.** Tail latency is a first-class + result: report p95/p99 and max alongside the mean, never the mean + alone. +- **Prefer repeatable automated benchmarks over ad hoc timings.** Runs + go through the canonical `laige-bench` command so a later reader can + reproduce the number byte-for-byte. +- **Representative workloads** — small, medium, and stress — per + PERF-010; a microbenchmark alone cannot validate an architectural + change. +- **Never change a benchmark solely to make a regression disappear.** + If the workload no longer represents the product, revise it in a + documented step (and the PRD §8.1 table with it, §5 below). + +## 2. How `budgets.json` maps to the report + +`budgets.json` (repo root) is the machine-readable budget table; schema +version 1, strictly validated by `loadBudgets` (ARCH-007; the schema is +documented in [api/budget_harness.md](../api/budget_harness.md)). Every +entry carries exactly six fields, and each maps to a report role: + +| `budgets.json` field | Report role | +|---|---| +| `name` | The budget's identity — the `budget=` of the report's first line and the section/baseline name | +| `metric` | Which statistic the check evaluates (`mean` / `min` / `max` / `p50` / `p95` / `p99`) — the report's `metric=` field | +| `unit` | The unit of `target`, `measured`, and every measured value | +| `target` | The hard PRD §8.1 limit — an at-most upper bound; `target == 0` is a **hard-zero budget** (e.g. `sim_heap_allocs`), not "not set" | +| `measured` | The last recorded value — the **before** number of the before/after pair. Updated when a run is recorded as the new baseline; `0` is the M0 convention for *not yet measured* | +| `workload` | The workload the budget applies to — the reference text of report field 6. The caller harness measures exactly this workload and echoes it in `context: workload=` | + +`budgetCheck` produces the before/after pair automatically: `after` is +the current run's value of `metric` over the histogram window, `before` +is the entry's `measured` field. Recording a run as the new baseline +means writing its `after` value back into `measured` in `budgets.json` +and committing the baseline file (§4) and the table in the **same +change** (CORE-006). + +## 3. The harness report and §12 field coverage + +`budgetCheck` emits the stable 4-line report (LOG-001 machine-greppable; +the format's single source of truth is `laige::formatStatsLine` — see +[api/budget_harness.md](../api/budget_harness.md)): + +```text +budget= result= metric= unit= + after= before= target= + stats: n= min= mean= p50= p95= p99= max= + context: workload= build= machine= warmup= +``` + +Coverage of the §1 field table: + +| Report field | Provided by | +|---|---| +| 10 (before / after / target) | the harness, from the entry and the histogram | +| 8 (`n`), 9 (statistics) | the `stats:` line | +| 6 (workload), 7 (warm-up) | the `context:` line — **caller-supplied**: the operator sets `--workload`/`--warmup` | +| 4 (build), 1 (machine, partially) | the `context:` line — the tool supplies compiler + build type; the operator supplies the machine (`LAIGE_BENCH_MACHINE`) | +| 2 (OS), 3 (compiler version), 5 (flags) | **not in the report** — a baseline file or archived CI log must add them | + +Consequently a baseline file is: the 4-line report verbatim, plus the +remaining §12 fields (hardware, OS, compiler + version, flags), plus the +exact command and the commit it was measured on. + +## 4. Baseline files + +- **Location and naming:** `docs/benchmarks/baselines/-.md` + (e.g. `m0-synthetic.md` — written by M0-EXIT-01 — and + `m1-profiler-cost.md`, written by M1-PROF-01). +- **Content:** the complete §1 record for one measurement: the §12 + fields, the stable 4-line report verbatim, the exact canonical command, + and the measured commit. +- **Immutability:** baseline files are records, not live state. A new run + supersedes an old baseline only by adding a new baseline file and + updating `measured` in `budgets.json` — never by editing an existing + baseline (the before/after history must survive for regressions and + audits). +- **`budgets.json`'s `measured`** always holds the *latest* recorded value + of each budget (its `0` entries mean "not yet measured" until the + subsystem that owns them lands). + +## 5. Regression policy (PRD §8.1, NFR-8.1) + +- **Budgets are part of CI.** A PR that regresses any budget by **> 10%** + against its last recorded value (**`before`**) — or breaches the + absolute **`target`** — fails CI unless the budget is revised via a + PRD revision. +- **CI-gateable:** `laige-bench --budget=` exits `0` on pass and + **`2` on a failed budget check** (`1` = usage or load failure); the + CI lane asserts the exit code. +- **The 10% band needs a baseline:** it applies only when + `before > 0`. A first measurement (`before == 0`, not yet measured) + must still pass the absolute target. +- **Hard-zero budgets have no band:** `target == 0` passes only when the + measured value is exactly 0 (any positive measurement is a failure). +- **`NO_SAMPLES` is a failure, not a skip:** a workload that recorded + nothing is a broken harness (CORE-008 — never silent). +- **Accepted budget revisions** change `budgets.json` in the same PR as + the PRD revision, and are noted in the milestone change log + (DOC-007) — a budget number is never silently moved. + +## 6. Workload discipline + +- **Deterministic workloads first.** The M0 reference workload + (`laige-bench --suite=synthetic`) is deterministic by construction + (fixed Marsaglia LCG64 constants, no RNG, no allocation) — which is + what makes its baseline reproducible across machines and commits. +- **No silent window truncation.** Set the histogram + `capacity >= runs` for a claim over "all samples"; if a rolling window + is used deliberately, check `totalRecorded()` and say so in the report + (the harness never hides a drop — CORE-008). +- **Warm up, then sample.** Discard the first N iterations (canonical + `--warmup=100`) so first-touch costs do not pollute samples; record N + in the report. +- **Tail latency always.** Budgets are at-most upper bounds on a named + percentile (or max/mean) — the `metric` field of the entry — so the + reported statistic must be the one the budget checks, not a friendlier + one. +- **Randomized workloads use the repo-wide seed convention** + ([testing.md §4](../testing.md)): fixed default seed `0x1F055EED`, + overridable, so CI runs of the same commit are comparable. +- **Record the environment.** Runs on different P0 platforms are not + comparable numbers: the §12 hardware/OS fields exist so a baseline + never travels without its machine. diff --git a/docs/compatibility/README.md b/docs/compatibility/README.md new file mode 100644 index 0000000..58783b5 --- /dev/null +++ b/docs/compatibility/README.md @@ -0,0 +1,47 @@ +# Compatibility + +Platforms, compilers, formats, and migration guides (AGENTS §13). + +## P0 platforms and compilers (PRD §6, NFR-8.8 / NFR-8.10) + +| P0 platform | Toolchain | CI jobs | +|---|---|---| +| Linux x64 (arm64 planned) | GCC / Clang | `linux-gcc`, `linux-clang` | +| Windows x64 | MSVC 2022 (clang-cl secondary) | `windows-msvc` | +| macOS arm64 / Intel | AppleClang | `macos-arm64`, `macos-intel` | + +- **Language:** C++20 (NFR-8.10). Engine targets compile with + `-Wall -Werror` and with exceptions/RTTI disabled (the documented MSVC + equivalent). +- **Build system:** CMake ≥ 3.22 (NFR-8.8), single configure, no network + access; all dependencies vendored in-tree and integrity-locked in + `deps.lock`. +- **Library flavors:** static (default) and shared (`LAIGE_BUILD_SHARED`, + NFR-8.9) both supported. +- **Sanitizers:** ASan+UBSan and TSan build trees on Linux + (NFR-8.2); see [building.md](../getting-started/building.md) — the + source of truth for the canonical commands and the CI matrix + (`.github/workflows/ci.yml` / `ci-pull.yml`). + +## Formats + +No persistent, networked, or replay data formats exist yet (M0 is +foundations only; they arrive with M1 replay and M6/M7 networking). The +machine-readable files that do exist, each with its schema documented: + +| File | Schema | Document | +|---|---|---| +| `budgets.json` | version 1, strict validation (ARCH-007) | [api/budget_harness.md](../api/budget_harness.md) ("budgets.json schema") | +| `laige-api.json` | manifest version 1, deterministic (byte-identical regeneration is the CI drift check) | the `tools/api/laige-api.cpp` header (M0-TOOL-01) | +| `deps.lock` | one entry per vendored dependency, integrity-checked at configure time | [ADR 0004](../decisions/0004-google-test-vendoring.md) | + +When a persistent format lands it MUST ship versioned, with a reader that +rejects or migrates unsupported data explicitly (ARCH-007) and a format +document added to this section in the same change (DOC-007). + +## Migration guides + +None yet: the engine is pre-1.0 and M0 has introduced no breaking public +changes. The first migration guide lands with the first breaking +public-API change; public API/ABI versioning is governed by the manifest +(NFR-13.1) and API-007. diff --git a/docs/concepts/README.md b/docs/concepts/README.md new file mode 100644 index 0000000..4d2056b --- /dev/null +++ b/docs/concepts/README.md @@ -0,0 +1,18 @@ +# Concepts + +Architecture, coordinates, lifecycle, and threading concepts +(AGENTS §13). **Nothing in this section is written yet** — M0 is +foundations only. The topics below are planned, and each document lands +with the milestone that defines it; until then the interim homes are: + +| Topic | Planned document | Interim home (today) | +|---|---|---| +| World axes, handedness, units, depth convention, render ordering, conversion rules (ARCH-008) | `coordinates.md` | The `Vec2`/`Vec3` comments in `src/laige-core/include/laige/sim_math.h` ((x, y) is the ground plane, z is depth/height) and the SimMath API contract in [api/sim_math.md](../api/sim_math.md) | +| Determinism scope (ARCH-010) | `determinism.md` | [ADR 0002](../decisions/0002-deterministic-math.md) (which paths use which backend), [api/sim_math.md](../api/sim_math.md) (NaN/Inf policy, pinned flags), [api/detcheck.md](../api/detcheck.md) (replay comparison contract) | +| Engine / scene / entity lifecycle; the fixed-timestep rule (ARCH-002) | `lifecycle.md` | — (the M1 loop steps define it) | +| Threading and ownership model (CONC-001…CONC-007) | `threading.md` | The per-API contracts in [api/](../api/) — each document states its threading, lifetime, and phase rules | +| Module architecture (PRD §10.1 stack) | `architecture.md` | The PRD §10.1 module map, enforced by the include-graph lint (`tools/laige-include-lint`, M0-CI-03) | + +Normative decisions about these topics live as ADRs in +[../decisions/](../decisions/README.md); this section will explain the +chosen designs once they exist. diff --git a/docs/debugging/README.md b/docs/debugging/README.md new file mode 100644 index 0000000..7b819ec --- /dev/null +++ b/docs/debugging/README.md @@ -0,0 +1,19 @@ +# Debugging + +Debug mode, logging, profiling, and troubleshooting (AGENTS §13). +The in-engine debug system (AGENTS §15: searchable overlay registry, +"Always"/"Debug" profiles) **does not exist yet** — its foundations +land with the profiling work (M1-PROF-01 counters, M2-PROF-01 render +timing). Until then this section indexes what is usable today: + +| Need | Document | +|---|---| +| Read and emit structured logs; severity contract, rate limiting, file sinks, crash handling | [api/logging.md](../api/logging.md) (M0-CORE-02; AGENTS §14) | +| Measure a suspected performance problem (rolling histograms, percentiles, budget checks) | [api/budget_harness.md](../api/budget_harness.md) + [benchmarks/methodology.md](../benchmarks/methodology.md) | +| Prove a determinism divergence (two builds, per-tick hash streams) | [api/detcheck.md](../api/detcheck.md) (M0-TOOL-02) | +| Find undefined behavior or data races locally | Sanitizer builds in [building.md](../getting-started/building.md) (`build-asan` / `build-tsan` trees; NFR-8.2) | +| Reproduce flaky behavior in tests (fixed seeds, KATs) | [testing.md](../testing.md) (seed convention, §4) | + +When the debug mode lands, this section grows with the overlay-registry +documentation, the Always/Debug profiles, counter capture (DBG-007), and +troubleshooting guides. diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 0597387..5c00a4b 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -1,7 +1,9 @@ # Architecture Decision Records -Index of ADRs (AGENTS.md DOC-005). The full `docs/` structure and this index's -expansion arrive with roadmap step **M0-DOC-01**. +Index of ADRs (AGENTS.md DOC-005). Significant architectural choices and +rule exceptions land here as ADRs containing context, decision, +alternatives, evidence, consequences, and review conditions; the full +`docs/` structure is indexed from [../README.md](../README.md). | ADR | Title | Status | Date | |---|---|---|---| diff --git a/docs/guides/README.md b/docs/guides/README.md new file mode 100644 index 0000000..83b007e --- /dev/null +++ b/docs/guides/README.md @@ -0,0 +1,19 @@ +# Guides + +Task-oriented usage and optimization guides (AGENTS §13). +**No guides exist yet** — M0 is foundations only. Guides land with the +milestones whose features they teach: + +| Planned guide | Lands with | +|---|---| +| First headless game project (template, first tick) | M1 (headless template, M1-SAMPLE-01) | +| Determinism and replay (seeded runs, lockstep, `laige-detcheck`) | M1 (M1-DET-*) | +| Profiling and working under a budget | M1 (M1-PROF-01) — see also [benchmarks/methodology.md](../benchmarks/methodology.md) | +| Rendering a 2.5D scene (isometric, parallax, depth order) | M2 | +| Server / zone setup for an MMO | M6 / M7 | + +Documentation that is guide-like today: +[building.md](../getting-started/building.md) (building), +[testing.md](../testing.md) (testing conventions), +[api/budget_harness.md](../api/budget_harness.md) (measuring), +[api/detcheck.md](../api/detcheck.md) (verifying determinism). From d4c7f44f145b923b2f27d75b00b5b8277e1b3821 Mon Sep 17 00:00:00 2001 From: Pascal Severin Date: Sun, 13 Sep 2026 11:26:06 +0200 Subject: [PATCH 2/3] [M0-DOC-01] Roadmap records: check the box, Decision/Verify/Size notes, board + change log - M0-foundations.md: M0-DOC-01 marked done with the house-style Decision (2026-09-13), Verify (manual per the step's 'CI or manual' clause: index coverage, 49-file dead-link check with 0 dead links, ADR refs, budgets.json mapping, ctest 32/32), and Size notes. - roadmap/README.md: progress board M0 20->21 done (of 22), total 20->21; change-log line for M0-DOC-01 (commit 972090d). --- roadmap/M0-foundations.md | 52 ++++++++++++++++++++++++++++++++++++--- roadmap/README.md | 5 ++-- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/roadmap/M0-foundations.md b/roadmap/M0-foundations.md index 7e3b5ae..fcc7e85 100644 --- a/roadmap/M0-foundations.md +++ b/roadmap/M0-foundations.md @@ -919,14 +919,60 @@ No rendering, no physics, no networking yet — `laige-core` only. override, loud failure, substream isolation — cohesively rather than split) -- [ ] **M0-DOC-01 · `docs/` skeleton + index** +- [x] **M0-DOC-01 · `docs/` skeleton + index** - **Refs:** AGENTS §13 (DOC-001…DOC-007), PRD NFR-8.12 - **Depends:** M0-DEC-01, M0-DEC-02, M0-DEC-03 - **Scope:** - Create the full AGENTS §13 structure: `docs/README.md` (index linking every section, honest about incomplete areas), `getting-started/`, `concepts/`, `api/`, `guides/`, `debugging/`, `benchmarks/` (with an empty `baselines/`), `decisions/` (index + the three ADRs from M0-DEC), `compatibility/`. - `docs/benchmarks/methodology.md`: required report fields per AGENTS §12, and how budget entries in `budgets.json` map to them. - - **Verify:** `docs/README.md` links every section; no dead links (checked in CI or manual); the three ADRs are referenced from the decisions index. - - **Size:** docs only + - **Decision (2026-09-13):** the full AGENTS §13 `docs/` tree now + exists: `docs/README.md` rewritten as the single index (links every + section; an explicit "not yet written" list keeps the status honest + per DOC-001); new section indexes — `concepts/README.md` (planned + documents + interim homes, incl. the coordinates/ARCH-008 topic + documented today in the `Vec2`/`Vec3` comments of + `src/laige-core/include/laige/sim_math.h`), `guides/README.md` + (milestone mapping), `debugging/README.md` (what is usable today + + the AGENTS §15 debug-mode status), `compatibility/README.md` + (evidence-based P0 platform/compiler table per PRD §6 and the CI + matrix; the current machine-readable formats — `budgets.json` v1, + `laige-api.json` v1, `deps.lock` — and the migration status: none + yet, pre-1.0); `docs/benchmarks/` with `methodology.md` (normative: + the AGENTS §12 report-field table, the `budgets.json` + field→report mapping, the immutable baseline-file convention, the + PRD §8.1 regression policy incl. the >10% band, hard-zero budgets, + and `NO_SAMPLES`) and `baselines/` (README placeholder; the first + baseline `m0-synthetic.md` lands with M0-EXIT-01). + `decisions/README.md` updated (the stale "arrives with M0-DOC-01" + note replaced; ADRs 0001–0004 remain indexed). Stale-reference + housekeeping in the same change (DOC-003): root `README.md` (the + docs line now points to `docs/README.md`; the ADR list corrected to + 0001–0004) and the old index's reference to a non-existent + "M0-DOC-02" step dropped (the coordinates topic is carried by the + concepts index with its interim home). + - **Verify:** (verified manually 2026-09-13 — the step's Verify allows + "checked in CI or manual" and the scope is docs-only, so no CI job + was added): (a) `docs/README.md` links every AGENTS §13 section — + getting-started, concepts, api, guides, debugging, benchmarks, + decisions, compatibility — plus the testing conventions and the + related documents; (b) repo-wide dead-link check over all 49 + `*.md` files (104 internal links checked; stdlib-only script; + external URLs skipped): **zero dead links**; (c) the decisions + index references ADR 0001, 0002, 0003 (the three M0-DEC ADRs) and + 0004 (M0-DEP-01); (d) the 15 `budgets.json` entries map + field-by-field onto the methodology's report table, and the stable + 4-line report format stays sourced from + `docs/api/budget_harness.md` (referenced, not duplicated); + (e) no build/test impact (docs only) — the existing `build` tree + re-ran `ctest` 32/32 green, and the full P0 CI lane runs on this + step's PR (`ci-pull.yml`). + - **Size:** ~420 lines of docs (7 new files: `methodology.md` 159, + four section indexes 18–47, `benchmarks/README.md` 22, + `baselines/README.md` 20; updated: `docs/README.md` 118, + `docs/decisions/README.md`, root `README.md`) + the roadmap records + (over the "docs only" estimate by nature: `methodology.md` carries + the normative AGENTS §12 ↔ `budgets.json` mapping — cohesive, not + split) ## Milestone gate diff --git a/roadmap/README.md b/roadmap/README.md index 274ac12..d65a37b 100644 --- a/roadmap/README.md +++ b/roadmap/README.md @@ -155,7 +155,7 @@ Updated in the same PR that closes steps. "Done" = box checked + Verify green. | Milestone | Steps | Done | Status | |---|---|---|---| -| M0 | 22 | 20 | ▶ in progress | +| M0 | 22 | 21 | ▶ in progress | | M1 | 25 | 0 | ⬜ not started | | M2 | 32 | 0 | ⬜ not started | | M3 | 36 | 0 | ⬜ not started | @@ -165,7 +165,7 @@ Updated in the same PR that closes steps. "Done" = box checked + Verify green. | M7 | 15 | 0 | ⬜ not started | | M8 | 8 | 0 | ⬜ not started | | M9 | 6 | 0 | ⬜ proposals only | -| **Total** | **193** | **20** | | +| **Total** | **193** | **21** | | --- @@ -193,6 +193,7 @@ One line per completed (or split/renumbered) step. | 2026-09-12 | M0-TOOL-01 | `937ac7c` | API manifest (NFR-13.1, PRD §9.4): `laige-api` target + `tools/api/laige-api-scanner` (line-oriented state machine — no regex pass; loud failure on every unsupported construct; doc association from consecutive `//` blocks with `@budget`/`@experimental` tags; `--check FILE` byte compare + symbol-level diff via `laige::parseJson`; exit 0 OK / 1 stale / 2 error) + checked-in `laige-api.json` (version 1, deterministic, no timestamps — byte-identical regeneration is the drift check) + `tests/api` CTest entries (fixture tree with exact manifest bytes, fresh/stale, unsupported-construct failure, real-tree `--check`) + the `api-manifest` CI job (every PR and merge, fails on drift); (board/changelog row retroactively added 2026-09-12 — the step merged as `937ac7c`/PR #10 without updating this board or log) | | 2026-09-12 | M0-TOOL-02 | `fe4460c` | Determinism checker skeleton (FR-11.5, AGENTS ARCH-010, TEST-004): `laige-detcheck` (`tools/detcheck`) runs a named scenario in two build configurations and compares per-tick hash streams; scenario contract (normative in the tool header, mirrored in `docs/api/detcheck.md`): one stdout line per tick ` ` — 16 lowercase hex hash digits (algorithm NOT part of the contract — lines compare byte-for-byte), tick starts at 0 step 1 no padding, trailing newline optional / trailing `\r` tolerated, stderr ignored, exit 0 — enforced strictly and bounded (65536 ticks, 64 bytes/line; a violation is a loud exit 2, CORE-008); modes: `--scenario=synthetic\|synthetic-perturbed` (built-in 32-body `fpx16_16`+Prng workload, two in-process runs — pure integer arithmetic, bit-exact per ADR 0002; perturbation fixture: +1 unit to body 3's x at tick 7) and `--run-a= --run-b= [-- scenario-args...]` (the M1-DET-04 mode; `--` separator keeps scenario args unambiguous); stable report `detcheck scenario= result=OK\|DIVERGED [first_diff_tick=]` + run-a/run-b lines (LOG-001); exit 0 match / 1 divergence / 2 error; POSIX fork/exec + pipe capture, Windows CreateProcessW + PeekNamedPipe (no shell, bounded memory, scenario stderr stays on the CI log); 9 CTest entries (`tests/detcheck`, `ctest -R detcheck`): self-check, built-in perturbation, identical/diverged/malformed/failure/short-stream cross-binary pairs — one fixture source, five compiled variants — each a generated `cmake -P` script asserting exit code + output fragments (tests/api pattern); CI `detcheck` job in ci-pull.yml/ci.yml (every PR and merge, no ci:* condition — tooling check, not a P0 OS build): runs the synthetic self-check and SKIPS the real-scenario step (two build configurations of M1-SAMPLE-01's hello) until it lands — M1-DET-04 activates it; local Verify: ctest 31/31, zero warnings on g++ static/shared, clang++, ASan+UBSan, TSan trees; Windows path compile-verified by the CI MSVC job — but NOT runtime-verified (stale as of 2026-09-13: the mode-2 capture was broken on the Windows CI runner and the mode-2 fragment assertions were dead, so the Windows failures were silent; both were found and fixed inside M0-TEST-01 / PR #13 — see the 2026-09-13 row); CI (observed 2026-09-12 via the GitHub API): `ci-pull.yml` run 34697638239 on `82c548d` green - the default-Linux lane's four P0/sanitizer jobs (linux-gcc, linux-clang, linux-asan+UBSan, linux-tsan) plus all three tooling jobs (include-lint, api-manifest, detcheck) passed; Windows/macOS jobs label-skipped as expected; the new `detcheck` job's real-scenario step correctly reported `skipped: no real scenario yet (M1-SAMPLE-01)` | | 2026-09-12 | M0-TEST-01 | `a292aef` | Test infrastructure conventions (docs/testing.md, source of truth, linked from docs/README.md, tests/README.md, building.md, README.md): tests/support/laige_test_seed.h (TestSeed()/TestPrng() — fixed default 0x1F055EED, identical to laige-fuzz's kDefaultSeed, one documented default seed repo-wide; LAIGE_TEST_SEED env override, 0x-hex/decimal, read at call time; set-but-unparseable value records a loud test failure and falls back to the default — CORE-008; per-test substream ids so streams never share position) + tests/testing (test_infra_tests, CTest entry `test_infra`, SeededRandom suite, 6 cases: 65536-draw FNV-1a KATs under the default seed 0x7EA4049545656830 and override seed 0x535D2CA741B61CBF, first-8-draw KAT, default/fuzz seed identity, loud invalid-env path via EXPECT_NONFATAL_FAILURE (gtest-spi.h), seed parser, substream isolation; machine-greppable `test-seed-check` line per KAT before asserting — the byte-identical-across-two-CI-runs identity check, M0-TEST-01 Verify) + first regress_ test (M0-CORE-08's ConfigJsonValid.ObjectMemberWhitespace renamed regress_json_object_member_ws; suite unchanged so `ctest -R config_json` still covers it; historical M0-CORE-08 record unchanged) + fuzz lane semantics (no new CI job — bounded --runs=1000 is the existing fuzz_json_parse ctest entry inside every P0 job's ctest, PRD §14 "every commit (bounded)"; nightly long form --runs=1000000 documented in docs/testing.md §3 + canonical command table; scheduled nightly lane lands with the first M1 fuzz target); CI workflow headers note the fuzz lane; local Verify: 32/32 ctest, zero warnings under NFR-8.10, on g++ static/shared, ASan+UBSan, TSan, and Clang trees; seeded KAT line identical on g++ and clang++ locally; cross-CI-run Verify: byte-identical `test-seed-check` lines in the archived Linux ASan `LastTest.log` across runs 34713354925/34714039135 (same-commit pair) and again across commits e2abce5→c8b8221 (runs 34728782624/34746755055); Windows CI fix chain landed inside this PR (M0-TOOL-02's Windows path, provenance per the established pattern — see the corrected M0-TOOL-02 row): MSVC portability (NOMINMAX, `getenv_s`/`fopen_s` C4996, C2664/C2440/C4457/C2660), `WaitForSingleObject` before `GetExitCodeProcess` (STILL_ACTIVE), then the root cause — the CI Windows runner (windows-2022) never delivers handles the process creates itself (pipes or files, INHERIT bit confirmed set, even duplicated) to children through `STARTUPINFO`; only parent-inherited (kernel-assigned) handles are delivered (measured runs 34728950395/34729337292) — and NULL `STARTUPINFO` is rejected by its CreateProcess machinery (run 34732057356); fixed by two-stage marker capture on all platforms (phase 1 `--run-a/--run-b` spawns with plain stdout inheritance + `@@DETCHK-RUN-A/B-BEGIN/END@@` markers; phase 2 `--compare-combined` splits/validates/compares) plus the zeroed-STARTUPINFO spawn; dead fragment assertions fixed in `7928379` (`@CHECKS@` variable-name misspelling + CMake single-backslash stripping → double-escaped regexes); final CI run 34746755055 (c8b8221): all 10 jobs green, Windows 32/32 | +| 2026-09-13 | M0-DOC-01 | `972090d` | Docs only: full AGENTS §13 `docs/` tree — `docs/README.md` rewritten as the single index (every section linked + honest "not yet written" list, DOC-001); new section indexes `concepts/` (planned docs + interim homes incl. the ARCH-008 coordinates topic), `guides/`, `debugging/` (usable today; AGENTS §15 debug-mode status), `compatibility/` (P0 platform/compiler table per PRD §6 + CI, current formats `budgets.json`/`laige-api.json`/`deps.lock`, no migration guides yet); `docs/benchmarks/` with `methodology.md` (normative AGENTS §12 report fields, `budgets.json` field→report mapping, immutable baseline-file convention, PRD §8.1 regression policy: >10% band, hard-zero budgets, loud `NO_SAMPLES`) and empty `baselines/` (first baseline `m0-synthetic.md` lands with M0-EXIT-01); `decisions/` index updated (stale M0-DOC-01 note replaced; ADRs 0001–0004 indexed); stale references fixed in the same change (root README docs pointer + ADR 0004; old index's non-existent "M0-DOC-02" reference dropped); dead-link check over all 49 repo `*.md` files (104 internal links, 0 dead — manual per the step's Verify clause; docs-only scope, no CI job added); `ctest` 32/32 green on the existing `build` tree | --- From 8404ffad41695469c2b614c477fb7004e8ade756 Mon Sep 17 00:00:00 2001 From: Pascal Severin Date: Sun, 13 Sep 2026 11:31:02 +0200 Subject: [PATCH 3/3] [M0-DOC-01] Record observed CI run in the step and change-log records MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ci-pull.yml run 34749554015 on PR #14: all 7 executed jobs green (linux-gcc, linux-clang, linux-asan+UBSan, linux-tsan, include-lint, api-manifest, detcheck); macOS/Windows skipped (label-gated, PRD §14 cadence). --- roadmap/M0-foundations.md | 6 +++++- roadmap/README.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/roadmap/M0-foundations.md b/roadmap/M0-foundations.md index fcc7e85..61c8512 100644 --- a/roadmap/M0-foundations.md +++ b/roadmap/M0-foundations.md @@ -965,7 +965,11 @@ No rendering, no physics, no networking yet — `laige-core` only. `docs/api/budget_harness.md` (referenced, not duplicated); (e) no build/test impact (docs only) — the existing `build` tree re-ran `ctest` 32/32 green, and the full P0 CI lane runs on this - step's PR (`ci-pull.yml`). + step's PR (`ci-pull.yml`). CI observed 2026-09-13 via the GitHub + API: `ci-pull.yml` run 34749554015 on PR #14 — all 7 executed jobs + green (linux-gcc, linux-clang, linux-asan+UBSan, linux-tsan, + include-lint, api-manifest, detcheck); macOS/Windows skipped + (label-gated, PRD §14 cadence). - **Size:** ~420 lines of docs (7 new files: `methodology.md` 159, four section indexes 18–47, `benchmarks/README.md` 22, `baselines/README.md` 20; updated: `docs/README.md` 118, diff --git a/roadmap/README.md b/roadmap/README.md index d65a37b..3ab99e0 100644 --- a/roadmap/README.md +++ b/roadmap/README.md @@ -193,7 +193,7 @@ One line per completed (or split/renumbered) step. | 2026-09-12 | M0-TOOL-01 | `937ac7c` | API manifest (NFR-13.1, PRD §9.4): `laige-api` target + `tools/api/laige-api-scanner` (line-oriented state machine — no regex pass; loud failure on every unsupported construct; doc association from consecutive `//` blocks with `@budget`/`@experimental` tags; `--check FILE` byte compare + symbol-level diff via `laige::parseJson`; exit 0 OK / 1 stale / 2 error) + checked-in `laige-api.json` (version 1, deterministic, no timestamps — byte-identical regeneration is the drift check) + `tests/api` CTest entries (fixture tree with exact manifest bytes, fresh/stale, unsupported-construct failure, real-tree `--check`) + the `api-manifest` CI job (every PR and merge, fails on drift); (board/changelog row retroactively added 2026-09-12 — the step merged as `937ac7c`/PR #10 without updating this board or log) | | 2026-09-12 | M0-TOOL-02 | `fe4460c` | Determinism checker skeleton (FR-11.5, AGENTS ARCH-010, TEST-004): `laige-detcheck` (`tools/detcheck`) runs a named scenario in two build configurations and compares per-tick hash streams; scenario contract (normative in the tool header, mirrored in `docs/api/detcheck.md`): one stdout line per tick ` ` — 16 lowercase hex hash digits (algorithm NOT part of the contract — lines compare byte-for-byte), tick starts at 0 step 1 no padding, trailing newline optional / trailing `\r` tolerated, stderr ignored, exit 0 — enforced strictly and bounded (65536 ticks, 64 bytes/line; a violation is a loud exit 2, CORE-008); modes: `--scenario=synthetic\|synthetic-perturbed` (built-in 32-body `fpx16_16`+Prng workload, two in-process runs — pure integer arithmetic, bit-exact per ADR 0002; perturbation fixture: +1 unit to body 3's x at tick 7) and `--run-a= --run-b= [-- scenario-args...]` (the M1-DET-04 mode; `--` separator keeps scenario args unambiguous); stable report `detcheck scenario= result=OK\|DIVERGED [first_diff_tick=]` + run-a/run-b lines (LOG-001); exit 0 match / 1 divergence / 2 error; POSIX fork/exec + pipe capture, Windows CreateProcessW + PeekNamedPipe (no shell, bounded memory, scenario stderr stays on the CI log); 9 CTest entries (`tests/detcheck`, `ctest -R detcheck`): self-check, built-in perturbation, identical/diverged/malformed/failure/short-stream cross-binary pairs — one fixture source, five compiled variants — each a generated `cmake -P` script asserting exit code + output fragments (tests/api pattern); CI `detcheck` job in ci-pull.yml/ci.yml (every PR and merge, no ci:* condition — tooling check, not a P0 OS build): runs the synthetic self-check and SKIPS the real-scenario step (two build configurations of M1-SAMPLE-01's hello) until it lands — M1-DET-04 activates it; local Verify: ctest 31/31, zero warnings on g++ static/shared, clang++, ASan+UBSan, TSan trees; Windows path compile-verified by the CI MSVC job — but NOT runtime-verified (stale as of 2026-09-13: the mode-2 capture was broken on the Windows CI runner and the mode-2 fragment assertions were dead, so the Windows failures were silent; both were found and fixed inside M0-TEST-01 / PR #13 — see the 2026-09-13 row); CI (observed 2026-09-12 via the GitHub API): `ci-pull.yml` run 34697638239 on `82c548d` green - the default-Linux lane's four P0/sanitizer jobs (linux-gcc, linux-clang, linux-asan+UBSan, linux-tsan) plus all three tooling jobs (include-lint, api-manifest, detcheck) passed; Windows/macOS jobs label-skipped as expected; the new `detcheck` job's real-scenario step correctly reported `skipped: no real scenario yet (M1-SAMPLE-01)` | | 2026-09-12 | M0-TEST-01 | `a292aef` | Test infrastructure conventions (docs/testing.md, source of truth, linked from docs/README.md, tests/README.md, building.md, README.md): tests/support/laige_test_seed.h (TestSeed()/TestPrng() — fixed default 0x1F055EED, identical to laige-fuzz's kDefaultSeed, one documented default seed repo-wide; LAIGE_TEST_SEED env override, 0x-hex/decimal, read at call time; set-but-unparseable value records a loud test failure and falls back to the default — CORE-008; per-test substream ids so streams never share position) + tests/testing (test_infra_tests, CTest entry `test_infra`, SeededRandom suite, 6 cases: 65536-draw FNV-1a KATs under the default seed 0x7EA4049545656830 and override seed 0x535D2CA741B61CBF, first-8-draw KAT, default/fuzz seed identity, loud invalid-env path via EXPECT_NONFATAL_FAILURE (gtest-spi.h), seed parser, substream isolation; machine-greppable `test-seed-check` line per KAT before asserting — the byte-identical-across-two-CI-runs identity check, M0-TEST-01 Verify) + first regress_ test (M0-CORE-08's ConfigJsonValid.ObjectMemberWhitespace renamed regress_json_object_member_ws; suite unchanged so `ctest -R config_json` still covers it; historical M0-CORE-08 record unchanged) + fuzz lane semantics (no new CI job — bounded --runs=1000 is the existing fuzz_json_parse ctest entry inside every P0 job's ctest, PRD §14 "every commit (bounded)"; nightly long form --runs=1000000 documented in docs/testing.md §3 + canonical command table; scheduled nightly lane lands with the first M1 fuzz target); CI workflow headers note the fuzz lane; local Verify: 32/32 ctest, zero warnings under NFR-8.10, on g++ static/shared, ASan+UBSan, TSan, and Clang trees; seeded KAT line identical on g++ and clang++ locally; cross-CI-run Verify: byte-identical `test-seed-check` lines in the archived Linux ASan `LastTest.log` across runs 34713354925/34714039135 (same-commit pair) and again across commits e2abce5→c8b8221 (runs 34728782624/34746755055); Windows CI fix chain landed inside this PR (M0-TOOL-02's Windows path, provenance per the established pattern — see the corrected M0-TOOL-02 row): MSVC portability (NOMINMAX, `getenv_s`/`fopen_s` C4996, C2664/C2440/C4457/C2660), `WaitForSingleObject` before `GetExitCodeProcess` (STILL_ACTIVE), then the root cause — the CI Windows runner (windows-2022) never delivers handles the process creates itself (pipes or files, INHERIT bit confirmed set, even duplicated) to children through `STARTUPINFO`; only parent-inherited (kernel-assigned) handles are delivered (measured runs 34728950395/34729337292) — and NULL `STARTUPINFO` is rejected by its CreateProcess machinery (run 34732057356); fixed by two-stage marker capture on all platforms (phase 1 `--run-a/--run-b` spawns with plain stdout inheritance + `@@DETCHK-RUN-A/B-BEGIN/END@@` markers; phase 2 `--compare-combined` splits/validates/compares) plus the zeroed-STARTUPINFO spawn; dead fragment assertions fixed in `7928379` (`@CHECKS@` variable-name misspelling + CMake single-backslash stripping → double-escaped regexes); final CI run 34746755055 (c8b8221): all 10 jobs green, Windows 32/32 | -| 2026-09-13 | M0-DOC-01 | `972090d` | Docs only: full AGENTS §13 `docs/` tree — `docs/README.md` rewritten as the single index (every section linked + honest "not yet written" list, DOC-001); new section indexes `concepts/` (planned docs + interim homes incl. the ARCH-008 coordinates topic), `guides/`, `debugging/` (usable today; AGENTS §15 debug-mode status), `compatibility/` (P0 platform/compiler table per PRD §6 + CI, current formats `budgets.json`/`laige-api.json`/`deps.lock`, no migration guides yet); `docs/benchmarks/` with `methodology.md` (normative AGENTS §12 report fields, `budgets.json` field→report mapping, immutable baseline-file convention, PRD §8.1 regression policy: >10% band, hard-zero budgets, loud `NO_SAMPLES`) and empty `baselines/` (first baseline `m0-synthetic.md` lands with M0-EXIT-01); `decisions/` index updated (stale M0-DOC-01 note replaced; ADRs 0001–0004 indexed); stale references fixed in the same change (root README docs pointer + ADR 0004; old index's non-existent "M0-DOC-02" reference dropped); dead-link check over all 49 repo `*.md` files (104 internal links, 0 dead — manual per the step's Verify clause; docs-only scope, no CI job added); `ctest` 32/32 green on the existing `build` tree | +| 2026-09-13 | M0-DOC-01 | `972090d` | Docs only: full AGENTS §13 `docs/` tree — `docs/README.md` rewritten as the single index (every section linked + honest "not yet written" list, DOC-001); new section indexes `concepts/` (planned docs + interim homes incl. the ARCH-008 coordinates topic), `guides/`, `debugging/` (usable today; AGENTS §15 debug-mode status), `compatibility/` (P0 platform/compiler table per PRD §6 + CI, current formats `budgets.json`/`laige-api.json`/`deps.lock`, no migration guides yet); `docs/benchmarks/` with `methodology.md` (normative AGENTS §12 report fields, `budgets.json` field→report mapping, immutable baseline-file convention, PRD §8.1 regression policy: >10% band, hard-zero budgets, loud `NO_SAMPLES`) and empty `baselines/` (first baseline `m0-synthetic.md` lands with M0-EXIT-01); `decisions/` index updated (stale M0-DOC-01 note replaced; ADRs 0001–0004 indexed); stale references fixed in the same change (root README docs pointer + ADR 0004; old index's non-existent "M0-DOC-02" reference dropped); dead-link check over all 49 repo `*.md` files (104 internal links, 0 dead — manual per the step's Verify clause; docs-only scope, no CI job added); `ctest` 32/32 green on the existing `build` tree; CI run 34749554015: 7/7 executed jobs green (macOS/Windows skipped, label-gated) | ---