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
Which Parts of My Prompt Actually Stuck?fold← all gifts

Palimpsest

You revise a prompt a dozen times — which words actually mattered? Palimpsest takes your successive versions IN ORDER and, for every line, computes how much of the revision history it survived. The lines you kept through every rewrite are the load-bearing CORE; the lines that came and went are CHURN. A line in all N versions has survival 100%; a line in one has survival 1/N. Lower the --core threshold to loosen “load-bearing” (--core 0.5 = present in at least half the versions). Trailing whitespace merges, blank lines drop, output is totally ordered — so the same versions yield the same core, every run. Deterministic, zero dependencies, offline; runs in Node or a browser.

The honest edge
palimpsest measures SURVIVAL, not QUALITY. A line that survived every draft is load-bearing to the author — not thereby correct, good, or necessary. A mistake copied faithfully through every version survives with rate 100% and lands in the core. Persistence is evidence of intent, never of merit. A human reads the core and decides what it means; the tool only makes survival visible and exact.
Run it
node palimpsest.js v1.txt v2.txt v3.txt # core = lines in every version; --core 0.5 loosens; exit 0 clean | 2 input error test_palimpsest.js (PASS) + --selftest (6/6: canon idempotence, all-versions→1.0→core, once-per-version presence, threshold monotonicity, trailing-ws merge, render stability) Zero dependencies, Node or browser, deterministic
The code — every file that ships
palimpsest.js265 lineson GitHub →
#!/usr/bin/env node
/* SPDX-License-Identifier: MIT */
/* palimpsest.js — layer every version of a text, find the load-bearing core.
 *
 * A palimpsest is a manuscript rewritten over an erased earlier one, where the
 * old writing still shows through. Give this tool the successive versions of a
 * prompt (or any text) in order — v1, v2, … vN — and it shows you what showed
 * THROUGH every rewrite: the lines that survived revision after revision (the
 * load-bearing CORE) versus the lines that came and went (CHURN).
 *
 *     v1.txt v2.txt … vN.txt ──▶ layer(versions)
 *                            ──▶ { core:[…], churn:[…], survival:{line→rate} }
 *
 * WHAT IT MEASURES. For each distinct line, its SURVIVAL RATE = (number of
 * versions the line appears in) / (number of versions). A line present in all N
 * versions has survival 1.0; a line in one version has survival 1/N. The CORE is
 * every line whose survival ≥ a threshold (default 1.0 — present in ALL versions);
 * CHURN is the rest. Lower the threshold with --core to loosen "load-bearing"
 * (e.g. --core 0.5 = present in at least half the versions).
 *
 * DETERMINISM (the promise, and the self-test that proves it). A line is keyed by
 * its canonical form (trimmed of trailing whitespace; interior preserved). Output
 * is sorted — core and churn each by descending survival then by the line's first
 * appearance (the version index it entered), so the result is a pure function of
 * the inputs: same versions, same bytes, every run. `--selftest` proves the key is
 * idempotent and the layering is stable.
 *
 * THE LINE IT WILL NOT CROSS (the honest ceiling — printed every --help/--list).
 * palimpsest measures SURVIVAL, not QUALITY. A line that survived every draft is
 * load-bearing to the AUTHOR — it is not thereby correct, good, or necessary. A
 * mistake copied faithfully through every version survives with rate 1.0 and lands
 * in the core. Persistence is evidence of intent, never of merit. A human reads
 * the core and decides what it means; the tool only makes survival visible and exact.
 *
 * EXIT CODES (analysis convention, gate-friendly).
 *   0  ran clean — a survival map was produced (this is the normal result; unlike a
 *      two-file diff there is no "they differ" state — an N-version fold always
 *      yields a map).
 *   2  input could not be used (fewer than one version, a missing/unreadable/
 *      directory path, or a --core outside [0,1]) — always a clean one-line
 *      message, never a stack trace.
 *
 * Runs identically in Node and in a browser (no DOM, no deps). MIT.
 */

'use strict';

var CEILING =
  'ceiling: palimpsest measures SURVIVAL, not QUALITY. A line that survived every\n' +
  '  draft is load-bearing to the author — not thereby correct, good, or necessary.\n' +
  '  A mistake copied through every version survives too. A human reads the core.';

/* ---- canonical form of a line (idempotent) --------------------------------
 * Trailing whitespace is churn no reader intends; interior whitespace is content.
 * Trimming only the end makes canon(canon(x)) === canon(x). We do NOT lowercase
 * or collapse interior space: two lines that differ in real content are different
 * lines, and that is exactly the signal we are counting.
 */
function canonLine(s) {
  return String(s).replace(/[ \t\r]+$/, '');
}

/* Split a version's raw text into canonical lines. Blank lines are dropped: an
 * empty line is layout, not content, and counting it would let indentation churn
 * masquerade as a surviving core line. */
function linesOf(raw) {
  var out = [];
  var parts = String(raw).split('\n');
  for (var i = 0; i < parts.length; i++) {
    var c = canonLine(parts[i]);
    if (c.length > 0) out.push(c);
  }
  return out;
}

/* ---- the fold -------------------------------------------------------------
 * versions: array of raw strings, in chronological order (v1 … vN).
 * opts.core: survival threshold in [0,1] for a line to count as CORE (default 1.0).
 * Returns { n, core:[{line,survival,enteredAt}], churn:[…], survival:{line:rate} }.
 * A line is counted ONCE PER VERSION (presence, not frequency): a line repeated
 * three times in v2 still contributes a single "present in v2". Survival is about
 * persistence across versions, not repetition within one.
 */
function layer(versions, opts) {
  opts = opts || {};
  var threshold = (opts.core === undefined || opts.core === null) ? 1.0 : opts.core;
  var n = versions.length;
  // presence[line] = set of version indices it appears in; firstSeen[line] = min index.
  var presence = Object.create(null);
  var firstSeen = Object.create(null);
  for (var v = 0; v < n; v++) {
    var seenThisVersion = Object.create(null);
    var ls = linesOf(versions[v]);
    for (var j = 0; j < ls.length; j++) {
      var line = ls[j];
      if (seenThisVersion[line]) continue;      // count once per version
      seenThisVersion[line] = true;
      if (!presence[line]) { presence[line] = 0; firstSeen[line] = v; }
      presence[line] += 1;
    }
  }
  var survival = Object.create(null);
  var rows = [];
  var keys = Object.keys(presence);
  for (var k = 0; k < keys.length; k++) {
    var ln = keys[k];
    var rate = presence[ln] / n;
    survival[ln] = rate;
    rows.push({ line: ln, survival: rate, enteredAt: firstSeen[ln] });
  }
  // Deterministic order: survival desc, then enteredAt asc, then line asc (total order).
  rows.sort(function (a, b) {
    if (b.survival !== a.survival) return b.survival - a.survival;
    if (a.enteredAt !== b.enteredAt) return a.enteredAt - b.enteredAt;
    return a.line < b.line ? -1 : (a.line > b.line ? 1 : 0);
  });
  var core = [], churn = [];
  for (var r = 0; r < rows.length; r++) {
    (rows[r].survival >= threshold ? core : churn).push(rows[r]);
  }
  return { n: n, core: core, churn: churn, survival: survival };
}

/* ---- rendering (deterministic text report) -------------------------------- */
function render(result) {
  var out = [];
  out.push('palimpsest — ' + result.n + ' version' + (result.n === 1 ? '' : 's') + ' layered');
  out.push('');
  out.push('CORE (load-bearing — survived the threshold):');
  if (result.core.length === 0) {
    out.push('  (none)');
  } else {
    for (var i = 0; i < result.core.length; i++) {
      out.push('  ' + pct(result.core[i].survival) + '  ' + result.core[i].line);
    }
  }
  out.push('');
  out.push('CHURN (came and went):');
  if (result.churn.length === 0) {
    out.push('  (none)');
  } else {
    for (var j = 0; j < result.churn.length; j++) {
      out.push('  ' + pct(result.churn[j].survival) + '  ' + result.churn[j].line);
    }
  }
  return out.join('\n');
}

function pct(rate) {
  // Fixed-width, deterministic: "100%", " 50%", " 33%". Integer floor of rate*100,
  // right-justified to 3 cols, plus '%'. Rounding is not used (would be locale-free
  // but still add ambiguity at .5); floor is exact and stable.
  var p = Math.floor(rate * 100 + 1e-9);
  var s = String(p);
  while (s.length < 3) s = ' ' + s;
  return s + '%';
}

/* ---- self-test (proves the promises) -------------------------------------- */
function selftest() {
  var fail = [];
  // 1. canon idempotence
  var samples = ['a', 'a  ', '  keep interior ', 'tab\there\t', ''];
  for (var i = 0; i < samples.length; i++) {
    var once = canonLine(samples[i]);
    if (canonLine(once) !== once) fail.push('canon not idempotent on ' + JSON.stringify(samples[i]));
  }
  // 2. a line in all versions has survival 1.0 and lands in the default core
  var vs = ['keep\ndrop1', 'keep\ndrop2', 'keep\ndrop3'];
  var res = layer(vs, {});
  if (!(res.survival['keep'] === 1.0)) fail.push('all-versions line survival != 1.0');
  if (!(res.core.length === 1 && res.core[0].line === 'keep')) fail.push('core is not exactly [keep]');
  if (res.churn.length !== 3) fail.push('churn count != 3');
  // 3. layering is stable: same inputs -> byte-identical render
  if (render(layer(vs, {})) !== render(layer(vs, {}))) fail.push('render not stable across runs');
  // 4. presence counted once per version (repetition within a version does not inflate survival)
  var rep = layer(['x\nx\nx', 'y'], {});
  if (rep.survival['x'] !== 0.5) fail.push('within-version repetition inflated survival');
  // 5. threshold loosening moves lines from churn to core monotonically
  var loose = layer(vs, { core: 0.0 });
  if (loose.churn.length !== 0) fail.push('core 0.0 left churn nonempty');
  // 6. trailing whitespace is not a distinct line (canon merge)
  var ws = layer(['line  \nline', 'line'], {});
  if (Object.keys(ws.survival).length !== 1) fail.push('trailing-ws produced a distinct line');
  return fail;
}

/* ---- CLI ------------------------------------------------------------------ */
function fail2(msg) {
  process.stderr.write('palimpsest: ' + msg + '\n');
  process.exit(2);
}

function main(argv) {
  var args = argv.slice(2);
  if (args.indexOf('--help') !== -1 || args.indexOf('-h') !== -1) {
    process.stdout.write(usage() + '\n\n' + CEILING + '\n');
    return 0;
  }
  if (args.indexOf('--list') !== -1) {
    process.stdout.write(CEILING + '\n');
    return 0;
  }
  if (args.indexOf('--selftest') !== -1) {
    var fails = selftest();
    if (fails.length === 0) { process.stdout.write('selftest: OK (6 checks)\n'); return 0; }
    process.stderr.write('selftest: FAIL\n  ' + fails.join('\n  ') + '\n');
    process.exit(1);
  }
  // parse --core <t> and collect file paths
  var threshold = 1.0, paths = [], i;
  for (i = 0; i < args.length; i++) {
    if (args[i] === '--core') {
      var t = parseFloat(args[i + 1]);
      if (isNaN(t) || t < 0 || t > 1) fail2('--core must be a number in [0,1]');
      threshold = t; i++;
    } else if (args[i].charAt(0) === '-') {
      fail2('unknown option: ' + args[i]);
    } else {
      paths.push(args[i]);
    }
  }
  if (paths.length < 1) fail2('need at least one version file (give them in order v1 … vN)');
  var fs = require('fs');
  var versions = [];
  for (i = 0; i < paths.length; i++) {
    var raw;
    try {
      var st = fs.statSync(paths[i]);
      if (st.isDirectory()) fail2('is a directory, not a file: ' + paths[i]);
      raw = fs.readFileSync(paths[i], 'utf8');
    } catch (e) {
      fail2('cannot read ' + paths[i] + ' (' + (e && e.code ? e.code : 'unreadable') + ')');
    }
    versions.push(raw);
  }
  var result = layer(versions, { core: threshold });
  process.stdout.write(render(result) + '\n');
  return 0;
}

function usage() {
  return [
    'palimpsest — layer every version of a text, find the load-bearing core vs churn.',
    '',
    'usage: palimpsest [--core <t>] <v1> <v2> ... <vN>',
    '       palimpsest --selftest',
    '',
    '  <v1> … <vN>   version files IN ORDER (oldest first). At least one.',
    '  --core <t>    survival threshold in [0,1] for CORE (default 1.0 = in every version).',
    '  --selftest    prove the canon is idempotent and the layering is stable.',
    '  --help        this message.   --list  the ceiling only.',
    '',
    'Each line\'s SURVIVAL RATE = (versions it appears in) / (number of versions).',
    'CORE = survival ≥ threshold; CHURN = the rest. Output is sorted, deterministic.'
  ].join('\n');
}

/* Dual use: CLI when run directly, library when required (Node or browser). */
if (typeof module !== 'undefined' && module.exports) {
  module.exports = { layer: layer, canonLine: canonLine, linesOf: linesOf, render: render, selftest: selftest };
}
if (typeof require !== 'undefined' && require.main === module) {
  main(process.argv);
}
test_palimpsest.js97 lineson GitHub →
#!/usr/bin/env node
/* SPDX-License-Identifier: MIT */
/* test_palimpsest.js — external battery for palimpsest.js.
 *
 * Proves the survival fold, the canon, determinism, and the CLI contract. Run:
 *     node test_palimpsest.js
 * Exit 0 = all pass; exit 1 = a failure (with the count). This battery is
 * external (require's the gift, does not reach inside it) so a mutation to the
 * gift's logic is caught here — the "bite." Verify the bite: break a line in
 * palimpsest.js and this battery goes RED.
 */
'use strict';
var P = require('./palimpsest.js');
var fails = [];
function check(name, cond) { if (!cond) fails.push(name); }
function eq(name, a, b) { if (a !== b) fails.push(name + ' (got ' + JSON.stringify(a) + ', want ' + JSON.stringify(b) + ')'); }

/* --- survival math --- */
var r = P.layer(['keep\na', 'keep\nb', 'keep\nc'], {});
eq('survival: all-versions line is 1.0', r.survival['keep'], 1.0);
eq('survival: one-version line is 1/3', r.survival['a'], 1 / 3);
eq('core default: exactly one core line', r.core.length, 1);
eq('core default: the survivor', r.core[0].line, 'keep');
eq('churn default: three churn lines', r.churn.length, 3);

/* --- threshold behavior --- */
var half = P.layer(['x\ny', 'x\nz', 'w\nx'], { core: 0.5 });
check('core 0.5: x (3/3) in core', half.core.some(function (o) { return o.line === 'x'; }));
check('core 0.5: y (1/3) not in core', !half.core.some(function (o) { return o.line === 'y'; }));
var none = P.layer(['a', 'b'], { core: 0.0 });
eq('core 0.0: no churn', none.churn.length, 0);
var allT = P.layer(['a', 'b'], { core: 1.0 });
eq('core 1.0: nothing survives disjoint versions', allT.core.length, 0);

/* --- presence counted once per version (not frequency) --- */
var rep = P.layer(['x\nx\nx\nx', 'y'], {});
eq('once-per-version: repeated x is still 1/2', rep.survival['x'], 0.5);

/* --- canon --- */
eq('canon: idempotent', P.canonLine(P.canonLine('a  ')), P.canonLine('a  '));
eq('canon: trailing ws trimmed', P.canonLine('a\t '), 'a');
eq('canon: interior ws preserved', P.canonLine('a  b'), 'a  b');
var ws = P.layer(['line  \nline', 'line'], {});
eq('canon: trailing-ws is not a distinct line', Object.keys(ws.survival).length, 1);

/* --- blank lines dropped --- */
var blanks = P.layer(['real\n\n\n', 'real'], {});
eq('blank lines dropped: only real counted', Object.keys(blanks.survival).length, 1);

/* --- determinism: render stable, order total --- */
var vs = ['tie\nsame', 'tie\nsame'];
eq('render: stable across runs', P.render(P.layer(vs, {})), P.render(P.layer(vs, {})));
// total order under a survival tie: two lines same survival + same enteredAt -> sorted by line
var tie = P.layer(['bbb\naaa'], {});
check('total order: alpha tiebreak', tie.core[0].line === 'aaa' && tie.core[1].line === 'bbb');

/* --- ordering: core sorted by survival desc --- */
var ord = P.layer(['p\nq', 'p\nr', 'p\ns'], { core: 0.0 });
eq('order: highest survival first', ord.churn.length + ord.core.length, 4);
eq('order: p first (survival 1.0)', ord.core[0].line, 'p');

/* --- selftest passes internally --- */
eq('internal selftest clean', P.selftest().length, 0);

/* --- CLI contract via subprocess (exit codes, ceiling in help) --- */
var cp = require('child_process');
var path = require('path');
var GIFT = path.join(__dirname, 'palimpsest.js');
function run(args) {
  var res = cp.spawnSync('node', [GIFT].concat(args), { encoding: 'utf8' });
  return { code: res.status, out: (res.stdout || '') + (res.stderr || '') };
}
var fs = require('fs');
var t1 = path.join(require('os').tmpdir(), 'palimp_t1_' + process.pid + '.txt');
var t2 = path.join(require('os').tmpdir(), 'palimp_t2_' + process.pid + '.txt');
fs.writeFileSync(t1, 'core\ndrop1\n');
fs.writeFileSync(t2, 'core\ndrop2\n');
eq('CLI: clean run exits 0', run([t1, t2]).code, 0);
eq('CLI: missing file exits 2', run(['/no/such/palimpsest/file']).code, 2);
eq('CLI: bad --core exits 2', run(['--core', '9', t1]).code, 2);
eq('CLI: no args exits 2', run([]).code, 2);
eq('CLI: --selftest exits 0', run(['--selftest']).code, 0);
var help = run(['--help']);
check('CLI: --help prints ceiling (stdout+stderr scanned)', /ceiling: palimpsest measures SURVIVAL/.test(help.out));
var list = run(['--list']);
check('CLI: --list prints ceiling', /ceiling: palimpsest measures SURVIVAL/.test(list.out));
try { fs.unlinkSync(t1); fs.unlinkSync(t2); } catch (e) {}

/* --- report --- */
if (fails.length === 0) {
  console.log('test_palimpsest: PASS (all checks)');
  process.exit(0);
} else {
  console.error('test_palimpsest: FAIL (' + fails.length + ')');
  fails.forEach(function (f) { console.error('  - ' + f); });
  process.exit(1);
}
Take the whole folder → MIT Zero dependencies, Node or browser, deterministic