Skip to content

Add a deterministic execution mode (injectable clock + seeded RNG) #881

Description

@frostney

Summary

Add a deterministic execution mode so a given source + config + host produces repeatable output: a host-injectable frozen clock and a seeded portable PRNG.

Why

Reproducible runs are core to the sandbox-for-AI vision (reproducible agent runs and reproducible test262), but every non-deterministic source reads a global OS/FPC primitive directly with no injection seam: Math.random calls FPC Random (Goccia.Builtins.Math.pas:479), the clock is TimingUtils.GetEpochNanoseconds / GetNanoseconds (raw clock_gettime / QueryPerformanceCounter), and Temporal.Now / Date.now / performance.now read those. Object/Map/Set iteration order is already deterministic, so no change is needed there.

Current behavior

  • Math.random -> FPC Random, never seeded, no seam.
  • Wall clock GetEpochNanoseconds feeds Temporal.Now and (via shim) Date.now / new Date(); monotonic GetNanoseconds feeds performance.now.
  • Nothing accepts a seed or injectable clock. (GocciaBenchmarkRunner --profile-deterministic is unrelated — a naming-collision risk.)

Expected behavior

Decided (grill): an engine-wide --deterministic CLI option (plus config key) that:

  • Injects a single synthetic clock at the TimingUtils seam, frozen at a fixed epoch — making Temporal.Now and Date deterministic together (shared GetEpochNanoseconds); performance.now (separate GetNanoseconds) is frozen the same way and timeOrigin is pinned.
  • Seeds a portable PRNG (e.g. splitmix64 / PCG, not FPC Random) for Math.random, so output is stable across platforms and FPC versions.
  • Pins the system timezone to UTC (Temporal.Now.timeZoneId / Date read host TZ today).

Scope notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    new featureNew feature or request

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions