Adds eight new audit-check modules covering the defect classes flagged
during the prior copyedit pass for the release gate. Each scanner
follows the canonical `check(file_path, text, scope, start_counter)`
shape and emits `Issue` objects compatible with the audit-ledger and
accept-list pipeline.
Defect-class coverage (A-H per the pre-Wave-6 mapping):
- A. **bare_attribution** — detects `Author et al. YEAR` / `Author and
Author (YEAR)` / `Surname (YEAR)` style hand-typed attributions
without an adjacent `[@cite]`. Six regex patterns; suppresses
well-known FP classes (footnote bold heads, product-year tags,
paths with `[@cite]` on the same or adjacent line). 0 hits at
HEAD (Waves 4+6 fixed the originals); serves as regression guard.
- B. **duplicate_citation** — detects `[@key]` cited 3+ times within a
50-line sliding window. Confidence=low (advisory). Skips footnote-
definition bodies (re-citation is normal). 3 genuine over-citation
candidates surfaced at HEAD (`tschand2025`, `kairouz2021`,
`dixit2021silent` — each cited inline in body prose + nearby
`Source: [@key]` fig-cap).
- C. **math_notation_render** — five patterns for math rendering bugs:
adjacent math spans (`$\sim$$15%$`), literal `100s W` plurals,
missing `\mu` in unit prefixes, bare `\times` without surrounding
space, bare `%` inside math. 12 hits at HEAD — mostly `\times`
spacing in vol1/model_serving + vol1/training Python display math.
- D. **unresolved_xref** — cross-file source-level check that every
`@sec-X`, `@fig-X`, `@tbl-X`, `@eq-X`, `@lst-X` reference resolves
to a defined ID. Both per-file `check()` and corpus-wide
`scan_corpus(root)` entrypoints. 0 hits at HEAD (binder check refs
baseline is clean); the source-level scanner closes the gap by
emitting in the unified ledger format for the release-gate.
- E. **longtable_continuity** — detects pipe tables with 25+ rows OR
8+ columns OR `{tbl-colwidths=...}` paired with 20+ dense rows.
1 candidate at HEAD (`vol1/backmatter/appendix_assumptions:623`,
a 23-row Unit Definitions table). Optional `verify_rendered_pdf`
stub documented for future render-output wiring.
- F. **sec_slug_placement** — detects `{#sec-...}`, `{#fig-...}`,
`{#tbl-...}`, `{#eq-...}`, `{#lst-...}` IDs at end-of-paragraph
on a non-heading/non-caption/non-blockquote line (Quarto parse
failure mode). 0 hits at HEAD; earlier audit waves already cleaned
this defect class.
- G. **footnote_numbering** — per-file integrity check: missing defs,
orphan defs, duplicate defs, plus a NEW category `footnote-numeric-id`
that flags bare `[^1]` / `[^2]` style refs (signal of unconverted
draft footnotes — book uses descriptive names everywhere). 0 hits
at HEAD; sits as regression guard.
- H. **layout_proxies** — source-level proxies for layout defects.
Four categories: `orphan-heading` (heading with 1-2 lines of body
before next heading), `figure-without-caption`, `runt-callout`,
`empty-section`. 289 orphan-heading + 8 empty-section hits at
HEAD — most are advisory; the design-doc docstring at top of the
file specifies the future render-output Scanner H+ (pdfplumber
bbox inspection for true page-level orphans, HTML figcaption
verification, cross-page table fragment detection).
Registry wire-up (`book/tools/audit/scan.py`):
- All 8 categories added to `CHECK_REGISTRY` under a "Wave 7" comment.
- Audit scan post-commit: total 879 issues, 15 accepted, 551 deferred
(notation-consistency parked), 313 open from new scanners (mostly
the 289 orphan-heading advisories).
Wave 7 Phase 1 of release-prep tooling. Phase 2 wires `binder check
release` as a CLI entrypoint that runs these eight scanners against
both rendered output and source, and wires it into `validate-dev` CI.