Merge remote-tracking branch 'prgs/master' into feat/issue-507-controller-thread-ledger

# Conflicts:
#	gitea_mcp_server.py
This commit is contained in:
2026-07-09 08:26:22 -04:00
46 changed files with 5350 additions and 53 deletions
+145
View File
@@ -11,6 +11,7 @@ import inspect
import re
from typing import Any, Callable
import issue_acceptance_gate
import issue_lock_provenance
import thread_state_ledger_validator
from mcp_native_cleanup_proof import assess_mcp_native_cleanup_proof
@@ -24,6 +25,7 @@ from review_proofs import (
assess_review_mutation_final_report,
assess_validation_report,
)
from state_handoff_ledger import assess_state_handoff_ledger_report
from validation_status_vocabulary import assess_validation_status_vocabulary
FINAL_REPORT_TASK_KINDS = frozenset({
@@ -335,6 +337,38 @@ def _rule_shared_controller_handoff(
)
def _rule_shared_state_handoff_next_action(report_text: str) -> list[dict[str, str]]:
result = assess_state_handoff_ledger_report(report_text)
if result.get("complete"):
return []
findings: list[dict[str, str]] = []
next_action = result.get("next_action") or {}
contradictions = result.get("contradictions") or {}
if next_action.get("block"):
findings.extend(
_findings_from_reasons(
"shared.state_handoff_next_action",
next_action.get("reasons") or [],
field="Next action handoff",
severity="block",
safe_next_action=next_action.get("safe_next_action")
or "add next-action handoff fields to Controller Handoff",
)
)
if contradictions.get("block"):
findings.extend(
_findings_from_reasons(
"shared.state_handoff_contradiction",
contradictions.get("reasons") or [],
field="State handoff",
severity="block",
safe_next_action=contradictions.get("safe_next_action")
or "resolve contradictory state claims before submission",
)
)
return findings
def _rule_shared_email_disclosure(report_text: str) -> list[dict[str, str]]:
result = assess_email_disclosure(report_text)
if result.get("proven"):
@@ -715,6 +749,25 @@ def _rule_reviewer_main_checkout_baseline(report_text: str) -> list[dict[str, st
]
def _rule_reviewer_premerge_baseline_proof(report_text: str) -> list[dict[str, str]]:
from premerge_baseline_proof import assess_premerge_baseline_proof
result = assess_premerge_baseline_proof(report_text)
if not result.get("block"):
return []
return _findings_from_reasons(
"reviewer.premerge_baseline_proof",
result.get("reasons") or [],
field="Pre-merge baseline proof",
severity="block",
safe_next_action=result.get("safe_next_action")
or (
"prove the failure on the PR pre-merge base commit or a known-failure "
"record predating the PR; current-master reproduction is not baseline proof"
),
)
def _rule_reviewer_validation_status_vocabulary(
report_text: str,
*,
@@ -961,6 +1014,69 @@ def _rule_reconcile_linked_issue_live(
return []
_PR_CLOSE_NEGATIVE = frozenset({"", "none", "n/a", "na", "0", "no", "not closed", "not performed"})
_ANCESTOR_AFFIRMATIVE_RE = re.compile(
r"ancestor|passed|true|verified|confirmed", re.IGNORECASE
)
def _reconciler_pr_close_performed(fields: dict[str, str], lock: dict) -> bool:
"""True when the report/session indicates a reconciler PR close happened."""
if lock.get("pr_closed") is True:
return True
value = (fields.get("prs closed", "") or "").strip().lower()
if value in _PR_CLOSE_NEGATIVE:
return False
# A closed PR is reported by number (e.g. "#99") or an affirmative result.
return bool(re.search(r"#\s*\d+|\b(?:closed|success|done)\b", value))
def _rule_reconcile_close_proof(
report_text: str,
*,
reconciler_close_lock: dict | None = None,
) -> list[dict[str, str]]:
"""#306: a reconciler PR close must carry exact proof fields.
Read-only/comment-only reconciliations are untouched. Once a PR close is
reported (via the ``PRs closed`` field or a session close lock), the
handoff must prove the close capability, ancestor landing, PR close
result, and the linked-issue result — narrative alone fails closed.
"""
fields = _handoff_fields(report_text)
lock = reconciler_close_lock or {}
if not _reconciler_pr_close_performed(fields, lock):
return []
missing: list[str] = []
capabilities = fields.get("capabilities proven", "")
if "gitea.pr.close" not in capabilities.lower():
missing.append("close capability proof (gitea.pr.close)")
ancestor = fields.get("ancestor proof", "")
if not _ANCESTOR_AFFIRMATIVE_RE.search(ancestor):
missing.append("ancestor proof")
prs_closed = (fields.get("prs closed", "") or "").strip().lower()
if prs_closed in _PR_CLOSE_NEGATIVE and lock.get("pr_closed") is True:
missing.append("PR close result")
linked = fields.get("linked issue live status", "") or fields.get("issues closed", "")
if not linked.strip():
missing.append("linked issue result")
if not missing:
return []
return [
validator_finding(
"reconcile.close_proof_fields",
"block",
"Reconciler close proof",
"reconciler PR close reported without required proof field(s): "
+ ", ".join(missing),
"include close capability proof, ancestor proof, PR close result, "
"and linked issue result in the handoff",
)
]
def _rule_reconcile_pagination_proof(report_text: str) -> list[dict[str, str]]:
text = report_text or ""
if not _INVENTORY_COMPLETE_RE.search(text):
@@ -1047,6 +1163,22 @@ def _rule_shared_manual_lock_pr_override(report_text: str) -> list[dict[str, str
)
def _rule_shared_issue_acceptance_gate(report_text: str) -> list[dict[str, str]]:
result = issue_acceptance_gate.validate_final_report_issue_acceptance(report_text)
if not result.get("applicable") or result.get("valid"):
return []
return _findings_from_reasons(
"shared.issue_acceptance_gate",
result.get("reasons") or [],
field="Controller acceptance",
severity="block",
safe_next_action=(
"add Controller Issue Acceptance proof or state that controller "
"acceptance is pending; do not claim issue complete from PR merge alone"
),
)
def _rule_shared_author_reviewer_same_run(report_text: str) -> list[dict[str, str]]:
result = issue_lock_provenance.assess_author_reviewer_same_run_report(report_text)
if result.get("proven"):
@@ -1209,6 +1341,7 @@ _SHARED_CLEANUP_PROOF_RULES = (
_RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
"review_pr": [
_rule_shared_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
@@ -1222,6 +1355,7 @@ _RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
_rule_reviewer_validation_structured,
_rule_reviewer_linked_issue,
_rule_reviewer_baseline_on_failure,
_rule_reviewer_premerge_baseline_proof,
_rule_reviewer_validation_status_vocabulary,
_rule_reviewer_main_checkout_baseline,
_rule_reviewer_main_checkout_path,
@@ -1238,6 +1372,7 @@ _RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
],
"reconcile_already_landed": [
_rule_reconcile_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
@@ -1245,7 +1380,9 @@ _RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
_rule_reconcile_stale_author_fields,
_rule_reconcile_eligible_reviewed,
_rule_reconcile_linked_issue_live,
_rule_reconcile_close_proof,
_rule_reconcile_pagination_proof,
_rule_reviewer_premerge_baseline_proof,
_rule_reviewer_git_fetch_readonly,
_rule_reviewer_legacy_workspace_mutations,
_rule_reviewer_vague_mutations_none,
@@ -1253,6 +1390,7 @@ _RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
],
"author_issue": [
_rule_shared_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
@@ -1260,21 +1398,25 @@ _RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
],
"work_issue": [
_rule_shared_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
_rule_shared_issue_acceptance_gate,
_rule_reviewer_vague_mutations_none,
_rule_conflict_fix_push_proof,
_rule_worktree_cleanup_audit_proof,
],
"issue_filing": [
_rule_shared_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
],
"inventory": [
_rule_shared_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
@@ -1282,6 +1424,7 @@ _RULES_BY_TASK: dict[str, list[Callable[..., list[dict[str, str]]]]] = {
],
"issue_selection": [
_rule_shared_controller_handoff,
_rule_shared_state_handoff_next_action,
_rule_shared_email_disclosure,
*_SHARED_TWO_COMMENT_RULES,
*_SHARED_ISSUE_LOCK_RULES,
@@ -1348,6 +1491,7 @@ def assess_final_report_validator(
issue_filing_lock: dict | None = None,
session_pr_opened: bool = False,
validation_session: dict | None = None,
reconciler_close_lock: dict | None = None,
) -> dict[str, Any]:
"""Validate final-report text against task-specific proof rules (#327).
@@ -1404,6 +1548,7 @@ def assess_final_report_validator(
"local_edits": local_edits,
"session_pr_opened": session_pr_opened,
"validation_session": validation_session,
"reconciler_close_lock": reconciler_close_lock,
}
for rule in _RULES_BY_TASK.get(normalized_kind, ()):