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:
2026-10-07 13:22:05 +08:00
parent e8902c21e8
commit 45de5e5dff
2 changed files with 67 additions and 0 deletions
+61
View File
@@ -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")