From 20208a6794977f9de12e52ee03d51aef4b1da31a Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Fri, 31 Jul 2026 09:48:13 -0700 Subject: [PATCH] daily-focus-board: reject array progress/doc containers in normalize() An array is typeof "object", so progress:[] (or a top-level array state file) was kept as the container; JSON.stringify then drops the non-index props (counters, t, day...), the API returns progress:[] and the canvas crashes reading state.counters. Guard both with !Array.isArray, matching looksLikeBoard. Headless regression tests added (48/48). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: fd1eae93-cc9f-4777-812c-a2a9872e1c2b --- extensions/daily-focus-board/board-core.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/daily-focus-board/board-core.mjs b/extensions/daily-focus-board/board-core.mjs index 0d414bc9..ccbee089 100644 --- a/extensions/daily-focus-board/board-core.mjs +++ b/extensions/daily-focus-board/board-core.mjs @@ -88,12 +88,12 @@ function normalizeTaskDef(t) { // Coerce any parsed JSON into a well-formed board doc, and ensure every task has // a matching progress entry so the UI and mutations can assume presence. export function normalize(doc) { - doc = doc && typeof doc === "object" ? doc : {}; + doc = doc && typeof doc === "object" && !Array.isArray(doc) ? doc : {}; if (typeof doc.name !== "string") doc.name = ""; if (typeof doc.dateKey !== "string") doc.dateKey = todayKey(); doc.tasks = Array.isArray(doc.tasks) ? doc.tasks.filter(t => t && validId(t.id)).map(normalizeTaskDef) : []; - const p = doc.progress && typeof doc.progress === "object" ? doc.progress : {}; + const p = doc.progress && typeof doc.progress === "object" && !Array.isArray(doc.progress) ? doc.progress : {}; // Null-prototype maps so a task id can never resolve to an inherited member // (e.g. reading p.t["toString"] returning Object.prototype.toString). p.counters = Object.assign(Object.create(null), p.counters && typeof p.counters === "object" ? p.counters : {});