Repository navigation
Description
Written-by: Chief
现象
一个 workflow 节点该打印哪些 OUTPUT,只来自它自己声明的 nodes[].outputs。但出边上的条件也读 OUTPUT(edges[].when.output),这部分节点完全看不到。于是「节点没声明 outputs + 出边却按某个 output 分流」的图,天生不可能满足自己的闸门:节点不知道要打那一行,每一步都会落进 Missing OUTPUT <name>。
issue 快线 wf-1cdf6ec5 正是这种图:triage 节点没有 outputs,出边是 {from:"triage",to:"claim",when:{output:"state",eq:"ready"}}。结果最近 10 个 run 里 7 个死在 Missing OUTPUT state(i2643/i2645/i2646/i2652/i2654/i2656/i2660),PR 都开好了、合入了,run 还是 failed。#2666 修的是「已经交付的步不要判死」这个症状;根因是节点拿不到它该打的 OUTPUT 名单,不修的话,任何新快线都会重新踩。
链路(tip 3b8d4e8c)
-
plugins/workflow/src/service.js:725-742stepBody()组这一步交给 Bot 的内容,其中outputs: node.outputs ?? []—— 只有声明过的端口,没有出边读的那些。 -
plugins/workflow/index.js:90-91把名单写成一句提示:const outputs = (step.outputs ?? []).map(port => port.name).filter(Boolean) if (outputs.length > 0) lines.push(`When you finish, add one line per output: OUTPUT <name>: <value> (${outputs.join(', ')}).`)
outputs为空时这句根本不出现,节点于是从来不知道自己该打state。 -
missingVerdicts()按出边读的 output 判缺,commitAdvance把步判 fail(service.js:1218-1239)。两边对同一件事的认知不一致。
修法
stepBody()(service.js:725)把「出边读的 OUTPUT」并进outputs:新增一个纯函数(放graph.js,与missingVerdicts相邻)edgeOutputs(item, nodeId),返回[{ name, values: [...] }]:遍历item.edges里from === nodeId且when?.output的边,按 output 名聚合when.eq的取值(else不贡献)。声明过的端口优先,同名合并且补上values。index.js:90-91的提示带上取值域:名字有values时写成OUTPUT state: <one of: ready, escalate>,没有就维持OUTPUT <name>: <value>。这样一个没读过图的节点也能知道该打哪几个值。- 不改
missingVerdicts的判据,也不放松 fail:它仍然是「出边要的没打就失败」,只是现在节点能知道要打什么。
红先测试(plugins/workflow/test/step-body.test.js 或现有 assign.test.js):
- 造图:节点
triage无outputs,边triage→claimwhen {output:'state',eq:'ready'}、triage→escalateelse;断言stepBody(...).outputs里有state,且values含ready(改前为空 → 红); dispatch收到的文本必须含OUTPUT state(用假fb.bot.send抓文本;改前不含 → 红);- 声明了
outputs的节点行为不变(按声明那组输出,不重复、不丢); - 一条端到端的:
wf-1cdf6ec5这种形状的 run 里,节点按提示打state: ready后triage=done且claim起跑(可复用assign.test.js的夹具)。
验收命令:
cd plugins/workflow && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/resolve.mjs --test test/step-body.test.js test/graph.test.js test/assign.test.js
新用例改前红、改后全绿;node .github/scripts/changelog.mjs check 通过。
范围外
- 定义图时对「出边读了没声明的 output」报警/拒绝(是另一个决策,另开单);
#2666已经做的「已交付步站住」兜底;- 重写
template.js里 issue 快线的 prompt 文案(那是权宜,不是根因)。
风险面
plugins/workflow/** 不是 T0/T1,T2,PR 要 tip 上的 PASS。改的是每个节点收到的提示文本,所有 workflow 都会受影响,所以既有 assign/queue/graph 套件要一起跑。
Activity
Birfy commentedon Nov 8, 2026
Written-by: Chief
已派实现线
wf-67229151:taskIdi2669-impl(build → ship → report),05:14Z 起跑。改动面按本单正文:graph.js新增edgeOutputs、service.js的stepBody并集、index.js:90-91的提示带取值域,附红先用例与docs/subsystems/workflow.md一句。出 PR 走 PR 快线拿 PASS(T2)。fix(workflow): tell a node the OUTPUTs its edges read (ThinkFlowLab#2670
Release v0.2.27 (ThinkFlowLab#2701)