#!/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