Code tour How a tick in the planner becomes progress on the phone: five excerpts and the checks
Polaris is my planning app: a calendar with a scheduling engine that sizes work into sessions and checks that it fits before the deadline. Olympus is my progress app: it turns finished work into elevation, in feet, on the web and on my iPhone. For about two months an AI agent scored my progress against a written rulebook; in August I switched that off: now I set what each finished item was worth myself, and the machine only does the bookkeeping. I designed and directed both; AI coding agents wrote the code. This shows the structure, not my data.
How the parts fit
- Polaris, on phone or desktop: I tick a finished item and set what it was worth.
- A small server function merges only what changed into one shared store, key by key.
- Every 2 minutes, a job on the always-on server makes the record of finished work match the ticks, then runs the build's checks. If a data check fails, it writes nothing.
- One data file is published and fetched fresh each time the Olympus app opens, on the web and in the iPhone app.
- At 6 a.m. and 8 p.m. New York time the server sends a notification through Apple's push service.
5 short excerpts from the real files
The numbers on the left are the real line numbers.
Polaris: "does this fit at all?"
Before any day-by-day schedule, Polaris asks a simpler question. Add up the work sessions needed before a deadline. Compare that with the sessions that exist between now and then. If the need is bigger than the supply, no clever ordering can save it, and the honest thing is to say so.
/* FEASIBILITY — the aggregate question, asked before any per-item detail. */
/* "Does this fit at all?" is answered by arithmetic, not by a schedule: sum */
/* the sessions required before a deadline, and compare with the sessions */
/* that exist between now and then. If the sum exceeds the supply, no amount */
/* of clever ordering rescues it, and the honest thing is to say so. */
/* ------------------------------------------------------------------------ */
function feasibility(ITEMS, LANES, today, deadline, capacity = {}, effortOverride = {}) {
const weeks = Math.max(0, diff(deadline, today) / 7);
const need = {}, supply = {};
for (const [k, v] of Object.entries(LANES)) {
if (v.floor || v.agentPool) continue;
supply[k] = (capacity[k] ?? v.cap) * weeks;
need[k] = 0;
}
for (const it of ITEMS) {
/* Count EVERY declared owner session, not only `task` rows. Agent reviews,
the rehearsal, the reserve and the milestones carry real hours; counting
only tasks left roughly a third of the Osiris lane's supply out of the
headline "does it fit" answer. A shared sitting is counted once. */
if (!it.due || diff(deadline, it.due) < 0) continue;
if (it.sharesSitting) continue;
const lane = ownerLane(it);
if (!(lane in need)) continue;
need[lane] += (effortOverride[it.id] ?? it.effort) || 0;
}Source: Teams/Odin - Research & Strategy Team Lead/BKM/in-flight/osiris-study/_polaris/engine.js, lines 459–483
Polaris: two devices must never erase each other
If each device sent everything it had, the last one to save would silently erase the other's work while both said "saved". So devices send only what changed, and the server merges. It first did this with a list of fields that were safe to merge. Three times, a new field was added to the app but not to the list, and real marks were wiped while the app said "Saved". So the rule was flipped: any object merges by default, and deleting needs its own explicit message.
/* ⚠️ 2026-08-10 — IT HAPPENED A THIRD TIME, AND THE ALLOWLIST IS WHY.
`edits`, `lanes` and `tags` were added to the client's MARK_MAPS and never
here. Restoring his marks after the functions outage posted `tags` with one
new tag; this list did not recognise the key, the `else` branch replaced the
whole map, and 15 tags were destroyed in one call — which returned
`ok: true`. They came back only because the export being restored happened
to be a superset. It would not always be.
So the rule is inverted below: ANY PLAIN OBJECT MERGES, and only scalars and
arrays replace. An allowlist has to be updated in two repositories at once to
stay safe, and three times running it was not — the list itself is the defect
generator, not the people forgetting it. Removal has always been the explicit
`clear` channel, so merging by default cannot strand a deletion. MAPS is kept
below only as documentation of what the client sends. */
const isMap = v => v && typeof v === "object" && !Array.isArray(v);Source: Teams/Odin - Research & Strategy Team Lead/BKM/in-flight/osiris-study/_polaris/functions/marks.mjs, lines 56–70
Olympus: the build refuses to publish wrong numbers
The data build runs its checks before it publishes, and each check is in one of two classes. A failed integrity check means a number on screen would be wrong, so nothing is written. A failed freshness check means the record is only behind while everything shown is still true, so it publishes with a loud warning. Every check must be given a class, or the build refuses to run. Today there are 15 integrity checks and 1 freshness check.
// ⚖️ TWO CLASSES — owner ruling 2026-08-01 (the decoupling).
// Every gate is classified EXPLICITLY below. There is no default class: a new
// gate must be added to GATE_CLASS or the build refuses to run (see the
// completeness check after the gates). That is deliberate — a gate that
// silently inherits "freshness" would be a hole in the ironclad design.
//
// • INTEGRITY — failing proves THE DATA WOULD BE WRONG. Stays FATAL: the
// build writes NOTHING and exits 1. Unchanged from the original design.
// • FRESHNESS — failing proves only THE RECORD IS BEHIND, while everything
// that would be displayed is still TRUE. Prints a loud warning, writes
// normally, exits 0, and the warning is carried to the publish-status line
// so it can never be silent.Source: Teams/Odin - Research & Strategy Team Lead/Research & Strategy Team/6 - Zeus the Guardian of Olympus/Olympus/dashboard-v2/build.mjs, lines 2010–2021
let ok = true; // INTEGRITY only — this alone decides the write
const freshness = []; // FRESHNESS warnings — loud, but never withholdSource: Teams/Odin - Research & Strategy Team Lead/Research & Strategy Team/6 - Zeus the Guardian of Olympus/Olympus/dashboard-v2/build.mjs, lines 2055–2056
Olympus: the app can never go blank
The app ships with a built-in copy of the data, and also fetches the newest data file when it opens. A stored copy wins only if it is strictly newer and has the right shape. Any error leaves the built-in copy in place, so a bad network or broken storage can never blank the screen.
try {
const baked = window.OLYMPUS_DATA;
const raw = localStorage.getItem(window.OLYMPUS_LIVE_KEY);
if (!raw) return;
const stored = JSON.parse(raw);
// minimal shape check — a corrupt payload must never boot the app
if (!stored || !stored.meta || !stored.meta.built_at
|| !Array.isArray(stored.ticks) || !Array.isArray(stored.lanes)) {
localStorage.removeItem(window.OLYMPUS_LIVE_KEY);
return;
}
// STRICTLY NEWER wins (ISO stamps compare lexically). A deploy that bakes
// fresher data beats the stored copy — which is then junk; drop it.
if (baked && baked.meta && baked.meta.built_at
&& stored.meta.built_at <= baked.meta.built_at) {
localStorage.removeItem(window.OLYMPUS_LIVE_KEY);
return;
}
window.OLYMPUS_DATA = stored;
} catch { /* storage/parse trouble → the baked data stands */ }Source: Teams/Odin - Research & Strategy Team Lead/Research & Strategy Team/6 - Zeus the Guardian of Olympus/Olympus/dashboard-v5-sonnet/js/livedata.js, lines 21–40
Olympus: a notification is sent once, on the right day
A timer that missed its time (say, after a restart) runs late, which could send yesterday's message or send it twice. So the sender checks, in order: is the off switch on, was this one already sent, is it still inside its time window? Then it records the send before sending, so a crash halfway can never lead to a second copy.
if (off) { log(`${stamp} ${slot}: OFF switch present (${OFF_FILE()}) — sent nothing`); return 0; }
if (test) return sendTest(slot, x, payload, stamp, log);
if (sent[sentKey]) { log(`${stamp} ${slot}: ${sentKey} already sent at ${sent[sentKey].at} — skipped (never twice)`); return 0; }
if (!slotWindowOK(slot, now())) { log(`${stamp} ${slot}: outside its send window — skipped (a late timer must not send a wrong-day message)`); return 0; }Source: Teams/Odin - Research & Strategy Team Lead/Research & Strategy Team/6 - Zeus the Guardian of Olympus/Olympus/native-app/push/olympus-push.js, lines 250–253
// record BEFORE sending: a crash mid-send must never lead to a second copy
sent[sentKey] = { at: new Date().toISOString(), feet: x.feet, overall: x.overall, results: 'sending' };
saveJSON(SENT_FILE(), sent);Source: Teams/Odin - Research & Strategy Team Lead/Research & Strategy Team/6 - Zeus the Guardian of Olympus/Olympus/native-app/push/olympus-push.js, lines 258–260
What broke in real use, and the fix
A "last safe start" plan is always red
ProblemThe first plan scheduled back from each due date. That leaves zero slack at every moment, so any ordinary bad week turns items red, and soon the whole board is red and ignored.
FixSchedule forward from today, keep the backward date only as an alarm line, and show the slack as the number that matters.
One late record blocked every unrelated fix
ProblemThe build was all-or-nothing. One record that was only behind held back data that was entirely correct, plus unrelated fixes, for hours.
FixThe two classes of check in excerpt 3: wrong data still blocks; late data warns.
How it is checked
My part, and the agents' part
- The scoring idea: progress as elevation in feet, summits to cross, and only provable work counts.
- The planning rules the engine follows, for example: if a month overflows, light items slip and the most important ones never do.
- "Un-ticking must look like it never happened."
- Turning off AI scoring in favour of pricing my own work.
- Both web apps, the scheduling engine, the sync function, the build and its checks, the iPhone shell and the notification sender.
- Turning my rules into working algorithms.
- Recording each defect in the code's comments, with the date and the cause, so every rule traces to a real failure.