Merge branch 'master' into fix/issue-693-review-decision-lock-recovery

This commit is contained in:
2026-07-17 09:32:27 -05:00
6 changed files with 1157 additions and 0 deletions
+50
View File
@@ -1104,6 +1104,7 @@ import allocator_service # noqa: E402
import control_plane_db # noqa: E402
import lease_lifecycle # noqa: E402
import incident_bridge # noqa: E402
import sentry_observability # noqa: E402 (#606 optional Sentry observability)
import agent_temp_artifacts
import issue_lock_worktree # noqa: E402
import issue_lock_provenance # noqa: E402
@@ -2005,6 +2006,18 @@ def _audited(action: str, *, host, remote, org=None, repo=None,
result=gitea_audit.FAILED, reason=_redact(str(exc)),
request_metadata=request_metadata, issue_number=issue_number,
pr_number=pr_number, target_branch=target_branch)
# #606: best-effort Sentry capture of the failing mutation (fail open).
sentry_observability.capture_exception(
exc,
tags={
"mutation_tool": action,
"remote": remote,
"repo": repo,
"org": org,
"issue_number": issue_number,
"pr_number": pr_number,
},
)
raise
_audit(action, host=host, remote=remote, org=org, repo=repo,
result=gitea_audit.SUCCEEDED, request_metadata=request_metadata,
@@ -2051,6 +2064,20 @@ def _audit_pr_result(action: str):
"merge_method": result.get("merge_method"),
},
)
# #606: surface fail-closed blockers / failed mutations to
# Sentry as structured events (best-effort, fail open).
if status in (gitea_audit.BLOCKED, gitea_audit.FAILED):
sentry_observability.capture_workflow_blocker(
action,
message="; ".join(reasons) or action,
next_action=result.get("safe_next_action"),
level="error" if status == gitea_audit.FAILED else "warning",
tags={
"mutation_tool": action,
"pr_number": result.get("pr_number"),
"current_head_sha": result.get("head_sha"),
},
)
except Exception:
pass # best-effort; never break the tool
return result
@@ -13050,6 +13077,11 @@ def gitea_assess_mcp_namespace_health(
probe_source=probe_source,
)
_record_live_namespace_health(result)
# #606: namespace-health watchdog check-in (best-effort, fail open).
sentry_observability.monitor_checkin(
"namespace_health",
"ok" if result.get("healthy", result.get("callable", True)) else "error",
)
return result
@@ -14980,6 +15012,18 @@ def gitea_allocate_next_work(
result["inventory_source"] = (
"candidates_json" if candidates_json else "gitea_live"
)
# #606: watchdog check-ins for the recurring jobs this allocator run
# performs — global stale-lease expiry, terminal-lock lookup, and the
# allocator itself. Best-effort; a failed selection reports "error".
_alloc_ok = bool(result.get("success"))
sentry_observability.monitor_checkin(
"allocator_health", "ok" if _alloc_ok else "error"
)
if _alloc_ok:
# These two scans complete inside allocate_next_work before selection;
# a successful result proves both ran.
sentry_observability.monitor_checkin("stale_lease_scan", "ok")
sentry_observability.monitor_checkin("terminal_lock_scan", "ok")
return result
@@ -15541,4 +15585,10 @@ if __name__ == "__main__":
# processes (e.g. review_pr.py) can detect and refuse profile
# side-channel overrides (#199).
_export_session_profile_lock()
# #606: optional self-hosted Sentry observability. No-op unless
# MCP_SENTRY_ENABLED is truthy and SENTRY_DSN is set; never blocks startup.
_sentry_status = sentry_observability.init_sentry()
sys.stderr.write(
f"--- Sentry observability: {_sentry_status.get('reason')} ---\n"
)
mcp.run(transport="stdio")