Commit Graph

395 Commits

Author SHA1 Message Date
jgrusewski
091707cae7 plan(ml-backtesting): ISV-driven stop controller implementation plan
11 tasks, each one commit, TDD-disciplined (test → fail → impl →
pass → commit). Covers all 11 sections of the spec at
docs/superpowers/specs/2026-05-19-isv-driven-stop-controller-design.md:

- Tasks 1-2: state slots + ATR EMA in book_update_apply_snapshot
- Task 3: stop_check_isv shared __device__ helper skeleton
- Tasks 4-6: SL trigger, trail-TP + HWM ratchet, multi-horizon avg
- Task 7: bytecode VM parity (wire helper into decision_policy_program)
- Task 8: seed_inflight_limits_batched target-delta + in-flight summation
- Task 9: pnl_track_step trail_hwm reset on close
- Task 10: atomic deletion of StopRules + use_cold_start_stopgap +
          integration-test retarget + CBSW SUPERSEDED markers
- Task 11: cluster smoke validation via argo-lob-sweep.sh

All 10 §9.1 unit tests have explicit failing-test scaffolds before
their implementations, and the retargeted integration test
(cold_start_persistent_bullish_now_closes) flips the assertion to
prove the fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 23:32:38 +02:00
jgrusewski
1ecce0d826 spec(ml-backtesting): critical-review pass on ISV stop controller — 9 fixes
Issues caught in self-review and fixed:

1. Encoding ambiguity: stop-fire writing (2, 0) would have silently
   collapsed weak-alpha no-op semantics with force-flat. Introduced
   distinct side=3 = force-flat; preserved side=2 = no-op for entry
   path. Updated §3 + §5 + §7 truth table.

2. trail_hwm reset on close was implied in §4 but missing from §8's
   touched-files list. Added pnl_track.cu modification (§7.1) +
   added to §8 Added list.

3. __device__ helper enforcement: §3 now mandates stop_check_isv()
   as a shared __device__ function called from both decision kernels,
   not duplicated code.

4. Kernel arg additions enumerated explicitly in new §4.1 table —
   every kernel-launch site gets named, no "thread through every kernel"
   hand-wave.

5. seed_inflight_limits_batched (resting_orders.cu:439–475) named
   explicitly in §1 + §7 — the actual kernel that needs the position-
   target-semantics fix.

6. In-flight order summation: naive delta = target_signed - pos was
   strictly worse than the original additive bug under non-zero
   latency (would produce pos = pre + K·delta after fills). Fixed
   §7 algorithm to compute effective_position by scanning all
   active∈{1, 2} slots and summing their signed sizes. Added
   position_target_not_additive_with_latency test.

7. ATR α=0.4 honest justification in §10: not strictly derived from
   pearl_wiener_alpha_floor_for_nonstationary (which is about co-
   adapting control loops, not passive observation); chosen as a
   pragmatic project-wide constant matching isv_kelly_update_on_close.

8. CUDA Graph host-branch-free affirmation added to §3 — explicit
   compatibility with P5 graph capture.

9. Cold-start symmetry caveat (§5): at n_trades_seen=0 both EMAs are
   0 so sl_distance == trail_distance == atr — asymmetry only
   emerges post-bootstrap. Acknowledged honestly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 23:20:04 +02:00
jgrusewski
11d1279990 spec(ml-backtesting): ISV-driven stop controller — supersedes falsified CBSW
Replaces StopRules::default()-all-zeros (the actual cause of the cluster
smoke's n_trades=0, falsifying the CBSW dilution diagnosis) with an
ISV-driven SL + trail-stop controller folded into the existing decision
kernel(s). Per-backtest ATR EMA on mid-price + per-horizon pnl_ema_*
drive distances under max(real, floor) per
pearl_blend_formulas_must_have_permanent_floor. No new kernel; single
source of truth in step_decision*. Folds in the position-target
semantics fix (200-event local repro showed position_lots=199 from
additive-vs-target order semantics) — same commit.

Removes: StopRules, sl_tp_rules, Q1 stopgap field/branch,
use_cold_start_stopgap propagation. Marks CBSW spec + plan SUPERSEDED.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 23:06:37 +02:00
jgrusewski
2130bee006 plan(ml-backtesting): CBSW cold-start aggregator implementation plan
4-task atomic ladder (Q1-Q4) implementing spec 566e8bcb0. Each task
maps to one commit per feedback_no_partial_refactor:

  Q1: Cold-start stopgap (bytecode max-confidence policy upload)
  Q2: CBSW kernel aggregator + Tier 1 revert (atomic)
  Q3: Memory pearl pearl_conviction_bootstrap_for_kelly_aggregation
  Q4: Parallelism spec §3.4 cross-reference

Kernel ABI unchanged across all 4 commits — Q2 modifies only
decision_policy_default's body (decision_policy_program left as a
pluggable bytecode-VM experiment surface). Q2 atomically deletes
the Q1 stopgap field/CLI/YAML/harness branch in the same commit
that lands the kernel fix (feedback_no_legacy_aliases compliance:
grep returns zero hits for use_cold_start_stopgap post-Q2).

Validation gates per spec §9:
  - Q1: cluster smoke n_trades > 100, total_pnl != 0 (diagnosis
    confirmation). If n_trades = 0 still, STOP — downstream bug.
  - Q2: pre-existing 11 CUDA tests still pass; 7 new cbsw_*
    regression tests pass; cluster smoke n_trades > 100; ev/s
    rate ratio Q2/Q1 ≥ 0.95.

Self-review confirms all 11 spec sections covered, no placeholders,
type/signature consistency across tasks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:53:28 +02:00
jgrusewski
566e8bcb0a spec(ml-backtesting): CBSW review pass — 11 fixes (perf + correctness)
Critical review surfaced 11 actionable issues in the v1 spec; 10 fixed
inline (#11 — legacy-comparison test — dropped per user decision since
empirical legacy behavior is already known: n_trades=0).

Performance:
1. expf → piecewise-linear ramp (~5× cheaper on GPU, no transcendental
   in the hot path). Operationally equivalent: monotonic, saturating,
   midpoint at K. Side-benefit: pure max-confidence at cold-start
   (sq=0 instead of sigmoid's 11.9% leakage).
2. Single fused per-horizon pass replaces the two-loop sketch.
3. Tier 2 scope narrowed to decision_policy_default ONLY. The bytecode
   VM (decision_policy_program) stays unchanged — runs only for custom
   strategy experiments, never in production policy. Halves Tier 2's
   surface area + test cost.
4. __device__ helpers cbsw_signal_quality + cbsw_weight introduced for
   single source of truth.

Correctness bugs (silently present in v1 sketch, would have shipped):
5. strong_h and sq_min_active initializers added (were referenced
   before init in the per-horizon loop).
6. Attribution mask at cold-start was setting all 5 bits because every
   w[h] >= floor > 1e-9; trades would pollute ALL horizons'
   recent_sharpe. Fix: binary split — at sq_min_active < 0.5 attribute
   only to strong_h; at mature, attribute per weights > floor + epsilon.
7. sq_min was "min over h", which permanently locked the aggregator
   into cold-start mode if any horizon never gets attributed (e.g.,
   h6000-only-trading regime). Fix: sq_min_active = min over h with
   n_trades_seen > 0; cold horizons don't gate maturity.
8. Opposing-horizons case now correctly fires on the strongest single
   horizon at cold-start (piecewise-linear sq=0 → pure max-conf), with
   explicit design-choice note explaining why this conservatism trade-
   off favors firing.

Spec hygiene:
9. Rate validation committed to a measurement gate (Q2 ev/s ≥ 95% of
   Q1 ev/s) instead of back-of-envelope estimate.
10. Kernel ABI explicitly stated as unchanged → feedback_no_partial_
    refactor compliance is trivial at the kernel boundary.
12. Tier 1's use_cold_start_stopgap field is DROPPED in Q2 atomically
    (not orphaned), and DoD checklist includes a grep-zero gate for
    feedback_no_legacy_aliases compliance.

Risks updated: removed the sigmoid-narrowing risk (irrelevant now);
added register-pressure risk with the rate-gate mitigation; added
explicit "cold-start may lose on noisy trades" risk with empirical
escalation path (bump kelly_floor 0.20 → 0.40 if Q2 smoke shows large
negative PnL).

Math walk-throughs rewritten for piecewise-linear (different numbers
at cold-start): cold = pure max-conf, mature = pure weighted-sharpe,
clean separation at sq_min_active threshold.

Awaiting review of the revised spec before writing-plans dispatch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:47:13 +02:00
jgrusewski
1271d03931 spec(ml-backtesting): CBSW cold-start aggregator design
The post-trunk-grows threshold-tuning smoke (81decf40f) produced
n_trades=0 despite the model having a HEALTHY max-conviction
distribution (74.6% of decisions ≥ 0.30, 26.7% ≥ 0.70, full spread
across [0,1]). Diagnosis: the linear-weighted-mean aggregator in
decision_policy_default is structurally dilution-bound at cold-start
— single-horizon strong signals get washed out when uniform-floor
weights produce mean-over-horizons aggregation.

Solution: Conviction-Bootstrapped Sharpe Weighting (CBSW). Hybrid
max-confidence × weighted-sharpe with a per-horizon sigmoid transition
keyed on n_trades_seen vs MIN_TRADES_FOR_VAR_CAP. Cold-start: sig_mag
(decision-time conviction) drives weights AND max-confidence aggregator
fires single-horizon trades. Mature: recent_sharpe (historical) drives
weights AND linear-mean aggregator emphasizes strong-Sharpe horizons.
Permanent floor preserved per pearl_blend_formulas_must_have_permanent_floor.

Mirrors DQN bootstrap pattern (pearl_thompson_for_distributional_action_
selection): when historical estimates are uncertain, use available
signal as the bootstrap. Sig_mag is the ISV signal at decision time;
recent_sharpe is the ISV signal at trade-close time. Transition
self-terminates based on data accumulation, not time constants.

3-tier delivery (one spec, atomic commits):
  Q1: Bytecode VM stopgap — upload max-confidence 7-instruction
      program per backtest. Validates diagnosis; zero kernel work.
  Q2: Kernel CBSW — replace weight + aggregator in both decision
      kernels. 5 new regression tests covering cold/mature/transition.
  Q3: New memory pearl pearl_conviction_bootstrap_for_kelly_aggregation
      capturing the lesson.
  Q4: Cross-reference from parallelism spec (deployability sweep
      depends on CBSW being live to produce meaningful verdict).

The parallelism work (P1-P6) is fully working — confirmed by the
threshold-tuning smoke completing end-to-end (Succeeded status, 500k
decisions, artifacts written, aggregator parquet emitted). What's
blocked is the deployability VERDICT, because the dilution bug means
all variants would show n_trades=0 regardless of cost/latency/threshold.
CBSW unblocks the verdict.

Awaiting review before transitioning to writing-plans for Q1-Q4
implementation plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 21:38:55 +02:00
jgrusewski
2b18835437 plan(ml-backtesting): deployability-sweep parallelism implementation plan
7-task atomic ladder (P1-P7) implementing spec d646c1eb3. Each task
maps to one commit per feedback_no_partial_refactor:

  P1: Per-backtest sim parameter arrays (BatchedSimConfig + kernel ABI)
  P2: seed_inflight_limits_batched kernel (replaces host roundtrip)
  P3: detect_close_transitions_batched kernel (replaces close-detect loop)
  P4: Threshold gate + per-fill cost integration
  P5: CUDA Graph capture of forward_only (1.3× forward target)
  P6: Batched-cell sweep schema + 140-variant runner
  P7: 3-pod scale + final verdict

Measurement gates per §9 of the spec (P2 ≤90s, P5 ≤60s, P6 ≤30min,
P7 ≤60min target / ≤120min firm). Stride=8 fallback activated at P6
if measurement misses by >20%.

Self-review confirms all 13 spec sections covered, no placeholders,
type consistency across tasks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:39:17 +02:00
jgrusewski
d646c1eb3c spec(ml-backtesting): apply 9 critical-review fixes to parallelism spec
Critical review surfaced 9 issues; all fixed inline:

1. §1 — Reframed "140× amortization" as "amortization on forward; sim
   runs parallel". True win is on the ~2ms forward shared across 140
   cells, not on sim work which scales linearly with n_backtests.
2. §2 — Made the 1h target vs firm bound explicit (≤1h target, ≤2h
   firm). Acknowledges Graph capture realistic speedup is 1.2-1.5×,
   not 2×.
3. §5 — Dropped atomicAdd. Plain `+=` under the single-writer-per-block
   convention (existing pattern across sim kernels). No race.
4. §4 — Documented max-over-horizons threshold rationale (vs per-
   horizon or aggregate-conviction). Flagged per-horizon as a follow-up
   tweak if dilution pathway matters in the verdict.
5. §7 P5 + §10 risk — Captured-vs-uncaptured tolerance is 1e-5 relative,
   NOT strict bit-identity. CUDA Graph capture can reorder reductions
   harmlessly by 1 ULP; strict bit-identity would be a false-positive.
6. §8 — Made explicit that parallel_sim_equivalence + independence
   tests are BOTH required. Equivalence alone is necessary but not
   sufficient (a shadow-backtest[0] bug still passes equivalence).
7. §3.3 — Specified output schema: `cell_W{n}/sim_<variant_name>/`
   with summary.json carrying a resolved `sim_config` block (verdict
   emitter reads that, not the directory name).
8. §7 P4 — Enumerated apply_fill_to_pos call sites + added grep-verify
   step before commit, so no fill path silently loses cost.
9. §9 — Tightened rate-validation gates with hard targets (P2 ≤90s,
   P5 ≤60s) instead of generous minute envelopes. Added §9.1 stride=8
   fallback as explicit Plan-B if Graph capture under-delivers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:27:38 +02:00
jgrusewski
bd35bdb6a3 spec(ml-backtesting): deployability-sweep parallelism + rate design
Brainstormed live with claude-opus-4-7. Targets ≤1h wall-clock per
4-quarter sweep on 1-3 L40S pods (vs ~750 GPU-hours naive). Three
multiplicative levers: per-backtest sim parameter matrix (~140×),
CUDA Graph capture (~2×), pod-level parallelism (~3×). Verified by
code-read during scoping:
  - forward_only has no graph capture (X11 plan said so, X11 commit
    didn't ship it)
  - two host-roundtrip loops in sim.rs need GPU-ization for batching
    to pay off (dispatch_latent_market_orders + close-detection)
  - cost system is a literal-zero placeholder in pnl_track.cu:92

7-commit atomic ladder (P1-P7), each gated by tests + a measured rate
target. bf16 explicitly deferred to follow-up.

Awaiting review before transitioning to writing-plans for the
implementation plan.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:08:24 +02:00
jgrusewski
d45dde8458 plan(ml-alpha): trunk-grows refactor + deployability validation roadmap
20-commit atomic ladder (X0–X19) + Phase 1→2 gate + Phase 2 runtime
runbook. Implements spec da1dd92bf:

  X0:    perception_forward_golden fixture (bit-equivalence gate)
  X1:    CfcTrunk v2 weight skeleton (no callers)
  X2–X9: incremental weight-group migrations (VSN, Mamba2 ×2, LN ×2,
         attn-pool, CfC, GRN heads), each gated by golden fixture
  X10:   hoist forward kernels into CfcTrunk methods
  X11:   capture_graph_a covers full v2 forward + captured-vs-uncaptured
         equivalence test
  X12:   CheckpointV2 envelope + save/load (V1 hard-rejected)
  X13:   PerceptionTrainer.save_checkpoint delegate
  X14:   alpha_train saves best_h6000 checkpoint
  X15:   verify ml-backtesting accepts CheckpointV2 (no code change)
  X16:   max_drawdown_pct with \$35k base
  X17:   emit_deployability_verdict + tiered logic + 6 unit tests
  X18:   GPU smoke test against real trained checkpoint
  X19:   three sweep YAMLs (smoke, threshold-tuning, deployability)
  Gate:  fold-0 smoke must reproduce recorded 3-fold A/B numbers
         within ±0.010 absolute before Phase 2 begins
  P.1–6: Argo runtime (training → smoke → threshold → sweep → verdict)

Self-review confirms 1:1 spec coverage. Three soft adaptation points
(HEAD_MID constant, Mamba2Block accessors, BacktestHarnessConfig field
names) resolve at code-read time. One placeholder (todo!() in X11
explanatory text) is called out in self-review for replacement when
that commit lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 01:04:30 +02:00
jgrusewski
da1dd92bf8 spec(ml-alpha): trunk-grows refactor + deployability validation (supersedes prior)
Supersedes the 2026-05-19 deployability spec (commit 07d5de504). The
prior spec assumed CfcTrunk::save_checkpoint was the producer-side
wiring point — discovered at execution time that alpha_train trains via
PerceptionTrainer (full v2: VSN + Mamba2 ×2 + LN ×2 + attn-pool + CfC +
heads), not the simpler CfcTrunk. The existing LOB backtester loads
CheckpointV1 envelopes that only know about CfC weights, so there is no
producer for a checkpoint containing the full v2 model.

New scope: one bigger spec covering refactor + deployability end-to-end.

Phase 1 (X0–X19, code commits): grow CfcTrunk to own the full v2
inference graph; restructure PerceptionTrainer to wrap a trunk + add
training-only state (grads, AdamW). Discipline: bit-equivalence golden
fixture (X0) gates every refactor commit (X1–X11). CheckpointV2
envelope (X12) replaces V1. Verdict emitter (X17) reuses the tiered
classification (Pass-robust / Pass-nominal / Fail-inconclusive / Fail /
Fail-degenerate) from the superseded spec.

Phase 2 (Argo runtime): production training → smoke gate → threshold
pre-registration → 560-cell deployability sweep → verdict + memory
update.

Hard gate before Phase 2: post-refactor fold-0 smoke must reproduce
recorded 3-fold A/B numbers (best_mean_auc 0.7529, best_h6000 0.7639,
both within ±0.010 absolute) from project_ml_alpha_v2_ab_verdict
memory. Prior spec marked SUPERSEDED in its header, kept in history as
audit trail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:54:45 +02:00
jgrusewski
4938ac2ec5 plan(ml-alpha): v2 deployability validation — atomic-commit roadmap
Five-commit implementation plan + two-step runtime runbook for the
deployability spec committed at 07d5de504. Bite-sized TDD tasks:

  C1: wire save_checkpoint(best_h6000) into alpha_train.rs (~10 LOC)
  C2: max_drawdown_pct field on Summary, $35k starting-capital base
  C3: emit_deployability_verdict + tiered logic + 6 unit tests
  C4: GPU integration smoke test (#[ignore], env-var-gated)
  C5: three sweep YAMLs (smoke, threshold-tuning, deployability)
  C6: runtime — Argo prod training → smoke → threshold pre-reg → full sweep
  C7: commit verdict, update memory

Self-review confirms 1:1 spec section ↔ task coverage. Two soft
adaptation points (AlphaTrainSummary struct name, BacktestHarnessConfig
defaults) marked as code-read-and-adapt; no hard TBDs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:40:15 +02:00
jgrusewski
07d5de5048 spec(ml-alpha): v2 deployability — stress anchor + max-dd gate + diagnostics
User revisions to design spec from this session:

1. §2.1 — split anchor into realistic (200 ms, 1 tick) and stress (400 ms,
   1.5 tick). Realistic remains the hard verdict gate; stress grades the Pass
   into Pass-robust vs Pass-nominal.

2. §2.2 — expand metrics from Sharpe-only to four: annualized daily Sharpe
   and max-drawdown are hard gates (median across windows > 1.0 and < 20%
   respectively); Sortino and profit factor are diagnostics. Per-window
   summary.json schema extended.

3. §2.6 — verdict emitter rewrites to two-anchor logic, tiered output:
   Pass-robust / Pass-nominal / Fail-inconclusive / Fail / Fail-degenerate.

4. §3.3 — added max-dd computation and zero-trade-window failure modes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:32:30 +02:00
jgrusewski
0809390cd5 spec(ml-alpha): v2 deployability validation — falsifiable LOB-backtest verdict
Closes the wiring gap between the existing real-LOB backtest system (C1–C19 on
this branch) and the v2 ml-alpha model. alpha_train.rs currently never calls
save_checkpoint, so the LOB harness/sweep/aggregate machinery has never been
pointed at a real trained model.

Design defines a single-pass falsifiable deployability gate: produce a
production checkpoint (cv-n-folds=1, cv-train-window=4 → train on 2024
quarters, val on 2025-Q1, hold out 2025-Q2..2026-Q1), pre-register one
threshold on the W0 val window, then evaluate median Sharpe across 4
held-out walk-forward quarters at the realistic Scaleway→IBKR anchor (200ms
RTT, 1-tick all-in cost). Pass iff median > 1.0; inconclusive in [0.8, 1.0]
counts as fail; smoke gate halts the full sweep on any wiring failure.

Approved through brainstorming. Awaiting user spec-review before plan
handoff.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:26:48 +02:00
jgrusewski
6b7920474d spec(ml-alpha): mark AUC-regret controller SUPERSEDED — empirically falsified
The motivating "50% saturation hit-rate" observation came from gm67g
fold 0 (Option-2 config, commit 004b662c8 — itself a -0.003 mean_auc
regression vs ISV-σ at 410ab6b0e). Re-running the same diagnostic on
the actual production baseline (ISV-σ 3 folds: rxm5t/r57lx/x24d6,
logs retrieved from MinIO argo-logs bucket) on 215 horizon-epoch
observations:

  saturated λ→AUC up:     8/13 = 61.5%   median Δauc = +0.0025
  non-saturated→AUC up:  96/202 = 47.5%   median Δauc = -0.0012
  difference:            +14pp in favor of the controller working

The BCE-z-score controller is empirically correlated with the
optimization target. No evidence it's misaligned with AUC. Spec
premise falsified.

Spec retained in tree as historical record. The diagnostic
methodology itself (saturation→Δauc analysis on archived MinIO logs)
is the durable artifact and is documented in the supersede block.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 23:24:01 +02:00
jgrusewski
1fc100ae74 spec(ml-alpha): AUC-regret controller — replace BCE-z-score signal with per-horizon-regret
The current λ controller boosts horizons by BCE-EMA z-score, which conflates
three distinct causes of high BCE — only one of which (under-trained
horizon) benefits from boosting. The other two (intrinsically harder
horizon, calibration drift) are unaffected by gradient-magnitude lifts.

Empirical motivation (gm67g fold-0, this branch's 3-fold run):
when λ_h6000 saturated at 2.0, h6000's next-epoch AUC went UP 2/4
times and DOWN 2/4 times. 50% hit rate ⇒ the BCE saturation signal
is misaligned with the optimization objective.

This spec replaces BCE-z-score with AUC-regret:

  best_auc[h]     = running max of per-horizon validation AUC
  regret[h]       = max(0, best_auc[h] - current_auc[h])
  regret_max_ema  = EMA of max_h regret[h]
  λ[h]            = clamp(1.0, 2.0, 1 + regret[h] / regret_max_ema)

Properties:
  - Aligned with the objective (AUC, not BCE)
  - Naturally bounded (regret ∈ [0, 1])
  - "At personal best" → λ=1.0 (no wasted boost)
  - Auto-saturation by design (max-regret horizon → ceiling)
  - Cold-start clean (e0: best=current, regret=0, uniform λ)
  - Zero hardcoded magic beyond bootstrap epsilons

Implementation surface ~250 LOC:
  - Split horizon_lambda kernel: horizon_loss_ema (per-step) +
    horizon_lambda (per-epoch, AUC-regret math)
  - Trainer state: drop z_max_ema, add best_auc + regret_max_ema
  - Per-epoch entry point: trainer.update_lambda_from_auc()
  - Extend isv snapshot log line with best_auc_h* + regret_h*

Test plan:
  - Local 9/9 perception_overfit
  - New synthetic-AUC unit test (controller correctness)
  - Cluster 5-epoch smoke + 3-fold A/B vs Option-2 baseline (004b662c8)
  - Success: mean_auc lifts ≥ +0.005 AND median sat→next-AUC delta positive

Awaiting user review before plan handoff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 23:06:29 +02:00
jgrusewski
4425a77844 plan(ml-alpha): v2 multi-horizon implementation plan (V1-V13)
Concrete TDD-driven commit map for the v2 spec
(2026-05-18-ml-alpha-v2-multi-horizon-design.md). Thirteen commits
ordered by dependency: delete falsified path, build new kernels with
numgrad parity (V2-V8), trainer state bundle (V9), wire into
PerceptionTrainer (V10), local smoke (V11), cluster smoke (V12), 3-fold
A/B (V13). Per-commit verification gates and explicit stop conditions.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 13:22:48 +02:00
jgrusewski
1c2ee1d7c3 spec(ml-alpha): v2 multi-horizon redesign (A+B+C+D+E integrated)
Integrated design spec for the post-A/B redesign: Kendall sigma BCE
(A), L2 anchor on horizon tokens + shared Q (B), horizon-token
K-prepend replacing per-horizon Q_h (C), regime-aware MoE gate (D),
and inverted-axis attention pass (E). Bundled per
pearl_no_deferrals_for_complementary_fixes — all five axes have
orthogonal architectural scope and independent kill criteria.

Spec drops the C21-C25 per-horizon Q_h path (falsified by sweep
2026-05-18: mean_auc -0.019 vs single-Q baseline) and migrates the
existing init buffers into the new horizon-tokens prefix.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 13:20:26 +02:00
jgrusewski
f5632649ca spec(ml-alpha): per-horizon attention pool design (C20)
Captures the brainstormed "alternative attention pool variants"
follow-on from the original real-LOB integration brainstorm (Axis 1,
deferred from the LOB workstream as a separate model-side spec).

Design:
  Replace shared learned query Q[HIDDEN_DIM] with per-horizon queries
  Q_h[N_HORIZONS, HIDDEN_DIM]. Per-horizon softmax + context vectors
  feed multi-horizon heads directly (PATH A) — each horizon attends
  to a different part of the K=6000 LN_b output sequence. CfC k=0
  state is initialised by the MEAN of per-horizon contexts so the
  K-loop recurrence + state amplification (per
  pearl_state_amplifies_short_horizon_into_long_horizon) survives.
  Heads consume per-horizon context concat CfC h_K (residual) with a
  default 75/25 weight split.

Falsifiable claim (§0): A/B-tested win means h6000 mean_auc lifts by
≥ +0.01 absolute OR per-horizon distribution shifts toward short
horizons (h1000, h300) with no net h6000 loss. The 3-fold variance
band on the current architecture (mean_auc 0.7749 ± 0.024) means a
+0.01 lift is within noise — a meaningful effect needs ≥ +0.024 or
qualitative distributional shift.

Two new kernels (per_horizon_attention_pool_fwd + _bwd) + signature
extension on multi_horizon_heads_{fwd,bwd}. Variant-toggle config flag
(SharedQuery vs PerHorizonQuery) keeps the existing path fully
functional; new variant is opt-in. CheckpointV1 → V2 with explicit
discriminant + optional q_h field; V1 files load as SharedQuery, new
V2 training writes the discriminant.

Three validation rings:
  1. Per-(b,h) numgrad parity at K=16
  2. One-epoch smoke (no NaN, loss decreases)
  3. 30-epoch × 3-fold A/B (#204) — decision gate per §0 falsifiable claim

Implementation explicitly deferred. The decision to invest depends on
(a) GPU time budget (~3-6 hrs on L40S × 5 GPUs for the A/B), (b)
whether per-horizon cost-frontier sweeps (#202 follow-ups) surface
viable horizons beyond h6000 that would benefit from per-horizon
specialisation, and (c) the 3-fold variance noise floor making the
expected effect size visible.

Next step when ready: invoke superpowers:writing-plans against this
spec for the ~6-8 commit implementation plan.

Closes the "good to have" question from the recent brainstorm with a
concrete decision framework rather than ad-hoc implementation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 10:20:38 +02:00
jgrusewski
fab2d70c92 plan(ml-backtesting): real-LOB integration implementation plan
10 atomic commits, ~40 sub-tasks, TDD per superpowers:writing-plans:
  C1 ml-alpha loader inference_only mode
  C2 ml-backtesting order types + SlotTag
  C3 policy tree + bytecode flatten
  C4 build.rs + book_update kernel + sim skeleton (3 fixtures)
  C5 order_match kernel + latency-aware fills (4 fixtures)
  C6 pnl_track kernel (1 fixture)
  C7 decision_policy kernel + per-horizon ISV-Kelly (3 fixtures)
  C8 BacktestHarness orchestrator + Ring 1b trainer-parity test
  C9 artifacts + aggregate + fxt-backtest binary
  C10 Ring 2 invariant fuzz (N in {1, 16, 256})

Plan ends with green Ring 1 (11 fixtures) + Ring 1b + Ring 2 (3 fuzz)
and a working fxt-backtest run|aggregate CLI. Ring 3 (production-day
replay), per-horizon cost-frontier sweep, model-checkpoint sweeps,
IBKR live adapter, and multi-fill P&L explicitly deferred.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 02:18:18 +02:00
jgrusewski
bfbaea2661 spec(ml-backtesting): real-LOB integration design
Greenfield LOB simulator + execution policy + backtest harness inside
existing ml-backtesting crate. Turns the AUC predictor into a P&L
producer at IBKR+Scaleway latency profile (100ms baseline).

Key design decisions:
- Reuse trainer's MultiHorizonLoader, Mbp10RawInput, snap_feature_assemble
  cubin, CfcTrunk captured graph verbatim (zero train-vs-deploy skew).
- Per-horizon ISV-Kelly + adaptive WeightedByRealizedSharpe aggregator
  (no static horizon mask; policy self-shifts capital).
- Block-per-backtest CUDA (32 threads/warp/block), ~1.4 KB shared mem.
- Three captured graphs (perception, step-event, decision); host branches
  only between captures.
- Mapped-pinned for all CPU/GPU buffers (hard requirement per
  feedback_no_htod_htoh_only_mapped_pinned).
- Three validation rings: N=1 bit-exact fixtures, trainer-parity check,
  N>1 invariant fuzz; production-day replay as Ring 3.

Single binary fxt-backtest with run + aggregate subcommands. No new
crates; extends existing ml-backtesting alongside barrier_backtest.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 01:51:11 +02:00
jgrusewski
c508d101c1 plan(perf): K-loop block-per-batch parallelization implementation plan
Bite-sized 22-task plan implementing the design at
docs/superpowers/specs/2026-05-17-kloop-parallelization-design.md.

Four atomic commits per the spec's Rollout section:
  Commit 1: reduce_axis0 kernel + cfc_step refactor (Tasks 1-10)
  Commit 2: GRN bwd refactor (Tasks 11-14)
  Commit 3: VSN bwd refactor (Tasks 15-17)
  Commit 4: attention_pool bwd refactor (Tasks 18-20)

Each commit covers kernel rewrite + per-batch scratch buffers +
reducer launches + memset_zeros wiring + smoke validation.

Tests added across commits:
  - cfc_bwd_b1_oracle.rs (Task 6): B=1 oracle vs single-sample helper
    within relative_eq 1e-5 (FP-tolerant, not bit-exact)
  - stacked_trainer_loss_shrinks_at_batch_32 (Task 7): first test
    that exercises the cross-batch reducer path
  - cfc_bwd_scratch_clears_between_steps (Task 8): scratch-zero
    regression guard

Acceptance gates 1-8 from the spec are mapped to Tasks 6, 7, 8, 9,
21, 22 (local + cluster A/B perf). Reference baseline for gate #8
is t6z89's per-epoch AUC trajectory.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 23:27:20 +02:00
jgrusewski
ea1d8703b7 spec(perf): revise K-loop parallelization design — full critical pass
Revises all 12 issues from the self-review pass:

1. (HIGH) Soften bit-equivalence claim — single-sample helper and
   batched kernel at B=1 are different CUDA kernels; FP order may
   differ. Acceptance is relative_eq ≤ 1e-6, not bit-exact.
2. (HIGH) Explicit asymmetry: only cfc_step has a single-sample GPU
   oracle. GRN/VSN/attn bwd rely on smoke + chain-rule preservation.
   feedback_no_cpu_test_fallbacks.md forbids a CPU reference oracle.
3. (HIGH) Realistic targets — 3× floor, 5× stretch. Drops 15× claim
   which was Amdahl-bounded under any reasonable assumption.
4. (MED) AdamW-after-reducer invariant stated explicitly: final grad
   buffer is OVERWRITE by reducer, meaningful only after reducer ran.
5. (MED) New B=32 smoke test (stacked_trainer_loss_shrinks_at_batch_32)
   actually exercises the cross-batch reduction path; existing
   perception_overfit suite is all B=1.
6. (MED) Rollout commit 1 bundles reduce_axis0 + first consumer
   (cfc_step refactor) to avoid feedback_wire_everything_up.md
   orphan-kernel anti-pattern.
7. (LOW) Drop "merge to ml-alpha-phase-a" — user already chose direct
   commits to that branch; clarify in Rollout.
8. (LOW) Add explicit scratch-sizing formula:
        scratch_bytes ≈ B × Σ(param tensor sizes per kernel).
9. (LOW) Remove resolved open question (memset_zeros ordering).
10. (STRUCT) Post-refactor bottleneck analysis section — names the
    next L40S floor (Mamba2 scan, launch latency, cuBLAS).
11. (STRUCT) cudaFuncSetAttribute note — refactored cfc_bwd's per-
    block shared mem drops to 1 KiB; no attribute change needed.
12. (STRUCT) Explicit Rollback section — atomic-commit-per-kernel +
    revert strategy; rollback baseline is the spec commit
    (54aa69c10) on ml-alpha-phase-a.

Plus locks the target pool to L40S — speedup must be attributable to
the refactor, not to a hardware bump. H100 / BF16 / larger batch
become candidates for a follow-up spec once the L40S floor is known.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 23:13:32 +02:00
jgrusewski
54aa69c108 spec(perf): K-loop block-per-batch parallelization design
Documents the design for fixing the single-SM bottleneck in five
backward/K-loop kernels: cfc_step (fwd+bwd), GRN bwd, VSN bwd, and
attention_pool bwd. All currently use grid=(1,1,1) with an internal
n_batch loop — on L40S (142 SMs) with B=32 this puts <1% of the GPU
to work in the K-loop critical path.

Architecture: block-per-batch (grid=(B,1,1)) for the kernel body, plus
per-batch grad scratch buffers reduced via a single parameterised
reduce_axis0 kernel (block tree-reduce, no atomicAdd per
feedback_no_atomicadd.md). Same pattern as the existing LayerNorm bwd
reducer — CUDA-Graph-safe, debuggable, and consistent with foxhunt's
no-cooperative-groups discipline.

Target: ≥3× epoch wall speedup (stretch 8-15×). Makes 3-fold CV
tractable (10.5h → 2-3h) and unblocks decision-stride / state-dim
sweeps that compound the gain.

Acceptance gates: (a) all 8 perception_overfit smokes still converge,
(b) new B=1 bit-equivalence test asserts the refactored batched bwd
kernel at B=1 matches the existing single-sample helper byte-for-byte,
(c) cluster A/B vs t6z89 baseline shows AUC trajectory within ±0.005
and epoch wall ≥3× faster.

Atomic refactor per kernel — one commit per kernel covering the
kernel rewrite, scratch buffer alloc, reducer launch wiring, and
smoke. No "_legacy" parallel kernels per feedback_no_legacy_aliases.md
+ feedback_no_partial_refactor.md.

Open implementation-plan decisions: exact memset_zeros ordering inside
the captured graph, batch-vs-per-tensor reducer launches, optimal
block_dim for reduce_axis0 itself.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 23:06:28 +02:00
jgrusewski
010445b5df docs(plans): pivot Phase 1.7 to TFT GRN heads; add Phase 2C (TGN Δt Fourier) + 2D (TFT VSN)
User directive 2026-05-17: borrow TFT GRN over the planned 2-layer MLP heads.
GRN structure: 2-layer GELU MLP body (eta_2 → eta_1) + GLU gate + main +
skip-projection from trunk → final sigmoid. Gives per-horizon "linear vs
deeper-transform" gating, matches the regime-conditional alpha pattern
(pearl_snapshot_alpha_is_regime_conditional). 5x parameter count vs the
2-layer MLP but the gated residual is exactly what TFT empirically wins on.

Phase 2C (TGN Δt Fourier features): 8 sin/cos features of Δt at log-spaced
periods [60s, 6s, 600ms, 60ms] appended to snap_features. Critical with
decision-stride>1 where Δt varies across positions. Bumps FEATURE_DIM 32→40.

Phase 2D (TFT VSN): per-feature softmax-normalised gates at the trunk entry,
replacing raw concat of snap_features. Learns to down-weight noisy
features per regime (canonical: trade-flow in low-volume, OFI in
spread-Q4). 2 new param tensors, 1 new cuda kernel (fwd+bwd).

Existing 2-layer MLP kernels from Tasks 1.3/1.4 stay in the cubin as
ablation baseline; wired path becomes GRN.

Phase 1.7 plan now spells out the full GRN forward + backward chain rule
(skip + sigmoid(gate) * main → outer sigmoid), kernel signatures,
parameter Xavier init, AdamW × 10 setup, and an extended numerical-grad
check covering all 10 new param tensors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 21:41:02 +02:00
jgrusewski
b5530b551b docs(plans): model capacity scale-up — 3-phase implementation plan
Three sequenced architectural capacity additions to push h6000 AUC
from current ~0.72-0.74 cross-fold plateau toward ≥0.78 deployment
target. Each phase independently deployable + measurable.

Phase 1 — Per-horizon specialisation (~1.5hr code):
  - LayerNorm between Mamba2 trunk and CfC K-loop (with backward
    + per-row param-grad reduction kernel; no atomicAdd).
  - 2-layer GELU MLP heads [hidden=128 → mid=64 → 1] per horizon;
    ISV lambda integrates into the trunk-grad component of head
    backward. Tasks 1.1-1.8 fully detailed (kernel source +
    integration + numerical grad check + smoke + deploy).

Phase 2A — Decision-stride sampling (~1.5hr code):
  - User-prioritised lever. Yield every S-th snapshot per training
    sequence; K=64 with stride=4 covers 256 ticks of context for
    the same compute as 64 ticks at stride=1. Mamba2's dt_s scalar
    becomes stride-aware. Tasks 2A.1-2A.5 fully detailed (loader
    refactor + test + CLI plumbing + synthetic smoke + deploy).

Phase 2B — 2-stack Mamba2 (~2hr code, sketch):
  - Two Mamba2Block instances; forward chain
    snap_feat → mamba2_l1 → LN → mamba2_l2 → LN → CfC.
  - Acceptance criteria + key implementation notes documented;
    bite-sized tasks elaborated when Phase 1+2A results land.

Phase 3 — Attention pool over Mamba2 K-positions (~4-6hr code,
sketch):
  - Replace CfC's zero-init initial state with an attention-
    pooled context vector over all K Mamba2 outputs. Design
    decision documented (Option A: attention sets initial state,
    preserving CfC's recurrent path).

Cross-phase deployment loop documented: fold-1 smoke → 3-fold
CV → per-fold comparison + isv-snapshot trajectory archive.

Honors `superpowers:writing-plans` skill: exact file paths,
complete code in every step, exact commands with expected output,
TDD-style steps, frequent commits, no placeholders in Phase 1
tasks. Self-review pass complete.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 21:18:49 +02:00
jgrusewski
ef35b10f3e refactor(ml-alpha): drop competitive-gate machinery — stacked is default
Per user direction "no gating, this is the new default": the stacked
Mamba2 -> CfC -> heads design is THE production architecture. There's
no competing-baseline comparison to run. Validation reduces to normal
training metrics (per-horizon val AUC, train loss curve, sanity floor
of >0.5 AUC).

Deletions:
  - crates/ml-alpha/src/gate/cfc_vs_mamba2.rs (gate verdict logic)
  - crates/ml-alpha/src/gate/mod.rs
  - crates/ml-alpha/examples/alpha_gate.rs (gate runner binary)

Renames:
  - crates/ml-alpha/src/gate/auc.rs -> crates/ml-alpha/src/eval/auc.rs
  - lib.rs: pub mod gate -> pub mod eval (gate implied comparison;
    eval doesn't)

Spec amendments:
  - Drop the "Gate baseline strategy" amendment (committed earlier
    this session)
  - Reframe the stacked-architecture amendment as a "decision" not a
    "gate"; production path is unambiguous
  - Reframe Section 4 "Validation gate: CfC must meet Mamba2" -> just
    "Validation: per-horizon val AUC" with the >0.5 sanity floor

Doc cleanups: stale "Mamba2 gate baseline" mentions in build.rs and
pinned_mem.rs replaced with neutral wording. The Argo template
comment about "downstream gate consumption" becomes "for monitoring".

Test status: all 26+ ml-alpha tests pass. AUC tests (6/6) still pass
under the eval:: namespace.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 23:17:33 +02:00
jgrusewski
6e868fd136 spec(ml-alpha): gate-baseline ablation strategy amendment
Defines the Mamba2-only baseline for the stacked-vs-baseline gate
verdict as an ablation of the SAME PerceptionTrainer (a --bypass-cfc
flag), not a separate model. Apples-to-apples; same data window,
same hyperparameters, same code path. The only difference is whether
the CfC step is in the loop.

Three ablation options evaluated:
  1. --bypass-cfc flag (recommended): Mamba2 -> heads directly
  2. --mamba2-state-dim 2 (crippled Mamba2, CfC stays)
  3. Frozen CfC initialized to identity (no code branch needed)

Option 1 wins on clarity: it answers "is CfC additive on top of
Mamba2" unambiguously, with the same Mamba2 capacity and same
training regime in both arms.

Concrete next-session work documented (1-2 hours):
  - PerceptionTrainerConfig.bypass_cfc: bool + step() branch
  - alpha_train --bypass-cfc CLI flag
  - alpha-perception-template.yaml workflow parameter + bash branch
  - submit both runs, fetch summaries, alpha_gate, commit verdict

gate_verdict logic unchanged — the cfc/mamba2 naming in the report
becomes stacked/bypass at the binding layer; the verdict math is
generic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 23:12:34 +02:00
jgrusewski
d4e46aba94 feat(ml-alpha): multi_horizon_heads kernel (128->5 sigmoid)
Per-horizon P(up) at h ∈ {30, 100, 300, 1000, 6000} snapshots forward.
Single-block 5-thread kernel; each thread is its own 128-dim dot
product + sigmoid. No atomicAdd.

Tests (5/5 pass on sm_86) assert invariants only:
  - sigmoid output ∈ [0, 1] for all heads
  - zero weights + zero bias → 0.5 exactly
  - bias = +20 → saturates near 1
  - bias = -20 → saturates near 0
  - per-head independence (mixed-bias configuration)

Addendum updated to explicitly state no-CPU-mirror discipline per
feedback_no_cpu_test_fallbacks.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:51:48 +02:00
jgrusewski
3389a59281 spec(ml-alpha): stacked Mamba2 -> CfC amendment
Mid-execution architecture revision: Mamba2 stays as a sequence
encoder; CfC becomes the layer on top (replacing the Phase 1d.3 MLP
stacker). Gate becomes 'stacked AUC >= Mamba2-only stacker AUC at
every horizon' — proves the CfC layer is additive, rather than CfC
alone beating Mamba2 alone.

Plan 1 kernels (cfc_step, heads, projection, BCE, AdamW, Graph A)
are unchanged. Only CfcTrunk's forward path gains a Mamba2 prefix
that consumes the snapshot stream and emits a 128-dim h_mamba which
CfC reads. The Mamba2 kernel (mamba2_alpha_kernel.cubin) is already
in the build.

Option B (parallel + fused dual-stream) is documented as the Plan 2
fallback if the stacked gate fails.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:42:57 +02:00
jgrusewski
d3b60b2ef3 build(ml-alpha): multi-cubin build.rs + placeholder kernels + local MappedF32Buffer
Cargo.toml: drops gbdt; adds memmap2 + approx; keeps ml-core only
(cannot depend on ml: would cycle since ml depends on ml-alpha for
the Mamba2 gate baseline).

build.rs: compiles 7 cubins (mamba2_alpha + 6 new placeholders)
with -O3 --use_fast_math --ftz --fmad. Skips kernels whose source
isn't present yet so partial check-ins work. Every env::var paired
with rerun-if-env-changed per the canonical build pearl.

src/pinned_mem.rs: local copy of MappedF32Buffer (mirrors
ml::cuda_pipeline::mapped_pinned::MappedF32Buffer). Drives the only
permitted CPU<->GPU path per feedback_no_htod_htoh_only_mapped_pinned.
Eventually the move-to-ml-core refactor will deduplicate; out of
scope for the Phase A branch.

Addendum: updates the import path to ml_alpha::pinned_mem.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:35:35 +02:00
jgrusewski
2deec0cf91 plan(ml-alpha): Phase A API addendum — cudarc 0.19 canonical patterns
Plan 1 was written against an older cudarc device-centric API. cudarc 0.19
moved alloc/launch ownership to the stream (partly for CUDA Graph capture
hygiene). This addendum pins:

- MlDevice -> CudaContext -> CudaStream construction
- Cubin load + module + function caching
- MappedF32Buffer staging -> DtoD-async -> CudaSlice (canonical CPU->GPU)
- Slow-path readback via DtoD into a staging MappedF32Buffer
- launch_builder(&func).arg(...).launch(cfg) idiom
- IsvBus and MappedPinnedSnapshotSlot/FillSlot using the real
  MappedF32Buffer API (host_slice_mut, read_all, dev_ptr field)
- CUDA Graph A capture via stream.begin_capture / end_capture / instantiate

Plan 1 kernel .cu source, CPU oracles, finite-diff thresholds, smoke
criteria, and gate logic are unchanged. Only Rust binding code uses
these patterns.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:31:53 +02:00
jgrusewski
056b4abe52 plan(ml-alpha): three-plan rollout for CfC+PPO greenfield
Plan 1 (Phase A, ~3000 lines): ml-alpha library scaffold, ISV bus,
mapped-pinned slots, CUDA build.rs, six perception kernels with
bit-equiv tests, AdamW + BCE, Graph A capture, Phase A trainer +
binary, CfC-vs-Mamba2 gate. Bite-sized 5-step TDD across 18 tasks.

Plan 2 (Phase B, ~780 lines): build_state, policy_forward (CfC
actor+critic), sample_action, replay buffer, multi-env rollout, GAE,
advantage_normalize, fused PPO loss, EWC, Graphs B+C, seven ISV
controllers, kill-switch, atomic weights swap, walk-forward CV across
6 folds. 19 tasks; tasks 2+ use compressed Step 2-5 TDD cycle pending
re-detail at the Plan 1 gate boundary.

Plan 3 (live, ~560 lines): IBKR adapter audit, AlphaPpoStrategy in
trading_agent_service, cold-start 4-state FSM, disconnect/failure
handling, observability, alpha-control IPC + fxt CLI, restart
semantics, paper trading harness (5 days), $1k live deploy with
manual ack gate, 5-day live window. 10 tasks.

Each plan has gate-pass criteria gating the next. On failure: post-
mortem + spec delta, no advance.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 20:48:14 +02:00
jgrusewski
90d14aaba5 spec(ml-alpha): GPU/CPU contract, CUDA Graphs, cold-start, disconnect handling
Critical-review pass on the CfC+PPO design adds:
- Public API: mapped-pinned ingress slots, single DtoH per decision
- Section 5.5: CUDA Graph capture topology (perception / policy / training),
  kernel inventory, cuBLAS Lt epilogue fusion, persistent ring layouts,
  determinism mode, build-time cubin compilation, perf budget
- Section 5.6: Databento/IBKR disconnect + failure response, never-do list
- Section 6 cold-start: 4-state bootstrap, Phase B walk-forward stats as
  pre-deployment kill-switch baseline, always-live ISV controllers

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 20:27:25 +02:00
jgrusewski
d4ea54d780 spec(ml-alpha): CfC + PPO greenfield design
Approved design document for the ml-alpha rebuild. Seven sections plus
appendices, all 7 sections + ISV-driven auto-tuning addition approved
via the brainstorming-skill flow.

Key architectural decisions:
- Full closed-loop scope: training + offline inference + live IBKR
- Three components: ml-alpha library, alpha_train binary, AlphaPpoStrategy
  in trading_agent_service (reuses existing data_acquisition,
  trading_service, broker_gateway, and the 1177-LOC IBKR adapter that
  already exists in trading_engine)
- Snapshot-level CfC perception trunk (Closed-form Continuous-time, the
  trainable LTC variant from Hasani 2022) — chosen over Mamba2 for
  native multi-time-scale via per-cell learnable τ; hard validation
  gate requires CfC AUC ≥ Mamba2 baseline before continuing
- 5 multi-horizon heads at {30, 100, 300, 1000, 6000} snapshots forward
- Decision-stride 50 snapshots (~1 min); empirically validated this
  session (per-bar→stride=200 flipped 3-fold mean Sharpe from -4.29 to
  +1.78 at quarter-tick cost)
- Action: target_position categorical ∈ {-10, ..., +10}; max_train=10
  fixed at architecture level, max_live ≤ 10 runtime-cappable
- Reward in price units (position-size invariant): dense per-segment
  PnL − C_trade·|Δcontracts| − C_vol·vol_excess; C_trade=0.034 fixed
  (IBKR $1.70 RT ÷ $50/point), C_vol=0 default
- Full online learning with EWC anchoring + 80/20 offline/live replay
  buffer + kill-switch on σ-band metric deviations (loss, mean reward,
  hit-rate, KL, entropy)
- All hyperparameters that vary during training are ISV-driven
  (controller outputs, not magic numbers) per
  pearl_controller_anchors_isv_driven.md
- Fully GPU-resident on hot path per feedback_cpu_is_read_only.md
- $35k starting capital; conservative max_live ramp 1→2→3 contracts
  with manual config bumps gated on realized track record
- Documented IBKR-specific quirks (PDT, mid-session margin spikes,
  rollover, halts, rate limits) with concrete design responses

Supersedes the abandoned 2026-05-16-alpha-ppo-trainer.md (DQN-port plan)
which inherited the wrong architectural shape.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 19:59:51 +02:00
jgrusewski
2fe76f2f34 docs(phase-e-4-a): execution status + T10 backward_from_h_enriched patch sketch
Two documentation deliverables produced while T14 backtest runs:

1. Plan update (specs/2026-05-15-phase-e-4-a-temporal-foundation.md):
   adds 'Execution Status' section reflecting actual T1-T14
   progression. T5 deferred (real MBP-10 peek), T9 skipped (GRN
   moved to E.4.B per integration notes), T10 partial (new C51
   grad-input kernel landed but Mamba2 backward wiring deferred),
   T14 in flight. Documents the 4 execution learnings:
   research-first saved a week of duplicate kernel work; cheap
   falsification experiments (Path 2, Path 3) avoided expensive
   investments; C51 borrow was the largest single Sharpe-lift in
   the session; GpuTensor/CudaSlice interop friction is the real
   integration cost.

2. T10 patch sketch (specs/2026-05-15-t10-mamba2-backward-from-h-enriched.md):
   ready-to-apply patch for ml-alpha::Mamba2Block adding a new
   public method backward_from_h_enriched(cache, d_h_enriched).
   Bypasses the W_out projection backward, accepts the
   [B, hidden_dim] gradient from C51's grad-input kernel directly,
   zero-initialises dw_out/db_out (AdamW step on zero grad is a
   no-op with correct moment decay — effectively freezes W_out
   params which is correct semantics since Phase E never uses
   them). Includes the smoke binary wiring snippet that consumes
   the new method via launch_alpha_c51_grad_input → Mamba2
   backward → AdamW step. Application gated on T14 backtest
   validation — if frozen Mamba2 already lifts Sharpe, T10
   becomes optimisation rather than prerequisite.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 22:08:31 +02:00
jgrusewski
eb9047fc30 docs(phase-e): E.4 temporal encoder design + E.4.A implementation plan
Design doc (specs/): TFT-style architecture for Phase E execution
policy — sliding window → Mamba2 SSM → GRN trunk → MoE regime gate
→ C51 head → Thompson selector. Two core pillars added per user:
  A) Full L1-L10 LOB depth input via hybrid MBP-10 peek
  B) ISV-continual-learning: controllers fire at training AND
     inference; Q-net weights frozen at inference but effective
     policy adapts via ISV modulation

Plan doc (plans/): 14-task implementation plan for E.4.A foundation
(window buffer + L1-L10 depth + Mamba2 forward+backward + ISV-eval
controllers). Falsification gates: smoke R_mean improvement ≥ 50%,
backtest cost=0 Sharpe ≥ +8 (no regression vs C51-flat +10.41),
half-tick Sharpe ≥ -8 (closes 5pt+ of 10pt gap to Phase 1d.4
baseline -4.0).

TGGN (foxhunt Temporal Graph Gated Network) explicitly deferred to
Phase E.5+: existing CPU graph implementation + GPU adapter at
ml-supervised/src/tgnn/ — marginal benefit for single-instrument ES
futures vs the TFT-Mamba2 stack; revisit for multi-instrument
extension or production HFT inference layer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 20:42:35 +02:00
jgrusewski
588a6d38af docs(phase-e-4-a): mamba2 + grn integration research — use ml-alpha Mamba2Block
Findings:
- Production Mamba2 (gpu_dqn_trainer) is coupled to SH2=256 trunk +
  ofi_embed + ISV[8] temporal routing — not portable to Phase E.
- ml-alpha::mamba2_block::Mamba2Block is from-scratch, fully
  configurable (in_dim/hidden_dim/state_dim/seq_len), GPU-pure with
  forward_train/backward/AdamW. Used in Phase 1d.2 to lift AUC 0.50
  to 0.66. ml-alpha is already a workspace dep of ml.
- GRN skipped for E.4.A — Mamba2 output goes straight to C51 head.
  Reintroduce GRN in E.4.B if Sharpe gates don't pass.
- Controller-at-inference: kernel has no training-mode branches;
  Wiener state preserved across episodes/cost cells for natural
  live-deployment simulation.

Revises Tasks 8-10 of the plan: use Mamba2Block API instead of
writing custom kernels. Only new CUDA needed: alpha_c51_grad_input
(C51 gradient w.r.t. input features, for Mamba2 backward chain).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 20:32:47 +02:00
jgrusewski
9c26e78cdc docs(phase-e): implementation plan for execution-layer RL policy
32 tasks across 5 milestones (E.0 foundation → E.4 shadow-mode), with
locked design decisions from three rounds of focused research memos:
- Q1 (fill sim): medium-tier Poisson regression from 5.2M trade tape
- Q2 (reward): terminal-only, n-step credit (consumes ISV slot 517)
- Q3 (alpha trust): implicit calibrated trust via state features
- Q4 (state window): current snapshot + 2 short-horizon scalars
- Q5 (sizing): hybrid decoupled fractional Kelly × Phase E attenuation

Trainer choice: DQN primary (Rainbow + Munchausen target), PPO control
on H=600 truncated only if kill criteria fire. Exploration: ε-greedy
with kill-criteria gate at end of week 2; NoisyNet escalation (4-6 days
due to dead scaffolding in our codebase) if criteria fail; RND beyond
that.

ISV consumption: 5 existing slots (n_step=517, γ=43-46, ε=41, Kelly=280,
reward_caps=452-453); new block 539..550 reserved for Phase E (10 in
active use, 2 spare). One new controller (stacker-threshold
engagement-rate-self-correction at slot 543).

Hardcoded by design: Kelly contract cap (Category-1 safety),
kill-criteria thresholds (circuit breakers). All other knobs are
ISV-driven per pearl_controller_anchors_isv_driven.

Decisive gates at week 1 (H=600 kill criteria), week 4 (composition
backtest Sharpe at half-tick > 0), and week 5 (shadow-vs-backtest
PnL within 30%).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 10:42:14 +02:00
jgrusewski
5d79bf0b22 docs(phase1d): implementation plan for regime-gated tick reasoning + memory accumulator
26 tasks across 5 milestones (1d.0 through 1d.4) with decisive falsification
gates at each. Anchors to commit db874b184 (Phase 1c validation) and references
real APIs: ml::trainers::mamba2, ml-alpha::training, backtesting::strategies.

Each task is bite-sized (TDD steps + commit). Decisive gates:
- 1d.0: best calibrated Brier ≤ 0.250
- 1d.1: Mamba AUC > 0.72 at K=100
- 1d.2: Mamba AUC > 0.55 at K=6000 (DECISIVE for two-head architecture)
- 1d.3: regime-gated conditional accuracy > 0.65
- 1d.4: out-of-sample Sharpe > 1.5

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-15 01:13:42 +02:00
jgrusewski
fb01906ddc docs(claude): foxhunt agents & skills rollout — phase 1 close-out
Phase 1 of the foxhunt specialized agents/skills rollout is complete: 14
commits, 5 auditor agents, 7 workflow/maintenance skills, 2 helper scripts,
warn-only PostToolUse hook router. All 8 acceptance criteria from the spec
verified. Hook latency 11-13 ms per call (target <200 ms). Memory-write
invariant held: only pearl-distiller and memory-curator are authorized
writers, no agent-driven memory edits during rollout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:19:28 +02:00
jgrusewski
bc3ebb5fb0 docs(claude): foxhunt agents & skills implementation plan — 14 tasks
14-task plan covering: foundation hook router (Task 1), 5 auditor agents
(Tasks 2-5, 13), 5 workflow skills (Tasks 6-10), 2 maintenance skills
(Tasks 11-12), end-to-end acceptance check (Task 14). Tasks 2-5, 6-8, 9-10,
11-12 fan out in parallel. Task 13 (sp-critical-reviewer) composes the four
domain auditors and is built last.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:19:28 +02:00
jgrusewski
9e6637c065 docs(claude): foxhunt-aware agents & skills design — phase 1 (12 items)
Pattern-cluster auditors + workflow-skill hybrid that internalize accumulated
project wisdom (15 feedback_*, 30+ pearl_*, 12+ project_* memory files; 30 SP
specs) into foxhunt-namespaced agents and skills under .claude/agents/foxhunt/
and .claude/skills/foxhunt/.

Phase 1: 5 auditor agents (isv-discipline, gpu-contract, reward-controller,
code-hygiene, sp-critical-reviewer) + 5 workflow skills (sp-spec-writer,
isv-slot-scaffolder, pearl-distiller, argo-deploy-helper, smoke-pilot) +
2 maintenance skills (memory-curator, stale-worktree-cleaner). Hook integration
is warn-only PostToolUse via a single thin router; agents read memory but only
pearl-distiller and memory-curator may write into memory/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:19:28 +02:00
jgrusewski
e1aef53373 docs(sp20): plan accuracy errata for Phase 2 (Tasks 2.0/2.1/2.2/2.3/2.4)
Append a "Plan Accuracy Errata" section to the SP19+20 plan
documenting the 6 deviations from the original Phase 2 plan that
emerged during implementation. Each entry captures the gap, the
decision made, and the rationale, so future implementers see what
was actually built vs what was specified.

Gaps documented:

  1. Task 2.0 (label-at-open infrastructure) was NEW — split out from
     Task 2.2 to land buffer + alloc + reset + write site atomically
     before Task 2.2's consumer ships. Sign convention mapping detail
     captured (kernel emits {0, 1, -1}, SP20 spec uses {-1, 0, +1}).

  2. Per-env alpha plumbing was not in Task 2.2 plan scope — built in
     Task 2.2 (NOT deferred to Phase 4) to preserve the
     `feedback_no_partial_refactor` contract atomicity. Touches 5
     files in one commit.

  3. Per-bar SP18 D-leg sites — KEEP for Phase 2 per `feedback_no_stubs`.
     Plan's wording "DELETE [these helpers]" was overbroad; only the
     trade-close-site call is deleted. The phantom
     `compute_sp12_reward_with_cost` doesn't exist as a function (the
     SP12 v3 reward is the inlined block).

  4. `sp20_compute_event_reward` placement — new dedicated
     `sp20_reward.cuh` header (NOT inside `experience_kernels.cu`,
     NOT inside `trade_physics.cuh`). Mirrors the
     compute_asymmetric_capped_pnl / compute_min_hold_penalty
     header-only pattern; needed for GPU oracle test wrapper to share
     the function bit-for-bit per `feedback_no_cpu_test_fallbacks`.

  5. Task 2.3 was subsumed by Task 2.2 — the existing Path C chain
     consumes the new `alpha` field automatically once `alpha_per_env`
     is wired; no separate `sp20_emas_compute` producer call needed.

  6. `min_hold_*` kernel-arg trio cleanup deferred to Task 2.4 — the 3
     kernel args were deleted in Task 2.2 (per `feedback_no_hiding`)
     but the upstream producer chain (`min_hold_temperature_update_kernel`,
     ISV[460], `read_min_hold_temperature_from_isv`, `config.min_hold_*`)
     deferred to Task 2.4 because it touches SP14 ISV slot registry +
     StateResetRegistry + ISV layout fingerprint bump.

Implementation-level details remain in `docs/dqn-wire-up-audit.md`
Task 2.0 / 2.1 / 2.2 entries; this errata is the plan-level
"what was actually built vs what was specified".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 00:30:33 +02:00
jgrusewski
235e838422 feat(sp20): Phase 1.4 (Path C) — kernel-arg refactor + aggregation kernel + wire-up
Atomic Phase 1.4 commit per `feedback_no_partial_refactor`. Wires the
SP20 fused-producer chain (Stats → Aggregate → EMAs → Controllers) into
GpuExperienceCollector's per-rollout-step path with one new aggregation
kernel + Phase 1.2 EMA kernel-signature refactor + production wire-up
+ tests + audit/spec/plan amendments, all in one commit.

## Path C decision rationale

The Phase 1.2 EMA kernel originally took 9 scalar value-args. The Phase
1.4 wire-up site (per-rollout-step in GpuExperienceCollector) needs to
feed per-env GPU-resident trade signals (trade_close_per_sample,
step_ret_per_sample, hold_at_exit_per_sample, packed factored
actions_out) into the kernel — forbidden via host sync
(`feedback_cpu_is_read_only`) and via memcpy_dtoh/htod
(`feedback_no_htod_htoh_only_mapped_pinned`). Path C refactors the EMA
kernel to take a device struct pointer (`SP20EmaInputs* ema_inputs`) +
adds an aggregation kernel that writes the struct on the GPU. Phase 1.2
had zero production consumers yet, so the sig change + Phase 1.4 wire-up
land atomically.

## What this commit contains

1. **EMA kernel signature refactor** (Phase 1.2 → Path C):
   `sp20_emas_compute_kernel.cu` swaps 9 scalar args for a single
   `const SP20EmaInputs* __restrict__ ema_inputs` device pointer.
   Math semantics bit-identical. Rust `EmaInputs` mirrored as
   `#[repr(C)]` byte-for-byte; new `pack_inputs_into_f32_view` helper
   for tests + collectors that fill the struct via a mapped-pinned
   f32-aliased buffer.

2. **New aggregation kernel** (`sp20_aggregate_inputs_kernel.cu`):
   Per-env arrays (sliced to current rollout step) + sp20_stats outputs
   (p50/std) + aux_dir_acc_reduce_kernel output [0] → SP20EmaInputs
   struct. Block tree-reduce (4 stripes × bdim × 4 bytes shmem); no
   atomicAdd. Aggregation rules per spec §4.5:
   - is_close = OR over envs
   - is_win = (≥ 0.5 of closed envs were wins)
   - trade_duration = round(mean(hold_at_exit) over closed envs)
   - action_is_hold = strict majority (count*2 > n_envs) HOLD
   - alpha = 0.0  (Phase 2 forward ref — reward kernel)
   - per_bar_hold_reward = 0.0  (Phase 3.2 forward ref — Hold-cost dual)
   - aux_logits_p50/std/dir_acc forwarded from upstream

3. **Production wire-up in GpuExperienceCollector**:
   4 kernel handles + 4 mapped-pinned buffers (struct fields, alloc,
   init); per-rollout-step launch sequence after env_step (step 5c):
   `Stats → Aggregate → EMAs → Controllers`. All on the same stream;
   stream-implicit producer→consumer ordering. Gated on
   `isv_signals_dev_ptr != 0 && trainer_params_ptr != 0` (matches the
   existing SP14-β EGF chain pattern).

4. **Fold-boundary reset**:
   3 new RegistryEntry records (sp20_ema_inputs_buf,
   sp20_emas_internal_buf, sp20_emas_obs_count_buf) + 13 new dispatch
   arms in training_loop.rs (10 SP20 ISV slot resets + 3 buffer resets).
   Closes the pre-existing `every_fold_and_soft_reset_entry_has_dispatch_arm`
   regression (was failing on fresh check after the SP20 ISV slot
   registrations landed in commit 4249ebc96).

5. **HEALTH_DIAG emit**:
   Per-epoch `HEALTH_DIAG[N]: sp20_isv [loss_cap=… alpha_ema=…
   wr_ema=… hold_cost_scale=… target_hold_pct=… hold_pct_ema=…
   hold_reward_ema=… n_step=… aux_conf_threshold=… aux_gate_temp=…]`
   right after the existing q_disagreement_diag emit.

6. **Tests** (5 test files, all green on RTX 3050 Ti sm_86):
   - sp20_emas_compute_test.rs (4 GPU oracle): updated to use the
     post-Path-C buffer-arg API (mapped-pinned f32-aliased struct).
   - sp20_aggregate_inputs_test.rs (NEW, 6 GPU oracle): aggregation
     rule coverage including the Phase 2 / Phase 3.2 placeholder
     contract.
   - sp20_phase1_4_wireup_test.rs (NEW, 2 GPU oracle): end-to-end
     4-kernel chain integration test.
   - sp20_stats_compute_test.rs (4 GPU oracle): unchanged, regression.
   - sp20_controllers_compute_test.rs (7 GPU oracle): unchanged,
     regression.
   - 18 lib unit tests across the SP20 launchers.

7. **Phase 2 / Phase 3.2 forward references**:
   The `alpha` (Phase 2) and `per_bar_hold_reward` (Phase 3.2) fields
   are emitted as 0.0 placeholders and documented at:
   - `sp20_aggregate_inputs_kernel.cu:46-52` (in-kernel docstring)
   - `sp20_aggregate_inputs.rs:46-49` (launcher docstring)
   - `dqn-wire-up-audit.md` "Phase 2 / Phase 3.2 forward references"
   These are NOT stubs — Phase 2 / 3.2 will replace the kernel's 0.0
   writes with real signals atomically with their respective producers.
   The original Task 2.3 (host-side aggregation) is **subsumed** by
   the GPU-side aggregation kernel.

## Hard rules

- `feedback_no_partial_refactor` — kernel sig change + aggregation
  kernel + production wire-up + tests + audit/spec/plan amendments
  in one atomic commit
- `feedback_no_atomicadd` — aggregation kernel uses block tree-reduce
- `feedback_no_cpu_compute_strict` — every aggregation lives on GPU
- `feedback_no_htod_htoh_only_mapped_pinned` — every Phase 1.4 buffer
  is mapped-pinned with `cuMemHostAlloc(DEVICEMAP)` reachable via
  `dev_ptr`; no memcpy_dtoh/htod
- `pearl_first_observation_bootstrap` — counter-based bootstrap
  preserved; placeholder writes (0.0) keep the ALPHA / HOLD_REWARD
  EMAs at 0.0 sentinel until Phase 2 / 3.2 wire real producers
- `pearl_no_host_branches_in_captured_graph` — every kernel is single-
  block; no host branches; safe to capture in the per-step CUDA Graph
- `pearl_tests_must_prove_not_lock_observations` — integration test
  asserts invariants (slots populate, bounds respected) rather than
  locked observed values

## Verification

- `cargo check -p ml --features cuda` clean
- 18 lib unit tests for SP20 launchers pass
- 23 GPU oracle tests across 5 test files pass on RTX 3050 Ti (sm_86)
- `every_fold_and_soft_reset_entry_has_dispatch_arm` regression test
  now passes (was failing pre-change)
- 14 baseline lib test failures unchanged (none introduced by this
  commit)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 20:49:07 +02:00
jgrusewski
4e21c38b85 fixup(sp20): Phase 1.1 K=3 → K=2 retarget (production aux head is K=2)
The Phase 1.1 sp20_stats_compute kernel (de922c6a4) assumed the SP14-C aux
head emits 3-class logits {short, hold, long} with baseline 1/3. This was
an error in the SP19+20 spec — production aux head emits K=2 logits
{down, up} per gpu_aux_heads.rs:61 (AUX_NEXT_BAR_K = 2, established by
SP13 B1.1a). Wiring K=2 production aux into the K=3 kernel = OOB reads +
corrupt stats.

Retargets the kernel + launcher + tests to K=2 atomically per
feedback_no_partial_refactor:

- Kernel: SP20_K_CLASSES 3→2; SP20_UNIFORM_K3 0.333…→SP20_UNIFORM_K2 0.5f;
  Pass A reads 2 logits (was 3); aux_conf range [0, 1/2] (was [0, 2/3]).
- Launcher: AUX_K_CLASSES 3→2; renamed unit test
  aux_k_classes_is_three → aux_k_classes_matches_production_aux_head.
- Tests: rewrote CPU oracle for K=2 input shape and 0.5 baseline; updated
  expected p50/std ranges; redesigned heterogeneous-distribution test to
  use ramped (not lockstep) clusters — K=2's saturated softmax in the hot
  half collapses every row to bin 255, triggering the
  pearl_sp4_histogram_warp_tile_undercount trap; ramped clusters distribute
  bin indices across each warp's 32 lanes so the histogram path matches
  the CPU oracle within bin_width tolerance.

Phase 1.2 (sp20_emas_compute) and Phase 1.3 (sp20_controllers_compute)
consume the scalar [p50, std] outputs and do NOT carry the K dimension.
Both regression suites verified passing unmodified:
- sp20_emas_compute_test: 4 GPU + 1 unit, all pass.
- sp20_controllers_compute_test: 7 GPU, all pass.

Verification (RTX 3050 Ti, sm_86):
- sp20_stats_compute_test: 4 GPU oracle + 4 launcher unit, all pass.
- cargo check -p ml --features cuda: clean (pre-existing warnings only).

Spec + plan amended at top with "AMENDED 2026-05-09" notes; audit doc
Phase 1.1 entry has a "K=2 fixup" subsection documenting the change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 19:46:17 +02:00
jgrusewski
99332003a4 plan(sp19+20): WR-first reward implementation plan
Implements the spec at docs/superpowers/specs/2026-05-09-sp19-20-wr-first-design.md
(commit 9d9ca3e6e). 38 top-level tasks across 8 phases:

- Pre-Phase: branch + worktree + 10 ISV slot reservations
- Phase 0: 7 behavioral test stubs (failing scaffold)
- Phase 1: 3 ISV producer kernels (stats, EMAs, controllers)
- Phase 2: Reward kernel + atomic SP18 D-leg / SP12 v3 replacement
- Phase 3: Hold opp-cost dual emission + replay buffer schema
- Phase 4: n-step credit distributor + SP18 B-leg trace reset fix
- Phase 5: Aux→Q confidence gate at Bellman target
- Phase 6: 7 behavioral tests pass — L40S deployment gate
- Phase 7: L40S smoke + 50e×3s×3f full validation + close-out

Plan follows TDD discipline (write failing test → run-fail → implement →
run-pass → commit) with bite-sized 2-5 minute steps. All file paths
exact, all kernel code complete, no placeholders.

Self-review confirmed: spec coverage complete, no placeholders, type
consistency across phases (Sp20EmasInputs, ISV slot constants, aux_conf
schema field).
2026-05-09 18:04:00 +02:00
jgrusewski
9d9ca3e6e7 spec(sp19+20): apply Q1(b) — Hold-reward EMA for Q-scale comparability
Q1 design decision (b): add explicit hold_reward_ema to center the per-bar
Hold reward, so Q(Hold) and Q(trade) targets are scale-comparable. The
marginal Q(trade) > Q(Hold) preference now comes from data variance in
each state (high-aux states pull Q(Hold) more negative), not from
structural scale asymmetry that depends on cost_scale magnitude.

Q2 decision: keep 4-quadrant fixed (no ramping partials). Already in spec.

Changes:
- §4.2 Hold opp-cost: dual emission documented — R_per_bar_centered
  (= R_per_bar - hold_reward_ema) for Q-target/replay tuple,
  R_per_bar uncentered for hold_baseline_buffer (Component 1 baseline)
- §4.5 Kernel 1: hold_reward_ema added (per-step on Hold-state bars only)
- §5 data flow: per-bar reward path shows the centered/uncentered split
- ISV slots: 9 → 10 (HOLD_REWARD_EMA_INDEX added)
- §8 footprint: Component 2 LoC 70 → 90 (+20 for dual emission)
- Total LoC estimate: 1620
2026-05-09 17:40:00 +02:00
jgrusewski
defbd0abe1 spec(sp19+20): patch 7 review issues
P1 (must-fix bugs/gaps):
1. ASYM_RATIO_INDEX → LOSS_CAP_INDEX with explicit formula in §4.1 and §4.5
   (was double source-of-truth — formula in §4.1, ISV slot orphaned)
2. Replay buffer schema change (per-bar aux_conf) added to §8 implementation
   footprint (~50 LoC additional, was invisible in original spec)
3. hold_baseline_buffer size specified = LOOKAHEAD_HORIZON_MAX = 30 bars (§4.2)
4. "4-tier gate" typo → "5-tier gate" in §7

P2 (clarifications):
5. alpha_ema centering documented as load-bearing for cold-start learning (§4.1)
   — not just for Q-target stability. EV is slightly negative at WR=46% with
   uninformed SP19 label; advantage-style centering rescues cold-start.
6. Q-scale asymmetry between Hold (uncentered) and trade (alpha_ema centered)
   documented as INTENTIONAL design choice (§4.2) — produces marginal
   Q(trade) > Q(Hold) preference that counteracts the Q(Hold) attractor.
   Behavioral test sp20_pure_noise validates the no-signal Hold default still works.

P3 (tightening):
7. Behavioral test thresholds tightened (§4.6):
   - sp20_pure_trend: WR > 70% → > 90%, PF > 2.0 → > 3.0
   - sp20_pure_noise: Hold% > 80% → > 95%, trades < 50 → < 20
2026-05-09 17:35:36 +02:00
jgrusewski
730337375f spec(sp19+20): WR-first reward + multi-horizon label utilization
Combines SP19 (multi-horizon labels, already landed) + SP20 (WR-first
reward) into one spec per pearl_no_deferrals_for_complementary_fixes.

Goal: WR ≥ 55%, textbook PF ≥ 2.0, walk-forward stable, per-regime stable.

Six components, atomic ship per feedback_no_partial_refactor:
1. Reward kernel (event-driven, 4-quadrant, asymmetric clamp ramped from
   wr_ema, multi-horizon directional ground-truth check)
2. Hold opportunity-cost (per-bar, dual emission for real reward + Hold
   baseline buffer)
3. n-step credit distributor (uniform over trade duration, fixes SP18
   B-leg self-bootstrap bug at gpu_experience_collector.rs:4154)
4. Aux→Q confidence gate (sigmoid threshold, mean_a Q baseline avoids
   Hold-everywhere punishment)
5. 3 fused producer kernels (sp20_emas, sp20_controllers, sp20_stats)
   driving 9 ISV slots in [510..520)
6. 7 behavioral tests on RTX 3050 Ti, gating L40S deployment

~1,550 LoC total. Spec includes data flow, error handling philosophy,
4-tier test gate, success criteria with explicit failure modes.

Cross-references:
- pearl_event_driven_reward_density_alignment (design principle)
- pearl_audit_unboundedness_for_implicit_asymmetry (asymmetric clamp)
- pearl_separate_aux_trunk_when_shared_starves (aux gate leverages SP14-C)
- project_metric_pipeline_inflation_audit (WR honest, Sharpe honest, goal grounded)
- project_goal_wr_55_pf_2 (the goal this spec implements)
2026-05-09 17:17:12 +02:00