tests/local-today-gates.test.mjs scoped itself to places that "GATE a decision rather than stamping a filename", and included assessment-log.mjs for "the date written into a user's assessments.tsv row". Two more write exactly that kind of date and are still on new Date().toISOString():
outcome.mjs:62 return new Date().toISOString().split('T')[0];
tracker.mjs:552 const today = new Date().toISOString().slice(0, 10);
outcome.mjs stamps the ## Entry: header and **Date**: in the append-only journal under data/outcomes/, which calibrate.mjs and funnel-velocity.mjs then read. An outcome recorded on a Sunday evening anywhere in the Americas is journaled as Monday — moving it into the next week and the next funnel bucket.
tracker.mjs dates a row in the SQLite status_events table. Lower severity because the index is derived, except that this is the one part a resync does not rebuild identically — the comment right below it says events "persist across rebuilds, keyed by id", so a wrong day is written once and sticks.
Two notes for whoever tests this
The tracker case needs two syncs with a status change between them. today is only reached on a transition; a first sync dates the event from the row's own Date column (DATE_RE.test(a.date) ? a.date : today), so a single-sync test never touches the clock.
And freezing the clock needs --import, not a wrapper module that imports the target. isMainModule() compares against the process entry path, so a wrapper entry makes these scripts decide they are libraries and skip their CLI bodies — a silent exit 0 that looks like the command ran and did nothing.
PR to follow.
tests/local-today-gates.test.mjsscoped itself to places that "GATE a decision rather than stamping a filename", and includedassessment-log.mjsfor "the date written into a user's assessments.tsv row". Two more write exactly that kind of date and are still onnew Date().toISOString():outcome.mjsstamps the## Entry:header and**Date**:in the append-only journal underdata/outcomes/, whichcalibrate.mjsandfunnel-velocity.mjsthen read. An outcome recorded on a Sunday evening anywhere in the Americas is journaled as Monday — moving it into the next week and the next funnel bucket.tracker.mjsdates a row in the SQLitestatus_eventstable. Lower severity because the index is derived, except that this is the one part a resync does not rebuild identically — the comment right below it says events "persist across rebuilds, keyed by id", so a wrong day is written once and sticks.Two notes for whoever tests this
The tracker case needs two syncs with a status change between them.
todayis only reached on a transition; a first sync dates the event from the row's own Date column (DATE_RE.test(a.date) ? a.date : today), so a single-sync test never touches the clock.And freezing the clock needs
--import, not a wrapper module that imports the target.isMainModule()compares against the process entry path, so a wrapper entry makes these scripts decide they are libraries and skip their CLI bodies — a silent exit 0 that looks like the command ran and did nothing.PR to follow.