D-04/D-05: Audit wrapper uses committed allowlist (audit-allowlist.json) with reason+reviewer+expiry per GHSA; Option B over native pnpm.auditConfig.ignoreGhsas (no accountability metadata in native approach)
D-06: check-outdated.mjs always exits 0; tiered report never gates
Pitfall 1 honored: pnpm audit --json with NO --audit-level flag
TDD gate: test(16-02) RED commit precedes feat(16-02) GREEN commit
scripts/audit-allowlist.json: committed GHSA waiver map. Seeded with GHSA-gv7w-rqvm-qjhr (esbuild High advisory, transitive dev-only via drizzle-kit/vitest/vite, not in production image). Each entry carries reason, reviewer, and expires fields for auditability.
scripts/check-audit.mjs: exports two pure functions (selectBlocking, partitionAdvisories) for unit testing. Main body runs only when invoked directly (import.meta.url guard). Uses pnpm audit --json with no --audit-level (Pitfall 1 honored). Exits 1 on unwaived High/Critical; exits 0 with advisory report for moderate/low.
scripts/__tests__/check-audit.test.mjs: 5 cases via node:test + node:assert (no extra deps). Covers: unwaived High → blocking; waived High → not blocking; moderate/low only → not blocking; no advisories → not blocking; mixed → correct partition.
scripts/check-outdated.mjs: classifies outdated packages into four tiers (AUDIT-ADVISORY > MAJOR-BEHIND-INTENTIONAL > MAJOR-BEHIND-UNPINNED > ROUTINE-DRIFT). Cross-checks pnpm audit --json to surface pinned-but-vulnerable packages under AUDIT-ADVISORY. Reads outdated-pins.json to label intentional pins with their reason. Always process.exit(0) — never gates (D-06).
Live run output: eslint/@eslint/js/zod/@types/node correctly under INTENTIONAL, @vitejs/plugin-react/jsdom/typescript under UNPINNED, hono/mysql2/@types/react under ROUTINE-DRIFT.