agent-exec transport 7da469a725ec41f651cf89a8616adaa7/78f40f5a0c57

This commit is contained in:
agent-exec-transport
2026-10-18 14:25:10 +00:00
parent 8d8585afec
commit f81326bd08
2 changed files with 50 additions and 9 deletions
+4 -1
View File
@@ -42,7 +42,10 @@ make task-start NAME=feature/my-task TRIAGE_RECEIPT=/tmp/my-task-triage.json PRE
恢复已有登记任务先捕获本次启动检查,再在原任务 worktree 用
`make task-resume PRECHECK_RECEIPT=/tmp/my-task-resume.json` 验证并原样导入;不重新建分支。
默认 `TASK_WORK_MODE=delivery`,继续要求严格 READY 和当前目标一致。
工作区忙或落后时先由 owner 保存现场并同步;远端不可达时只继续不依赖新鲜基线的阅读和分析。
工作区忙或落后时先由 owner 保存现场并同步。远端不可达时,delivery 恢复仍以 REMOTE_UNVERIFIED 拒绝;
显式 `TASK_WORK_MODE=local` 可在先核验收据、活动任务、原 R0/HEAD/工作区范围后导入 LOCAL_READY 收据,
继续已授权局部工作(子任务以已登记的本地父分支为参考,且须包含记录的 `parent_head_sha`)。远端可达但目标缺失、
回退/分叉或无法比较时仍拒绝。离线不得建任务、同步、PR 检查、Review/合入或交付,本地参考不视为最新或可交付。
局部恢复接口已具备,正式交付仍按[合入调度](delivery.md#合入调度)的单一最终窗口执行。
启用后,既有任务可以显式选择 local,保持原 R0,标记落后,继续已授权局部工作:
+46 -8
View File
@@ -18,9 +18,10 @@ fetch_target() {
git rev-parse --verify "refs/remotes/origin/${TARGET_BRANCH}^{commit}" >/dev/null \
|| { echo "[verdict] REMOTE_UNVERIFIED — target commit missing" >&2; return 6; }
}
target_history() { # 输出 ok(远端不可查询/目标 ref 缺失/无缓存目标/通告提交为缓存后代)、rewound(回退或分叉)或 uncomparable(通告提交本地缺失或无法比较)
target_history() { # $1=可选基线(无缓存目标时代替比较,如任务 R0)→ 输出 ok(远端不可查询/目标 ref 缺失/无缓存目标/通告提交为缓存后代)、rewound(回退或分叉)或 uncomparable(通告提交本地缺失或无法比较)
local cached advertised rc=0
cached=$(git rev-parse -q --verify "refs/remotes/origin/${TARGET_BRANCH}^{commit}" 2>/dev/null) || { echo ok; return 0; }
cached=$(git rev-parse -q --verify "refs/remotes/origin/${TARGET_BRANCH}^{commit}" 2>/dev/null) || cached=${1:-}
[ -n "$cached" ] || { echo ok; return 0; }
advertised=$(git ls-remote origin "refs/heads/${TARGET_BRANCH}" 2>/dev/null \
| awk -v ref="refs/heads/${TARGET_BRANCH}" '$2 == ref && !seen { print $1; seen = 1 }') || { echo ok; return 0; }
[ -n "$advertised" ] || { echo ok; return 0; }
@@ -477,9 +478,9 @@ cmd_resume() {
need_repo
local mode
mode=$(work_mode)
fetch_target
[ "$mode" = local ] || fetch_target
[ -n "${PRECHECK_RECEIPT:-}" ] || die "PRECHECK_RECEIPT required: capture the current task precheck before resume"
local receipt
local receipt remote_fresh=1
receipt=$(realpath -- "$PRECHECK_RECEIPT")
VALIDATE_RECEIPT="$receipt" VALIDATE_RECEIPT_PURPOSE="resume-${mode}" bash "${SCRIPT_DIR}/evidence.sh"
# 立即目标:子任务为其父 initiative(delivery 下取远端头),其余为根目标。
@@ -487,14 +488,44 @@ cmd_resume() {
branch=$(git rev-parse --abbrev-ref HEAD)
card=$(branch_card "$branch")
[ -n "$card" ] && immediate=$(card_immediate_target "$card")
if [ "$mode" = local ]; then
# local 先核验收据与活动任务再刷新:刷新成功按新目标复核;失败只在远端确实不可达时以登记 R0 继续,
# 远端可达而目标缺失、回退/分叉或无法比较时保持 REMOTE_UNVERIFIED,不导入收据。
git check-ref-format "refs/heads/${TARGET_BRANCH}" >/dev/null || die "invalid target branch"
if fetch_target 2>/dev/null; then
VALIDATE_RECEIPT="$receipt" VALIDATE_RECEIPT_PURPOSE=resume-local bash "${SCRIPT_DIR}/evidence.sh"
else
remote_fresh=0
local r0 ls_rc=0
[ -n "$card" ] || die "no registered task card for ${branch}; receipt not imported"
r0=$(sed -n 's/^- 权威仓:.*;R0(initial_base_sha)= \([0-9a-f]\+\)[[:space:]]*$/\1/p' "$card" | head -1)
[ -n "$r0" ] || die "task card has no initial baseline; receipt not imported"
git ls-remote --exit-code --heads origin "refs/heads/${TARGET_BRANCH}" >/dev/null 2>&1 || ls_rc=$?
if [ "$ls_rc" -eq 2 ]; then
echo "[verdict] REMOTE_UNVERIFIED — origin is reachable but ${TARGET_BRANCH} is missing; preserve local work, receipt not imported" >&2
return 6
fi
case "$(target_history "$r0")" in
rewound)
echo "[verdict] REMOTE_UNVERIFIED — origin/${TARGET_BRANCH} rewound or diverged from the known target; preserve local work, receipt not imported" >&2
return 6 ;;
uncomparable)
echo "[verdict] REMOTE_UNVERIFIED — advertised origin/${TARGET_BRANCH} cannot be compared with the known target; preserve local work, receipt not imported" >&2
return 6 ;;
esac
echo "[remote-freshness] unavailable — resuming on registered R0=${r0} for authorized local work only; delivery still requires a fresh target"
fi
fi
if [ "$immediate" != "${TARGET_BRANCH}" ]; then
observed=$(resolve_parent_ref "$immediate") || die "immediate target ${immediate} unavailable; receipt not imported"
recorded=$(card_field "$card" parent_head_sha)
if [ -n "$recorded" ] && ! git merge-base --is-ancestor "$recorded" "$observed"; then
die "immediate target ${immediate} no longer contains recorded parent head ${recorded}; receipt not imported"
fi
else
elif [ "$remote_fresh" -eq 1 ]; then
observed=$(git rev-parse "origin/${TARGET_BRANCH}")
else
observed=unavailable
fi
IMPORT_RECEIPT="$receipt" bash "${SCRIPT_DIR}/evidence.sh"
echo "[resumed] work_mode=${mode} source_head=$(git rev-parse HEAD) observed_target=${observed} immediate_target=${immediate}"
@@ -630,7 +661,7 @@ except Stop as error:
sys.exit("ERROR: " + error.message)
sys.exit(0 if any(row["子任务分支"].strip("`").strip() == sys.argv[2] for row in rows) else 1)' "$SCRIPT_DIR" "$1"
}
resolve_parent_ref() { # $1=父 initiative 分支 → 打印用于同步/核验的提交(delivery 仅远端;local 取远端与本地包含对方的一侧)
resolve_parent_ref() { # $1=父 initiative 分支 → 打印用于同步/核验的提交(delivery 仅远端;local 取远端与本地包含对方的一侧,远端不可查询时取本地)
git check-ref-format "refs/heads/$1" >/dev/null || die "invalid parent branch $1"
if [ "$(work_mode)" = delivery ]; then
# delivery 只认 origin 上刚取回的父分支头:本地领先/分叉意味着未准入的提交,不得被同步或合入。
@@ -652,8 +683,15 @@ resolve_parent_ref() { # $1=父 initiative 分支 → 打印用于同步/核验
fi
remote=$(git rev-parse --verify "refs/remotes/origin/$1^{commit}")
elif [ "$rc" -ne 2 ]; then
echo "[verdict] REMOTE_UNVERIFIED — cannot query origin/$1; preserve local work and retry" >&2
return 6
# 远端不可查询时只把已登记的本地父分支作为局部续作参考;不声称其为最新或可交付,调用方仍核验 parent_head_sha。
local_ref=$(git rev-parse -q --verify "refs/heads/$1^{commit}" 2>/dev/null || true)
if [ -z "$local_ref" ]; then
echo "[verdict] REMOTE_UNVERIFIED — cannot query origin/$1 and no local $1 exists; preserve local work and retry" >&2
return 6
fi
echo "[remote-freshness] origin/$1 unavailable — using local $1 for authorized local continuation only; not current or delivery-ready" >&2
printf '%s\n' "$local_ref"
return 0
fi
local_ref=$(git rev-parse -q --verify "refs/heads/$1^{commit}" 2>/dev/null || true)
if [ -n "$remote" ] && [ -n "$local_ref" ]; then