Forrige commit skrev en CLAUDE.md-invariant om at en betalt test far sin egen opt-in, men gatet bare den NYE testen. test_portfolio_live.py passerer ingen client_factory og er derfor selv en betalt kjoring - den fyrte pa to-variabel-paret fra et bart `uv run pytest`. Invarianten var altsa halvt usann den dagen den ble skrevet, som er nyaktig Fase 3-klassen (en pastand flaten gjor om seg selv uten dekning). MALT etter fiksen, med begge Foundry-vars satt og UTEN PORTFOLIO_LIVE_FULL_RUN: test_foundry_profile_live PASSED (det billige trinnet, med vilje pa to vars) test_portfolio_live SKIPPED (var betalt og ugatet for dette) test_full_run_live SKIPPED Ovrige oppfolgingspunkter fra review: - assert_full_run_contract far ekte type hints (repoets "type hints overalt"; mypy src ser ikke tests/, sa den ville rotnet ubemerket). - Maleprotokollen SS6 far oppsettet STATE peker pa - model-map-formen og de fire export-linjene. Pekeren lovet noe seksjonen ikke hadde. 869 passed / 5 skipped, uendret. ruff+format+mypy rene. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GF7va4cpRiuf79kTzAi3vW
40 lines
1.9 KiB
Python
40 lines
1.9 KiB
Python
"""Fase 3 — GATED live Azure portfolio run (SC7 / SC9).
|
|
|
|
NOT default CI: skips cleanly without a configured Foundry endpoint + deployment. When set,
|
|
``run_portfolio`` fans out over the reference portfolio on the REAL ``azure`` profile (one
|
|
project, hard token-capped per D6). SC9 is unchanged — this arm stays skipped offline.
|
|
|
|
**``PORTFOLIO_LIVE_FULL_RUN`` added 14.08 (økt 40), and the reason is this file, not the new one.**
|
|
This test passes NO ``client_factory``, so it drives the real Azure backend: it is a PAID run, and
|
|
until now it fired on the same two variables as ``test_foundry_profile_live.py``'s one-word probe.
|
|
That is exactly the collapse the new full-run gate was designed to prevent — an operator exporting
|
|
the pair to run the CHEAP rung would have paid for this fan-out too, from a bare ``uv run pytest``.
|
|
The rule the sibling file states must hold for EVERY paid arm, or it is not a rule; leaving this one
|
|
on the two-var pair would have made the CLAUDE.md invariant half-true the day it was written.
|
|
Truthiness, not presence (Fase 4b): an exported-but-empty value must not arm a paid run.
|
|
"""
|
|
|
|
import os
|
|
|
|
import pytest
|
|
|
|
from portfolio_optimiser.run import PortfolioResult, run_portfolio
|
|
|
|
_ENDPOINT = os.environ.get("PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT")
|
|
_DEPLOYMENT = os.environ.get("PORTFOLIO_FOUNDRY_DEPLOYMENT")
|
|
_OPTED_IN = bool(os.environ.get("PORTFOLIO_LIVE_FULL_RUN"))
|
|
_NO_FOUNDRY = not (_ENDPOINT and _DEPLOYMENT and _OPTED_IN)
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
_NO_FOUNDRY,
|
|
reason=(
|
|
"paid fan-out not armed (set PORTFOLIO_LIVE_FULL_RUN=1 alongside "
|
|
"PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT + PORTFOLIO_FOUNDRY_DEPLOYMENT)"
|
|
),
|
|
)
|
|
async def test_portfolio_live_azure_fanout() -> None:
|
|
# No client_factory -> the real AZURE backend is used; hard-capped per D6.
|
|
result = await run_portfolio(["FV42-GSV-E1"], "azure", max_tokens=2000)
|
|
assert isinstance(result, PortfolioResult)
|
|
assert len(result.runs) == 1
|