fix(reconcile): safely resolve worktree bindings whose paths are missing (Closes #970)
This commit is contained in:
@@ -13547,6 +13547,110 @@ def gitea_scan_already_landed_open_prs(
|
||||
}
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def gitea_audit_missing_worktree_bindings(
|
||||
remote: str = "dadeschools",
|
||||
host: str | None = None,
|
||||
org: str | None = None,
|
||||
repo: str | None = None,
|
||||
) -> dict:
|
||||
"""Read-only: audit and classify worktree bindings whose paths are missing on disk (#970).
|
||||
|
||||
Correlates missing-path bindings from control-plane leases, session checkpoints,
|
||||
and issue locks with repository, host, branch, issue/PR, session, and lease state.
|
||||
Distinguishes deleted worktrees from moved paths, host/mount failures, and live
|
||||
leases/sessions.
|
||||
|
||||
Args:
|
||||
remote: Known instance — 'dadeschools' or 'prgs'.
|
||||
host: Override the Gitea host.
|
||||
org: Override the owner/organization.
|
||||
repo: Override the repository name.
|
||||
|
||||
Returns:
|
||||
dict with audit counts, missing binding classifications, and resolution status.
|
||||
"""
|
||||
read_block = _profile_operation_gate("gitea.read")
|
||||
if read_block:
|
||||
return {
|
||||
"success": False,
|
||||
"performed": False,
|
||||
"reasons": read_block,
|
||||
"permission_report": _permission_block_report("gitea.read"),
|
||||
}
|
||||
|
||||
import missing_worktree_reconcile
|
||||
db, _ = _control_plane_db_or_error()
|
||||
root = _canonical_local_git_root()
|
||||
h, o, r = _resolve(remote, host, org, repo)
|
||||
|
||||
return missing_worktree_reconcile.audit_missing_worktree_bindings(
|
||||
db,
|
||||
project_root=root,
|
||||
remote=remote,
|
||||
org=o,
|
||||
repo=r,
|
||||
host=h,
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def gitea_reconcile_missing_worktree_bindings(
|
||||
dry_run: bool = True,
|
||||
operator_authorized: bool = False,
|
||||
remote: str = "dadeschools",
|
||||
host: str | None = None,
|
||||
org: str | None = None,
|
||||
repo: str | None = None,
|
||||
) -> dict:
|
||||
"""Audit and safely resolve (retire) missing worktree path bindings (#970).
|
||||
|
||||
Identifies confirmed stale deleted worktree bindings, re-validates them
|
||||
immediately before mutation to prevent recreation races, and retires only the
|
||||
exact stale bindings while preserving unrelated worktrees and Git metadata.
|
||||
|
||||
Args:
|
||||
dry_run: If True (default), reports planned mutations without modifying state.
|
||||
operator_authorized: Explicit operator authorization required for apply mode.
|
||||
remote: Known instance — 'dadeschools' or 'prgs'.
|
||||
host: Override the Gitea host.
|
||||
org: Override the owner/organization.
|
||||
repo: Override the repository name.
|
||||
|
||||
Returns:
|
||||
dict with before/after audit state, resolutions, and dimension status.
|
||||
"""
|
||||
read_block = _profile_operation_gate("gitea.read")
|
||||
if read_block:
|
||||
return {
|
||||
"success": False,
|
||||
"performed": False,
|
||||
"reasons": read_block,
|
||||
"permission_report": _permission_block_report("gitea.read"),
|
||||
}
|
||||
|
||||
import missing_worktree_reconcile
|
||||
db, db_errs = _control_plane_db_or_error()
|
||||
root = _canonical_local_git_root()
|
||||
h, o, r = _resolve(remote, host, org, repo)
|
||||
|
||||
profile = get_profile()
|
||||
role = profile.get("role") or ""
|
||||
workflow_authorized = role in ("reconciler", "author", "controller")
|
||||
|
||||
return missing_worktree_reconcile.reconcile_missing_worktree_bindings(
|
||||
db,
|
||||
project_root=root,
|
||||
remote=remote,
|
||||
org=o,
|
||||
repo=r,
|
||||
host=h,
|
||||
dry_run=dry_run,
|
||||
operator_authorized=operator_authorized,
|
||||
workflow_authorized=workflow_authorized,
|
||||
)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def gitea_audit_worktree_cleanup(
|
||||
remote: str = "dadeschools",
|
||||
|
||||
Reference in New Issue
Block a user