Do not record a no-op consistency sync as a fix.
A binding put that only refreshes the sync timestamp, a push that reports the remote is already current, and a C-11 skip on a finished workplan are not repairs. Leave those out of FIXES APPLIED so a clean second run stays clean. Assistant: grok Assistant-Session: 01a16071-5425-78d3-80b4-20fe2ee30f0a
This commit is contained in:
parent
64d698e65d
commit
bd6fd62b0a
5 changed files with 130 additions and 10 deletions
|
|
@ -2493,6 +2493,37 @@ def check_repo(
|
|||
return report
|
||||
|
||||
|
||||
def _bindings_already_synced(index: Any, bindings: list[dict[str, Any]]) -> bool:
|
||||
"""True when the hub index already stores each binding's file location."""
|
||||
if not isinstance(index, dict) or "_error" in index:
|
||||
return False
|
||||
workplans = index.get("workplans")
|
||||
if not isinstance(workplans, dict):
|
||||
return False
|
||||
for binding in bindings:
|
||||
current = workplans.get(binding["workplan_id"])
|
||||
if not isinstance(current, dict):
|
||||
return False
|
||||
if current.get("filename") != binding["filename"]:
|
||||
return False
|
||||
if current.get("relative_path") != binding["relative_path"]:
|
||||
return False
|
||||
if bool(current.get("archived")) != bool(binding["archived"]):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _record_push_seal(report: ConsistencyReport, ok: bool, msg: str) -> None:
|
||||
"""Record a push that moved commits. An already-current remote is not a fix."""
|
||||
if not ok:
|
||||
report.fixes_applied.append(f"push WARN: {msg}")
|
||||
return
|
||||
lowered = msg.lower()
|
||||
if "up-to-date" in lowered or "up to date" in lowered:
|
||||
return
|
||||
report.fixes_applied.append(f"push: {msg}")
|
||||
|
||||
|
||||
def _sync_workplan_bindings(
|
||||
api_base: str,
|
||||
repo_slug: str,
|
||||
|
|
@ -2540,10 +2571,16 @@ def _sync_workplan_bindings(
|
|||
bindings.append(binding)
|
||||
if not bindings:
|
||||
return
|
||||
# A timestamp-only binding write is not drift. Skip it when the index
|
||||
# already has the same filename, path, and archive flag. A failed lookup
|
||||
# still falls through to the put.
|
||||
current = _api_get(api_base, "/workplans/index", {"refresh": "true"})
|
||||
if _bindings_already_synced(current, bindings):
|
||||
return
|
||||
result = _api_put(api_base, "/workplans/index/bindings", {"bindings": bindings})
|
||||
if isinstance(result, dict) and "_error" in result:
|
||||
report.fixes_applied.append(f"bindings WARN: {result['_error']}")
|
||||
elif isinstance(result, dict):
|
||||
elif isinstance(result, dict) and int(result.get("updated") or 0) > 0:
|
||||
report.fixes_applied.append(
|
||||
f"bindings: synced {result.get('updated', 0)}/{result.get('received', len(bindings))}"
|
||||
)
|
||||
|
|
@ -4172,9 +4209,9 @@ def fix_repo(
|
|||
# Skip creating tasks for finished workstreams — the workstream is
|
||||
# done/archived so unlinked tasks are stale file artefacts, not gaps.
|
||||
if normalise_workstream_status(ws_status) in CLOSED_WORKSTREAM_STATUSES:
|
||||
report.fixes_applied.append(
|
||||
f"C-11 skipped: task '{t_id}' in {ws_status} workstream — not created"
|
||||
)
|
||||
# The warn already names the unlinked task. Leaving it
|
||||
# uncreated is not a repair, so it is not a fix.
|
||||
pass
|
||||
else:
|
||||
t_status = normalise_task_status(task.get("status", "todo"))
|
||||
t_priority = str(task.get("priority", "medium")).strip()
|
||||
|
|
@ -4358,10 +4395,7 @@ def fix_repo(
|
|||
# timer idempotent and preventing commit pile-up.
|
||||
if repo_path:
|
||||
push_ok, push_msg = _git_push(repo_path)
|
||||
if push_ok:
|
||||
report.fixes_applied.append(f"push: {push_msg}")
|
||||
else:
|
||||
report.fixes_applied.append(f"push WARN: {push_msg}")
|
||||
_record_push_seal(report, push_ok, push_msg)
|
||||
|
||||
return report
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,12 @@ def push_ff(repo_path: str) -> tuple[bool, str]:
|
|||
capture_output=True, text=True, timeout=PUSH_TIMEOUT_SECONDS,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return True, result.stdout.strip() or "pushed"
|
||||
detail = "\n".join(
|
||||
part.strip() for part in (result.stdout, result.stderr) if part and part.strip()
|
||||
)
|
||||
if "everything up-to-date" in detail.lower():
|
||||
return True, "Everything up-to-date"
|
||||
return True, detail or "pushed"
|
||||
return False, result.stderr.strip() or "push failed"
|
||||
except subprocess.TimeoutExpired:
|
||||
return False, "push timed out; remote outcome unverified; inspect the remote ref before retrying"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue