fix(chv-muse-r12fix3-3): 回落审计 repo 记解析后的仓目录(P6 小项 A)

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 项全过。
This commit is contained in:
host committed 2026-11-08 09:48:41 +00:00
1 parent 7cba3c2b21
commit 7784be0657
3 files changed
+30 -6

No files matched your search

+7 -3
View File
@@ -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
}
+18
View File
@@ -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")
+5 -3
View File
@@ -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。