Commit Graph

360 Commits

Author SHA1 Message Date
jgrusewski
7a01618e86 fix(infra): upgrade OpenTelemetry 0.27→0.31 to align tonic versions, fix DCGM scheduling
OTLP fix: opentelemetry-otlp 0.27 bundled tonic 0.12 while the workspace
uses tonic 0.14, making with_channel() impossible (type mismatch). Upgrading
to otel-otlp 0.31 aligns both on tonic 0.14, enabling explicit Channel
construction that respects http:// scheme (no spurious TLS negotiation).

API migrations (otel 0.27→0.31):
- TracerProvider → SdkTracerProvider
- with_batch_exporter(exporter, runtime) → with_batch_exporter(exporter)
- Resource::new(vec![...]) → Resource::builder().with_service_name().build()
- global::shutdown_tracer_provider() removed (Drop-based shutdown)
- opentelemetry-otlp feature "tonic" → "grpc-tonic"

DCGM fix: remove runtimeClassName: nvidia from DaemonSet — Scaleway Kapsule
GPU pools use nvidia runtime as default containerd handler. The RuntimeClass
CRD is only created by the full GPU Operator, not the device plugin alone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:31:22 +01:00
jgrusewski
30fcb9abe9 fix(dashboards): correct DCGM metric names in all Grafana dashboards
DCGM exporter v3.x emits lowercase metric names (dcgm_gpu_utilization)
but dashboards used the old uppercase format (DCGM_FI_DEV_GPU_UTIL).
Fixed across 4 dashboard files:
- foxhunt-cockpit.json (Infrastructure Cockpit)
- foxhunt-training-cockpit.json (Training Cockpit)
- foxhunt-gpu-training.json (GPU Training)
- gpu-overview.json (GPU Overview)

Replaced DCGM_FI_DEV_FB_TOTAL with (dcgm_fb_used + dcgm_fb_free)
since DCGM v3 doesn't emit a total metric.

Redeployed all dashboard ConfigMaps and restarted Grafana.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:29:57 +01:00
jgrusewski
16db63d71e fix(monitoring): DCGM exporter — nvidia runtime, custom counters, GitLab annotations
Three fixes for GPU metrics not appearing in dashboards:

1. Added runtimeClassName: nvidia so DCGM can access NVML/GPU devices
2. Custom counters ConfigMap without DCP/profiling metrics (avoids
   SYS_ADMIN requirement that caused fatal crash)
3. Added gitlab.com/prometheus_* annotations so GitLab's Prometheus
   discovers and scrapes the DCGM pods

Increased memory limit 128Mi → 1Gi (was OOMKilled).
Metrics now flowing: gpu_utilization, fb_used/free, power_usage, temps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:15:19 +01:00
jgrusewski
f6cf857db2 fix(infra): remove unused L4 (ci-rl) pool — consolidate all training on ci-training
The L4 pool was unused: all training routes to ci-training (L40S) and
all compilation routes to ci-compile-cpu (POP2). Disabled in terragrunt
and applied to destroy the pool. Removed all ci-rl references from K8s
manifests and CI comments.

Final pool layout:
- ci-compile-cpu (POP2-32C-128G) — Rust compilation
- ci-training (L40S-1-48G) — all GPU training + hyperopt
- services (DEV1-L) — production services
- gitlab (GP1-XS) — GitLab CE
- gpu-dev (GP1-L) — DevPod development

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:02:54 +01:00
jgrusewski
c97c02677e fix(infra): rename L4 pool ci-compile → ci-rl, remove stale moved blocks
Applied terragrunt to recreate the L4 GPU pool with the correct name
`ci-rl` (was `ci-compile` due to immutable Scaleway pool names).
Updated all K8s manifests and comments to match. Removed the 3 stale
`moved` blocks from main.tf since the state renames are now applied.

Pool naming is now consistent across Terraform, Scaleway, and K8s configs:
- ci-compile-cpu (POP2-32C-128G) — CPU compilation
- ci-rl (L4-1-24G) — RL training / CUDA compile
- ci-training (L40S-1-48G) — supervised training + hyperopt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:59:44 +01:00
jgrusewski
a27ff8790c fix(ci): restore nvidia runtime_class_name on RL runner
RL runner only handles GPU training jobs, so global nvidia runtime
is safe and required (KUBERNETES_RUNTIME_CLASS_NAME override wasn't
being applied). Main runner keeps overwrite-allowed pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:37:58 +01:00
jgrusewski
972c3cb3cc fix(ci): correct pool naming — all training to ci-training, compile to ci-compile-cpu
Pool mapping:
- ci-compile-cpu (POP2-32C-128G): Rust compile, web dashboard, manifest
- ci-compile (L4): CUDA compile with stubs only
- ci-training (L40S): ALL training (RL + supervised)

Main runner default → ci-compile-cpu
RL runner default → ci-training
.train-rl-base → explicit ci-training node selector

Replaced all stale ci-rl references with correct pool names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:21:14 +01:00
jgrusewski
a36fce0b87 fix(infra): increase Tempo memory to 1Gi, RL runner CPU limits to 8000m
Tempo was OOMKilled every ~30 min at 512Mi, causing web-gateway OTLP
export errors. Increased to 1Gi.

RL runner had cpu_request_overwrite_max_allowed=4000m but hyperopt RL
jobs need 6000m for parallel PSO trials. Increased to 8000m.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:04:26 +01:00
jgrusewski
cfdd878fff fix(ci): move nvidia runtime from global to per-job
Remove runtime_class_name="nvidia" from runner configs (applied to ALL
pods, broke compile on CPU-only ci-compile-cpu nodes). Instead use
runtime_class_name_overwrite_allowed + KUBERNETES_RUNTIME_CLASS_NAME
per-job on GPU templates (.train-rl-base, .train-validate-base).

Also routes build-web-dashboard and write-manifest to ci-compile-cpu.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:43:24 +01:00
jgrusewski
ab67c1ec7e fix(minio): map cert-manager TLS keys to MinIO names, fix mc CA cert path
cert-manager stores certs as tls.crt/tls.key but MinIO expects
public.crt/private.key — add volume items projection.

mc client doesn't use MC_CA_CERTIFICATE env; instead copy CA cert to
~/.mc/certs/CAs/ before running mc alias set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:09:39 +01:00
jgrusewski
74a572a5c4 feat(infra): enable MinIO TLS with self-signed CA for in-cluster HTTPS
Switch all MinIO communication from HTTP to HTTPS across the entire stack:
- MinIO deployment: mount TLS secret, tcpSocket probes, HTTPS init-buckets
- 11 service YAMLs: HTTPS rclone endpoint + CA cert volume mount
- Training job template + train.sh: HTTPS for fetch-binaries and uploader
- CI pipeline (.gitlab-ci.yml): all 7 rclone exports use HTTPS + CA cert
- GitLab runner values: minio-ca-cert ConfigMap volume for CI pods
- Rust: CA cert loading via MINIO_CA_CERT_PATH in training_uploader,
  storage backend, data_acquisition uploader, and k8s_dispatcher
- Cert generation script (infra/scripts/generate-minio-tls.sh)

Fixes training uploader S3 upload failures caused by with_allow_http(false)
connecting to an HTTP endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:56:06 +01:00
jgrusewski
64c068cc3b fix(training): correct nodeSelector to ci-training GPU pool
The job template referenced a non-existent 'gpu-training' pool. The
actual L40S GPU pool in Kapsule is named 'ci-training' (scale-from-zero,
0→1 autoscaling).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:55:58 +01:00
jgrusewski
af08d65a3c fix(monitoring): add gitlab.com/prometheus_* annotations to kube-state-metrics and node-exporter
GitLab's bundled Prometheus only scrapes pods with gitlab.com/prometheus_scrape
annotations, not the standard prometheus.io/* ones. Without this, the
Infrastructure Cockpit shows no data for node/pod/cluster metrics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:40:08 +01:00
jgrusewski
fbd6ebe13a fix(gitlab): disable KAS at global level to stop Sidekiq NotifyGitPushWorker errors
The existing `global.appConfig.gitlab_kas.enabled: false` only affected
the KAS subchart config but was ignored by the chart template that
generates gitlab.yml. Adding `global.kas.enabled: false` properly sets
`gitlab_kas.enabled: false` in gitlab.yml and removes the orphaned
gitlab-kas Service, stopping ~5 GRPC::Unavailable errors per git push.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:35:27 +01:00
jgrusewski
efda8bca94 rename(dashboard): Cockpit -> Infrastructure Cockpit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:33:14 +01:00
jgrusewski
7f2f618e17 fix(dashboards): consolidate cockpits into single folder
Move all 3 cockpit dashboards (Cockpit, Trading Cockpit, Training
Cockpit) into a single "Cockpits" folder. GPU & Training Jobs moved
to Infrastructure. 4 folders total: Cockpits, Operations,
Infrastructure, CI-CD.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:29:44 +01:00
jgrusewski
02c9ec09a9 fix(dashboards): remove Foxhunt prefix from titles, clean folder names
Strip "Foxhunt - " prefix from all dashboard titles since the folder
structure already provides context. Use clean folder names without
slashes (Trading, Training, Operations, Infrastructure, CI-CD) and
per-folder provisioning providers to prevent duplicate folder creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:21:52 +01:00
jgrusewski
1491404fd0 fix(dashboards): exclude infra containers from Loki ERROR queries
Dashboard Loki queries used naive `|= "ERROR"` string matching which
created a self-referential feedback loop: Loki and Grafana log query
execution text containing "ERROR" at INFO level, inflating the error
count by ~19/min with phantom matches.

Add `container!~"loki|grafana|grafana-sc-dashboard|prometheus-server"`
filter to all 11 affected queries across 4 dashboards (cockpit,
overview, logs, services).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:14:30 +01:00
jgrusewski
8346eae948 refactor(dashboards): reorganize into 5 logical folders
Replaces single "Foxhunt" folder with Trading, Training, Operations,
Infrastructure, and CI/CD groupings. Updates ConfigMap definitions in
import.sh and Grafana Helm values to use foldersFromFilesStructure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:05:05 +01:00
jgrusewski
1c2985d1ee infra: add pushgateway scrape config to Prometheus
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:31:38 +01:00
jgrusewski
4611ab97f3 infra: add Prometheus Pushgateway for training job metrics
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:31:37 +01:00
jgrusewski
38832661ee infra(web-gateway): add metrics port 9098 and prometheus scrape annotations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:12:17 +01:00
jgrusewski
7384bd4c41 fix(dashboard): use real metric names in training cockpit
Replace 28 placeholder PromQL expressions with real metric names:
- Active Jobs: kube_job_status_active from kube-state-metrics
- Training Progress: foxhunt_training_epoch_loss, current_epoch, etc.
- GPU Resources: DCGM_FI_DEV_GPU_UTIL/FB_USED/GPU_TEMP/POWER_USAGE
- Model Quality: foxhunt_training_eval_accuracy/f1/precision/recall
- Checkpoints: foxhunt_training_checkpoint_saves/failures/duration/size
- Data Pipeline: foxhunt_training_batches_processed, data_load_seconds
- Errors: foxhunt_training_nan_detected/gradient_explosion/feature_errors
- Job History: kube_job_complete_time/start_time for duration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:09:38 +01:00
jgrusewski
58c0f0ebc9 fix(dashboard): use real Tempo metric names in traces dashboard
Replace placeholder metric names (traces_spanmetrics_calls_total,
traces_spanmetrics_latency_*) with real Tempo metrics
(tempo_distributor_spans_received_total, tempo_spanmetrics_latency_*).
Switch Recent Traces panel from nativeSearch to TraceQL query.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:08:41 +01:00
jgrusewski
430b098f2c fix(dashboard): use real metric names in trading cockpit
Replace all placeholder PromQL expressions with real metric names
that match actual Prometheus metrics emitted by the trading system.
Add $model, $symbol, and $service template variables for filtering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:08:30 +01:00
jgrusewski
56ca1fb083 fix(dashboard): use real Tempo metrics in cockpit trace health row
Replace traces_spanmetrics_calls_total with tempo_distributor_spans_received_total
in all 3 Trace Health panels (Spans/sec, Trace Error Rate, Spans/sec by Service).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:05:17 +01:00
jgrusewski
fcf9ec3ba5 fix(grafana): add folder annotations to dashboard ConfigMaps
The Grafana sidecar supports grafana_folder annotations to place
dashboards in specific folders. Without this, all provisioned
dashboards land in the General folder. Add Foxhunt/Infrastructure/CI-CD
folder mapping to both CI pipeline and import.sh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:33:56 +01:00
jgrusewski
1c4ab071ae fix(infra): add http:// scheme to MinIO endpoints, harden initContainer fallback
Two bugs found during validation:

1. rclone defaults to HTTPS when endpoint has no scheme — MinIO serves
   plain HTTP. All RCLONE_S3_ENDPOINT values now include http:// prefix.

2. rclone copyto returns exit 0 for non-existent S3 keys (empty bucket).
   initContainers crashed on chmod of missing file instead of falling
   through to PVC cache. Added `&& [ -f /binaries/$SERVICE ]` guard.

Also: deploy stage uses `kubectl apply -k` (not -f) for minio/ dir
to properly handle kustomization.yaml.

Deleted stale s3-credentials secret from cluster.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:32:38 +01:00
jgrusewski
995b46a680 feat(infra): migrate binary storage from Scaleway S3 to in-cluster MinIO
Move all compiled binary uploads/downloads from public Scaleway S3 to
MinIO running inside Kapsule. Keeps proprietary binaries and trained
models off the public internet.

- CI compile/upload jobs: Scaleway → MinIO endpoint + credentials
- train.sh: all 3 rclone blocks → RCLONE_CONFIG_MINIO_*
- Deploy stage: apply MinIO manifests + wait for readiness before rollout
- Add infra/k8s/minio/ (Deployment, Service, Secret, PVC, init-buckets Job)
- Update s3-credentials.secret.example → minio-credentials format

IaC Terragrunt jobs and SCW registry pulls intentionally unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:19:39 +01:00
jgrusewski
82b32394fa feat(dashboards): add Trading, Training, and Traces cockpit dashboards
- foxhunt-trading-cockpit.json: 22 panels covering signal quality,
  execution, risk, ML model health, and latency
- foxhunt-training-cockpit.json: 36 panels covering active jobs,
  training progress, GPU resources, model quality, checkpoints,
  data pipeline, errors, and job history
- foxhunt-traces.json: 12 panels with service map, trace search,
  latency by service, and error rate from Tempo
- foxhunt-cockpit.json: added Trace Health row (spans/sec, error rate,
  spans by service) and DS_TEMPO datasource input
- import.sh: added 3 new dashboards to ConfigMap group and API fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:00:54 +01:00
jgrusewski
033eed1526 feat(infra): add Prometheus scrape annotations to all service deployments
Enable GitLab Prometheus to auto-discover and scrape metrics from all
foxhunt pods by adding gitlab.com/prometheus_scrape annotations to the
pod template metadata of 9 service deployments and the training job
template.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:42:17 +01:00
jgrusewski
1aef51f99b fix(stubs): implement 15 production stubs, fix routing, delete placeholders
Web-gateway routing:
- Point TRADING_SERVICE_URL at api-gateway (proto mismatch fix)
  Web-gateway uses foxhunt.tli.TradingService proto but was connecting
  directly to trading-service which implements trading.TradingService.
  api-gateway already proxies Subscribe* → Stream* correctly.

GitLab KAS:
- Disable gitlab_kas in appConfig to stop sidekiq NotifyGitPushWorker
  errors (KAS pod was already disabled but Rails still tried to connect)

Trading service monitoring (3 stubs → real):
- AcknowledgeAlert: real alert lookup + state mutation in shared store
- GetActiveAlerts: returns actual active alerts from in-memory store
- StreamAlerts: now persists generated alerts (capped at 1000 entries)

Trading service ML streams (2 stubs → real):
- StreamModelMetrics: emits real inference_count, error_count, latency
  per model every N seconds from the RuntimeModelInfo registry
- StreamSignalStrength: emits per-symbol signal aggregation from model
  ensemble weights and latency confidence

Backtesting service:
- stop_backtest: real CancellationToken cancellation (was no-op)
  Tokens stored per-backtest, execute_backtest wraps strategy call
  in tokio::select! for immediate cancellation

Deleted 7 empty placeholder files:
- 4 Wave D regime stubs (dynamic_stops, ensemble, performance_tracker,
  position_sizer) — comment-only files, never wired
- 2 Wave 3 feature stubs (microstructure, statistical)
- 1 PPO stub (unified_ppo.rs — empty struct definitions)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:47:31 +01:00
jgrusewski
8ee1f810e6 fix(production): resolve all runtime errors and add CI migration automation
- Add ohlcv_bars table migration (050) for trading_service prediction loop
- Fix kube-state-metrics RBAC: add admissionregistration.k8s.io and
  certificates.k8s.io API groups to suppress forbidden errors
- Fix web-gateway gRPC stream reconnect: detect Unimplemented via both
  status code and error message text (proxy may remap codes)
- Add automated migration step to CI deploy pipeline with tracking table
  (_applied_migrations) so migrations are applied before service rollouts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:26:43 +01:00
jgrusewski
a1c104718a fix(monitoring): import.sh deploys via ConfigMaps, API fallback
Grafana dashboards are provisioned via sidecar ConfigMaps (label
grafana_dashboard=1), making the API endpoint reject overwrites. The
import script now resolves ${DS_*} variables and deploys via kubectl
ConfigMap updates with automatic Grafana restart. Falls back to API
import when kubectl is unavailable or SKIP_CONFIGMAP=1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:14:18 +01:00
jgrusewski
33b4020e06 feat(monitoring): add cockpit dashboard, migrate all dashboards to dynamic datasources
Add foxhunt-cockpit.json — single-page overview with 7 rows (health bar,
service status, resources, GPU/training, restarts/network, errors, live
logs) pulling critical signals from all domain dashboards.

Migrate all 10 dashboards from hardcoded datasource UIDs to ${DS_PROMETHEUS},
${DS_LOKI}, ${DS_TEMPO} variables with __inputs sections for portable import.
Update import.sh to auto-detect datasource UIDs from Grafana API at deploy
time, using /api/dashboards/import endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:04:42 +01:00
jgrusewski
6b94045bcd fix(observability): switch to containerd stdout logging, fix stream retry
- Disable file logging in init_observability — use console-only (stdout).
  Containerd captures stdout, Promtail ships to Loki. Eliminates
  "Failed to create log directory: Permission denied" errors on 3 services.
- Remove LOG_DIR env vars and /app/logs emptyDir volumes from 5 deployments.
- Add OTEL_EXPORTER_OTLP_ENDPOINT=tempo to 5 services that were missing it
  (api-gateway, web-gateway, data-acquisition, trading-agent, broker-gateway).
- Make OTLP tracing init non-fatal — services degrade gracefully if Tempo is
  unavailable instead of failing entire observability stack.
- Stop web-gateway gRPC stream retry on Unimplemented status. When trading-service
  doesn't implement streaming endpoints, log once and stop instead of retrying
  every 60s indefinitely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:49:57 +01:00
jgrusewski
48316d6874 feat(infra): add api.fxhnt.ai DNS + gRPC reverse proxy for API Gateway
Add nginx server block for api.fxhnt.ai with grpc_pass to the
api-gateway ClusterIP service. Add Scaleway DNS A record via Terraform
module. Fix fxt gRPC client to enable TLS when connecting to https://
endpoints (tonic requires explicit ClientTlsConfig).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:41:55 +01:00
jgrusewski
3bdefe86d5 feat(monitoring): production dashboards, remove Cockpit, add Kapsule logs
- Remove Cockpit remote_write from GitLab Prometheus (all metrics local)
- Uninstall k8s-monitoring Helm (Alloy no longer pushes to Cockpit)
- Deploy standalone node-exporter DaemonSet + kube-state-metrics
- Add 10 extra Prometheus scrape configs: node-exporter, kube-state-metrics,
  kubelet, cadvisor, DCGM GPU, foxhunt services, Loki, Tempo, Promtail,
  prometheus.io annotated pods
- Provision 9 Grafana dashboards via sidecar (ConfigMap-based):
  overview, services, GPU/training, infrastructure, logs, CI/CD pipelines,
  cluster overview, GPU overview, GitLab services
- Expand Promtail to ingest kube-system + GitLab runner + node-level logs
- Add dashboard.fxhnt.ai DNS record + nginx routing to Grafana
- Update CI deploy job to apply new monitoring manifests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:20:32 +01:00
jgrusewski
6c4482a5af feat(monitoring): deploy Loki + Tempo + Promtail observability stack
- Loki (3.4.2): log aggregation on gitlab node, 7-day retention, TSDB storage
- Tempo (2.7.1): OTLP trace receiver on gitlab node, 7-day retention
- Promtail (3.4.2): DaemonSet log shipper with K8s pod discovery + RBAC
- Grafana datasources: Prometheus + Loki + Tempo with trace-to-log correlation
- Services: OTEL_EXPORTER_OTLP_ENDPOINT=http://tempo:4317 on ml-training,
  trading, backtesting services
- CI deploy job: applies monitoring manifests alongside service deployments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:32:01 +01:00
jgrusewski
ada33cf181 fix(observability): use LOG_DIR env for file logging, add RBAC for K8s job dispatch
- init_observability now reads LOG_DIR env var for log directory (falls back
  to relative logs/ path). Gracefully disables file logging if directory
  cannot be created instead of failing the entire observability init.
- Add ServiceAccount, Role, and RoleBinding for ml-training-service to
  create/get/list/watch/delete batch/v1 Jobs (K8s training dispatch).
- Add LOG_DIR=/app/logs env to ml-training-service, trading-service, and
  backtesting-service deployment YAMLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:21:13 +01:00
jgrusewski
cd8a45d8a8 fix(gpu): wire PPO GPU experience collection, fix debug log levels, increase hyperopt deadline
- Wire GPU experience collection into PPO hyperopt adapter with CPU fallback
  (ensure_gpu_data, gpu_collect_trajectories, batch-to-trajectory converter)
- Downgrade 6 ERROR-level debug logs to debug!() in DQN hyperopt adapter
- Increase hyperopt activeDeadlineSeconds from 1h to 6h (job-template + train.sh)
- Mark 3 data-dependent real_data_loader tests as #[ignore]
- Fix 4 clippy map_or → is_none_or warnings in trading_service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:58:16 +01:00
jgrusewski
64d57e7454 fix(infra): RWO PVC strategy, probe fixes, deploy hardening
- All services: maxSurge=0, maxUnavailable=1 (ReadWriteOnce PVCs
  deadlock with maxSurge=1 — new pod can't attach volume while old
  pod still holds it)
- ml-training-service: switch httpGet /health:8080 to tcpSocket:50053
  (service crashes on log dir permission, never binds health port)
- GPU overlays: same strategy and probe fixes
- job-template.yaml: use generateName instead of placeholder name
  (training-MODEL-TIMESTAMP fails k8s RFC 1123 validation)
- deploy job: increase rollout timeout 120s → 300s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:50:53 +01:00
jgrusewski
e58ce4f585 fix(ci): halve CPU requests for parallel compilation on single node
Scaleway quota limits POP2-32C-128G to 1 instance. Reduce each compile
job from 28→14 CPUs so compile-services and compile-training run in
parallel on the same 32-vCPU node instead of sequentially.

Also fix data-acquisition-service health probe: service doesn't implement
gRPC health protocol, switch to tcpSocket probe on port 50057.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:12:34 +01:00
jgrusewski
f5b836f98f fix(infra): increase data-acquisition-service memory limit to 1Gi
Was OOMKilled at 512Mi (exit code 137). Increased request to 256Mi
and limit to 1Gi.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:57:36 +01:00
jgrusewski
5a03e41ee6 fix(infra): run initContainer as root for PVC cache write access
The foxhunt-runtime base image runs as uid 1000 (foxhunt user), but
new PVC volumes are owned by root. The initContainer needs root to
write the cached binary to the PVC. Main container still runs as
foxhunt (non-root) for security.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:47:50 +01:00
jgrusewski
23ccbf1c66 fix(infra): increase binary cache PVCs from 500Mi to 1Gi
Scaleway block storage minimum volume size is 1Gi. The 500Mi PVCs
were stuck in Pending state, blocking all service pod scheduling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:45:16 +01:00
jgrusewski
a36cee8628 infra: update GPU overlay deployments with S3 binary fetch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:12:07 +01:00
jgrusewski
6288404c69 infra: update all service deployments with S3 binary fetch initContainer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:10:33 +01:00
jgrusewski
3d3083879a infra: update image-prepuller to cache foxhunt-training-runtime
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:10:16 +01:00
jgrusewski
def4f56d92 infra: update training job template with S3 binary fetch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:10:04 +01:00