agent-exec transport dfbdcf8f9879479cec6791f6db4182b1/9e213bfbef61

This commit is contained in:
agent-exec-transport
2026-10-18 16:13:01 +00:00
parent 398d12141c
commit a06209ff0a
2 changed files with 44 additions and 6 deletions
+13 -6
View File
@@ -35,13 +35,20 @@ origin_transport_unavailable() { # $1=失败的远端命令 stderr → 仅明确
esac
[ ! -e "$path" ]
}
target_history() { # $1=可选基线(无缓存目标时代替比较,如任务 R0)→ 输出 ok(远端传输不可达/通告提交为基线后代)、rewound(回退或分叉)或 uncomparable(认证/授权/未知错误、目标 ref 缺失、无基线、通告提交本地缺失或无法比较)
local cached listing advertised rc=0
cached=$(git rev-parse -q --verify "refs/remotes/origin/${TARGET_BRANCH}^{commit}" 2>/dev/null) || cached=${1:-}
target_history() { # $1=可选基线(如任务 R0;无缓存目标时代替比较)→ 输出 ok(通告提交为基线后代;传输不可达时缓存目标为基线后代或无缓存目标)、rewound(回退或分叉)或 uncomparable(认证/授权/未知错误、目标 ref 缺失、无基线、提交本地缺失或无法比较)
local base=${1:-} cached listing advertised rc=0
cached=$(git rev-parse -q --verify "refs/remotes/origin/${TARGET_BRANCH}^{commit}" 2>/dev/null) || cached=
if ! listing=$(git ls-remote origin "refs/heads/${TARGET_BRANCH}" 2>&1); then
if origin_transport_unavailable "$listing"; then echo ok; else echo uncomparable; fi
if ! origin_transport_unavailable "$listing"; then echo uncomparable
elif [ -z "$cached" ]; then echo ok
elif [ -z "$base" ]; then echo uncomparable
else
git merge-base --is-ancestor "$base" "$cached" 2>/dev/null || rc=$?
case "$rc" in 0) echo ok ;; 1) echo rewound ;; *) echo uncomparable ;; esac
fi
return 0
fi
[ -n "$cached" ] || cached=$base
advertised=$(printf '%s\n' "$listing" \
| awk -v ref="refs/heads/${TARGET_BRANCH}" '$2 == ref && !seen { print $1; seen = 1 }')
[ -n "$advertised" ] && [ -n "$cached" ] || { echo uncomparable; return 0; }
@@ -174,9 +181,8 @@ cmd_precheck() {
exit 3
fi
if [ "$mode" = local ]; then
python3 "${SCRIPT_DIR}/evidence.py" --local-context --active || return 2
if [ "$remote_fresh" -eq 0 ]; then
# 无缓存目标时只以活动任务卡登记的 R0 作比较基线,不把它当作远端最新值。
# 以活动任务卡登记的 R0 为比较基线(不把它当作远端最新值);先于任务上下文核验,使缓存目标与 R0 矛盾时给出明确判定。
case "$(target_history "$(card_r0 "$(branch_card "$branch")")")" in
rewound)
echo "[verdict] REMOTE_UNVERIFIED — origin/${TARGET_BRANCH} rewound or diverged from the known target; preserve local work and reconcile the target history"
@@ -186,6 +192,7 @@ cmd_precheck() {
return 6 ;;
esac
fi
python3 "${SCRIPT_DIR}/evidence.py" --local-context --active || return 2
[ "$remote_fresh" -eq 1 ] || echo "[remote-freshness] unavailable — LOCAL_READY rests on local task context only"
echo "[verdict] LOCAL_READY — existing task may continue authorized local work; final delivery still requires latest-target sync and checks"
return 0
+31
View File
@@ -1290,6 +1290,37 @@ class TaskRecoveryTests(unittest.TestCase):
"the task HEAD must not move when the precheck refuses to "
"advertise LOCAL_READY")
def test_local_outage_rejects_cached_target_diverged_from_r0(self):
"""Origin transport is unavailable and the cached origin/main does not
descend from the registered R0. Local precheck must surface
REMOTE_UNVERIFIED and local resume must not import the receipt, instead
of continuing on a cache that already contradicts the task baseline."""
f = self.fixture
receipt = self.capture()
original = receipt.read_bytes()
card_before = self.card.read_bytes()
r0 = self.local_authorization_scope()["r0"]
divergent = f.git(self.wt, "commit-tree", r0 + "^{tree}", "-m",
"Unrelated cached target").stdout.strip()
f.git(self.wt, "update-ref", "refs/remotes/origin/main", divergent)
self.assertEqual(f.git(self.wt, "merge-base", "--is-ancestor", r0, divergent,
check=False).returncode, 1)
f.git(self.wt, "remote", "set-url", "origin", str(f.root / "missing.git"))
head_before = f.git(self.wt, "rev-parse", "HEAD").stdout
local = self.precheck()
self.assertNotEqual(local.returncode, 0, local.stdout)
self.assertIn("[verdict] REMOTE_UNVERIFIED", local.stdout)
self.assertIn("rewound or diverged", local.stdout)
self.assertNotIn("[verdict] LOCAL_READY", local.stdout)
resumed = self.resume(receipt)
self.assertNotEqual(resumed.returncode, 0, resumed.stdout)
self.assertNotIn("[resumed]", resumed.stdout)
self.assertEqual(self.card.read_bytes(), card_before)
self.assertEqual(receipt.read_bytes(), original)
self.assertEqual(f.git(self.wt, "rev-parse", "HEAD").stdout, head_before)
if __name__ == "__main__":
unittest.main()