v0.4.4 — diff-scoped flow refresh
The per-file stale signal becomes a per-span worklist
A flow page's claims are per-span, but staleness fired per-file: one line added to a covered file made every citation anchored to it fail wiki-flow-check with "moved — re-verify", forcing a choice between re-verifying everything and blind re-stamping (the trust-eroding "refresh-by-rote").
New vendored script: wiki-flow-refresh.mjs (node + git stdlib, offline — ADR-003/006). It diffs each recorded blob against the working tree and classifies every citation:
| Class | Meaning | On --apply |
|---|---|---|
current |
recorded SHA matches | — |
untouched |
cited span byte-identical | SHA re-recorded |
shifted |
span identical, moved ±N lines | lines + SHA rewritten, region re-rendered |
touched |
the diff intersects the span | left at old SHA — re-verify |
gone |
a match string vanished | left at old SHA — re-research |
unknown |
recorded blob unavailable | left at old SHA — re-verify |
The key design choice: unsafe classes are deliberately not fixed, so after an apply, wiki-flow-check fails on exactly the citations that still need a human — the checker becomes the live worklist. covers: is never touched; page-level blessing stays wiki-stamp's.
Dogfood-proven: a mixed edit to update.mjs (3 inserted lines + 1 real change inside a cited span) auto-fixed 13 of 14 citations and left exactly the touched one failing.
Honesty line: this proves byte-level safety only — semantic drift behind dodged spans remains the audit workflow's territory (ROADMAP).
8 new tests pin the contract (touched-is-never-auto-fixed, insertion-inside-a-span, covers-untouched, idempotency). The refresh procedure, references/flow.md, and the vendored AGENTS.md teach the loop.