AI编码助手安全防护:Agent Guardrails开源项目详解与实践指南
1. 项目概述为AI编码助手戴上“紧箍咒”如果你和我一样每天都在和Cursor、Claude Code、VS Code Copilot这些AI编码助手打交道那你一定经历过那种又爱又恨的瞬间。助手能帮你快速生成代码效率提升肉眼可见但下一秒它可能就把你的API密钥写进了日志或者未经询问就执行了rm -rf这种高风险命令。更让人头疼的是这些错误往往不是一次性的——由于AI缺乏跨会话的持久记忆同样的坑你可能会反复踩。这种不安全感尤其是在团队协作或处理敏感项目时会严重制约我们放手使用AI的能力。Agent Guardrails代理护栏这个开源项目就是为了解决这个核心痛点而生的。它不是一个复杂的监控系统而是一个极其简单、开放的文件协议。你可以把它理解为给AI助手制定的“项目宪法”——一套写在项目根目录.agents/guardrails/文件夹下的Markdown规则文件。每次AI助手开始一个新的会话时它都会读取这些文件明确知道在这个项目里“什么事绝对不能做”。这与定义AI“能做什么”的 Agent Skills 协议形成了完美互补一个定义能力边界一个划定行为红线。这个项目的价值在于它的“文件优先”和“协议开放”理念。它不依赖某个特定的IDE或AI模型而是定义了一个标准格式。任何遵循此协议的IDE或AI客户端都能读取并遵守这些规则。这意味着你为项目定义的一套安全护栏无论是在Cursor、Claude Code还是未来的任何新工具中都能持续生效。对于开发者个人它是防止低级安全失误的“自动检查清单”对于团队它是一套可以通过Git版本控制来共享和演进的团队安全规范对于IDE厂商它则是一个清晰的、可以原生集成的行为约束协议实现标准。2. 核心设计思路为什么是文件协议2.1 解决AI的“健忘症”问题当前AI编码助手的工作模式本质上是“无状态”的。每次对话甚至每次调用工具都可以看作一个独立的上下文窗口。虽然系统提示词System Prompt能在单次会话内提供指导但它无法在项目层面持久化。你不可能每次都手动输入一长串“不要记录密钥、不要乱删文件、加包要问我”的规则。Agent Guardrails通过将约束规则物化为项目目录中的标准文件巧妙地解决了这个问题。AI助手在会话初始化时将这些文件内容作为上下文的一部分加载从而获得了跨会话的、项目专属的“行为记忆”。2.2 实现团队约束与个人自由的平衡在团队开发中统一的安全和质量标准至关重要。传统的做法是靠文档README、Wiki和代码审查时的口头提醒但这依赖于人的记忆和自觉极易遗漏。Agent Guardrails将团队共识编码为机器可读、可执行的规则文件。新人克隆仓库后npx guardrails-ref init一下所有安全护栏自动就位。AI助手在为他工作时会自动遵守这些团队级约束从源头避免了因个人疏忽或经验不足导致的合规性问题。同时项目负责人可以通过更新.agents/guardrails/中的文件轻松地将新的安全要求同步给所有团队成员和他们的AI助手。2.3 开放协议带来的生态优势项目选择定义一个开放的、基于文件的协议而非一个封闭的SaaS服务或插件是极具远见的。这带来了几个关键优势工具无关性规则一旦定义在任何实现了该协议的IDE或AI客户端中都能生效避免了供应商锁定。极低的采用成本开发者无需安装复杂的后台服务只需在项目中添加一个文件夹和几个Markdown文件。易于集成与扩展协议规范Specification和参考实现CLI完全开源任何团队都可以基于此构建自己的检查工具、CI/CD流水线集成甚至开发新的护栏模板。版本控制友好规则文件本身就是代码的一部分其变更历史、评审过程都可以通过Git来管理与项目生命周期完全同步。这种设计使得Agent Guardrails更像是一个“基础设施层”的标准为上层丰富的工具生态奠定了基础。3. 快速上手指南十分钟搭建你的第一道护栏3.1 环境准备与初始化开始使用Agent Guardrails几乎没有任何前置条件。你只需要一个Node.js环境用于运行其CLI工具guardrails-ref和一个你正在开发的项目目录。进入你的项目根目录执行初始化命令npx guardrails-ref init这个命令会完成以下几件事在项目根目录创建.agents/guardrails/文件夹结构。在该文件夹下创建一个示例护栏文件no-plaintext-secrets/GUARDRAIL.md这是一个关于“禁止明文记录密钥”的规则。尝试为你当前项目中已检测到的IDE如Cursor、Claude Code等添加一条规则引导AI在会话开始时读取GUARDRAIL.md文件。注意目前主流IDE尚未原生支持Agent Guardrails协议。init和后续的setup命令实际上是在IDE的特定配置位置如Cursor的.cursorrules文件添加一条文本指令告诉AI“请去读取GUARDRAIL.md并遵守它”。这是一种临时的、基于提示工程的适配方案。一旦未来IDE厂商原生集成此协议这些配置步骤将不再需要。如果你希望更干净地开始可以加上--minimal参数它只创建目录结构不添加示例文件和IDE配置npx guardrails-ref init --minimal3.2 为你的项目添加核心护栏初始化后你的护栏目录还是空的除了可能的示例。接下来就是根据项目类型添加具体的约束规则。项目提供了“预设包”Preset的概念可以一键添加一组相关的护栏。对于绝大多数项目我建议从default预设开始它包含了四个最核心、最通用的安全约束npx guardrails-ref add --preset default这四条护栏分别是no-plaintext-secrets: 防止在日志、代码或提交中泄露API密钥、密码等秘密信息。no-destructive-commands: 禁止未经明确批准执行rm -rf、DROP TABLE等破坏性命令。no-new-deps-without-approval: 添加新的npm/pip等依赖包前必须获得人工确认。require-commit-approval: 执行git commit或push前必须获得用户明确批准。如果你的项目是Web前端应用强烈建议再加一个frontend预设它包含了对可访问性、代码风格等方面的约束npx guardrails-ref add --preset frontend你也可以在一条命令中组合多个预设npx guardrails-ref add --preset default,frontend3.3 验证与查看已安装的护栏添加完成后如何确认一切就绪使用list和validate命令。# 列出当前项目所有已安装的护栏名称 npx guardrails-ref list . # 以紧凑格式列出方便脚本处理 npx guardrails-ref list . --compact # 验证所有护栏文件的格式是否正确 npx guardrails-ref validate . # 如果验证发现格式问题如空格、换行符可以尝试自动修复 npx guardrails-ref validate . --fixvalidate命令会检查每个GUARDRAIL.md文件的YAML前置元数据Frontmatter格式、文件结构等是否符合协议规范确保AI客户端能够正确解析。3.4 理解护栏文件的结构让我们打开一个具体的护栏文件看看比如.agents/guardrails/no-plaintext-secrets/GUARDRAIL.md。它的结构非常清晰--- name: no-plaintext-secrets description: Never log, print, or commit API keys, passwords, tokens, or other secrets in plaintext. scope: global severity: critical category: secrets triggers: - tool_call - code_generation - file_edit --- # Never log or commit secrets **Trigger:** You are about to log, print, write to a file, or commit code that contains an API key, password, token, or other secret. **Instruction:** Stop. Do not proceed. Secrets must never be exposed in plaintext. If you need to handle secrets, you must: 1. Ask the user for the secret value and store it in a secure way (e.g., environment variable, secret manager). 2. Use placeholders (e.g., YOUR_API_KEY_HERE) in code and documentation. 3. If logging is necessary, redact the secret completely (e.g., sk_...redacted). **Reason:** Plaintext secrets in logs, code, or commits are a severe security risk and can lead to account compromise, data breaches, and financial loss.文件分为两部分YAML Frontmatter元数据位于---之间用于机器解析。定义了护栏的名称、描述、作用范围全局/特定语言、严重程度、类别以及触发场景如工具调用、代码生成时。正文内容采用固定的“触发-指令-原因”Signs Pattern三段式结构用自然语言清晰地告诉AI在什么情况下Trigger应该怎么做Instruction以及为什么Reason。这部分是AI直接阅读和理解的内容。这种设计兼顾了机器可读性便于工具扫描、分类、管理和AI可理解性用自然语言明确指令非常精妙。4. 高级配置与管理打造团队级安全基线4.1 项目级策略文件.guardrails-ref.json当项目发展到一定阶段或者需要在团队中推行统一的护栏标准时仅仅依靠手动添加护栏就不够了。你需要一种方式来定义“这个项目必须满足哪些安全要求”。这就是.guardrails-ref.json文件的作用。在项目根目录创建这个文件你可以配置CI/CD流程中的检查策略{ validate: { requireGuardrails: true }, check: { requireGuardrails: true }, test: { minScorePercent: 80, requireCategories: [secrets, destructive, prompt], requireGuardrails: [ no-plaintext-secrets, no-destructive-commands, no-new-deps-without-approval ] } }validate和check: 设置requireGuardrails: true后如果项目里没有任何护栏文件相应的命令会执行失败返回非零退出码。这可以确保护栏机制被启用。test: 这是更强大的策略引擎。minScorePercent: 定义项目必须达到的最低安全分数通过npx guardrails-ref test .计算得出。requireCategories: 要求项目必须安装属于“秘密保护”、“破坏性命令”、“提示词安全”等类别的护栏。requireGuardrails: 明确要求必须安装的、具体的护栏名称列表。4.2 策略继承与组织级管理对于拥有多个项目的大型团队或组织你可以在一个中心位置如一个内部npm包或Git子模块定义组织级的默认策略然后让各个项目继承。假设你有一个共享目录.org-guardrails/policy里面包含了一个基础的.guardrails-ref.json。在各个项目里你的策略文件可以这样写{ extends: [../.org-guardrails/policy], test: { minScorePercent: 85 // 覆盖组织默认值要求更高 } }通过extends字段项目可以继承组织的安全基线比如必须安装的护栏列表同时又能根据项目特性进行局部覆盖。这极大地简化了多仓库的护栏策略管理。4.3 环境差异化配置使用Profiles不同环境对安全的要求可能不同。例如在CI流水线中你可能要求更严格而在本地开发时可能允许一些警告。Profiles功能可以帮你实现这一点。在.guardrails-ref.json中定义Profile{ test: { minScorePercent: 60 }, profiles: { ci: { test: { minScorePercent: 80 } }, strict: { test: { minScorePercent: 90, requireCategories: [secrets, destructive, tools, prompt] } } } }然后在执行命令时通过环境变量或命令行参数指定Profile# 使用CI环境配置 GUARDRAILS_REF_PROFILEci npx guardrails-ref test . # 或使用命令行参数 npx guardrails-ref test . --profile strict4.4 集成到开发工作流为了让护栏真正发挥作用需要将其集成到日常开发流程中。1. Git预提交钩子Pre-commit Hook这是最有效的防线之一可以在代码提交前自动检查护栏状态。项目提供了与Husky或pre-commit框架集成的示例。# 使用CLI快速添加到Husky钩子 npx guardrails-ref setup --pre-commit这会在你的pre-commit钩子中添加一条命令在每次执行git commit前运行npx guardrails-ref check . --require-guardrails确保提交时项目已配置了必要的护栏。2. 持续集成CI流水线在GitHub Actions、GitLab CI等中集成护栏检查确保合并到主分支的代码符合安全基线。# GitHub Action 示例 - name: Check Agent Guardrails uses: 9atar6/agent-guardrails/.github/actions/guardrailsmain with: path: . strict: true minScore: 70这个Action会运行检查如果护栏缺失或安全分数低于70分则CI流程失败。3. 本地实时监控在开发时你可以开启一个监听进程当护栏文件被修改时自动重新验证npx guardrails-ref watch .这能让你在编辑护栏规则后立刻得到反馈避免因格式错误导致规则失效。5. 护栏库深度解析从安全到质量的全面防护Agent Guardrails提供了一个丰富的、不断增长的护栏模板库。理解这些护栏的类别和用途能帮助你为项目构建最合适的防护体系。以下是对核心预设包的详细拆解5.1 安全Security预设包这是最关键的防护层专注于防止直接的安全漏洞和风险操作。执行npx guardrails-ref add --preset security会添加多达15条安全相关护栏主要包括秘密管理no-plaintext-secrets: 基石性规则杜绝密钥明文暴露。no-pii-in-output: 防止个人身份信息PII在日志、API响应中未脱敏输出。no-placeholder-credentials: 禁止使用类似“test_123”的假密钥提交代码必须要求用户提供或指引其正确配置环境变量。注入与越权no-eval-or-dynamic-code: 禁止使用eval()、new Function()等动态代码执行这是预防代码注入攻击的第一道防线。no-path-traversal: 对用户提供的文件路径进行校验防止../等路径遍历攻击。no-unsafe-html-injection: 在React/Vue等框架中禁止未经净化sanitization就直接使用dangerouslySetInnerHTML或类似属性防范XSS攻击。require-access-control: 在执行涉及敏感数据或管理员操作前必须进行角色或权限检查。no-client-only-access-control: 特别针对前端强调权限检查必须在服务端重复进行不能仅依赖前端逻辑。系统与操作安全no-destructive-commands: 覆盖rm -rf、数据库DROP/TRUNCATE、文件系统格式化等高风险命令。no-sudo-commands: 禁止未经批准使用sudo、su等提权命令。privilege-boundaries: 划定“禁区”如未经明确许可AI不得修改node_modules、.git目录、锁文件或.env文件。tools-permissions: 对AI可以调用的工具如执行shell、访问网络进行权限控制要求使用允许列表allowlist并设置调用阈值。实操心得对于任何涉及用户数据、外部API或线上环境的项目安全预设包应该是必选项。即使项目初期看起来简单未雨绸缪建立这些约束能从根本上杜绝一大类由AI助手“好心办坏事”引入的安全隐患。5.2 代码质量与最佳实践Quality预设包这个预设包npx guardrails-ref add --preset quality关注的是代码的可维护性、健壮性和开发者体验包含11条规则。代码健壮性require-tests: 在修改核心逻辑或添加新功能后AI应提示或协助编写相应的测试用例而不是直接提交未经测试的代码。no-raw-sql: 禁止编写未参数化的原始SQL字符串强制使用预处理语句或查询构建器这是防止SQL注入的又一道保险。no-magic-numbers: 要求为代码中的字面数字如超时时间5000、状态码404命名常量提高可读性和可维护性。no-silent-error-handling: 禁止捕获异常后什么都不做空的catch块必须记录日志或通知用户。架构与模式prefer-existing-code: 当项目中已存在实现相似功能的工具函数、组件或模块时AI应优先复用而不是重新实现一套。这有助于控制代码熵。database-migrations: 要求对数据库结构的任何变更都必须通过迁移文件migration进行禁止直接连接生产数据库执行ALTER TABLE。no-breaking-changes-without-versioning: 当AI建议的修改会破坏现有API公共函数、接口时必须同时提出版本号升级遵循SemVer或提供迁移方案。配置与维护no-unsafe-env-assumptions: 禁止代码直接假设某个环境变量一定存在必须包含存在性检查或提供回退fallback方案。require-documentation-updates: 当AI修改了函数行为、API接口或配置方式时必须同时更新对应的README、注释或Swagger文档。注意事项质量类护栏有时会与“快速实现功能”的目标产生轻微冲突。建议团队根据项目成熟度逐步引入。对于快速原型可以先关闭其中一些规则对于稳定维护期的项目则应该全部启用将其作为代码审查的自动化前哨。5.3 前端专项Frontend预设包针对Web前端项目的特殊场景定制npx guardrails-ref add --preset frontend。可访问性A11yrequire-accessibility: 这是前端护栏的重中之重。它要求AI在生成UI组件时必须考虑并添加必要的可访问性属性如图片的alt文本、交互元素的aria-*属性、键盘导航支持、以及足够的颜色对比度。这对于满足法律合规如WCAG和提升用户体验至关重要。用户体验UXrequire-loading-and-error-states: 强制要求为所有异步操作数据获取、表单提交提供加载中和错误状态UI避免界面无响应或白屏。require-form-validation: 生成的表单必须包含前端验证逻辑、字段级错误提示并且在提交出错后能保留用户已输入的内容。代码样式与维护no-inline-styles: 禁止在JSX/HTML元素上使用style{{color: red}}这样的内联样式强制使用CSS类、Styled Components或CSS-in-JS方案以保持样式可维护性和一致性。no-hardcoded-user-facing-strings: 用户界面上显示的文本标签、按钮文字、错误信息不能硬编码在组件里应该提取到国际化i18n文件或常量文件中为后续的多语言支持做准备。require-design-tokens: 颜色、字体大小、间距等样式值必须引用设计令牌Design Tokens如CSS变量或主题对象中的值而不是直接使用#ff0000、16px这样的硬编码值。这有助于实现设计与代码的同步以及主题切换。避坑技巧前端护栏的引入可能会显著改变AI生成代码的方式。建议在引入require-accessibility这类规则时配合提供项目的具体设计系统或组件库文档链接作为上下文这样AI能生成更符合你项目现有规范的、具备可访问性的代码而不是通用的、可能不匹配的实现。5.4 其他专业预设包API预设包(--preset api): 针对消费外部API的客户端。强调API调用的韧性超时、重试、降级、禁止硬编码URL、要求环境变量验证等。后端预设包(--preset backend): 在安全预设基础上增加针对服务端环境的约束如日志标准、版本管理、数据库迁移规范等。生产预设包(--preset production): 可视为一个“上线前检查清单”融合了测试、文档、迁移、XSS防护、服务端鉴权、日志、工具权限等要求确保代码具备上生产环境的基本质量。6. 自定义护栏开发打造属于你的规则虽然预设包覆盖了大部分场景但每个团队、每个项目都有其独特的流程和禁忌。Agent Guardrails的强大之处在于你可以轻松创建自定义护栏。6.1 手动创建护栏文件自定义护栏就是创建一个符合协议规范的Markdown文件。假设你想创建一个名为require-code-review-before-merge的护栏要求AI在创建Pull Request或合并代码前必须提及代码审查。在.agents/guardrails/目录下创建子文件夹require-code-review-before-merge。在该文件夹内创建GUARDRAIL.md文件。编辑文件内容如下--- name: require-code-review-before-merge description: Always remind the user that code changes should be reviewed by a teammate before merging. scope: global severity: high category: process triggers: - git_operation - conversation_summary --- # Require code review before merging **Trigger:** You have completed a significant code change, fixed a bug, or implemented a feature, and the user is about to merge it into the main branch. **Instruction:** Before proceeding, you must explicitly remind the user that this change should be reviewed by at least one other team member. You can suggest creating a Pull Request (GitHub/GitLab) or a Merge Request. Do not assume the change is ready to merge without human review. **Reason:** Code review is a critical quality gate that catches bugs, improves design, and shares knowledge across the team. Skipping review increases the risk of defects and technical debt entering the codebase.关键点在于YAML元数据要填写准确正文部分要用清晰、无歧义的自然语言描述触发场景、指令和原因。6.2 使用交互式脚手架对于不熟悉格式的用户CLI提供了交互式创建工具npx guardrails-ref scaffold my-custom-guardrail --interactive这个命令会一步步提示你输入护栏的名称、描述、严重程度、类别等并生成一个结构完整、带有注释的模板文件你只需要填充正文部分即可。6.3 测试与验证自定义护栏创建完成后务必运行验证命令npx guardrails-ref validate .确保你的自定义护栏格式正确。你还可以使用explain命令来查看所有护栏包括自定义的的人类可读摘要npx guardrails-ref explain .这会输出一个表格清晰展示每个护栏的作用、范围和触发条件方便团队新成员理解项目约束。6.4 分享与复用自定义护栏如果你创建了一个非常有用的自定义护栏可以通过以下方式在团队内共享Git子模块或子仓库将.agents/guardrails/目录设置为一个独立的Git仓库让多个项目引用。内部NPM包将护栏文件打包成一个npm包项目通过npx guardrails-ref add从包内安装。复制粘贴最简单直接将创建好的GUARDRAIL.md文件复制到其他项目的对应目录即可。经验之谈自定义护栏的“触发条件”Trigger描述至关重要。它需要足够具体能让AI准确识别场景但又不能过于狭窄。多从AI可能“犯错”的实际案例出发去构思Trigger并用项目中的特定术语如你们团队对“完成功能”的定义来描述效果会更好。7. 故障排查与效能评估7.1 常见问题与解决方案问题1AI助手似乎没有读取护栏规则。检查IDE配置运行npx guardrails-ref setup --check查看当前项目为哪些IDE配置了读取规则。如果输出为空或缺少你使用的IDE运行npx guardrails-ref setup --ide [ide-name]进行配置如cursor,claude。确认会话开始目前规则通常在AI开始一个新的“会话”Session或“聊天”Chat时加载。尝试关闭并重新打开与AI的对话窗口。检查规则文件路径和格式运行npx guardrails-ref validate .确保所有GUARDRAIL.md文件格式正确没有YAML语法错误。问题2validate或check命令执行失败。错误信息包含“Invalid frontmatter”说明某个护栏文件的YAML头部格式错误。使用npx guardrails-ref validate . --fix尝试自动修复如修正缩进、引号。如果不行手动检查该文件的---之间部分确保是合法的YAML。错误信息包含“No guardrails found”如果配置了requireGuardrails: true但项目中没有护栏文件命令会失败。请至少添加一个护栏如npx guardrails-ref add no-plaintext-secrets。命令未找到确保你在项目根目录执行命令并且node_modules/.bin在系统PATH中或者直接使用npx guardrails-ref。问题3AI在某些情况下仍然违反了护栏规则。护栏规则描述可能不够清晰检查对应护栏的“Trigger”描述。AI可能没有正确识别当前场景属于触发条件。尝试用更具体、更场景化的语言重写Trigger部分。规则冲突或优先级问题如果安装了多条规则理论上它们应同时生效。但如果AI收到矛盾的指令极少发生它可能会困惑。确保你的规则之间没有逻辑上的直接冲突。AI模型限制目前的实现依赖于AI模型对自然语言指令的理解和遵循能力。虽然GPT-4等模型在此方面表现优异但并非100%可靠。护栏是一种强大的约束和提醒但不能替代开发者的最终审查。7.2 安全效能评估test命令详解guardrails-ref test命令是一个强大的评估工具它不仅仅检查护栏是否存在还会模拟一些常见的“攻击”或风险场景来评估当前护栏配置的实际防护效果。# 运行安全测试并给出分数 npx guardrails-ref test . # 要求最低分数为70分否则测试失败可用于CI npx guardrails-ref test . --min-score 70 # 生成一份Markdown格式的详细报告 npx guardrails-ref test . --report markdown guardrails-report.md # 生成HTML报告 npx guardrails-ref test . --report html report.html测试命令通常会检查以下几个方面覆盖率针对已知的风险类别如秘密泄露、破坏性命令检查是否有相应的护栏覆盖。规则有效性部分测试会尝试“触发”护栏看AI在模拟场景下是否会给出正确的阻止或提醒反应这需要与AI会话交互可能在某些环境下受限。配置完整性检查关键护栏如no-plaintext-secrets是否安装并配置正确。测试结果会给出一个百分比分数和详细的分类覆盖情况。这个分数是衡量项目AI安全基线的一个有用指标可以将其集成到CI/CD门禁中或者作为团队安全成熟度的一个跟踪指标。7.3 集成到IDE问题面板对于使用VS Code的开发者可以将护栏检查集成到“问题”Problems面板实现类似代码检查Lint的体验。按照项目文档在.vscode/tasks.json中创建任务。运行该任务后任何护栏文件的格式错误或验证警告都会显示在Problems面板中点击可以直接跳转到有问题的文件行。更进一步可以结合watch命令实现保存护栏文件后自动检查。这种深度集成将护栏从“后台规则”变成了可视化的、与编码环境融为一体的开发约束大大提升了其实用性和开发者体验。8. 项目演进与社区参与Agent Guardrails作为一个开源协议和工具集其价值会随着社区贡献的护栏模板和集成案例的增长而不断提升。关注协议更新定期运行npx guardrails-ref upgrade --dry-run可以查看是否有新的官方护栏模板或协议更新。保持更新能让你获得最新的安全实践。贡献你的护栏如果你创建了一个解决特定痛点例如针对某种特定云服务、框架或团队流程的优秀护栏考虑向官方examples/目录提交Pull Request。你的经验可以帮助成千上万的开发者。参与工具生态如果你使用的是尚未被guardrails-refCLI原生支持的IDE或AI编码工具可以查阅spec/client-implementation.md了解如何为其添加支持。或者你可以构建自己的插件或扩展来增强护栏的管理和可视化功能。从我个人的使用经验来看引入Agent Guardrails最大的转变在于心态。它让我从“时刻提防AI犯错”的紧张状态转变为“在明确的规则下与AI协作”的信任状态。我知道只要我定义好了红线AI就会在绝大多数时候自觉遵守。这不仅仅是增加了安全性更是解放了生产力让我能更专注于利用AI解决更复杂的逻辑问题而不是反复纠正那些本可以避免的低级错误。