Skip to content

Commit a824bdf

Browse files
committed
Promote successor local commit proof
1 parent 0712903 commit a824bdf

10 files changed

Lines changed: 565 additions & 30 deletions

agent_os/coder_worktree_execution.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ class CoderWorktreeCommitResult:
155155
parent_commit_sha: str | None = None
156156
effect_id: str | None = None
157157
alias_evidence_path: str | None = None
158+
source_coder_commit_decision: str | None = None
159+
source_coder_commit_decision_md: str | None = None
160+
source_commit_decision_sha256: str | None = None
161+
source_commit_decision_md_sha256: str | None = None
162+
source_coder_commit_decision_markdown_consumed: bool = False
158163

159164

160165
def request_coder_worktree_approval(
@@ -1062,6 +1067,7 @@ def promote_coder_worktree_commit(
10621067
raise CoderWorktreeCommitError(f"commit approval not found: {approval_id}")
10631068
if approval.status == "committed":
10641069
_ensure_recorded_commit_exists(approval)
1070+
local_commit_payload = _load_coder_local_commit_payload(root, approval)
10651071
return CoderWorktreeCommitResult(
10661072
approval=approval,
10671073
status="already_committed",
@@ -1072,9 +1078,39 @@ def promote_coder_worktree_commit(
10721078
alias_evidence_path=str(
10731079
(_coder_commit_dir(root, approval) / "commit.json").relative_to(root)
10741080
),
1081+
source_coder_commit_decision=local_commit_payload.get(
1082+
"source_coder_commit_decision"
1083+
),
1084+
source_coder_commit_decision_md=local_commit_payload.get(
1085+
"source_coder_commit_decision_md"
1086+
),
1087+
source_commit_decision_sha256=local_commit_payload.get(
1088+
"source_commit_decision_sha256"
1089+
),
1090+
source_commit_decision_md_sha256=local_commit_payload.get(
1091+
"source_commit_decision_md_sha256"
1092+
),
1093+
source_coder_commit_decision_markdown_consumed=(
1094+
local_commit_payload.get(
1095+
"source_coder_commit_decision_markdown_consumed"
1096+
)
1097+
is True
1098+
),
10751099
)
10761100
if approval.status != "approved":
10771101
raise CoderWorktreeCommitError("approval is not approved")
1102+
try:
1103+
decision_proof = _load_commit_decision_proof(root, approval)
1104+
except CoderWorktreeCommitError as error:
1105+
_block_commit_approval(
1106+
root,
1107+
storage,
1108+
approval,
1109+
failure_class="missing_commit_decision_proof",
1110+
detail=str(error),
1111+
verification_exit_code=None,
1112+
)
1113+
raise
10781114

10791115
run = get_coder_worktree_run(storage, approval.run_id)
10801116
if run is None:
@@ -1385,6 +1421,22 @@ def promote_coder_worktree_commit(
13851421
"changed_files": approval.changed_files,
13861422
"committed_files": committed_files,
13871423
"commit_message": commit_message,
1424+
"source_coder_commit_decision": decision_proof[
1425+
"source_coder_commit_decision"
1426+
],
1427+
"source_coder_commit_decision_md": decision_proof[
1428+
"source_coder_commit_decision_md"
1429+
],
1430+
"source_commit_decision_sha256": decision_proof[
1431+
"source_commit_decision_sha256"
1432+
],
1433+
"source_commit_decision_md_sha256": decision_proof[
1434+
"source_commit_decision_md_sha256"
1435+
],
1436+
"source_coder_commit_decision_markdown_consumed": True,
1437+
"source_coder_commit_decision_markdown_excerpt": decision_proof[
1438+
"markdown_excerpt"
1439+
],
13881440
"source_coder_worktree_run_sha256": approval.source_coder_worktree_run_sha256,
13891441
"source_diff_sha256": approval.source_diff_sha256,
13901442
"verification_command": verification_command,
@@ -1415,6 +1467,22 @@ def promote_coder_worktree_commit(
14151467
"branch_name": approval.branch_name,
14161468
"commit_request_id": approval.id,
14171469
"commit_approval_id": approval.id,
1470+
"source_coder_commit_decision": decision_proof[
1471+
"source_coder_commit_decision"
1472+
],
1473+
"source_coder_commit_decision_md": decision_proof[
1474+
"source_coder_commit_decision_md"
1475+
],
1476+
"source_commit_decision_sha256": decision_proof[
1477+
"source_commit_decision_sha256"
1478+
],
1479+
"source_commit_decision_md_sha256": decision_proof[
1480+
"source_commit_decision_md_sha256"
1481+
],
1482+
"source_coder_commit_decision_markdown_consumed": True,
1483+
"source_coder_commit_decision_markdown_excerpt": decision_proof[
1484+
"markdown_excerpt"
1485+
],
14181486
"commit_sha": commit_sha,
14191487
"parent_commit_sha": parent_commit_sha,
14201488
"commit_message": commit_message,
@@ -1471,6 +1539,17 @@ def promote_coder_worktree_commit(
14711539
parent_commit_sha=parent_commit_sha,
14721540
effect_id=effect.id,
14731541
alias_evidence_path=str((coder_commit_dir / "commit.json").relative_to(root)),
1542+
source_coder_commit_decision=decision_proof["source_coder_commit_decision"],
1543+
source_coder_commit_decision_md=decision_proof[
1544+
"source_coder_commit_decision_md"
1545+
],
1546+
source_commit_decision_sha256=decision_proof[
1547+
"source_commit_decision_sha256"
1548+
],
1549+
source_commit_decision_md_sha256=decision_proof[
1550+
"source_commit_decision_md_sha256"
1551+
],
1552+
source_coder_commit_decision_markdown_consumed=True,
14741553
)
14751554

14761555

@@ -1906,6 +1985,7 @@ def render_commit_coder_worktree_cli_lines(
19061985
evidence_path = result.alias_evidence_path or str(
19071986
(_coder_commit_dir(root.resolve(), approval) / "commit.json").relative_to(root.resolve())
19081987
)
1988+
payload = _load_coder_local_commit_payload(root.resolve(), approval)
19091989
return [
19101990
f"commit_coder_worktree: {result.status}",
19111991
f"commit_request_id: {approval.id}",
@@ -1920,6 +2000,16 @@ def render_commit_coder_worktree_cli_lines(
19202000
f"worktree_path: {approval.worktree_path}",
19212001
f"branch_name: {approval.branch_name}",
19222002
f"committed_files: {','.join(approval.changed_files) or 'none'}",
2003+
"source_coder_commit_decision: "
2004+
f"{payload.get('source_coder_commit_decision', result.source_coder_commit_decision or 'missing')}",
2005+
"source_coder_commit_decision_md: "
2006+
f"{payload.get('source_coder_commit_decision_md', result.source_coder_commit_decision_md or 'missing')}",
2007+
"source_commit_decision_sha256: "
2008+
f"{payload.get('source_commit_decision_sha256', result.source_commit_decision_sha256 or 'missing')}",
2009+
"source_commit_decision_md_sha256: "
2010+
f"{payload.get('source_commit_decision_md_sha256', result.source_commit_decision_md_sha256 or 'missing')}",
2011+
"source_coder_commit_decision_markdown_consumed: "
2012+
f"{_bool(payload.get('source_coder_commit_decision_markdown_consumed') is True or result.source_coder_commit_decision_markdown_consumed)}",
19232013
f"evidence: {evidence_path}",
19242014
"commit_created: true",
19252015
"push_created: false",
@@ -2071,12 +2161,19 @@ def render_coder_local_commit_dashboard_lines(root: Path) -> list[str]:
20712161
lines: list[str] = []
20722162
for approval in list_coder_worktree_commit_approvals(root, status="committed", limit=10):
20732163
artifact = _coder_commit_dir(root.resolve(), approval) / "commit.json"
2164+
payload = _load_coder_local_commit_payload(root.resolve(), approval)
20742165
lines.append(
20752166
f"- {approval.id}: delegation={approval.delegation_id} project={approval.project_id} "
20762167
f"coder_worktree_run={approval.run_id} commit={approval.commit_sha or 'none'} "
20772168
f"parent={approval.pre_commit_head} effect={approval.effect_id or 'none'} "
20782169
f"github_handoff_available={_bool(bool(approval.effect_id))} "
20792170
f"committed_files={','.join(approval.changed_files) or 'none'} "
2171+
"source_commit_decision_md="
2172+
f"{payload.get('source_coder_commit_decision_md', 'missing')} "
2173+
"source_commit_decision_md_sha256="
2174+
f"{payload.get('source_commit_decision_md_sha256', 'missing')} "
2175+
"source_commit_decision_markdown_consumed="
2176+
f"{_bool(payload.get('source_coder_commit_decision_markdown_consumed') is True)} "
20802177
f"artifact={artifact.relative_to(root.resolve())} "
20812178
"push_created=false pr_created=false deploy_created=false"
20822179
)
@@ -3238,6 +3335,58 @@ def _load_commit_request_proof(
32383335
}
32393336

32403337

3338+
def _load_commit_decision_proof(
3339+
root: Path,
3340+
approval: CoderWorktreeCommitApprovalRecord,
3341+
) -> dict[str, Any]:
3342+
decision_path = _coder_commit_dir(root, approval) / "coder_commit_decision.json"
3343+
decision_markdown_path = decision_path.with_suffix(".md")
3344+
try:
3345+
payload = json.loads(decision_path.read_text(encoding="utf-8"))
3346+
markdown_text = decision_markdown_path.read_text(encoding="utf-8")
3347+
except (OSError, json.JSONDecodeError) as error:
3348+
raise CoderWorktreeCommitError("coder commit decision is not readable") from error
3349+
if payload.get("kind") != COMMIT_APPROVAL_DECISION_KIND:
3350+
raise CoderWorktreeCommitError("coder commit decision has unexpected kind")
3351+
if payload.get("commit_request_id") != approval.id:
3352+
raise CoderWorktreeCommitError("coder commit decision does not match approval")
3353+
if payload.get("coder_worktree_run_id") != approval.run_id:
3354+
raise CoderWorktreeCommitError("coder commit decision does not match run")
3355+
if payload.get("status") != "approved":
3356+
raise CoderWorktreeCommitError("coder commit decision is not approved")
3357+
if payload.get("source_coder_commit_request_markdown_consumed") is not True:
3358+
raise CoderWorktreeCommitError(
3359+
"coder commit decision is missing request markdown proof"
3360+
)
3361+
if f"- commit_request_id: {approval.id}" not in markdown_text:
3362+
raise CoderWorktreeCommitError("coder commit decision markdown does not match approval")
3363+
if "- status: approved" not in markdown_text:
3364+
raise CoderWorktreeCommitError("coder commit decision markdown is not approved")
3365+
return {
3366+
"payload": payload,
3367+
"markdown_text": markdown_text,
3368+
"markdown_excerpt": markdown_text[:2000],
3369+
"source_coder_commit_decision": str(decision_path.relative_to(root)),
3370+
"source_coder_commit_decision_md": str(decision_markdown_path.relative_to(root)),
3371+
"source_commit_decision_sha256": _sha256_path(decision_path),
3372+
"source_commit_decision_md_sha256": hashlib.sha256(
3373+
markdown_text.encode("utf-8")
3374+
).hexdigest(),
3375+
}
3376+
3377+
3378+
def _load_coder_local_commit_payload(
3379+
root: Path,
3380+
approval: CoderWorktreeCommitApprovalRecord,
3381+
) -> dict[str, Any]:
3382+
artifact = _coder_commit_dir(root, approval) / "commit.json"
3383+
try:
3384+
payload = json.loads(artifact.read_text(encoding="utf-8"))
3385+
except (OSError, json.JSONDecodeError):
3386+
return {}
3387+
return payload if isinstance(payload, dict) else {}
3388+
3389+
32413390
def _record_coder_worktree_incident(
32423391
storage: Storage,
32433392
*,
@@ -3278,6 +3427,7 @@ def _commit_failure_class_from_error(error_text: str) -> str:
32783427
("worktree does not exist", "missing_worktree"),
32793428
("unsafe_git_state", "unsafe_git_state"),
32803429
("approved commit request is missing", "missing_commit_request"),
3430+
("coder commit decision", "missing_commit_decision_proof"),
32813431
("approval is not approved", "commit_request_not_approved"),
32823432
("approval is not pending", "commit_request_not_approved"),
32833433
("source_hash_mismatch", "source_hash_mismatch"),
@@ -3309,6 +3459,7 @@ def _commit_failure_next_action(failure_class: str) -> str:
33093459
return "review_coder_worktree_run"
33103460
if failure_class in {
33113461
"missing_commit_request",
3462+
"missing_commit_decision_proof",
33123463
"commit_request_not_approved",
33133464
"source_hash_mismatch",
33143465
"changed_files_mismatch",
@@ -4105,6 +4256,13 @@ def _render_coder_local_commit_markdown(payload: dict[str, Any]) -> str:
41054256
f"- parent_commit_sha: {payload['parent_commit_sha']}",
41064257
f"- branch_name: {payload['branch_name']}",
41074258
f"- worktree_path: {payload['worktree_path']}",
4259+
f"- source_coder_commit_decision: {payload['source_coder_commit_decision']}",
4260+
f"- source_coder_commit_decision_md: {payload['source_coder_commit_decision_md']}",
4261+
f"- source_commit_decision_sha256: {payload['source_commit_decision_sha256']}",
4262+
"- source_commit_decision_md_sha256: "
4263+
f"{payload['source_commit_decision_md_sha256']}",
4264+
"- source_coder_commit_decision_markdown_consumed: "
4265+
f"{_bool(payload['source_coder_commit_decision_markdown_consumed'] is True)}",
41084266
f"- next_recommended_action: {payload['next_recommended_action']}",
41094267
"",
41104268
"## Committed Files",

agent_os/local_app.py

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29174,6 +29174,16 @@ def add(label: str, path: str | Path | None, *, source: str) -> None:
2917429174
("commit_artifact", approval.commit_artifact_path),
2917529175
]:
2917629176
add(label, path, source="commit")
29177+
if path:
29178+
add(f"{label}_markdown", Path(path).with_suffix(".md"), source="commit")
29179+
coder_commit_dir = Path(approval.source_run_evidence_path) / "coder_commit"
29180+
for label, path in [
29181+
("coder_commit_request", coder_commit_dir / "coder_commit_request.json"),
29182+
("coder_commit_decision", coder_commit_dir / "coder_commit_decision.json"),
29183+
("coder_local_commit", coder_commit_dir / "commit.json"),
29184+
]:
29185+
add(label, path, source="commit")
29186+
add(f"{label}_markdown", path.with_suffix(".md"), source="commit")
2917729187
for publication in state["publications"]:
2917829188
for label, path in [
2917929189
("publication_request", publication.request_artifact_path),
@@ -48117,24 +48127,82 @@ def _handle_post(
4811748127
)
4811848128
elif action == "commit-coder-worktree":
4811948129
run_id = _required(form, "run_id")
48120-
result = commit_coder_worktree(
48130+
commit_result = commit_coder_worktree(
4812148131
root,
4812248132
storage,
4812348133
run_id,
4812448134
message=_required(form, "message"),
4812548135
committed_by=_one(form, "committed_by") or "operator",
4812648136
)
48127-
message = f"commit_coder_worktree: {result.status}"
48137+
commit_payload: dict[str, Any] = {}
48138+
commit_artifact_path = (
48139+
root / commit_result.alias_evidence_path
48140+
if commit_result.alias_evidence_path
48141+
else root / commit_result.evidence_path
48142+
)
48143+
try:
48144+
commit_payload = json.loads(
48145+
commit_artifact_path.read_text(encoding="utf-8")
48146+
)
48147+
except (OSError, json.JSONDecodeError):
48148+
commit_payload = {}
48149+
result = {
48150+
"approval": commit_result.approval,
48151+
"status": commit_result.status,
48152+
"commit_sha": commit_result.commit_sha,
48153+
"parent_commit_sha": commit_result.parent_commit_sha,
48154+
"effect_id": commit_result.effect_id,
48155+
"evidence_path": commit_result.evidence_path,
48156+
"alias_evidence_path": commit_result.alias_evidence_path,
48157+
"source_coder_commit_decision": commit_payload.get(
48158+
"source_coder_commit_decision",
48159+
commit_result.source_coder_commit_decision or "missing",
48160+
),
48161+
"source_coder_commit_decision_md": commit_payload.get(
48162+
"source_coder_commit_decision_md",
48163+
commit_result.source_coder_commit_decision_md or "missing",
48164+
),
48165+
"source_commit_decision_sha256": commit_payload.get(
48166+
"source_commit_decision_sha256",
48167+
commit_result.source_commit_decision_sha256 or "missing",
48168+
),
48169+
"source_commit_decision_md_sha256": commit_payload.get(
48170+
"source_commit_decision_md_sha256",
48171+
commit_result.source_commit_decision_md_sha256 or "missing",
48172+
),
48173+
"source_coder_commit_decision_markdown_consumed": (
48174+
commit_payload.get(
48175+
"source_coder_commit_decision_markdown_consumed"
48176+
)
48177+
is True
48178+
or commit_result.source_coder_commit_decision_markdown_consumed
48179+
),
48180+
"bounded_file_validation": commit_payload.get(
48181+
"bounded_file_validation",
48182+
{},
48183+
),
48184+
"commit_created": commit_payload.get("commit_created") is True,
48185+
"push_created": commit_payload.get("push_created") is True,
48186+
"pr_created": commit_payload.get("pr_created") is True,
48187+
"deploy_created": commit_payload.get("deploy_created") is True,
48188+
"network_actions_taken": int(
48189+
commit_payload.get("network_actions_taken") or 0
48190+
),
48191+
"external_mutations_taken": int(
48192+
commit_payload.get("external_mutations_taken") or 0
48193+
),
48194+
}
48195+
message = f"commit_coder_worktree: {commit_result.status}"
4812848196
run_location = f"/runs/{quote(run_id)}"
4812948197
location = _safe_local_return_path(_one(form, "return_to")) or run_location
4813048198
_remember_delegation_workspace(
4813148199
root,
4813248200
storage,
48133-
result.approval.delegation_id,
48201+
commit_result.approval.delegation_id,
4813448202
artifact_path=(
48135-
Path(result.alias_evidence_path).with_suffix(".md")
48136-
if result.alias_evidence_path
48137-
else Path(result.evidence_path).with_suffix(".md")
48203+
Path(commit_result.alias_evidence_path).with_suffix(".md")
48204+
if commit_result.alias_evidence_path
48205+
else Path(commit_result.evidence_path).with_suffix(".md")
4813848206
),
4813948207
updated_by="commit-coder-worktree",
4814048208
resume_surface=location,

0 commit comments

Comments
 (0)