{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://procedure-dsl/spec/format/case-data.schema.json", "title": "Procedure DSL · case_data", "description": "Canonical structure consumed by spec/tools/renderer.build_html(case_data) -> str. 一篇 case 可含 1 ~ N 个独立工序 (procedures), 共享同一份 source 原帖. 单工序 case 也用 procedures 数组长度 1 的形式 — schema 不区分.", "type": "object", "required": [ "page_title", "source", "procedures" ], "additionalProperties": false, "properties": { "page_title": { "type": "string", "description": "HTML + <h1>. e.g. 'Case 5 · 产品宣传图 AI 工作流可视化'" }, "case_id": { "type": ["integer", "string", "null"], "description": "Optional case identifier shown in UI badge." }, "source": { "$ref": "#/$defs/Source", "description": "case-level 原帖信息, 跨所有 procedures 共享 (一篇文章对应一份 source)." }, "procedures": { "type": "array", "minItems": 1, "description": "一篇 case 包含的工序数组. 多工序场景 (e.g. case-5 '简单工作流 + 进阶工作流 + 附加案例'). 单工序 case 也用长度 1 数组. 每个 procedure 独立含 declarations / steps / type_registry / return_row.", "items": { "$ref": "#/$defs/Procedure" } } }, "$defs": { "Procedure": { "type": "object", "description": "一个独立工序: 工序头部 (name/purpose/...) + declare 块 + 步骤 + 返回行. 一个 procedure 内的 type_registry 是该工序的 case-specific 类型扩展.", "required": ["id", "name", "purpose", "category", "platform", "author", "declarations", "steps"], "additionalProperties": false, "properties": { "id": { "type": "string", "description": "procedure 局部 id (单 case 内唯一). e.g. 'p1' / 'p1-simple' / 'p2-advanced'." }, "name": { "type": "string", "description": "工序名称, e.g. '简单工作流: 一步生成'." }, "purpose": { "type": "string", "description": "One-sentence intent (该工序在做什么)." }, "category": { "type": "string", "description": "Top-level taxonomy, e.g. '产物创造'." }, "platform": { "type": "string", "description": "原帖来源 platform; 通常跟 case-level source.platform 一致." }, "author": { "type": "string", "description": "原作者; 通常跟 case-level source.author 一致." }, "declarations": { "$ref": "#/$defs/Declarations" }, "type_registry": { "type": "object", "description": "Per-procedure case-specific type entries; 渲染期跟 spec/taxonomy/type.json 的 stdlib 叶子合并 — case 项覆盖 stdlib 项. 跨工序共享的 case-specific type 可在多个 procedure 各自声明 (允许冗余).", "additionalProperties": { "$ref": "#/$defs/TypeRegistryEntry" } }, "steps": { "type": "array", "description": "工序的步骤数组, 按执行顺序排. block/step 在顶层; nested 子项 kind:nested + group 指向父 block id.", "items": { "$ref": "#/$defs/Step" } }, "return_row": { "$ref": "#/$defs/ReturnRow" } } }, "Declarations": { "type": "object", "description": "工序的声明: declared inputs / resources / return type. 渲染成 declare 折叠块.", "required": ["inputs", "resources", "returns"], "additionalProperties": false, "properties": { "inputs": { "type": "array", "items": { "$ref": "#/$defs/DeclareItem" }, "description": "Caller-provided inputs to the procedure." }, "resources": { "type": "array", "items": { "$ref": "#/$defs/DeclareItem" }, "description": "Long-lived resources (libraries, knowledge bases) read or written across runs." }, "returns": { "$ref": "#/$defs/DeclareReturn" } } }, "DeclareItem": { "type": "object", "required": ["type", "name"], "additionalProperties": false, "properties": { "type": { "type": "string", "description": "Type leaf (§A.3) or case-extended type." }, "name": { "type": "string" }, "default": { "type": "string", "description": "Optional default value/template." }, "desc": { "type": "string", "description": "Optional human description." } } }, "DeclareReturn": { "type": "object", "required": ["type"], "additionalProperties": false, "properties": { "type": { "type": "string" }, "note": { "type": "string", "description": "e.g. 'extends 视频成品 (序列关系)'." } } }, "Source": { "type": "object", "description": "case-level 原帖信息. 渲染成 foldable 折叠块 (default closed). 跨所有 procedures 共享.", "required": ["platform", "author", "date", "title", "excerpt"], "additionalProperties": false, "properties": { "platform": { "type": "string" }, "author": { "type": "string" }, "date": { "type": "string", "description": "Free-text date, e.g. '2026 上半年'." }, "url": { "type": ["string", "null"], "description": "原帖 URL; 没有干净 URL 时填 null 或省略 (不强制 uri 格式)." }, "title": { "type": "string" }, "excerpt": { "type": "string", "description": "1-2 sentence pipeline summary." }, "body_text": { "type": "string", "description": "Optional full body of the source article." }, "cover_image": { "type": "string", "description": "Optional cover image URL." } } }, "TypeRegistryEntry": { "type": "object", "description": "Case-specific 类型定义 (procedures[*].type_registry). 桥接到一个 stdlib 叶子 + 人类可读描述.", "required": ["extends", "desc"], "additionalProperties": false, "properties": { "extends": { "type": "string", "description": "桥接到的 stdlib 叶子名 (spec/taxonomy/type.json $leaves 之一)." }, "desc": { "type": "string", "description": "case-specific 类型的人类可读说明 (renderer drawer + type_suggestions 用)." } } }, "Step": { "type": "object", "description": "One row group in the 25-column procedure table. Renders to N <tr> where N = max(len(inputs), len(outputs), 1). The dictionary-tree fields (effect/via/action/feature/control) MUST hit canonical leaves per spec §A. NOTE: kind=block 是控制容器, 只带 control + intent + via='-' + feature='-' + io; effect/action/focus 由其下 kind=nested 执行步承担 (见下方 allOf 条件: 仅 step/nested/atom 要求 effect/action/focus).", "required": ["id", "kind", "via", "feature", "inputs", "outputs", "intent"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^(s\\d+(\\.\\d+)*|a\\d+)$", "description": "Step id. Plain step / block / nested use 's' prefix (block children dotted, e.g. 's3.1'); atoms use 'a' prefix (e.g. 'a1') scoped under their parent step." }, "kind": { "enum": ["step", "block", "nested", "atom"], "description": "step=plain; block=control-flow parent; nested=child of a block; atom=experimental dimensional projection (only used in case1)." }, "group": { "type": "string", "description": "When kind=nested, the parent block's id (e.g. 's3')." }, "parent_step": { "type": "string", "description": "When kind=atom, the host step's id." }, "name": { "type": "string", "description": "Only meaningful for kind=atom (displayed above the intent text)." }, "key_dim": { "type": "string", "description": "atom-only: the dimension this atom projects (e.g. '实质' / '形式')." }, "key_value": { "type": "string", "description": "atom-only: the specific path within the key_dim (e.g. '/表象/视觉/.../形象呈现')." }, "effect": { "enum": [ "预处理", "主体生成", "装配", "后期", "工艺规约", "预准备", "配套伴生", "检验", "交付" ], "description": "§A.1 L3 leaf. Required to hit a leaf — non-leaf = extraction error." }, "via": { "type": "string", "description": "Canonical L1 tool name (manus / nano_banana_pro / human / <llm-agent>) or generic placeholder for unspecified tools ('(AI 生图工具)'). Use '-' for control-flow blocks." }, "action": { "type": "string", "pattern": "^[^/]+(/[^/]+)*$", "description": "§A.2 path, e.g. '生成/元素生成', '提取/化学提取/反推'. Control-flow already routed to `control` field." }, "feature": { "type": "string", "enum": ["随机", "幂等", "人工", "本地", "写外部", "读外部", "-"], "description": "Execution attribute (internal). Block-level steps use '-'. NEVER referenced in intent column." }, "control": { "type": "string", "enum": ["并行", "遍历", "分支", "请求", "等待", "", "-"], "description": "Control-flow kind. Typically on kind=block; may appear on a regular step that itself is a control. Empty string or '-' = no control flow (kept for atom rows and plain steps that explicitly set the field)." }, "instruction": { "type": "array", "description": "Heterogeneous list of (kind, text) tuples. Order is preserved; any subset of kinds is allowed; control-flow blocks usually only carry memo entries.", "items": { "type": "array", "prefixItems": [ { "enum": ["directive", "config", "decorator", "memo"], "description": "directive=literal prompt text; config=tool runtime params; decorator=caller-side @decorator; memo=engineering wisdom not captured elsewhere." }, { "type": "string" } ], "items": false, "minItems": 2, "maxItems": 2 } }, "inputs": { "type": "array", "items": { "$ref": "#/$defs/IOItem" } }, "outputs": { "type": "array", "items": { "$ref": "#/$defs/IOItem" } }, "intent": { "type": "string", "description": "≤ ~20 chars natural-language sentence. Tokens `{kind:value}` with kind ∈ {effect, via, act, control, in-type, out-type, in-sub, out-sub, in-form, out-form}. NEVER reference {feature:X}, NEVER use variable-name tokens, NEVER use 'X: Y → Z' pseudo-code." }, "focus": { "type": "array", "items": { "type": "string" }, "description": "Column-cell keys to highlight on this row. Format: bare key for step-level cells ('via', 'action', 'effect', 'idx', 'intent'), or '<col>-<io_index>' for IO cells ('in-type-0', 'out-substance-1', etc.)." }, "inferred_marks": { "type": "object", "description": "Step-level field-by-field inference annotations (single cells, not whole rows). Maps column key → reason string. Used when only a specific field was filled by 工艺补全, not the whole row.", "additionalProperties": { "type": "string" } }, "atoms": { "type": "array", "description": "EXPERIMENTAL extension (case1-only). Dimensional projections of this step; each atom mirrors a Step shape with kind='atom' + parent_step + name + key_dim + key_value.", "items": { "$ref": "#/$defs/Step" } } }, "allOf": [ { "if": { "properties": { "kind": { "enum": ["step", "nested", "atom"] } } }, "then": { "required": ["effect", "action", "focus"] } }, { "if": { "properties": { "kind": { "const": "nested" } } }, "then": { "required": ["group"] } }, { "if": { "properties": { "kind": { "const": "atom" } } }, "then": { "required": ["parent_step", "name", "key_dim", "key_value"] } } ] }, "IOItem": { "type": "object", "description": "One row in inputs[] or outputs[]. Input and output items share the same shape (anchor points up for inputs, down for outputs).", "required": ["type", "name", "value", "anchor"], "additionalProperties": false, "properties": { "substance": { "type": ["string", "array", "null"], "items": { "type": "string" }, "description": "What the content IS (理念 vs 表象 layer). Path from `分类库导出_实质_*.json`. Can be a single path string, an array of path strings, or null for abstract containers / pure tool params." }, "form": { "type": ["string", "array", "null"], "items": { "type": "string" }, "description": "How the content is PRESENTED (呈现 vs 架构 layer). Path from `分类库导出_形式_*.json`. Can be a single path string, an array of path strings, or null when not applicable." }, "type": { "type": "string", "description": "§A.3 leaf or case-extended type name." }, "name": { "type": "string", "description": "Variable identifier within this step. Same concept across steps MUST use the same name (lint enforces this)." }, "value": { "type": "string", "description": "Content itself. Text data: full prose, no wrappers. Non-text data: '<整段描述>' (the whole description angle-bracketed). NEVER metadata ('[图 N 显示]', '原文: ...') or upstream refs ('← sN.x' — those go in anchor)." }, "anchor": { "type": "string", "description": "Inputs: upstream ref ('← 工序输入', '← sN.varname', '← 容器[i]'). Outputs: downstream destination ('→ sN', '→ 视频片段列表.追加', '→ 返回 X')." }, "inferred": { "type": "boolean", "description": "True when this whole IO item was filled by 工艺补全 (not in source material). Renderer dyes the entire row's 6 data-flow cells." }, "inferred_reason": { "type": "string", "description": "REQUIRED when inferred=true. Shown on hover." } }, "if": { "required": ["inferred"], "properties": { "inferred": { "const": true } } }, "then": { "required": ["inferred_reason"] } }, "ReturnRow": { "type": "object", "description": "Bottom row of the table announcing what the procedure returns.", "required": ["arrow", "text"], "additionalProperties": false, "properties": { "arrow": { "type": "string", "description": "Usually '↩'." }, "text": { "type": "string", "description": "May contain inline HTML fragments (chip / name / em spans) — emitted verbatim into a colspan=24 cell." } } } } }