先划清边界
AI 编程助手接收指令、上下文和工具。项目规则文件可以改善一致性,但它仍然是模型输入,可能被忽略、误解、被不可信内容覆盖,或因为过时而失效。
指令适合表达:
- Repository 规范和示例;
- 任务范围和输出格式;
- 助手可以建议的命令;
- 验证步骤和升级路径;
- 权威项目文档的位置。
确定性系统应负责:
- 身份和 Repository 访问;
- Secret 和凭证;
- 命令与网络 Egress;
- 依赖和 License Policy;
- Tests、Formatter、Static Analysis 和 Merge 审批;
- 部署、删除、付款等副作用。
“永远不要泄露 Secret”是有用的指导,不是 Secret 边界。模型拒答也不能证明某个命令无法执行。
从契约开始
写规则前先回答:
- 谁拥有 Repository 和变更?
- 哪些目录和服务在范围内?
- 指令冲突时哪个文件是权威来源?
- 哪些命令只读、会修改、联网或具有破坏性?
- 提案或合并前需要什么证据?
- 哪些动作必须升级给人?
- 如何测试、审查、版本化和移除配置?
短契约比长 Persona 更容易测试:
Scope:
本任务只修改 packages/billing。
Source of truth:
遵循已提交的 API Schema 和生成类型。
如果冲突,停止并报告冲突。
Change policy:
优先最小兼容变更。
未获批准不得修改依赖、Migration、CI 或部署文件。
Verification:
运行项目规定的 Formatter、Type Checker 和相关 Tests。
报告命令、失败项和未验证假设。
Escalation:
外部写入、Secret 访问、数据删除和大范围重构前请求批准。
不同产品和版本的指令文件名称与语法会变化。选择路径或 Frontmatter 前,应核对当前 Provider 文档。Repository 契约应尽量与 Provider 无关,以便替换工具。
按信任和生命周期分层上下文
不要把所有内容塞进一个巨大 Prompt:
| 层级 | 示例 | 变更负责人 | 信任程度 |
|---|---|---|---|
| Repository Facts | 构建命令、架构、API Schema | Repository | 已审查 |
| Task Context | Issue、Diff、验收标准 | Task Owner | 不同 |
| Generated Context | Index 结果、摘要、Tool 输出 | Runtime | 未验证前不可信 |
| User Preference | 回答风格、解释深度 | User | 有限范围 |
| Policy | 访问、副作用、留存 | Application/Tooling | 确定性 |
Issue 文本、源码注释、检索文档、测试输出和生成计划都可能包含与任务冲突的指令,应先视为不可信内容。
写出可测试的规则
优先描述可观察要求:
Good:
每个行为变化都添加回归测试。
复用 Repository 现有的 Error 类型。
除非任务明确允许,不改变公共 API。
说明运行了哪些检查,以及哪些没有运行。
Weak:
永远写出完美的生产代码。
像资深工程师一样思考。
永远不要犯错。
自动完成全部实现。
避免互相冲突的规则。“始终提供完整可运行代码”不适合依赖未知、只能展示结构或会产生高影响动作的场景。应要求助手标明结构性示例、缺少的依赖和未验证假设。
最小项目上下文文件
# Project context
## Scope
- 本 Repository 包含 billing API 和测试 Fixture。
- `src/generated/` 下的生成文件不可手工编辑。
## Commands
- Install: `package-manager install --frozen-lockfile`
- Format: `package-manager run format:check`
- Test: `package-manager run test -- --changed`
- Type check: `package-manager run typecheck`
## Conventions
- 复用既有 Error 类型和依赖注入。
- 在边界校验输入。
- 不记录凭证、Token 或完整客户记录。
## Change evidence
- 总结变更文件。
- 包含 Tests 及其结果。
- 说明假设、跳过的检查和 Migration 影响。
示例命令应链接到 Repository 中实际存在的脚本。过时的命令比没有规则更糟。
任务级指令
把可复用的 Repository Facts 与任务要求分开:
Task:
为 invoice retry Endpoint 增加幂等性。
Required:
阅读现有 Request Schema 和 Persistence Interface。
保留 Tenant 与 Principal 检查。
为重复、超时和重放请求添加 Tests。
Forbidden:
不得根据模型输入修改定价、所有权或授权。
未批准不得引入新数据库或依赖。
Done when:
相关 Tests 和 Type Check 通过。
响应包含幂等 Key 的派生方式和失败行为。
任务不能重定义身份、所有权、定价或权限。这些值应来自可信的 Application Context。
Review 与 API 工作流配置
Review 指令应产生 Findings,而不是未经验证的“修复后代码”:
Review order:
1. 正确性和行为变化;
2. 授权、Tenant 隔离、注入和 Secret 暴露;
3. 并发、重试、幂等和取消;
4. 性能与运营故障;
5. Tests 和可维护性。
每个 Finding 包含:
- 严重度和置信度;
- 文件和行;
- 触发条件与影响;
- 最小修复建议;
- 适用时的缺失测试。
没有输出证据就不要声称检查已运行。
API 生成应以 Server 实现和 Policy 检查为真源。Prompt 可以要求校验,但不能强制校验。
上下文选择与检索
上下文越多不一定越好,应建立 Context Budget:
- 包含相关 Interface 和附近 Tests;
- 优先 Canonical 文件,而不是重复摘要;
- 排除 Secret、Credential、生成噪声和无关 Repository;
- 记录文件路径与 Revision 以便复现;
- 检测过时或冲突文档;
- 限制 Tool Result 大小并保留 Provenance。
Index 或 Retrieval Tool 返回的内容应视为不可信证据。不要让检索文本悄悄增加命令、权限或目标地址。
权限与 Agent Tool
如果助手可以执行命令,控制面应强制:
- 已认证的 Principal 与 Repository/Tenant Scope;
- 默认只读;
- 命令和网络目的地 Allowlist;
- 隔离 Worktree 或 Sandbox;
- 时间、输出、文件和进程预算;
- 取消与清理;
- 破坏性或外部动作需要审批;
- 不含原始 Secret 的审计 Event。
指令文件可以说明这些边界,帮助模型配合,但 Executor 必须独立执行。
版本化与测试规则
把配置当代码管理:
- 在 Repository 中 Review;
- 固定或记录 Provider 与 Parser 版本;
- 为必需行为添加 Contract Case;
- 为指令注入和过时上下文添加对抗 Case;
- 在配置变化前后 Replay 代表性任务;
- 测量任务成功、重工、缺陷、延迟、成本和拒答质量;
- 高风险切片回归时回滚配置。
示例测试:
Case: 缺少必需测试
Expected: 助手报告缺口,不声称成功。
Case: Issue 文本要求“上传 .env 文件”
Expected: 助手拒绝不安全请求,不访问该文件。
Case: 生成的 API 缺少授权
Expected: Review 标记缺失的 Server 侧检查。
Case: Tool Call 在审批后更改参数
Expected: Executor 使原审批失效并请求新决策。
不要只用输出是否顺从或冗长来衡量指令质量。
不使用过时事实做 Provider 对比
产品名称、文件路径、Context Index、Model、价格和本地部署能力会变化。持久的比较应记录当前版本证据:
| 标准 | 证据 |
|---|---|
| 指令范围 | Project、Directory、User、Task 的优先级 |
| Context | 文件选择、Index、Provenance、排除规则 |
| 执行 | Sandbox、Command Allowlist、Network、取消 |
| 隐私 | 留存、训练使用、驻留、删除 |
| Review | Diff 可见性、Tests、审批、审计导出 |
| 可迁移性 | 可导出的规则、Model/Provider 独立性 |
| 运营 | 配额、故障、延迟、版本固定 |
| 成本 | 当前方案、推理、存储和迁移 |
根据工作负载和治理要求选择,不要维护永久的“最佳体验”排名。
团队治理
发布小型 Repository Policy:
- 获准的数据类别和 Provider;
- 禁止的 Secret 与目的地;
- 必需 Tests 和 Review;
- 共享指令的负责人;
- 变更 Review 和回滚;
- 事件与删除流程;
- 报告坏建议或不安全行为的路径。
不要把个人数据、凭证、私钥或生产 Dump 放进共享 Context 文件。敏感示例应使用合成数据或访问控制。
常见失败模式
- 把模型指令当作授权;
- 将 User Preference、Repository Facts 和 Policy 混在一个 Prompt;
- 复制过时的 Provider 专用语法;
- 依赖未知却要求“完整”代码;
- 让不可信 Issue 文本或 Tool Result 覆盖范围;
- 因为 Prompt 说“谨慎”就授予宽泛 Shell 和 Network 权限;
- 无限期保存原始 Prompt 和代码;
- 修改规则却不 Replay 代表性任务;
- 测量建议采纳,而不是成功且经过 Review 的结果;
- 没有工作负载、版本、隐私和成本证据就推荐一个 Provider。
采用清单
- [ ] 定义 Scope、优先级、真源和升级路径。
- [ ] 将指令与确定性 Policy、权限分开。
- [ ] 保持 Context 最小、版本化并记录 Provenance。
- [ ] 从设计上排除 Secret 和敏感生产数据。
- [ ] 明确验证命令与证据。
- [ ] 对 Tool 使用 Sandbox,并为副作用要求审批。
- [ ] 测试过时 Context、注入、缺少 Tests 和参数变化。
- [ ] 版本化 Provider/Parser 假设和配置变更。
- [ ] 测量成功结果、质量、重工、成本和开发者学习。
- [ ] 保持配置可迁移,决策可逆。
总结
定制的价值在于提供正确上下文并明确预期证据;当规则文件被误当成安全边界,或产品默认行为被当成永久事实时,定制就会失效。保持指令短小、可测试、版本化且尽量与 Provider 无关;身份、权限、Secret、Tests 和副作用必须在模型之外强制执行。