From 7784be0657ec820bd01043c210b4a830f536ebfc Mon Sep 17 00:00:00 2001 From: host Date: Sun, 8 Nov 2026 09:48:41 +0000 Subject: [PATCH] =?UTF-8?q?fix(chv-muse-r12fix3-3):=20=E5=9B=9E=E8=90=BD?= =?UTF-8?q?=E5=AE=A1=E8=AE=A1=20repo=20=E8=AE=B0=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E4=BB=93=E7=9B=AE=E5=BD=95=EF=BC=88P6=20?= =?UTF-8?q?=E5=B0=8F=E9=A1=B9=20A=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit R12 复测 2 轻微缺口:回落审计行的 repo 字段为空串——fallback_warn 记的是调用方传的原始参数,而驱动与日常调用都是无参调用 (cd 仓 && chv-sync status)。单仓无损,多仓时审计分不清是哪 一仓回落。 修法:cmd_pull/cmd_push/cmd_status 三处都先调 resolve_repo 解析 仓目录,再以解析后的目录调 fallback_warn。解析失败即 die、不 留回落审计——同步本身已失败,没有“回落”可记(此前是先记审计 再解析,解析失败也留一行空 repo 审计)。 测试:ChvSyncDelegationTest——无参回落的 repo 即唯一仓目录 (不再是空串),显式给仓目录时 repo 即该目录。P6 模块 65 项全过。 --- chv-guest/chv-sync.sh | 10 +++++++--- cloud/tests/test_chv_muse_p6.py | 18 ++++++++++++++++++ docs/chv-muse-p6-gap.md | 8 +++++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/chv-guest/chv-sync.sh b/chv-guest/chv-sync.sh index 4ccaa08..37522ab 100755 --- a/chv-guest/chv-sync.sh +++ b/chv-guest/chv-sync.sh @@ -152,9 +152,13 @@ cmd_pull() { local rc=0 try_worker pull "${1:-}" || rc=$? [ "$rc" != "42" ] && exit "$rc" - fallback_warn pull "${1:-}" + # round-12 修复轮第三轮(小项 A):先解析仓目录再记回落审计, + # repo 字段记 resolve_repo 解析后的仓目录(无参调用时不再是 + # 空串,多仓审计才能分清是哪一仓回落)。解析失败即 die, + # 不留回落审计——同步本身已失败,没有“回落”可记。 local dir dir="$(resolve_repo "${1:-}")" + fallback_warn pull "$dir" [ -z "$(git -C "$dir" status --porcelain)" ] \ || die "工作树有未提交改动,拒绝 pull(先 commit 或 stash)" git -C "$dir" pull --ff-only \ @@ -166,9 +170,9 @@ cmd_push() { local rc=0 try_worker push "${1:-}" || rc=$? [ "$rc" != "42" ] && exit "$rc" - fallback_warn push "${1:-}" local dir dir="$(resolve_repo "${1:-}")" + fallback_warn push "$dir" if git -C "$dir" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then git -C "$dir" push \ || die "push 被拒绝(远端已有新提交,先 pull 再 push,不 --force)" @@ -183,9 +187,9 @@ cmd_status() { local rc=0 try_worker status "${1:-}" || rc=$? [ "$rc" != "42" ] && exit "$rc" - fallback_warn status "${1:-}" local dir dir="$(resolve_repo "${1:-}")" + fallback_warn status "$dir" git -C "$dir" status -sb git -C "$dir" log --oneline -5 } diff --git a/cloud/tests/test_chv_muse_p6.py b/cloud/tests/test_chv_muse_p6.py index d4ed525..aa99ea8 100644 --- a/cloud/tests/test_chv_muse_p6.py +++ b/cloud/tests/test_chv_muse_p6.py @@ -681,10 +681,28 @@ class ChvSyncDelegationTest(unittest.TestCase): record = json.loads(lines[0]) self.assertEqual(record["event"], "chv_sync_worker_fallback") self.assertEqual(record["action"], "status") + # round-12 修复轮第三轮(小项 A):repo 记 resolve_repo + # 解析后的仓目录——无参调用时是唯一仓的目录,不再是空串。 + self.assertEqual(record["repo"], + os.path.join(self.ws, "repo")) self.assertIs(record["delegated_to_worker"], False) self.assertIs(record["privsep_active"], False) self.assertIn("ts", record) + def test_fallback_audit_repo_is_explicit_arg(self): + # 显式给仓目录时 repo 即该目录(与无参解析同款语义)。 + self.env["CHV_GITEA_WORKER_SOCK"] = os.path.join( + self.tmp.name, "no-worker.sock") + proc = self._run_sync( + "status", os.path.join(self.ws, "repo")) + self.assertIn("worker 不在", proc.stderr) + with open(self.audit) as fh: + lines = [line for line in fh if line.strip()] + self.assertEqual(len(lines), 1) + record = json.loads(lines[0]) + self.assertEqual(record["repo"], + os.path.join(self.ws, "repo")) + def test_fallback_audit_accumulates_one_line_per_call(self): self.env["CHV_GITEA_WORKER_SOCK"] = os.path.join( self.tmp.name, "no-worker.sock") diff --git a/docs/chv-muse-p6-gap.md b/docs/chv-muse-p6-gap.md index cfb9bb2..dd20460 100644 --- a/docs/chv-muse-p6-gap.md +++ b/docs/chv-muse-p6-gap.md @@ -154,9 +154,11 @@ Base64、零宽字符)、藏在图片/附件/二进制里的指令、需要理 项 2 钉死)**:worker socket 不存在时 `chv-sync` pull/push/status 仍走旧的直接路径,为的是旧镜像不被一次改断;但回落不再静默—— 每次回落都在 stderr 警告(“worker 不在…privsep 未生效”)+ 追加 - 一行 JSON 审计(`~/.chv-sync-fallback-audit.log`)。旧镜像退役 - 后应删掉该回落,改为无 worker 即 fail-closed;删除前不得声称 - “旧路径已关闭”。 + 一行 JSON 审计(`~/.chv-sync-fallback-audit.log`)。round-12 + 修复轮第三轮(小项 A):审计的 `repo` 字段改记 `resolve_repo` + 解析后的仓目录(无参调用不再是空串,多仓时能分清是哪一仓回 + 落;解析失败即 die、不留审计)。旧镜像退役后应删掉该回落, + 改为无 worker 即 fail-closed;删除前不得声称“旧路径已关闭”。 5. **无真机验证**:本轮全部是代码 + 本地单测(含 worker 真 socket 回路 + 假 git runner)。真机待验证清单见 §4。