- Make the shared
.cdtRNG contract address-driven and minimal: the canonical per-draw attribution token is the original executable’scaller_static_u32. - Scope this branch to the shared trace schema, Frida finalization, Python replay recording, and the diff/focus consumers. Zig producer changes are explicitly deferred to a follow-up branch.
- Use
.cdtas the only shared authoritative format. Frida raw JSONL may keep producer-private detail, but no extra shared RNG semantics live only on the Frida side.
- Bump debug trace schema from
7to8and update the spec/docs accordingly. - Simplify
RngStreamRowto:tick_call_indexvalue_15state_before_u32state_after_u32caller_static_u32: int | None
- Remove
branch_idfrom the shared durable schema entirely. - Keep
caller_static_u32as an integer on disk; render it as hex only in human-facing output. - Update Frida finalize so raw
caller_statichex strings are canonicalized into durablecaller_static_u32ints when building.cdtrows. - Leave Frida raw capture format private; no raw-format compatibility layer is required beyond what finalize already consumes.
- Change
grim.rand.CrtRand.rand()to accept explicit per-draw provenance:rand(*, caller_static_u32: int | None = None) -> int
- Expand the trace sink contract so Python runtime recording receives
caller_static_u32with each draw, anddbg recordwrites it intoRngStreamRow. - Add strict trace mode for replay/differential recording:
- when active, any RNG draw emitted during supported gameplay replay recording without
caller_static_u32fails the trace immediately. - this strictness applies to the replay trace path, not to normal gameplay outside debug recording.
- when active, any RNG draw emitted during supported gameplay replay recording without
- Audit and tag the first-wave gameplay areas in this order:
- creature spawning
- effects / FX RNG
- perks
- projectiles / weapon fire
- creature runtime
- bonuses
- Use original static addresses directly at call sites; do not add a semantic
site_idlayer or resolver registry in this branch.
- Update
dbg diff,focus, and RNG comparison helpers to treatcaller_static_u32as part of the shared RNG row and include it in mismatch details. - Human-facing reports should print the address in hex form (for example
0x00430b88) so divergence still maps cleanly to HLIL/decompile work. - Do not add phase-anchor redesign, resolver tables, or decompile-link generation in this branch; those stay as follow-up work.
- Unit tests for
CrtRand.rand():- tagged draw reaches the trace sink with the correct address
- strict trace mode rejects missing
caller_static_u32
- Python record tests:
- recorded
.cdtrows containcaller_static_u32 - schema v8 trace metadata and channel payloads encode/decode cleanly
- recorded
- Frida finalize tests:
- raw hex
caller_staticbecomes durablecaller_static_u32 - legacy
branch_idno longer appears in schema v8 rows
- raw hex
- Consumer tests:
- RNG mismatch detail includes
caller_static_u32 - first-mismatch reporting still works with the simplified row shape
- RNG mismatch detail includes
- One short replay integration scenario that exercises at least spawn, fire/effects, and perk RNG, and fails if any audited gameplay draw is left untagged.
- No compatibility fallback: schema v8 readers accept v8 only, consistent with current trace-version policy.
- Zig remains on the old producer path for this branch and will need a follow-up branch to emit actual tagged draws instead of reconstructed RNG transitions.
- The root memo and format docs should be updated to reflect the new
caller_static_u32-first contract and the narrowed branch scope.