Ruff ty 生态分析的 Subagent Handoff 协议:多智能体协作下的证据冻结、复现与最小化交接实践
本文以仓库
.agents/skills/summarise-ecosystem-results/references/subagent-handoff.md为骨架,结合其所属的summarise-ecosystem-results与minimizing-ty-ecosystem-changes两套 Agent 技能、scripts/collect_ty_ecosystem_run_metadata.py元数据采集脚本以及Cargo.toml中的 profiling 构建配置,完整还原 Ruff(ty 类型检查器)生态分析结果汇总时"主代理 → 子代理"交接的分工、不变量与回报规范。读者将理解:为什么必须先冻结报告与 Actions 运行证据、如何用不可变路径发布共享二进制与配置、指派给每个子代理的最小完整上下文清单、以及"来源可归因"与"无来源证据"两类任务各自必须交付的产物。
一、文档定位:何时触发 Subagent 交接
subagent-handoff.md 是 summarise-ecosystem-results 技能(见 .agents/skills/summarise-ecosystem-results/SKILL.md)的内部参考文档。该技能负责把"Ruff PR 的 ty 生态分析运行结果"整理成一份可发布到 GitHub 评论的总结报告。技能约定:当报告中包含多个受影响项目或可独立调查的条目时,显式要求启动子代理并行处理,并且"主代理拥有冻结的证据、共享 profiling 二进制、配置、协调与最终报告",任何分工交接都必须遵循本参考文档。
因此这份文档解决的是多智能体流水线中的一个具体协作问题:summary 主代理如何把"复现(reproduction)"与"最小化(minimization)"任务安全地下放给子代理,同时保证每个子代理都在完全相同的、被冻结的历史证据上工作,避免各自污染共享状态。
背景补充(均为仓库内可验证的事实):这里分析的"ty"是指本仓库中与 Ruff 一同开发的 Python 类型检查器(构建入口为 cargo build --package ty,见 Cargo.toml 中 [profile.profiling] 的注释),而"生态分析"是对若干 mypy-primer 收录的开源项目分别运行 merge-base 与 PR 两个版本的 ty 二进制,对比诊断与失败结果的变化。
二、主代理(Primary Agent)的交接前义务
交接不是从"分配任务"开始的,而是从"冻结证据"开始的。文档将主代理在指派任何子代理工作之前的责任划分为五件事,缺一不可:
- 冻结精确证据:锁定本次要汇总的精确报告、对应的 Actions 运行(run)与重试编号(attempt)。具体采集方法见 evidence-acquisition.md:保存用户显式提供的报告或生态结果评论、用
gh run view ... --attempt抓取作业图、按 artifact ID(而非可变名称)下载并校验full-report与各 diagnostics shard。核心原则是绝不拿较新的评论、重跑或同一 PR 的当前报告去替换用户给出的那一份。 - 一次性采集运行元数据:对所有仍保留"来源可归因诊断"或出现"新出现/修复/有意义变化的可复现失败"的项目,运行一次
scripts/collect_ty_ecosystem_run_metadata.py。 - 构建并复制两个精确版本(exact-revision)的 profiling 二进制:merge-base 与 PR 各一份,在指派任何子代理工作前完成。
- 发布不可变路径:将
TY_ECOSYSTEM_RUN_METADATA、TY_ECOSYSTEM_BASE_BINARY、TY_ECOSYSTEM_PR_BINARY三个绝对路径发布给所有子代理;将复制的 PR 生态配置安装一次到$TY_ECOSYSTEM_CONFIG_HOME/ty/ty.toml,并发布TY_ECOSYSTEM_CONFIG_HOME的绝对路径。 - 声明只读共享输入:快照、可选的结构化 JSON、两个二进制、元数据清单、复制的配置与已安装的配置,一律视为只读共享输入,任何一方(含主代理自身)不得在调查中途改写。
2.1 元数据清单里到底装了什么
collect_ty_ecosystem_run_metadata.py(见 scripts/collect_ty_ecosystem_run_metadata.py)读取 Actions 日志与远程文件,输出一份 JSON 清单,其顶层字段包括:
run:attempt、conclusion、run id、url;ruff:merge_base与pr_revision两个 40 位 SHA(从Build ty (base)作业日志中解析Merge base:/PR commit:);exclude_newer:依赖裁剪时间点EXCLUDE_NEWER;ecosystem_analyzer:解析器仓库pyproject.toml中锁定的 revision,以及src/ecosystem_analyzer/config.py里的MINIMUM_PYTHON_VERSION;mypy_primer:从 analyzer 依赖中唯一锁定的 mypy-primer revision;project_python:按 mypy-primerprojects.py逐项目解析的 CI Python 版本(min_python_version与基线取较大者)。
脚本对"无法唯一确定的值"一律抛出 MetadataError(例如日志中出现多个冲突的 merge base、找不到 shard 作业、uv.lock 中没有 ecosystem-analyzer 等),绝不静默猜测。运行方式按技能文档为:
GH_TELEMETRY=false uv run --script scripts/collect_ty_ecosystem_run_metadata.py \
<actions-run> <project-name>... \
--attempt <actions-attempt> \
--output target/ty-ecosystem-run.json
注意两点:所有 gh 调用必须以前缀 GH_TELEMETRY=false 开头(Agent 每次工具调用可能启动独立 shell,之前的 export 不会继承);该清单用于判断"以哪个 revision 的源码为准",因为工作区当前检出的提交并不等于被分析二进制对应的提交。
2.2 profiling 二进制是"行为裁判"(behavioral oracle)
两个二进制是判断差异是否复现、缩减是否保真的唯一权威。Cargo.toml 中专门为其配置了 profiling 构建档(见 Cargo.toml,注释明确"Use the --profile profiling flag to show symbols in release mode",即 cargo build --profile profiling),使崩溃栈等信息在接近 release 的性能下仍保留行级符号。
子代理永远不重建这两个二进制。它们由主代理在干净工作区上构建并复制到共享位置;由于 PR 运行通常基于 GitHub 的合成 merge commit,普通克隆里并不存在该提交,需要先显式 fetch PR revision。相关构建命令序列(含 CARGO_PROFILE_PROFILING_DEBUG=line-tables-only、git checkout --detach 往返、把 ty 产物复制为 ty-base/ty-pr、把 .github/ty-ecosystem.toml 复制为共享配置)的完整细节记录在 minimizing-ty-ecosystem-changes/SKILL.md 中,此处不赘述。
2.3 精确版本 debug 二进制的独占构建协议
如果子代理在排查"内部类型无法辨别"等歧义时需要精确版本的 debug 二进制,只有主代理可以构建。文档规定了严格的暂停协议:
- 暂停所有正在工作的子代理,并等待它们确认;
- 确认共享检出(shared checkout)是干净的,记住其原始 ref;
- 构建并复制被请求的二进制;
- 无论构建是否成功,恢复共享检出的原始 ref;
- 只有构建成功且 ref 已恢复之后,才发布该二进制的不可变路径。
子代理侧对应的义务是:需要 debug 二进制时向主代理申请而不是自己构建、不得切换共享 Ruff ref;当主代理请求暂停时,停止所有依赖检出(checkout-dependent)的工作与子进程,确认已停止之后再确认暂停,即使 debug 构建失败也保持暂停直到被显式恢复。
2.4 子代理的共享状态禁区
文档用一句话划定了红线,子代理必须遵守:
- 不重新生成共享清单(manifest);
- 不重建共享 profiling 二进制;
- 不切换共享 Ruff ref;
- 不重写共享配置;
- 不覆盖其他 Agent 正在使用的工作文件;
- 不信任此前的本地复现结果;
- 不以当前依赖元数据替代冻结版本。
三、指派清单:交给每个子代理的最小完整上下文
文档要求"给每个子代理"以下完整上下文(这是交接内容的下限,缺一项都可能让子代理跑到错误证据上):
- PR 与详细报告链接,以及(若可得)生态结果评论链接;
- 冻结的 HTML 报告路径、可选的对应结构化 JSON、可用的 diagnostics shard 路径,以及(若可得)冻结的评论路径、选定的 Actions run 与 attempt——要求使用这些已捕获的输入,而不是重新抓取实时证据;
- 结构化 JSON 中分配到的精确条目(JSON 不可用时取自冻结的 HTML 报告),并区分两类工作:来源可归因的变化(source-attributable)与无法恢复来源证据的结果(outcomes without recoverable source);对间歇性严重失败还要提供报告的 merge-base 与 PR 两侧运行次数;
- 四个不可变绝对路径:
TY_ECOSYSTEM_RUN_METADATA、TY_ECOSYSTEM_BASE_BINARY、TY_ECOSYSTEM_PR_BINARY、TY_ECOSYSTEM_CONFIG_HOME; - 所有直接或间接的
gh调用都要加GH_TELEMETRY=false前缀; - 需要复现的任务:使用
minimizing-ty-ecosystem-changes技能,配合共享清单、复制来的 profiling 二进制、已安装配置与唯一的临时目录,绝不生成另一份清单; - 来源可归因的任务:通过走完完整的 advanced-minimization 工作流,产出完全最小化且保留来源(provenance-preserving)的复现器——包括第三方依赖内联、标准库内联,以及对其余每个 import 的审查;
- 查看 vendored 定义与 Rust 实现时,用
git -C <ruff-checkout> show <exact-revision>:<repository-relative-path>,且 revision 必须取自不可变清单中分析过的版本,而不是恢复后的工作区; - 独立发明的相似例子不满足来源可归因任务;部分最小化的示例或原始代码摘录永远不满足任何最小化任务。若存在真实的外部阻塞,返回该阻塞并把任务标记为未完成(incomplete);
- 对无法恢复来源证据的结果:验证并报告捕获到的结果、stderr、panic 证据与运行频率,不要求源码复现器或最小化代码;
- 需要精确版本 debug 二进制时向主代理申请,不自行构建、不切换共享 Ruff ref;
- 主代理请求暂停时停止一切依赖检出的工作与子进程,确认后再确认暂停,保持暂停直到被显式恢复(即使 debug 构建失败);
- 不重建 profiling 二进制、不重新生成已发布的元数据、不重写已安装的配置、不切换共享 Ruff ref、不覆盖共享产物、不信任此前的本地复现、不以当前依赖元数据替代冻结版本。
3.1 复现与最小化的底层要求
被指派的子代理实际执行的是 minimizing-ty-ecosystem-changes/SKILL.md 中定义的流程。其不变量与交接文档完全一致:使用 Actions 运行里的精确 Ruff 版本、用户级 PR 配置、依赖裁剪时间点、mypy-primer revision、项目 Python 版本与严格性设置;先复现差异,再解释或编写更小的示例;每个缩减候选都同时用 base 与 PR 两个二进制验证;每个候选必须由前一个已验证候选推导而来,绝不凭空构造。
复现时,ty 以用户级配置方式使用生态配置(通过 XDG_CONFIG_HOME 指向 TY_ECOSYSTEM_CONFIG_HOME,并 unset TY_CONFIG_FILE、export RUST_BACKTRACE=1),strict 项目额外追加 --config analysis.strict-equality-semantics=true --config analysis.strict-generic-narrowing=true 两个严格性开关。项目源码则由 scripts/setup_primer_project.py 以 --revision <报告中的项目提交> --exclude-newer <EXCLUDE_NEWER> 检出到唯一临时目录,绕过相邻脚本自带的 lockfile。
最小化阶段必须阅读并穷尽 advanced-minimization.md 描述的完整缩减循环:先删除无关文件,再依次移除 import/定义/装饰器/注解/语句/分支,内联第一方定义;需要第三方依赖时先整体复制到源码树验证差异仍在,再开始删减;标准库定义则从被分析 revision 的 crates/ty_vendored 提取内联(merge-base 与 PR 定义不同时要逐一比对);最后用更简单的等价结构替换复杂构造。只有对每一阶段做一次穷尽性通过、再无进一步缩减时,最小化才算完成。
这里还有一个关键判定标准:诊断文本相同或显示的 @Todo 类型相同,都不足以证明原因相同。输出有歧义时,要用精确版本的 debug 输出、定向 reveal_type 或对应分析版本中的 Rust 调用点来比对"底层触发原因(causal fingerprint)"。而"相同行为变化 + 相同原因"的条目才能被归组(group by cause)或被判为重复。
四、必需的回报格式(Required Return)
交接文档同时规定了主代理应向子代理索要的回报结构与内容下限,区分两类任务:
来源可归因的任务,需要交付两份内容:
- 报告就绪的 GitHub Flavored Markdown:精确描述 base 对比 PR 的行为差异与最小化代码,可直接进入最终报告;
- 单独的 working notes(工作笔记):包含原始来源的 permalink、复现过程、被接受的缩减序列、两个二进制各自的结果、间歇性严重失败的分侧运行次数、任何必要的因果指纹(causal fingerprint)以及 import 审查结论。
无来源证据的结果,则交付报告就绪的 Markdown:描述验证过的项目结果、相关 stderr、panic 证据与运行频率——不涉及源码复现器。
重复条目(duplicates):若后续条目与已最小化条目"行为变化与原因完全相同",子代理可以将其分类为重复而无需重做完整最小化,但必须解释匹配依据。
五、从交接产出到最终报告
子代理的回报最终汇入 summarise-ecosystem-results 技能的主流程(见 SKILL.md):
- 识别变化:检查结构化 diff 中新增/删除/修改的项目、稳定的诊断增删改、项目失败与间歇性退出状态变化;保留诊断级别、重复出现次数、来源 permalink、项目严格性、panic 证据与观察到的运行频率;剔除 flaky 诊断与纯频率噪声,但不得因为项目本身 flaky 就排除其稳定诊断或严重失败变化。
- 从零复现:忽略保留的记忆与旧本地产物,对每个保留的来源可归因诊断或 panic 先复现再解释/最小化。
- 按已核实的原因归组,然后对照 ty 的问题跟踪器寻找精确对应的既有 issue 并从相关报告小节直接链接。
- 写作与验证:基于 report-template.md 填充
PR_<number>_ECOSYSTEM_SUMMARY.md(模板约定报告只含 Project failures / Intermittent severe failures / Affected projects / Reproduction 四个区段,每个 prose 段落与列表项保持单行源格式,删掉全部占位符与 HTML 注释),然后运行GH_TELEMETRY=false uv run --only-group dev --locked prek run --files PR_<number>_ECOSYSTEM_SUMMARY.md做格式校验,全部通过后才把 Markdown 作为最终成品呈现。
并行执行时,技能建议按可用并发预算尽量多地启动子代理(保留一个槽位给主代理自己),主代理按"不相交的项目或明确的报告条目"分派工作;如果存在多个独立任务却未启动任何子代理,则必须记录具体原因。
六、小结:这套交接协议在防什么
把 subagent-handoff.md 的通篇约束归纳成一句话:多智能体并行调查的最大风险不是"算得慢",而是"各自证据不一致"。 因此协议的核心动作全部围绕一致性与不可变性展开——冻结报告与 attempt、一次生成不可变元数据清单、主代理独占构建两个精确版本二进制、以不可变绝对路径发布共享产物、禁止任何子代理改写共享状态、对"来源可归因"任务强制完整最小化链路与独立 working notes。对于阅读或贡献本仓库的开发者而言,这份文档的实操价值在于:凡是需要复现历史 ty 生态差异的场景,都应当以 scripts/collect_ty_ecosystem_run_metadata.py + minimizing-ty-ecosystem-changes 技能为唯一入口,以两个 profiling 二进制为行为裁判,并始终警惕工作区提交与"被分析版本"之间的错位。
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 StartedRust0624
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