主 Agent 把 workflow.json 发给两个子 Agent 并行处理, 都 in-place 加字段 (不要 Write 重写整个文件). 收集后合并的状态仍是同一份 workflow.json (子 Agent 改的是不同字段, 不冲突).
工作模式 (重要): Phase 1 已经 Write 了 workflow.json 骨架, Phase 2 子 Agent Read workflow.json + 给已有 step/IO 逐字段填值, 不写新文件。每个值都是逐 step 的语义判断(这个 step 的 effect 是哪片叶子、这个 IO 的 type 是什么)—— 不要写 normalize 脚本去机械批改, 那等于把判断退化成代码里的映射规则。落字段的两种方式:
wf-patch.py —— 把决策写成 --patch _scratch/2a.json 清单 ([{"path":"p1.s2.effect","value":"主体生成"}, ...]) 一次应用。工具写入即校验 (effect 必须是叶子、type 必须叶子或已注册、substance/form 走词表校验), 非法整批不写, 你不碰 JSON 序列化。详见 tools.md §2。这样:
context: workflow.json + spec §A.1 (作用树, 9 叶) + §A.2 (动作树, 5 L1 + 控制) + §A.3 (类型树, 4 大类) + 现有 type_registry — 全部小, 整体进 context。
任务:
提取/化学提取/反推、生成/元素生成); 控制类 控制/并行 控制/遍历 自动转到 特性 字段类型归一 (对每个 input/output 的 type, 走以下 funnel 不要省步骤):
候选扩展: 基于 IO 的 name + value 描述, 显式列出 3-5 个候选 type 词 (不是只猜一个).
<图: 苏晚 25 岁年轻女性肖像, 卧室床上> →
候选: [参考图, 主角图, 人物肖像, 人物参考, 分镜图]字典匹配 (按优先级, 命中即停):
$leaves)? 用它 (e.g. 候选含"参考图" → 命中)b. extends 桥接: 都没命中, 但有候选语义贴近某叶子 → 选最近 leaf 做 extends. Edit workflow.json, 在该 procedure 顶层加 type_registry 段 (每个 procedure 独立 type_registry, 单 case 多工序时不冲突). 格式:
// workflow.json (部分)
{
"procedures": [
{
"id": "p1-simple",
"name": "...",
"type_registry": {
"主角图": {"extends": "参考图", "desc": "case-specific 主角肖像"}
},
"steps": [ ... ]
}
]
}
⚠ 不要只在 IO item 内 inline 写 extends 子字段 — renderer 走 procedure 顶层 type_registry 找, IO inline 字段它不读.
不必手工写 type_suggestions.md:
Phase 3 跑 bin/lint-case.py --workflow 时, 会自动扫每个 procedure 的 type_registry 把所有 case-specific entry record 到 spec/taxonomy/type_suggestions.md (幂等, 同 (type_name, case_id) 只写一次). 你只要保证 procedure.type_registry 每个 entry 含 extends + desc 就行, suggestions 文件让工具维护.
lint 自查 (轻量自检, 真正校验由 Phase 3 lint-case.py 跑):
[ ] 每个 IO 的 type 要么命中 §A.3 叶子 (type.json $leaves), 要么所在 procedure 的 type_registry 段里有该 type 的 extends + desc 项
[ ] 走 2b 的所有新 type 都在对应 procedure 的 type_registry 段出现
[ ] 不允许 type 字段写"自由名"但所在 procedure 的 type_registry 缺对应 entry — 这种 silent gap 会让 Phase 3 渲染 HTML 时 drawer metadata 全丢, Phase 3 lint-case.py 会捕捉到
输出: 写回 workflow.json (几十个字段批量用 wf-patch.py --patch, 见开头工作模式; type_registry 也能 --set p1.type_registry.X.extends=... 注册), 给每个 step 加 effect / action / feature / control 字段 + 给每个 IO 加 type 字段 (Phase 1.2 已有则归一, 没有则填). 不写新文件, 不写生成脚本.
context: workflow.json 中所有 input/output 的 name + value + 上下文 + 调 spec/tools/taxonomy-lookup.py tool. 实质·形式 JSON 词表本身不进 context, 完全通过 tool 查询。
tool 接口: ```
spec/tools/taxonomy-lookup.py --dim {实质|形式} --list-l2 # 列二级路径 spec/tools/taxonomy-lookup.py --dim {实质|形式} --subtree # 返回子树 (叶子 + alias) spec/tools/taxonomy-lookup.py --dim {实质|形式} --match "" # 多 token 拆词聚合 (推荐用法) spec/tools/taxonomy-lookup.py --dim {实质|形式} --narrow "" # 层级下钻 (--match miss 兜底) spec/tools/taxonomy-lookup.py --dim {实质|形式} --validate # 校验路径存在 ```
任务 (对每个 input/output value):
--match "tok1 tok2 tok3" (空格分隔, tool 自动拆词聚合)
<图: 苏晚 25 岁年轻女性肖像, 卧室床上> → --match "年轻女性 卧室 床上 肖像"--match 返 (无匹配) → 同 query 切 --narrow 走层级下钻 (按子树整体语义打分)--subtree <候选> 列叶子细节, 选最贴的--validate <chosen_leaf> 确认前再写回; 完全无法匹配 → unmatched⚠ 避坑: 不要把整段 value 描述塞进
--match(e.g.--match "苏晚 25 岁年轻女性, 卧室床上, 湿发素颜"), 标点会被当 token 一部分干扰拆词. 提炼 2-5 个干净的描述性词组就够.
输出: 写回 workflow.json (几十个 IO 批量用 wf-patch.py --patch, 见开头工作模式; substance/form 会自动走 taxonomy-lookup 校验, 设 null 传 __null__), 给每个 IO 加 substance: /xxx/yyy + form: /xxx/yyy (或 null). 不写新文件, 不写生成脚本.