feat(scheduler-core): implement what-if branching and simulation output recording (task 11.5)

Add sim_record.c (scheduler_t-free .replay writer: ReplayHeader + loaded
SnapshotEntry once, then per-event pass-through and per-session
ReplaySession finalization) and wire --sim-alt-events event-source
selection into sim_loop.c's drain loop, coexisting with task 11.2's
stdout default and task 11.4's --sim-verify. Extract scheduler_t-free
halves out of recording_session.c's begin/end so sim-side code can reuse
the decision-encoding path without gaining an xce_scheduler_t* dependency,
preserving Req 5 AC 17 isolation. Per Req 5 AC 16/19.
This commit is contained in:
Rongsong Shen 2026-08-07 02:42:50 +00:00
parent a6083d803e
commit 564408e967
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
14 changed files with 1750 additions and 91 deletions

View file

@ -52,6 +52,19 @@
* it; this task only stores it)
* bool interactive; -- --interactive/-i (task 12 acts on
* it; this task only stores it)
*
* `snapshot_ts` below is ONE field beyond design.md's literal 8-field
* struct sketch (scheduler-core spec, task 11.5, Req 5 AC 19) -- added, not
* merely implied, because writing a `--sim-output` file's initial
* SnapshotEntry needs the EXACT timestamp Step 2's snapshot scan
* (sim_locate_and_load_snapshot(), sim.c) chose, and re-deriving it via
* xce_core_now(&sim->core) from inside sim_loop.c's event loop is NOT
* equivalent for any --sim-speed other than frozen (0): the virtual clock
* keeps advancing with real wall-clock time between
* sched_sim_driver_start() returning and sim_loop.c's first opportunity to
* write the output header/snapshot, so a re-derived value would drift from
* "the same SnapshotEntry that was loaded" (AC 19's own wording -- same ts,
* not merely a same-shaped one taken moments later).
*/
typedef struct {
xce_sched_core_t core;
@ -62,6 +75,7 @@ typedef struct {
uint64_t sim_speed_den;
bool verify;
bool interactive;
uint64_t snapshot_ts;
} xce_sched_sim_driver_t;
/*