fix: clear gate-derived rows on step rerun (idempotency)
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""step 重跑幂等:gate 派生行必须随 step 清理,否则崩溃重跑累积重复。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from app.harness.runner import _clear_step_rows
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _mk_db(tmp_path: Path) -> Path:
|
||||
"""构造含 rollout 行、gate 派生行、他 step 行与前缀陷阱行的最小 harness.db。
|
||||
|
||||
参数:
|
||||
tmp_path: pytest 临时目录。
|
||||
|
||||
返回:
|
||||
harness.db 路径。
|
||||
"""
|
||||
db = tmp_path / "harness.db"
|
||||
conn = sqlite3.connect(db)
|
||||
conn.execute("CREATE TABLE predictions (run_id TEXT, question_id TEXT)")
|
||||
conn.execute("CREATE TABLE traces (run_id TEXT, question_id TEXT)")
|
||||
conn.execute("CREATE TABLE gate_evidence (run_id TEXT, epoch INTEGER, step INTEGER)")
|
||||
conn.execute("CREATE TABLE quadrant_pair (run_id TEXT, epoch INTEGER, step INTEGER)")
|
||||
rows = [
|
||||
("infer_adhoc_e1_s0", "q1"), # rollout 行
|
||||
("infer_adhoc_e1_s0_gate_action-reasoning_base", "q2"), # gate base 臂
|
||||
("infer_adhoc_e1_s0_gate_action-reasoning_cand", "q3"), # gate cand 臂
|
||||
("infer_adhoc_e1_s1", "q4"), # 其他 step,不许误删
|
||||
("infer_adhoc_e1_s10_gate_x_base", "q5"), # s10 前缀陷阱,不许误删
|
||||
]
|
||||
conn.executemany("INSERT INTO predictions VALUES (?, ?)", rows)
|
||||
conn.executemany("INSERT INTO traces VALUES (?, ?)", rows)
|
||||
conn.execute("INSERT INTO gate_evidence VALUES ('infer_adhoc', 1, 0)")
|
||||
conn.execute("INSERT INTO gate_evidence VALUES ('infer_adhoc', 1, 1)")
|
||||
conn.execute("INSERT INTO quadrant_pair VALUES ('infer_adhoc', 1, 0)")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return db
|
||||
|
||||
|
||||
def test_clear_step_rows_removes_rollout_and_gate_rows(tmp_path) -> None:
|
||||
"""rollout 行 + 本 step 全部 gate 派生行被清;他 step 与 s10 前缀陷阱不动。"""
|
||||
db = _mk_db(tmp_path)
|
||||
_clear_step_rows(str(db), baseline_run_id="infer_adhoc", epoch=1, step=0)
|
||||
conn = sqlite3.connect(db)
|
||||
left = {r[0] for r in conn.execute("SELECT run_id FROM predictions")}
|
||||
assert left == {"infer_adhoc_e1_s1", "infer_adhoc_e1_s10_gate_x_base"}
|
||||
left_t = {r[0] for r in conn.execute("SELECT run_id FROM traces")}
|
||||
assert left_t == left
|
||||
ge = list(conn.execute("SELECT step FROM gate_evidence"))
|
||||
assert ge == [(1,)] # 只剩 step=1 的行
|
||||
assert list(conn.execute("SELECT COUNT(*) FROM quadrant_pair"))[0][0] == 0
|
||||
conn.close()
|
||||
|
||||
|
||||
def test_clear_step_rows_missing_tables_is_noop(tmp_path) -> None:
|
||||
"""gate_evidence/quadrant_pair 表尚未建(首个 step)时不报错。"""
|
||||
db = tmp_path / "harness.db"
|
||||
conn = sqlite3.connect(db)
|
||||
conn.execute("CREATE TABLE predictions (run_id TEXT)")
|
||||
conn.execute("CREATE TABLE traces (run_id TEXT)")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
_clear_step_rows(str(db), baseline_run_id="infer_adhoc", epoch=1, step=0)
|
||||
Reference in New Issue
Block a user