Skip to content

replay: the recorded decision clock reaches one consumer while three other reads still decide outcomes #9539

Description

@JSONbored

Parent: #9492

Summary

#9028/#9256 shipped "replayable time": exactly ONE Date.now() per decision pass, captured as decisionClock and recorded into DecisionReplayInput. That guarantee is worth nothing if a second, unrecorded clock read in the same pass also decides an outcome — the recorded instant is then not the instant that decided, and the decision is unreplayable.

The captured clock reached exactly one consumer (maybeForceFreshRebase, processors.ts:3911). At least three other reads still decided outcomes.

Why this fails silently, in the worst direction

replayDecision pins action and only re-derives evaluateGateCheck. So replaying a decision that was actually made on an unrecorded clock read reports verdict: "match" — a false certification. The determinism feature actively vouches for the pipeline precisely where the pipeline is not deterministic. A divergence that is reported as a match is strictly worse than no replay at all.

The three reads

  1. processors.ts:2907activeMergeBlockedSha(pr, pr.headSha, Date.now()). Feeds the plan AND the recorded reason code. It is a second, unrecorded clock read in the very same pass that captures decisionClock at :3184.
  2. processors.ts:3498 — account age. Date.now()isNewAccount → halves the contributor cap → can flip a cap close. decisionClock is already in scope and simply unused. The twin helper src/queue/account-age-throttle.ts:13 has no nowMs seam at all.
  3. src/review/unlinked-issue-guardrail.ts:277 (also :192, :92) — a wall-clock gap chooses close vs hold.

There is also a class no JS-side grep can see: SQL-side datetime('now', ?) in src/review/submitter-reputation.ts.

Requirements

  1. Every clock read that can change a decision inside the recorded pass must consume the captured instant.
  2. A read deliberately left on the live clock must be named in decision-replay.ts's honest-scope note. The current note does not list them, and a scope claim that silently widens is worse than a narrow one.
  3. No behaviour change for callers outside the decision pass.

Deliverables

Tests (must fail against current main)

  • The velocity exception evaluated at a supplied instant diverges from the live clock. Use a confirmed miner — the exception only applies to one, so it is the only configuration where the gap is decisive; an unconfirmed author closes on repeat regardless of gap, which would make the assertion pass without exercising the clock at all.
  • The repeat lookback shares that same instant, not just the velocity gap.
  • Account age judged at a supplied instant flips isNewAccount.
  • Invariant: omitting the instant preserves live-clock behaviour byte-identically at every new seam.

Expected outcome

A decision made in the recorded pass is replayable from the recorded instant, and verdict: "match" means what it claims.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.orbGittensory Orb related - maintainer self-hosting analytics.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions