Files
gplan-2/.zcode/hooks/rule-delivery.sh
T

48 lines
3.3 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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