feat(bf16): 1722/1722 tests pass — ALL PASS, zero failures

Fix last 2 tests:
- action_masking: test used 81-action FactoredAction decoder for
  45-action mask. Fixed to use mask's own 5×9 exposure encoding.
- hyperopt bounds: test both Full (all ranges) and Fast (architecture
  fixed) phases. Implemented phase_fast override in continuous_bounds
  to pin hidden_dim_base, num_atoms, dueling_hidden_dim from TOML.

Final scorecard:
  ml-core:   300/300  (100%)
  ml-dqn:    359/359  (100%)
  ml-ppo:    168/168  (100%)
  ml:        895/895  (100%)
  Total:    1722/1722 (100%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-28 13:11:47 +01:00
parent 3738677d46
commit 9b02f86fca
3 changed files with 69 additions and 45 deletions

View File

@@ -210,50 +210,51 @@ mod tests {
#[test]
fn test_45_action_masking_canonical_layout() {
use ml_core::action_space::{ExposureLevel, FactoredAction};
// 45-action layout: 5 exposure levels × 9 sub-actions each
// exposure_idx = action_idx / 9:
// 0 = Short100, 1 = Short50, 2 = Flat, 3 = Long50, 4 = Long100
let max_position = 5.0;
// At max position: Long50 (idx 3) and Long100 (idx 4) should be masked
let mask = create_action_mask(max_position, max_position, 45);
for idx in 0..45 {
if let Ok(action) = FactoredAction::from_index(idx) {
match action.exposure {
ExposureLevel::Long50 | ExposureLevel::Long100 => {
assert!(
!mask.get(idx).copied().unwrap_or(true),
"Long action {} should be masked at max position",
idx
);
}
_ => {
assert!(
mask.get(idx).copied().unwrap_or(false),
"Non-long action {} should NOT be masked at max position",
idx
);
}
let exposure_idx = idx / 9;
match exposure_idx {
3 | 4 => {
assert!(
!mask[idx],
"Long action {} (exposure_idx={}) should be masked at max position",
idx, exposure_idx
);
}
_ => {
assert!(
mask[idx],
"Non-long action {} (exposure_idx={}) should NOT be masked at max position",
idx, exposure_idx
);
}
}
}
// At min position: Short100 (idx 0) and Short50 (idx 1) should be masked
let mask = create_action_mask(-max_position, max_position, 45);
for idx in 0..45 {
if let Ok(action) = FactoredAction::from_index(idx) {
match action.exposure {
ExposureLevel::Short50 | ExposureLevel::Short100 => {
assert!(
!mask.get(idx).copied().unwrap_or(true),
"Short action {} should be masked at min position",
idx
);
}
_ => {
assert!(
mask.get(idx).copied().unwrap_or(false),
"Non-short action {} should NOT be masked at min position",
idx
);
}
let exposure_idx = idx / 9;
match exposure_idx {
0 | 1 => {
assert!(
!mask[idx],
"Short action {} (exposure_idx={}) should be masked at min position",
idx, exposure_idx
);
}
_ => {
assert!(
mask[idx],
"Non-short action {} (exposure_idx={}) should NOT be masked at min position",
idx, exposure_idx
);
}
}
}