首页
/ Astro Triage 流程解析:diagnose.md 的源码诊断工作流与 report.md 协作机制

Astro Triage 流程解析:diagnose.md 的源码诊断工作流与 report.md 协作机制

2026-09-05 10:18:23作者:幸俭卉

本文聚焦 Astro 仓库 .agents/skills/triage/diagnose.md 定义的“诊断(Diagnose)”技能:它规定了一个已复现 Bug 在 Astro 源码中被定位根因的完整工作流——从读取复现报告、定位 packages/ 下的源文件、添加插桩日志,到还原现场并输出带置信度诊断结论的 report.md。读完本文,你将掌握这条 LLM Agent 诊断流水线的每个步骤约束、服务端管理规则,以及它与 reproduce/verify/fix 技能之间通过 report.md 传递上下文的协作机制。

1. 在 Triage 流水线中的定位

diagnose.md 不是独立文档,而是 triage 技能(SKILL.md)四步流水线中的第二步。整个流程为:

  1. Reproducereproduce.md):搭建最小复现项目,写出 report.md
  2. Diagnosediagnose.md):在源码中定位根因,向 report.md 追加诊断章节;
  3. Verifyverify.md):判断行为是 Bug 还是有意设计;
  4. Fixfix.md):实现最小修复并补测试、changeset。

diagnose.md 开头对两个硬约束的定义决定了它与其他技能的关系:

  • CRITICAL(必须写报告):无论诊断成功与否——找不到根因、遇到报错、结论不确定——都必须在结束前读取并追加 report.md。原文强调“orchestrator 和下游技能依赖这个文件判断发生了什么”,如果诊断结束而没写报告,整条流水线会“静默失败”。
  • SCOPE(只做诊断):完成本工作流即结束,不做更大范围的问题验证、不修复问题、不派生子任务/子代理。

另外,orchestrator 会根据诊断产出的置信度决定走向:confidence 为 low 时直接跳到 Output 结束 triage;medium/high 才进入 verify 阶段(见 SKILL.md Step 2)。因此诊断输出的置信度字段实际上是一条流程控制信号,而不只是描述性标签。

2. 前置变量(Prerequisites)

文档声明了四个贯穿全流程的变量,它们可以由 orchestrator 作为 args 传入,也可以在独立运行时从对话上下文推断:

变量 说明 仓库依据
triageDir 复现项目所在目录(如 triage/issue-123),未传入时从先前对话推断 pnpm-workspace.yamltriage/* 声明为 pnpm workspace 包,因此复现项目能直接链接到 monorepo 内的 astro 源码包
issueDetails GitHub API 的 issue 详情 payload;若上下文缺失,可运行 gh issue view ${issue_number} 从 GitHub 拉取 SKILL.md 中同样接受 issueTitle/issueBody 作为输入
report.md 位于 triageDir 内、可能已存在的文件,包含之前所有技能写入的完整上下文 由 reproduce 技能创建,diagnose 只追加不覆盖
Astro Compiler 源码 withastro/compiler 仓库可能被克隆到仓库根的 .compiler/(已被 gitignore)。若存在则纳入诊断范围——有些 Bug 源于编译器而非 packages/(例如 HTML 解析、.astro 文件转换)。当堆栈或调查发现指向编译器行为时,应到 .compiler/ 中查相关源码 .gitignore 第 3 行的 /.compiler/ 确认该目录被刻意忽略;fix.md 进一步说明该克隆“仅作参考”(reference only),未接入 monorepo 依赖,无法端到端测试

从源码结构看,这一设计解决了 Astro 仓库诊断的特殊难点:.astro 文件先被编译器转成 JS 模板,再进入 packages/astro 的运行时/构建逻辑,一条渲染类 Bug 的堆栈可能跨越两个代码库。文档因此要求诊断者具备“先判断 Bug 属于哪一层”的意识。

3. Step 1:审阅复现结果(含提前退出)

诊断的第一步是读取 triageDir/report.md。文档给出了明确的提前退出(skip)规则

  • report.md 显示 Bug 未复现或被跳过(识别关键词:"could not reproduce""SKIP REASON""skipped: true"),则向 report.md 追加 DIAGNOSIS SKIPPED: No reproduction 并返回 confidence: null,立即结束。

这条规则与下游 fix.md 的“低置信度路径”(confidence 为 lownull 时不尝试改代码,只留下失败测试和 // TRIAGE: 路标注释)严格对应——诊断阶段不猜测,修复阶段就不会基于猜测下手。

需要重新触发一次复现来亲眼看到报错时,标准命令是:

pnpm -C <triageDir> run build  # 或 dev/preview

pnpm -C 的用法与 AGENTS.md 中的 monorepo 约定一致:在 packages/examples/triage 目录下执行项目本地脚本时必须带 -C

4. Step 2:定位相关源文件

利用 Step 1 收集到的错误信息、堆栈和其他复现细节,圈定 packages/ 中可能涉及的源文件。

这一步之所以可行,依赖于 AGENTS.md 中明确的 dist→src 映射规则:

  • node_modules/astro/dist/...packages/astro/src/...
  • node_modules/@astrojs/react/...packages/integrations/react/src/...

也就是说,复现项目(triageDir)跑的是本地 workspace 链接的 Astro 包,错误堆栈里出现的 dist/ 路径可以直接翻译回 packages/ 下的 TypeScript 源码进行阅读和插桩。这也是为什么 triage 复现项目要接进 pnpm workspace(triage/*pnpm-workspace.yaml 中声明),而不是安装 npm 上发布的版本——只有源码版 Astro 才能被插桩调试。

5. Step 3:用插桩(Instrumentation)还原代码路径

这是 diagnose 技能的核心手段:向源码添加 console.log 来理解实际执行路径。文档给出的示例直接指向构建入口:

// In packages/astro/src/core/build/index.ts
console.log('[DEBUG] Building page:', pagePath);
console.log('[DEBUG] Props:', JSON.stringify(props, null, 2));

示例文件确实存在——packages/astro/src/core/build/index.ts 就是 astro build 的构建入口(导出 build 函数,负责 resolveConfigcreateVite、路由清单与静态构建流程),在其中打日志可以观察每一页构建时的入参。

添加日志后,文档规定的完整循环是:

  1. 重新构建包(例如 pnpm -C packages/astro build)——这对应 AGENTS.md 的关键事实:“Edits to source files take effect after rebuilding the package via pnpm build”,改了 src/ 不重新构建,复现项目里跑的还是旧的 dist/
  2. 重跑复现(例如 pnpm -C <triageDir> build|dev|preview);
  3. 观察调试输出

迭代目标是用三个问题收敛:正在执行哪条代码路径?传入了什么数据?逻辑在哪里偏离了预期行为?

服务器管理规则(防“时间预算”耗尽)

文档用一整段约束 dev server 的生命周期管理,这些规则直接映射到仓库工具链的真实能力:

  • 重启前必须先停旧服务器pnpm -C <triageDir> dev stop。这套 dev --background / dev logs / dev status / dev stop 子命令在 AGENTS.md 的 “Background Dev Servers” 一节有完整说明;
  • 失败两次即放弃:服务器连续两次起不来就停止重试,用已有数据写出诊断,不要在服务器重启上空转。这与 SKILL.md 的总则“Do not get stuck on infrastructure problems……bail out after 2 attempts”一致;
  • 优先用 astro build:能用构建期复现就避免 dev/preview,从根上绕开服务器生命周期问题;
  • 永远不要用 & 后台化:用 pnpm -C <triageDir> dev --background& 在 CI 环境会挂起。

插桩后的现场还原

循环结束后有一条不可妥协的收尾规则:git checkout -- <file> 撤掉所有插桩。文档的原话是“Debug logs must not leak into downstream steps”——遗留的 console.log 会污染后续的 verify/fix 阶段,fix.md 的 Step 11 清理清单里也把“Debug code, console.logs”列为必须回滚项。诊断阶段对源码树是“借而不留”的关系。

6. Step 4:确定根因并书面化

当代码路径被理解后,诊断必须回答四个问题:

  1. 哪个文件包含 Bug;
  2. 代码做错了什么——具体的逻辑错误;
  3. 为什么表现为观察到的现象——错误如何外显;
  4. 修复应该怎么做——高层思路(注意:只给思路,不给补丁,实现属于 fix 技能)。

同时要求考虑三个延伸问题:这是不是近期变更引入的回归?是否影响其他相似用例?有没有需要留意的边界情况?

文档还有两条非常“工程文化”式的约束:

  • 禁止以“删掉用户依赖”作为修复建议。原文:“Never suggest removing a user's dependency (adapters, framework integrations, features like MDX or DB) as a fix, those are things the user needs.” 修复必须在用户现有技术栈内成立。这条禁令在 fix.md Step 3 中被原样重申,说明它是整条 triage 流水线的一等约束;
  • 语气校准(Tone calibration):根因描述要事实化、不戏剧化。除非证据真正支持,避免 “critical flaw”“fundamentally broken”“severe vulnerability” 之类措辞。文档给的例子很直白:“缺一个 null 检查就是缺一个 null 检查,不是‘渲染管线中的关键疏漏’。” 诊断的目标是帮维护者理解哪里错了并导向修复,而不是制造恐慌。

7. Step 5:写回 report.md(输出契约)

诊断结果以追加新章节的方式写入 report.md(不覆盖 reproduce 技能写的内容),章节必须包含:根因、带行号的影响文件、代码路径的详细解释、插桩结果,以及建议的修复方向——文档明确说这样做的目的是“help the fix skill work faster”。

报告同时承担了“最终 GitHub 评论原料”的角色(评论由下游 comment 技能生成),因此硬性要求包含四项:

  • 根因解释(哪些文件、什么逻辑错了、为什么);
  • 受影响文件路径及行号
  • 建议的修复方向;
  • 置信度(high / medium / low)与所有保留意见(caveats)。

这套“文件即交接”的模式在四个 triage 技能里完全对称:每个技能都声明 “MUST always read report.md and append to report.md before finishing”,reproduce.md 更直言 “Downstream skills will NOT have access to the original issue — report.md is their only source of context”。report.md 实际上是一条追加式日志(append-only log),把 issue 正文、环境、复现步骤、报错栈、诊断、验证与修复结果全部沉淀在 triageDir 中。由于 /triage/.gitignore 中被忽略(第 2 行),这些中间产物不会进入版本库,每个 issue 的 triage 目录天然隔离。

8. 评测如何验证这套工作流

diagnose 技能的行为由 live-model 评测守护。.agents/skills/triage/evals/evals.json 定义了三个用例,其中两个恰好覆盖了本文讲的两类分支:

  • 用例 1(完整 dry-run):合成 Bug “getTimeStat(0, 119999) 打印 1m 60s”。断言要求诊断“解释秒余数取整会产生 60”并给出 medium/high 置信度、验证结论为 bug、修复保证分钟格式的秒位在 0–59 且 60 秒进位、回归测试断言 getTimeStat(0, 119999) 返回 2m 0s、changeset 为 'astro': patch。值得注意的是该用例中的 getTimeStat 并非虚构——它真实存在于构建计时工具 packages/astro/src/core/build/util.ts,且 packages/astro/test/units/build/static-build.test.ts 中有对应单测,说明评测集是围绕真实源码路径构造的;
  • 用例 2(提前退出):只在 Cloudflare Pages 上出现的 binding 问题,断言复现阶段直接以 host-specific 分类跳过、写完整报告、不执行任何诊断/修复动作——这正是 reproduce.md 的 early-exit 机制;
  • 用例 3(intended-behavior)Astro.url.hash 在含 fragment 的 URL 下为空,期望验证阶段给出 intended-behavior 高置信结论(浏览器不把 fragment 发给服务器),不进入修复。

运行方式见 .agents/evals/README.md:先 pnpm eval:skills:validate 校验所有 manifest,再如 ANTHROPIC_API_KEY=... pnpm eval:skills -t "triage" 跑单个技能用例;每个用例消耗一次被测模型加一次评判模型的运行,评测在临时工作区中进行且结束后删除。

9. 小结:diagnose 技能的设计要点

diagnose.md 的约束汇总成一份可执行清单:

  1. 报告优先:无论成败,退出前必须追加 report.md(根因、文件+行号、修复方向、置信度);
  2. 范围锁定:只诊断,不验证、不修复、不派生子代理;未复现则追加 DIAGNOSIS SKIPPED: No reproduction 并以 confidence: null 返回;
  3. 双层代码库意识packages/ 是主诊断范围,堆栈指向编译器行为(HTML 解析、.astro 转换)时扩展到 .compiler/
  4. 插桩—构建—重跑—观察四步循环,利用 workspace 链接让 triage/ 下的复现项目跑本地源码 Astro,用 pnpm -C packages/astro build 使插桩生效;
  5. 服务器纪律:先 dev stop 再起新服务、失败两次即罢手、优先 build、禁用 &
  6. 现场还原git checkout -- <file> 撤掉全部 console.log,不让调试痕迹流入下游;
  7. 结论克制:根因描述事实化;禁止建议删除用户依赖;置信度字段直接决定流水线是否继续。

这套文档与 reproduce.mdverify.mdfix.md 共同构成 Astro 仓库内一套可被 LLM Agent 逐步执行的 Bug 分诊标准作业程序(SOP):report.md 是唯一上下文载体,triageDir 是唯一工作现场,而 diagnose 负责其中最关键的一环——把“能稳定复现的异常”翻译成“带行号的根因定位”。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
503
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384