Commit Graph

377 Commits

Author SHA1 Message Date
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
jgrusewski
662bf7eb36 plan(sp18 v2): Phase 0 Task 0.5 — pearl candidate draft
Drafts `pearl_diagnostic_decomposition_before_reward_intervention` per
the plan's Task 0.5 deliverable. Captures the discipline pattern
applied in Tasks 0.1–0.2:

  Before changing reward weights or Bellman target arithmetic to fight
  a Q-attractor, instrument a per-action decomposition of the existing
  reward components AND a trajectory observable on the Q-target
  distribution. The instrumentation is observability-only and lands
  atomically. One epoch of dispatch surfaces whether the suspected
  pathology is real BEFORE any production-path code changes.

Pearl is DRAFT — pending the Task 0.3 (reviewer L40S 1-epoch
dispatch) + Task 0.4 (KILL CRITERION evaluation) outcomes. Promotion
to user memory + cross-reference to MEMORY.md is gated on both legs
returning PROCEED.

Cross-references: pearl_canary_input_freshness_launch_order,
pearl_first_observation_bootstrap, pearl_wiener_alpha_floor_for_
nonstationary, feedback_no_partial_refactor, feedback_wire_everything_up.

No production code changes — single doc-only commit.

Plan: docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md
      § Phase 0 Task 0.5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 01:20:08 +02:00
jgrusewski
44e1f58b69 docs(sp18): copy spec + plan to feat/sp18-combined branch
Mirrors the SP17 PP.1 plan-copy pattern. Plan and spec source-of-truth
live on the sister `feat/sp17-dueling-q-network` worktree; this commit
copies them onto the SP18 branch so subsequent commits reference local
paths.

Spec: docs/superpowers/specs/2026-05-08-sp18-reward-shape-hold-attractor-design.md
Plan: docs/superpowers/plans/2026-05-08-sp18-reward-shape-hold-attractor.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 00:25:06 +02:00
jgrusewski
509035dea6 docs(sp17): copy plan file to feat/sp17-dueling branch
Plan was authored on sister worktree (sp15-phase1-honest-numbers) by
the SP17 planner agent; copying it to feat/sp17-dueling so future task
references in commit messages and audit-doc entries resolve from this
branch.

No content change vs sister-worktree copy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 20:57:28 +02:00
jgrusewski
641aa0dfde fix(sp16-t3): Wiener-optimal adaptive α per pearl — hold_cost_scale + min_hold_temperature
Per train-multi-seed-hjzss validation: SP16 T1+T2 chain was structurally
landed but BEHAVIORALLY INERT in 5-epoch smoke (bit-identical to pfh9n
baseline through epoch 3). Root cause: hardcoded `alpha = 0.05f` in both
producer kernels violates feedback_isv_for_adaptive_bounds AND prevents
convergence in short runs (~60 epochs needed from cold start).

Fix per pearl_wiener_optimal_adaptive_alpha:
  α = diff_var / (diff_var + sample_var + ε)

Where sample_var = running variance of target signal (Welford accumulator)
and diff_var = running variance of consecutive one-step differences.

Cold-start: target jumps 1.0 → 6.4 → 7.0 → high diff_var → α ≈ 0.6+
            → near-bootstrap responsiveness in epochs 1-3
Steady-state: signal stabilizes → diff_var drops → α decays naturally
              → smoothing emerges without hardcoded constant

Adds 12 new ISV slots (6 per producer):
- HCS_TARGET_MEAN/M2, HCS_DIFF_MEAN/M2, HCS_PREV_TARGET, HCS_SAMPLE_COUNT
- MHT_TARGET_MEAN/M2, MHT_DIFF_MEAN/M2, MHT_PREV_TARGET, MHT_SAMPLE_COUNT

ISV_TOTAL_DIM 462 → 474.

Both kernels migrated atomically. Pearl-A bootstrap preserved (sentinel
on prev_blended triggers REPLACE; cold-start α=1.0 when N<3 samples).
Defensive bounds [WELFORD_ALPHA_MIN=0.01, WELFORD_ALPHA_MAX=0.95] on the
Wiener-derived α to guard against denormal/underflow corner cases.

HEALTH_DIAG[N] emit extended with `alpha=...` and `sample_count=...` for
direct trajectory observation in validation smoke.

Behavioral tests verify:
- α high during signal jumps (>0.3 at epoch 3 post-cold-start)
- α low in steady state (mean tail α<0.4 under converging signal)
- Pearl-A bootstrap fires on first observation (Welford state advances
  regardless of REPLACE branch)
- α stays within [WELFORD_ALPHA_MIN, WELFORD_ALPHA_MAX] over 50 epochs
  (post-cold-start; cold-start α=1.0 by design)
- No 0.05f hardcoded literal remains in blend math (regression-locked
  via host-only string scan)

5 GPU + host tests pass: sp16_phase3_alpha_high_during_signal_jump,
alpha_low_in_steady_state, pearl_a_bootstrap_first_obs,
alpha_naturally_bounded, no_hardcoded_alpha. sp14 + sp15 oracle suites
unchanged (34 GPU tests + 4 host tests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:56:58 +02:00
jgrusewski
0426ce8887 fix(sp16-p1): MIN_HOLD_TEMPERATURE signal swap to hold-rate overrun + slot 330 non-bug closure
Per train-multi-seed-pfh9n post-mortem follow-up: slot 460 stuck at 50
in Fold 1 was NOT a launch-lifecycle bug. Producer fires per-epoch but
kernel had early-return guard on AUX_DIR_ACC_SHORT_EMA (slot 373) at
sentinel 0.5. Slot 373 reset on fold boundary; aux dir-acc EMA either
didn't fire or settled within ε of 0.5 → kernel kept early-returning.

Fix: drop slot 373 dependency entirely. Drive temperature from observed
hold-rate vs target overrun:

  overrun = max(0, observed_hold_rate - target_hold_rate)
  overrun_norm = clamp(overrun / max(target, 0.01), 0, 1)
  new_temp = TEMP_MIN + (TEMP_MAX - TEMP_MIN) × overrun_norm
  blended_temp = Welford EMA α=0.05 with Pearl-A bootstrap

When over-holding: temp HIGH → exit ramp permissive (matches design intent).
When at/under target: temp LOW → exit penalty strict.

Survives fold reset: hold-rate measurement starts fresh with real data
immediately, no chained-input-sentinel masking.

Slot 330 (KELLY_WARMUP_FLOOR) investigated and confirmed NON-BUG: producer
behaves correctly per pearl_kelly_cap_signal_driven_floors cross-fold-
persistence. floor=0 post-warmup is correct steady state.

Behavioral tests:
- sp16_phase1_min_hold_temp_climbs_with_hold_overrun
- sp16_phase1_min_hold_temp_strict_when_at_target
- sp16_phase1_min_hold_temp_strict_when_under_target
- sp16_phase1_min_hold_temp_no_longer_reads_slot_373

Instrumentation: HEALTH_DIAG[N]: min_hold_temp_diag obs/target/overrun/temp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:24:12 +02:00
jgrusewski
b26b189925 feat(sp14-c.5b): atomic contract migration — h_s2 → h_s2_aux + revert zero-fills
Atomic flip of the aux heads' input from Q's GRN trunk output `save_h_s2`
to the SEPARATE aux trunk's output `h_s2_aux`. The aux trunk now trains
its own w1/w2/w3/b1/b2/b3 from CE loss (next-bar + regime); Q's encoder
is structurally protected by `aux_trunk_backward`'s missing `dx_in`
output param (encoder boundary stop-grad enforced at the kernel-set
level).

Reverts the C.0 stop-grad band-aid commits (`872bd7392`, `411a30473`):
the zero-fills in `aux_next_bar_backward` + `aux_regime_backward` Step 3
are replaced with the genuine SAXPY-back-to-input gradient
(`dh_s2_aux[b,j] = sum_k sh_dh_pre[k] * w1[k,j]`). The leak that
motivated stop-grad is now blocked structurally rather than by data
zero-fill — aux gradient flows through the aux trunk's own params, never
into Q's encoder.

Wired in this commit (atomic, ~330 LOC):
- 4 kernel signatures renamed `h_s2 → h_s2_aux` / `dh_s2_out → dh_s2_aux_out`
  (`aux_next_bar_forward`, `aux_regime_forward`, `aux_next_bar_backward`,
  `aux_regime_backward`); Rust wrappers in `gpu_aux_heads.rs` follow
- Trainer fwd: insert `aux_trunk_forward_ops.launch(...)` in
  `aux_heads_forward` Step 0, populating `h_s2_aux` from `save_h_s1`
  (encoder layer-1 output, dim=shared_h1=256). Both head fwds redirect
  input pointer from `save_h_s2` to `h_s2_aux`
- Trainer bwd: SAXPY both `aux_dh_s2_*_buf` into `dh_s2_aux_accum`
  (pre-zeroed each step via graph-safe `cuMemsetD32Async`); then
  `aux_trunk_backward_ops.launch(...)` propagates through w3/w2/w1 +
  b3/b2/b1; then `launch_aux_trunk_adam_update` applies global L2-norm
  clip + per-tensor Adam updates over 6 grad tensors
- Collector fwd: insert `exp_aux_trunk_forward_ops.launch(...)` after
  `forward_online_f32`, reading `exp_h_s1_f32` and writing `exp_h_s2_aux`;
  redirect `exp_aux_heads_fwd.forward_next_bar` input from
  `exp_h_s2_f32` to `exp_h_s2_aux`
- Pre-capture host-write of ISV-driven LR + grad-clip + step counter
  into mapped-pinned buffers in `launch_cublas_backward_to` (BEFORE
  `aux_heads_backward`); same `&mut self` pattern as `step_ofi_embed_adam`

Verification:
- `cargo check -p ml --tests` clean (1m02s, only pre-existing warnings)
- `aux_trunk_oracle_tests` + `sp14_oracle_tests` 12/12 pass:
  - aux_trunk gradient check: max_rel_err=1.33e-2 (tol=2e-2) — matches C.4 baseline
  - aux_trunk_backward_does_not_write_dx: kernel source clean of dx_in/dx_in_out
  - aux_sign_label_lookahead_mask: 60/100 masked, 40/100 valid
  - 9 other oracle tests pass bit-identically

Plan: docs/superpowers/plans/2026-05-07-sp14-layer-c-separate-aux-trunk.md §C.5b
Audit: docs/dqn-wire-up-audit.md "SP14 Layer C Phase C.5b" section
2026-05-08 03:01:13 +02:00
jgrusewski
c90de98594 feat(sp14-c.5a): allocate aux trunk fwd/bwd buffers + Adam launcher (dead code)
Phase C.5a — additive infrastructure for the aux trunk wire-up.
Allocates saved-fwd buffers (h_s2_aux, h_aux1, h_aux2),
gradient buffers (6× aux_trunk_*_grad), accumulator
(dh_s2_aux_accum), and dedicated Adam launcher
(launch_aux_trunk_adam_update) reading β1/β2/ε/LR/grad-clip from
ISV[444..449).

No contract change. No call sites for the new launcher yet.
C.5b atomically wires these in.

Phase C.5 was split (authorized 2026-05-08) after the original
implementer flagged ~600-800 LOC scope across 4 files with
correctness windows. C.5a is purely additive; C.5b is the genuine
~300 LOC atomic migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 02:10:17 +02:00
jgrusewski
3b71d21834 feat(sp14-c): aux prediction horizon ISV-driven (multi-bar pivot)
Aux's original label was (p_{t+1} > p_t) — pure HFT-scale microstructure
noise that's unlearnable at our HFT-MFT trading frequency. Migrated to
(p_{t+H} > p_t) where H is read from ISV[AUX_PRED_HORIZON_BARS_INDEX=450].

Adaptive producer drives H from observed avg winning hold time:
- Pearl-A first-observation bootstrap: replace sentinel H=60 directly
  on first valid observation
- Steady-state Wiener-α EMA blend, slow (α=0.01) for stable horizon
  (no target-variance EMA available, fallback per
  pearl_wiener_optimal_adaptive_alpha)
- "No winning trades yet" guard keeps sentinel until first valid observation

Lookahead truncation: labels at t where t+H >= total_bars are masked
(sentinel -1, loss-reduce skips). The existing aux_next_bar_loss_reduce
in aux_heads_kernel.cu already supports the -1 mask convention via the
B_valid count — no new valid_mask parameter needed.

Step 5b finding: Case B — existing per-sample buffers
(hold_at_exit_per_sample, trade_profitable_per_sample) populated by
unified_env_step_core, but no aggregate ISV slot. Added new aggregator
slot AVG_WIN_HOLD_TIME_BARS_INDEX=451 + new producer kernel
avg_win_hold_time_update_kernel.cu (block-tree-reduce, no atomicAdd).
ISV_TOTAL_DIM bumped 450 → 452.

ATOMIC migration per feedback_no_partial_refactor: both label kernels
(aux_sign_label_kernel.cu trajectory + aux_sign_label_per_step_kernel.cu
per-rollout-step) migrated together to the new
(targets, bar_indices, isv, isv_h_idx, out_labels, total, total_bars)
signature. The lookahead host-passed scalar argument is removed; H is
read from ISV inside the kernel (broadcast value, single read per
thread, on-device clamp [1, 240]).

Producer chain (per-epoch boundary): new
GpuDqnTrainer::launch_aux_horizon_chain orchestrates
avg_win_hold_time_update → aux_horizon_update sequentially alongside
launch_kelly_cap_update at the existing epoch-boundary slot in
training_loop.rs.

Trunk math (C.2/C.3/C.4) unchanged — separate aux trunk is label-
agnostic. Validation in C.10 will use H=60 cold-start; the adaptive
producer drives H from real winning-trade observations.

Tests (8 oracle, 5 new + 3 preserved):
- aux_trunk_forward_matches_numpy_reference (C.3) ✓
- aux_trunk_backward_gradient_check (C.4) ✓
- aux_trunk_backward_does_not_write_dx (C.4) ✓
- aux_sign_label_h_bar_horizon (NEW) ✓
- aux_sign_label_lookahead_mask (NEW) ✓
- aux_horizon_pearl_a_bootstrap (NEW) ✓
- aux_horizon_converges_to_steady_target (NEW) ✓
- aux_horizon_holds_sentinel_with_no_winning_trades (NEW) ✓

8/8 pass on RTX 3050 Ti.

Phase C.4b of SP14 Layer C separate-aux-trunk refactor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 01:37:39 +02:00
jgrusewski
35935ae441 plan(sp15): fix 3 critical compile-breakers from third review
Targeted fixes per user direction (option 3 of "fix critical only,
accept rest as execution-time gaps"):

1. build.rs cubin manifest is 1:1 source-to-cubin (verified: list of
   .cu filenames, NOT (source, name) tuples). Fixed Phase 3.1 Step 5
   to use single manifest entry; both kernels load from SAME module
   via get_function() with their symbolic names.

2. egf_anchor_p1 helper in sp4_histogram_p99.cuh: replaced the
   `return 0.0f` stub with the full ~80-line body. Pass 1 + Pass 2
   byte-identical to sp4_histogram_p99 (mirrored verbatim from the
   existing sibling). Pass 3 walks cumulative-from-bottom for p1
   instead of cumulative-from-top for p99. Returns lower-edge of the
   first bin reaching 1% threshold.

3. Added Task 4.2.5: `fxt evaluate` subcommand (PREREQUISITE for 4.3).
   Verified that bin/fxt/src/main.rs Commands enum has no Evaluate
   variant. Without this task, eval-final-template.yaml fails at
   runtime. Full subcommand shown: bin/fxt/src/evaluate.rs with 5
   flags (--checkpoint-dir, --quarter, --seeds, --output-dir,
   --report-card-md), report card markdown emitter per spec §10.5.

5 IMPORTANT and 2 NIT issues from review remain documented as
execution-time friction; subagent-driven-development's spec-compliance
reviewer between tasks is expected to catch them per-task.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 10:32:10 +02:00
jgrusewski
eb5e19d670 plan(sp15): rewrite v2 — fix all 16 reviewer-flagged issues
Rewrite of 2026-05-06-sp15-trader-discipline-and-recovery.md from v1
(commit 0178a53ab) which had 16 reviewer-flagged issues including
5 critical compile-breakers and 8 important plan-failure violations.

CRITICAL fixes:
- Real GATE1_OPEN_STATE_INDEX (slot 391) — was wrong GATE1_STATE_INDEX
- Real PS_PEAK_EQUITY/PS_PREV_EQUITY (state_layout.cuh slots 7+9) —
   no invented CUMULATIVE_EQUITY_INDEX
- Real sp4_histogram_p99<BLOCK_SIZE> block-tree-reduce pattern, no
   atomicAdd_block (was feedback_no_atomicadd violation)
- Real evaluate_dqn_graphed pattern (gpu_backtest_evaluator.rs:1143) —
   no nonexistent evaluate_on_val_slice
- Real services/ml_training_service/src/main.rs path — was wrong

IMPORTANT fixes:
- Fork from current main 0178a53ab, not stale 5417e2756
- Phase 0.B has explicit case-(a)/case-(b) branches driven by 0.A
   diagnostic conclusion
- Phase 2B uses TEMPLATE + 17-row differential table — every test fully
   specified, no compressed bullets
- Phase 3 each teaching gets full TDD: write test → run-fail → kernel
   (full code) → launcher → consumer → run-pass → commit (5+ steps)
- Phase 3.5 each mechanism same TDD pattern with full kernel code
- Plasticity 3.5.4 specifies TWO-STEP recovery (Flat first, then
   cooldown) + Kaiming-He init (not Xavier — architecturally appropriate)
- Phase 4.3 includes FULL eval-final-template.yaml (not 4 bullets)
- 4 EGF constants replaced (not 3 — verified all four in
   alpha_grad_compute_kernel.cu lines 142,143,144,147)
- Behavioral_suite test target ordering fixed (Cargo.toml entry lands
   before tests run against it)

Stats: 4947 lines, ~270 [- [ ]] step checkboxes, 0 todo!() in test
bodies, every kernel shown in compilable form.

Self-review section maps every spec section to implementing task,
verifies all cross-references against verified codebase facts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 09:58:30 +02:00
jgrusewski
0178a53ab0 plan(sp15): trader discipline and recovery implementation plan
Implementation plan for SP15 spec at docs/superpowers/specs/2026-05-06-trader-
discipline-and-recovery-design.md (commit 5417e2756).

Six phases ~4900 LOC, Approach B parallel-where-independent (~10-15 days realistic):
- P.1 Branch + sub-worktrees scaffolding
- 0.0 sp15_isv_slots.rs lands FIRST on sp15 (slots 397-442, ISV_TOTAL_DIM 396→443)
- Phase 0 (3 sub-tasks): EGF diagnostic + ISV-driven retune + anchor test 2.21
- Phase 1 (7 sub-tasks): unified sharpe, cost-net (commission+spread+OFI), DD,
   8 baselines fused trunk, dd_pct trunk concat (LAYOUT BREAK), CLI flags,
   test slice consumption
- Phase 2 (2A scaffold + 2B 17 tests + 2C 5 tests paired with 3.5)
- Phase 3 (5 teachings sequential): r_quality/r_discipline split, explicit cost,
   quadratic DD, regret signal, confidence-aware Hold floor (sigmoid)
- Phase 3.5 (4 mechanisms): asymmetric DD reward, cooldown gate, plasticity
   injection (TWO-STEP: Flat + cooldown, Kaiming-He init), recovery PER curriculum
- Phase 4 (4 sub-tasks): pre-flight, L40S Q1-Q7+Q8 walk-forward, sealed Q9 eval-
   only workflow, production-track gate

Each task: TDD-discipline (write failing test → run-fail → implement → run-pass
→ commit). Per-commit discipline rule: Phase 2 behavioral test + wire-up audit
+ pearl candidate. Sub-worktree merge model: each phase merges back to sp15
atomically; sp15 merges to main only after Phase 4 production-track gate passes.

Self-review: spec coverage table maps every section to its implementing task.
Some derivative tasks (3.2-3.5) summarized as templated bullets per writing-
plans pattern for skilled-implementer derivative work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 09:11:35 +02:00
jgrusewski
5417e27567 docs(sp15): amend spec v2 — 10 fixes from second critical review
Second critical review pass found 10 more issues, 3 critical.
All addressed:

CRITICAL:
- §8.2 (3.1): ALPHA_SPLIT cold-start was unspecified — formula
   produces 0/0=0, not the claimed 0.5 sentinel. Now: ISV slot
   initialized DIRECTLY to 0.5 in trainer constructor; formula
   takes over only after both grad-norm EMAs accumulate N_warm
   non-zero observations
- §9.2 (3.5.4): plasticity now performs TWO-STEP recovery:
   (1) Flat all positions at fire bar (close current losing trade),
   (2) engage warmup cooldown forcing Hold for M_warm bars.
   Without step 1, forced Hold preserved the losing position
   that drove drawdown for the entire 200-bar warmup
- §12.2: stale "5-10%" baseline cost estimate updated to "15-25%"
   matching §6.4 (was contradicting earlier amendment)

IMPORTANT:
- §9.2 (3.5.5): DD_TRAJECTORY_DECREASING threshold 0.02 hardcoded
   → ISV-driven via new slot DD_TRAJECTORY_FLOOR (slot 441,
   25th percentile of running dd_pct distribution)
- §8.2 (3.5): HOLD_FLOOR_ALPHA tracked from rolling 95th percentile
   of |Q_dir| (NOT running max — was outlier-ratchet vulnerable)
- §9.2 (3.5.3): MEDIAN_STREAK_LENGTH formerly undefined in cooldown
   K formula → ISV-driven via new slot 442, running median of
   observed loss-streak lengths via two-heap algorithm
- §9.2 (3.5.2): asymmetric reward × α split compound interaction
   explicitly stated as intentional with POS_CAP as binding ceiling

NIT:
- §7.4: "2C: Group 3 (4 tests)" → "(5 tests)" (was off-by-one
   after 2.22 added)
- §9.2 (3.5.4): Xavier → Kaiming-He init for advantage head reset
   (architecturally appropriate for ReLU-gated activation chain)

ISV_TOTAL_DIM: 441 → 443 post-SP15 (added DD_TRAJECTORY_FLOOR
and MEDIAN_STREAK_LENGTH at slots [441..443)). 46 SP15 slots
total. File: 799 → 811 lines.

Spec is now consistent end-to-end with no contradictions between
sections, no hardcoded values violating feedback_isv_for_adaptive_
bounds, and no underspecified load-bearing parameters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 08:58:28 +02:00
jgrusewski
f3cb0c78c2 docs(sp15): amend spec — 14 fixes from critical review
Critical review (combined fresh-eyes subagent + self-critique) flagged
14 issues. All addressed in this amendment.

CRITICAL (blocks implementation):
- §4.3 NEW: ISV slot allocation map [397..441) per phase, prevents
   parallel-dispatch ISV-table conflict (was: undefined, would break
   Approach B)
- §4.4 NEW: Phase 2A ↔ Phase 1.2 ABI contract (LobBar struct as
   canonical contract, Phase 2A defines first; Phase 1.2 conforms).
   Restores parallelism dependency
- §9.2 (3.5.4): plasticity injection now MANDATES cooldown engagement
   via PLASTICITY_WARM_BARS_REMAINING slot 438. NEW anchor test 2.22
   plasticity_cooldown_interlock prevents random-tail-output retrigger
   loop
- §9.2 (3.5.5): recovery curriculum replaced episode-level metadata
   (didn't exist in transition-level PER) with per-step DD_TRAJECTORY_
   DECREASING signal — same goal, no PER restructure

IMPORTANT (rework prevention):
- §9.2 (3.5.3): cooldown K threshold from running mean of per-trade
   PnL (NOT variance — variance is LOW during streaks, would delay
   cooldown when needed)
- §8.2 (3.5): Hold floor function form specified as bounded sigmoid
   with α/k/ε₀ ISV-driven; was "monotonic_inv_func" (undefined family)
- §6.2: cost kernel per-side semantics explicit. Half-spread × side_
   indicator at entry AND exit; commission_per_rt on close. Resolves
   round-trip vs per-side ambiguity
- §6.2: OFI impact λ initial value 2e-4 + ISV refit methodology;
   was "empirical fit from MES historical" (hand-wavy)
- §6.4: 8 baselines now mandate shared trunk forward; honest 15-25%
   overhead estimate (was 5-10%, optimistic)
- §12.3: Q9 burn policy explicitly honor-system, not enforcement.
   Mitigations described as deterrents not enforcement
- §10.6: Phase 4.5 thresholds CLI-config-driven with rationale,
   anchored empirically post-Phase-1 (was hardcoded > 1.0)

NIT:
- §9.2 (3.5.2): multiplier vs SP12 cap interaction explicit (applied
   BEFORE cap)
- §8.2 (3.1): α=0.7 hardcoded → ISV-driven from grad ratio (was
   feedback_isv_for_adaptive_bounds violation)
- §13: pearls reframed as candidates pending validation per discipline
   rule; pre-naming pressure removed

Test count: 21 → 22 (added 2.22). Phase 2 LOC: 2000 → 2100.
ISV_TOTAL_DIM: 396 → 441 post-SP15.

All 14 issues addressed in spec text. Ready for user review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 08:51:35 +02:00
jgrusewski
fb5f2394d0 docs(sp15): trader discipline and recovery design spec
Design spec for SP15 — addresses the train-dd4xl downward spiral
post-mortem (8 epochs, trades 131k→64k, sharpe 79→44 with monotone
descent across active_frac, dir_entropy) and the walk-forward audit
finding (test_start..test_end slice generated but never consumed,
val IS the selection set, no sealed test).

Six phases over ~13-21 days:
- Phase 0: SP14 EGF ISV-driven retune (gate1=closed forever fix)
- Phase 1: honest numbers — unified sharpe kernel, cost-net (commission
   + spread + OFI-impact, dev/prod parity), drawdown reporting,
   8 counterfactual baselines, dd_pct as foundational state input,
   --holdout-quarters/--dev-quarters CLI, consume abandoned test slice
- Phase 2: 21 behavioral tests on dev RTX 3050 Ti, pre-commit hook
   gates argo-train.sh
- Phase 3: 5 trader teachings (r_quality/r_discipline split, explicit
   cost, quadratic DD, regret, confidence-aware Hold floor)
- Phase 3.5: 4 recovery mechanisms (asymmetric reward under DD,
   cooldown gate, plasticity injection, recovery curriculum in PER)
- Phase 4: L40S walk-forward Q1-Q7, Q8 final dev, sealed Q9 OOS

Cross-cutting discipline rule: no new pearl/controller/kernel/ISV
slot/reward term ships without a Phase 2 behavioral test that proves
the intended trader behavior. Hard rule, no exceptions.

Decisions captured from 7 clarifying questions answered 2026-05-06.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 08:32:37 +02:00
jgrusewski
037c24116d plan(sp14): implementation plan for spec v3
Two-sub-project plan:
- Layer A (4 tasks, ~50 LOC): C51 atom-floor, set_aux_weight clamp lift,
  stagnation warmup gate, smoke validation
- Layer B (15 tasks, ~1180 LOC): 13 ISV slots, 4 kernels (q_disagreement,
  alpha_grad, gradient_hack_detect, dir_concat_qaux), forward wire,
  backward gradient gating, orchestrator wire-up, HEALTH_DIAG, tests, smoke

Each task has bite-sized TDD steps (write failing test, run fail,
implement, run pass, commit) per the writing-plans skill conventions.
Phase 0 verification tasks (A.0, B.0) anchor against current code at
HEAD 40e737a18+ before edits.

19 total tasks across 2 layers. Each layer commits independently as
an atomic feature; intermediate per-task commits during Layer B keep
the wire safety-protected (forward concat lands before backward gating
in B.9 → B.10 sequence).

8 explicit kill criteria for Smoke A2-B per spec B.7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 17:36:56 +02:00
jgrusewski
40e737a181 docs(sp14): spec v3 — K=4 direction + ISV-adaptive β rate limiter
Two further user-flagged corrections from second-critical review:

1. Direction Q-head emits K=4 actions, NOT K=3.
   Authoritative source: state_layout.cuh:123-126
     #define DIR_SHORT 0   // open/maintain short
     #define DIR_HOLD  1   // keep current position (no-op)
     #define DIR_LONG  2   // open/maintain long
     #define DIR_FLAT  3   // close all to zero
   The "default: 3 — Short/Flat/Long" comment at gpu_dqn_trainer.rs:2438
   is stale pre-SP13. Production callsites all set branch_0_size: 4.
   SP13 added DIR_HOLD as a separate fourth direction action (Hold-pricing).
   The config default comment was never updated when DIR_HOLD landed.
   This is exactly the feedback_trust_code_not_docs failure mode — a
   single stale comment would have silently corrupted the q_disagreement
   signal (Hold/Flat being indices 1/3 instead of just Flat=1).

   Updates:
   - B.1 action-space context: 4 actions with Hold AND Flat both
     non-committal (Hold = keep position, Flat = exit to zero)
   - B.2.3 q_disagreement mapping: K=4↔K=2 with both Hold and Flat
     masked from disagreement signal (no new directional commitment
     to evaluate); only Short and Long picks contribute to disagreement
   - Edge case handling for all-Hold/all-Flat batches

2. Adaptive β rate limiter (was structural β=0.9).
   Per feedback_isv_for_adaptive_bounds, β should be signal-driven
   not hardcoded. v3 derives β from variance of α_grad_raw, mirroring
   the k_aux/k_q variance-driven steepness pattern in B.2.5.

   Formula:
     β = clip(β_base + variance_alpha_raw / variance_ref_alpha,
             [β_base, β_max])
     β_base = 0.5 (light smoothing baseline; ~2-step half-life)
     β_max  = 0.95 (heavy smoothing; ~20-step half-life)

   Stable α_grad_raw → β = β_base (preserves directional intent)
   Volatile α_grad_raw → β → β_max (dampens jitter)

   Adds 2 ISV slots:
     ALPHA_GRAD_RAW_VARIANCE_EMA_INDEX (Welford variance)
     BETA_RATE_LIMITER_ADAPTIVE_INDEX (current β value)

ISV slot count: 11 → 13 (net +2 for variance + adaptive β).
LOC estimate: ~1150 → ~1180 (negligible delta; 3 Welford
variances now in alpha_grad_compute_kernel instead of 2).

HEALTH_DIAG pearl_egf_diag emit updated to expose all three
adaptive scalars (α, β, k_aux/k_q) plus all three driving
variances (var_alpha, var_aux, var_q) for full observability.

Verified against current code at HEAD d243a6f08:
  - state_layout.cuh:123-126 (DIR_* enum truth source)
  - gpu_dqn_trainer.rs:2438 (stale K=3 comment confirmed)
  - branch_0_size: 4 in 5 production callsites
    (smoke_tests, gpu_iqn_head, gpu_backtest_evaluator)
  - DIR_HOLD usage in experience_kernels.cu:1298 + 14 other sites

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 17:21:17 +02:00
jgrusewski
d243a6f080 docs(sp14): spec v2 — critical review corrections
8 corrections from code-anchored critical review at HEAD eaf4adcb9:

1. Direction Q-head emits K=3 (Short/Flat/Long), not K=4. Aux head
   emits K=2 (down/up). Gate 2 q_disagreement now uses K=3↔K=2 mapping
   with Flat masking. Verified against gpu_dqn_trainer.rs:2438.

2. Forward launch order constraint added: aux forward must complete
   before direction Q-head forward (new serial dep). Cited
   pearl_canary_input_freshness_launch_order.

3. Adaptive sigmoid k formula fixed: v1 had unreachable k_max=50
   because formula caps k ≤ k_base. v2 uses max(..., k_min) with
   k_max = k_base implicit.

4. α_grad rate limiter promoted from nice-to-have to v1. Schmitt
   state-flip introduces sigmoid discontinuity. β=0.9 EMA smoothing
   added; new ALPHA_GRAD_SMOOTHED_INDEX slot.

5. q_disagreement_baseline drop: v1 had adaptive baseline as long-EMA
   (feedback loop risk). v2 uses structural 0.5 (analytic K=3-with-
   Flat-masked random alignment). Drop BASELINE_INDEX slot.

6. Backward gradient scaling clarified: α_grad scales dL/dx (input
   gradient flowing back to aux), NOT dL/dW (Q-head's weight grad).
   Q-head learns to use the wire freely; gate only controls upstream
   flow.

7. 4 hard rules added: feedback_no_hiding,
   feedback_no_htod_htoh_only_mapped_pinned,
   feedback_kill_runs_on_anomaly_quickly,
   pearl_canary_input_freshness_launch_order.

8. Smoke A2 explicit kill criteria table added (8 triggers).

Net ISV slot count unchanged (11), composition shifted: dropped
BASELINE, added SMOOTHED. Total impl cost ~1150 LOC (was ~1060).

Verified against current code:
  - TARGET_DIR_ACC_INDEX=372, AUX_DIR_ACC_SHORT_EMA_INDEX=373,
    AUX_DIR_PREDICTION_INDEX=375 (sp13_isv_slots.rs)
  - set_aux_weight clamp(0.05, 0.3) at gpu_dqn_trainer.rs:14722
    (confirms Bug 3 from Smoke A diagnostic)
  - mag_concat_qdir precedent at experience_kernels.cu:4560
    (direction-conditioning pattern; SP14's wire is the analog)
  - state_reset_registry pattern at lines 913-922 (canonical
    template for new EMA fold-reset entries)
  - branch_0_size = 3 in production config (the K=3 finding)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 17:11:04 +02:00
jgrusewski
eaf4adcb98 docs(sp14): spec — aux→Q wire + Earned Gradient Flow pearl
Designs the SP14 chain on top of SP13 Layer B (HEAD 6657e5626):

1. Sub-project A — stability fixes (3 small bugs found in Smoke A)
   - C51 atom-probability floor (ISV-driven from SP4 atom_pos_p99)
   - aux_w setter clamp lift [0.05, 0.3] → [0.15, 1.5]
   - Stagnation warmup gate at fold boundary

2. Sub-project B — the architectural piece (THIS spec)
   - Forward wire: aux_softmax_diff per-bar into direction Q-head input
     concat (in_dim+1, fingerprint bump, zero-init new column)
   - Earned Gradient Flow pearl — adaptive ISV-driven gradient gating:
     * Gate 1 (aux competence) — Schmitt-trigger hysteresis
     * Gate 2 (Q-head disagreement) — NEW signal, EMA per-step argmax
       mismatch
     * ISV-adaptive sigmoid steepness (variance-driven k_aux, k_q)
     * Per-epoch warmup ramp
     * Anti-gradient-hacking circuit breaker (mesa-opt defense)
   - 11 new ISV slots, 3 new GPU kernels, ~1060 LOC total
   - HEALTH_DIAG pearl_egf_diag observability line

3. Sub-project C — Adaptive LR (deferred until A+B effects measured)

Motivation from Smoke A diagnostic:
- aux_dir_acc reached 0.61 (signal extraction works)
- val_win_rate stuck 45-48% (no path to action selection)
- WR-flat-while-aux-varies = Q-head directional weights frozen
- 1109 GRAD_CLIP_OUTLIER events (chronic; not noise)

Three parallel diagnostic agents triangulated three interlocking root
causes:
- Slot 375 has zero readers (the wire was scoped but never built)
- C51 raw grad reaches 9.5e6, saturates SP7 budget controller
- aux_w controller muzzled by SP11-era [0.05, 0.3] clamp

The Earned Gradient Flow pearl is a new application of the codebase's
pearl pattern: ISV-driven adaptive controller, but applied to backward-
pass gradient flow instead of forward-pass features. The wire is one-
way (stop-gradient) by default; co-training is earned by both:
(a) aux head demonstrating label competence, AND
(b) Q-head showing it's actually fighting aux signal (informative
    disagreement above baseline).

Stability additions hardened against:
- Oscillation around target (Schmitt hysteresis)
- Numerical sigmoid saturation (argument clipping ±30)
- Stale variance EMAs across folds (state-reset-registry)
- Discontinuous warmup transitions (linear ramp)
- Mesa-optimization (gradient-hacking circuit breaker)
- Cold-start sentinel-state spurious gate openings (Pearl-A bootstrap)

Awaiting user review before invoking superpowers:writing-plans for
sub-project B (and a separate small plan for sub-project A).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 16:59:26 +02:00