feat(continuation): formalize continuation proofs for claim and push (closes #189)

Extend #188 continuation mode with issue claim status evidence,
force-with-lease push reporting, canonical secret sweep helper, and
composite final-report checks wired into assess_issue_selection_final_report.
This commit is contained in:
2026-07-06 11:54:40 -04:00
parent e441b81d3b
commit 1158594a20
3 changed files with 264 additions and 6 deletions
+117 -1
View File
@@ -1046,6 +1046,8 @@ HANDOFF_ROLE_FIELDS = {
("Continuation mode", ("continuation mode", "continuation")),
("Existing PR", ("existing pr", "pr number")),
("PR author", ("pr author", "existing pr author")),
("Issue claim status", ("issue claim", "claim status",
"status:in-progress")),
("Branch", ("branch", "existing branch")),
("Old PR head", ("old pr head", "old head")),
("New PR head", ("new pr head", "new head")),
@@ -1054,6 +1056,13 @@ HANDOFF_ROLE_FIELDS = {
),
}
# Canonical secret/provenance sweep for comparable continuation runs (#189).
CANONICAL_SECRET_SWEEP_COMMAND = (
"git diff prgs/master...HEAD | rg -i "
"'(token|password|secret|api[_-]?key|authorization:)'"
)
CANONICAL_SECRET_SWEEP_SCOPE = "full feature-branch diff against prgs/master"
def _handoff_section_lines(report_text):
"""Return the lines of the Controller Handoff section, or None."""
@@ -1657,18 +1666,89 @@ def assess_fresh_issue_selection(classifications: list[dict] | None) -> dict:
}
def canonical_secret_sweep_report(*, clean: bool) -> dict:
"""Return a sweep report using the canonical command/scope (#189)."""
return {
"method": CANONICAL_SECRET_SWEEP_COMMAND,
"scope": CANONICAL_SECRET_SWEEP_SCOPE,
"clean": clean,
}
def assess_force_with_lease_push_report(
report_text: str,
*,
old_remote_head: str | None = None,
expected_lease_head: str | None = None,
new_pushed_head: str | None = None,
branch_pushed: str | None = None,
used_force_with_lease: bool | None = None,
) -> dict:
"""Issue #189: force-with-lease pushes must disclose lease evidence."""
if not used_force_with_lease:
return {"complete": True, "downgraded": False, "reasons": []}
text = report_text or ""
lower = text.lower()
reasons = []
if "force-with-lease" not in lower and "force with lease" not in lower:
reasons.append(
"continuation push used force-with-lease but report does not say so"
)
for label, sha in (
("old remote", old_remote_head),
("lease", expected_lease_head),
("pushed", new_pushed_head),
):
if not sha:
reasons.append(f"force-with-lease proof missing {label} head SHA")
elif not _FULL_SHA.match(sha.lower()):
reasons.append(
f"force-with-lease {label} head SHA is not a full 40-hex SHA"
)
elif sha.lower() not in lower:
reasons.append(
f"continuation report missing {label} head SHA in evidence"
)
if branch_pushed:
if branch_pushed.lower() not in lower:
reasons.append("continuation report missing pushed branch name")
only_branch_tokens = (
"only feature branch",
"push branch only",
"only the feature branch",
"only pushed feature branch",
)
if not any(t in lower for t in only_branch_tokens):
reasons.append(
"continuation report missing confirmation that only the "
"feature branch was pushed"
)
return {
"complete": not reasons,
"downgraded": bool(reasons),
"reasons": reasons,
}
def assess_continuation_mode_report(
report_text: str,
*,
pr_number: int | None = None,
pr_author: str | None = None,
issue_number: int | None = None,
issue_claim_status: str | None = None,
branch: str | None = None,
old_head_sha: str | None = None,
new_head_sha: str | None = None,
session_authored_pr: bool | None = None,
continuation_allowed_reason: str | None = None,
) -> dict:
"""Issue #188: continuation mode must disclose full PR evidence."""
"""Issue #188/#189: continuation mode must disclose full PR evidence."""
text = report_text or ""
lower = text.lower()
reasons = []
@@ -1681,6 +1761,23 @@ def assess_continuation_mode_report(
reasons.append(f"continuation report missing PR #{pr_number}")
if pr_author and pr_author.lower() not in lower:
reasons.append("continuation report missing PR author")
if issue_number is not None:
if (
f"#{issue_number}" not in lower
and f"issue #{issue_number}" not in lower
and f"issue {issue_number}" not in lower
):
reasons.append(f"continuation report missing issue #{issue_number}")
if issue_claim_status:
claim_lower = issue_claim_status.lower()
claim_tokens = (
claim_lower,
"claim status",
"issue claim",
"status:in-progress",
)
if not any(t in lower for t in claim_tokens):
reasons.append("continuation report missing issue claim status")
if branch and branch.lower() not in lower:
reasons.append("continuation report missing branch name")
@@ -1817,12 +1914,26 @@ def assess_issue_selection_final_report(
report_text,
pr_number=proof.get("pr_number"),
pr_author=proof.get("pr_author"),
issue_number=proof.get("issue_number"),
issue_claim_status=proof.get("issue_claim_status"),
branch=proof.get("branch"),
old_head_sha=proof.get("old_head_sha"),
new_head_sha=proof.get("new_head_sha"),
session_authored_pr=proof.get("session_authored_pr"),
continuation_allowed_reason=proof.get("continuation_allowed_reason"),
)
push_proof = proof.get("push_proof") or {}
checks["force_with_lease_push"] = assess_force_with_lease_push_report(
report_text,
old_remote_head=push_proof.get("old_remote_head"),
expected_lease_head=push_proof.get("expected_lease_head"),
new_pushed_head=push_proof.get("new_pushed_head"),
branch_pushed=push_proof.get("branch_pushed"),
used_force_with_lease=push_proof.get("used_force_with_lease"),
)
sweep = proof.get("secret_sweep")
if sweep is not None:
checks["secret_sweep"] = assess_secret_sweep(sweep)
reasons = []
downgraded = False
@@ -1831,6 +1942,11 @@ def assess_issue_selection_final_report(
if verdict in ("missing", "incomplete"):
downgraded = True
reasons.extend(result.get("reasons") or [])
elif result.get("proven") is False:
downgraded = True
reasons.extend(
f"{name}: {r}" for r in (result.get("reasons") or [])
)
elif result.get("downgraded") or not result.get("complete", True):
downgraded = True
reasons.extend(