分享一个AI管理本地issue的工作流

国庆这几天参与到一个朋友写的minecraft mod项目里面,用来让AI玩minecraft。原本我也基于mineflayer写过一个maicraft-mcp-server,但是受限于mineflayer只能游玩原版minecraft。这个项目以mod的形式可以兼容其他的mod,且可以直接以第一人称视角而不必进入旁观者模式来直播,可以作为另一个我作为主力开发者的AI Vtuber项目Amaidesu 的minecraft agent实现。

花了一两天搞明白项目整体架构之后,我就开始让AI对此进行实机测试了,因为它本身是一个mcp server,让AI来测试是很自然的。

随后我便发现,既然AI自己就是用户,那么AI自己测出问题提issue,自己修,再自己回去游戏里面验证,这个循环好像不用我管,可以省很多事情。而且重要的事情让它挑出来给我决策,也不会出什么大事。

于是参考github的issue设计了一套本地issue的方式,在这个项目里面使用,本文分享一下这个方法。

AGENTS.md

1
2
3
4
5
6
.omo/issue/
├── REGISTRY.md
├── closed/
├── outbound/
├── pending-decision/
└── pending-verify/

具体的内容比较长,我用人话总结一下核心内容,可以自行让AI扩展出属于读者自己的:

  1. 在本地不被版本管理的目录(我这里就复用oh-my-opencode的.omo目录了)里面建一个issue子目录,
    • 其根目录里面放待修复的问题(3位数编号,每个问题一个md文件)
    • 修完的问题放在待验证目录(pending-verify);
    • 验证没问题的放在关闭目录(closed);
    • 需要人来决策开发方向的放在待决策区(pending-decision);
    • 给我朋友去处理的放在外发区(outbound。当然,为了避免AI issue污染仓库,我基本上都是直接私信他的);
  2. 在提issue之前,需要在公共文件取号占号,避免思考过程中编号被人抢了导致重复;
  3. 在修复issue的时候,需要在.omo/worktree.md选一个没有被占用的常驻worktree,如果都满了,就再在项目父级目录再扩充一个,完成后不删除。

本地issue结构

其实没有固定的结构,只要把复现方式写清楚,就可以让负责验证的AI来复现并且验证修复情况。

如下列出的例子是多个AI多次修改后的结果,实机测试的AI只负责以用户视角提出issue,修复问题的AI编写原因和修复方式,接着再交还实机测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 063:craft 能力不把背包内的合成台计为可用工作面,导致配方规划爆炸  

状态:closed

## 场景(003 通关实机,2026-10-04)

玩家背包内携带 `minecraft:crafting_table ×1`,提交 `maicraft:craft item_id=minecraft:wooden_hoe count=1`:

- 失败 `crafting_surface_missing`,但同时规划器进入递归原料爆炸:为凑"工作面"把 `crafting_table / fletching_table / smithing_table` 当作**待合成的库存事实**递归展开,枚举了全部 20+ 种原木(acacia/birch/oak/crimson/bamboo…)作为建桌原料,issues 列表膨胀到上百条;
- 而此时背包里明明白白有 crafting_table ×1(failure_observation 可见),却未被计为可用表面;
- 对比:`acquire_items` 的 craft 族在同一背包状态下正常走通——自建临时工作台(放置+用完回收),同一配方一次成功(铁镐/铁剑/熔炉均如此)。

## 问题实质(两层)

1. **背包内合成台不计为可用工作面**:craft 族的表面判定只认"已放置在世界中的合成台",不认携带物品;而它自己的姊妹路径(acquire 的 craft 族)却支持临时放置。同一状态两条路径行为不一致。
2. **递归规划无剪枝**:把"工作面"当合成目标递归展开原木全家族枚举,issues/recipe_trace 输出失控(单条回执超 80KB),既浪费算力也淹没真正有用的失败原因。

## 复现要点

背包带 crafting_table ×1 + 任意 3x3 配方材料(无已放置合成台),直接 execute `maicraft:craft`。稳定复现。

## 影响

- 直接 craft 路径在野外(未放置合成台时)不可用,调用方必须绕道 acquire_items 才能合成——本局因此多绕 1 次调用;
- 规划爆炸回执超预算被截断,掩盖真实失败原因。

## 建议方向

- craft 族的表面准备对齐 acquire 的 craft 族:可临时放置背包内合成台(放置+回收);
- 或至少把"携带合成台"计为可用表面(原地使用);
- 递归原料枚举设置深度/宽度上限,超出后摘要报告。

## 修复情况(2026-10-04 远端并入,待实机验收)

两个远端提交联合覆盖本 issue 的全部症状:

- `0c5652f9 fix(craft): 排除伪合成台并阻止重复补台`——`CraftingWorkstationCoordinator` 新增 `ordinaryCraftingTable` 判定,把复用工作台父类但不提供三乘三合成的制箭台、锻造台从候选集排除;扫描、随身取台(`carriedTable`)与补台材料树统一到同一候选集,堵住"一个入口排除的错误工作面又从另一入口回来"的递归来源;失败回执新增 `main_inventory_workstations`(随身背包中的可用台),区分没带台、找不到放置点与已发现世界中的台。
- `ad1ca0d2 fix(acquire): 中间材料到包后收起多余的递归需求`——`SemanticAcquireCompanionTask` 在中间材料入库后收起对应递归需求,抑制规划爆炸。

代码级验证:`CraftingRegressionSuite` 新增/扩展 `CraftingWorkstationPlanningTest`(伪台排除与重复补台)、`CraftAbilityWorkstationTest`(能力级工作面事实)、`AcquisitionRecipePlanningTest`、`AcquisitionPrerequisiteRefreshTest`(递归收敛)。

待取的实机证据(按原复现剧本):背包带 crafting_table ×1 + 任意 3x3 配方材料、无已放置合成台,直接 `maicraft:craft`——应一次成功(放置随身台或就地使用),回执无递归原料爆炸、issues 列表不再上百条。

关闭说明(2026-10-04):修复提交 `0c5652f9` + `ad1ca0d2` 已随远端并入 dev 并推送。验证程度:4 个相关回归通过,实机复现剧本未执行——用户指示直接关闭。若后续实机在原剧本上复现任一症状,将本文件移回 open 并引用原剧本。

工作流

原本我是自己手动执行上面的流程的,也就是开多个会话让AI去修复各个issue,以及进行实机测试,之后猛然意识到,都有固定流程了那肯定得让AI来干活啊。

于是我就让agent自己派子agent去干活了,甚至结合idea的mcp和Computer Use能力,还能让它自己重启游戏客户端并点进存档派子代理测试。

最后隔一段时间就让其rebase回dev,然后用cherry-pick和filter-branch –msg-filter进行提交信息改写,把那些不像人话的提交信息改一改,提交之后compact上下文,开始下一轮。

# 管家调度规则(issue 派单与实机验收)  
  
会话管家的工作手册。管家不亲自占坑开发:修复由派出的 agent 会话在常驻工作树完成,  
实机环境(游戏客户端、IDEA 界面)由管家直接操作。目标是 open 与 pending-verify  
两区的 issue 全部按本规则流转到 closed。  
  
## 区位与流转  
  
| 区 | 含义 | 管家动作 |  
|---|---|---|  
| `issue/`(根) | open,可开工 | 派单修复;拿不准修法的移 pending-decision |  
| `issue/pending-decision/` | 待用户拍板 | 只进不出:存量不代答不改动;新增项移入时写明待决策问题与可选项 |  
| `issue/pending-verify/` | 代码已收口,只差实机 | 安排实机验证批次,按文内剧本取证 |  
| `issue/closed/` | 实机验证通过 | 终点;移入时补实机验证结论(场景、任务 ID、净变化) |  
| `issue/outbound/` | 已外发 GitHub 公开池 | 本地不自行开工;上游修复合并进 dev 后按正常流转实机收口 |  
  
流转路径:  
  
- open → 修复提交(回归通过)→ pending-verify(状态改"已修复待实机",写提交 hash 与代码级验证方式)  
- pending-verify → 实机验证通过 → closed(补实机验证结论)  
- pending-verify → 实机验证失败或部分成功 → 退回 open(附失败证据),继续修  
- open → 修法涉及产品语义/授权边界/多方案取舍 → pending-decision  
- 移区不改号;REGISTRY.md 位置列与文件实际位置保持一致;issue 认领行与 `worktree.md` 占坑表一致  
  
## 派单流程  
  
1. 盘点:open 区无认领项 × 占坑表空闲 worktree;汇报时活跃任务置顶。  
2. 交集预检:新任务目标文件集与主工作区、其他占用 worktree 的未提交变更求交集,非零重叠换 issue 或协调串行;对已提交待并入分支的同文件改动,登记并入顺序预期。在途分支的交集判定用树差异 `git diff --name-only <dev头> <分支名>`(内容级真实差异),不用提交范围 `git log A..B`——任务分支基于历史重写前的旧 dev 时,重写前原始件(内容已并入但 hash 不同)会被错算成未并入提交产生假重叠。
3. 占坑:管家代写 `worktree.md` 占用节与 issue 认领行(先占坑后开工);分支 `task/<slug>` 基于 dev。  
4. 派发:agent 会话提示词自足(规约指向 AGENTS.md,列明 issue 路径、修复范围与验证纪律——**代理在任务分支自行 git commit**(2026-10-06 晚起提交交回子代理),提交信息按 AGENTS.md「提交信息起草自查」全项执行、含机械禁用词 grep,回报分支名、提交 hash、改动文件清单与套件结论;同时要求同步更新受影响的文档/知识卡/能力契约与注释,文档过时与缺失同罪;**派单提示词必须写明提交规范与机械扫描要求**);验证/实机会话立新 issue 时执行 AGENTS.md「issue 文风同人话纪律」与「issue 场景必须自足」——禁用「腿」「露天柱」等直译黑话,场景按四要素写全,**派单与回报文案同样执行机械禁用词扫描**;agent 只改自己认领的 issue 文件与生产代码,`worktree.md` 与 `REGISTRY.md` 由管家统一收口改写。  
5. 收口与并入:回报到达后管家复核任务分支 diff 与提交信息(黑话/编号/模板痕迹不合即退回改写),线性重放(cherry-pick)到最新 dev 完成增量并入——不等其它分支;若子代理已跑过的套件与并入后同树则结论沿用,跨支并入后由下一轮全量 check 兜底。占坑表、账本位置列、issue 移区由管家统一改写;工作树切回占位分支、任务分支待推送后清理。  
  
## 实机验证流程  
  
- 环境:两个游戏客户端,IDEA 运行配置 NeoForge Client (1)/(2),MCP 端口 8766/8767,各占一块副屏;一个客户端同一时刻只服务一个验证会话。  
- 待验物必须是客户端里真实包含的代码:修复未并入 dev 的先由用户并入(管家不自行合并/推送),或明确按任务分支构建验证。  
- 证据标准:任务终态 data 加背包/世界净变化对账,两者齐才下结论;回执状态不作实物裁决。  
- 等待游戏内任务一律 `perceive attention`(wait_ms),禁止 sleep 无人看管。  
- 含中文的 MCP 参数走 `tools/maicraft_cli.py` 的 `@file` UTF-8 载荷;游戏重启后先 `init` 重握手;界面弹窗、崩溃报告、重启客户端由管家操作。  
  
## 流水账  
  
`.omo/butler-log.md`:顶部「当前活跃」表跟踪进行中的派单与验证(收口后移入日志);  
每次派单、验收、移区、实机操作记一行(时刻 | 动作 | 对象 | 结果/下一手)。并发写纪律:写前重读、写后复读——多个会话与管家并发追加时,整文件读改写会用旧内容覆盖他人新行(2026-10-05 实发),丢失的行以最新事实补写。  
  

分享一个AI管理本地issue的工作流

https://yxchangingself.xyz/posts/local-issue-tracking/

作者

憧憬少

发布于

2026-10-05

更新于

2026-10-05

许可协议