


让 AI 智能体遵守大型全栈仓库的贡献规则
让 AI 智能体在含有类型化前端和后端的大型仓库中工作时使用。它会在推送前通过提交前检查,用仓库正在迁移到的新写法写代码,按各角色被允许做的事判断安全问题,并按项目的规定完成测试、文档和拉取请求。
要使用这个AI规则
## 每次推送前先通过提交前检查
在推送提交之前,务必对所有文件运行仓库的提交前(pre-commit)检查套件。提交前检查失败时持续集成也会失败,因此这是一道不可协商的关卡,而不是一种偏好。
高效运行的方法:
- 先暂存改动。提交前检查只检查已暂存的文件,因此未暂存的编辑会被静默跳过。
- 若想要快速的内层循环,可只对已暂存文件运行套件,或运行某个具名钩子(类型检查器、格式化工具、代码检查器)。在开启或更新拉取请求的那次推送之前,要运行覆盖全部文件的完整检查。
- 运行前先激活项目的虚拟环境或工具链 shell。常见位置因开发者而异;如果找不到命令,请询问用户该激活哪个环境,而不要凭猜测使用某个路径。
- 有些钩子会自动修复(格式化工具、行尾空白)。请重新暂存被修复的文件并重新运行,因为第一次运行会报告它已经修复过的失败项。
预期会有三类失败:可自动修复的格式问题、需要手动修复的类型检查器错误,以及需要手动修复的代码检查错误。
## 新代码用仓库正在迁移到的写法,不用旧写法
有若干迁移正在进行中。符合旧模式的代码依然存在,但它的存在并不等于允许你再写更多这样的代码。新增和修改的代码要遵循目标模式。
- 类型化前端:不使用作为逃生舱口的 `any` 类型,也不新增未加类型的脚本文件——用类型化方言编写,并复用已有的类型定义。
- 共享组件层:从项目自有的设计系统包中导入 UI 组件,而不是直接从第三方库导入;优先使用设计系统的主题令牌而非遗留令牌;避免自定义 CSS,改用组件库所支持的样式方案。
- 测试金字塔:优先写单元测试而非集成测试,优先写集成测试而非端到端测试。新的端到端测试要用已采用的框架编写;被取代的那个端到端框架已废弃,迁移完成后将被移除。
- 后端类型标注:所有新代码都要带类型提示,模型要使用正确的注解,并且类型检查器必须通过。
- 标识符迁移:新模型使用不透明的唯一标识符作为主键,公开 API 暴露这些标识符而不是内部的自增整数,而已有模型则在整数标识符之外新增该标识符,以便逐步切换。
## 按各角色被允许做的事判断安全问题
在评估任何代码路径的安全问题之前,先阅读仓库的权威安全策略文档。它是安全模型的权威来源,也是衡量人工报告者和自动化扫描器的共同标准。
判断某个发现是否在范围内的唯一检验标准是:它是否让某个主体执行了安全策略中的角色与能力矩阵并未授予其执行的操作?如果是,就在范围内。如果否,就不在范围内。
有三条信任边界为该检验标准提供框架:
1. 管理员角色是完全受信任的运维主体。管理员通过文档化的配置、API 或 UI 所能做的任何事情,都属于预期内的能力,而不是漏洞。
2. 运维方掌管部署期的决策:密钥、网络暴露面、功能开关的选择、连接器与编解码器的选择、通知目的地,以及第三方插件。这一层的配置错误属于部署缺陷,而不是产品漏洞。
3. 代码库负责在其向主体暴露功能的每一处强制执行角色与能力矩阵——API 路由、命令层与数据访问层、UI 处理器、后台任务,以及其他所有入口点。缺失或不正确的强制检查无论出现在哪里都在范围内。
该模型假定由运维方控制的基础设施——元数据数据库、缓存、消息代理、密钥存储、部署环境——始终处于运维方的信任边界之内。有效的发现必须证明存在由尚未控制这些系统的攻击者所造成的边界违规。
## 为每种路由和数据类型使用正确的权限检查
路由级授权对每一类路由使用一个装饰器,具体用哪一个取决于路由的种类:现代 REST API 面用一个,遗留 JSON 视图路由用一个,遗留 HTML 视图路由用一个。把它们弄混就是强制执行缺陷,即使表面上看起来存在检查也一样。
对象级授权是第二道独立的关卡。它适用于承载数据的资源——仪表盘、图表、数据集与数据源、查询、数据库与表的访问权限,以及查询上下文——并通过安全管理器的访问检查按对象逐个调用。如果某个路由返回或修改特定的承载数据对象,而代码却省略了逐对象的关卡,那么这在范围内。
其他资源——注释、标签、样式模板、报表、行级安全规则等——是有意依赖路由级装饰器加上数据访问层基础过滤器中的归属范围限制。这些资源上缺少逐对象检查是设计使然,不构成一个发现。
对某一资源类别遵循了正确的授权模式,并不代表该代码就没有其他问题。注入、服务端请求伪造、跨站脚本等类别与授权无关,需要单独评估。
## 让自动扫描工具写明被违反的规则和攻击者的角色
自动化扫描器——基于模型的代码扫描器、静态分析器和依赖工具——在针对本代码库提交的每一个发现中,都必须明确指出两件事:
1. 该发现认为被违反的、安全策略中角色与能力矩阵的具体那一行。
2. 该发现假定攻击者所持有的主体:匿名或公开主体、低权限的已认证角色、查询工具角色、提升的创作角色、管理员角色、嵌入式访客令牌,或带有明确能力授予的具名自定义角色。
无法同时指明这两点的发现,必须以提问的形式提交,而不能作为漏洞提交。设立该要求是为了让每一个上报的问题都能对照已发布的安全模型进行验证,也为了让推测性的、或仅靠模式匹配得出的报告不进入分诊队列。
## 遵守前端和后端的代码规范
前端:避免使用 `any` 并复用已有类型;使用带 hooks 的函数式组件;从共享的设计系统包中取用 UI 组件,而不是直接导入第三方库;使用项目标准的测试运行器和测试库,而不是已被移除的遗留渲染器;已有全局 store 的地方使用全局 store,其余情况使用本地 hook 状态。
后端:所有新代码都必须有类型提示,静态类型检查器必须通过,数据模型要带有正确的类型标注,测试要使用项目标准的测试框架。构建查询时,对布尔列使用 ORM 的取反运算符,而不是把它与 false 字面量作比较——后者会被代码检查器标记。
许可证头:新的源文件需要带上项目标准的许可证头。智能体指令文件(本文件及其面向各厂商的同类文件)被有意排除在该要求之外,以免在许可证头上消耗 token。
注释:避免使用"现在""目前""今天"这类与时间相关的表述,因为它们会过时。写出无论何时被阅读都依然准确的注释。
## 改代码时同步更新文档和破坏性变更记录
文档是变更的一部分,而不是后续任务:
- 任何面向用户的变更都要更新文档树。
- 把破坏性变更记录到专用的升级说明文件中,这样运维方就能在同一个地方找到它们。
- 为每一个新的函数和类编写文档字符串。
当某项变更触及运维方或最终用户可以观察到的行为时,一个没有配套文档修改的拉取请求就是不完整的。
## 自动生成的组件文档要在 story 文件里修,不改生成器
开发者门户会依据组件目录中的故事(story)自动生成组件文档。故事是唯一可信来源,由此引出两条规则:当某处渲染不正确时,先修故事文件而不是修生成器;同时保持生成器轻量——它只负责提取并透传故事数据,因此要克制住在其中为单个组件添加特例的冲动。
要让某个组件的文档正确生成,它的故事文件必须:
- 以内联方式把元数据对象作为默认导出来导出,而不是先赋值给变量再导出该变量。
- 用统一的前缀加上组件名来命名交互式故事。
- 在故事的参数(arguments)中定义默认的 prop 值。
- 在故事级别而非元数据级别定义参数类型,包括控件类型和描述。
- 对变体网格、需要子元素的组件的示例子元素、自定义实时代码块,以及无法内联解析的复杂对象 prop,使用文档中规定的参数键。
诊断文档问题时,请把生成器脚本、它的包装组件和生成输出目录这三个活动部件放在心上。
## 不自己写测试准备,使用仓库提供的测试辅助工具
仓库自带辅助工具;请使用它们,而不是自己手工搭建准备代码。在后端,这意味着共享的测试基类、用于模拟配置和切换功能开关的装饰器、用于以某个角色登录的认证辅助工具,以及用于创建测试所需固件的工厂辅助工具。在前端,这意味着会装配标准 provider 的自定义 render 辅助工具、用于 store、路由器和主题的包装器工厂,以及下拉选择交互辅助工具。
模拟规则:对配置对象使用普通 mock;当被测代码是同步的时候,不要动用异步 mock。当模型新增了一个字段时,要更新 API 测试中的预期列清单。
要知道如何运行每一套测试:整套前端测试、单个前端测试文件、全部后端测试、单个后端测试文件、某个后端测试目录,以及端到端测试套件的无头、交互、有头和调试模式。
如果后端测试失败是由于数据库或环境配置而不是被测代码本身,请让用户去运行测试环境的初始化设置,而不要临时凑合地去修改他们的环境。
## 调试前先用健康检查端点确认环境
先做快速的配置检查:访问应用的健康检查端点,确认它有响应,然后再花时间处理缺陷报告。健康检查失败通常意味着工作区从未被配置过,而不是代码坏了。
如果健康检查失败,请告诉用户环境看起来没有配置好,并指引他们查看项目中关于与智能体协作的配置说明文档,而不是你自己去尝试修复他们的环境。
在熟悉环境时要了解关键的项目文件:包含构建、测试、检查脚本以及开发服务器端口的前端包清单文件;包含代码检查器和类型检查器配置的 Python 项目文件;以及拆分为基础依赖集和开发依赖集的依赖需求文件夹。
## 填完拉取请求模板,并用 conventional commits 格式写标题
开启拉取请求时:
1. 起草之前先阅读仓库中当前的拉取请求模板文件。务必阅读实际文件,而不是复用缓存的内容,因为模板会随时间变化。
2. 填写模板定义的每一个部分——摘要、变更前后的证据、测试说明,以及附加信息。
3. 使用约定式提交格式 `type(scope): description` 为拉取请求命名标题,例如 `fix(dashboard): load charts correctly`。有效的类型是 `fix`、`feat`、`docs`、`style`、`refactor`、`perf`、`test` 和 `chore`。
## 修改不熟悉的区域前,先了解目录结构和文件模式
有两个习惯能让改动在大型仓库中落到正确的位置。第一,编辑之前先了解目录地图:哪棵目录树存放后端应用及其 API 端点、数据模型和连接器;哪棵目录树存放前端源码及其组件、图表构建器、仪表盘和查询编辑器等区域;共享的设计系统包位于何处;以及测试、文档和破坏性变更日志分别在哪里。
第二,了解反复出现的文件模式,好让新功能落到约定俗成的文件中:用于放置端点及其装饰器和生成 schema 的文档字符串的 API 模块;用于请求与响应校验、并为生成的 API 规范提供输入的 schemas 模块;用于承载包裹在事务中的业务逻辑的 commands 层;以及用于持久化的 models 层。生成的 API 文档正是从这些文档字符串和 schema 派生而来,因此改了端点却不更新文档字符串,会悄无声息地让文档质量下降。
数据库迁移遵循它自己的约定:它们存放在 migrations 的 versions 目录中,命名包含时间戳、修订哈希和描述,并且应当调用共享的迁移工具辅助函数而不是原始的 ORM 操作,以保持在不同数据库引擎之间的兼容性。
最后请注意,本仓库为不同的智能体厂商保留了并行的指令文件。当你修改一条适用于所有这些文件的规则时,要让它们保持一致。
