{"slug":"approvals-viewer","total":21,"limit":100,"offset":0,"since":null,"commits":[{"hash":"c9833a1","date":"2026-09-14 13:58:24 -0700","author":"Steve","subject":"approvals-viewer: implement openAudit() — Audit All button was a dead handler","body":"The \"🔍 Audit All\" button called openAudit(), which was defined nowhere\n(confirmed live: PAGEERROR \"openAudit is not defined\" on click). Add a\nread-only full-queue overlay that renders every loaded memo at once\n(chip/date/rating/title/file + collapsible body via <details>), reusing\nmd()/fmtDate() and card styles. Esc or ✕ closes; swiper keys are\nsuppressed while open so arrow-keys can't fire decisions behind it.\nAlso add the missing .b-audit style. No new writes — purely client-side.\n\nVerified in Chrome: typeof openAudit === 'function', overlay shows all 77\nitems, memo bodies expand, Esc closes, swiper state restored, no pageerror.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01X7mfnaSD5EB3DGZcaamU8A"},{"hash":"c9cbd5f","date":"2026-09-14 01:12:05 -0700","author":"Steve Abrams","subject":"TK-11685: approval-time freshness re-check guard (read-only, advisory)","body":"Closes the governance gap where a delete list could be approved against a\nSTALE enumeration: an approval fired at 18:26Z for a list a sibling lane had\nalready invalidated at 15:43Z, because nothing joined a fresh enumeration\nagainst concurrent findings before the memo reached Steve.\n\nfreshness-guard.js joins a gated memo's enumerated target set (Shopify\nvariant/product ids, DW-SKUs, GMC offer-ids, /products/ handles) against every\nnewer concurrent finding — the executed-reversible ledger (already-done), memos\nsince filed to _done/_resolved/_superseded, other open memos, and decision\nlogs — and flags any target a finding newer than the memo's as-of has touched,\nsurfacing \"N of M targets are now stale, do NOT execute blind\". Precision\nanchors + now-clamp (future expiry/scheduled dates never corrupt as-of or a\nfinding ts) + Drafted-date as-of + NOT_MEASURED-is-never-PASS. Verdicts in the\nfleet-health PASS/WARN/FAIL vocabulary.\n\nREAD-ONLY + ADVISORY throughout: it annotates/warns and surfaces the memo's own\nre-verify command; it NEVER approves, rejects, edits, moves, or executes any\nmemo, delete, or target action, and never runs the memo's re-verify command\nitself.\n\n- freshness-guard-cli.js: one memo / --all / --stale / --json\n- server.js: read-only GET /api/freshness?file=<memo.md> (additive, guarded)\n- test/freshness-guard.test.js: NEGATIVE TEST — injects the concurrent-\n  invalidation fault, proves STALE; proves FRESH on a still-fresh set; proves\n  the future-date clamp. 19/19 assertions pass.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: 963c1354-d10a-451f-8e5b-936663056ab7"},{"hash":"a3df63a","date":"2026-08-25 10:48:54 -0700","author":"Steve","subject":"creds-safe fetch guard: resolve relative fetch vs credential-free location (creds-in-URL trap)","body":"Fleet inoculation — opening this basic-auth app with credentials in the URL\npoisoned document.baseURI and made relative fetch('/api/…') throw. Guard resolves\nnon-absolute request URLs against location instead. Ref: creds-in-url-fetch-guard-fleet-pattern.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"7bb6722","date":"2026-08-20 08:13:37 -0700","author":"Steve Abrams","subject":"nav-agent: sync v1.3 (host left-sidebar collapse on load)","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a1a138e","date":"2026-08-19 14:30:59 -0700","author":"Steve","subject":"nav-agent: List data full-width tight columns (grid) — layout fix","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"b58ccd4","date":"2026-08-19 14:06:49 -0700","author":"Steve","subject":"Refresh nav-agent to v1.2 (adds kv-list compact List view, default-off) — Steve-approved public surface","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a8dae36","date":"2026-08-19 04:16:52 -0700","author":"Steve Abrams","subject":"approvals-viewer: gitignore ratings.json — live queue state, not source","body":""},{"hash":"69d3d3a","date":"2026-08-19 04:03:36 -0700","author":"Steve Abrams","subject":"approvals-viewer: add star ratings (1-5) + sort-by-rating/category/security","body":"- /api/rate POST endpoint stores per-memo ratings in ratings.json\n- /api/memos?sort= supports: mtime (default), rating, category, security\n- Star widget (★) on each card, clickable; keyboard shortcut 1-5 to rate\n- Rating badge chip in header row + rating-first sort surfaces urgent items\n- Toggle off same star to clear rating"},{"hash":"528c44e","date":"2026-08-13 11:52:48 -0700","author":"Steve Abrams","subject":"approvals-viewer: serve public/ static assets so /nav-agent/* resolves (was 404)","body":"Raw Node http server had no static route; nav-agent.js/.css 404'd. Added a\npath-traversal-guarded static handler for public/ before the 404 fallback.\nAdditive + reversible; asset stays behind Basic auth.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"af6b411","date":"2026-08-13 09:27:27 -0700","author":"Steve Abrams","subject":"nav-agent: universal grid-controls drop-in on internal dashboard/command-center pages (STRONG-only)","body":""},{"hash":"a188fef","date":"2026-08-11 13:37:08 -0700","author":"Steve Abrams","subject":"chore: harden /api/undo (path-traversal guard + decision whitelist), session-close lint","body":""},{"hash":"f3b563d","date":"2026-08-11 12:59:54 -0700","author":"Steve Abrams","subject":"approvals-viewer UI: always show action buttons + fetch error/retry so it never hangs on Loading","body":""},{"hash":"06062c8","date":"2026-08-11 12:48:58 -0700","author":"Steve Abrams","subject":"approvals-viewer: re-enable Basic auth + pin default port 9795 (public via CF tunnel)","body":""},{"hash":"33ba103","date":"2026-07-31 09:23:45 -0700","author":"steve","subject":"drop basic-auth (localhost-only tool)","body":""},{"hash":"65b30e1","date":"2026-07-31 08:53:02 -0700","author":"steve","subject":"pin approvals-swipe to stable port 9788","body":""},{"hash":"4cc1b1d","date":"2026-07-31 08:51:17 -0700","author":"steve","subject":"approvals yes/no swipe viewer","body":""},{"hash":"4529ded","date":"2026-07-28 10:32:36 -0700","author":"Steve Abrams","subject":"rollup: detect gated packet-memos per task (real convergence signal)","body":""},{"hash":"9ff4214","date":"2026-07-28 10:02:44 -0700","author":"Steve Abrams","subject":"add top-10 fan-out rollup board (:9793) tracking TK-10012 task states","body":""},{"hash":"a0197a4","date":"2026-07-28 09:21:59 -0700","author":"Steve Abrams","subject":"approvals-viewer: fix blank page — nested-quote SyntaxError in inline handlers","body":"The card action buttons + memo toggle used single-quoted inline onclick handlers\ninside single-quoted JS strings; the escaped quotes collapsed and broke the whole\ninline script (page stuck on 'loading…'). Switched action buttons to\ndata-attributes + one delegated click listener; memo toggle to a named tog()."},{"hash":"ecc4f6c","date":"2026-07-28 09:19:35 -0700","author":"Steve Abrams","subject":"approvals-viewer: skip auth for loopback (fixes blank page)","body":"Chrome drops the userinfo credential on the follow-up /api/drafts fetch, so the\ndata call 401'd and the page rendered blank. Loopback (this Mac) is now trusted\nand served without auth; remote callers still need basic auth admin/DW2024!."},{"hash":"be8f9d3","date":"2026-07-28 09:10:41 -0700","author":"Steve Abrams","subject":"approvals-viewer: yes/no board for the pending-approval queue","body":"Zero-dep Node viewer (basic auth admin/DW2024!) on :9792. Reads\n~/.claude/yolo-queue/pending-approval/*.md, shows gate/DTD/reversibility +\nClaude's recommendation, and records Approve/Defer/Block per draft to\ndecisions.json, mirrored into cncp-approvals-state.json. Decision-capture only\n— nothing is executed. Pre-seeded with the 15 quick-triage batch-1 approvals.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n"}]}