Commit Graph

128 Commits

Author SHA1 Message Date
jgrusewski
62484e9c59 fix: stop deleting feature cache on every hyperopt run
The feature cache auto-invalidates via content hash — manual rm -f
wasted ~2 minutes of MBP-10 + OFI recomputation per trial start.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:03:48 +01:00
jgrusewski
704ee72412 Revert "fix: stop clearing feature cache on every Argo run — auto-invalidates via content hash"
This reverts commit eab24bd288.
2026-03-25 08:40:10 +01:00
jgrusewski
eab24bd288 fix: stop clearing feature cache on every Argo run — auto-invalidates via content hash 2026-03-25 08:37:59 +01:00
jgrusewski
e8a3104159 feat: DSR warm-up, num_atoms=101, clear stale cache on H100
- DSR warm-up: skip first 50 steps when EMA has insufficient history
- Phase Fast num_atoms: 51 → 101 (H100 can afford finer resolution,
  1.19 per atom vs 2.35 — critical for distinguishing Q-values)
- Argo template: clear stale feature cache before hyperopt (ensures
  fresh computation with VPIN/trades enrichment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:32:48 +01:00
jgrusewski
eabc7ae36b feat: Phase 3 reward tuning — fix dynamics+architecture, search 7 reward dims
Three-phase hyperopt pipeline:
  Phase 1 (fast): fix architecture + reward, search dynamics (~17D)
  Phase 2 (full): fix dynamics, search architecture (~5D)
  Phase 3 (reward): fix dynamics + architecture, search reward weights (7D)

Phase 3 is the fastest (~10s/trial) since only experience collection
changes. CLI: --phase reward --hyperopt-params phase2_results.json

Argo template runs all 3 phases sequentially. Phase 2 writes to
_phase2_results.json, Phase 3 writes final _hyperopt_results.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:45:00 +01:00
jgrusewski
6f0a1231df fix: set CARGO_TARGET_DIR in hyperopt step for cubin cache persistence
Without CARGO_TARGET_DIR, cubin cache goes to /tmp (ephemeral).
With it, cubins persist at /workspace/.cubin_cache/ on the PVC
across runs — saves ~30s of nvcc compilation per trial.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:30:43 +01:00
jgrusewski
1d47636474 fix: add missing git-branch parameter to compile-and-train template
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:11:29 +01:00
jgrusewski
adce841e6b fix: H100 GPU test failures — stale profile assertions + smoke test stability
- test_embedded_h100_parses: update assertions to match h100.toml values
  (gpu_n_episodes=2048, gpu_timesteps_per_episode=100)
- dqn_training_smoke_test: apply dqn-smoketest profile to cap hidden_dim=32.
  H100's gpu profile sets hidden_dim_base=256 which causes loss explosion
  (375x in 3 epochs) with lr=0.001.
- Revert gpu-test-pipeline DAG to compile-and-test (RWO PVC constraint)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 11:08:23 +01:00
jgrusewski
87a37ac020 fix: detect config/training + config/gpu changes as ml-changed
TOML training profiles are include_str!() into the ml binary at compile
time. Changes to config/training/ or config/gpu/ must trigger GPU test
rebuild, otherwise the binary runs with stale embedded defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:56:44 +01:00
jgrusewski
78cd46953f fix: bump both main+wait executor memory to 256Mi for submit-gpu-test
The Argo 'main' (emissary) container was the OOMKilled one, not 'wait'.
podSpecPatch now targets both containers to prevent executor OOM when
tracking large child workflow status JSON.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:53:19 +01:00
jgrusewski
a7c22ca5aa fix: CI OOMKilled on submit-gpu-test + YAML indentation fixes
submit-gpu-test wait sidecar had 64Mi limit — OOMKilled when tracking
large child workflow status JSON. Bumped to 256Mi.

Fixed YAML indentation errors in compile-and-train and training-pipeline
templates (misaligned labels, duplicate component keys).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:45:43 +01:00
jgrusewski
ca94c0e851 feat: wire two-phase hyperopt into Argo training workflows
Phase 1 writes ${MODEL}_phase1_results.json to PVC, Phase 2 reads it
via --hyperopt-params. Phase 2 uses half the trials but double epochs.
train-best downstream reads final ${MODEL}_hyperopt_results.json unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 10:39:36 +01:00
jgrusewski
b759467259 fix: add pushgateway port 9091 to GPU test network policy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 02:22:11 +01:00
jgrusewski
ae5ae056d6 fix: add gpu-test network policy label to all GPU workflow templates
5 templates were missing app.kubernetes.io/component=gpu-test label,
causing MinIO log archival to fail (port 9000 blocked by network policy).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 02:08:50 +01:00
jgrusewski
922fd5e93e ci: add DQN perf benchmark step + 3Q test data for CI
GPU test pipeline:
- Add perf-benchmark step after compile-and-test
- Runs DQN training on 3Q ES.FUT (OHLCV + MBP-10 + trades)
- Reports epoch time (ms), fails if > 500ms (H100 regression guard)
- batch_size=1024, 5 epochs × 100 steps, skips epoch 1 (init)

Populate test data job:
- Copy 3 quarters per symbol (was 1) for all data types
- OHLCV: ~6MB/symbol for walk-forward + perf benchmarks
- MBP-10: 3Q for OFI feature pipeline testing
- Trades: 3Q for trade-flow feature testing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:17:27 +01:00
jgrusewski
65891816ee fix: resolve all CI test failures — TFT, DQN pipeline, benchmarks
DQN pipeline tests:
- Split dqn-pipeline into per-test cargo invocations in CI (CUDA Graph
  capture corrupts async memory pool between sequential tests)
- Drop impl for GpuDqnTrainer: sync stream + destroy graph before buffers
- check_err drains in constructor and after graph capture

TFT fixes:
- forward_loss: reshape output [batch,horizon,quantiles] → [batch,quantiles]
  to match target shape (fixes DimensionMismatch {expected:3, actual:3})
- smoke test: accept step=0 for models without backward support
- benchmark: remove hardcoded batch_size≤4 assertion (H100 can be larger)

Cleanup:
- Remove debug eprintln from elementwise.rs
- GPU-native cat bounds check

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:09:51 +01:00
jgrusewski
9f5b88c81d revert: remove data subset hacks — need proper approach
Reverts 4 commits (8139911c, 282f3aff, b3aca96d, dad61e4e) that
tried to workaround slow CI by limiting data subsets and cleaning
caches. The real issue is debug-mode .dbn.zst parsing taking minutes.

Kept: --test-threads=1 fix (root cause), hard CUDA error, action
range fixes, #[ignore] for heavy tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:55:46 +01:00
jgrusewski
b3aca96d51 fix(ci): clean stale test binaries from PVC before GPU tests
Cargo incremental compilation on persistent PVC reuses old test
binaries even when source changed. Force cargo clean -p for ML crates
to ensure fresh compilation with latest max_bars and test fixes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 21:15:15 +01:00
jgrusewski
10b86b4319 fix(ci): enforce --test-threads=1 for ALL GPU integration tests
Root cause: parallel test execution within a single cargo test binary
corrupts the CUDA primary context (cuDevicePrimaryCtxRetain race).

The dqn-smoke tests ran in parallel threads — 3 GPU tests using a
shared OnceLock<MlDevice> raced with smoke_e2e_dqn_training_loop
which creates a fresh CudaContext::new(0). The parallel context
init/teardown left the primary context in an error state, causing
subsequent cuInit(0) to fail silently.

Lib tests passed because they already had --test-threads=1.
Integration tests (dqn-smoke, dqn-smoke-train, ppo-barrier, etc.)
were missing it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 20:20:30 +01:00
jgrusewski
266f7417f5 fix(ci): bump GPU test opt-level to 2, revert one-time cache clean
opt-level=1 caused DQN lib tests to timeout at the 2-hour deadline
(113 tests × debug-mode GPU init = too slow). opt-level=2 matches
local dev behavior.

Revert the cargo clean -p steps now that stale Candle cache is purged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:57:49 +01:00
jgrusewski
79ab30f414 fix(ci): clean stale ML cache in GPU test pipeline + save logs
Same stale incremental cache issue as ci-pipeline. Also saves compile
output to PVC for post-mortem debugging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:54:42 +01:00
jgrusewski
3cec1a415e fix(ci): save build logs to PVC for post-mortem debugging
Pipe clippy and test output to /cargo-target/*.log via tee so errors
are readable after pod GC. Fixes blind CI failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:37:44 +01:00
jgrusewski
9e530e31bb fix(ci): clean stale ML crate cache before build
The Candle→cudarc migration invalidated all incremental compilation
artifacts for ml, ml-core, ml-dqn, ml-ppo, ml-supervised. CI PVC
retains stale .rmeta/.rlib causing spurious compile errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:24:40 +01:00
jgrusewski
ddfa57af11 infra: VPC gateway in Terraform + DNS deadlock prevention
- Added scaleway_vpc_public_gateway + DHCP + gateway_network to TF
  (was manually created, now codified with push_default_route=true)
- Added scripts/safe-node-replace.sh — one-at-a-time with DNS verification
- Added dns-bootstrap-policy.yaml — incident documentation + recovery procedure
- Bastion enabled (port 61000) for emergency SSH access

Prevention: NEVER replace all nodes at once. Use safe-node-replace.sh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 00:38:20 +01:00
jgrusewski
cfa5db39e8 fix(ci): test-gate uses ci-builder (CUDA) — cudarc 0.19 needs nvcc
ci-builder-cpu → ci-builder in test-gate template. cudarc 0.19 requires
nvcc at build time for its build.rs. Still runs on ci-compile-cpu node.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 21:22:04 +01:00
jgrusewski
2357337bbd fix(infra): move Argo logs to dedicated argo-logs bucket
Argo artifact logs were stored in foxhunt-training-results which is
meant for model checkpoints. Separate bucket makes logs findable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 09:33:11 +01:00
jgrusewski
8c4657a3a4 fix(infra): resolve commit-sha=HEAD to remote branch tip, not local PVC HEAD
When commit-sha defaults to "HEAD", git checkout HEAD is a no-op — it keeps
the PVC's stale checkout. Now resolves HEAD to origin/{branch} after fetch,
ensuring the latest pushed code is always compiled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 14:49:55 +01:00
jgrusewski
e807558cd8 fix(infra): remove --initial-capital from train-best step
train_baseline_rl doesn't accept --initial-capital (only hyperopt and
evaluate binaries do). Removing it fixes the exit code 2 in DQN
hyperopt v3 train-best step.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 13:50:46 +01:00
jgrusewski
92f8cba74a fix(infra): add LD_LIBRARY_PATH stubs filter and env vars to compile-and-train template
The ci-builder image has CUDA stub libraries that shadow real NVIDIA
drivers. Without filtering stubs from LD_LIBRARY_PATH, training binaries
report "CUDA GPU required but none available" even on GPU nodes.

Add to hyperopt, train-best, and evaluate steps:
- LD_LIBRARY_PATH stubs filter (grep -v stubs)
- nvidia-smi verification
- RUST_LOG, SQLX_OFFLINE, CUBLAS_WORKSPACE_CONFIG env vars
- PATH includes /workspace/bin (use binary name, not full path)

Matches the existing pattern in training-workflow-template.yaml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:22:55 +01:00
jgrusewski
23a122607d feat(infra): Argo log persistence, network policies, lightweight CI images
- Argo workflow archive via PostgreSQL — persistent logs after pod GC
- Allow Argo controller to reach PostgreSQL via network policy
- Allow Argo server to reach MinIO for S3 log archival
- Replace foxhunt-runtime with lightweight images (alpine:3.21, curlimages/curl)
  in orchestration steps: fetch-binary, upload-results, detect-changes, gpu-warmup
- Use ci-builder for training steps (hyperopt, train-best, evaluate) — nvcc required
- Fix --hyperopt-results → --hyperopt-params flag in train-best step
- Remove invalid podGCGracePeriod from Argo Helm values
- Archive RBAC, kustomization updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:00:46 +01:00
jgrusewski
aabc1d95e5 fix(infra): pin workflow-trigger eventsource to platform pool
The eventsource had no nodeSelector and landed on ci-compile-cpu
(POP2-HC-32C-64G, €0.56/hr), blocking autoscaler from scaling it
to 0. Now pinned to platform pool — ci-compile-cpu will autoscale
down, saving ~€410/mo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 09:26:31 +01:00
jgrusewski
ddf1082cb5 Revert "fix(ci): retain completed pods 10 min for log access (CPU only)"
This reverts commit 8e6effb7f6.
2026-03-14 01:10:34 +01:00
jgrusewski
8e6effb7f6 fix(ci): retain completed pods 10 min for log access (CPU only)
Add deleteDelayDuration: 600s to podGC on CPU workflow templates and
sensors (ci-pipeline, compile-deploy, build-image). GPU training
workflows keep immediate cleanup to avoid wasting expensive GPU time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 01:10:06 +01:00
jgrusewski
3112e07a5a perf(ci): serialize dqn-pipeline tests to avoid GPU contention
4 concurrent DQN trainers on a shared H100 causes severe GPU contention
(28-39% utilization, 42 GB VRAM). Serializing with --test-threads=1
gives each test full GPU access, reducing total wallclock time despite
sequential execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 19:52:04 +01:00
jgrusewski
0c571c351b fix(cuda): deterministic SHA-256 PTX cache key + extend deadline to 120min
DefaultHasher (SipHash) uses random per-process keys — the PTX cache
would never hit across separate cargo test runs. Switch to SHA-256
(deterministic) so cached PTX persists on the PVC across CI runs.

Also extend activeDeadlineSeconds from 90min to 120min to accommodate
the one-time cold-start NVRTC compilation (30+ min for the fused
experience collector kernel).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:16:04 +01:00
jgrusewski
fefb9e3185 perf(ci): enable opt-level=1 for GPU test builds
Integration tests (e2e DQN training on 148k bars) take 30+ minutes
in debug mode (opt-level=0). CARGO_PROFILE_TEST_OPT_LEVEL=1 enables
basic optimizations for test binaries — requires recompile but tests
run 5-10x faster. Local dev unaffected (env override only in CI).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:34:26 +01:00
jgrusewski
2c9d929777 chore(ci): restore podGC OnPodCompletion after successful validation
Pipeline validated end-to-end on H100: 3/3 steps green, 539 tests pass.
Switch podGC back to OnPodCompletion to auto-clean all pods after runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:55:53 +01:00
jgrusewski
5b0b5ef917 fix(ci): add LD_LIBRARY_PATH for CUDA runtime, fix git checkout
1. CUDA_ERROR_STUB_LIBRARY: ci-builder image has CUDA stubs ahead of
   real NVIDIA driver libs in LD_LIBRARY_PATH. Prepend
   /usr/local/nvidia/lib64 (device-plugin mount) so real driver is
   found first.
2. Git checkout: `git checkout --force main` stays on local main
   without pulling. Add `git reset --hard origin/$REF` to fast-forward
   branch to latest remote commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:42:30 +01:00
jgrusewski
13e36a14d3 fix(ci): use bash for compile-and-test, fix --nocapture placement
Two bugs in gpu-test-pipeline-template.yaml:
1. /bin/sh doesn't support bash-isms (<<<, read -ra, arrays) used in
   the test runner script. Switch to /bin/bash.
2. --nocapture was appended as a cargo argument instead of a test binary
   argument. Now detects whether -- separator exists in args and places
   --nocapture correctly after it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:36:30 +01:00
jgrusewski
5cb9be71e4 fix(infra): add gpu-test egress NetworkPolicy, revert archiveLogs hack
Root cause: default-deny-all blocks egress from gpu-test pods to MinIO,
causing the Argo wait sidecar to hang on log upload. Fix: add egress
policy for gpu-test component (DNS, git, MinIO, Mattermost, registry).
Revert archiveLogs: false — logs should be stored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:20:26 +01:00
jgrusewski
337aff80df fix(infra): disable archiveLogs on gpu-test templates (MinIO not running)
The wait sidecar blocks indefinitely trying to save logs to MinIO which
has no running pods. Disable log archiving on all 3 templates since test
output is captured in Argo's pod logs already.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:14:36 +01:00
jgrusewski
af92fb099d fix(ci): grant argo-workflow SA configmaps + networkpolicies RBAC
apply-argo-templates step failed because the service account lacked
permissions to manage configmaps (auto-compile-configmap.yaml) and
networkpolicies (argo-workflow-netpol.yaml) in the foxhunt namespace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:10:55 +01:00
jgrusewski
5ca26d2da0 fix(infra): use runtime image for gpu-warmup (Argo emissary compat)
busybox doesn't support Argo's emissary executor protocol, causing the
wait sidecar to hang indefinitely and hold the GPU allocation. Switch to
foxhunt-runtime which has proper /bin/sh and lets the sidecar detect
container exit. Also adds nvidia-smi check during warmup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:09:10 +01:00
jgrusewski
10b7fd9e68 fix(ci): wire Redis integration tests to real sidecar container
Remove #[ignore] from 3 Redis tests and use REDIS_URL env var from CI.
Add Redis 7 sidecar to test-gate pod with readiness probe + nc wait loop.
Tests gracefully skip if Redis unavailable (local dev without Docker).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:00:12 +01:00
jgrusewski
fb59b0a10e ci: add on-push GPU test trigger gated by ML file changes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:57:57 +01:00
jgrusewski
24e4ff48e5 infra: add suspended CronWorkflow for nightly GPU test runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:57:03 +01:00
jgrusewski
1520c56e41 infra: add gpu-test-pipeline WorkflowTemplate for H100 test suite
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:55:36 +01:00
jgrusewski
c535564e2e infra: add PVCs for GPU test pipeline (cargo-target-cuda-test + test-data)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:54:13 +01:00
jgrusewski
18fe480e8f fix(ci): replace PIPESTATUS bashism with POSIX-compatible test capture
The test-gate script runs under /bin/sh (dash), which doesn't support
${PIPESTATUS[0]}. This caused 'Bad substitution' (exit 2) on EVERY CI
run regardless of test results.

Fix: redirect cargo test to file, capture $?, then cat for log output.
This is POSIX-compatible and correctly captures the test exit code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:51:16 +01:00
jgrusewski
85b3f02af4 fix(hyperopt): enforce minimum 5 trials, skip hyperopt when trials=0
The hyperopt binary was crashing with "trials (5) must be greater than
n_initial (5)" when --trials 0 was passed. Root cause: the bump logic
set trials = n_initial instead of max(5, n_initial + 1).

Fix: both hyperopt_baseline_rl and hyperopt_baseline_supervised now clamp
trials to max(5, n_initial + 1). Also add `when` condition to the
compile-and-train DAG so hyperopt step is skipped when trials=0, and
train-best gracefully handles missing hyperopt results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 21:58:11 +01:00