Explorar el Código

dim_attributes 去中文(how/what/why) + Why content 改结构化 {name,desc}

- TYPE2ATTR/schema const: how工序/what构成/why原理 → how/what/why
- Why payload content: 阐述字符串 → 对象 {name=title, desc=阐述}(与 What 结构化对齐)
- lint 加 why content {name,desc} 校验;rebuild 重生成 payloads.json(确定性,不调 LLM)
- 24 颗 0 ERROR

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SamLee hace 3 semanas
padre
commit
fd6b407e93

+ 4 - 4
scripts/decompose.py

@@ -57,7 +57,7 @@ SOURCES = [
     {"cid": "6a33655e000000000f0055af", "platform": "xiaohongshu", "from": "live"},  # 无知识 Voodoo(最后)
 ]
 SRC2CN = {"substance": "实质", "form": "形式", "feeling": "感受", "effect": "作用", "intent": "意图"}
-TYPE2ATTR = {"how": "how工序", "what": "what构成", "why": "why原理"}
+TYPE2ATTR = {"how": "how", "what": "what", "why": "why"}
 CSTAGE = {"定向", "构思", "结构", "成文", "打磨"}  # 创作阶段受控 5 值
 KINDS = {"子集", "多维关系", "序列"}               # what.kind 受控 3 值
 KIND_FIX = {"多维度关系": "多维关系", "多维": "多维关系", "集合": "子集", "序列型": "序列"}  # LLM 偶发变体归一
@@ -360,7 +360,7 @@ def apply_scopes(knowledges: list[dict], scopes: list, linker: ScopeLinker) -> N
 
 # ---------- ⑤ 组装 ----------
 def build_content(k: dict):
-    """How/Why → 拍平字符串;What → 结构化实体对象 {name,kind,维度拆分规则,body[]}。"""
+    """How → 拍平字符串;What → 结构化实体对象 {name,kind,维度拆分规则,body[]};Why → 结构化对象 {name,desc}。"""
     t = k.get("type")
     if t == "how":
         lines = [f"目标:{k.get('purpose','')}"]
@@ -373,7 +373,7 @@ def build_content(k: dict):
                 "维度拆分规则": k.get("维度拆分规则") if k.get("kind") == "子集" else None,
                 "body": [{"item_name": it.get("item_name", ""), "item_desc": it.get("item_desc", ""),
                           "作用域": it.get("作用域") or []} for it in (k.get("body") or [])]}
-    return k.get("阐述", "")
+    return {"name": k.get("title") or "", "desc": k.get("阐述") or ""}
 
 
 def _sections(blocks) -> list[str]:
@@ -427,7 +427,7 @@ def build_payload(post, k: dict, how_titles: dict | None = None) -> dict:
     return {"source": {"id": post.id, "source_type": "post", "title": post.title or "",
                        "author": post.author_name or "", "source_metadata": {"platform": post.platform, "url": post.url}},
             "title": k.get("title"), "content": build_content(k),
-            "dim_creations": ["创作"], "dim_attributes": [TYPE2ATTR.get(t, "how工序")],
+            "dim_creations": ["创作"], "dim_attributes": [TYPE2ATTR.get(t, "how")],
             "scopes": scopes, "custom_ext": ext}
 
 

+ 4 - 4
scripts/rebuild_payloads.py

@@ -13,7 +13,7 @@ from pathlib import Path
 ROOT = Path(__file__).resolve().parent.parent
 FW = ROOT / "web/frameworks.json"
 PL = ROOT / "web/payloads.json"
-TYPE2ATTR = {"how": "how工序", "what": "what构成", "why": "why原理"}
+TYPE2ATTR = {"how": "how", "what": "what", "why": "why"}
 KINDS = {"子集", "多维关系", "序列"}
 KIND_FIX = {"多维度关系": "多维关系", "多维": "多维关系", "集合": "子集", "序列型": "序列"}  # LLM 偶发变体归一
 
@@ -37,7 +37,7 @@ def _sections(blocks) -> list:
 
 
 def content(k: dict):
-    """How/Why → 拍平字符串;What → 结构化实体对象 {name,kind,维度拆分规则,body[]}。"""
+    """How → 拍平字符串;What → 结构化实体对象 {name,kind,维度拆分规则,body[]};Why → 结构化对象 {name,desc}。"""
     t = k["type"]
     if t == "how":
         L = [f"目标:{k.get('purpose','')}"]
@@ -50,7 +50,7 @@ def content(k: dict):
                 "维度拆分规则": k.get("维度拆分规则") if k.get("kind") == "子集" else None,
                 "body": [{"item_name": it.get("item_name", ""), "item_desc": it.get("item_desc", ""),
                           "作用域": it.get("作用域") or []} for it in (k.get("body") or [])]}
-    return k.get("阐述", "")
+    return {"name": k.get("title") or "", "desc": k.get("阐述") or ""}
 
 
 def main() -> None:
@@ -106,7 +106,7 @@ def main() -> None:
                 "source": {"id": p.get("source_id") or f"xhs_{p['post_id']}", "source_type": "post", "title": p.get("title", ""),
                            "author": "", "source_metadata": {"platform": p.get("platform"), "url": p.get("url")}},
                 "title": k.get("title"), "content": content(k), "dim_creations": ["创作"],
-                "dim_attributes": [TYPE2ATTR.get(t, "how工序")], "scopes": scopes, "custom_ext": ext})
+                "dim_attributes": [TYPE2ATTR.get(t, "how")], "scopes": scopes, "custom_ext": ext})
     FW.write_text(json.dumps(d, ensure_ascii=False, indent=1), encoding="utf-8")
     PL.write_text(json.dumps(payloads, ensure_ascii=False, indent=2), encoding="utf-8")
     print(f"rebuilt {len(payloads)} payloads; 降级组件→orphan: {demoted}")

+ 68 - 53
web/payloads.json

@@ -4,7 +4,7 @@
       "id": "xhs_699308fa0000000016009697",
       "source_type": "post",
       "title": "真正能爆的选题,往往是你写完后感觉羞耻的",
-      "author": "方圆的增长飞轮",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/699308fa0000000016009697"
@@ -16,7 +16,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "how工序"
+      "how"
     ],
     "scopes": [
       {
@@ -106,19 +106,22 @@
       "id": "xhs_699308fa0000000016009697",
       "source_type": "post",
       "title": "真正能爆的选题,往往是你写完后感觉羞耻的",
-      "author": "方圆的增长飞轮",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/699308fa0000000016009697"
       }
     },
     "title": "爆款选题的“羞耻感”防伪定律",
-    "content": "真正能爆的选题往往由于其不仅通过了大脑审核,更通过了情绪审核。羞耻感是好选题的防伪标签,它本质上触碰到了社交礼仪包裹下、平时大家不敢说出口的真实内容。在内容过剩时代,观众需要的不是正确答案,而是有人帮他们说出“正确答案在特殊场景下不好使”的真相。没有情绪触发就没有转发,作者在发布前感到的安全感(无风险选题)通常等于观众的无感。冒犯感是对“正确共识”的挑战,这种撕裂感能产生更强的穿透力和爆发力。",
+    "content": {
+      "name": "爆款选题的“羞耻感”防伪定律",
+      "desc": "真正能爆的选题往往由于其不仅通过了大脑审核,更通过了情绪审核。羞耻感是好选题的防伪标签,它本质上触碰到了社交礼仪包裹下、平时大家不敢说出口的真实内容。在内容过剩时代,观众需要的不是正确答案,而是有人帮他们说出“正确答案在特殊场景下不好使”的真相。没有情绪触发就没有转发,作者在发布前感到的安全感(无风险选题)通常等于观众的无感。冒犯感是对“正确共识”的挑战,这种撕裂感能产生更强的穿透力和爆发力。"
+    },
     "dim_creations": [
       "创作"
     ],
     "dim_attributes": [
-      "why原理"
+      "why"
     ],
     "scopes": [
       {
@@ -168,7 +171,7 @@
       "id": "xhs_699308fa0000000016009697",
       "source_type": "post",
       "title": "真正能爆的选题,往往是你写完后感觉羞耻的",
-      "author": "方圆的增长飞轮",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/699308fa0000000016009697"
@@ -196,7 +199,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -243,7 +246,7 @@
       "id": "xhs_698481e1000000000a02a7c1",
       "source_type": "post",
       "title": "7种编剧常用的叙事结构,写剧不用愁!",
-      "author": "Irvin是个编剧(接稿版)",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/698481e1000000000a02a7c1"
@@ -296,7 +299,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -370,7 +373,7 @@
       "id": "xhs_67e2e39b0000000003028ff0",
       "source_type": "post",
       "title": "剧本创作:理解前提、人物、冲突",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e2e39b0000000003028ff0"
@@ -393,7 +396,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -435,7 +438,7 @@
       "id": "xhs_67e2e39b0000000003028ff0",
       "source_type": "post",
       "title": "剧本创作:理解前提、人物、冲突",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e2e39b0000000003028ff0"
@@ -468,7 +471,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -514,7 +517,7 @@
       "id": "xhs_67e2e39b0000000003028ff0",
       "source_type": "post",
       "title": "剧本创作:理解前提、人物、冲突",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e2e39b0000000003028ff0"
@@ -552,7 +555,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -598,19 +601,22 @@
       "id": "xhs_67e2e39b0000000003028ff0",
       "source_type": "post",
       "title": "剧本创作:理解前提、人物、冲突",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e2e39b0000000003028ff0"
       }
     },
     "title": "冲突升级的原理与动力",
-    "content": "冲突是行动的源泉,其本质由生活环境和社会状况构成。有效的冲突源于‘对立统一’:必须让具备强烈意志力(名誉、金钱、复仇等需求)的主使人物与同样强大且无情的对立人物相遇。冲突的推进模式是‘攻击—反击’,只有势均力敌的对手通过不断的决策(互为因果)产生反应,才能驱动冲突不断升级并自然走向高潮。",
+    "content": {
+      "name": "冲突升级的原理与动力",
+      "desc": "冲突是行动的源泉,其本质由生活环境和社会状况构成。有效的冲突源于‘对立统一’:必须让具备强烈意志力(名誉、金钱、复仇等需求)的主使人物与同样强大且无情的对立人物相遇。冲突的推进模式是‘攻击—反击’,只有势均力敌的对手通过不断的决策(互为因果)产生反应,才能驱动冲突不断升级并自然走向高潮。"
+    },
     "dim_creations": [
       "创作"
     ],
     "dim_attributes": [
-      "why原理"
+      "why"
     ],
     "scopes": [
       {
@@ -651,7 +657,7 @@
       "id": "xhs_67e2e39b0000000003028ff0",
       "source_type": "post",
       "title": "剧本创作:理解前提、人物、冲突",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e2e39b0000000003028ff0"
@@ -663,7 +669,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "how工序"
+      "how"
     ],
     "scopes": [
       {
@@ -756,7 +762,7 @@
       "id": "xhs_680659e8000000001a007a11",
       "source_type": "post",
       "title": "故事设计原理拆解学习",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/680659e8000000001a007a11"
@@ -768,7 +774,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "how工序"
+      "how"
     ],
     "scopes": [
       {
@@ -893,7 +899,7 @@
       "id": "xhs_680659e8000000001a007a11",
       "source_type": "post",
       "title": "故事设计原理拆解学习",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/680659e8000000001a007a11"
@@ -936,7 +942,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -986,7 +992,7 @@
       "id": "xhs_680659e8000000001a007a11",
       "source_type": "post",
       "title": "故事设计原理拆解学习",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/680659e8000000001a007a11"
@@ -1019,7 +1025,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1066,7 +1072,7 @@
       "id": "xhs_680659e8000000001a007a11",
       "source_type": "post",
       "title": "故事设计原理拆解学习",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/680659e8000000001a007a11"
@@ -1104,7 +1110,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1146,19 +1152,22 @@
       "id": "xhs_680659e8000000001a007a11",
       "source_type": "post",
       "title": "故事设计原理拆解学习",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/680659e8000000001a007a11"
       }
     },
     "title": "真正选择的“两难”原理",
-    "content": "真正的选择必须是两难之择,即在不可调和的两善中取其一,或在两恶中取其轻。这种危机时刻是故事中最高压、最紧张的时刻,不仅能制造强烈的冲突,还能揭示人物的深层性格。",
+    "content": {
+      "name": "真正选择的“两难”原理",
+      "desc": "真正的选择必须是两难之择,即在不可调和的两善中取其一,或在两恶中取其轻。这种危机时刻是故事中最高压、最紧张的时刻,不仅能制造强烈的冲突,还能揭示人物的深层性格。"
+    },
     "dim_creations": [
       "创作"
     ],
     "dim_attributes": [
-      "why原理"
+      "why"
     ],
     "scopes": [
       {
@@ -1195,19 +1204,22 @@
       "id": "xhs_680659e8000000001a007a11",
       "source_type": "post",
       "title": "故事设计原理拆解学习",
-      "author": "拾意",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/680659e8000000001a007a11"
       }
     },
     "title": "情感回报递减定理",
-    "content": "如果情感连续重复出现,其效果会随着时间减少。因此在创作中需要通过价值的正面与负面动态交替,来引导核心情感(快感与痛感)的转变,从而确保持续吸引观众。",
+    "content": {
+      "name": "情感回报递减定理",
+      "desc": "如果情感连续重复出现,其效果会随着时间减少。因此在创作中需要通过价值的正面与负面动态交替,来引导核心情感(快感与痛感)的转变,从而确保持续吸引观众。"
+    },
     "dim_creations": [
       "创作"
     ],
     "dim_attributes": [
-      "why原理"
+      "why"
     ],
     "scopes": [
       {
@@ -1248,7 +1260,7 @@
       "id": "xhs_67e4bdf50000000006028a59",
       "source_type": "post",
       "title": "只要学会这几样,写短视频脚本真的不难❗️",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e4bdf50000000006028a59"
@@ -1260,7 +1272,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "how工序"
+      "how"
     ],
     "scopes": [
       {
@@ -1351,7 +1363,7 @@
       "id": "xhs_67e4bdf50000000006028a59",
       "source_type": "post",
       "title": "只要学会这几样,写短视频脚本真的不难❗️",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e4bdf50000000006028a59"
@@ -1394,7 +1406,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1437,7 +1449,7 @@
       "id": "xhs_67e4bdf50000000006028a59",
       "source_type": "post",
       "title": "只要学会这几样,写短视频脚本真的不难❗️",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e4bdf50000000006028a59"
@@ -1485,7 +1497,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1527,7 +1539,7 @@
       "id": "xhs_67e4bdf50000000006028a59",
       "source_type": "post",
       "title": "只要学会这几样,写短视频脚本真的不难❗️",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e4bdf50000000006028a59"
@@ -1560,7 +1572,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1602,7 +1614,7 @@
       "id": "xhs_67e4bdf50000000006028a59",
       "source_type": "post",
       "title": "只要学会这几样,写短视频脚本真的不难❗️",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e4bdf50000000006028a59"
@@ -1630,7 +1642,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1676,19 +1688,22 @@
       "id": "xhs_67e4bdf50000000006028a59",
       "source_type": "post",
       "title": "只要学会这几样,写短视频脚本真的不难❗️",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/67e4bdf50000000006028a59"
       }
     },
     "title": "视频节奏的时长分配原理",
-    "content": "长视频需要通过周期性的刺激来维持用户注意力,通常每15秒需设置一个重点内容;而短视频留给创作者的时间极短,必须在3-5秒内迅速呈现出核心主题,否则用户极易流失。",
+    "content": {
+      "name": "视频节奏的时长分配原理",
+      "desc": "长视频需要通过周期性的刺激来维持用户注意力,通常每15秒需设置一个重点内容;而短视频留给创作者的时间极短,必须在3-5秒内迅速呈现出核心主题,否则用户极易流失。"
+    },
     "dim_creations": [
       "创作"
     ],
     "dim_attributes": [
-      "why原理"
+      "why"
     ],
     "scopes": [
       {
@@ -1725,7 +1740,7 @@
       "id": "xhs_6901e15a0000000003019fa3",
       "source_type": "post",
       "title": "爆款标题公式直接抄❗️笔记想不火都难",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/6901e15a0000000003019fa3"
@@ -1758,7 +1773,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1804,7 +1819,7 @@
       "id": "xhs_6901e15a0000000003019fa3",
       "source_type": "post",
       "title": "爆款标题公式直接抄❗️笔记想不火都难",
-      "author": "海狸教自媒体运营",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/6901e15a0000000003019fa3"
@@ -1867,7 +1882,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {
@@ -1925,7 +1940,7 @@
       "id": "xhs_69ff58670000000023016fa2",
       "source_type": "post",
       "title": "海外营销灵感|五月爆款Reels创意合集",
-      "author": "NotJustAgency",
+      "author": "",
       "source_metadata": {
         "platform": "xiaohongshu",
         "url": "https://www.xiaohongshu.com/explore/69ff58670000000023016fa2"
@@ -1958,7 +1973,7 @@
       "创作"
     ],
     "dim_attributes": [
-      "what构成"
+      "what"
     ],
     "scopes": [
       {

+ 1 - 1
创作知识提取-skill/format/ingest-payload-how.schema.json

@@ -42,7 +42,7 @@
     },
     "dim_attributes": {
       "type": "array",
-      "items": { "const": "how工序" },
+      "items": { "const": "how" },
       "minItems": 1,
       "maxItems": 1
     },

+ 1 - 1
创作知识提取-skill/format/ingest-payload-what.schema.json

@@ -78,7 +78,7 @@
     },
     "dim_attributes": {
       "type": "array",
-      "items": { "const": "what构成" },
+      "items": { "const": "what" },
       "minItems": 1,
       "maxItems": 1
     },

+ 9 - 4
创作知识提取-skill/format/ingest-payload-why.schema.json

@@ -2,7 +2,7 @@
   "$schema": "http://json-schema.org/draft-07/schema#",
   "$id": "ingest-payload-why.schema.json",
   "title": "创作知识 Ingest Payload · Why(原理)",
-  "$comment": "Why 颗 = 解释某做法/判断背后的道理。content 为一段文字:阐述(这条原理是什么+为什么成立,忠实整合原帖;不含'怎么用')。一颗知识 = 一个 payload;同帖多颗共享 source.id。",
+  "$comment": "Why 颗 = 解释某做法/判断背后的道理。content 为结构化对象 {name,desc}:name=原理名,desc=阐述(是什么+为什么,忠实整合原帖;不含'怎么用')。一颗知识 = 一个 payload;同帖多颗共享 source.id。",
   "type": "object",
   "required": ["source", "title", "content", "dim_creations", "dim_attributes", "scopes"],
   "additionalProperties": false,
@@ -29,9 +29,14 @@
     },
     "title": { "type": "string", "minLength": 1, "$comment": "原理名,如 爆款选题的情绪触发原理" },
     "content": {
-      "type": "string",
-      "minLength": 1,
-      "$comment": "一段文字:阐述(是什么+为什么,忠实整合原帖,不含'怎么用')"
+      "type": "object",
+      "required": ["name", "desc"],
+      "additionalProperties": false,
+      "properties": {
+        "name": { "type": "string", "$comment": "原理名,通常同 title" },
+        "desc": { "type": "string", "minLength": 1, "$comment": "阐述(是什么+为什么,忠实整合原帖,不含'怎么用')" }
+      },
+      "$comment": "结构化对象 {name,desc}:name=原理名,desc=阐述(是什么+为什么,忠实整合)"
     },
     "dim_creations": {
       "type": "array",

+ 9 - 0
创作知识提取-skill/tools/lint-payload.py

@@ -101,6 +101,15 @@ def lint_one(p: dict, idx: int) -> tuple[list[str], list[str]]:
                     warn.append(f"{tag} 子集型建议填 维度拆分规则")
             if "概要" not in keys_present:
                 warn.append(f"{tag} what 颗建议 custom_ext 带『概要』")
+        if kind == "why":  # Why 的 content 是结构化对象 {name,desc}
+            c = p.get("content")
+            if not isinstance(c, dict):
+                err.append(f"{tag} why 的 content 须为结构化对象 {{name,desc}},实为 {type(c).__name__}")
+            else:
+                if not c.get("name"):
+                    err.append(f"{tag} why.content 缺 name")
+                if not c.get("desc"):
+                    err.append(f"{tag} why.content 缺 desc")
     if ext and "业务阶段" not in keys_present:
         warn.append(f"{tag} custom_ext 建议至少有一个『业务阶段』")