5.7 KiB
DEB Training Settlement Worker Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Restore automatic DEB training data freshness after the realtime collector/canonical-cache split.
Architecture: Add a dedicated low-frequency training settlement service that runs city analysis for forecast/DEB snapshots and reconciles recent settled actual highs. Keep it separate from the high-frequency observation collector so user-facing realtime updates stay light.
Tech Stack: Python, FastAPI service modules, Docker Compose, pytest, existing update_daily_record() and reconcile_recent_actual_highs() paths.
Task 1: Training Settlement Service
Files:
-
Create:
web/training_settlement_service.py -
Create:
tests/test_training_settlement_service.py -
Step 1: Write the failing service test
def test_training_settlement_cycle_runs_analysis_and_reconciles_supported_cities():
calls = {"analysis": [], "reconcile": []}
def analysis_runner(city):
calls["analysis"].append(city)
return {"city": city, "deb": {"prediction": 31.2}}
def reconciler(city, *, lookback_days):
calls["reconcile"].append((city, lookback_days))
return {"ok": True, "updated": 1}
result = run_training_settlement_cycle(
city_registry={
"shanghai": {"icao": "ZSSS", "settlement_source": "metar"},
"legacy": {"settlement_source": "wunderground"},
},
analysis_runner=analysis_runner,
actual_reconciler=reconciler,
lookback_days=9,
)
assert result["ok"] is True
assert result["processed"] == 1
assert calls["analysis"] == ["shanghai"]
assert calls["reconcile"] == [("shanghai", 9)]
- Step 2: Run the test to verify it fails
Run: python -m pytest tests/test_training_settlement_service.py::test_training_settlement_cycle_runs_analysis_and_reconciles_supported_cities -q
Expected: FAIL because web.training_settlement_service does not exist.
- Step 3: Implement the service
Create run_training_settlement_cycle() with injectable city_registry, analysis_runner, and actual_reconciler. Default analysis runner calls web.analysis_service._analyze(city, force_refresh=False, detail_mode="panel"); default reconciler calls src.analysis.deb_algorithm.reconcile_recent_actual_highs().
- Step 4: Run the test to verify it passes
Run: python -m pytest tests/test_training_settlement_service.py -q
Expected: PASS.
Task 2: Worker Entrypoint And Compose
Files:
-
Create:
web/training_settlement_worker.py -
Modify:
docker-compose.yml -
Modify:
tests/test_deployment_runtime_config.py -
Step 1: Write failing deployment tests
Assert the compose file contains polyweather_training_settlement, command python -m web.training_settlement_worker, role training_settlement, and conservative interval/lookback environment variables.
- Step 2: Run the deployment test to verify it fails
Run: python -m pytest tests/test_deployment_runtime_config.py::test_runtime_compose_splits_realtime_workers -q
Expected: FAIL because the worker service is absent.
- Step 3: Implement worker and compose service
The worker loops run_training_settlement_cycle() every POLYWEATHER_TRAINING_SETTLEMENT_INTERVAL_SEC seconds, with initial delay and lookback from environment.
- Step 4: Run focused tests
Run: python -m pytest tests/test_training_settlement_service.py tests/test_deployment_runtime_config.py -q
Expected: PASS.
Task 3: Stale Monitoring
Files:
-
Modify:
web/diagnostics/health.py -
Modify:
web/services/system_api.py -
Modify:
tests/test_web_observability.py -
Step 1: Write failing observability tests
Assert system status training summaries include stale_days for daily/truth/features, and Prometheus exports stale gauges for training data.
- Step 2: Run focused observability tests to verify failure
Run: python -m pytest tests/test_web_observability.py::test_system_status_includes_training_data tests/test_web_observability.py::test_metrics_endpoint_returns_prometheus_payload_for_ops_admin -q
Expected: FAIL because stale fields/gauges are absent.
- Step 3: Implement stale summary and gauges
Add date-diff calculation against UTC today. Export polyweather_daily_records_stale_days, polyweather_truth_records_stale_days, polyweather_training_features_stale_days, and polyweather_training_data_stale.
- Step 4: Run focused observability tests
Run: python -m pytest tests/test_web_observability.py::test_system_status_includes_training_data tests/test_web_observability.py::test_metrics_endpoint_returns_prometheus_payload_for_ops_admin -q
Expected: PASS.
Task 4: Verification And Backfill
Files:
-
Optional create:
scripts/backfill_training_settlement.py -
Step 1: Run backend checks
Run: python -m ruff check .
Run: python -m pytest tests/test_training_settlement_service.py tests/test_deployment_runtime_config.py tests/test_web_observability.py -q
- Step 2: Run local one-shot cycle
Run: python -m web.training_settlement_worker --once --lookback-days 10 --cities shanghai
Expected: JSON-like log output with ok=True; local DB should get a fresh row for the current local target date if analysis succeeds.
- Step 3: Production note
Missed forecast snapshots from 2026-06-15 to 2026-06-22 cannot be reconstructed honestly unless archived city analysis payloads exist. The worker restores forward automatic samples; actual-high truth can still be reconciled for supported settlement sources.