diff --git a/AGENTS.md b/AGENTS.md index c683a10..e4b4575 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -372,10 +372,46 @@ local_pii_tokens=$(awk -F: '...' "$ZFIN_HOME/accounts.srf" ...) grep -rn -E "$local_pii_tokens" src/ | grep -v ie_data.csv ``` -The grep should always return zero non-`ie_data.csv` hits before -committing. The `ie_data.csv` exclusion is because the Shiller -dataset contains coincidental numeric matches in historical-year -fields that aren't PII. +The grep is a **starting point, not a pass/fail gate** - it produces +false positives that must be triaged rather than dismissed wholesale. +Two known classes: + +- **Short numeric tokens.** A 3- or 4-digit account number matches + coincidentally inside Unix timestamps, trade volumes, hex color + literals, fake git SHAs, dollar amounts in CSV fixtures, and even + file line numbers. The `ie_data.csv` exclusion exists for the same + reason (Shiller's historical-year fields). +- **Generic account-type names.** An account literally named for an + IRS category (`Roth IRA`, `Inherited IRA`, `HSA`) matches inside the + approved placeholder vocabulary above - e.g. the real name + `Inherited IRA` is a substring of the sanctioned fixture value + `Sample Inherited IRA`. + +So the rule is: **inspect the context of every hit**, and confirm each +is either coincidental or a generic category before dismissing it. A +hit whose surrounding context is a real-looking account name, a +composite identifier, or a value that could only have come from the +user's data is PII and must be fixed in the same change. + +When reporting the result, redact: print the matching lines with the +sensitive token substituted out, or report only `file:line`. Do not +paste raw matches into a transcript. + +**`ZFIN_HOME` does NOT isolate you for smoke tests.** Pointing +`ZFIN_HOME` at a scratch directory does not sandbox the whole tool: +`ZFIN_AUDIT_FILES` is read independently (`audit/hygiene.zig`) and +points at wherever real brokerage exports get downloaded. A flagless +`zfin audit` will discover, parse, and print **real account numbers and +balances** from that directory regardless of `ZFIN_HOME`. This has +already caused one leak into a session transcript. + +So when smoke-testing against scratch data: + +- Run under `env -u ZFIN_AUDIT_FILES` (and unset any other + path-carrying `ZFIN_*` var the command consumes). +- Bound the output. Never pipe a whole command's output through a broad + `grep`/`head` - `sed -n '/Section Header/,/^$/p'` the one section + under test, so an unexpected section can't spill into the transcript. If you're uncertain whether something is PII, **ask before committing.** PII can be surgically removed from a working @@ -592,6 +628,28 @@ Each file's report shows red lines (uncovered) and green lines (covered). For a quick numeric breakdown by file, the kcov JSON output under `coverage/kcov-merged/coverage.json` is greppable. +**Two traps if you script against the coverage output.** Both have +already produced a confidently-wrong "fully covered" claim: + +1. **Per-line data lives in the `.js` files, not the `.html`.** Each + `coverage//..html` has only a handful of + `class="lineNum"` nodes; the real per-line records are in the + sibling `.js` as + `{"lineNum":" 42","line":"...","class":"lineCov|lineNoCov|linePartCov"}`. + A scraper pointed at the HTML matches **zero** lines, so + "0 uncovered" silently means "0 tracked." Always assert that the + tracked-line count is non-zero before trusting a coverage verdict, + and sanity-check the scraper against a line you know is uncovered. +2. **`coverage/` accumulates stale per-binary directories across + runs.** Old reports for a file you just edited stay on disk with the + previous source text. Filter to reports whose embedded `"line"` + content matches the current file (grep for a string you just added) + before unioning them. + +Note that per-file numbers are a union across binaries: the same source +file appears in several `coverage//` directories, and a line +covered by any of them counts. + **Common reasons coverage looks lower than expected:** - A new `.zig` file's tests aren't being discovered. Check the