- runs the five static gates in Pattern-4 order; --live adds the KV-expiry
and asset-header probes; the no-flag skip prints '(pass --live)' and is
never silently green
- exit 0 CLEAN / 1 FAILED (violations counted across gates) / 2 NOT RUN
(credentials or build or deployment drift — never mistaken for a pass)
- header states the maintainer-time-tool law, the GPL fork-reuse contract,
and D-02's zero-telemetry prove-the-absence posture
- AU1-3 CLI vectors green: CLEAN exit 0 on this tree, FAILED exit 1 via the
PRIVACY_AUDIT_ROOT fixture, NOT RUN exit 2 for --live without credentials
- golden-corpus.json: 75 hand-written pinned cases (D-13) — landmark 17 /
abbreviation 15 / glued 7 / typo 14 / alias 15 / negative 7, incl. two
near-miss negatives (Penang 0.625, Kampung Cina ~0.58) below the 0.72
admission line; threshold.top3_hit_rate pinned at 0.9
- gazetteer-corpus.mjs: the D-14 runner — imports the SAME src/index.ts the
bot uses, measures top-1/top-3 + per-category rates + avg ms/query, prints
the refusal margin and the fixed escalation ladder on failure, exports
measureCorpus() for the in-process suite, exits 0 only on threshold + zero leaks
- corpus.test.mjs goes green: CO1-CO8 (the Nyquist gate inside npm run search:test)
- delegates: search:corpus (root) + corpus (search workspace)
Measured: top-3 68/68 (100.0%) >= 90%, negatives refused 7/7, margin 0.643 < 0.72 —
threshold met on the first run (D-14 lever: None).
- bot/ npm workspace sibling to theme/: grammy ^1.46.0, wrangler ^4.151.3, TS ^5.9.3
- src/config.ts exports Env (BOT_TOKEN, WEBHOOK_SECRET, chat_sessions KVNamespace)
- wrangler.jsonc: main src/webhook.ts + chat_sessions KV binding (id filled in plan 03)
- .gitignore ships .dev.vars/.wrangler/ in the same commit as .dev.vars.example (D-17)
- root delegate scripts bot:test/typecheck/dev/deploy/commands