flow-atlas 是做什么的?
仓库自身的 AGENTS.md、设计文档和治理准则优先于本技能。
三个组成部分
atlas 自动生成代码已确定的事实。你需要编写需要意图的内容,atlas 负责校验。两者之间,你需要根据 references/boundaries.md 中的边界标准,判断哪些工作属于哪个组件。你做出的所有决策都必须写入 atlas 能读取的文件(流程文件、例外文件、配置、反馈),以便下一次运行和下一个 agent 能够看到。
atlas 生成:切勿手动编写
| 事实 | 命令 |
|---|---|
| surfaces、calls、edges、operationIds、registries、contract versions | scan |
| 按路径、方法或组件查询 surfaces 和 calls | query |
| 某个 surface 的上游调用方及其下游到达的服务 | trace |
| 流程草稿:名称、代码路径上的步骤、当某个组件调用它时的入口、存在分支时的候选步骤 | draft flow |
| 某个 flow 是否与代码一致,以及其作者字段是否已填写 | flows (conditions) |
| 附有位置和附近路径的发现项 | check, explain |
| 版本之间的差异 | diff |
| 配置候选及其覆盖程度 | inventory, scan |
| 每个组件的 OpenAPI 描述,已提交的描述与代码的一致程度,以及当代码决定时哪个描述是该组件的 | scan, inventory |
不要手动搜索 graph.json、通过文本搜索猜测调用方,或凭记忆输入 surface id:请从 atlas 输出中复制。
你需要编写:atlas 负责校验
| 内容 | 校验方式 |
|---|---|
Flow 的 title 和每个步骤的 role | Documented |
owner、labels、sources、lifecycle(当某个步骤尚未构建时标记为 planned) | schema;Resolved 会将 planned 步骤单独计数 |
一旦你写完了 flow 的意图,添加 generated: { by: <工具>/<模型>, at };当需要审查时添加 stale_after (OKF) | schema;Fresh |
| 当多个组件调用第一个步骤时的入口组件;当处理程序分支时下一步骤的归属 | EntryCalled, Connected |
produces | ProducesListed |
例外:原因、decidedBy、reviewBy | 过期后相应发现项会重新出现 |
| 误报,附上原因 | stats |
| 配置 | scan 覆盖度 |
由框架生成的 OpenAPI 文档(针对 atlas 无法解析的组件) (routes[].openapi, references/openapi.md) | scan 覆盖度和 limit: 行 |
origins:每个组件在某个环境中运行的基础 URL,来源于部署文件 | export arazzo 会提示缺失项 |
当 atlas 报告某个组件的描述 ambiguous 时,添加 openapi.<component> | export arazzo 会拒绝,直到设置此值 |
不要将属于你的工作交给工具:没有一个人能接受的理由,就不要进行 publicSurfaces、例外或基线的更新。永远不要使用 human: 参与者编写 verified 条目:那记录的是人的审查,而流程的可信等级(unverified、machine-confirmed、human-reviewed)依赖于此。
你需要解释:边界
判断一个跳转是否属于它所在的组件、是否存在类似的 surface 已经完成了相同的工作、一个缺口是缺陷、计划还是误报、对某个边的信任程度,以及流程的起点和终点。遵循 references/boundaries.md;它会规定源的优先顺序(仓库规则优先,其次是 flow roles,最后是代码),并给出标准。
设置
- 运行
atlas --help。如果atlas未安装,可以通过 npx 运行(npx github:hellices/flow-atlas --help)或要求用户安装;不要手动重新实现它的读取逻辑。 - 配置文件按顺序查找:
<root>/atlas.config.yaml、<out>/atlas.config.yaml或--config <文件>。如果没有配置文件,请按照下面的“初始设置”操作。 - 如果仓库不允许写入,请传入
--out <仓库外的目录>。所有写入操作都在该目录下进行。
设计变更
- 使用
atlas query --path <路径或片段>和atlas query --component <组件名>查看已有内容。 - 使用
atlas trace <最近的 surface>查看调用链:客户端调用、BFF 路由、其处理程序到达的端口方法、每个方法匹配的服务路由。 - 决策:复用、扩展或新增。记录你将添加或更改的 surface keys 以及每个跳转所属的组件。如果两个组件最终会做同一个步骤,请先确定归属再编写代码。
- 如果仓库维护 flow 文件(
flows/*.flow.yaml),请更新 Flow,或使用atlas draft flow <surface>新建一个(参见“编写一个 flow”)。将尚未存在的步骤标记为lifecycle: planned。
实现过程中
添加路由或客户端调用后,运行 atlas trace <surface>。上游应显示你预期的调用方,下游应显示你预期的调用。空的一侧意味着要么尚未连接,要么连接方式工具无法读取(路径构建离调用很远、处理程序用其他语言编写);请查看代码并说明原因。
当你添加、删除或更改某个组件的路由时,如果该组件的路由来自生成的 OpenAPI 文档,请在同一个变更中重新生成文档。仅更改客户端调用不会影响文档。
编写一个 flow
atlas draft flow <第一个 surface>会输出一个 Flow,其中包含所有代码已确定的事实;添加--to <surface>可以沿着代码追踪到指定终点。将其保存到flows/<名称>.flow.yaml(如果仓库不允许更改,则保存到<out>/flows/)。- 填写每个
agent:注释:title、每个步骤的role(该组件做什么、留给其他组件做什么)、owner、lifecycle、produces;在草稿列出候选步骤的地方,选择入口和下一步骤。保留没有标记的值;它们来自代码。 - 运行
atlas flows直到 flow 的Ready=True。如果Resolved、Connected或EntryCalled为 False,则说明代码或 flow 有误:使用references/boundaries.md判断哪个有问题。如果Documented为 False,则说明某个作者字段为空。
一个文件可以由 --- 分隔包含多个 flow。Surface ids 会将路径参数写为 OpenAPI 模板({id})。不要将位置、边或条件复制到文件中;atlas 会在每次运行时计算它们。格式定义在 flow-atlas 包的 schema/flow.schema.json 中,其 docs/schema.md 和 docs/responsibilities.md 提供了详细说明。
完成之前
- 运行
atlas check --since <你所基于的版本>。只会显示你的变更引入的发现项。 - 对每个发现项,运行
atlas explain <key>查看位置和相似路径。然后修复它,或记录一个例外,或记录一个误报。参见“处理发现项”。 - 将
atlas diff <基准>..WORKTREE --format markdown(或<基准>..HEAD)以及每个新 surface 的trace输出放入 PR 描述或交接说明中。
当配置落后时
迹象:stderr 上的 limit: 行(配置的文件无匹配项、某个源产出的内容不到其基线的一半),或者针对你知道被调用的路由出现 FA001 发现项。运行 atlas inventory,与配置对比,修正配置文件(references/config.md),然后再次检查 atlas scan 的覆盖度。在有人要求之前,不要运行 atlas baseline update。
初始设置
atlas inventory 会列出候选配置而不做任何决定。根据它编写配置(references/config.md);对于 atlas 无法解析的服务器框架(Spring、Django、Flask 等),生成其 OpenAPI 文档并将路由指向它(references/openapi.md)。运行 atlas scan,直到每个源都产出了你期望的内容,然后运行 atlas check,并与人一起检查一部分发现项。之后才能记录基线。
处理发现项
首先根据 references/boundaries.md 判断它是缺陷、计划还是误报,然后:
-
如果发现项就是 bug,则修复它:连接缺失的调用方、移除死路由、添加生产者、将调用指向正确的服务路径。
references/rules.md按规则列出了常见原因。 -
如果代码是有意为之,则添加一个包含决策理由的例外:
# flows/atlas-exceptions.yaml (或 <out>/exceptions.yaml) - rule: FA001 key: FA001|orders|GET /orders/{id}/history reason: 服务先行发布;应用界面将在下一个版本中跟进。 decidedBy: docs/orders.md#history reviewBy: 2026-12-31服务于仓库外部客户端的 surfaces 应在配置的
publicSurfaces中声明。 -
如果发现项是错误的:运行
atlas feedback <key> false-positive --note "<原因>"。如果提取器误读了某个文件,请说明是哪个文件以及如何误读。
除非有人要求,否则永远不要运行 atlas baseline update。永远不要为满足某个发现项而编辑生成的代码。
机器可读输出
--format json 或 --format yaml 会输出遵循 flow-atlas 包 schema/*.schema.json 的文档,每个文档包含 apiVersion、kind 和 provenance(提交和读取的文件及其摘要)。请读取这些内容,而不是解析文本输出;应根据条件的 reason 进行分支判断,而不是 message。atlas check --format sarif 会以 SARIF 2.1.0 格式输出发现项,适用于代码扫描和 IDE 查看器;atlas export arazzo 会以 Arazzo 1.0 格式输出 flow,适用于 API 工作流和端到端测试工具,但后者仍需填写参数、请求体和成功条件。
读取输出
- 发现项状态:
new是你的;baseline是接受的债务;excepted已覆盖;expired-exception需要人工处理。 - 在 trace 中:
=通过方法和路径将调用连接到 surface;~将路由连接到其处理程序运行的外部调用:这些调用可能编写在处理程序自身的代码或其调用的函数中(证据为static),或者包含在处理程序调用的某个名称的方法中(证据为name),或者对于 Spring 页面,由视图名称渲染的模板发出(via view <名称>)。通过通用名称(get、send)进行的~连接需要查看代码。 - 调用中的
in <名称>是包含该字符串的函数。错误标签或日志消息中的字符串即使看起来像路径,也不是请求;作用域通常可以表明这一点。 - 只读取配置文件中已确定的内容:字面量路径,具有标准或框架赋予的含义。来自变量、其他模板引擎或 htmx 和 Vue 属性的 URL 不会被读取或猜测。因此,“没有调用方”意味着 atlas 无法读取任何调用方;在删除任何内容之前请检查代码,并在
publicSurfaces中声明服务于仓库外部的 surfaces。没有发现项并不能证明 flow 是完整的。
引用
- 解释边界、判断缺陷/计划/误报:
references/boundaries.md - 规则、原因、解决方法、何时适用例外:
references/rules.md - 编写或修正配置:
references/config.md - 从框架生成的 OpenAPI 文档中读取路由,以及如何生成它:
references/openapi.md