12.6 案例一:文档改写后的自动测试与风险拦截

面向经管学生、研究者与从业者的 AI 智能体设计教材

作者

李学恒、林建浩、严翊歆

发布于

2026-05-11

12.6 配图

场景设定:你要让 Claude Code 批量改写项目里的 Markdown 文档,统一结构和语言风格,同时保持链接、标题层级和引用格式不被破坏。

如果只靠提示词提醒——“不要改到允许目录之外”“改完检查格式和链接”——仍可能漏掉。于是把它拆成两个 Hook。

写前拦截:PreToolUse 做路径与命令拦截

当 Claude Code 准备执行 WriteEdit 或 Bash 命令时,PreToolUse 先检查目标路径和操作类型:是否写到了允许目录之外、是否出现高风险命令、是否违反当前任务边界。如果检测到违规,立刻阻断操作并把原因回灌给当前会话。

.claude/settings.json 中配置:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash scripts/check_path_safety.sh"
          }
        ]
      }
    ]
  }
}

scripts/check_path_safety.sh 的核心逻辑是解析工具输入中的目标路径,检查是否落在允许范围内:

#!/usr/bin/env bash
# check_path_safety.sh — 拦截越界写入和高风险命令

ALLOWED_DIRS=("docs/" "content/" "outputs/")
BLOCKED_CMDS=("rm -rf" "sudo" "chmod 777")

INPUT="$CLAUDE_TOOL_INPUT"

for cmd in "${BLOCKED_CMDS[@]}"; do
  if echo "$INPUT" | grep -q "$cmd"; then
    echo "BLOCKED: 检测到高风险命令 '$cmd'" >&2
    exit 2
  fi
done

TARGET_PATH=$(echo "$INPUT" | sed -n 's/.*"file_path" *: *"\([^"]*\)".*/\1/p')
if [ -n "$TARGET_PATH" ]; then
  ALLOWED=false
  for dir in "${ALLOWED_DIRS[@]}"; do
    if [[ "$TARGET_PATH" == "$dir"* ]]; then
      ALLOWED=true
      break
    fi
  done
  if [ "$ALLOWED" = false ]; then
    echo "BLOCKED: 路径 '$TARGET_PATH' 不在允许目录内" >&2
    exit 2
  fi
fi

写后检查:PostToolUse 做文档格式验证

如果写入顺利执行,PostToolUse 立刻触发文档检查脚本——检查标题层级是否跳跃、相对链接是否失效、是否引入格式错误。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash scripts/check_doc_format.sh"
          }
        ]
      }
    ]
  }
}

写后检查不阻断流程,而是把问题回灌给模型,由模型决定是否修补。重点不是检查脚本多复杂,而是它在正确的时间点稳定触发。

四类机制的配合

机制 在本案例中的角色
提示层约束 说明改写目标、风格、禁改范围
Skill 组织”读取素材 -> 重组结构 -> 改写正文”的流程
Hooks 在写前拦截风险,在写后自动检查
测试闭环 根据检查结果决定是否进入修订
案例启发

判断一个 Hook 是否合格,看它有没有同时满足三点:触发点明确、责任单一、输出能立刻被当前工作流消费。