diff --git a/.github/workflows/reusable-drift-check.yml b/.github/workflows/reusable-drift-check.yml index ea9a6f4..76f824c 100644 --- a/.github/workflows/reusable-drift-check.yml +++ b/.github/workflows/reusable-drift-check.yml @@ -62,6 +62,14 @@ on: required: false type: string default: "" + live_stream_id: + description: >- + Optional PerformanceStore live_runs stream id for monitor. When empty, + monitor uses preflight/research return CSVs only (not paper/live account + PnL). Set only for a verified account-bound stream. + required: false + type: string + default: "" secrets: codex_audit_service_url: required: false @@ -86,6 +94,7 @@ jobs: LIFECYCLE_PERFORMANCE_BUCKET: ${{ inputs.lifecycle_performance_bucket || vars.LIFECYCLE_PERFORMANCE_BUCKET || '' }} LIFECYCLE_LOCAL_ROOT: ${{ github.workspace }}/data/lifecycle_store LIFECYCLE_STRATEGY_PROFILE: ${{ inputs.strategy_profile }} + LIFECYCLE_LIVE_STREAM_ID: ${{ inputs.live_stream_id }} steps: - name: Validate trusted caller @@ -258,10 +267,15 @@ jobs: shell: bash run: | set -euo pipefail + # Without LIFECYCLE_LIVE_STREAM_ID, monitor reads preflight/research + # portfolio_and_tracker_returns.csv proxies — not paper/live account PnL. lifecycle_args=() if [ -n "${LIFECYCLE_STRATEGY_PROFILE:-}" ]; then lifecycle_args+=(--strategy "${LIFECYCLE_STRATEGY_PROFILE}") fi + if [ -n "${LIFECYCLE_LIVE_STREAM_ID:-}" ]; then + lifecycle_args+=(--live-stream-id "${LIFECYCLE_LIVE_STREAM_ID}") + fi quant-lifecycle monitor --domain ${{ inputs.strategy_domain }} "${lifecycle_args[@]}" - name: Validate lifecycle prerequisites diff --git a/tests/test_reusable_drift_workflow.py b/tests/test_reusable_drift_workflow.py index 4396ac5..630d7e7 100644 --- a/tests/test_reusable_drift_workflow.py +++ b/tests/test_reusable_drift_workflow.py @@ -23,6 +23,8 @@ def test_reusable_drift_workflow_enforces_lifecycle_preflight() -> None: assert "caller_pr_head_repository:" in workflow assert "lifecycle_preflight_artifact:" in workflow assert "strategy_profile:" in workflow + assert "live_stream_id:" in workflow + assert "LIFECYCLE_LIVE_STREAM_ID: ${{ inputs.live_stream_id }}" in workflow assert "codex_audit_service_url:" in workflow assert 'python-version: ${{ inputs.python_version }}' in workflow assert "LIFECYCLE_PERFORMANCE_BUCKET: ${{ inputs.lifecycle_performance_bucket || vars.LIFECYCLE_PERFORMANCE_BUCKET || '' }}" in workflow @@ -36,6 +38,8 @@ def test_reusable_drift_workflow_enforces_lifecycle_preflight() -> None: assert "SNAPSHOT_REPOSITORY_TOKEN:" not in workflow assert "LIFECYCLE_STRATEGY_PROFILE: ${{ inputs.strategy_profile }}" in workflow assert 'lifecycle_args+=(--strategy "${LIFECYCLE_STRATEGY_PROFILE}")' in workflow + assert 'lifecycle_args+=(--live-stream-id "${LIFECYCLE_LIVE_STREAM_ID}")' in workflow + assert "not paper/live account PnL" in workflow assert 'quant-lifecycle monitor --domain ${{ inputs.strategy_domain }} "${lifecycle_args[@]}"' in workflow assert 'quant-lifecycle doctor --domain ${{ inputs.strategy_domain }} --require-snapshot --require-backtest --max-freshness-days 7 "${lifecycle_args[@]}"' in workflow assert 'quant-lifecycle drift --domain ${{ inputs.strategy_domain }} --no-alerts "${lifecycle_args[@]}"' in workflow