Commit Graph

4015 Commits

Author SHA1 Message Date
jgrusewski
51436e5cd0 fix(ml): update Mamba2 test fixtures for parquet→data_dir rename
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 09:30:15 +01:00
jgrusewski
017eafb9f7 Merge branch 'feature/training-pipeline' into main
feat(ml): add manually-triggered GitLab CI training pipeline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 09:06:56 +01:00
jgrusewski
6e339316cf feat(ml): add manually-triggered GitLab CI training pipeline
Adds a parent/child GitLab CI pipeline for ML model training:

- Generator script produces per-model hyperopt/train/evaluate jobs
- Parent pipeline (.gitlab-ci-training.yml) with manual trigger
- NFS-backed ReadWriteMany PVC for shared training outputs
- Hyperopt params wired into training binaries (DQN, PPO, TFT, Mamba2)
- Shared DBN loader eliminates duplicate code across hyperopt adapters
- Supervised hyperopt unified to DBN data (was parquet-only)

Pipeline: hyperopt (4 models) → train (10 models) → evaluate ensemble

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 09:04:58 +01:00
jgrusewski
e3b8fe9382 fix(ci): deploy job uses infra-runner with scw + kubectl
Deploy was silently failing — bitnami/kubectl image lacks scw CLI
needed by Kapsule kubeconfig credential plugin. Now uses infra-runner
(has scw), installs kubectl inline until image is rebuilt. Adds
cluster-info check before deploy and proper error reporting per service.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:50:53 +01:00
jgrusewski
f0bbca23a5 perf(ci): compile training binaries with CUDA in compile-services job
Training image was recompiling from scratch inside Kaniko (~16+ min)
without sccache. Now training binaries are built in compile-services
with --features ml/cuda and PVC sccache (warm cache from service
binaries), then packaged into a CUDA runtime image (~30s).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 01:37:52 +01:00
jgrusewski
e72e4db235 refactor: delete 22 dead examples, 4 CSVs, consolidate data to test_data/
- Delete 22 dead/placeholder/broken example files (-3,489 lines code)
- Delete 4 tracked CSV files (-1.1M lines, were accidentally committed)
- Move baseline training data default from data/cache/ to test_data/
- Update 5 unified binary defaults, gitignore, k8s upload comment, docs
- Consolidate all training data under test_data/futures-baseline/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 01:24:02 +01:00
jgrusewski
c5db5aa39e perf(ci): compile once with PVC sccache, package with Kaniko
Split the build pipeline: one compile-services job builds all 8 service
binaries with PVC-backed sccache, saves as artifacts. Then 9 Kaniko jobs
just package pre-built binaries into slim runtime images (~30s each).

Before: 9 parallel Kaniko jobs each doing full cargo build --release
  (~20min each, no sccache, 9x duplicated dep compilation)
After:  1 compile job with sccache (~5min cached) + 9 package jobs (~30s)

- Add compile stage between test and build
- Add Dockerfile.runtime (minimal debian + pre-built binary)
- Add Dockerfile.web-gateway-runtime (Node dashboard + pre-built binary)
- Keep Dockerfile.training via Kaniko (needs CUDA dev image for H100)
- Remove all SCCACHE_BUCKET build-args from service builds
- Use dir:// context for Kaniko (only sends build-out/ dir, not full repo)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:50:25 +01:00
jgrusewski
754baeb434 perf(ci): skip check+clippy stage — test already compiles workspace
The check stage ran cargo check + clippy (~6min) before tests, but
the test stage compiles the same workspace anyway. Skip check with
an echo pass-through to save ~6min per pipeline. Easy to uncomment
when clippy enforcement is needed (e.g., before releases).

Also adds sccache stats to the test job for cache monitoring.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:24:57 +01:00
jgrusewski
c67ae083a9 fix(ci): remove stale SCCACHE_BUCKET override — S3 CI vars deleted
The SCCACHE_BUCKET, SCCACHE_REGION, and SCCACHE_ENDPOINT CI variables
were deleted from GitLab settings. The .rust-base override is no longer
needed — sccache now uses SCCACHE_DIR (PVC) by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:14:09 +01:00
jgrusewski
f6ef23c966 refactor(ml): delete 121 dead examples, 6 QAT tests, orphan binary
Mass cleanup of crates/ml/:
- Delete 121 dead/broken/superseded example files (-44,098 lines)
- Delete 6 QAT test files (-4,201 lines) — QAT is disabled at runtime
  (trainer.rs falls back to FP32 with warning)
- Delete 2 stale markdown files in examples/
- Delete orphaned src/bin/train_tft.rs (unimplemented stub)
- Clean up Cargo.toml: remove stale [[example]] entries, add missing ones
- Fix stale binary references in log_size_test.rs
- Add infra consistency test (35 checks across Dockerfile/train.sh/Cargo.toml)

Remaining examples (7): train_baseline_rl, train_baseline_supervised,
evaluate_baseline, hyperopt_baseline_rl, hyperopt_baseline_supervised,
download_baseline, cuda_test

All 2390 lib tests pass. All examples compile. 35/35 infra checks pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:05:38 +01:00
jgrusewski
ff8a275d47 fix(ml): widen flaky QAT checkpoint test range + use PVC sccache
- Widen observer checkpoint test bounds from 4σ to 5σ — random
  calibration data can exceed 4.0 with 100 batches of normal(0,1)
- Override SCCACHE_BUCKET="" in .rust-base so check/test jobs use
  PVC-backed SCCACHE_DIR instead of S3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:55:35 +01:00
jgrusewski
7b9da53603 infra(ci): switch CI builds from H100 to L4 — 4.7x cost reduction
Create dedicated ci-build node pool (L4-1-24G, €0.75/hr) replacing
H100 (€3.50+/hr) for CI builds. H100 reserved for training only.

- Add ci-build pool to Terraform (L4-1-24G, scale-to-zero, fr-par-2)
- Update GitLab Runner to target ci-build pool with L4-sized limits
- Change CUDA_COMPUTE_CAP from 90 (H100) to 89 (L4) in CI
- Dockerfile.training keeps CUDA_COMPUTE_CAP=90 for H100 training

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:30:04 +01:00
jgrusewski
71eefa6d53 refactor(ml): delete straggler train_mamba2/train_ppo examples
These two files survived the 20-file consolidation in 022036cb.
Both are now fully superseded:
- train_ppo.rs → train_baseline_rl --model ppo
- train_mamba2.rs → train_baseline_supervised --model mamba2

Also updates entrypoint-generic.sh usage examples to reference
the unified binaries (train_baseline_rl, train_baseline_supervised).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:24:53 +01:00
jgrusewski
267240530d perf(ci): enable Kaniko layer caching + Docker Hub auth on all builds
- Add --cache=true --cache-repo to all 12 Kaniko builds
- Cache Docker layers in Scaleway CR (rg.fr-par.scw.cloud/foxhunt-ci/cache)
- Add Docker Hub auth to devcontainer + infra-runner prepare jobs
- First build populates cache; subsequent builds skip base image pulls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:20:44 +01:00
jgrusewski
022036cb96 refactor(ml): consolidate 21 training binaries into 2 unified baselines
Replace 20 per-model training examples with:
- train_baseline_rl: DQN + PPO (renamed from train_baseline)
- train_baseline_supervised: TFT, Mamba2, Liquid, TGGN, TLOB, KAN, xLSTM, Diffusion
  via model factory + UnifiedTrainable generic training loop

Update Dockerfile.training (16→7 binaries), train.sh MODEL_BINARY map,
and job-template.yaml default. -12,759 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:16:25 +01:00
jgrusewski
373a6f33a1 fix(ci): add Docker Hub auth to Kaniko to avoid pull rate limits
All Kaniko builds hit Docker Hub anonymous rate limit (100 pulls/6h).
Add DOCKERHUB_USERNAME + DOCKERHUB_TOKEN to config.json alongside
Scaleway CR credentials.

Requires CI variables: DOCKERHUB_USERNAME, DOCKERHUB_TOKEN

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:15:40 +01:00
jgrusewski
51460a3382 perf(ci): switch sccache from S3 to local block storage PVC
- Create 20Gi sccache-pvc (scw-bssd) for fast local cache hits
- Mount at /mnt/sccache in CI build pods via runner helm values
- Use SCCACHE_DIR instead of SCCACHE_BUCKET for check/test jobs
- Kaniko builds keep S3 sccache (can't mount PVCs in Kaniko)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:12:34 +01:00
jgrusewski
387bc0d400 docs: add unified training binaries implementation plan
8-task plan covering rename, new supervised binary, deletions, and infra updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:05:10 +01:00
jgrusewski
45483d203a docs: unified training binaries design
Consolidate 21 training examples into 2 binaries:
- train_baseline_rl (DQN, PPO with RL walk-forward)
- train_baseline_supervised (8 models via UnifiedTrainable)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:59:51 +01:00
jgrusewski
a3cb195671 fix(docker): pin rclone to v1.69.1 — current download URL returns 404
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:51:51 +01:00
jgrusewski
ac688cac24 fix(ci): skip Rust builds on infra-only changes, remove stale files
Add `rules:` with `changes:` filters to check, test, and .kaniko-base
jobs so the Rust build pipeline only triggers when source code changes
(crates/, bin/, services/, Cargo.*). Prevents H100 spin-up on
infra-only pushes.

Remove 31 stale/orphan files (-11,885 lines):
- monitoring/ directory (duplicated by config/grafana + config/prometheus)
- 10 broken/placeholder migration files (.broken, .skip)
- 10 unreferenced config files (haproxy, nginx-lb, mutants, etc.)

Add 3 historical design docs from previous restructure work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:45:44 +01:00
jgrusewski
9729395073 fix(ml): wire spread_cost_bps into all training examples, remove dead code
- Add tx_cost_bps/tick_size/spread_ticks CLI args to tggn, xlstm, diffusion
- Subtract spread + commission from target returns during data prep
- Delete unused validate_model_parameters from train_mamba2_dbn
- Wire validate_training_batch into mamba2 pre-training validation

All 16 training examples now compile with zero warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:30:24 +01:00
jgrusewski
6c59e16cd6 fix(ml): fix train_mamba2_dbn and train_dqn_es_fut compile errors
- Add missing Mamba2Config fields (early_stopping_enabled, patience, min_delta, min_epochs)
- Replace unwrap_or on f64 (not Option) with direct field access
- Replace .unwrap() on path.to_str() with safe .ok_or_else()
- Fix DQN closure signature: 3 args (epoch, data, is_final), not 2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:19:22 +01:00
jgrusewski
0eff692cf3 feat(infra): IaC pipeline, tfstate migration, and drift detection
- Migrate tfstate backend from nl-ams to fr-par
- Add missing resources to TF: sccache bucket, foxhunt-ci registry,
  grafana + prometheus DNS records
- Add infra-runner Dockerfile (terraform + terragrunt + scw + glab)
- Add CI jobs: infra-plan (MR), infra-apply (merge), drift-check (weekly)
- All IaC jobs run on gitlab pool (zero extra cost)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:52:42 +01:00
jgrusewski
980489edc5 fix(ci): use relative artifact paths and avoid PIPESTATUS in drift check
- Artifact paths changed from /tmp/ to ${CI_PROJECT_DIR}/ for GitLab
  k8s executor compatibility
- Drift check uses $? instead of PIPESTATUS (Alpine sh doesn't support
  bash arrays)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:51:46 +01:00
jgrusewski
1caeb0b0d6 ci: add IaC pipeline (plan on MR, apply on merge, weekly drift check)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:48:57 +01:00
jgrusewski
9d20c3c97c infra: migrate tfstate backend from nl-ams to fr-par
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:48:33 +01:00
jgrusewski
3f4ae18a4c infra: add Dockerfile for IaC CI runner (terraform + terragrunt + scw + glab)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:47:59 +01:00
jgrusewski
d271315e7e infra(dns): add grafana + prometheus A records to Terraform
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:46:56 +01:00
jgrusewski
b321fa47a7 infra(object-storage): add sccache bucket to Terraform
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:46:45 +01:00
jgrusewski
c80899066c infra(registry): add foxhunt-ci namespace to Terraform
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:46:39 +01:00
jgrusewski
254b72d111 docs: IaC pipeline implementation plan (10 tasks)
Tasks 1-7: code changes (cleanup, module updates, Dockerfile, CI jobs,
root.hcl migration). Tasks 8-10: manual ops (state migration, resource
imports, image build, schedule setup).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:44:20 +01:00
jgrusewski
7d80a0db48 docs: IaC pipeline & tfstate migration design
Covers tfstate migration nl-ams→fr-par, resource import for
drift gaps (sccache bucket, foxhunt-ci registry, DNS records),
and GitLab CI/CD pipeline (plan on MR, apply on merge, weekly
drift detection).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:41:45 +01:00
jgrusewski
f3619ebcec fix(ci): add AWS_REGION for sccache S3 in Dockerfiles
sccache 0.8+ (opendal backend) requires AWS_REGION, not just
AWS_DEFAULT_REGION. Also set SCCACHE_REGION as belt-and-suspenders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:39:39 +01:00
jgrusewski
6b9e58feee fix(infra): add wait_for_pool_ready=false for gpu-dev pool
Scale-to-zero pools start with 0 nodes, so Terraform's default
wait_for_pool_ready=true always fails with "state warning, wants ready".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:28:37 +01:00
jgrusewski
3e7bf11d99 feat: DevPod remote development environment
Adds one-click remote dev on Kapsule with Claude Code, persistent
storage, and autoscale-to-zero. GP1-L (16 vCPU, 64GB) dev pool,
50Gi PVC for home directory, devcontainer image on SCW registry.

- .devcontainer/ (Dockerfile, devcontainer.json, pod-template, init-home)
- Terraform gpu-dev pool (GP1-L, 0→1 autoscaling)
- CI job to build devcontainer image (Kaniko → SCW registry)
- scripts/devpod-setup.sh for one-time provider config
- "Open in DevPod" link: https://devpod.sh/open#ssh://git@100.90.76.85:2222/root/foxhunt.git

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:23:25 +01:00
jgrusewski
75a528abea fix(ci): remove blank lines breaking Kaniko multi-line commands
The replace_all for --insecure-registry left blank lines in the YAML
multi-line scalars, splitting each kaniko command in two. GitLab only
executed the first half (--context + --dockerfile), missing --destination.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:23:11 +01:00
jgrusewski
b8d4138c28 fix: review fixes — IMAGE_PULL_SECRETS, SCW registry, devpod provider
- Add missing IMAGE_PULL_SECRETS=gitlab-registry to devpod-setup.sh
- CI job pushes devcontainer to SCW registry (not internal GitLab)
- Remove unused internal registry auth from build-devcontainer job
- Add customizations.devpod.provider to devcontainer.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:19:32 +01:00
jgrusewski
fca785533b ci: add build-devcontainer job
Builds .devcontainer/Dockerfile with Kaniko, pushes to internal
GitLab registry. Triggers on .devcontainer/ changes or manual run.
Authenticates to both internal registry and Scaleway CR (for base image pull).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:16:25 +01:00
jgrusewski
d59da19dd8 feat(devcontainer): add Dockerfile extending CI builder
Adds Node.js 22, Claude Code, Python 3, kubectl, helm, scw, glab,
terraform, terragrunt, zsh, ripgrep, fd-find. Non-root dev user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:15:02 +01:00
jgrusewski
22803e8b37 feat: add devpod-setup.sh for one-time provider config
Configures DevPod kubernetes provider, creates dev-home PVC,
verifies cluster access. Run once on developer laptop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:13:09 +01:00
jgrusewski
8cdbdf9625 infra: add gpu-dev pool for DevPod remote development
GP1-L (16 vCPU, 64GB), autoscaling 0→1, dedicated for dev pods.
Separate from CI (H100) and inference (L4) pools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:12:49 +01:00
jgrusewski
30516764c6 feat(devcontainer): add init-home.sh for PVC bootstrap
Links cargo binaries, creates sccache dir, and writes default .zshrc
on first boot. No-op on subsequent sessions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:12:42 +01:00
jgrusewski
5dc617fa20 feat(devcontainer): add k8s pod template for DevPod
Mounts dev-home PVC (50Gi) and training-data PVC (read-only).
Targets gpu-dev node pool. Resource requests: 4 CPU / 16Gi,
limits: 14 CPU / 56Gi.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:12:40 +01:00
jgrusewski
d9386f905f feat(devcontainer): add devcontainer.json
Builds from CI builder base, runs as non-root dev user.
postCreateCommand bootstraps PVC home dir on first session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:12:36 +01:00
jgrusewski
b4d0fee1e0 infra: add 50Gi PVC for DevPod home directory
Persistent block storage for Claude Code, cargo registry, sccache
cache, and shell config. Survives pod restarts and node scale-down.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:12:18 +01:00
jgrusewski
c6247ea9f8 fix(ci): update Dockerfiles for restructured repo + migrate to SCW registry
- Update COPY paths in all 3 Dockerfiles for crates/bin/services/testing layout
- Migrate service image builds from internal GitLab registry to SCW CR
- Update Kaniko auth to use SCW credentials (nologin + SCW_SECRET_KEY)
- Remove --insecure-registry flags (SCW CR is HTTPS)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:09:52 +01:00
jgrusewski
74615823ce docs: add DevPod implementation plan (10 tasks)
Terraform pool, PVC, Dockerfile, devcontainer.json, pod template,
CI job, setup script, infra apply, GitLab badge. TDD-style steps
with exact file paths and commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:09:31 +01:00
jgrusewski
f3a3b61049 docs: add DevPod remote development environment design
DevPod on Kapsule with GP1-L (16 vCPU, 64GB) autoscaling to zero,
persistent PVCs for Claude Code + cargo cache, "Open in DevPod"
GitLab badge, CI-built devcontainer image.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:06:51 +01:00
jgrusewski
3bfb9611b5 fix(ci): move PVC mount to /mnt/training-data (avoids Redis /data conflict)
Redis image WORKDIR is /data and entrypoint runs chown recursively.
PVC mounted at /data/training was read-only, causing chown to fail
with exit code 1, crashing the Redis sidecar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:54:28 +01:00