mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
Three root causes from a fourth max-effort review (15 raw findings deduped; the synthesize step died on a session limit so they arrived unmerged): 1. The previous commit's telemetryEnabled fix was ineffective: the arm site passed readConfig() — the process-lifetime cache — into isDeParallelRouterTrialBlocked, making it exactly as stale as the shouldTrack() memoization it claimed to bypass. A mid-batch `hyperframes telemetry off` (or another process persisting fired=true) was never observed. Now reads readConfigFresh() at the arm site; the test mock previously hid this because readConfig/readConfigFresh were behaviorally identical views over one shared object. 2. The verify-and-retry write loop double-counted a render whenever OUR write landed but a concurrent writer advanced the file before our verify read — the retry re-applied the increment on top (two renders → three counts), tripping the 25-render exposure cap early and permanently killing the trial with less telemetry than the cap was designed to allow. Reworked: the render COUNTER is written exactly once, unverified (a lost increment under-counts by one — benign); only the FIRED flag is verified and re-asserted, which is idempotent, so retries can no longer corrupt anything (persistDeParallelRouterTrialFired). 3. writeConfig swallows all fs errors, so on an unwritable ~/.hyperframes a reverted outcome could never persist — the trial would re-arm and re-fail on every subsequent render forever, silently. Added an in-process fired latch (set at decision time, before persistence is attempted) consulted by the blocked-check, plus a one-time console warning when persistence exhausts its attempts. Later processes still re-arm (disk is the only cross-process channel), but each process now stops after at most one failure it couldn't record. Test infrastructure fix enabling all of the above to be tested: the config mock now models disk vs cache SEPARATELY (readConfig serves the cache, readConfigFresh re-reads "disk", writeConfig updates both) with a failWrites hook simulating the real writeConfig's silent error swallowing. The old single-shared-object mock made cached-vs-fresh mis-routing and retry iterations untestable by construction. 3 new regression tests: mid-batch opt-out observed through the cache; fired flag re-asserted after a lost write WITHOUT re-counting the render; unwritable-config latch blocking re-arm. 56 tests total across render.test.ts + config.test.ts. Not fixed (by design): the widened pinned-fallback retry paying a doubled render on deterministic mid-stream failures (e.g. ENOSPC) — the accepted tradeoff of the fallback design; cancellation and OOM are special-cased. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>