Skip to content

feat(format): training-loop-v1 6-gate PARTIAL discharge#1389

Closed
noahgift wants to merge 2 commits into
mainfrom
feat/loop-001-006-partial-discharge
Closed

feat(format): training-loop-v1 6-gate PARTIAL discharge#1389
noahgift wants to merge 2 commits into
mainfrom
feat/loop-001-006-partial-discharge

Conversation

@noahgift
Copy link
Copy Markdown
Contributor

@noahgift noahgift commented May 2, 2026

Summary

  • Binds FALSIFY-LOOP-001..006 from training-loop-v1 at PARTIAL_ALGORITHM_LEVEL via 6 verdict functions + reference ema() helper.
  • 30 unit tests including 9-bucket loss sweep + 3-state shuffle table.
  • Algorithm-level coverage advances by 6 gates; runtime ship % unchanged.

Gates bound

Gate ID Rule
LOOP-001 EMA(losses[0..5]) > EMA(losses[len-5..]) (learning)
LOOP-002 val_loss finite AND val_accuracy ∈ [0, 1] every epoch
LOOP-003 |restored - checkpoint|.abs() < 0.01
LOOP-004 LR climbs in warmup, decays post-warmup (cosine)
LOOP-005 train/val sets disjoint AND |train| + |val| == total
LOOP-006 every adjacent epoch order differs

Reference helper

ema(values) -> f32 with alpha = 2/(n+1) — pinned EMA formula matches the YAML test code.

Five Whys

See commit message — captures why bind reference EMA in-module, why 1e-2 tolerance for restorable, and why HashSet for split disjointness.

Test plan

  • cargo test -p aprender-core --lib loop_001_006 — 30 passed
  • PMAT pre-commit gates green
  • CI green

🤖 Generated with Claude Code

Binds FALSIFY-LOOP-001..006 from training-loop-v1 at PARTIAL_ALGORITHM_LEVEL
via 6 verdict functions plus a reference EMA helper.

- LOOP-001: EMA(losses[0..5]) > EMA(losses[len-5..]) (model is learning)
- LOOP-002: every epoch's val_loss finite + accuracy ∈ [0, 1]
- LOOP-003: |restored_loss - checkpoint_loss| < 0.01 (full state restored)
- LOOP-004: LR climbs in warmup, decays post-warmup (cosine schedule)
- LOOP-005: train/val sets disjoint AND |train| + |val| == total
- LOOP-006: every adjacent epoch order differs (shuffle applied)

## Five Whys

1. Why does training-loop-v1 list 6 falsification IDs without
   algorithm-level discharge? PMAT lints flagged FALSIFY-LOOP-001..006
   as unbound at PARTIAL_ALGORITHM_LEVEL.
2. Why does that block ship? Coverage % cannot move while peripheral
   training-loop invariants have no algorithm-level verdict module.
3. Why bind both verdicts AND a reference `ema()` helper? The
   loss-decreasing gate (LOOP-001) needs deterministic EMA — the
   contract YAML uses `ema(&[..5])` and `ema(&[15..])`. Pinning the
   alpha-from-len formula in-module prevents future "we tried a
   different smoothing" drift from silently passing the gate.
4. Why a 1e-2 tolerance for LOOP-003 (not bit-exact)? Per the
   contract YAML: `(restored_loss - loss_at_5).abs() < 0.01`.
   Numerical evaluation passes through the same float ops; small
   rounding differences (e.g., reordered batch summation when
   restoring optimizer state) are tolerated, but a missing optimizer
   state (drift > 0.01) is correctly caught.
5. Why HashSet equality for LOOP-005 vs sorted-vec? IDs are unordered;
   sorted-vec equality would impose an arbitrary canonical-order
   constraint the contract doesn't require. HashSet captures the
   set semantics exactly: "no element appears in both sets."

Adds 30 unit tests including 9-bucket loss sweep + 3-state shuffle
table. Realistic-healthy walks the canonical 20-epoch train run;
pre-fix walks 6 simultaneous regressions (flat losses, NaN val_loss,
checkpoint drift, constant LR, train/val overlap, no shuffle).

No runtime % shift; algorithm-level coverage advances by 6 gates.
@noahgift noahgift force-pushed the feat/loop-001-006-partial-discharge branch from 0218b77 to 28c570e Compare May 11, 2026 15:30
@noahgift noahgift enabled auto-merge (squash) May 11, 2026 15:30
@noahgift
Copy link
Copy Markdown
Contributor Author

Superseded by #1637 (135-PR squash). The commit content is included verbatim in that PR's diff. Closing now to release runner slots; this PR would have auto-closed when #1637 merges.

@noahgift noahgift closed this May 12, 2026
auto-merge was automatically disabled May 12, 2026 09:21

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant