← back to Approvals Viewer
FRESHNESS-GUARD.md
65 lines
# Approval-time freshness re-check guard (TK-11685)
**Read-only. Advisory. Never approves, rejects, edits, moves, or executes anything.**
## The incident it closes
An approval was granted at **18:26Z** for a delete list that a **sibling lane had
already invalidated at 15:43Z the same day**. Nothing joined a *fresh enumeration
against concurrent findings* before the memo reached Steve — so a gated delete list
could be approved against a **stale** target set: targets a newer lane had already
deleted, superseded, or re-classified since the list was enumerated.
## What it does
Given a gated memo that carries an **enumerated target set** (Shopify variant/product
ids, DW-SKUs, GMC offer-ids, `/products/<handle>` handles), it cross-references
**every newer concurrent finding** and flags any target a finding *newer than the
memo's own as-of* has since touched. Concurrent-finding surfaces:
| surface | signal |
|---|---|
| `executed-reversible/ledger.jsonl` | target **already executed** (strongest) |
| memos filed to `_done/_resolved/_superseded/_approved/_rejected/…` | target's memo **since resolved/superseded** |
| other open memos in `pending-approval/` | another **open** memo also targets it |
| `_decisions.jsonl` / `_review-decisions.jsonl` | a related memo **already decided** |
Output answers one question: **"N of M targets are now stale — do NOT execute this
list blind; re-enumerate first."** It also surfaces the memo's own re-verify command
(it does **not** run it — that would be arbitrary code from a parsed file).
## Correctness rails
- **Precision anchors only** — long numeric ids, `DW*-####` SKUs, `shopify_XX_..`
offer ids, and `/products/`-context handles. Infra names (skill/canary names, the
store domain) are deliberately **not** anchors, so a shared anchor means "same
target," not a coincidence.
- **now-clamp** — a future-dated string (a GMC `googleExpirationDate`, a scheduled
date) is never an enumeration/execution event. Timestamps in the future are
excluded from both the memo's as-of and from findings, so a future date can neither
push a memo falsely FRESH nor make a finding look newer than it is.
- **as-of** = the memo's most recent *past* full timestamp, else its **Drafted/Written**
date — so findings the memo already accounted for do not fire.
- **NOT_MEASURED is never PASS** — an unreadable memo or one with no parseable as-of
is WARN, never a false green.
## Verdicts (fleet-health-rollup vocabulary)
`FRESH → PASS` · `STALE → WARN` (advisory) · `NO_TARGETS → PASS` (not a delete list) ·
`NOT_MEASURED → WARN`.
## Usage
```sh
node freshness-guard-cli.js <memo.md> # one memo (path or queue basename)
node freshness-guard-cli.js --all # every open memo
node freshness-guard-cli.js --all --stale # only the flagged ones
node freshness-guard-cli.js <memo> --json # machine-readable
```
Viewer endpoint (read-only): `GET /api/freshness?file=<memo.md>` returns the report
JSON so a memo card can show its freshness badge before Steve decides.
## Test
```sh
node test/freshness-guard.test.js
```
Ships a **negative test**: it injects a concurrent-invalidation fault (a sibling-lane
execution landing after the memo's as-of — the exact incident) and proves the guard
flips to STALE, then proves it stays FRESH when only older findings exist, and proves
the future-date clamp holds.