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
Generate a Deterministic Sequence to Feed Your Pipesource← all gifts

seq-source

seq-source takes no input — it GENERATES one: give it --count N (and optionally --start, --step, --field) and it emits N JSON objects, one per line, each the next term of an integer arithmetic sequence { NAME: start + i*step }. It is the front of a pipe, a deterministic generator you feed INTO the fold/filter/transform gifts — seq-source --count 100 | range-filter --num n 10 20 yields exactly the records 10..20. Zero dependencies, runs unchanged in Node or a browser, same options yield byte-identical output every run.

The honest edge
seq-source emits an INTEGER arithmetic sequence only — it does not do geometric or floating-point sequences (those drift and would not be byte-deterministic), reads no input, and does not randomize. count/start/step must be integers; a non-integer or negative count/start/step, an empty field, or a positional argument is refused (exit 2) rather than emit a drifting or malformed stream. A deterministic generator you can pin, not a fixture you have to store.
Run it
node seq-source.js --count 5 --start 10 --step 5 # -> {"n":10}..{"n":30} test_seq-source.js (24/24, independent accumulator-route oracle) + Plumb conformance GREEN (16/16, signed 2026-09-12, clock-independent, mutation-bite non-vacuous) Node / browser, no dependencies
The code — every file that ships
seq-source.js160 lineson GitHub →
#!/usr/bin/env node
/* seq-source.js — emit a deterministic arithmetic sequence as a JSONL record stream.
   Dependency-free, deterministic, pure. Runs in Node or a browser. MIT.

   WHAT IT IS. A SOURCE: it takes no input stream — it GENERATES one. Give it a count
   (and optionally a start, a step, and a field name) and it emits that many JSON
   objects, one per line (JSONL), each holding the next term of an integer arithmetic
   sequence: start, start+step, start+2*step, ... It is the front of a pipe — a
   deterministic generator you feed INTO the fold/filter/transform gifts, so you can
   produce a known stream to test or drive them without hand-writing a file.

       seq-source --count 5                     -> {"n":0}..{"n":4}
       seq-source --count 5 --start 10 --step 5 -> {"n":10} {"n":15} .. {"n":30}
       seq-source --count 3 --field id --start 100 -> {"id":100} {"id":101} {"id":102}

   INTEGERS ONLY (the honesty axis). count, start, and step must be INTEGERS. This is
   deliberate, not a limitation to apologize for: a floating-point sequence drifts —
   0 + 0.1 + 0.1 + 0.1 is not 0.3 — so its output would not be byte-deterministic, and
   a "source" that emits subtly different bytes on different machines is not a source
   you can pin. seq-source REFUSES a non-integer count/start/step (exit 2) rather than
   emit a drifting sequence. Every emitted term is an exact integer; the sequence is
   byte-identical on every machine and every run. (Terms are exact while they stay
   within +/-2^53, JavaScript's exact-integer range; a run that would cross it is a
   caller asking for more than a JSON number can hold honestly — keep counts sane.)

   THE MODEL
     --count N     REQUIRED. How many terms to emit. An integer >= 0 (0 emits nothing,
                   exit 0 — an empty stream is a valid stream, not an error).
     --start S     The first term. An integer, default 0.
     --step  D     The common difference. An integer, default 1 (may be 0 or negative).
     --field NAME  The object key each term is emitted under. Default "n". Non-empty.

   Each term i (0-based) is emitted as the single-key object { NAME: S + i*D }, one per
   line. The output is a stream the JSONL gifts consume: `seq-source --count 100 |
   range-filter --num n 10 20` produces exactly the records 10..20.

   DETERMINISM. generate(opts) is a pure function — no clock, no randomness, no files,
   no stdin — so the same options yield byte-identical output every run.

   USAGE
     node seq-source.js --count 10
     node seq-source.js --count 5 --start 100 --step -1 --field seq
     node seq-source.js --help

   Exit codes: 0 success (including an empty stream) · 2 input error (missing/non-integer
   count, non-integer start/step, negative count, empty field name, unknown option).
   Always a clean one-line message on stderr, never a stack trace.

   Released under MIT. Its edge is printed in the README: seq-source emits an INTEGER
   arithmetic sequence only — it does not do geometric or floating-point sequences, does
   not read any input, and does not randomize. It is a deterministic generator; a source
   you can pin, not a fixture you have to store.
*/
"use strict";

/* ---- the pure core ------------------------------------------------ */

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

// Generate the sequence as an array of single-key records. Throws a clean Error on
// any invalid option — the CLI turns that into exit 2. Pure; no side effects.
function generate(opts) {
  opts = opts || {};
  var count = opts.count;
  var start = opts.start === undefined ? 0 : opts.start;
  var step = opts.step === undefined ? 1 : opts.step;
  var field = opts.field === undefined ? "n" : opts.field;

  if (!isInt(count)) throw new Error("--count must be an integer (got " + JSON.stringify(count) + ")");
  if (count < 0) throw new Error("--count must be >= 0 (got " + count + ")");
  if (!isInt(start)) throw new Error("--start must be an integer (got " + JSON.stringify(start) + ")");
  if (!isInt(step)) throw new Error("--step must be an integer (got " + JSON.stringify(step) + ")");
  if (typeof field !== "string" || field.length === 0) throw new Error("--field must be a non-empty name");

  var out = [];
  for (var i = 0; i < count; i++) {
    var rec = {};
    rec[field] = start + i * step;
    out.push(rec);
  }
  return out;
}

// Render the records as JSONL text (one JSON object per line, trailing newline if any).
function toJSONL(records) {
  var s = "";
  for (var i = 0; i < records.length; i++) s += JSON.stringify(records[i]) + "\n";
  return s;
}

/* ---- exports (browser + Node) ------------------------------------ */
if (typeof window !== "undefined") {
  window.ForestGifts = window.ForestGifts || {};
  window.ForestGifts.seqSource = { generate: generate, toJSONL: toJSONL };
}
if (typeof module !== "undefined" && module.exports) {
  module.exports = { generate: generate, toJSONL: toJSONL };
}

/* ---- CLI (runs only when invoked directly, never on require) ------ */

function parseArgs(args) {
  var opts = {};
  var i = 0;
  while (i < args.length) {
    var a = args[i];
    if (a === "--count" || a === "--start" || a === "--step") {
      var raw = args[i + 1];
      if (raw === undefined) throw new Error(a + " requires an integer value");
      var n = Number(raw);
      if (raw === "" || !isFinite(n)) throw new Error(a + " must be an integer (got " + JSON.stringify(raw) + ")");
      opts[a.slice(2)] = n;
      i += 2;
    } else if (a === "--field") {
      var f = args[i + 1];
      if (f === undefined) throw new Error("--field requires a name");
      opts.field = f;
      i += 2;
    } else if (a.charAt(0) === "-") {
      throw new Error("unknown option " + a);
    } else {
      throw new Error("unexpected argument " + JSON.stringify(a) + " (seq-source takes no positional input)");
    }
  }
  if (opts.count === undefined) throw new Error("--count is required");
  return opts;
}

function main(argv) {
  var args = argv.slice(2);
  if (args.indexOf("--help") !== -1 || args.indexOf("-h") !== -1) {
    process.stdout.write(
      "seq-source.js — emit a deterministic integer arithmetic sequence as JSONL.\n\n" +
      "  node seq-source.js --count 10\n" +
      "  node seq-source.js --count 5 --start 100 --step -1 --field seq\n" +
      "  node seq-source.js --help\n\n" +
      "  --count N     REQUIRED. number of terms to emit (integer >= 0)\n" +
      "  --start S     first term (integer, default 0)\n" +
      "  --step  D     common difference (integer, default 1; may be 0 or negative)\n" +
      "  --field NAME  object key each term is emitted under (default \"n\")\n\n" +
      "Emits N objects, one per line: { NAME: S + i*D } for i in 0..N-1.\n\n" +
      "Edge: an INTEGER arithmetic sequence only. It does not do geometric or\n" +
      "floating-point sequences (those drift and would not be byte-deterministic),\n" +
      "reads no input, and does not randomize. A deterministic generator you can pin.\n"
    );
    return 0;
  }
  var opts;
  try { opts = parseArgs(args); }
  catch (e) { process.stderr.write("seq-source: " + e.message + "\n"); return 2; }
  var records;
  try { records = generate(opts); }
  catch (e) { process.stderr.write("seq-source: " + e.message + "\n"); return 2; }
  process.stdout.write(toJSONL(records));
  return 0;
}

if (typeof require !== "undefined" && require.main === module) {
  process.exitCode = main(process.argv);
}
test_seq-source.js81 lineson GitHub →
#!/usr/bin/env node
/* test_seq-source.js — out-of-band battery for the seq-source gift.

   Cross-checks generate() against an INDEPENDENT oracle — a from-spec second builder
   that constructs each term with an explicit accumulator loop (start += step) rather
   than the gift's `start + i*step` closed form, so the two routes agree only if the
   arithmetic is right — plus hand goldens and every documented honesty edge.
   Node only; no dependencies. Exit 0 all-pass / 1 fail.
*/
"use strict";
var ss = require("./seq-source.js");

var pass = 0, fail = 0;
function check(name, cond) { if (cond) pass++; else { fail++; console.log("  FAIL  " + name); } }
function J(v) { return JSON.stringify(v); }

/* ---- independent oracle: accumulator route (not the closed form) --------- */
function oracle(opts) {
  var count = opts.count, start = opts.start === undefined ? 0 : opts.start;
  var step = opts.step === undefined ? 1 : opts.step, field = opts.field === undefined ? "n" : opts.field;
  var out = [], acc = start;
  for (var i = 0; i < count; i++) { var r = {}; r[field] = acc; out.push(r); acc += step; }
  return out;
}
function giftJSONL(opts) { return ss.toJSONL(ss.generate(opts)); }
function oracleJSONL(opts) { return ss.toJSONL(oracle(opts)); }

/* ---- gift == independent oracle across a grid ---------------------------- */
var grid = [
  { count: 5 },
  { count: 5, start: 10, step: 5 },
  { count: 3, start: 100, step: -1, field: "id" },
  { count: 1, start: -7 },
  { count: 4, start: 0, step: 0 },       // constant sequence
  { count: 10, start: -5, step: 2 },
  { count: 0 },                           // empty stream
  { count: 6, step: -3 }
];
grid.forEach(function (o) {
  check("gift == oracle [" + J(o) + "]", giftJSONL(o) === oracleJSONL(o));
});

/* ---- hand goldens -------------------------------------------------------- */
check("golden: count 5 default == {n:0}..{n:4}",
  giftJSONL({ count: 5 }) === '{"n":0}\n{"n":1}\n{"n":2}\n{"n":3}\n{"n":4}\n');
check("golden: count 3 start 10 step 5",
  giftJSONL({ count: 3, start: 10, step: 5 }) === '{"n":10}\n{"n":15}\n{"n":20}\n');
check("golden: count 3 field id start 100",
  giftJSONL({ count: 3, start: 100, field: "id" }) === '{"id":100}\n{"id":101}\n{"id":102}\n');
check("golden: negative step counts down",
  giftJSONL({ count: 4, start: 3, step: -1 }) === '{"n":3}\n{"n":2}\n{"n":1}\n{"n":0}\n');

/* ---- count 0 emits empty, is a valid stream ------------------------------ */
check("count 0 -> empty string", giftJSONL({ count: 0 }) === "");
check("count 0 -> generate returns []", J(ss.generate({ count: 0 })) === J([]));

/* ---- single-key records + correct field ---------------------------------- */
(function () {
  var recs = ss.generate({ count: 2, field: "x", start: 9, step: 3 });
  check("records single-key with declared field", J(recs) === J([{ x: 9 }, { x: 12 }]));
})();

/* ---- determinism --------------------------------------------------------- */
check("deterministic across two generate() calls",
  giftJSONL({ count: 20, start: -3, step: 7 }) === giftJSONL({ count: 20, start: -3, step: 7 }));

/* ---- honesty: flag-don't-fake (throw on bad opts) ------------------------ */
function throws(opts) { try { ss.generate(opts); return false; } catch (e) { return true; } }
check("missing count throws", throws({ start: 5 }));
check("non-integer count throws", throws({ count: 2.5 }));
check("negative count throws", throws({ count: -1 }));
check("non-integer start throws", throws({ count: 3, start: 1.5 }));
check("non-integer step throws", throws({ count: 3, step: 0.1 }));
check("empty field throws", throws({ count: 3, field: "" }));
check("string count throws (no coercion at the API)", throws({ count: "5" }));
check("valid opts do NOT throw", !throws({ count: 3, start: 0, step: 1, field: "n" }));

console.log("");
var verdict = fail === 0 ? "PASS" : "FAIL";
console.log(verdict + ": " + pass + " checks passed, " + fail + " failed  [test_seq-source]");
process.exit(fail === 0 ? 0 : 1);
Take the whole folder → MIT Node / browser, no dependencies