Wire up the task_runs.last_commit_sha column so it is populated with the
on-main commit SHA whenever a task branch is squash-merged to origin/main.
This enables the waste_detector's abandonment signal
(last_commit_sha IS NULL OR last_commit_sha = '') to accurately
distinguish "ran but produced no commit" from "never ran".
The last_commit_sha column was added to task_runs (Orchestra migration 020)
but is never populated — every row has last_commit_sha = ''. The
waste_detector.scan() already checks for this column and falls back to
1=1 (no commit-sha filter) when the column is absent, which reduces
abandonment detection precision.
The commit SHA is computed by _do_push_main in orchestra/sync.py after a
successful squash-merge or fast-forward merge, stored in the local variable
new_remote. It is not currently returned to the caller or persisted.
orchestra/services.py::ensure_tables adds last_commit_sha TEXT DEFAULT ''task_runs (migration 020).
orchestra/sync.py::push_main returns main_sha (the newrefs/remotes/origin/main SHA) in its success dict.
orchestra/services.py::process_merge_candidate updatestask_runs.last_commit_sha with the returned main_sha after apush_main, using the run_id from the merge_candidates row.
scripts/backfill_task_runs_last_commit_sha.py — idempotent, 30-daylast_commit_sha column exists; skips gracefully if not.task_runs rows (last 30 days, terminal status) wherelast_commit_sha IS NULL OR last_commit_sha = ''.tasks.git_branch, runsgit rev-parse origin/<branch> in the project root to get the current--dry-run (default) and --apply.
reason= field to watchdog).File: orchestra/services.py
In ensure_tables(), after the migration 019 block (around line 465), add:
# Migration 020 — last_commit_sha: on-main SHA from squash-merge step.
if "last_commit_sha" not in task_runs_cols:
cur.execute("ALTER TABLE task_runs ADD COLUMN last_commit_sha TEXT DEFAULT ''")File: orchestra/sync.py
In _do_push_main(), the new_remote variable holds the resulting main SHA
after both the PR-merge path (line ~1740) and the direct-push path. Add it
to all success return dicts:
# In the PR merge success return (line ~1743):
return {
"success": True,
"commits_merged": commits,
"main_sha": new_remote, # ADD THIS
"merge_strategy": "gh_pr_merge",
...
}
# In the direct-push success return (line ~1882):
return {
"success": True,
"commits_merged": commits,
"main_sha": new_remote, # ADD THIS
"message": ...
}Also update push_main() wrapper to pass main_sha through.
File: orchestra/services.py::process_merge_candidate
After a successful push_main (around line 6556), add:
main_sha = result.get("main_sha", "")
if main_sha and row.get("run_id"):
try:
conn.execute(
"UPDATE task_runs SET last_commit_sha = ? "
"WHERE id = ? AND (last_commit_sha IS NULL OR last_commit_sha = '')",
(main_sha, row["run_id"]),
)
conn.commit()
except Exception as e:
logger.warning("Failed to backfill last_commit_sha for run %s: %s",
row["run_id"], e)File: scripts/backfill_task_runs_last_commit_sha.py (new)
Idempotent backfill script. See the script itself for details.
reason= field) — soft dependencyorchestra/services.py::ensure_tables migration 020 must have runtask_runs.last_commit_sha column does not exist in current/home/ubuntu/Orchestra/orchestra.db points to/data/orchestra/orchestra.db which is not mounted in this environment).
waste_detector.py already handles missing column gracefully withhas_commit_sha flag.
Files created:
scripts/backfill_task_runs_last_commit_sha.py — idempotent backfill scriptlast_commit_sha for historical task_runs rows from theorchestra/services.py — add last_commit_sha column in ensure_tables()orchestra/sync.py — return main_sha from push_main()orchestra/services.py::process_merge_candidate — update task_runs after