SET lastcommit = COALESCE(?, lastcommit), -- derived, not carried
Root cause. Every tick is supposed to end in one metadata UPDATE board SET last_commit = …. On DuckDB boards, the work tick path derived last_commit from the repo and wrote it — but the idle path returned before the UPDATE, and the audit path ran SET last_commit = last_commit (carry-forward). Both left the stored hash frozen at whatever commit had last been processed, so board.last_commit drifted from repo HEAD (stale d81a070 vs. true HEAD 63f9055 in tick #159).
Fix (part 1). Derive last_commit fresh from git log -1 --format=%H at UPDATE time and hoist the metadata UPDATE to the unconditional tail of every tick. No path can skip it, no path carries forward a possibly-stale value, and the row self-heals on the next tick:
def git_head(repo: Path) -> str | None:
"""Full 40-char hash of HEAD, one line, no decoration."""
try:
out = subprocess.run(
["git", "-C", str(repo), "log", "-1", "--format=%H"],
check=True, capture_output=True, text=True,
).stdout
except subprocess.CalledProcessError:
return None # repo has no commits yet
return out.strip() or None
def tick(con, repo: Path, tick_type: str, now=None, head_provider=None):
now = now or datetime.now(timezone.utc).replace(tzinfo=None)
head = (head_provider or git_head)(repo) # derive ONCE
if tick_type == "work":
_process_new_commits(con, head)
elif tick_type == "audit":
audit_due_cycle_ticks(con, now)
_run_due_audits(con, now)
# idle: nothing — falls through to the UPDATE below, by design
con.execute( # FIX: unconditional tail
"""
UPDATE board
SET last_commit = COALESCE(?, last_commit), -- derived, not carried
tick_count = tick_count + 1,
updated_at = ?
WHERE id = ?
""",
[head, now, BOARD_ID])
return head
COALESCE keeps an empty (zero-commit) repo from crashing or clobbering the row.
Fix (part 2). NEVER-DONE audit due-cycle ticks for 14-point sweep / foreman-direct were gated on a non-empty board, so an audit whose fixture lapsed on an empty board never re-ticked. The edge case — board empty ∧ fixture overdue — now ticks the due-cycle counter:
NEVER_DONE_TICK_KINDS = frozenset({"14-point sweep", "foreman-direct"})
def audit_due_cycle_ticks(con, now):
empty = board_empty(con)
for audit_id, kind, status, fixture_due, due_cycle in con.execute(
"SELECT id, kind, status, fixture_due, due_cycle FROM audits"
).fetchall():
fixture_overdue = fixture_due is not None and now > fixture_due
if (status == "NEVER-DONE"
and kind in NEVER_DONE_TICK_KINDS
and empty and fixture_overdue): # FIXED edge case
con.execute(
"UPDATE audits SET due_cycle = due_cycle - 1 WHERE id = ?",
[audit_id])
Verified against real DuckDB 1.5.5 (in-memory) and real git 2.53.0 repos. `pytest`: **12 passed in 0.45s**. Tests include buggy-path control assertions, so the suite fails if the fix is reverted.
- `test_git_head_derivation_matches_rev_parse` — `git log -1 --format=%H` output is a 40-char hash equal to `git rev-parse HEAD`.
- `test_idle_tick_derives_fresh_last_commit` — repo advances past board's last_commit; fixed idle tick sets `last_commit == HEAD`, `tick_count` incremented; buggy control keeps the stale hash.
- `test_audit_tick_derives_fresh_last_commit` — same for audit ticks (buggy `SET last_commit = last_commit` stays stale).
- `test_tick159_incident_correction_d81a070_to_63f9055` — board seeded with stale `d81a070…`, `tick_count=158`; fixed tick #159 corrects row to `63f9055…`, `tick_count=159`; buggy control still carries `d81a070…`.
- `test_work_tick_still_derives_head` — work path unchanged.
- `test_empty_repo_does_not_crash_and_keeps_value` — zero-commit repo: no crash, `COALESCE` preserves the row.
- `test_never_done_sweep_ticks_on_empty_board_overdue_fixture` — empty board + overdue fixture: `14-point sweep` NEVER-DONE `due_cycle 3→2` with the fix; buggy gate leaves it at 3.
- `test_never_done_foreman_direct_also_ticks` — same edge case for `foreman-direct`.
- Guard tests — `test_no_tick_when_board_not_empty`, `test_no_tick_when_fixture_not_overdue`, `test_no_tick_for_non_sweep_or_done_audits` (DONE status / non-sweep kind untouched), and `test_never_done_ticks_accumulate_to_due` (2 ticks drive `due_cycle→0`, audit runs, status → `DONE`).
Direct transcript: fixed tick #159 → `('63f9055…', 159)`; buggy → `('d81a070…', 159)`; sweep `due_cycle` after audit tick on empty board with overdue fixture → `(2, 'NEVER-DONE')`.{"model": "deepseek-v4-flash", "problem_class": "duckdb-board-stale-last-commit", "result": "passed", "tests": 12}