diff --git a/app/harness/log.py b/app/harness/log.py index 7231abe..4cab15f 100644 --- a/app/harness/log.py +++ b/app/harness/log.py @@ -52,6 +52,9 @@ class HarnessLog: run_id: 本次运行的唯一标识。 git_sha: 代码版本,默认自动获取。 config_snapshot: 本次运行的配置快照。 + register_run: 是否注册运行(upsert _runs + 退出时同步 status)。默认 True; + 只读查询已有 run(如基线预测回读)时传 False,避免把该 run 的 + started_at/config/status 改写、把基线元数据污染成本次进程的运行状态。 """ def __init__( @@ -60,27 +63,33 @@ class HarnessLog: run_id: str, git_sha: str | None = None, config_snapshot: dict[str, Any] | None = None, + *, + register_run: bool = True, ) -> None: self._run_id = run_id + self._register_run = register_run Path(db_path).parent.mkdir(parents=True, exist_ok=True) self._conn = sqlite3.connect(db_path, check_same_thread=False) self._lock = threading.Lock() self._conn.row_factory = sqlite3.Row self._conn.execute("PRAGMA journal_mode=WAL") self._init_fixed_tables() - resolved_sha = git_sha or _get_git_sha() - config_json = json.dumps(config_snapshot, ensure_ascii=False) if config_snapshot else None - self._conn.execute( - "INSERT INTO _runs" - " (run_id, git_sha, started_at, config, status)" - " VALUES (?, ?, ?, ?, ?)" - " ON CONFLICT(run_id) DO UPDATE SET" - " started_at=excluded.started_at," - " config=excluded.config," - " status=excluded.status", - (run_id, resolved_sha, _now_iso(), config_json, "running"), - ) - self._conn.commit() + if register_run: + resolved_sha = git_sha or _get_git_sha() + config_json = ( + json.dumps(config_snapshot, ensure_ascii=False) if config_snapshot else None + ) + self._conn.execute( + "INSERT INTO _runs" + " (run_id, git_sha, started_at, config, status)" + " VALUES (?, ?, ?, ?, ?)" + " ON CONFLICT(run_id) DO UPDATE SET" + " started_at=excluded.started_at," + " config=excluded.config," + " status=excluded.status", + (run_id, resolved_sha, _now_iso(), config_json, "running"), + ) + self._conn.commit() def _init_fixed_tables(self) -> None: """创建 _runs 和 _events 固定表。""" @@ -217,13 +226,18 @@ class HarnessLog: 参数: status: 最终状态,"completed" 或 "failed"。 + + 关键实现: + register_run=False(只读打开)时跳过 status 更新,仅关闭连接, + 避免只读回读把已有 run 的 finished_at/status 改写。 """ with self._lock: - self._conn.execute( - "UPDATE _runs SET finished_at = ?, status = ? WHERE run_id = ?", - (_now_iso(), status, self._run_id), - ) - self._conn.commit() + if self._register_run: + self._conn.execute( + "UPDATE _runs SET finished_at = ?, status = ? WHERE run_id = ?", + (_now_iso(), status, self._run_id), + ) + self._conn.commit() self._conn.close() def __enter__(self) -> HarnessLog: diff --git a/app/harness/pools.py b/app/harness/pools.py index 89763de..1606c28 100644 --- a/app/harness/pools.py +++ b/app/harness/pools.py @@ -797,7 +797,9 @@ def build_or_load_pools( # 增量构建新类别 paths = resolve_paths(config.workspace_dir) questions = load_benchmark(paths.questions_dir) - with HarnessLog(str(db_path), baseline_run_id) as hlog: + with HarnessLog( + str(db_path), baseline_run_id, register_run=False + ) as hlog: rows = hlog.query( "SELECT question_id, prediction, answer " "FROM predictions WHERE run_id=?", @@ -872,7 +874,7 @@ def build_or_load_pools( # ── 全新构建 ── paths = resolve_paths(config.workspace_dir) questions = load_benchmark(paths.questions_dir) - with HarnessLog(str(db_path), baseline_run_id) as hlog: + with HarnessLog(str(db_path), baseline_run_id, register_run=False) as hlog: rows = hlog.query( "SELECT question_id, prediction, answer FROM predictions WHERE run_id=?", (baseline_run_id,), diff --git a/app/harness/runner.py b/app/harness/runner.py index 463f52e..f468e12 100644 --- a/app/harness/runner.py +++ b/app/harness/runner.py @@ -920,7 +920,9 @@ class Runner: self._gate_units_by_id: dict[str, QuestionUnit] = { u.unit_id: u for u in build_units(questions) } - with HarnessLog(str(self._paths.db_path), pools.baseline_run_id) as log: + with HarnessLog( + str(self._paths.db_path), pools.baseline_run_id, register_run=False + ) as log: rows = log.query( "SELECT question_id, prediction, answer FROM predictions WHERE run_id=?", (pools.baseline_run_id,), diff --git a/tests/unit/test_harness_log.py b/tests/unit/test_harness_log.py index 5e90855..35a0e84 100644 --- a/tests/unit/test_harness_log.py +++ b/tests/unit/test_harness_log.py @@ -215,6 +215,30 @@ class TestHarnessLogUpsert: rows = log3.query("SELECT COUNT(*) as cnt FROM _runs WHERE run_id='run_1'") assert rows[0]["cnt"] == 1 + def test_register_run_false_skips_upsert(self, tmp_path: Path) -> None: + """register_run=False 时只读打开不改写已有 _runs 行(started_at/status 不变)。""" + db = str(tmp_path / "h.db") + + def _read_run_row(run_id: str) -> dict: + # 用 register_run=False 只读,避免读取本身污染 _runs + with HarnessLog(db, run_id, register_run=False) as log: + rows = log.query( + "SELECT started_at, status FROM _runs WHERE run_id=?", (run_id,) + ) + return rows[0] + + with HarnessLog(db, "r1"): + pass # 初次注册 + 正常退出置 completed + row0 = _read_run_row("r1") + + time.sleep(0.02) + with HarnessLog(db, "r1", register_run=False) as log: + log.query("SELECT 1") # 只读 + row1 = _read_run_row("r1") + + assert row1["started_at"] == row0["started_at"] + assert row1["status"] == row0["status"] + # =========================================================================== # RunLogImpl 测试