工程+文档(车道恢复批·worktree铁律回归): 车道恢复2026-10-26前默认——主工作区只作合并落点,一切改动走独立worktree(建区即setup_worktree_userdir,收口=冻结→件核→并master→重塑→主区merge --no-ff→CI全量绿→删区,CI红回任务worktree修复合回);pre-commit直改闸随主区直改车道退役(tools/hooks/pre-commit删除+run_all_gates.sh摘在位自检段与--staged增量档,闸清单/域划分/判据零动);CI三件(ci_runner/post-merge/post-commit)零改动,验证模型不动;执法移交agent侧worktree-guard(本机件,合回后主区随动换代);规则四份随动: process-conventions §1四条重写+§2直改序列句+§3.4一切批建区+§3.8验收费注,AGENTS车道铁律/运行与验证/改动四类/五段铁律/规范导航行,architecture车道执法节(删pre-commit行+守卫职责换代+合回闸残句订正),test-conventions §4主区直提句摘除;孤立验证=worktree内--docs手动档全绿(06-08e+10),件核grep主区直改/直提/pre-commit仅剩退役凭据注记与豁免面说明
This commit is contained in:
1 parent
870b2f2bf6
commit
94628fca83
6 files changed
+32
-172
No files matched your search
@@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# 直改车道闸(git pre-commit,2026-10-30 本地 CI 化换代)——提交点现场跑文档域闸
|
||||
# (tools/run_all_gates.sh --docs,秒级文本扫描):绿=落地,红=中止。
|
||||
# 代码面提交不再拦(2026-10-30 用户裁:主区直改全面放开)——代码验证归合回后的本地 CI
|
||||
# (tools/hooks/post-merge 全量跑批;CI 红态下 tools/hooks/post-commit 追绿复验)。
|
||||
# 合并收尾提交跳过(MERGE_HEAD 在=冲突合并的收尾 commit)——内容归合回后的 CI 全量验。
|
||||
# --no-verify 绕过仅属用户(agent 侧由 worktree-guard 拦截)。
|
||||
set -u
|
||||
REPO="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# 合并收尾提交:跳过文档闸,交合回后 CI
|
||||
[ -f "$(git rev-parse --git-dir)/MERGE_HEAD" ] && exit 0
|
||||
|
||||
RC=0
|
||||
# 收暂存清单(增量档输入):quotepath 关闭保中文名原样,NUL 转行落临时文件传闸机
|
||||
_LIST="$(mktemp "${TMPDIR:-/tmp}/gates-staged.XXXXXX")" || _LIST=""
|
||||
if [ -n "$_LIST" ]; then
|
||||
git -C "$REPO" -c core.quotepath=false diff --cached --name-only -z | tr '\0' '\n' >"$_LIST"
|
||||
bash "$REPO/tools/run_all_gates.sh" --docs --staged "$_LIST" || RC=$?
|
||||
rm -f "$_LIST"
|
||||
else
|
||||
bash "$REPO/tools/run_all_gates.sh" --docs || RC=$?
|
||||
fi
|
||||
if [ "$RC" -eq 0 ]; then
|
||||
exit 0
|
||||
elif [ "$RC" -eq 1 ]; then
|
||||
echo "[直改闸] 文档域闸有新增红,提交已拦。修上方红项后重新 commit,钩子会自动重跑闸;禁跑代码域/游戏类测试,与本次红项无关。" >&2
|
||||
else
|
||||
echo "[直改闸] 闸脚本自身故障(退出码 $RC),不是文档红——把本输出原样呈报用户,勿改文档、勿跑替代测试。" >&2
|
||||
fi
|
||||
exit 1
|
||||
+10
-118
@@ -22,13 +22,6 @@
|
||||
# ——本批改动只有文档件时用:game/ 内的 .md(README、生成清单)、design/、根规则文件、
|
||||
# tools/ 工具脚本、.zcode/ 配置等一切非代码面改动。
|
||||
# --quick 全量档的中段自检形态:跳过渲染闸(窗口化,需开显示器)与静态扫描;完成出库禁用。
|
||||
# --staged <清单文件> 文档域增量档(仅配 --docs):清单=本次提交暂存文件(pre-commit 钩子生成,NUL 转行)。
|
||||
# 触发矩阵(唯一落点):任一 .md → 06/06b/07/08/08d 先按清单内 .md 扫描(快路径);
|
||||
# 待办清单.md/roadmap.md/reports/**.md 任一 → 08c 全量(关系型,不可切片);
|
||||
# design/gdd/systems/**、game/tests/README.md、reports/**.md 任一 → 08e 全量(关系型);
|
||||
# 10 熵增闸恒跑(结构哨兵)。快路径扫出红时全量复跑定谳——清单面外文件的失败不在全量档
|
||||
# 判定面内,全量复跑绿=按绿放行并注记,红=真红;增量判定面与 CI 全量档严格对齐,
|
||||
# 跨文件漏检面(改 A 断 B 的链)由合回后 CI 全量兜底。缺省不带 --staged = 现行全量档,CI 零影响。
|
||||
# 不带参数 = 全量档(两域全跑),触发条件=同批既有代码面改动又有文档件改动。闸件(tools/ 下机检脚本
|
||||
# 与闸壳)自身的改动不占合回全量——其质量义务=落批时人工确认闸可跑通且判据口径未变;
|
||||
# 闸真崩溃时合回闸 fail-closed(跑不出回执即拦),不以全量为兜底。
|
||||
@@ -54,24 +47,16 @@ BASELINE="$STAMP_DIR/baseline.json"
|
||||
|
||||
QUICK=0
|
||||
DOMAIN="full"
|
||||
STAGED_FILE=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--quick) QUICK=1 ;;
|
||||
--code|--docs)
|
||||
[ "$DOMAIN" = "full" ] || { echo "用法: --code 与 --docs 互斥"; exit 2; }
|
||||
DOMAIN="${1#--}" ;;
|
||||
--staged)
|
||||
[ -n "${2:-}" ] || { echo "用法: --staged <暂存清单文件>"; exit 2; }
|
||||
STAGED_FILE="$2"; shift ;;
|
||||
*) echo "用法: tools/run_all_gates.sh [--code|--docs|--quick] [--staged <清单文件>]"; exit 2 ;;
|
||||
*) echo "用法: tools/run_all_gates.sh [--code|--docs|--quick]"; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [ -n "$STAGED_FILE" ]; then
|
||||
[ "$DOMAIN" = "docs" ] || { echo "用法: --staged 仅配 --docs(增量档只定义在文档域)"; exit 2; }
|
||||
[ -f "$STAGED_FILE" ] || { echo "用法: --staged 清单文件缺位:$STAGED_FILE"; exit 2; }
|
||||
fi
|
||||
|
||||
# 每个代码面 worktree 用独立 Godot user 目录(game/override.cfg 由 setup 脚本自愈生成;主区 no-op)。
|
||||
# 并行批共用一套夹具、日志与截图目录会互相踩盘造成假红——隔离建不起来就拒跑(fail-closed)。
|
||||
@@ -88,23 +73,8 @@ fi
|
||||
# 与基线比必判「红项清单变化」假红)、末尾汇总自身崩掉打不出结论。
|
||||
export PYTHONIOENCODING=utf-8
|
||||
|
||||
# ── 直改闸在位自检(车道铁律):pre-commit 钩子失位=主区直改提交静默免验,任何跑批点红暴露 ──
|
||||
_HP="$(git -C "$REPO" config core.hooksPath)"
|
||||
if [ -n "$_HP" ]; then
|
||||
case "$_HP" in /*) _HPT="$_HP/pre-commit" ;; *) _HPT="$REPO/$_HP/pre-commit" ;; esac
|
||||
if [ ! -f "$_HPT" ]; then
|
||||
echo "[gates] FAIL — core.hooksPath=$_HP 但 pre-commit 文件缺位:直改闸失位,主区直改提交免验。"
|
||||
echo " 处置:确认 tools/hooks/pre-commit 在位后 git config core.hooksPath tools/hooks"
|
||||
exit 1
|
||||
fi
|
||||
elif [ ! -f "$(git -C "$REPO" rev-parse --git-path hooks)/pre-commit" ]; then
|
||||
echo "[gates] FAIL — core.hooksPath 未设置且默认钩子位无 pre-commit:主区直改提交免验。"
|
||||
echo " 自愈:git config core.hooksPath tools/hooks"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 代码面(game/ 下非 .md 的行为载体)是否带着未提交改动(只算已跟踪文件——闸件自身产物都落在
|
||||
# gitignore 面)。脏树跑出来的回执记的是 HEAD,验的却是别的字节,合回闸据此拒收。
|
||||
# gitignore 面)。脏树跑出来的回执记的是 HEAD,验的却是别的字节,回执标 dirty_game 由 CI 落账留痕。
|
||||
DIRTY_GAME=0
|
||||
if [ -n "$(git -C "$REPO" -c core.quotepath=false diff HEAD --name-only -- game/ 2>/dev/null | grep -viE '\.md$')" ]; then
|
||||
DIRTY_GAME=1
|
||||
@@ -357,38 +327,6 @@ gate() { # gate <名称> <日志名> <命令...>
|
||||
return 0
|
||||
}
|
||||
|
||||
# 增量文档检查壳(--staged 档专用):先按暂存清单扫(快路径),扫出红时全量复跑定谳——
|
||||
# 清单面外文件的失败不在全量档判定面内,全量复跑绿=按绿放行并注记,红=真红。
|
||||
# 增量判定面与 CI 全量档严格对齐(增量档不产生全量档不会有的红)。
|
||||
gate_docs_inc() { # gate_docs_inc <名称> <日志名> <全量命令...> -- <增量命令...>
|
||||
local name="$1" log="$2"; shift 2
|
||||
local -a full_cmd=() inc_cmd=()
|
||||
local _in_inc=0 _a
|
||||
for _a in "$@"; do
|
||||
if [ "$_a" = "--" ]; then _in_inc=1; continue; fi
|
||||
if [ $_in_inc -eq 0 ]; then full_cmd+=("$_a"); else inc_cmd+=("$_a"); fi
|
||||
done
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════"
|
||||
echo " $name(增量档:暂存 .md $(( ${#inc_cmd[@]} - ${#full_cmd[@]} )) 件)"
|
||||
echo "════════════════════════════════════════════"
|
||||
local rc=0
|
||||
"${inc_cmd[@]}" >"$STAMP_DIR/$log" 2>&1
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
"${full_cmd[@]}" >>"$STAMP_DIR/$log" 2>&1
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ]; then
|
||||
echo " [增量注记] 清单扫描出红、全量复跑绿——红项在暂存清单面外(不在全量档判定面内),按绿放行。"
|
||||
fi
|
||||
fi
|
||||
if [ $rc -ne 0 ]; then
|
||||
grep -E "FAIL|红|Error|error" "$STAMP_DIR/$log" | tail -12 | sed 's/^/ | /'
|
||||
fi
|
||||
NAMES+=("$name"); EXITS+=("$rc"); LOGS+=("$log")
|
||||
return 0
|
||||
}
|
||||
|
||||
gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分片态=多 Godot 进程各跑一片
|
||||
local name="02 单元与集成测试"
|
||||
# 关联档选跑:把套件词列表经 --only= 传给 run_all(闸机来源标记 --only-source=gates,
|
||||
@@ -478,60 +416,14 @@ fi
|
||||
fi
|
||||
# ══ 文档域(6–8e)══
|
||||
if in_domain docs; then
|
||||
# ── 增量触发矩阵(唯一落点,判据依据与漏检面见头注 --staged 段)──
|
||||
_md_list=()
|
||||
_trigger_08c=0
|
||||
_trigger_08e=0
|
||||
if [ -n "$STAGED_FILE" ]; then
|
||||
while IFS= read -r _f; do
|
||||
[ -z "$_f" ] && continue
|
||||
case "$_f" in
|
||||
待办清单.md|roadmap.md|reports/*) _trigger_08c=1 ;;
|
||||
esac
|
||||
case "$_f" in
|
||||
design/gdd/systems/*|game/tests/README.md|reports/*) _trigger_08e=1 ;;
|
||||
esac
|
||||
case "$_f" in
|
||||
*.md) [ -f "$REPO/$_f" ] && _md_list+=("$_f") ;;
|
||||
esac
|
||||
done < "$STAGED_FILE"
|
||||
fi
|
||||
if [ -z "$STAGED_FILE" ]; then
|
||||
# 全量档(CI 与手动档原路径,判定面不变)
|
||||
gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
|
||||
gate "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only
|
||||
gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
|
||||
gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
gate "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
else
|
||||
# 增量档:清单内 .md 走快路径(扫出红全量复跑定谳,见 gate_docs_inc)
|
||||
if [ "${#_md_list[@]}" -gt 0 ]; then
|
||||
gate_docs_inc "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py" -- "$PY" "$REPO/tools/gdd_lint.py" "${_md_list[@]}"
|
||||
gate_docs_inc "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only -- "$PY" "$REPO/tools/gdd_lint.py" --changelog-only "${_md_list[@]}"
|
||||
gate_docs_inc "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict -- "$PY" "$REPO/tools/doc_link_audit.py" --strict "${_md_list[@]}"
|
||||
gate_docs_inc "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict -- "$PY" "$REPO/tools/doc_term_audit.py" --strict "${_md_list[@]}"
|
||||
gate_docs_inc "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict -- "$PY" "$REPO/tools/doc_ref_audit.py" --strict "${_md_list[@]}"
|
||||
else
|
||||
for _n in "06 gdd_lint" "06b 变更记录节" "07 doc_link" "08 doc_term" "08d 引用可核"; do
|
||||
NAMES+=("$_n"); EXITS+=("SKIP"); LOGS+=("")
|
||||
done
|
||||
echo ""; echo "[gates] 06/06b/07/08/08d → SKIP(增量档:暂存清单无 .md)"
|
||||
fi
|
||||
if [ "$_trigger_08c" -eq 1 ]; then
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
else
|
||||
NAMES+=("08c 流水线闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 08c 流水线闸 → SKIP(增量档:登记面文件未触)"
|
||||
fi
|
||||
if [ "$_trigger_08e" -eq 1 ]; then
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
else
|
||||
NAMES+=("08e 能力审计"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 08e 能力审计 → SKIP(增量档:系统文档/能力清单/卡片未触)"
|
||||
fi
|
||||
fi
|
||||
# 全量档(CI 与手动档同判定面)
|
||||
gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
|
||||
gate "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only
|
||||
gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
|
||||
gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
gate "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
fi
|
||||
|
||||
# ── 7. 静态扫描(代码域)+ 熵增闸(两域都跑:它查顶层目录/根文件/图像白名单/退役路径,
|
||||
|
||||
Reference in new issue
Block a user