Mastra Software Factory 中的 factory-complete-issue 技能:把已完成的 GitHub Issue 干净利落地标记为 Done
2026/9/13 17:18:28 网站建设 项目流程

Mastra Software Factory 中的 factory-complete-issue 技能:把已完成的 GitHub Issue 干净利落地标记为 Done

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

Mastra Software Factory(位于本仓库mastracode/factory)是一套基于@mastra/factory的软件交付流水线:Agent 依次经过 Intake(接单)、Triage(分诊)、Planning(规划)、Execute(执行)、Review(审查),最终在 Work 看板的done终态阶段完成收尾。factory-complete-issue正是这条流水线的"最后一公里"技能——它负责把流水线背后关联的 GitHub Issue 正式标记为已完成,并同步清理之前各阶段留下的状态标签。

读完本文,你将掌握:该技能在 Factory 流水线中的触发位置与调用契约、它精确执行的标签变更与评论动作、它与factory-triage等上游技能之间完整的状态标签生命周期,以及它的幂等设计与安全边界。

技能在 Factory 流水线中的位置:done阶段的入口处理器

factory-complete-issue并不是一个需要人工调用的工具,而是 Work 看板进入终态时的自动动作。看 Work 看板的定义(mastracode/factory/src/boards/work.ts):

done: { title: 'Done', kind: 'terminal', outcomes: allOtherPhases, onEnter: { issue: completeIssue }, },

当一张卡片通过factory_transition_work_item被推进到done阶段时,completeIssue处理器被触发(mastracode/factory/src/boards/work.ts#L91-L99):

function completeIssue(context: FactoryStageRuleContext) { return { type: 'invokeSkill', idempotencyKey: `${context.ingress.id}:factory-complete-issue`, role: 'triage', skillName: 'factory-complete-issue', arguments: context.item.url ? `GitHub issue (${context.item.url})` : context.item.title, } as const; }

这段实现揭示了几条关键信息:

  • 触发条件:只有done阶段且事件来源为issue(即 GitHub Issue)时才调用该技能;从源码结构看,Linear Issue 等来源不经过completeIssue分支。
  • 入参来源:技能的$ARGUMENTScontext.item.url提供(形如GitHub issue (<url>)),无 URL 时退化为工作项标题——这正好对应技能正文要求的"从$ARGUMENTS解析 Issue URL 或编号"。
  • 幂等键${context.ingress.id}:factory-complete-issue由不可变的 ingress 身份派生,保证同一次进入done的动作最多被交付一次。
  • 角色role: 'triage',复用 triage 席位承载这个收尾动作,而不是为它注册独立 Agent——这与 README 中"Working roles name bindings on the shared Code Agent"的设计一致。

技能目录:六个内置 Factory 技能之一

该技能文件本身位于 mastracode/factory/factory-skills/factory-complete-issue/SKILL.md,是 Factory 服务端捆绑的六个内置技能之一。其注册清单见 mastracode/factory/src/workspace.ts#L81-L88:

export const FACTORY_SKILL_NAMES = new Set([ 'configure-factory-rules', 'factory-complete-issue', 'factory-plan', 'factory-rereview', 'factory-review', 'factory-triage', ]);

技能的加载与展示逻辑由 mastracode/factory/src/skills/catalog.ts 实现:它逐个读取SKILL.md,剥离 YAML frontmatter(namedescription),把正文作为技能内容提供给设置界面与运行时。路由层则通过GET /web/factory/projects/:id/skills之类的技能接口对外暴露,routes/skills.test.ts中也有对应断言(mastracode/factory/src/routes/skills.test.ts#L510-L513),确认factory-complete-issue会出现在技能清单中。

核心动作契约:精确的标签清理与状态回写

SKILL.md 正文定义了该技能的完整操作序列,这里逐条展开:

第 1 步:解析并读取现状。$ARGUMENTS中解析出 GitHub Issue 的 URL 或编号,然后用gh issue view读取其当前状态(open / closed)与全部标签。

第 2 步:清理三枚分诊标签。若以下标签存在于该 Issue 上,逐一用gh issue edit移除:

  • status: needs triage
  • status: auto-triaged
  • status: needs approval

第 3 步:按状态分支处理(核心判断逻辑):

  • Issue 仍处于 open 状态:若status: pending-close尚未存在则添加之;并发布评论This issue has now been marked as done.(仅当该评论尚未存在时)。
  • Issue 已处于 closed 状态:不添加status: pending-close,也不发布评论。

第 4 步:边界约束("Do not"清单):

  • 不修改任何其他标签或 Issue 字段;
  • 不关闭、不重新打开、不指派(assign)该 Issue;
  • 不请求另一次 Factory 阶段流转。

换言之,这个技能把"关闭 Issue"的最终决定权留给外部流程(如定时 sweep 依据status: pending-close标签处理关闭),Agent 只负责在 Issue 上留下一致的、可审计的状态痕迹。这也与@mastra/factoryREADME 中"transition decisions are governed by server rules"的总体设计一致——技能本身不越权执行阶段流转。

状态标签生命周期:从 Triage 到 Complete

要理解这些标签为何要"被清理",需要对照上游技能factory-triage(mastracode/factory/factory-skills/factory-triage/SKILL.md)为 Issue 打上的状态:

标签由谁添加含义
status: needs triagetriage 阶段 Phase 1(Issue 尚无status:标签时)等待人工/自动分诊
status: auto-triagedtriage 阶段 Phase 5(发布分诊评论后,所有 GitHub Issue)已由 Factory 自动分诊
status: needs approvaltriage 阶段(当Route: Await approval或推荐动作需要维护者批准时)等待批准
status: pending-closefactory-complete-issue(Issue 仍 open 时)工作已完成,等待外部流程关闭
effort:<level>/impact:<level>triage 阶段工作量与影响分级

因此factory-complete-issue实质上承担了标签生命周期的"收尾清理"职责:把整个分诊过程留下的三枚status:标签全部移除,同时打上终态标签status: pending-close,使 Issue 的标签状态与流水线卡片的done阶段保持一致。而effort:/impact:标签与领域标签(如@mastra/core)不在移除范围内——它们是对问题的长期归档信息,这正体现了"只动状态标签、不碰其他元数据"的克制设计。

幂等与防重:为什么"评论已存在就不重复发布"

SKILL.md 反复强调"除非该评论已存在"与"仅当status: pending-close尚不存在时添加",这是为重复执行(replay / re-entry)设计的幂等保护。结合completeIssueidempotencyKey,整套机制可以归纳为:

  • 进入done阶段的动作是幂等的:同一次 ingress 不会重复调用技能;
  • 技能内部的写操作也各自幂等:标签添加、评论发布都先检查再写入,即使技能因重放被再次执行,也不会产生重复评论或重复标签;
  • 关闭 Issue 被明确排除在技能职责之外:避免 Agent 在边界不清时做出不可逆操作。

从源码结构看(mastracode/factory/src/boards/work.ts 中donekind: 'terminal'终态,Work 看板另有canceled终态,两者均无对外二次流转),整个收尾链条是单向且闭合的——技能完成后流水线不再请求新的阶段流转,这与 SKILL.md 最后一条"Do not request another Factory transition"完全对应。

运行前提与验证方式

要实际看到该技能被执行,部署环境需要满足 mastracode/factory/README.md 描述的基本条件:配置好FactoryStorage后端、GitHub 集成、已连接的项目仓库,并通过宿主应用的prepare()new Mastra(...)finalize()序列完成装配。同时满足:

  1. 一个 GitHub Issue 已被接单并走完intake → triage → planning → execute → review流程;
  2. 卡片通过受管制的factory_transition_work_item被推进到 Work 看板的done阶段;
  3. 运行环境拥有对目标仓库调用gh issue viewgh issue edit的权限。

验证时,可以对比 Issue 标签前后状态:执行前若存在status: needs triage/status: auto-triaged/status: needs approval中的任意组合,执行后应全部消失;若 Issue 原本 open,则新增status: pending-closeThis issue has now been marked as done.评论;若原本 closed,则两者都不出现。routes/skills.test.tsskills/catalog.ts的测试/实现可用于验证技能在技能清单中的注册与 frontmatter 解析是否正确(mastracode/factory/src/routes/skills.test.ts#L510-L513)。

小结

factory-complete-issue是 Mastra Software Factory 收尾环节的关键拼图:它由 Work 看板done终态的onEnter处理器自动触发,通过一组精确、幂等的 GitHub 标签与评论操作,把"流水线已完成"这一事实同步回源 Issue,同时把关闭动作留给外部机制。理解它,也就理解了 Factory 如何在整个软件交付循环中维持"卡片状态、Issue 状态、标签状态"三者的一致性。

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询