Independent education · Sources and limitations documented
Portfolio / Smart NOA simulation

Software simulation

Source snapshot · 5 November 2026

simulator/tests/depth-advisory-full-2026-11.test.mjs

// Depth-low advisory, full-auto real runs (engine/depth-advisory.js). Split from
// tests/depth-advisory-2026-11.test.mjs so that node --test runs it in parallel (audit 05l, finding 4).
// EDUCATIONAL SIMULATION — fictional patients — not a medical device.
import test from 'node:test';
import assert from 'node:assert/strict';
import { REAL } from './helpers.mjs';
import { EXAMPLE_PLANS } from '../data/scenarios.js';
import { checkDA7, driveCached } from './depth-advisory-runs.mjs';

if (REAL) {
  test('DA7 example plans × full × seeds 1–20: identical completion outcomes, doses, alarms and pauses with the advisor; it appears only after incision in GA', (t) => {
    checkDA7(t, 'full');
  });

  // Audit 05l, finding 1: the plan scheduler inside _substep used to call the public action()/administer(),
  // whose depth-advisor refresh then ran mid-substep with dt = 1 on the previous second's index.
  test('DA-R refresh after an action never adds time; none runs inside _substep; card counts and outcomes equal the step-only path (4 example plans × seeds 1–20, full-auto)', (t) => {
    const expected = { ga_healthy: [20, 20], ga_elderly_cad_ckd: [20, 20], tiva_mh: [3, 3], mac_obese_osa: [0, 0] };
    const got = {}; let refreshes = 0; let ended = 0;
    for (const tpl of EXAMPLE_PLANS) {
      let runs = 0; let cards = 0;
      for (let seed = 1; seed <= 20; seed++) {
        const r = driveCached(tpl, 'full', seed); const tag = `${tpl.id} seed ${seed}`;
        for (const c of r.probe.calls) {
          assert.equal(c.inSubstep, false, `${tag} t=${c.t}: no advisor update from inside _substep`);
          if (!c.refreshOnly) continue;
          refreshes++;
          const { before: b, after: a } = c;
          assert.equal(a.lastT, b.lastT, `${tag} t=${c.t}: refresh does not move lastT`);
          assert.equal(a.totalBelowSec, b.totalBelowSec, `${tag} t=${c.t}: refresh adds no time below the band`);
          assert.equal(a.entries, b.entries, `${tag} t=${c.t}: refresh never starts an episode`);
          assert.ok(a.runSec <= b.runSec && (a.active ? a.episodeSec === b.episodeSec : true), `${tag} t=${c.t}: refresh never lengthens a run or episode`);
          if (b.active && !a.active) ended++;
        }
        const real = r.adv.record(); const step = r.probe.shadow.record();
        assert.equal(real.shown, step.shown, `${tag}: card count equals the step-only path`);
        assert.equal(real.totalBelowBandSec, step.totalBelowBandSec, `${tag}: time below the band equals the step-only path`);
        real.entries.forEach((x, i) => {
          const y = step.entries[i];
          assert.equal(x.shownAtSec, y.shownAtSec, `${tag} ${x.id}: shown on the same second`);
          assert.equal(x.status, y.status, `${tag} ${x.id}: same outcome`);
          assert.equal(x.index, y.index, `${tag} ${x.id}`);
          if (x.endedAtSec !== y.endedAtSec) {
            // Only allowed difference: the refresh ends the card on the action's second (e.g. Begin emergence),
            // the step-only path one step later; it is never later and never longer.
            assert.match(x.note, /disarmed/, `${tag} ${x.id}: only a disarm may end earlier`);
            assert.ok(y.endedAtSec === null || (x.endedAtSec < y.endedAtSec && y.endedAtSec - x.endedAtSec <= 1), `${tag} ${x.id}: ended ${x.endedAtSec} vs step-only ${y.endedAtSec}`);
            assert.ok(x.episodeSec <= y.episodeSec, `${tag} ${x.id}: never longer`);
          } else assert.equal(x.episodeSec, y.episodeSec, `${tag} ${x.id}: same episode length`);
        });
        if (real.shown) runs++; cards += real.shown;
      }
      got[tpl.id] = [runs, cards];
    }
    assert.deepEqual(got, expected, 'full-auto card counts (runs with a card, cards) for seeds 1–20');
    assert.ok(refreshes > 0 && ended >= 1, `refresh path exercised (${refreshes} refresh calls, ${ended} episodes ended by a refresh)`);
    t.diagnostic(`refresh-only calls: ${refreshes}; episodes ended by a refresh: ${ended}; counts ${JSON.stringify(got)}`);
  });
}
Source and scope

Published from Smart-NOA-Controller/simulator/tests/depth-advisory-full-2026-11.test.mjs at revision 6e5b205e3843. Full source text is retained; HTML presentation does not establish independent clinical review. In-memory simulation with no patient, monitor or pump interface; not clinically validated.