Angular 仓库 AI Agent 协作规范:AGENTS.md 环境约定、Zoneless 测试模式与 Bazel 开发实践
本文以 Angular 框架源码仓库根目录的 AGENTS.md 为核心,完整解读这份面向 AI Agent 的仓库协作指南:从 pnpm + Bazel 的环境约定,到 "Zoneless & Async-First" 测试范式中的 Act/Wait/Assert 三步法,再到提交信息与 PR 流程规范。读完之后,你能掌握在该仓库中运行目标、编写符合框架测试风格规范的单元测试、以及产出符合提交格式要求的变更所需的完整工作流。
环境与基础约定
AGENTS.md 开头明确了仓库定位——这是 Angular 框架的源码仓库("This is the source code for the Angular framework"),并给出了两条最基础的环境约定:
- 包管理统一使用
pnpm,而不是 npm 或 yarn; - 运行测试统一使用
pnpm bazel test //target,其中//target为 Bazel 目标路径。
这两条约定与仓库配套文档完全一致。building-and-testing-angular.md 说明了开发环境的完整前置条件:Git、Node.js(版本由 .nvmrc 指定)、pnpm(版本由 package.json 的 engines 字段指定);安装依赖只需 pnpm install,构建产物通过 pnpm build 输出到 dist/packages-dist。
Bazel 的使用方式在 building-with-bazel.md 中有更细的说明:Angular 通过 npm 包 @bazel/bazelisk 安装 Bazel 本体(而非让贡献者自行安装),以保证所有人使用同一版本,统一通过 pnpm bazel 调用。常用命令模式为:
# 构建单个包
pnpm bazel build packages/core
# 构建全部包
pnpm bazel build packages/...
# 在 Node 中测试某个包的测试目标
pnpm test packages/core/test:test
# 通过 karma 在浏览器中测试
pnpm test packages/core/test:test_web
# 测试所有包
pnpm test packages/...
其中 ... 是 Bazel 的通配符,表示执行指定路径下的所有测试;首次构建通常比后续构建慢很多,因为 Bazel 会非常有效地缓存构建结果。
关键文档地图
AGENTS.md 用 "Key Documentation" 一节将三份文档指定为权威依据,这也是本仓库贡献流程的三大支柱:
| 文档 | 职责 |
|---|---|
| Building and Testing | 运行各类构建/测试目标的权威指南 |
| Coding Standards | TypeScript 等文件的风格规范 |
| Commit Guidelines | 提交信息与 PR 标题的格式 |
这三份文档均位于 contributing-docs/ 目录下,下面分别展开其核心内容。
构建与测试:格式、Lint 与本地验证
building-and-testing-angular.md 中的几项硬约束值得特别关注,因为 CI 会强制执行:
- 提交 PR 前必须执行全量测试套件:
pnpm test //packages/...。即使忘记运行部分测试,CI 也会执行受影响测试并报错,但 PR 只有在代码格式正确且所有测试通过时才能合并。 - 格式化使用 prettier,源码未正确格式化会导致 CI 失败。可用命令:
pnpm ng-dev format changed [shaOrRef]:仅格式化自指定 sha/ref 以来的改动文件(默认相对main);pnpm ng-dev format all:格式化全部源码;pnpm ng-dev format files <files..>:仅格式化指定文件。
- 风格校验:
pnpm lint一次性检查格式与编码风格。 - 本地库联动验证:用
pnpm ng-dev misc build-and-link <path-to-local-project-root>可以本地构建 Angular 并pnpm link到本地项目验证变更;此时需ng cache disable关闭 CLI 磁盘缓存,且启动 CLI 时必须带--preserve-symlinks标志(否则符号链接被解析为真实路径会导致模块解析失败)。
building-with-bazel.md 进一步补充了调试手段:--config=debug 以调试模式运行测试;Node 测试可通过 pnpm bazel test packages/core/test:test --config=debug 配合 Chrome DevTools(chrome://inspect 的 "Open dedicated DevTools for Node")或 VSCode 的 Attach 配置(端口 9229)调试;karma 测试则在目标名后追加 _debug 后访问 http://localhost:9876/debug.html。
编码标准:与框架本体同源的代码风格
coding-standards.md 明确其适用范围是 Angular 框架本身的开发(而非用 Angular 构建应用),以 Google JavaScript Style Guide 为基础,并用 prettier 强制自动格式化。其中与测试工作最相关的几条规范:
- 注释要解释 "why" 而非 "what":说明代码为何如此实现(例如某个
tabindex处理是为了防止 ngAria 过度添加)的注释远比复述代码行为的注释有价值;TypeScript 中公共 API 使用 JSDoc,其他说明用//。 - 测试命名要有描述性:jasmine 测试名理想情况下应读起来像一句话,常见形式是 "it should...":
// 推荐:完整描述被测场景
describe('Router', () => {
describe('with the default route reuse strategy', () => {
it('should not reuse routes upon location change', () => { ... });
});
});
// 避免:无法说明被测场景
it('should work', () => { ... });
- 测试类同样要有描述性命名(
FormGroupWithCheckboxAndRadios优于Comp)。 - 其余通用规则包括:避免
any、优先const/readonly、布尔属性用is/has前缀、Observable 不以$结尾、导入 rxjs 的of时别名化为observableOf等。
提交信息:header + body + footer 三段式
commit-message-guidelines.md 规定了严格的提交信息结构:
<header>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
- header 为必填,格式为
<type>(<scope>): <short summary>。type 必须是以下之一:build、ci、docs、feat、fix、perf、refactor、test;summary 用祈使句、现在时、首字母小写、结尾不加句号。 - scope 为可选,应填写受影响的 npm 包名(如
animations、common、compiler、compiler-cli、core、forms、http、localize、platform-browser、platform-server、router、service-worker、upgrade、zone.js等)。少数例外:dev-infra用于/scripts与/tools目录内的开发基建变更;docs-infra用于/adev目录(angular.dev 应用本身)的基础设施变更,而纯文档内容(如编辑.md文件)应使用不带 scope 的docs:;migrations用于ng update迁移;devtools用于浏览器扩展(devtools/ 项目)。 - body 除 docs 类型外为必填,且至少 20 个字符,用于解释变更动机(why),可对比前后行为。
- footer 可选,承载破坏性变更与弃用声明:
BREAKING CHANGE:开头需附变更摘要 + 空行 + 详细描述与迁移指引;DEPRECATED:同理;并可引用 issue(Fixes #<issue number>/Closes #<pr number>)。 - Revert 提交须以
revert:开头,body 中包含This reverts commit <SHA>以及回退原因。
测试规范:Zoneless & Async-First
这是 AGENTS.md 中技术含量最高的一节,也是整个指南的核心。它规定 Agent 在编写 Angular 仓库测试时必须遵守 Zoneless & Async-First 原则:
假定运行环境是 zoneless 的,状态变化会以异步方式调度更新。
由此引出三条硬性规则:
- 禁止使用
fixture.detectChanges()手动触发更新; - 始终采用 "Act, Wait, Assert" 模式:
- Act(操作):更新状态或执行一个动作;
- Wait(等待):
await fixture.whenStable(),让框架处理已调度的更新; - Assert(断言):验证输出;
- 尽量最小化等待以保持测试速度:
- 使用
useAutoTick()(来自packages/private/testing/src/utils.ts)通过 mock 时钟快速推进时间; - 必须等待时,使用真实异步测试(
it('...', async () => { ... })),配合:await timeout(ms)(同文件提供)等待指定毫秒数;await fixture.whenStable()等待框架稳定。
- 使用
源码级解读:useAutoTick() 与 timeout() 如何实现
useAutoTick 与 timeout 均定义在 packages/private/testing/src/utils.ts,该目录是一个独立的 Bazel 测试库(BUILD.bazel 中 ng_project(name = "testing", testonly = True)),依赖 //packages/core/testing、//packages/platform-browser 等,供各包测试以 @angular/private/testing 导入。
useAutoTick() 的实现本质是在 beforeEach 中安装 Jasmine 的假时钟并开启自动推进,afterEach 中卸载:
/**
* Installs Jasmine's fake clock with auto-tick enabled for all tests in the describe block.
* Call at the top level of a describe block to automatically advance time for async operations.
*/
export function useAutoTick() {
beforeEach(() => {
jasmine.clock().install();
jasmine.clock().autoTick();
});
afterEach(() => {
jasmine.clock().uninstall();
});
}
timeout(ms) 则是一个简单的基于 setTimeout 的 Promise 封装,用于在真实异步测试中等待特定时长:
export async function timeout(ms?: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
值得注意的是,同一文件中还提供了一批配套的测试工具,可以视为 AGENTS.md 所倡导模式的延伸:waitFor(callback, options) 以真实时钟(刻意绕过假时钟)轮询等待条件成立,默认超时 100ms,超时会附带重试次数与最后一次错误的详细信息;expectText(text, options) 等待页面文本出现,支持字符串或正则,默认容器为 TestBed.getLastFixture().nativeElement;withBody / withHead 负责在 Node 环境下通过 domino 安装 document 并管理测试间的清理(ensureDocument / cleanupDocument 已在模块加载时自动注册到 beforeEach/afterEach)。这意味着在 Node 环境中编写这些测试不需要额外搭建 DOM 基础设施。
仓库中的真实用例
useAutoTick + timeout 的组合在仓库各包的测试中被广泛使用,例如 packages/forms/signals/test/node/resource.spec.ts:
import {isNode, timeout, useAutoTick} from '@angular/private/testing';
describe('resources', () => {
useAutoTick();
beforeEach(() => {
globalThis['ngServerMode'] = isNode;
TestBed.configureTestingModule({providers: [provideHttpClient(), provideHttpClientTesting()]});
// ...
});
it('Takes a simple resource which reacts to data changes', async () => { ... });
});
其他典型使用者包括 packages/common/test/pipes/async_pipe_spec.ts(AsyncPipe 测试)、packages/forms/test/form_control_spec.ts(各表单指令测试普遍同时引入 useAutoTick 与 timeout)、packages/common/http/test/transfer_cache_spec.ts 以及 packages/core/test/acceptance/authoring/signal_inputs_spec.ts。这些用例印证了 AGENTS.md 所述模式已落地为仓库测试代码的实际惯例:在 describe 块顶层调用 useAutoTick(),在异步 it 中配合 await timeout(ms) 与 await fixture.whenStable() 完成 Act/Wait/Assert。
Pull Request 流程约定
AGENTS.md 的最后一节规定:使用 gh CLI(GitHub CLI)创建和管理 Pull Request。结合前文规范,一个完整的 Agent 工作流闭环为:
pnpm install安装依赖;- 按 coding-standards.md 的规范修改代码,测试遵循 Zoneless & Async-First 模式;
pnpm ng-dev format changed格式化改动文件,pnpm lint校验风格;pnpm bazel test //target运行受影响目标,提交前执行pnpm test //packages/...全量回归;- 按 commit-message-guidelines.md 编写提交信息(
<type>(<scope>): <summary>+ 动机 body + 可选 BREAKING CHANGE footer); - 使用
ghCLI 创建 PR——PR 标题同样遵循提交信息 header 格式。
小结
AGENTS.md 虽篇幅不长,但把 Angular 仓库的协作契约压缩到了四个可执行要点:pnpm + pnpm bazel test 的环境基线、三份关键文档的权威分工(构建测试 / 编码风格 / 提交格式)、Zoneless & Async-First 的测试范式(禁用 detectChanges(),坚持 Act/Wait/Assert,用 useAutoTick() 和 timeout() 控制等待),以及 gh CLI 的 PR 管理约定。配套的 packages/private/testing/src/utils.ts 源码与各包测试用例则提供了可直接对照的实现细节,使这份指南从"约定"落到可验证的工程实践。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00