fix(pipeline): 控制台判死接死亡回写——factor_verdict graveyard 分支调 writeback_card_death(复用 T4 降级留痕:失败 stderr+death_writeback_missed 附记不阻断;pipeline_db 与 CLI 同源 env)——D5 回写不再只活在 CLI (审计 #91②) [vps] [no-doc]
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# tests/api/test_routes_pipeline_factors.py
|
||||
"""pipeline 因子评审端点 TDD——#91② 控制台判死回写卡片(D5 对齐 CLI)."""
|
||||
import os
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from sanguo_api.app import create_app
|
||||
from sanguo_api.auth import create_token, set_jwt_config
|
||||
|
||||
from sanguo_portfolio import pipeline_store
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client(tmp_path, monkeypatch):
|
||||
# fixture 逐字对齐 test_routes_pipeline_hypotheses.py 既有范式,另隔离注册表/事件
|
||||
monkeypatch.setenv("SANGUO_PIPELINE_DB", str(tmp_path / "pipeline.db"))
|
||||
monkeypatch.setenv("SANGUO_LLM_API_KEY", "sk-test")
|
||||
monkeypatch.setenv("SANGUO_FACTOR_REGISTRY", str(tmp_path / "reg.yaml"))
|
||||
monkeypatch.setenv("SANGUO_FACTOR_EVENTS", str(tmp_path / "events.jsonl"))
|
||||
set_jwt_config(secret="test", expire_minutes=60)
|
||||
app = create_app(db_path=str(tmp_path / "t.db"), file_dir=None)
|
||||
c = TestClient(app)
|
||||
c.headers.update({"Authorization": f"Bearer {create_token('admin')}"})
|
||||
return c
|
||||
|
||||
|
||||
def _seed_factor_card(client, name="fa_dead"):
|
||||
r = client.post("/api/v1/pipeline/hypotheses", json={
|
||||
"title": "t", "logic": "If a,则 b", "expectedSign": "positive",
|
||||
"falsifiable": "若 a<=0 则证伪", "dataNeeds": ["bars_daily"],
|
||||
"sentence": "s"})
|
||||
hyp = r.json()["item"]["id"] # hyp- 前缀,回写才生效
|
||||
reg = {"factors": {name: {"name": name, "hypothesis": hyp,
|
||||
"status": "assessable", "versions": []}}}
|
||||
with open(os.environ["SANGUO_FACTOR_REGISTRY"], "w", encoding="utf-8") as f:
|
||||
yaml.safe_dump(reg, f, allow_unicode=True)
|
||||
return name, hyp
|
||||
|
||||
|
||||
def test_graveyard_verdict_writes_back_card(client, tmp_path):
|
||||
name, hyp = _seed_factor_card(client)
|
||||
r = client.post(f"/api/v1/pipeline/factors/{name}/verdict",
|
||||
json={"verdict": "graveyard", "note": "ic 崩了"})
|
||||
assert r.status_code == 200 and r.json()["action"] == "graveyard"
|
||||
card = next(c for c in pipeline_store.list_hypotheses(
|
||||
str(tmp_path / "pipeline.db")) if c["id"] == hyp)
|
||||
assert card["state"] == "graveyard"
|
||||
assert card["factorId"] == name
|
||||
assert name in card["deathReason"] and "ic 崩了" in card["deathReason"]
|
||||
|
||||
|
||||
def test_revise_verdict_does_not_write_back(client, tmp_path):
|
||||
name, hyp = _seed_factor_card(client)
|
||||
r = client.post(f"/api/v1/pipeline/factors/{name}/verdict",
|
||||
json={"verdict": "revise", "note": "再看看"})
|
||||
assert r.status_code == 200
|
||||
card = next(c for c in pipeline_store.list_hypotheses(
|
||||
str(tmp_path / "pipeline.db")) if c["id"] == hyp)
|
||||
assert card["state"] != "graveyard" and not card.get("deathReason")
|
||||
Reference in New Issue
Block a user