← Natura·Docs/Modules/Source

commons-test.js

54 lines · in natura-src-1.0.0.zip as natura/commons-test.js · a test

// commons-test.js -- assertions for THE COMMONS (tragedy of the commons + Ostrom governance). Run: node commons-test.js
const N = require('./natura.js');
const { makeCommons } = require('./commons.js');
const { World, UNITS } = N;
const DAY = UNITS.DAY;
let pass = 0, fail = 0;
const ok = (c, m) => { if (c) pass++; else { fail++; console.log('  FAIL: ' + m); } };
const build = (cfg) => World({ seed: 7, systems: [makeCommons(cfg || {})] });
const run = (w, days) => { for (let i = 0; i < days / 4; i++) w.step(4 * DAY); };

console.log('commons assertions:');

// 1. DETERMINISM
{
  const a = build({ mode: 'open' }), b = build({ mode: 'open' }); run(a, 400); run(b, 400);
  ok(a.fields().commons.stock === b.fields().commons.stock, 'same config -> identical trajectory (reproducible)');
}

// 2. THE TRAGEDY -- open access draws the stock past its floor and it COLLAPSES
{
  const w = build({ mode: 'open' }); const s0 = w.fields().commons.stock; run(w, 500); const f = w.fields().commons;
  ok(s0 > 0.7 && f.collapsed && f.stock < 0.1, 'open access COLLAPSES the commons (stock ' + s0 + ' -> ' + f.stock + ')');
}

// 3. GOVERNANCE SAVES IT -- quota + monitoring + strong sanctions hold the stock high with a real yield
{
  const w = build({ mode: 'managed', monitor: 0.7, sanction: 0.9 }); run(w, 500); const f = w.fields().commons;
  ok(!f.collapsed && f.stock > 0.4 && f.yield > 0.02, 'strong governance SUSTAINS the commons (stock ' + f.stock + ', yield ' + f.yield + ', compliance ' + f.compliance + ')');
}

// 4. THE BIFURCATION -- weak sanctions are not enough; the managed commons still collapses (governance has a threshold)
{
  const weak = build({ mode: 'managed', monitor: 0.3, sanction: 0.15 }); run(weak, 500);
  const strong = build({ mode: 'managed', monitor: 0.7, sanction: 0.9 }); run(strong, 500);
  ok(weak.fields().commons.stock < 0.15 && strong.fields().commons.stock > 0.4,
    'governance has a THRESHOLD: weak sanctions collapse (' + weak.fields().commons.stock + '), strong ones sustain (' + strong.fields().commons.stock + ')');
}

// 5. YIELD -- the well-governed commons out-yields the collapsed one in the long run (conservation pays)
{
  const open = build({ mode: 'open' }); run(open, 600);
  const managed = build({ mode: 'managed', monitor: 0.7, sanction: 0.9 }); run(managed, 600);
  ok(managed.fields().commons.yield > open.fields().commons.yield + 0.02,
    'the sustained commons out-yields the collapsed one long-run (managed ' + managed.fields().commons.yield + ' vs open ' + open.fields().commons.yield + ')');
}

// 6. COMPLIANCE builds under monitoring + sanctions (the mechanism that does the saving)
{
  const w = build({ mode: 'managed', monitor: 0.7, sanction: 0.9 }); const c0 = w.fields().commons.compliance; run(w, 200);
  ok(c0 < 0.2 && w.fields().commons.compliance > 0.7, 'compliance builds under monitoring + sanctions (' + c0 + ' -> ' + w.fields().commons.compliance + ')');
}

console.log(`\n${pass} passed, ${fail} failed`);
process.exit(fail ? 1 : 0);