"""ORCH-019 (TC-15) — additive, idempotent tasks.track migration. The bug-fast-track stores the task type in an additive ``tasks.track`` column (``TEXT DEFAULT 'full'``) created via ``_ensure_column`` (idempotent). A repeated ``init_db`` must not crash, existing rows must default to ``'full'``, and the helpers must round-trip. """ import os import tempfile import pytest os.environ.setdefault( "ORCH_DB_PATH", os.path.join(tempfile.gettempdir(), "test_db_migrations.db") ) os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token") os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token") import src.db as db # noqa: E402 from src.db import init_db, get_db, set_task_track, get_task_track # noqa: E402 @pytest.fixture(autouse=True) def fresh_db(tmp_path, monkeypatch): dbfile = tmp_path / "m.db" monkeypatch.setattr(db.settings, "db_path", str(dbfile)) init_db() yield def _columns(table): conn = get_db() try: return [r[1] for r in conn.execute(f"PRAGMA table_info({table})").fetchall()] finally: conn.close() def test_tc15_track_column_present_with_default(): assert "track" in _columns("tasks") # A row inserted WITHOUT track gets the DEFAULT 'full'. conn = get_db() conn.execute( "INSERT INTO tasks (plane_id, work_item_id, repo, branch, stage, title) " "VALUES ('p','ORCH-1','orchestrator','feature/x','analysis','t')" ) conn.commit() row = conn.execute("SELECT track FROM tasks WHERE work_item_id='ORCH-1'").fetchone() conn.close() assert row["track"] == "full" def test_tc15_init_db_idempotent(): # Running init_db again is a no-op on the existing column (no crash). init_db() init_db() assert "track" in _columns("tasks") def test_tc15_helpers_round_trip(): conn = get_db() cur = conn.execute( "INSERT INTO tasks (plane_id, work_item_id, repo, branch, stage, title) " "VALUES ('p2','ORCH-2','orchestrator','feature/y','analysis','t')" ) tid = cur.lastrowid conn.commit() conn.close() assert get_task_track(tid) == "full" # default set_task_track(tid, "bug") assert get_task_track(tid) == "bug" set_task_track(tid, "full") assert get_task_track(tid) == "full" def test_tc15_get_task_track_missing_row_failsafe(): # Unknown task id -> 'full' (fail-safe -> full cycle), never raises. assert get_task_track(999999) == "full"