Code review for transformer-spectrum
Review the changes currently in the working tree (staged + unstaged + untracked)
against the standards that matter for this codebase specifically. Most bugs here are
silent: they pass pytest (the 93 tests assert shapes + isfinite, mock nothing
heavy, and never exercise the sweep/experiment paths) yet change the loss math, the
spectral metric definitions, the experiment's scientific validity, or the logged
metric names. The job is to catch those.
The review is read-only by default — fixes are surfaced as recommendations and
only applied if the user explicitly asks.
Arguments
$ARGUMENTS — optional. Specific files or globs to scope the review (defaults to the
entire diff).
Flow
Step 1: Gather changes
git status --short
git diff --staged --stat
git diff --stat
If there is nothing pending, stop: "Nothing to review."
Step 2: Read the diff
For each changed file, read the actual diff (not just the file list). Note which
subsystems are touched — that selects which checks below apply and which subagent to
delegate to.
Step 3: Delegate deep audits to subagents
When the diff touches a fragile subsystem, dispatch the matching subagent (via the
Agent tool, subagent_type) and fold its findings into the report. Run independent
subagents in parallel.
- Touches
modeling/loss_functions.py or settings.py SGTLossConfig
→ loss-math-reviewer.
- Touches
metrics/spectral_metrics.py, metrics/heavy_tail_estimation.py, or
modeling/trainer.py SpectralLoggingMixin → spectral-metrics-reviewer.
- Touches
experiments/*.py, data/**/*.py, modeling/data_processing.py,
modeling/harness.py, train.py/train_es.py/train_ga.py, or the seed/split/ES/GA
paths in trainer.py → experiment-methodology-auditor.
- Touches
experiments/utils/collect_artifacts.py, the MLflow log_metric(s) calls in
trainer.py/train*.py, models.py (cached_mask), or the ESConfig definition
→ mlflow-contract-auditor.
For a small diff that clearly matches none of these, do the checks inline.
Step 4: CRITICAL — Loss math & gradient correctness
Applies to modeling/loss_functions.py and settings.py SGTLossConfig.
- SGT moment-domain guard:
SGTLoss.__init__ keeps if not (p * q > 2): raise —
this is load-bearing (the beta functions beta(2/p, q-1/p), beta(3/p, q-2/p) need
q - 2/p > 0, else silent NaN/degenerate loss). SGTLossConfig carries the same
model_validator (p*q > 2). Removing either reopens the NaN-loss bug.
- SGT residual & skew:
forward keeps diff = y_true - y_pred + m; the skew term
(1 + lam*torch.sign(diff))**p reads that same diff. The trainer calls
criterion(out, tgt) (pred first, truth second).
- eps guards & log1p: SGT keeps its
+ eps denominators and torch.log1p(ratio);
Cauchy keeps gamma * torch.log1p(diffs**2 / gamma).
- dtype/device: every
torch.tensor constant in SGTLoss derives dtype=/device=
from the input; the loss returns a scalar .mean().
- Factory:
get_loss_function still maps mse→MSELoss, mae→L1Loss,
cauchy→CauchyLoss(gamma=2.0 default), sgt→SGTLoss(p=2.0, ...); the default
TRAINING_CONFIGS SGT entries all satisfy p*q > 2 (q ≥ 1.001 at p=2).
Step 5: CRITICAL — Spectral-metric methodology
Applies to metrics/spectral_metrics.py, metrics/heavy_tail_estimation.py,
modeling/trainer.py SpectralLoggingMixin.
- Naming honesty:
zipf_sv_slope is a rank/Zipf slope, NOT the Martin-Mahoney HTSR
tail index. Reject any rename back to alpha_exponent or any code/doc that equates it
with pl_alpha_hill/pl_alpha_ks.
- Small-matrix guard:
_hill_alpha/_ks_alpha keep the MIN_TAIL_POINTS guard
(return NaN when the tail is too small). The eigenvalue count is min(rows, cols) = embed_dim for EVERY matrix (incl. FFN) — do not claim FFN gives more eigenvalues.
- MP baseline:
get_spectral_metrics still returns mp_lambda_plus, mp_n_spikes,
mp_signal_energy_frac and computes the SVD once (passes s into the helpers).
- Matrix selection:
_ATTN_SPECS covers encoder self-attn, decoder self-attn AND
decoder cross-attn; _FFN_SPECS covers linear1/linear2. Don't silently narrow it.
- kappa reproducibility:
estimate_kappa_exponent keeps the explicit
np.random.default_rng(random_state) + bootstrap averaging + the M_1/M_n > 0 guard;
compute_dispersion_scaling_series starts at n=2.
Step 6: CRITICAL — Experiment protocol & data methodology
Applies to experiments/*.py, data/**, modeling/data_processing.py,
modeling/harness.py, train*.py.
- Paired seeds:
experiments/{synthetic,owid_covid,rvr_us}_data.py derive one
deterministic seed per run (base_seed + run_idx) shared across ALL losses in that
run (paired init + split). Reject any reintroduction of unseeded random.randint, or
a loop that gives different losses different seeds within a run.
- No leakage: the per-chunk
StandardScaler in data/rvr_us/dataset.py and
data/owid_covid/dataset.py is fit on the INPUT window only (chunk[:input_len]),
never the full window that includes the forecast horizon.
- Test set: the harness builds train/val/TEST; val selects the best model,
test_*
metrics are reported. Reject reporting selection metrics as final results.
- ES/GA tiny model:
train_es.py/train_ga.py (and the CLI) default to the tiny
model (embed_dim=16, num_heads=2, num_layers=1, dim_feedforward=32, 6k params) —
black-box opt cannot train the full 2.3M-param net. GA init_lo/hi stay near the
PyTorch init scale (±0.15, not ±0.5); TrainerGA._make_objective uses
resample_each_call=False (fixed batch set). Any cross-optimizer spectral claim must
be at MATCHED final train loss.
- Smoothing:
generate_data.main keeps the excess-kurtosis warning (smoothing
attenuates the heavy tail). Matched epochs: sweeps disable early stopping.
Step 7: CRITICAL — MLflow contract, ESConfig, checkpoint portability
Applies to experiments/utils/collect_artifacts.py, trainer.py/train*.py logging,
models.py, the ESConfig definition.
- Artifact selectors:
collect_artifacts._download_artifacts selectors
(esd_*.json, singular_vals_*.json) match the names log_qkv_figs actually dumps.
- Metric names: training logs
*_mae/*_rmse/*_wmape (NOT *_mape/*_smape),
the mp_*/zipf_sv_slope/pl_alpha_*/spectral_entropy/stable_rank spectral keys,
and test_*. A rename must update every consumer (collect_artifacts, notebooks, the
aggregate.py --metric default).
- Single ESConfig: there is ONE
ESConfig (pydantic, in settings.py); trainer.py
re-exports it. Reject a second dataclass ESConfig.
- Checkpoint portability:
TransformerWithPE keeps register_buffer('cached_mask', None, persistent=False) so a fresh model can load_state_dict(strict=True).
- evotorch optional: evotorch is imported lazily inside
TrainerGA.fit (not at
module top); requests stays declared in pyproject.toml.
Step 8: HIGH — Model tensor-shape & autoregressive contracts
forward()/infer() return (B, tgt_len, out_dim), keep batch_first=True, build
and pass the causal tgt_mask (.to(tgt.device)); dropping it leaks future tokens.
PositionalEncoding.forward keeps its length guard; TransformerWithPE threads
dim_feedforward. LSTM.__init__ keeps the input_dim == output_dim guard.
- Any new model in the
get_model factory implements BOTH forward(src, tgt) and
infer(src, tgt_len) (else log_sample_images crashes after a run).
Step 9: MEDIUM — Style, hygiene & docs drift
- Line length 99 consistent across
pyproject.toml ([tool.black], [tool.isort],
[tool.ruff]) and setup.cfg [flake8]. .pre-commit-config.yaml pins a modern
black (not 20.8b1). make format then pre-commit run --all-files yield no diff.
- Package version stays under
[project] in pyproject.toml (flit backend; no
[tool.poetry]). requests declared.
- No secrets / no artifact files: nothing staged under
data/, models/,
mlruns/, no *.npy/*.pt/*.pkl/*.ipynb, no git add -f, no file > 10 MB.
(The block_large_secret hook also guards this.)
- New public function/class has a docstring + type hints; tensor shapes documented in
forward/infer stay in sync. New source module gets a matching test_<module>.py.
- If tests/metrics/CLI changed, README + CLAUDE.md (test count, metric names, CLI
reference, invariants) were updated.
Step 10: Run tests + hooks
Run both and report exit status:
make test # pytest (currently 93 tests)
pre-commit run --all-files # or: make pre-commit
Either failing is a critical finding. (Formatting hooks auto-fix on a re-run; report
what changed.)
Step 11: Report findings
Group by severity:
- Critical — wrong loss math/NaN gradient, spectral-metric definition/guard break
(HTSR-vs-Zipf relabel, dropped Hill/KS guard, lost MP baseline), paired-seed/leakage/
test-split regression, ES/GA tiny-model or matched-loss break, MLflow metric-name or
artifact-selector break, duplicate ESConfig,
cached_mask portability break, broken
test/pre-commit, secret/large-file leak.
- High — model shape/autoregressive/checkpoint contract break, evotorch hard import,
a known silent-bug-class match.
- Medium — style/hygiene/version-table violation, docs drift.
- Low — comment / naming / docstring / type-hint polish.
For each finding: file path, the symbol or line, and a concrete suggestion. Do not make
changes unless the user asks.
If there are zero findings: report "Review passed — N files reviewed, M lines changed,
pytest , pre-commit ."
Source: mgrts/transformer-spectrum — distributed by TomeVault.
1---2name: code-review-2403description: Review pending changes in the transformer-spectrum repo for correctness and the silent-bug classes this spectral-analysis research codebase actually hits — SGT/robust-loss math & gradients, spectral-metric reliability (HTSR vs Zipf, small-matrix Hill/KS, Marchenko-Pastur), the paired-seed/leakage/test-split experiment protocol, the ES/GA tiny-model + matched-loss contract, the MLflow metric-name & artifact-selector contract, model tensor-shape/autoregressive/checkpoint contracts, and secrets/large-file hygiene. Read-only by default; surfaces findings grouped by severity. Use before every commit, or via /commit-push. Use when this capability is needed.4---56# Code review for transformer-spectrum78Review the changes currently in the working tree (staged + unstaged + untracked)9against the standards that matter for this codebase specifically. Most bugs here are10**silent**: they pass `pytest` (the 93 tests assert shapes + isfinite, mock nothing11heavy, and never exercise the sweep/experiment paths) yet change the loss math, the12spectral metric definitions, the experiment's scientific validity, or the logged13metric names. The job is to catch those.1415The review is **read-only by default** — fixes are surfaced as recommendations and16only applied if the user explicitly asks.1718## Arguments1920`$ARGUMENTS` — optional. Specific files or globs to scope the review (defaults to the21entire diff).2223## Flow2425### Step 1: Gather changes2627```bash28git status --short29git diff --staged --stat30git diff --stat31```3233If there is nothing pending, stop: "Nothing to review."3435### Step 2: Read the diff3637For each changed file, read the actual diff (not just the file list). Note which38subsystems are touched — that selects which checks below apply and which subagent to39delegate to.4041### Step 3: Delegate deep audits to subagents4243When the diff touches a fragile subsystem, dispatch the matching subagent (via the44Agent tool, `subagent_type`) and fold its findings into the report. Run independent45subagents in parallel.4647- Touches `modeling/loss_functions.py` or `settings.py` `SGTLossConfig`48 → **`loss-math-reviewer`**.49- Touches `metrics/spectral_metrics.py`, `metrics/heavy_tail_estimation.py`, or50 `modeling/trainer.py` `SpectralLoggingMixin` → **`spectral-metrics-reviewer`**.51- Touches `experiments/*.py`, `data/**/*.py`, `modeling/data_processing.py`,52 `modeling/harness.py`, `train.py`/`train_es.py`/`train_ga.py`, or the seed/split/ES/GA53 paths in `trainer.py` → **`experiment-methodology-auditor`**.54- Touches `experiments/utils/collect_artifacts.py`, the MLflow `log_metric(s)` calls in55 `trainer.py`/`train*.py`, `models.py` (`cached_mask`), or the `ESConfig` definition56 → **`mlflow-contract-auditor`**.5758For a small diff that clearly matches none of these, do the checks inline.5960### Step 4: CRITICAL — Loss math & gradient correctness6162Applies to `modeling/loss_functions.py` and `settings.py` `SGTLossConfig`.6364- **SGT moment-domain guard:** `SGTLoss.__init__` keeps `if not (p * q > 2): raise` —65 this is load-bearing (the beta functions `beta(2/p, q-1/p)`, `beta(3/p, q-2/p)` need66 `q - 2/p > 0`, else silent NaN/degenerate loss). `SGTLossConfig` carries the same67 `model_validator` (`p*q > 2`). Removing either reopens the NaN-loss bug.68- **SGT residual & skew:** `forward` keeps `diff = y_true - y_pred + m`; the skew term69 `(1 + lam*torch.sign(diff))**p` reads that same `diff`. The trainer calls70 `criterion(out, tgt)` (pred first, truth second).71- **eps guards & log1p:** SGT keeps its `+ eps` denominators and `torch.log1p(ratio)`;72 Cauchy keeps `gamma * torch.log1p(diffs**2 / gamma)`.73- **dtype/device:** every `torch.tensor` constant in `SGTLoss` derives `dtype=`/`device=`74 from the input; the loss returns a scalar `.mean()`.75- **Factory:** `get_loss_function` still maps `mse→MSELoss`, `mae→L1Loss`,76 `cauchy→CauchyLoss(gamma=2.0 default)`, `sgt→SGTLoss(p=2.0, ...)`; the default77 `TRAINING_CONFIGS` SGT entries all satisfy `p*q > 2` (q ≥ 1.001 at p=2).7879### Step 5: CRITICAL — Spectral-metric methodology8081Applies to `metrics/spectral_metrics.py`, `metrics/heavy_tail_estimation.py`,82`modeling/trainer.py` `SpectralLoggingMixin`.8384- **Naming honesty:** `zipf_sv_slope` is a rank/Zipf slope, NOT the Martin-Mahoney HTSR85 tail index. Reject any rename back to `alpha_exponent` or any code/doc that equates it86 with `pl_alpha_hill`/`pl_alpha_ks`.87- **Small-matrix guard:** `_hill_alpha`/`_ks_alpha` keep the `MIN_TAIL_POINTS` guard88 (return NaN when the tail is too small). The eigenvalue count is `min(rows, cols) =89 embed_dim` for EVERY matrix (incl. FFN) — do not claim FFN gives more eigenvalues.90- **MP baseline:** `get_spectral_metrics` still returns `mp_lambda_plus`, `mp_n_spikes`,91 `mp_signal_energy_frac` and computes the SVD **once** (passes `s` into the helpers).92- **Matrix selection:** `_ATTN_SPECS` covers encoder self-attn, decoder self-attn AND93 decoder cross-attn; `_FFN_SPECS` covers linear1/linear2. Don't silently narrow it.94- **kappa reproducibility:** `estimate_kappa_exponent` keeps the explicit95 `np.random.default_rng(random_state)` + bootstrap averaging + the `M_1/M_n > 0` guard;96 `compute_dispersion_scaling_series` starts at `n=2`.9798### Step 6: CRITICAL — Experiment protocol & data methodology99100Applies to `experiments/*.py`, `data/**`, `modeling/data_processing.py`,101`modeling/harness.py`, `train*.py`.102103- **Paired seeds:** `experiments/{synthetic,owid_covid,rvr_us}_data.py` derive one104 deterministic seed per run (`base_seed + run_idx`) shared across ALL losses in that105 run (paired init + split). Reject any reintroduction of unseeded `random.randint`, or106 a loop that gives different losses different seeds within a run.107- **No leakage:** the per-chunk `StandardScaler` in `data/rvr_us/dataset.py` and108 `data/owid_covid/dataset.py` is fit on the INPUT window only (`chunk[:input_len]`),109 never the full window that includes the forecast horizon.110- **Test set:** the harness builds train/val/TEST; val selects the best model, `test_*`111 metrics are reported. Reject reporting selection metrics as final results.112- **ES/GA tiny model:** `train_es.py`/`train_ga.py` (and the CLI) default to the tiny113 model (`embed_dim=16, num_heads=2, num_layers=1, dim_feedforward=32`, ~6k params) —114 black-box opt cannot train the full 2.3M-param net. GA `init_lo/hi` stay near the115 PyTorch init scale (~±0.15, not ±0.5); `TrainerGA._make_objective` uses116 `resample_each_call=False` (fixed batch set). Any cross-optimizer spectral claim must117 be at MATCHED final train loss.118- **Smoothing:** `generate_data.main` keeps the excess-kurtosis warning (smoothing119 attenuates the heavy tail). Matched epochs: sweeps disable early stopping.120121### Step 7: CRITICAL — MLflow contract, ESConfig, checkpoint portability122123Applies to `experiments/utils/collect_artifacts.py`, `trainer.py`/`train*.py` logging,124`models.py`, the `ESConfig` definition.125126- **Artifact selectors:** `collect_artifacts._download_artifacts` selectors127 (`esd_*.json`, `singular_vals_*.json`) match the names `log_qkv_figs` actually dumps.128- **Metric names:** training logs `*_mae`/`*_rmse`/`*_wmape` (NOT `*_mape`/`*_smape`),129 the `mp_*`/`zipf_sv_slope`/`pl_alpha_*`/`spectral_entropy`/`stable_rank` spectral keys,130 and `test_*`. A rename must update every consumer (`collect_artifacts`, notebooks, the131 `aggregate.py` `--metric` default).132- **Single ESConfig:** there is ONE `ESConfig` (pydantic, in `settings.py`); `trainer.py`133 re-exports it. Reject a second dataclass `ESConfig`.134- **Checkpoint portability:** `TransformerWithPE` keeps `register_buffer('cached_mask',135 None, persistent=False)` so a fresh model can `load_state_dict(strict=True)`.136- **evotorch optional:** evotorch is imported lazily inside `TrainerGA.fit` (not at137 module top); `requests` stays declared in `pyproject.toml`.138139### Step 8: HIGH — Model tensor-shape & autoregressive contracts140141- `forward()`/`infer()` return `(B, tgt_len, out_dim)`, keep `batch_first=True`, build142 and pass the causal `tgt_mask` (`.to(tgt.device)`); dropping it leaks future tokens.143- `PositionalEncoding.forward` keeps its length guard; `TransformerWithPE` threads144 `dim_feedforward`. `LSTM.__init__` keeps the `input_dim == output_dim` guard.145- Any new model in the `get_model` factory implements BOTH `forward(src, tgt)` and146 `infer(src, tgt_len)` (else `log_sample_images` crashes after a run).147148### Step 9: MEDIUM — Style, hygiene & docs drift149150- Line length **99** consistent across `pyproject.toml` (`[tool.black]`, `[tool.isort]`,151 `[tool.ruff]`) and `setup.cfg [flake8]`. `.pre-commit-config.yaml` pins a modern152 `black` (not `20.8b1`). `make format` then `pre-commit run --all-files` yield no diff.153- Package version stays under `[project]` in `pyproject.toml` (flit backend; no154 `[tool.poetry]`). `requests` declared.155- **No secrets / no artifact files**: nothing staged under `data/`, `models/`,156 `mlruns/`, no `*.npy`/`*.pt`/`*.pkl`/`*.ipynb`, no `git add -f`, no file `> 10 MB`.157 (The `block_large_secret` hook also guards this.)158- New public function/class has a docstring + type hints; tensor shapes documented in159 `forward`/`infer` stay in sync. New source module gets a matching `test_<module>.py`.160- If tests/metrics/CLI changed, README + CLAUDE.md (test count, metric names, CLI161 reference, invariants) were updated.162163### Step 10: Run tests + hooks164165Run both and report exit status:166167```bash168make test # pytest (currently 93 tests)169pre-commit run --all-files # or: make pre-commit170```171172Either failing is a critical finding. (Formatting hooks auto-fix on a re-run; report173what changed.)174175### Step 11: Report findings176177Group by severity:178179- **Critical** — wrong loss math/NaN gradient, spectral-metric definition/guard break180 (HTSR-vs-Zipf relabel, dropped Hill/KS guard, lost MP baseline), paired-seed/leakage/181 test-split regression, ES/GA tiny-model or matched-loss break, MLflow metric-name or182 artifact-selector break, duplicate ESConfig, `cached_mask` portability break, broken183 test/pre-commit, secret/large-file leak.184- **High** — model shape/autoregressive/checkpoint contract break, evotorch hard import,185 a known silent-bug-class match.186- **Medium** — style/hygiene/version-table violation, docs drift.187- **Low** — comment / naming / docstring / type-hint polish.188189For each finding: file path, the symbol or line, and a concrete suggestion. Do not make190changes unless the user asks.191192If there are zero findings: report "Review passed — N files reviewed, M lines changed,193pytest <result>, pre-commit <result>."194195---196> Source: [mgrts/transformer-spectrum](https://github.com/mgrts/transformer-spectrum) — distributed by [TomeVault](https://tomevault.io).197<!-- tomevault:4.0:skill_md:2026-06-16 -->