|
| 1 | +--- |
| 2 | +name: math-auditor |
| 3 | +description: > |
| 4 | + Run an adversarial mathematical-accuracy review of a Julia package's src/ and |
| 5 | + test/ directories, producing a dated markdown report plus concise, self-contained |
| 6 | + fix-prompt markdowns suitable for handing to a smaller model (e.g. Sonnet) in a |
| 7 | + later session. Use this skill whenever the user asks for an adversarial review, |
| 8 | + a math audit, a full code review focused on mathematical/numerical correctness, |
| 9 | + a check of algorithmic consistency with the literature, or says things like |
| 10 | + "review the math in src/", "is the algebra right?", "audit the update equations", |
| 11 | + "check the statistics/linear algebra for bugs", or "construct a code review as |
| 12 | + markdown". Trigger even when the user does not say "audit" — any request for a |
| 13 | + correctness-focused sweep of a scientific Julia codebase qualifies. |
| 14 | +--- |
| 15 | + |
| 16 | +# Math Audit |
| 17 | + |
| 18 | +Adversarial review of a scientific Julia package for **mathematical accuracy and |
| 19 | +consistency** — not software architecture (flag architecture only when it causes |
| 20 | +mathematical wrongness, e.g. mutation aliasing, accidental type demotion, or |
| 21 | +inconsistent conventions between modules). |
| 22 | + |
| 23 | +The output is written for the package's own developers: findings must cite exact |
| 24 | +`file:line`, state the correct mathematics, and give a concrete failure scenario. |
| 25 | +A finding that can't survive an attempt at refutation doesn't ship. |
| 26 | + |
| 27 | +## What "adversarial" means here |
| 28 | + |
| 29 | +Each reviewer's job is to *break* the code, not describe it. Concretely, hunt for: |
| 30 | + |
| 31 | +- **Wrong equations**: emulator predictive mean/covariance formulas, kernel and |
| 32 | + feature-map definitions, MCMC proposal/acceptance ratios, likelihood and prior |
| 33 | + terms that differ from the cited papers or from the docstring's own LaTeX. |
| 34 | + Derive the correct expression independently and diff it against the code. |
| 35 | +- **Convention drift**: rows-vs-columns for ensemble members/input points, |
| 36 | + `N-1` vs `N` normalization, factor-of-2 / sign errors, Cholesky `L` vs `U`, |
| 37 | + covariance vs precision, whitened vs unwhitened space, whether decorrelation |
| 38 | + is applied in input- or output-space — especially *inconsistencies between |
| 39 | + modules that must agree* (e.g. `GaussianProcess.jl` vs `ScalarRandomFeature.jl` |
| 40 | + vs `VectorRandomFeature.jl` on the same emulator interface). |
| 41 | +- **Statistical validity**: is observational/model noise sampled and scaled |
| 42 | + correctly? Are means/covariances computed over the right dimension (samples |
| 43 | + vs output components)? Do scalar and vector emulator variants agree in |
| 44 | + expectation? Do the SVD/PCA-based decorrelation and elementwise scaling |
| 45 | + transforms in `Utilities/` compose correctly with the emulator and sampler |
| 46 | + that consume them? |
| 47 | +- **Numerical soundness**: unguarded `inv`/`\` on possibly-singular matrices, |
| 48 | + loss of symmetry/PSD-ness, subtraction-based variance formulas, missing |
| 49 | + regularization/jitter, `sqrt` of negative-by-roundoff eigenvalues. |
| 50 | +- **Edge cases the math must survive**: single training point, single output |
| 51 | + dimension (scalar vs matrix degeneracy), zero variance, degenerate/rank- |
| 52 | + deficient covariance after decorrelation, empty or singleton minibatches, |
| 53 | + MCMC chains that reject every proposal. |
| 54 | +- **Test-math consistency**: do the tests actually pin the mathematics |
| 55 | + (analytic solutions, invariants, convergence rates), or just check shapes and |
| 56 | + "it runs"? A wrong equation whose test only checks `size()` is a *double* |
| 57 | + finding: the bug and the missing test. |
| 58 | + |
| 59 | +## Workflow |
| 60 | + |
| 61 | +### 1. Partition |
| 62 | + |
| 63 | +First establish what is actually **live**: grep the top-level module (and the |
| 64 | +files it includes, recursively) for `include(...)`, and compare against |
| 65 | +`git ls-files src/`. Files never included in the build, or untracked, are dead |
| 66 | +code — assign them skim-only status and cap their findings at minor/hygiene |
| 67 | +(they can't produce wrong results today, but note them in the report so future |
| 68 | +reviewers and greps don't confuse dead sampler math with live code). |
| 69 | + |
| 70 | +List the live `src/*.jl` and `test/**/*.jl` with line counts. Group into 4–8 |
| 71 | +review units of roughly comparable size, pairing each source module with the |
| 72 | +tests that exercise it. Group modules that *share mathematical conventions* |
| 73 | +together so the reviewer can catch cross-module inconsistencies — in this |
| 74 | +package that typically means: the emulator variants (`Emulator.jl` plus |
| 75 | +`MachineLearningTools/GaussianProcess.jl`, `RandomFeature.jl`, |
| 76 | +`ScalarRandomFeature.jl`, `VectorRandomFeature.jl`) in one or two units since |
| 77 | +they must agree on the same predict/covariance interface; the MCMC samplers in |
| 78 | +another; and the `Utilities/` preprocessing transforms (decorrelation, |
| 79 | +elementwise scaling, canonical correlation, likelihood-informed subspace) in |
| 80 | +another, since they feed both the emulator and the sampler and a convention |
| 81 | +mismatch there propagates silently downstream. |
| 82 | + |
| 83 | +Reserve the smallest unit as a **cross-cutting unit**. Alongside its own files |
| 84 | +(module wiring, display code, package-wide greps for `dims=`, `corrected=`, |
| 85 | +jitter constants, symmetrization idioms), give it an explicit mandate to |
| 86 | +independently re-derive the *single highest-risk formula* in each other unit's |
| 87 | +territory — MCMC acceptance ratios, structure-matrix congruence transforms, |
| 88 | +predictive-covariance noise semantics. This overlap is deliberate: in one |
| 89 | +audit the cross-cutting unit independently found and numerically verified the |
| 90 | +same critical pCN acceptance-ratio bug as the MCMC unit, on a *different* toy |
| 91 | +problem — two matching numerical confirmations settle a critical finding in a |
| 92 | +way a single one never can. Tell that agent the overlap is intentional so it |
| 93 | +doesn't defer to the "owning" unit. |
| 94 | + |
| 95 | +### 2. Fan out reviewers (parallel agents) |
| 96 | + |
| 97 | +Spawn one agent per unit, in a single message so they run concurrently. Build |
| 98 | +each prompt from `references/unit-agent-prompt.md`: fill the placeholders |
| 99 | +(unit file list, domain context, unit-specific extra hunts, scratch directory) |
| 100 | +and paste in the full "What adversarial means here" list above — agents don't |
| 101 | +see this skill. The template carries the rules that have earned their keep in |
| 102 | +past audits (the numerical-verification tiering, the warn/throw grep before |
| 103 | +any "silent" claim, severity-rule reporting) and fixes the required |
| 104 | +three-section output: the findings JSON, a CONVENTIONS section, and a |
| 105 | +TEST-COVERAGE section. The CONVENTIONS lines are the raw material for the |
| 106 | +step-3 matrix — without them you must re-read the code yourself to build it. |
| 107 | + |
| 108 | +As each agent's report arrives, save its raw findings verbatim to a scratchpad |
| 109 | +file (one per unit). A full audit plus verification is long enough that |
| 110 | +context summarization mid-run can silently lose findings; the scratchpad files |
| 111 | +are the durable record the report is assembled from. |
| 112 | + |
| 113 | +### 3. Verify |
| 114 | + |
| 115 | +For each critical/major finding, attempt refutation before it enters the |
| 116 | +report: re-read the cited lines yourself, re-derive the math, and check whether |
| 117 | +a test or an upstream transformation already accounts for it (common false |
| 118 | +positives: a transpose hidden in a helper, normalization done at construction |
| 119 | +time, a convention documented elsewhere, a `@warn` at the constructor that the |
| 120 | +reviewer never read — re-run the warn/throw grep yourself for any "silent" |
| 121 | +claim). Prioritise findings tagged `verified: inspection`; numerically verified |
| 122 | +ones usually need only a sanity re-read. Spawn skeptic agents for findings you |
| 123 | +can't settle from the main context. Demote or drop findings that don't survive; |
| 124 | +mark surviving ones **CONFIRMED** vs **PLAUSIBLE** (couldn't fully verify). |
| 125 | + |
| 126 | +Then build a small **conventions matrix** from the agents' CONVENTIONS |
| 127 | +sections before writing anything: rows = modules, columns = the conventions |
| 128 | +they reported (covariance normalization N vs N−1, whitened vs unwhitened |
| 129 | +space, whether predictive covariance includes observational noise, |
| 130 | +symmetrization idiom, jitter constants, RNG threading, rows-vs-columns). Any |
| 131 | +mismatched cell between modules that must agree is a finding candidate in |
| 132 | +itself — in practice the worst bugs are a scale factor or transform applied in |
| 133 | +one emulator variant or preprocessing step but not its sibling, and they only |
| 134 | +become visible side by side. |
| 135 | + |
| 136 | +### 4. Write the report |
| 137 | + |
| 138 | +Create `full-code-review/<YYYY-MM-DD>/` (date from `date +%F`, never from |
| 139 | +memory). Before writing, copy every numerical-verification scratch script into |
| 140 | +`full-code-review/<date>/verification/<unit>/` and cite those repo-relative |
| 141 | +paths in the report — scratchpad paths die with the session, and a numerical |
| 142 | +finding whose evidence has evaporated is just an inspection finding with extra |
| 143 | +steps. |
| 144 | + |
| 145 | +Write `review.md`: |
| 146 | + |
| 147 | +```markdown |
| 148 | +# Adversarial Mathematical Review — <Package> (<date>) |
| 149 | +## Scope and method <!-- files covered, units, verification policy --> |
| 150 | +## Summary table <!-- ID | severity | verdict | file:line | one-line claim --> |
| 151 | +## Critical findings <!-- full detail: evidence, math, failure scenario, fix sketch --> |
| 152 | +## Major findings |
| 153 | +## Minor findings & hygiene <!-- terser --> |
| 154 | +## Cross-module consistency notes |
| 155 | +## Test-coverage gaps <!-- LEAD with 2-3 "keystone tests" — see below --> |
| 156 | +## What was checked and found sound <!-- credit where due; prevents re-auditing --> |
| 157 | +``` |
| 158 | + |
| 159 | +In **Test-coverage gaps**, lead with the 2–3 *keystone tests* whose absence |
| 160 | +masked the most findings, ranked by findings-caught-per-test. In practice a |
| 161 | +handful of missing test archetypes hide many bugs at once — e.g. an analytic |
| 162 | +linear-Gaussian posterior test asserting the MCMC mean **and variance** would |
| 163 | +have caught two critical sampler bugs in one audit, and a single test of the |
| 164 | +default noise-flag semantics would have caught three emulator findings. This |
| 165 | +list is the highest-leverage part of the report for maintainers. |
| 166 | + |
| 167 | +Findings get stable IDs used everywhere, including fix prompts: `C1…` critical, |
| 168 | +`M1…` major, `m1…` minor, `h1…` hygiene; grouped-minor fix prompts get `G1…`. |
| 169 | + |
| 170 | +### 5. Write fix prompts |
| 171 | + |
| 172 | +For each finding with an actionable fix (usually critical + major, plus grouped |
| 173 | +minors), write `full-code-review/<date>/fix-prompts/<ID>-<slug>.md`. These are |
| 174 | +consumed by a *smaller model in a fresh session with no context*, so each must |
| 175 | +be self-contained: |
| 176 | + |
| 177 | +```markdown |
| 178 | +# Fix <ID>: <one-line title> |
| 179 | +**File**: `src/Foo.jl`, function `bar!`, around line NNN. |
| 180 | +**Problem**: <2–4 sentences: what the code does vs what the math requires. |
| 181 | +Include the incorrect snippet verbatim.> |
| 182 | +**Required change**: <exact edit, or precise description with the correct formula> |
| 183 | +**Do not**: <guardrails — e.g. "do not change the API", "do not touch other methods"> |
| 184 | +**Verify**: <the test to run or add, with the invariant it should pin> |
| 185 | +``` |
| 186 | + |
| 187 | +Keep each under ~40 lines. One finding per file; group only truly mechanical |
| 188 | +repeats (e.g. the same typo pattern in five docstrings) into one prompt. |
| 189 | +Quote enough of the offending snippet that the fixer can locate it by function |
| 190 | +name + snippet — line numbers drift between the audit and the fix session, so |
| 191 | +present them as hints, not anchors. |
| 192 | +Also write `fix-prompts/README.md` listing prompts in recommended application |
| 193 | +order (independent fixes first, same-file prompts sequenced, conflicting ones |
| 194 | +flagged) and naming which fixes *intentionally change numerical results* — so |
| 195 | +the fixer checks a failing loose regression test against the analytic reference |
| 196 | +in the prompt before "fixing" the test. |
| 197 | + |
| 198 | +### 6. Report back |
| 199 | + |
| 200 | +Final message: lead with the headline (how many confirmed critical/major |
| 201 | +findings and the single worst one), then the report path, then a compact |
| 202 | +summary table. Do not paste the whole report into the chat. |
| 203 | + |
| 204 | +## Calibration |
| 205 | + |
| 206 | +- Severity: **critical** = produces mathematically wrong results in mainstream |
| 207 | + use; **major** = wrong in common configurations or silently degrades |
| 208 | + statistical properties; **minor** = wrong in edge cases, misleading docs |
| 209 | + math, dead/misnamed math; **hygiene** = style-level (only if math-adjacent). |
| 210 | +- A numerically demonstrated wrong stationary distribution, wrong acceptance |
| 211 | + ratio, or wrong variance scaling in *exported* functionality is **critical** |
| 212 | + even if the feature looks niche — samplers and estimators exist to produce |
| 213 | + distributions, and a wrong distribution is the worst failure they have. |
| 214 | + (Agents report which calibration rule they applied, so when two units rate |
| 215 | + the same bug differently you arbitrate on the rule, not the adjective.) |
| 216 | +- A docstring–code mismatch is a real finding even when the code is right — |
| 217 | + users implement against docstrings. |
| 218 | +- A statistically unjustified combination that the package explicitly warns |
| 219 | + about (e.g. a constructor `@warn "... experimental ..."`) caps at **minor** |
| 220 | + unless the warning itself is wrong — the trap isn't silent. |
| 221 | +- Don't pad. If a unit is sound, the report says so in one paragraph; an audit |
| 222 | + that cries wolf gets ignored next time. |
| 223 | + |
| 224 | +## Improving this skill |
| 225 | + |
| 226 | +After delivering the report, offer: "Would you like to improve the |
| 227 | +**math-auditor** skill itself using skill-creator? You can share suggestions, or |
| 228 | +I can analyse this run — finding quality, false-positive rate, fix-prompt |
| 229 | +usability — to refine the skill for next time." |
0 commit comments