Add evidence gates: facts registry, evidence tooling, and precheck checks
Why: declarations were passing as capability; hand-transcribed outputs flowed through cards and PR bodies as if they were execution evidence, and stale external facts (e.g. the dead git-panel host) kept being trusted until burned. Evidence: guidelines draft.10 (PR Development-Guidelines#4, merged af199ee) pinned here; policy/facts.md F1-F4 each re-verified on 2026-10-05 before registration (endpoint version, token HTTP 200 via header only, SSH ls-remote, dead-host negative probe); scripts syntax-checked (bash -n); tool self-tests and make test recorded in the task card via the new make evidence. Impact: new AGENTS.md section (SELF/REPLAY/GATE, tool-written evidence, replay-on-review, zero-trust facts, honest-empty); make evidence/facts-verify; precheck gains [hooks]/[facts], task-sync gains stale-evidence-HEAD warning; task-start cards now embed the evidence table; gitlink advances to draft.10. Refs: task card .task/feature-evidence-driven-gates.md; guidelines CHANGELOG 0.1.0-draft.10.
This commit is contained in:
@@ -6,11 +6,23 @@
|
||||
|
||||
- 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 602d2ce9c6900343155f2a9c7ccb4f1c83aa4a59
|
||||
- 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-evidence-driven-gates(worktree);分支:feature/evidence-driven-gates
|
||||
- 授权与交付终点:<本次允许的动作与终点;未授权事项写明>
|
||||
- 授权与交付终点:用户 2026-10-05 授权「按证据驱动方案完善规范」——guidelines 子模块(PR)+
|
||||
Dev 仓(AGENTS.md/policy/工具/Makefile/task.sh + gitlink 推进)经 `make test` 组合验证后
|
||||
PR 合入 main 并回收工作区。未授权:改前端/后端业务代码、解除分支保护、改写历史。
|
||||
|
||||
## 目标与非目标
|
||||
|
||||
<预期结果、受影响入口/模块/契约;明确不做什么。>
|
||||
目标:落地「声明≠能力」证据门禁——
|
||||
1) guidelines draft.10:证据来源三分 SELF/REPLAY/GATE、工具写入、审阅者重放、外部事实
|
||||
零信任、诚实出口(verification/collaboration/delivery/baseline/glossary/两模板/CHANGELOG)。
|
||||
2) Dev 仓:AGENTS.md「证据与验证门禁」节;policy/facts.md 事实登记表(F1–F4 实测后登记);
|
||||
scripts/evidence.sh(make evidence:命令×HEAD×sha256×尾部写入任务卡);
|
||||
scripts/facts-verify.sh(make facts-verify [--update]);task.sh:precheck 增 [hooks]/[facts],
|
||||
sync 增 [evidence] 旧 HEAD 告警,task-start 卡片模板带证据表;Makefile 增两目标。
|
||||
3) gitlink 推进至 guidelines 合入 SHA(af199ee),组合验证 make test。
|
||||
|
||||
非目标:task-close 核对 CI 状态(PR3 权威迁移)、CI 工作流改动、UI/业务代码、
|
||||
review 技能文本改造(后续任务)。
|
||||
|
||||
## 同步记录
|
||||
|
||||
|
||||
@@ -36,6 +36,29 @@
|
||||
`feature/card-close-*` 分支+PR,任务分支内加 `FOLD=--fold` 随当前 PR 合入。
|
||||
precheck 的 `[cards]` 行报告欠账,验收前应清零;闭合 PR 由所有者合入。
|
||||
|
||||
## 证据与验证门禁(强制)
|
||||
|
||||
原则:**「声明已就位」≠「能力已就位」**。任何来源(用户输入、方案、报告、他人或自己的
|
||||
叙述)的结果声明都不是证据;证据 = 命令 × 被测对象 SHA × 可复核输出,三者齐备才算事实。
|
||||
规范依据:guidelines `standards/verification.md`「声明与证据来源」(draft.10)。
|
||||
|
||||
- **来源三分**:产出物(任务卡、PR、报告、review 结论)中的通过类断言须标注来源——
|
||||
`GATE`(CI/分支保护/precheck 实测)/ `REPLAY`(审阅者独立重跑)/ `SELF`(作者粘贴)。
|
||||
合入与验收判定只认 GATE/REPLAY;SELF 仅为线索,与重验不一致时以重验为准。
|
||||
- **证据由工具写入**:命令输出进入任务卡/PR 一律经 `make evidence CMD="…"` 写入
|
||||
(自动记录命令、被测 HEAD、退出码、输出 sha256 与尾部摘录并脱敏 token)。手抄、转写、
|
||||
凭记忆重构的输出视为无效证据;补写输出与伪造测试同级红线。
|
||||
- **完成声明三段输出**(precheck / task-sync / 测试)必须由 evidence 工具写入任务卡,
|
||||
PR 描述引用任务卡段落,不另手抄。测试通过的权威源是 CI(`.gitea/workflows/ci.yaml`,
|
||||
在 PR HEAD 上 `make test`+`make build`),本地输出降级为辅助线索。
|
||||
- **验收即重放**:请求审核后,审阅者先在评审环境重放最小重放集(关键门禁命令 + 变更
|
||||
直接相关检查)再读作者证据;重放与声明不一致直接阻塞,并作为失实事件登记。
|
||||
- **外部事实零信任**:用户/文档/旧报告里的「可用/已就位」必须先执行 `policy/facts.md`
|
||||
登记表中对应验证命令(或当场实测)才能写进产出物;无法当场复核的结论标 `[未经证实]`,
|
||||
禁止裸写。登记表每条事实带 `last_verified` 与 TTL,precheck `[facts]` 报告过期项,
|
||||
`make facts-verify` 逐条重验。
|
||||
- **诚实出口**:未执行/未验证是合法状态,如实标注(NOT_RUN/未验证)优于补写。
|
||||
|
||||
## 提交与 PR
|
||||
|
||||
- 主题行:英文祈使句一行(≤100 列,不以句点结尾);body 写 `Why: / Evidence: / Impact: / Refs:`
|
||||
@@ -44,10 +67,14 @@
|
||||
- **高后果操作双钥匙**:改写历史、解除/变更分支保护、删除归档引用、发布版本——Agent 只准备
|
||||
方案与命令,由用户确认并亲手执行;Agent 不得自行实施(baseline 硬边界 1 的授权范围要求)。
|
||||
- 模块边界、公开契约与隔离档位见 `policy/modules/`(如有)与 PROJECT.md。
|
||||
- 验证命令见 PROJECT.md「验证」节;完成声明须附实际命令输出证据。
|
||||
- 验证命令见 PROJECT.md「验证」节;完成声明的三段输出按「证据与验证门禁」节由
|
||||
`make evidence` 写入任务卡,不手抄。
|
||||
- 首次克隆本仓后运行 `make setup` 启用本地 pre-commit 钩子。
|
||||
|
||||
## Gitea 与 Git 访问事实(2026-09-30 实测)
|
||||
## Gitea 与 Git 访问事实(2026-09-30 实测;登记表 `policy/facts.md`)
|
||||
|
||||
机器可核的登记表在 `policy/facts.md`(每条带验证命令、last_verified 与 TTL);
|
||||
引用任一事实前先跑其验证命令。以下为叙述版:
|
||||
|
||||
历史任务卡与旧脚本里的 `git-panel.u1680832.nyat.app:30319` 已失效(TLS 握手失败),
|
||||
见到一律按过期处理,不要再试。当前权威通道:
|
||||
|
||||
@@ -13,7 +13,7 @@ PLUGINS := plugins
|
||||
COMBO := core=$(shell git -C $(CORE) rev-parse --short HEAD 2>/dev/null)+backend=$(shell git -C $(BACKEND) rev-parse --short HEAD 2>/dev/null)+frontend=$(shell git -C $(FRONTEND) rev-parse --short HEAD 2>/dev/null)+ui=$(shell git -C $(UI) rev-parse --short HEAD 2>/dev/null)+agentcmd=$(shell git -C deps/agent-command rev-parse --short HEAD 2>/dev/null)+documents=$(shell git -C modules/documents rev-parse --short HEAD 2>/dev/null)+native=$(shell git -C deps/agent-native rev-parse --short HEAD 2>/dev/null)+squad=$(shell git -C deps/agent-squad rev-parse --short HEAD 2>/dev/null)+intent=$(shell git -C deps/agent-intent rev-parse --short HEAD 2>/dev/null)
|
||||
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null)+$(COMBO)
|
||||
|
||||
.PHONY: help sync status build frontend svc svc-list svc-info svc-commits svc-history svc-update test-backend test-frontend test-ui test-core test-agentcmd test-pins test-libs dev pin clean setup precheck task-start task-sync task-close task-finish version
|
||||
.PHONY: help sync status build frontend svc svc-list svc-info svc-commits svc-history svc-update test-backend test-frontend test-ui test-core test-agentcmd test-pins test-libs dev pin clean setup precheck task-start task-sync task-close task-finish facts-verify evidence version
|
||||
|
||||
version:
|
||||
@echo "agent-system $(VERSION)"
|
||||
@@ -22,7 +22,7 @@ TASK := scripts/task.sh
|
||||
|
||||
setup:
|
||||
git config core.hooksPath scripts/hooks
|
||||
chmod +x scripts/hooks/pre-commit scripts/hooks/post-merge scripts/task.sh
|
||||
chmod +x scripts/hooks/pre-commit scripts/hooks/post-merge scripts/task.sh scripts/evidence.sh scripts/facts-verify.sh
|
||||
@echo "OK: pre-commit/post-merge 钩子已启用(core.hooksPath=scripts/hooks)"
|
||||
|
||||
precheck:
|
||||
@@ -41,6 +41,16 @@ task-close:
|
||||
task-finish:
|
||||
@bash $(TASK) finish $(ABANDON)
|
||||
|
||||
# 证据写入:执行命令并把结果行追加进当前任务卡(AGENTS.md「证据与验证门禁」)。
|
||||
# 用法:make evidence CMD="<单行命令>" [SRC=SELF|REPLAY|GATE] [TAIL=15];退出码随被执行命令。
|
||||
evidence:
|
||||
@test -n "$(CMD)" || (echo 'usage: make evidence CMD="<command>" [SRC=SELF|REPLAY|GATE] [TAIL=15]'; exit 2)
|
||||
@CMD='$(CMD)' SRC='$(SRC)' TAIL='$(TAIL)' bash scripts/evidence.sh
|
||||
|
||||
# 外部事实登记表逐条重验(--update 刷新 PASS 项 last_verified)。
|
||||
facts-verify:
|
||||
@bash scripts/facts-verify.sh $(ARGS)
|
||||
|
||||
help:
|
||||
@echo "make sync 物化全部 submodule(递归)"
|
||||
@echo "make build 构建单二进制 bin/agent-system(契约同步→前端构建→embed→静态链接)"
|
||||
|
||||
Vendored
+1
-1
Submodule deps/development-guidelines updated: ed2af3e604...af199eeaa2
@@ -0,0 +1,16 @@
|
||||
# 项目外部事实登记表
|
||||
|
||||
规则见 AGENTS.md「证据与验证门禁」与 deps/development-guidelines/standards/verification.md「声明与证据来源」。
|
||||
|
||||
- 每条事实 = 陈述 + 验证命令 + last_verified + TTL;**引用前必须先执行其验证命令**(外部事实零信任)。
|
||||
- 过期(>TTL)必须重验后更新:`make facts-verify` 逐条重验,`make facts-verify ARGS=--update`
|
||||
把 PASS 项的 last_verified 刷新为当天并写回本表(随 PR 合入)。
|
||||
- 表内验证命令不得含竖线 `|`(保持表格与解析可核);新增事实先实测再登记,不得凭记忆填日期。
|
||||
- precheck 的 `[facts]` 行报告过期项;AGENTS.md「Gitea 与 Git 访问事实」节为本表的叙述版。
|
||||
|
||||
| ID | 事实 | 验证命令 | last_verified | TTL(天) |
|
||||
|---|---|---|---|---|
|
||||
| F1 | Gitea Web/API 可达:https://git-home.u1680832.nyat.app:30319(1.27.3) | `curl -fsS -m 10 https://git-home.u1680832.nyat.app:30319/api/v1/version` | 2026-10-05 | 30 |
|
||||
| F2 | API token 存在且可用(值在 ~/.secrets/gitea,不入仓不回显) | `t=$(sed -n "s/^ACCESS_TOKEN=//p" ~/.secrets/gitea); test -n "$t" && curl -fsS -m 10 -o /dev/null -H "Authorization: token $t" https://git-home.u1680832.nyat.app:30319/api/v1/user` | 2026-10-05 | 30 |
|
||||
| F3 | Git over SSH 可达:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/<Repo>.git(key ~/.ssh/home_gitea) | `GIT_SSH_COMMAND="ssh -i ~/.ssh/home_gitea -o BatchMode=yes" git ls-remote ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Development-Guidelines.git HEAD` | 2026-10-05 | 30 |
|
||||
| F4 | 旧端点 git-panel.u1680832.nyat.app:30319 已失效(TLS 握手失败),不得使用 | `! curl -fsS -m 8 https://git-panel.u1680832.nyat.app:30319/api/v1/version` | 2026-10-05 | 180 |
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
# 证据写入工具:执行命令,把(命令、被测 HEAD、退出码、输出 sha256、尾部摘录、时间、来源)
|
||||
# 追加到当前分支任务卡的「## 证据(Evidence)」表。规范依据:AGENTS.md「证据与验证门禁」、
|
||||
# guidelines standards/verification.md「声明与证据来源」——转写/手抄的输出视为无效证据。
|
||||
# 用法:make evidence CMD="<单行命令>" [SRC=SELF|REPLAY|GATE] [TAIL=15]
|
||||
# 退出码 = 被执行命令的退出码(失败可见),证据行无论成败都会写入。
|
||||
set -uo pipefail
|
||||
|
||||
CMD="${CMD:-}"; SRC="${SRC:-SELF}"; TAILN="${TAIL:-15}"
|
||||
[ -n "$CMD" ] || { echo 'usage: make evidence CMD="<command>" [SRC=SELF|REPLAY|GATE] [TAIL=15]' >&2; exit 2; }
|
||||
case "$SRC" in SELF|REPLAY|GATE) ;; *) echo "ERROR: SRC 须为 SELF|REPLAY|GATE(当前:$SRC)" >&2; exit 2 ;; esac
|
||||
case "$TAILN" in ''|*[!0-9]*) TAILN=15 ;; esac
|
||||
case "$CMD" in *$'\n'*) echo 'ERROR: CMD 须为单行命令' >&2; exit 2 ;; esac
|
||||
|
||||
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
[ -n "$branch" ] || { echo "ERROR: 不在 git 仓库内" >&2; exit 1; }
|
||||
slug=$(echo "$branch" | tr '/' '-')
|
||||
card=".task/${slug}.md"
|
||||
if [ ! -f "$card" ]; then
|
||||
# 回退:按卡片「分支:」字段匹配(与 task.sh cmd_sync 同款口径)
|
||||
for pc in .task/*.md; do
|
||||
[ -f "$pc" ] || continue
|
||||
if [ "$(sed -n 's/^- 工作区:.*分支:\([A-Za-z0-9._/-]\+\).*/\1/p' "$pc" | head -1)" = "$branch" ]; then
|
||||
card=$pc; break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
[ -f "$card" ] || { echo "ERROR: 找不到分支 ${branch} 的任务卡(.task/${slug}.md)" >&2; exit 1; }
|
||||
|
||||
head=$(git rev-parse HEAD)
|
||||
short_head=$(echo "$head" | cut -c1-10)
|
||||
ts=$(date -u +%FT%TZ)
|
||||
|
||||
tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT
|
||||
bash -c "$CMD" >"$tmp" 2>&1; rc=$?
|
||||
digest=$(sha256sum "$tmp" | cut -c1-16)
|
||||
|
||||
# 脱敏(baseline 硬边界 2):token 风格的 40 位 hex / Authorization 头不打进任务卡。
|
||||
sanitize() {
|
||||
sed -E -e 's/(token[ =:]+)[0-9a-fA-F]{40}/\1<redacted>/g' \
|
||||
-e 's/(Authorization: *token +)[^ ]+/\1<redacted>/Ig' \
|
||||
-e 's/(access_token[=:]+)[0-9a-fA-F]{40}/\1<redacted>/Ig'
|
||||
}
|
||||
|
||||
if ! grep -q '^## 证据(Evidence)' "$card"; then
|
||||
printf '\n## 证据(Evidence)\n\n<!-- make evidence CMD="…" 写入;手抄/转写输出视为无效证据(AGENTS.md 证据与验证门禁)。 -->\n| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) |\n|---|---|---|---|---|---|\n' >> "$card"
|
||||
fi
|
||||
cmd_cell=$(echo "$CMD" | sed -e 's/|/\\|/g' -e 's/`/‘/g')
|
||||
printf '| %s | `%s` | %s | %d | %s | %s |\n' "$ts" "$cmd_cell" "$short_head" "$rc" "$SRC" "$digest" >> "$card"
|
||||
printf '\n<!-- evidence:run %s -->\n```\n$ %s\n[exit %d | HEAD %s | sha256:%s] 输出尾部 %s 行:\n%s\n```\n' \
|
||||
"$ts" "$CMD" "$rc" "$short_head" "$digest" "$TAILN" "$(tail -n "$TAILN" "$tmp" | sanitize)" >> "$card"
|
||||
|
||||
echo "[evidence] card=$card cmd=\"${CMD}\" exit=$rc src=$SRC head=$short_head sha256=$digest"
|
||||
exit "$rc"
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# 外部事实登记表逐条重验:对 policy/facts.md 每条事实执行其验证命令并报告 PASS/FAIL。
|
||||
# 规则依据:AGENTS.md「证据与验证门禁」(外部事实零信任);verification.md「声明与证据来源」。
|
||||
# 用法:make facts-verify [ARGS=--update] (--update:把 PASS 项 last_verified 刷为当天并写回)
|
||||
# 表内验证命令约定不含竖线;含 "\|" 转义时按字面还原后执行。
|
||||
set -uo pipefail
|
||||
F="${FACTS:-policy/facts.md}"
|
||||
[ -f "$F" ] || { echo "ERROR: 事实登记表 $F 不存在" >&2; exit 1; }
|
||||
python3 - "$F" "${1:-}" <<'PY'
|
||||
import re, subprocess, sys, datetime
|
||||
path, update = sys.argv[1], sys.argv[2] == "--update"
|
||||
lines = open(path, encoding="utf-8").read().splitlines(keepends=True)
|
||||
today = datetime.date.today().isoformat()
|
||||
total = fails = 0
|
||||
for i, line in enumerate(lines):
|
||||
if not re.match(r"^\|\s*F\d+\s*\|", line):
|
||||
continue
|
||||
raw = line.strip().strip("|").replace("\\|", "\x00")
|
||||
cells = [c.strip().replace("\x00", "|") for c in raw.split("|")]
|
||||
if len(cells) < 4:
|
||||
print(f"[row {i+1}] SKIP 格式不符(列数<4)", file=sys.stderr)
|
||||
continue
|
||||
fid, cmd = cells[0], cells[2].strip("`")
|
||||
total += 1
|
||||
try:
|
||||
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=90)
|
||||
ok = r.returncode == 0
|
||||
except subprocess.TimeoutExpired:
|
||||
ok = False
|
||||
print(f"[{fid}] TIMEOUT >90s", file=sys.stderr)
|
||||
print(f"[{fid}] {'PASS' if ok else 'FAIL'} :: {cmd[:80]}")
|
||||
if not ok:
|
||||
fails += 1
|
||||
elif update and len(cells) >= 4 and re.match(r"\d{4}-\d{2}-\d{2}", cells[3]):
|
||||
cells[3] = today
|
||||
lines[i] = "| " + " | ".join(c.replace("|", "\\|") for c in cells) + " |\n"
|
||||
if update:
|
||||
open(path, "w", encoding="utf-8").writelines(lines)
|
||||
print(f"[facts-verify] total={total} pass={total - fails} fail={fails}"
|
||||
+ (";last_verified 已刷新为 " + today if update and total else ""))
|
||||
sys.exit(1 if fails else 0)
|
||||
PY
|
||||
+43
-1
@@ -59,6 +59,34 @@ cmd_precheck() {
|
||||
fi
|
||||
done < <(git for-each-ref --format='%(refname:short) %(committerdate:unix)' "refs/remotes/origin/feature/card-close-*")
|
||||
[ -n "$stale" ] && echo "[cards] 闭合分支超过 24 小时未合入:$(echo $stale)"
|
||||
# [hooks] 声明≠能力:core.hooksPath 未指向 scripts/hooks 时,"钩子已启用"只是声明。
|
||||
local hp; hp=$(git config core.hooksPath 2>/dev/null || true)
|
||||
if [ "$hp" = "scripts/hooks" ] && [ -x scripts/hooks/pre-commit ]; then
|
||||
echo "[hooks] core.hooksPath=scripts/hooks(pre-commit/post-merge 实际接线)"
|
||||
else
|
||||
echo "[hooks] WARN core.hooksPath='${hp:-未设置}'——本地钩子未生效,先 make setup;本检出提交将绕过本地闸(远端准入仍在)"
|
||||
fi
|
||||
# [facts] 外部事实登记表过期项(policy/facts.md;引用前先跑其验证命令,AGENTS.md 证据与验证门禁)。
|
||||
if [ -f policy/facts.md ]; then
|
||||
local fid lv ttl expired="" ftotal=0
|
||||
while IFS='|' read -r _ fid _ _ lv ttl _; do
|
||||
fid=$(echo "${fid:-}" | tr -d ' '); case "$fid" in F[0-9]*) ;; *) continue ;; esac
|
||||
ftotal=$((ftotal+1))
|
||||
lv=$(echo "$lv" | tr -d ' '); ttl=$(echo "$ttl" | tr -d ' ')
|
||||
case "$lv" in [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]) ;; *) expired="$expired ${fid}(日期格式)"; continue ;; esac
|
||||
case "$ttl" in ''|*[!0-9]*) ttl=30 ;; esac
|
||||
if [ $(( $(date +%s) - $(date -d "$lv" +%s) )) -gt $(( ttl*86400 )) ]; then
|
||||
expired="$expired ${fid}(last=${lv},ttl=${ttl}d)"
|
||||
fi
|
||||
done < <(grep -E '^\| *F[0-9]+ ' policy/facts.md || true)
|
||||
if [ -n "$expired" ]; then
|
||||
echo "[facts] WARN 过期事实:$(echo $expired)——引用前先 make facts-verify 重验并更新登记表"
|
||||
else
|
||||
echo "[facts] policy/facts.md ${ftotal} 条事实均在有效期内"
|
||||
fi
|
||||
else
|
||||
echo "[facts] WARN policy/facts.md 不存在——外部事实登记表缺失(AGENTS.md 证据与验证门禁)"
|
||||
fi
|
||||
echo "[required-reading] core/baseline.md, workflows/delivery.md §1$([ "$dirty" -gt 0 ] && echo ", standards/collaboration.md(树脏=他人或未收尾现场,不得写入)")"
|
||||
echo "[R0] $(echo "$rmain" | cut -c1-10)(完整:$rmain)"
|
||||
if [ "$dirty" -gt 0 ] || [ "${sub_drift:-0}" -gt 0 ]; then
|
||||
@@ -120,10 +148,16 @@ cmd_start() {
|
||||
|---|---|---|---|
|
||||
| 启动 | ${rmain} | $(git -C "$wt" rev-parse HEAD) | $(date -u +%FT%TZ) |
|
||||
|
||||
## 证据(Evidence)
|
||||
|
||||
<!-- make evidence CMD="…" 写入;手抄/转写输出视为无效证据(AGENTS.md 证据与验证门禁)。 -->
|
||||
| 时间(UTC) | 命令 | 被测HEAD | exit | 来源 | sha256(16) |
|
||||
|---|---|---|---|---|---|
|
||||
|
||||
## 结果与验证(完成后填写)
|
||||
|
||||
- 结果:
|
||||
- 验证:
|
||||
- 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表>
|
||||
- 影响与剩余项:
|
||||
EOF
|
||||
git -C "$wt" add .task && git -C "$wt" commit -q -m "Record the task card for ${slug}" && echo "[card] $card(已随分支提交)"
|
||||
@@ -155,6 +189,14 @@ cmd_sync() {
|
||||
printf '| 同步前验收 | %s | %s | %s |\n' "$base" "$head" "$(date -u +%FT%TZ)" >> "$card"
|
||||
git add "$card"
|
||||
git commit -q -m "Record the sync checkpoint" || true
|
||||
# [evidence] 同步改变了被测对象:卡片证据表中旧 HEAD 的行自动失效,关键检查须重跑。
|
||||
local eh stale_ev="" short_head
|
||||
short_head=$(echo "$head" | cut -c1-10)
|
||||
while IFS='|' read -r _ _ _ eh _ _ _; do
|
||||
eh=$(echo "$eh" | tr -d ' `')
|
||||
[ -n "$eh" ] && [ "$eh" != "$short_head" ] && stale_ev="$stale_ev $eh"
|
||||
done < <(grep -E '^\| [0-9]{4}-[0-9]{2}-[0-9]{2}T[^|]*\|' "$card" 2>/dev/null || true)
|
||||
[ -n "$stale_ev" ] && echo "[evidence] WARN 证据表含旧被测 HEAD:$(echo $stale_ev | tr ' ' '\n' | sort -u | tr '\n' ' ')(≠ 当前 $short_head)——同步后关键检查须重跑并以 make evidence 重新写入"
|
||||
else
|
||||
echo "[warn] 找不到分支 ${branch} 的任务卡,同步记录未写入" >&2
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user