fix(agentctl): fence integrate prepare merge via supervise

Pre-commit requires AGENTCTL_FENCE; run merge --no-ff through supervise like integrate ff-only.
This commit is contained in:
weichen
2026-09-24 14:15:50 +00:00
parent f9f055bee1
commit f5cdae1a41
+20 -5
View File
@@ -10,6 +10,7 @@ import argparse
import contextlib
import json
import mimetypes
import os
import re
import tempfile
import threading
@@ -177,8 +178,9 @@ def integrate_prepare(repo: ac.Repo, args) -> dict:
_register_integrate_task(integ_path, integrate_id, owner=task.get('owner') or 'Cursor')
integ_repo = ac.Repo(str(integ_path))
integ_task = ac.task_row(integ_repo, integrate_id)
request_id = getattr(args, 'request_id', None) or f"{integrate_id}-prepare"
request_id = getattr(args, 'request_id', None) or f"{integrate_id}-prepare-{uuid.uuid4().hex[:8]}"
msg = f"merge: candidate {args.task} into dev"
# New request_id when recovering after a failed fence-less attempt.
with ac.Lease(integ_repo, integ_task, ['path:.', 'git:index', 'git:dev'],
request_id, ac.digest(msg + expected + task_branch), kind='integrate_prepare') as lease:
if lease.replay:
@@ -191,12 +193,25 @@ def integrate_prepare(repo: ac.Repo, args) -> dict:
'head': head,
'expected_dev': expected,
}
result = ac.git(integ_path, 'merge', '--no-ff', '-m', msg, task_branch, check=False)
if result.returncode != 0:
# Merge commit must run with AGENTCTL_* fence (pre-commit hook), same as integrate().
env = os.environ.copy()
env.update(
AGENTCTL_RUN_ID=lease.request_id,
AGENTCTL_TASK_ID=integrate_id,
AGENTCTL_GENERATION=str(lease.row['generation']),
AGENTCTL_EPOCH=integ_repo.identity()['epoch'],
AGENTCTL_FENCE=str(lease.row.get('fence') or 0),
)
code, orphan = ac.supervise(
integ_repo, lease,
['git', 'merge', '--no-ff', '-m', msg, task_branch],
integ_path, env,
)
if code or orphan:
with contextlib.suppress(Exception):
ac.git(integ_path, 'merge', '--abort', check=False)
lease.finish(1, True)
ac.deny('GIT_ERROR', 'merge --no-ff failed', stderr=(result.stderr or '')[:500])
lease.finish(code or 1, True)
ac.deny('GIT_ERROR', 'merge --no-ff failed', exit_code=code, orphan=bool(orphan))
head = ac.git(integ_path, 'rev-parse', 'HEAD')
first_parent = ac.git(integ_path, 'rev-parse', 'HEAD^1')
if first_parent != expected: