跑这道 skill 时会用命令行调用几个脚本,这里讲它们怎么用。脚本都在
spec/tools/下,你不用读脚本源码,会调就行。
spec/tools/taxonomy-lookup.py — 查"实质/形式"两张大词表做什么:第二阶段给整步标"实质/形式"时,用它查这两张大词表(911 + 565 条路径)。词表太大不直接读进来,全靠这个命令现查。
子命令:
| 子命令 | 用法 | 返回 |
|---|---|---|
| 列二级路径 | python spec/tools/taxonomy-lookup.py --dim 实质 --list-l2 |
各 L2 路径 + 该子树叶子数 |
| 看子树 | python spec/tools/taxonomy-lookup.py --dim 实质 --subtree /表象/视觉 |
该子树所有叶子 |
| 字符串匹配 | python spec/tools/taxonomy-lookup.py --dim 形式 --match "中景特写" |
排序候选路径 (单 token 行为) |
| 多 token 聚合 | python spec/tools/taxonomy-lookup.py --dim 实质 --match "年轻女性 卧室 床上" |
各 token 各自打分聚合, 覆盖多 token 的 path bonus |
| 层级下钻 | python spec/tools/taxonomy-lookup.py --dim 实质 --narrow "AI生成 提示词" |
从 L2 起按子树语义打分逐层下钻 top-K (兜底 match miss) |
| 校验路径存在 | python spec/tools/taxonomy-lookup.py --dim 实质 --validate /理念/知识/化学 |
OK / PARTIAL / MISS (exit 0/1) |
关于 --match 的多 token 行为 (2026-05-22 起):
--narrow 兜底关于 --narrow 的层级下钻 (2026-05-22 新增):
(token 命中次数, 命中的 token 数), 按 cov ↘ hits ↘ 排序--top-per-level (默认 3), 进下一层只展开这些候选的直接子节点--depth (默认 3 层, L2→L3→L4→L5) 或全部到叶子--match 容错更强: alias 完全没覆盖但路径段语义沾边的 case 也能召回 (e.g. "镜头语言" 不在 alias 但 /呈现/视觉/视觉制作/构图编排 路径段直接对路)Agent 用法 (典型 funnel):
--list-l2 决定大致 domain (实质先选 /理念 vs /表象, 形式先选 /呈现 vs /架构)--match <query> 多 token 召回候选 (大概率一步搞定)--match 返 (无匹配) → --narrow <query> 按子树语义下钻--subtree <chosen_path> 看候选 leaf--validate <leaf> 确认后写回 workflow.json 对应 IO 的 substance/form 字段词表文件路径 (按优先级 fallback):
$TAXONOMY_DIR/分类库导出_{实质|形式}_*.json (env override)procedure-dsl/data/分类库导出_*.jsonexamples/process_pipeline/script/resource/分类库导出_*.jsonexamples/process_pipeline/test_script/procedure_dsl_agent/data/分类库导出_*.json~/Downloads/分类库导出_*.jsonspec/tools/wf-patch.py — workflow.json 安全批量字段设置器做什么:批量给 workflow.json 的步骤/输入输出填字段(第一阶段连"来源",第二阶段填作用/动作/类型/实质/形式)。凡是"给一批字段赋值"都用它,别写 Python 脚本去拼/改 workflow.json(脚本拼 JSON 容易把文件弄坏)。分工:你出判断(哪个字段填什么),工具负责安全写入 + 当场检查对错。
两个保证:
用法:
# 单条 / 多条 --set (path=value, 只在第一个 = 处切; value 可含 = 和空格, 整体加引号)
python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json \
--set 'p1.s1.inputs[0].anchor=← s0.主角图' \
--set 'p1.s2.effect=主体生成' \
--set 'p1.s2.action=生成/图像生成/文生图'
# 批量: 几十处 anchor / 字段一次过 — 写一份 patch 清单 (你仍逐条显式决策每个值), 一条命令应用
python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --patch _scratch/anchors.json
# anchors.json = [{"path":"p1.s1.inputs[0].anchor","value":"← s0.x"}, ...]
# 只校验不写
python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
# 透传回填: anchor 设好后, 自动把"原样透传"的 value/directive 从源逐字抄过来
python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --resolve-passthrough
--resolve-passthrough(省得重复抄内容):规矩是"值"要写真实内容,不能写"(同上)""见 s1o1"这类引用(那是"来源"该干的,lint 会报)。但同一段内容被后面好几步原样复用时,手抄好几遍很烦。用这个:只在源头那个输出里填一次真内容,其余引用处把"来源"设成 ← 源的编号,工具就顺着编号把真内容逐字抄到每个"值"还空着的输入(链式引用也会一路抄到底)。源头找不到的会用 ⚠ 提示。可单独跑,也可跟在 --set/--patch 后面。
路径语法 (proc / step 按 id 寻址, 不是下标; 只有真列表才用 [i]; 嵌套步 id 带点如 s2.1 也支持):
| 路径 | 设的字段 |
|---|---|
p1.s2.effect |
step 标量 (effect / substance / form / via / action / directive / kind / intent / group) |
p1.s1.inputs[0].anchor |
IO 字段 (anchor / type / value / id) |
p1.s2.1.outputs[0].type |
嵌套步的 IO |
p1.s2.focus |
step 的 focus 数组 (逗号分隔: focus=via,action,out-type-0) |
p1.purpose |
procedure 头部 (name / purpose / category / platform / author) |
p1.declarations.inputs[0].desc |
declarations 内任意字段 (通用下钻) |
source.url |
case-level 原帖信息 (platform / author / date / url / title / excerpt) |
p1.type_registry.场景图.extends |
注册 case-specific 类型 (自动建 type_registry 段) |
--unset PATH (删字段, 可重复): 删掉某字段, 取代手 Edit 删. e.g. --unset p1.declarations.inputs[0].inferred (declarations 不收 inferred, schema 会拒). 字段本就不存在 → 跳过 (幂等, 不报错).
各字段校验规则:
effect → effect.json 叶子 (给全路径会自动归一到叶名)action → action.json 叶子 / 叶路径 (给叶名自动展开成全路径)type → type.json 叶子 或 本 procedure 已注册的 type_registry 名 (没注册会提示先 --set p.type_registry.X.extends=<叶子>)extends → 必须桥到 type.json 叶子substance / form / url → substance/form (step 级) 走 taxonomy-lookup --validate; 三者均可传 __null__ 设 JSON nullanchor → 必须 ← (输入引用, 指向某 output id) 或 → (输出去向) 开头kind → {step / block / nested}focus → 逗号分隔 → 数组 (空串 → [])仍用 Write / Edit 的只剩: 骨架首次创建 (Phase 1.2 从 template Write). 改字段 / 删字段 / 改 source 现在都走 wf-patch (directive 也是普通标量字段, 直接 --set), 不要再 Read→Edit 改 workflow.json (那会反复重读、烧 token).
退出码: 0 全通过并写入 (或 --dry-run 通过) / 1 有校验失败 (整批未写) / 2 CLI 错 / 文件不存在 / JSON 损坏.
spec/tools/render-case.py — 阶段三 workflow.json → HTML 渲染 + schema 校验用途: 阶段三. 接收 workflow.json (多工序 procedures:[]), 在内存组装成 case_data (merge --source-input 原帖 + --page-title + --case-id), 跑 schema 校验, 渲染输出 HTML. 不落盘 case_data.json.
Agent 用法 (推荐): workflow.json 已含全部 procedures + 标注后:
# 1. 只校验, 看 schema 错 (建议带 --source-input, 让校验看到的就是 merge 后的最终版)
python spec/tools/render-case.py \
--workflow outputs/case-{N}/workflow.json \
--source-input input/case-{N}-raw.json \
--page-title "Case {N} · <主题>" \
--case-id {N} \
--validate
# 2. 校验通过后渲染输出 (--source-input 必带, 否则 HTML 折叠原文区只剩 60 字 excerpt)
python spec/tools/render-case.py \
--workflow outputs/case-{N}/workflow.json \
--source-input input/case-{N}-raw.json \
--page-title "Case {N} · <主题>" \
--case-id {N} \
--out outputs/case-{N}/case-{N}-<slug>.html
关于 --source-input (2026-05-22 新增): renderer 直接从原帖 raw json 抽 body_text + 封面 + 图集兜底, in-place 填到 case_data.source —— Agent 不必手工复制原文内容. 行为:
body_text / cover_image 直接覆盖 case_data 同字段title / url 仅在 case_data 缺时填excerpt / author / date / platform 不动 (那些是 Agent 推断的友好版本)[image:URL] 标记, 把 raw.image_url_list 里没 inline 也不是封面的图 append 到 body 末尾 (加 --- 附图 --- 分隔符). 适配"小红书短文 + 多图独立列" 和 "微信公众号长文 + inline 图" 两种平台输入契约: 见 spec/format/case-data.schema.json (canonical JSON Schema Draft 2020-12, 受控字段 + enum + 条件约束 if/then).
模板: spec/templates/workflow.template.json (复制到 outputs/case-{N}/workflow.json 后替换 <填:...> 占位符).
⚠ 绝对不要参考其他 outputs/case-*/build_html.py 或 outputs/case-*/*.json — 那些是 case-specific 产物, 不是模板. 唯一 canonical 模板是 spec/templates/workflow.template.json.
输出码:
0 — 成功 (渲染或校验通过)1 — IO / schema / 渲染异常2 — CLI 参数错误依赖:
spec/tools/renderer.py (跟本脚本同目录, 自动 import)jsonschema (装了用 Draft 2020-12 完整校验; 没装走 minimal check fallback)spec/tools/lint-case.py — 轻量 lint + 自动 record 新 type用途: 阶段三. 跑完 render-case.py 后跑一次. 干三件事:
type_registry 漏注册 / 缺 extends / 缺 desc"的情况, 打 stdout 给 Agent / 用户看wf-patch.py --resolve-passthrough 自动回填spec/taxonomy/type_suggestions.md 累积条目段 (Agent 不必手工 Write suggestions, 工具代劳)幂等: dedup key = (type_name, case_id) 二元组. 同 case 重跑不重复; 不同 case 同名允许 (跨 case 频次是升级信号).
用法:
# 默认: 检测 + 自动 record
python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N}
# 只检测不写
python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N} --no-record
输出范例 (case 含 silent gap 的情况):
[lint] case-1 (workflow.json)
· type 完整性: 2 个提示
- [p1] step[1].outputs[0].type='主角图' 是 case-specific 但该 procedure 的 type_registry 没注册
- [p1] step[8].inputs[1].type='主角图' 是 case-specific 但该 procedure 的 type_registry 没注册
· 无新 type 可 record (type_registry 为空 — 全部 type 命中字典叶子)
退出码: 始终 0 (不阻塞流程). 解析 2 = CLI 参数错 / 文件不存在.
设计哲学: 不严格. 检测项是 hint 不是 fail; record 是副作用不是核心契约. Agent 看 stdout 决定回不回去补 case_data.type_registry.
spec/tools/renderer.py — HTML 渲染主模板 (Python 模块)做什么:把数据渲染成网页的主程序,被 render-case.py 在内部调用。
你不用读它——通过 render-case.py 调用即可。要了解格式,看 format/case-data.schema.json(机器清单)和 format/workflow-format.md(格式说明)就够了。
run_procedure_dsl.py — runner 本身 (不在 skill 内)跑 Agent 的入口脚本. Agent 不读它 — 它在跑 Agent. 但 Agent 可能想知道自己被怎么起的:
allowed_tools = ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task", "Agent"] # 🟢 Task / Agent 均可召唤子 Agent (新旧标识符)permission_mode = "bypassPermissions" (Agent 全自动, 不停下来问)cwd = procedure-dsl/ (Agent 的工作目录)--resume 支持 (中断后续跑)outputs/case-{N}/_trace.md| 路径 | 内容 | 谁负责 |
|---|---|---|
input/case-{N}-raw.json |
原 case 素材 (title / link / body_text / image_url_list / ...) | 人 (Agent 读, 不写) |
outputs/case-{N}/ |
Agent 工作目录 (一 case 一目录) | Agent (写产物) |
outputs/case-{N}/.session_id |
SDK session UUID, 用于 --resume |
runner 写, Agent 不动 |
outputs/case-{N}/_trace.md |
runner 写的实时执行流水 | runner (Agent 别 Read) |
outputs/case-{N}/_scratch/ |
sanctioned scratch 区 — 只用于 dump 大 Bash 输出 (taxonomy --subtree 长结果 / find 结果) 之后 Read 切片, 或一次性 smoke test. runner 预创建. 不要用项目根的 scratch/. ⚠ 不是写 build/normalize 脚本生成 workflow.json 的地方 —— 那个用 §2 wf-patch.py |
Agent (随便 dump, 跟着 case 一起清理) |
outputs/case-{N}/understanding.md |
阶段一 1.1 心智模型 (含多工序判断) | Agent |
outputs/case-{N}/workflow.json |
唯一中间产物 — Phase 1.2 Write 骨架 (从 template), 之后逐字段演化: 单处用 Edit, 批量结构化字段 (1.3 anchor / 2 effect·action·type + step 级 substance·form) 用 §2 wf-patch.py. 绝不写 Python 脚本生成 / 批改它. 符合 case-data.schema.json (procedures:[]) |
Agent |
outputs/case-{N}/case-{N}-<slug>.html |
阶段三 .html 输出 (跑 render-case.py 生成; 唯一产物, .md 已取消) | render-case.py |
分类库导出_*.json 词表为什么不放 spec/:
spec/tools/taxonomy-lookup.py 的 funnel API (--list-l2 / --subtree / --match), 一次 query 几百 tokens, 比整树 Read 省 50-100xAgent 阶段二 2B 完全通过 tool 查, 不要 Read 词表 JSON 本身.
Agent(或 Task)— 召唤子助手做什么:第二阶段,主流程用它召唤两个轻量子助手并行做归类。好处是把主流程的"重上下文"(一堆配图 + 长篇说明)和"琐碎高频的查词"隔开,还能并发提速。
子助手的工作说明放在 spec/agents/*.md,运行器启动时自动加载;召唤时 subagent_type 直接填注册名(phase-2a-normalizer / phase-2b-matcher),只点明做哪个 case 即可,不用重述方法。别用 subagent_type="Explore"——那是通用助手,会绕过子助手的工作说明。
具体怎么切任务、收结果,见 phase2-normalize.md(第二阶段编排)。