Refactor code structure for improved readability and maintainability

This commit is contained in:
DKChan committed 2026-11-09 02:53:10 +08:00
1 parent 6bfd8009a2
commit a710477be2
47 files changed
+5357 -5

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# 规约投递闸(PostToolUse:Read | mcp__node_repl__js,2026-10-26 立)
# 干两件事:①读到 design/、game/ 下的文件时把对应规约要点注入上下文(每会话每域一次);
# ②读到四份规约本体时在读取记录里记 read: 标记——worktree-guard 的规则闸据此放行写入。
# 记录文件:${TMPDIR:-/tmp}/zcode-rule-ledger/<会话ID>.ledger,纯文本,会话结束自然失效。
# 本钩子创建记录文件这一行为本身是规则闸的启用条件(闸只在记录文件存在时生效,
# 保证「写标记的钩子活着」与「闸执法」永远成对出现)。解析异常一律静默放行。
SID="${CLAUDE_SESSION_ID:-}"
[ -z "$SID" ] && exit 0
LEDGER_DIR="${TMPDIR:-/tmp}/zcode-rule-ledger"
LEDGER="$LEDGER_DIR/$SID.ledger"
mkdir -p "$LEDGER_DIR" 2>/dev/null
touch "$LEDGER" 2>/dev/null || exit 0
payload="$(cat)"
# 目标路径:优先 file_path 字段;node_repl 等无 file_path 的载荷退化为全文找 design/、game/ 路径段
target="$(printf '%s' "$payload" | sed -n 's/.*"file_path" *: *"\([^"]*\)".*/\1/p' | head -1 | sed 's#\\\\#/#g; s#\\#/#g')"
[ -z "$target" ] && target="$(printf '%s' "$payload" | grep -oE '(design|game)/[A-Za-z0-9_./-]+' | head -1)"
[ -z "$target" ] && exit 0
low="$(printf '%s' "$target" | tr 'A-Z' 'a-z')"
# 规约本体:记 read: 标记(每份只记一次),不投递
case "$low" in
*doc-conventions.md) grep -q '^read:doc-conventions.md$' "$LEDGER" 2>/dev/null || printf 'read:doc-conventions.md\n' >> "$LEDGER"; exit 0 ;;
*concept-conventions.md) grep -q '^read:concept-conventions.md$' "$LEDGER" 2>/dev/null || printf 'read:concept-conventions.md\n' >> "$LEDGER"; exit 0 ;;
*code-conventions.md) grep -q '^read:code-conventions.md$' "$LEDGER" 2>/dev/null || printf 'read:code-conventions.md\n' >> "$LEDGER"; exit 0 ;;
*test-conventions.md) grep -q '^read:test-conventions.md$' "$LEDGER" 2>/dev/null || printf 'read:test-conventions.md\n' >> "$LEDGER"; exit 0 ;;
esac
domain=""
case "$low" in
*/design/*|design/*) domain=doc ;;
*/game/*|game/*) domain=code ;;
esac
[ -z "$domain" ] && exit 0
# 域投递:每会话每域一次(文案单行、无内部双引号,保 JSON 字面合法)
if ! grep -q "^DELIVERED:$domain$" "$LEDGER" 2>/dev/null; then
if [ "$domain" = doc ]; then
msg='【规约投递】你正在读 design/ 下的文件。定文档方案/动笔前必须先完整读 design/engineering/doc-conventions.md 与 concept-conventions.md。要点提醒:正文单点维护(引用写指针不复制具体值);附加物独立成对象(禁摊平成父概念属性);概念状态用封闭枚举;禁自造黑话;文档增删同步根索引 02-系统清单。写 design/ 前无读取记录会被规则闸拦截。'
else
msg='【规约投递】你正在读 game/ 下的文件。定代码/测试方案前必须先完整读 design/engineering/code-conventions.md 与 test-conventions.md。要点提醒:数值单一事实源(data/tables 的 .tres 经 ConfigDB);RNG 单点(禁 randomize 与自建 RNG);Core 层零 UI 依赖;fail-fast;验收断言从真实入口进入,禁变异类测试与撤销类取证。写 game/ 前无读取记录会被规则闸拦截。'
fi
printf '{"additionalContext":"%s"}\n' "$msg"
printf 'DELIVERED:%s\n' "$domain" >> "$LEDGER"
fi
exit 0
+195
View File
@@ -0,0 +1,195 @@
#!/usr/bin/env bash
# agent 侧守卫(PreToolUse,本机件不入 git;2026-10-31 车道恢复随动——worktree 铁律回归)
# 拦四路:①Edit/Write 族写主工作区(主工作区只作合并落点;豁免 .zcode/ 与 .qoder/)
# ②Bash 在主工作区一切 git commit 一律拦(直提走 worktree;冲突/红态续合=git merge --abort → 回 worktree → 重新 git merge --no-ff,合并收尾提交不再例外)
# ③Bash 在主工作区 git commit 带 --no-verify/-n(agent 禁用,旗标仅属用户)
# (合回 merge 零机检,全量验证归合回后本地 CI:tools/hooks/post-merge)
# ④规则闸:Edit/Write 写 design/、game/,或 Bash 以文件触碰动词+路径命中两域时,
# 本会话读取记录须含对应规约 read: 标记(PostToolUse 规约投递闸读规约本体时记入;
# 记录文件不存在=投递闸未运行→本闸不启用;子代理不经守卫层,2026-10-26 实测)
# 附快速通道:Edit/Write 族目标在主工作区外(worktree)→ 免 python+git 直接过
# pre-commit 直改闸已随主区直改车道退役(commit 点零执法,全量验证归合回后本地 CI);
# 本守卫只约束 agent,用户手工改动不受限
# 退出码 2 = 拦截(stderr 回传模型);0 = 放行;任何解析异常一律放行(守卫是兜底,不能挡死会话收口)
proj="${ZCODE_PROJECT_DIR:-$PWD}"
_payload=""
IFS= read -r -d '' _payload || true # 内建全量读 stdin;临时文件只在走 python 路时才落
# ── 规则闸+快速通道(2026-10-26 立,规约投递闸配套;纯 bash 内建,零额外进程)────────────
# 规则闸:Edit/Write 写 design/、game/,或 Bash 命令以文件触碰动词+路径命中两域时,
# 本会话读取记录须含对应规约 read: 标记(PostToolUse 规约投递闸读规约本体时记入);
# 记录文件不存在=投递闸未运行(含子代理——不经守卫层,2026-10-26 实测)→ 本闸不启用。
# 快速通道:Edit/Write 族目标在主工作区外(worktree)→ 车道判定本就放行,免 python+git 直接过。
# 两段都遵守总纲:解析异常一律放行。
_rg_norm() { # 路径归一:反斜杠→斜杠、小写、/d/ 形转 d:/ 形、折叠重复斜杠(内建零进程)
local p="${1//\\//}"
p="${p,,}"
[[ $p =~ ^/([a-z])/(.*)$ ]] && p="${BASH_REMATCH[1]}:/${BASH_REMATCH[2]}"
while [[ $p == *"//"* ]]; do p="${p//\/\//\/}"; done
printf '%s' "$p"
}
_rg_tool=""; _rg_fp=""
[[ $_payload =~ \"tool_name\"[[:space:]]*:[[:space:]]*\"([^\"]*)\" ]] && _rg_tool="${BASH_REMATCH[1]}"
[[ $_payload =~ \"file_path\"[[:space:]]*:[[:space:]]*\"([^\"]*)\" ]] && _rg_fp="${BASH_REMATCH[1]}"
[ -z "$_rg_fp" ] && [[ $_payload =~ \"notebook_path\"[[:space:]]*:[[:space:]]*\"([^\"]*)\" ]] && _rg_fp="${BASH_REMATCH[1]}"
_rg_low="$(_rg_norm "$_rg_fp")"
_rl_sid="${CLAUDE_SESSION_ID:-}"
_rl_ledger="${TMPDIR:-/tmp}/zcode-rule-ledger/${_rl_sid}.ledger"
if [ -n "$_rl_sid" ] && [ -f "$_rl_ledger" ]; then
_rl_marks="$(<"$_rl_ledger")"
_rg_need() { # 域规约标记齐备→0(内建子串匹配,零进程)
if [ "$1" = doc ]; then
[[ $_rl_marks == *read:doc-conventions.md* && $_rl_marks == *read:concept-conventions.md* ]]
return
fi
[[ $_rl_marks == *read:code-conventions.md* && $_rl_marks == *read:test-conventions.md* ]]
}
_rg_block() { printf '%s\n' "$1" >&2; exit 2; }
case "$_rg_tool" in
Edit|Write|MultiEdit|NotebookEdit)
case "$_rg_low" in
*/design/*|design/*)
_rg_need doc || _rg_block "[规则闸] 写入 design/ 前本会话未读过 doc-conventions.md 与 concept-conventions.md——先用 Read 完整读这两份规约再继续(读完自动记读取记录)。" ;;
*/game/*|game/*)
_rg_need code || _rg_block "[规则闸] 写入 game/ 前本会话未读过 code-conventions.md 与 test-conventions.md——先用 Read 完整读这两份(或把读文件操作改用 Read 工具),读完自动记读取记录。" ;;
esac
;;
Bash)
# 命令文本(含描述字段)里「文件触碰动词+域路径」同现 → 按域核对读取记录
_lp="${_payload,,}"
if [[ $_lp =~ (^|[^a-z])(cat|head|tail|sed|less|more|grep|rg|awk|find|cp|mv|tee|wc|sort|diff)([^a-z]|$) || $_lp == *">"* ]]; then
[[ $_lp =~ (^|[^a-z])design/ ]] && { _rg_need doc || _rg_block "[规则闸] 用 Bash 触碰 design/ 前本会话未读过 doc-conventions.md 与 concept-conventions.md——先用 Read 完整读这两份(或把读文件操作改用 Read 工具),读完自动记读取记录。"; }
[[ $_lp =~ (^|[^a-z])game/ ]] && { _rg_need code || _rg_block "[规则闸] 用 Bash 触碰 game/ 前本会话未读过 code-conventions.md 与 test-conventions.md——先用 Read 完整读这两份(或把读文件操作改用 Read 工具),读完自动记读取记录。"; }
fi
;;
esac
fi
# 快速通道:Edit/Write 族且目标路径在主工作区外(worktree)——车道判定本就放行,免 python+git
case "$_rg_tool" in
Edit|Write|MultiEdit|NotebookEdit)
_rg_projn="$(_rg_norm "$proj")"
if [ -n "$_rg_fp" ] && [ "${_rg_low#"$_rg_projn"/}" = "$_rg_low" ]; then
exit 0
fi
;;
esac
tmp="$(mktemp)"
printf '%s' "$_payload" > "$tmp"
projw="$(cygpath -w "$proj" 2>/dev/null || echo "$proj")"
python - "$projw" "$(cygpath -w "$tmp" 2>/dev/null || echo "$tmp")" <<'PY'
import json, os, re, subprocess, sys
try:
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
except Exception:
pass
def winpath(p):
# MSYS 风格路径(/d/...)原生 Windows Python 不识别,统一转 Windows 形式
if isinstance(p, str) and re.match(r"^/[A-Za-z](/|$)", p):
try:
r = subprocess.run(["cygpath", "-w", p], capture_output=True, text=True, timeout=5,
encoding="utf-8", errors="replace")
return r.stdout.strip() or p
except Exception:
return p
return p
proj = os.path.abspath(winpath(sys.argv[1]))
try:
with open(sys.argv[2], encoding='utf-8') as f:
d = json.load(f)
except Exception:
sys.exit(0)
tool = d.get("tool_name") or d.get("tool") or ""
ti = d.get("tool_input") or {}
cwd = os.path.abspath(winpath(d.get("cwd") or proj))
def in_dir(p, root):
p = os.path.normcase(os.path.abspath(p))
root = os.path.normcase(os.path.abspath(root))
return p == root or p.startswith(root.rstrip('\\/') + os.sep)
def trunk_branch(repo):
try:
r = subprocess.run(["git", "-C", repo, "branch", "--show-current"],
capture_output=True, text=True, timeout=5,
encoding="utf-8", errors="replace")
return r.stdout.strip()
except Exception:
return ""
TRUNK = {"master", "main"}
# 车道铁律(2026-10-31 恢复):主工作区只作合并落点——agent 的 Edit/Write 族写主工作区即拦;
# 豁免 .zcode/ 与 .qoder/(本机件不入 git,worktree 带不进去);worktree 目标已在快速通道放行
if tool in ("Edit", "Write", "MultiEdit", "NotebookEdit"):
fp = ti.get("file_path") or ti.get("notebook_path") or ""
if fp:
fpn = os.path.abspath(winpath(fp))
if in_dir(fpn, proj):
rel = os.path.relpath(fpn, proj).replace("\\", "/").lower()
if not rel.startswith(".zcode/") and not rel.startswith(".qoder/"):
sys.stderr.write(
"[车道铁律] 主工作区只作合并落点,改动走独立 worktree——"
"git worktree add ../g-plan2-<任务名> -b <任务分支>,在区里改与提交;"
"豁免面仅 .zcode/ 与 .qoder/。\n")
sys.exit(2)
sys.exit(0)
cmd = ti.get("command", "") or ""
toks = cmd.split()
has_commit = False
for i, t in enumerate(toks):
if t.rstrip(';') != 'git':
continue
j = i + 1
while j < len(toks) and j - i <= 5:
u = toks[j].rstrip(';')
if u == "commit":
has_commit = True
break
if u.startswith("-"):
if u in ("-C", "--git-dir", "-c") and j + 1 < len(toks):
j += 2
continue
j += 1
continue
break
# 主工作区判定:cwd 在内,或命令文本里显式指到主工作区路径(不含 worktree 兄弟目录)
norm = cmd.replace("\\", "/").lower()
ref_main = re.search(r"/d/code/g-plan2(?![\w-])", norm) or re.search(r"d:/code/g-plan2(?![\w-])", norm)
ref_wt = re.search(r"/g-plan2-[\w-]+", norm)
sibling = bool(ref_wt) and not ref_main
on_trunk = trunk_branch(proj) in TRUNK
in_main = (in_dir(cwd, proj) or bool(ref_main)) and on_trunk
if not in_main or sibling:
sys.exit(0)
# 车道铁律(2026-10-31 恢复):主工作区禁止一切 git commit——令回 worktree;合并类命令不在本分支,
# 冲突/前置检查红态(MERGE_HEAD 在)的 git commit 续合同拦——一律 abort → 回 worktree → 重新 git merge --no-ff
if has_commit:
# --no-verify/-n 仅属用户紧急出口,agent 禁用(词法匹配兜底;
# 只扫 -m 之前的参数区,防 commit 消息里提及该旗标名造成误拦)
_flag_zone = toks
for _i, _t in enumerate(toks):
if _t.rstrip(';') == "-m":
_flag_zone = toks[:_i]
break
if any(u.rstrip(';') in ("--no-verify", "-n") for u in _flag_zone):
sys.stderr.write(
"[车道铁律] git commit --no-verify 仅属用户紧急出口,agent 禁用——"
"移除该旗标重新提交;改动走独立 worktree。\n")
sys.exit(2)
# 主区一切 git commit 一律拦(含 MERGE_HEAD 态续合),不再探测 MERGE_HEAD;
# 合并提交只由 git merge --no-ff 一步落地,两合回钩子必触发。
sys.stderr.write(
"[车道铁律] 主工作区禁止一切 git commit(含 MERGE_HEAD 态续合)——改动走独立 worktree;"
"主区唯一合法写动作=git merge --no-ff。"
"若正处合并冲突/前置检查红态:一律 git merge --abort → 回 worktree 处理 → 重新 git merge --no-ff <任务分支>。\n")
sys.exit(2)
sys.exit(0)
PY
rc=$?
rm -f "$tmp"
exit $rc