This website is meant to be read and understood quickly by humans, but is only fully parsable, on a technical level, with the aid of an AI system. Read why →
Loop MMT
Drive a Render Loop That Replays Identically and Never Melts the Tab?render← all gifts

render-loop-harness

Every interactive app with a live view re-hand-rolls the same second step: take a stream of validated events and drive a state -> frame render loop off them — and that is where the resource-exhaustion bugs live (a requestAnimationFrame busy-spin with no budget, a loop that paces on Date.now() and breaks replay the moment it ships, a frame function that is not pure). render-loop-harness is that step done once, correctly, as a bounded deterministic reducer over the input-event-router envelope it inherits: validated events in, a sequence of pure frames out, advanced on each event's logical tick t, and bounded by a declared per-fold tick budget the harness REFUSES to exceed — a log longer than the budget halts at exactly budget frames with reject-reason "tick-budget-exceeded", never a busy-spin, never an OOM. Replaying the same log yields byte-identical frames. Set the budget with --budget. Zero dependencies, pure, offline; browser or headless Node.

The honest edge
this drives a pure state -> frame render loop from an inherited event log, advancing on the event's logical tick t and never a wall-clock; it refuses to exceed its declared per-fold tick budget; it does NOT render pixels, it does NOT persist, it holds NO clock/network/entropy, and it schedules nothing it cannot bound.
Run it
node render-loop-harness.js < events.jsonl # fold -> final frame + frame-count summary | node render-loop-harness.js --budget 500 < events.jsonl | node render-loop-harness.js --help test_render-loop-harness.js (37/37) — replay-determinism over frames, per-fold tick-budget halt at exactly budget (hostile over-budget vector), pure state->frame projection, inherited-envelope validation Zero dependencies, Node or browser, deterministic
The code — every file that ships
render-loop-harness.js307 lineson GitHub →
#!/usr/bin/env node
/* render-loop-harness.js — a dependency-free, deterministic, BOUNDED reducer that
   drives a pure state -> frame render loop off an inherited input-event log.

   WHY THIS EXISTS. Every interactive app with a live view re-hand-rolls the same
   second step: take a stream of validated events and drive a state -> frame
   render loop off them. Hand-rolled, that step is where the resource-exhaustion
   bugs live — a requestAnimationFrame busy-spin with no budget, a loop that reads
   Date.now() to pace itself (which breaks replay the moment it ships), a frame
   function that is not pure so the same log renders differently on replay. This is
   that step done once, correctly, as a BOUNDED DETERMINISTIC REDUCER over an
   input-event log: validated events in, a sequence of pure frames out, advanced on
   each event's LOGICAL tick `t`, and bounded by a declared per-fold tick budget the
   harness REFUSES to exceed.

   THE STRIP-CLEAN RULE (the whole reason to trust it). state_t is a pure fold of
   state_0 and the ordered event log up to t. Replaying the same log yields
   byte-identical state, frame sequence, and render. The harness holds NO clock, NO
   network, and NO entropy it did not receive as an event — the render clock enters
   ONLY as the event field `t`, supplied by the caller as data. So the same log
   replays identically forever, in a browser or headless on Node.

   THE ENVELOPE (INHERITED, not authored — input-event-router fixed it). One event
   per JSONL line:
     { "seq": <int>=0, monotonic +1 >, "t": <int>=0, non-decreasing logical tick >,
       "type": <one of the declared accepted types>, "payload": <object> }
   The emitted typed stream of input-event-router IS the input log of this harness
   (the covenant's composition algebra). This gift does NOT re-author the envelope;
   it folds the validated stream its sibling emits.

   THE BOUND (this gift's mandatory security clause — resource bounds, covenant §3.3).
   The fold produces at most `budget` frames and REFUSES to exceed it: a log longer
   than the budget HALTS at exactly `budget` frames with reject-reason
   "tick-budget-exceeded", never a busy-spin, never an OOM. The bound is a
   frame-COUNT per fold (not a wall-clock rate), so it is decidable, adversarially
   checkable, and replay-stable — the same log halts at the same frame every run.

   USAGE
     node render-loop-harness.js < events.jsonl              # fold -> final frame + summary
     node render-loop-harness.js --budget 500 < events.jsonl # set the per-fold tick budget
     node render-loop-harness.js --help

   Released under MIT. Its edge, printed in the README and --help: this drives a pure
   state -> frame render loop off an inherited event log, advancing on the event's
   logical tick `t` and never a wall-clock; it refuses to exceed its declared per-fold
   tick budget; it does NOT render pixels (the frame is deterministic text), it does
   NOT persist, it holds NO clock/network/entropy, and it schedules nothing it cannot
   bound. (Retaining event history is the undo-stack-kernel's job, under its own
   declared bound — this harness keeps a bounded, fixed-shape render view.)
*/
"use strict";

// The default accepted event-type vocabulary (INHERITED shape; the render lane adds
// a render-driving `tick` type). CONFIG, not frozen (covenant §2/§5 U2): what the
// gift enforces is that the vocabulary is DECLARED and CLOSED — the decidable
// security property. An app supplies its own set via cfg.acceptedTypes.
var DEFAULT_ACCEPTED_TYPES = ["tick", "pointer", "key", "select", "edit", "commit"];

// The default per-fold tick budget: the maximum number of frames a single fold will
// produce before it REFUSES to continue. CONFIG (cfg.budget / --budget). Declared and
// bounded is the security property; the specific number is a policy the app sets.
var DEFAULT_BUDGET = 1000;

// The initial fold-state. Bounded, fixed-shape by contract: five scalars + a
// bounded declared-shape `view` (NEVER a growing history buffer — that is the
// undo-stack-kernel's job under its own bound).
function state0() {
  return { nextSeq: 0, lastTick: -1, frameCount: 0, tickBudgetSpent: 0, view: view0() };
}

// The render view: a small, fixed-shape accumulator the frame renders. Declared
// shape, bounded size — it does not grow with the log. Here: a running fold of the
// render-relevant fields (a count of applied ticks and the last applied payload
// marker), enough to prove a pure state -> frame projection without pretending to
// paint pixels (Real-or-Made: the frame is honest text).
function view0() {
  return { applied: 0, lastType: null, lastMark: null };
}

// isPlainObject — an object, not null, not an array, not a scalar. payload must be
// an object; we do NOT walk its contents (depth-1 check => bounded work,
// resource-bounds clause §3.3).
function isPlainObject(v) {
  return v !== null && typeof v === "object" && !Array.isArray(v);
}

function isInt(v) {
  return typeof v === "number" && isFinite(v) && Math.floor(v) === v;
}

/* validate(state, event, cfg) -> { ok: true } | { ok: false, reason: <string> }
   Pure. Checks the INHERITED envelope against the schema BEFORE the fold sees it.
   Every failure is a DECLARED rejection reason; nothing is coerced. (Inherited from
   input-event-router's discipline — §3.3 clause 2.) */
function validate(state, event, cfg) {
  var accepted = (cfg && cfg.acceptedTypes) || DEFAULT_ACCEPTED_TYPES;

  if (!isPlainObject(event)) return { ok: false, reason: "event-not-object" };

  // seq: present, int >= 0, exactly the next expected (total order, no gap/repeat).
  if (!isInt(event.seq) || event.seq < 0) return { ok: false, reason: "seq-not-int" };
  if (event.seq < state.nextSeq) return { ok: false, reason: "seq-repeat" };
  if (event.seq > state.nextSeq) return { ok: false, reason: "seq-gap" };

  // t: present, int >= 0, non-decreasing (LOGICAL tick as data; never a clock).
  if (!isInt(event.t) || event.t < 0) return { ok: false, reason: "tick-not-int" };
  if (event.t < state.lastTick) return { ok: false, reason: "tick-decrease" };

  // type: non-empty string in the declared accepted set.
  if (typeof event.type !== "string" || event.type.length === 0) {
    return { ok: false, reason: "type-not-string" };
  }
  if (accepted.indexOf(event.type) === -1) return { ok: false, reason: "type-not-accepted" };

  // payload: an object (opaque cargo). A scalar/null/array payload is rejected.
  if (!isPlainObject(event.payload)) return { ok: false, reason: "payload-not-object" };

  return { ok: true };
}

// safePayloadMark(payload) -> a bounded, proto-safe render marker pulled from the
// payload. Copies ONLY the one declared render-relevant field ("mark") onto a
// null-proto read, skipping the prototype-pollution keys (NOTE-13.1242-1 guard,
// carried from input-event-router). Bounded work: reads one declared field, never
// walks arbitrary payload depth (resource-bounds clause §3.3).
function safePayloadMark(payload) {
  // A hostile __proto__/constructor/prototype key must not reach anything. We read a
  // single declared field via a null-proto copy so a malicious key cannot pollute
  // Object.prototype and cannot be mistaken for the field we want.
  var clean = Object.create(null);
  var keys = Object.keys(payload);
  for (var i = 0; i < keys.length; i++) {
    var k = keys[i];
    if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
    if (k === "mark") clean.mark = payload[k];
  }
  var m = clean.mark;
  // Only a scalar mark is rendered (an object/array mark would be unbounded to
  // stringify — reject it to null, keeping the frame bounded).
  if (m === null || (typeof m !== "object" && typeof m !== "function")) return m === undefined ? null : m;
  return null;
}

/* advance(state, event, cfg) -> { state, frame, reject }
   The pure per-tick reducer. On a valid event, IF spending a tick would not exceed
   the declared budget: fold the event into `view`, spend one budget unit, and
   produce a pure frame. If spending would exceed the budget: HALT with
   "tick-budget-exceeded" (the harness REFUSES to run past its declared bound —
   the §3 clause-1 decidable check). On an invalid event: reject, do not advance
   into a corrupt place. */
function advance(state, event, cfg) {
  var budget = (cfg && isInt(cfg.budget)) ? cfg.budget : DEFAULT_BUDGET;

  var v = validate(state, event, cfg);
  if (!v.ok) {
    var seq = isInt(event && event.seq) ? event.seq : null;
    return { state: state, frame: null, reject: { seq: seq, reason: v.reason } };
  }

  // RESOURCE BOUND (primary clause): refuse to exceed the declared budget. If this
  // frame would be the (budget+1)-th, HALT rather than produce it.
  if (state.tickBudgetSpent >= budget) {
    return { state: state, frame: null, reject: { seq: event.seq, reason: "tick-budget-exceeded" } };
  }

  // Fold the event into the bounded render view (pure). Reads only declared,
  // proto-safe, bounded fields.
  var mark = safePayloadMark(event.payload);
  var nextView = { applied: state.view.applied + 1, lastType: event.type, lastMark: mark };
  var next = {
    nextSeq: state.nextSeq + 1,
    lastTick: event.t,
    frameCount: state.frameCount + 1,
    tickBudgetSpent: state.tickBudgetSpent + 1,
    view: nextView
  };
  var frame = render(next);
  return { state: next, frame: frame, reject: null };
}

/* foldLoop(events, cfg) -> { state, frames, rejections, halted }
   Folds an ordered array of inherited events under the tick budget. reject-policy
   default is HALT: a hostile/corrupt log (INCLUDING one that exceeds the budget)
   STOPS at the first violation rather than folding into an ambiguous frame
   sequence. cfg.rejectPolicy = "skip" is available for genuinely best-effort input
   (but a tick-budget-exceeded is ALWAYS a halt — a bound is not skippable). */
function foldLoop(events, cfg) {
  var policy = (cfg && cfg.rejectPolicy) || "halt";
  var state = state0();
  var frames = [];
  var rejections = [];
  var halted = false;
  for (var i = 0; i < events.length; i++) {
    var r = advance(state, events[i], cfg);
    if (r.reject) {
      rejections.push(r.reject);
      // The budget bound is never skippable — exceeding it always halts.
      if (r.reject.reason === "tick-budget-exceeded" || policy === "halt") {
        halted = true;
        break;
      }
      // skip: record the rejection, do not advance, continue to the next event.
      continue;
    }
    state = r.state;
    frames.push(r.frame);
  }
  return { state: state, frames: frames, rejections: rejections, halted: halted };
}

/* render(state) -> string. Pure state -> frame projection. An interactive gift is
   still pipe-testable headless: the frame is deterministic TEXT, never a live
   canvas (Real-or-Made: this does not pretend to paint pixels). */
function render(state) {
  return (
    "frame#" + state.frameCount +
    " t=" + state.lastTick +
    " applied=" + state.view.applied +
    " type=" + (state.view.lastType === null ? "-" : state.view.lastType) +
    " mark=" + (state.view.lastMark === null || state.view.lastMark === undefined ? "-" : String(state.view.lastMark))
  );
}

var API = {
  DEFAULT_ACCEPTED_TYPES: DEFAULT_ACCEPTED_TYPES,
  ACCEPTED_TYPES: DEFAULT_ACCEPTED_TYPES,
  DEFAULT_BUDGET: DEFAULT_BUDGET,
  state0: state0,
  validate: validate,
  advance: advance,
  foldLoop: foldLoop,
  render: render
};

// Browser attach.
if (typeof window !== "undefined") {
  window.ForestGifts = window.ForestGifts || {};
  window.ForestGifts.renderLoopHarness = API;
}

// Node require.
if (typeof module !== "undefined" && module.exports) {
  module.exports = API;
}

// CLI.
function main(argv) {
  var args = argv.slice(2);
  if (args.indexOf("--help") !== -1 || args.indexOf("-h") !== -1) {
    process.stdout.write(
      "render-loop-harness.js — bounded deterministic reducer: inherited event log -> pure frame sequence.\n\n" +
      "  node render-loop-harness.js < events.jsonl              fold -> final frame + summary\n" +
      "  node render-loop-harness.js --budget <int> < events.jsonl  set the per-fold tick budget\n" +
      "  node render-loop-harness.js --help\n\n" +
      "Envelope (INHERITED from input-event-router; one JSON object per line):\n" +
      "  { \"seq\": <int, monotonic +1>, \"t\": <int, non-decreasing logical tick>,\n" +
      "    \"type\": <accepted type>, \"payload\": <object> }\n\n" +
      "Edge: this drives a pure state -> frame render loop off an inherited event log,\n" +
      "advancing on the event's logical tick t and never a wall-clock; it refuses to\n" +
      "exceed its declared per-fold tick budget; it does not render pixels (the frame is\n" +
      "deterministic text), does not persist, holds no clock/network/entropy, and\n" +
      "schedules nothing it cannot bound.\n"
    );
    return 0;
  }
  var budget = DEFAULT_BUDGET;
  var bi = args.indexOf("--budget");
  if (bi !== -1 && args[bi + 1] !== undefined) {
    var b = parseInt(args[bi + 1], 10);
    if (isFinite(b) && b >= 0) budget = b;
  }
  var chunks = [];
  process.stdin.on("data", function (d) { chunks.push(d); });
  process.stdin.on("end", function () {
    var text = Buffer.concat(chunks).toString("utf8");
    var lines = text.split("\n");
    var events = [];
    for (var i = 0; i < lines.length; i++) {
      var line = lines[i].trim();
      if (line.length === 0) continue;
      try {
        events.push(JSON.parse(line));
      } catch (e) {
        // A non-JSON line is itself a rejectable event: push a sentinel the schema
        // will reject as event-not-object (a string is not an object).
        events.push(line);
      }
    }
    var out = foldLoop(events, { budget: budget });
    process.stdout.write((out.frames.length ? out.frames[out.frames.length - 1] : "frame#0 (no frames)") + "\n");
    process.stdout.write(
      "frames=" + out.frames.length +
      " budget=" + budget +
      " rejected=" + out.rejections.length +
      (out.halted ? " HALTED" : "") + "\n"
    );
    for (var j = 0; j < out.rejections.length; j++) {
      var rj = out.rejections[j];
      process.stdout.write("  reject seq=" + rj.seq + " reason=" + rj.reason + "\n");
    }
  });
  return 0;
}

if (typeof require !== "undefined" && require.main === module) {
  process.exitCode = main(process.argv);
}
test_render-loop-harness.js181 lineson GitHub →
#!/usr/bin/env node
/* test_render-loop-harness.js — the golden event-log corpus + out-of-band oracle
   for render-loop-harness. Stdlib-only, zero-dep.

   The oracle rule (covenant §4 B6): expected states/frames are computed
   INDEPENDENTLY here (by hand from the reducer rules), never by running the gift.
   The battery carries the mandatory hostile vectors — the budget-exceeding log
   FIRST (the §3 clause-1 primary check) — plus the inherited input-validation
   vectors, a composition proof against input-event-router's emitted stream, and
   two mutation bites. */
"use strict";

var H = require("./render-loop-harness.js");
var assert = require("assert");

var passed = 0;
var failed = 0;
function ok(name, cond) {
  if (cond) { passed++; process.stdout.write("  ok   " + name + "\n"); }
  else { failed++; process.stdout.write("  FAIL " + name + "\n"); }
}

function ev(seq, t, type, payload) {
  return { seq: seq, t: t, type: type, payload: payload === undefined ? {} : payload };
}

/* ---- 1. Golden valid log -> INDEPENDENTLY-computed expected final state + frames ---- */
(function goldenValid() {
  var log = [
    ev(0, 0, "tick", { mark: "a" }),
    ev(1, 1, "tick", { mark: "b" }),
    ev(2, 1, "pointer", { mark: 7 }),   // t may stay equal (non-decreasing)
    ev(3, 4, "tick", {})                // empty payload -> mark null
  ];
  // Hand-computed (NOT by running the gift):
  //  after 4 valid events: nextSeq=4, lastTick=4, frameCount=4, tickBudgetSpent=4,
  //  view.applied=4, view.lastType="tick", view.lastMark=null (last payload {}).
  var out = H.foldLoop(log, { budget: 100 });
  ok("golden.nextSeq==4", out.state.nextSeq === 4);
  ok("golden.lastTick==4", out.state.lastTick === 4);
  ok("golden.frameCount==4", out.state.frameCount === 4);
  ok("golden.budgetSpent==4", out.state.tickBudgetSpent === 4);
  ok("golden.view.applied==4", out.state.view.applied === 4);
  ok("golden.view.lastType==tick", out.state.view.lastType === "tick");
  ok("golden.view.lastMark==null", out.state.view.lastMark === null);
  ok("golden.frames.length==4", out.frames.length === 4);
  ok("golden.not-halted", out.halted === false);
  ok("golden.no-rejections", out.rejections.length === 0);
  // The independently-expected LAST frame string:
  ok("golden.lastFrame",
    out.frames[3] === "frame#4 t=4 applied=4 type=tick mark=-");
  // The independently-expected SECOND frame (mark carried through):
  ok("golden.frame1",
    out.frames[1] === "frame#2 t=1 applied=2 type=tick mark=b");
})();

/* ---- 2. Replay-determinism (the canonicalizer self-test) ---- */
(function replay() {
  var log = [
    ev(0, 0, "tick", { mark: 1 }),
    ev(1, 2, "tick", { mark: 2 }),
    ev(2, 5, "pointer", { mark: 3 })
  ];
  var a = H.foldLoop(log, { budget: 100 });
  var b = H.foldLoop(log, { budget: 100 });
  var c = H.foldLoop(log, { budget: 100 });
  var sa = JSON.stringify(a), sb = JSON.stringify(b), sc = JSON.stringify(c);
  ok("replay.folds-twice-identical", sa === sb && sb === sc);
  ok("replay.frames-identical",
    JSON.stringify(a.frames) === JSON.stringify(c.frames));
})();

/* ---- 3. RESOURCE-BOUNDS known-bad vector (PRIMARY §3 clause-1) ---- */
(function budgetExceeded() {
  // A log LONGER than the budget MUST halt at exactly `budget` frames.
  var budget = 5;
  var log = [];
  for (var i = 0; i < 50; i++) log.push(ev(i, i, "tick", { mark: i }));
  var out = H.foldLoop(log, { budget: budget });
  ok("budget.frames==budget", out.frames.length === budget);
  ok("budget.spent==budget", out.state.tickBudgetSpent === budget);
  ok("budget.halted", out.halted === true);
  ok("budget.reject-reason",
    out.rejections.length === 1 &&
    out.rejections[0].reason === "tick-budget-exceeded");
  // It refused to process the whole 50-event log — proof the bound holds.
  ok("budget.did-not-run-to-end", out.state.nextSeq === budget);
})();

/* ---- 4. Inherited input-validation known-bad vectors (§3 clause-2) ---- */
(function hostileEnvelopes() {
  function firstReject(log) {
    var out = H.foldLoop(log, { budget: 100 });
    return out.rejections.length ? out.rejections[0].reason : null;
  }
  ok("bad.seq-gap",
    firstReject([ev(0,0,"tick",{}), ev(1,1,"tick",{}), ev(3,2,"tick",{})]) === "seq-gap");
  ok("bad.seq-repeat",
    firstReject([ev(0,0,"tick",{}), ev(1,1,"tick",{}), ev(1,2,"tick",{})]) === "seq-repeat");
  ok("bad.tick-decrease",
    firstReject([ev(0,5,"tick",{}), ev(1,2,"tick",{})]) === "tick-decrease");
  ok("bad.type-not-accepted",
    firstReject([ev(0,0,"WOMBAT",{})]) === "type-not-accepted");
  ok("bad.payload-scalar",
    firstReject([ev(0,0,"tick",42)]) === "payload-not-object");
  ok("bad.payload-null",
    firstReject([ev(0,0,"tick",null)]) === "payload-not-object");
  ok("bad.payload-array",
    firstReject([ev(0,0,"tick",[1,2])]) === "payload-not-object");
  ok("bad.event-not-object",
    firstReject(["i am not an object"]) === "event-not-object");
})();

/* ---- 4b. Prototype-pollution guard (NOTE-13.1242-1, carried) ---- */
(function protoGuard() {
  var before = Object.prototype.polluted;
  var log = [ ev(0, 0, "tick", JSON.parse('{"__proto__":{"polluted":"yes"},"mark":"ok"}')) ];
  var out = H.foldLoop(log, { budget: 100 });
  ok("proto.Object.prototype-not-polluted", Object.prototype.polluted === before);
  ok("proto.mark-still-read", out.state.view.lastMark === "ok");
  // A payload whose "mark" is itself an object must render as null (bounded frame),
  // not stringify an arbitrary object.
  var out2 = H.foldLoop([ ev(0,0,"tick",{ mark: { deep: { deeper: 1 } } }) ], { budget: 5 });
  ok("proto.object-mark-bounded-to-null", out2.state.view.lastMark === null);
})();

/* ---- 5. State-bounds assertion (§3 clause-3) ---- */
(function stateBounds() {
  var budget = 200;
  var log = [];
  for (var i = 0; i < budget; i++) log.push(ev(i, i, "tick", { mark: i }));
  var out = H.foldLoop(log, { budget: budget });
  // State shape is exactly the five declared keys + a fixed-shape view — no
  // retained frame/history buffer in state.
  var keys = Object.keys(out.state).sort().join(",");
  ok("bounds.state-shape",
    keys === "frameCount,lastTick,nextSeq,tickBudgetSpent,view");
  var vkeys = Object.keys(out.state.view).sort().join(",");
  ok("bounds.view-shape", vkeys === "applied,lastMark,lastType");
  ok("bounds.no-history-buffer-in-state",
    typeof out.state.view.applied === "number");
})();

/* ---- 6. Composition proof (the covenant's reducer algebra) ----
   The EMITTED typed stream of input-event-router is exactly this harness's input.
   Reconstruct a router-emit stream shape { seq, t, type, payload } and prove the
   harness folds it cleanly. (We construct the emitted-shape objects directly — the
   router's emit is { seq, t, type, payload } with a null-proto payload copy; the
   harness must fold that shape without complaint.) */
(function composition() {
  var routerEmitStream = [
    { seq: 0, t: 0, type: "pointer", payload: { mark: "x" } },
    { seq: 1, t: 3, type: "commit",  payload: { mark: "y" } },
    { seq: 2, t: 3, type: "select",  payload: {} }
  ];
  var out = H.foldLoop(routerEmitStream, { budget: 100 });
  ok("compose.folds-router-emit-cleanly",
    out.rejections.length === 0 && out.halted === false && out.frames.length === 3);
  ok("compose.final-frame",
    out.frames[2] === "frame#3 t=3 applied=3 type=select mark=-");
})();

/* ---- 7. Mutation bites (>=2) ---- */
(function mutationBites() {
  // Bite (a): a deliberately-wrong expected final frame MUST be caught.
  var out = H.foldLoop([ev(0,0,"tick",{mark:"z"})], { budget: 100 });
  var wrongExpected = "frame#1 t=0 applied=1 type=tick mark=WRONG";
  ok("bite.a.wrong-frame-caught", out.frames[0] !== wrongExpected);

  // Bite (b): a harness that IGNORED the budget (folded past it) MUST fail the
  // resource-bounds vector. We simulate the mutant by asserting the REAL harness
  // does NOT fold all 20 events under a budget of 3 — i.e. the bound is real, not a
  // rubber stamp. If the harness folded all 20 (mutant behavior), frames would be 20.
  var log = [];
  for (var i = 0; i < 20; i++) log.push(ev(i,i,"tick",{}));
  var b = H.foldLoop(log, { budget: 3 });
  ok("bite.b.budget-not-ignored", b.frames.length === 3 && b.frames.length !== 20);
})();

process.stdout.write("\nrender-loop-harness golden corpus: " + passed + " passed, " + failed + " failed\n");
process.exit(failed === 0 ? 0 : 1);
Take the whole folder → MIT Zero dependencies, Node or browser, deterministic