Browse Source

假how根治(三层)+ 重跑:离散构成→what/why组件,how 收成实指链

- 层1 phase1-frame 闸①:后步 input 必须实指前步产出物原话(禁"←s1产出")+ 反驳自检 + 离散构成例(前提/人物/冲突→拆 what/why);§B input 字段+模板同步
- 层2 decompose `_chain_signals`:确定性检出并列输入/产出近义,喂层3
- 层3 `how_gate`(admit/refute/tiebreak 对抗投票,边界倾向假how)+ `reshape_nonhow`(假how→只拆 what/why 主颗);`fix_fake_hows` 在 ②后、guard 前调用
- prompts/gate_how_{admit,refute,tiebreak}.txt
- 重跑数据:剧本帖原"5步假how"→ how(前提→人物→冲突→大纲实指链)+3 what组件+1 why组件;
  其余 how 均为实指链;意图豁免随此轮落地;19 颗 0 ERROR/0 WARN

subagent 12 项验证全 PASS(refute 归一、主循环顺序、reshape id 唯一+兜底、无崩溃)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SamLee 3 weeks ago
parent
commit
8d144c203a

+ 7 - 0
prompts/gate_how_admit.txt

@@ -0,0 +1,7 @@
+你在判断:下面这颗「how 工序」是不是【真流水线】——后一步必须消费前一步的**具体产出**,缺了前步、后步就做不了,打乱顺序就跑不通。
+
+用户消息是这颗 how 的 purpose + 各步(input/方法/产出),可能附带「代码信号」。
+逐对相邻步骤检查:**后步是否真用到前步产出的那个具体物**(不是"话题相关",是"没有前步那个产出就无法进行")。
+只要存在"步骤各自独立、可换序、或只是并列地讲'X 是什么/分几类'",就不是真流水线。
+
+输出 JSON:{"复述":"<这颗在教什么,一句话>","逐步依赖":"<s2 用了 s1 的什么…逐对说,说不出就写'无'>","is_real_how":true/false,"理由":"..."}

+ 10 - 0
prompts/gate_how_refute.txt

@@ -0,0 +1,10 @@
+你在【挑刺】:下面这颗「how 工序」是不是【假 how】——其实是几块离散构成/原理,被硬串成了步骤。
+
+属于以下任一 → is_fake=true:
+- 步骤的产出彼此近义/重复(都产出"同一类东西");
+- 打乱步骤顺序,成品仍成立(无强制先后);
+- 某步的"输入"其实是工序总输入、而非前一步的产出(步骤各自起头、互不喂给);
+- 这些"步骤"各自是"X 是什么 / 分几类"(如 前提 / 人物 / 冲突 这种离散构成),互为定义但**无"产出→输入"传递**。
+
+用户消息含该 how 的 purpose + 各步,可能附「代码信号」;**尽量找出它是假 how 的理由**。
+输出 JSON:{"复述":"...","假链证据":"...","is_fake":true/false,"若假how建议拆成":"<几颗 what/why,如:前提构成(what)/人物维度(what)/冲突类型(what)/势均力敌原理(why)>"}

+ 8 - 0
prompts/gate_how_tiebreak.txt

@@ -0,0 +1,8 @@
+两个判断者对"这颗 how 是不是真流水线"产生分歧,你来裁决。用户消息是该 how 的 purpose + 各步(可能附「代码信号」)。
+
+标准:
+- 真流水线 = 后步消费前步的**具体产出**、打乱顺序就跑不通(如 腌制→下锅→收汁)。
+- 假 how = 离散构成/原理被硬串成步骤(如"前提/人物/冲突"各自是"是什么"、互不传递)。
+
+**重要:拿不准、或像"几块各自是什么"硬串的 → 判 is_real_how=false(边界倾向"假how")。**
+输出 JSON:{"复述":"...","is_real_how":true/false,"理由":"..."}

+ 81 - 1
scripts/decompose.py

@@ -32,6 +32,9 @@ GATE_ADMIT = load_prompt("gate_admit")        # ①.5 创作判定闸:判"是
 GATE_REFUTE = load_prompt("gate_refute")      # ①.5:挑刺"是制作/越界"
 GATE_TIEBREAK = load_prompt("gate_tiebreak")  # ①.5:分歧裁决(边界倾向排除)
 NORMALIZE = load_prompt("normalize_scope")    # ③前:作用域值名词化(③LLM)
+GATE_HOW_ADMIT = load_prompt("gate_how_admit")        # ②.5 有序性闸:判"真流水线"
+GATE_HOW_REFUTE = load_prompt("gate_how_refute")      # ②.5:挑"假how(离散构成硬串)"
+GATE_HOW_TIEBREAK = load_prompt("gate_how_tiebreak")  # ②.5:分歧裁决(边界倾向假how)
 
 # ① 窄表确定性兜底:只放无歧义裸动作动词(绝不放 营造/引导/表达 等名词语素)
 _STRIP_VERBS = ("寻找", "定位", "推导", "核验", "提取", "挖掘", "捕捉",
@@ -142,6 +145,83 @@ def creation_gate(read: str) -> tuple[bool, str]:
     return v_tie, f"admit={v_admit}/refute={v_refute} 分歧→裁决={v_tie}"
 
 
+# ---------- ②.5 假how根治:有序性审查(层2信号+层3对抗投票)+ 假how重拆为 what/why ----------
+def _chain_signals(steps: list[dict]) -> list[str]:
+    """层2 确定性信号:并列输入(input 不指向前步产出)/ 产出近义。喂给层3当证据。"""
+    sigs, outs = [], [(s.get("output") or "") for s in steps]
+    indep = 0
+    for i, s in enumerate(steps):
+        if i == 0:
+            continue
+        inp = s.get("input") or ""
+        if not (("←" in inp) or any(o and o[:4] in inp for o in outs[:i])):
+            indep += 1
+    if indep >= 2:
+        sigs.append(f"{indep} 个后步的 input 未指向前步产出(各自起头)")
+    for i in range(len(outs)):
+        for j in range(i + 1, len(outs)):
+            a, b = outs[i], outs[j]
+            if a and b and (a in b or b in a):
+                sigs.append(f"步骤{i+1}与{j+1}产出近义({a} / {b})")
+                break
+    return sigs
+
+
+def how_gate(k: dict) -> tuple[bool, str]:
+    """层3a 有序性闸(对抗投票:admit 判真链 / refute 挑假链 / 分歧裁决,边界倾向假how)。"""
+    payload = json.dumps({
+        "purpose": k.get("purpose"),
+        "steps": [{"input": s.get("input"), "方法": (s.get("directive") or "")[:300], "产出": s.get("output")}
+                  for s in k.get("steps", [])],
+        "代码信号": _chain_signals(k.get("steps", [])),
+    }, ensure_ascii=False)
+    v_admit = _vote(GATE_HOW_ADMIT, payload, "is_real_how", on_fail=True)
+    v_refute = not _vote(GATE_HOW_REFUTE, payload, "is_fake", on_fail=False)  # 不假 → 真
+    if v_admit == v_refute:
+        return v_admit, f"admit={v_admit}/refute={v_refute} 一致"
+    v_tie = _vote(GATE_HOW_TIEBREAK, payload, "is_real_how", on_fail=False)
+    return v_tie, f"admit={v_admit}/refute={v_refute} 分歧→裁决={v_tie}"
+
+
+def reshape_nonhow(k: dict) -> list[dict]:
+    """层3b 假how重拆:只拆成 What/Why 主颗(不要 how/组件)。失败则保留原颗,不丢内容。"""
+    body = f"目标:{k.get('purpose','')}\n" + "\n".join(
+        f"- 输入:{s.get('input','')}|方法:{s.get('directive','')}|产出:{s.get('output','')}"
+        for s in k.get("steps", []))
+    user = ("【下面这块原被误判为 how 工序,实为「离散构成 / 原理」,请只拆成 What/Why 主颗——"
+            "每个'是什么/分几类'的构成块拆一颗 What,背后的原理/标准拆一颗 Why;"
+            "不要 how、不要组件颗,parent 一律 null。作用域字段留空 []。】\n\n"
+            f"原标题:{k.get('title','')}\n{body}\n\n"
+            "只输出 JSON:{\"knowledges\":[ ... 仅 what/why,见模板 ... ]}")
+    try:
+        out = chat_json(PHASE1, user, timeout=120).get("knowledges") or []
+    except Exception:
+        out = []
+    res = []
+    for i, nk in enumerate(out, 1):
+        if nk.get("type") == "how":   # 保险:拒绝又冒出来的 how
+            continue
+        nk["id"] = f"{k.get('id','k')}r{i}"
+        nk["role"], nk["parent"] = "主", None
+        res.append(nk)
+    return res or [k]   # 兜底:没拆出来就保留原颗
+
+
+def fix_fake_hows(knowledges: list[dict]) -> list[dict]:
+    """逐颗 how 审查;假how → 重拆为 what/why(替换原颗)。"""
+    out = []
+    for k in knowledges:
+        if k.get("type") == "how" and len(k.get("steps", [])) >= 2:
+            real, why = how_gate(k)
+            if not real:
+                new = reshape_nonhow(k)
+                print(f"  ②.5 假how「{k.get('title')}」({why})→ 重拆 {len(new)} 颗")
+                out.extend(new)
+                continue
+        out.append(k)
+    return out
+
+
 # ---------- ③ 作用域候选 + 定位 ----------
 def _slim(knowledges: list[dict]) -> list[dict]:
     slim = []
@@ -328,7 +408,7 @@ def main() -> None:
             posts_out.append({**meta, "no_knowledge": True, "knowledges": []})
             continue
         print(f"  ① 读懂 {len(read)} 字({media['type']})· ①.5 闸:创作({gate_why})")
-        knowledges = shape(post, read)
+        knowledges = fix_fake_hows(shape(post, read))   # ② 拆颗 → ②.5 假how根治(假how重拆为 what/why)
         how_ids = {k.get("id") for k in knowledges if k.get("type") == "how"}
         how_titles = {k.get("id"): k.get("title") for k in knowledges if k.get("type") == "how"}
         for k in knowledges:

File diff suppressed because it is too large
+ 363 - 305
web/frameworks.json


File diff suppressed because it is too large
+ 275 - 193
web/payloads.json


+ 9 - 7
创作知识提取-skill/extraction/phase1-frame.md

@@ -34,11 +34,13 @@
 
 把一组动作封成 how 之前,必须同时过这两闸;否则它不是 how。
 
-**闸① 有序性(步骤之间真有数据依赖吗?)**
-> 后一步是否**消费前一步的 output**、换了顺序就跑不通?
-> - 是 → 真有序,可成 how。
-> - **否(各步并列、可换序、互不依赖,甚至只做其中一个也成立)→ 这是一组「并列招式/途径」,不是工序**。改成一颗 **What(方法清单)**,别套 step1→step2 的假顺序(有序语义会骗下游 AI 以为必须按序、后步吃前步)。
-> 识别信号:相邻 step 的 output **近义或重复**(都产出"同一种东西")= 八成是并列,不是链条。
+**闸① 有序性(步骤之间真有「产出→输入」传递吗?)**
+> 后一步是否**消费前一步的具体产出**、换了顺序就跑不通?
+> - 是 → 真有序,可成 how。**且每个后步的 `input` 必须实指它消费的前步产出物原话**(写"← s1 的〈赛道圣经句清单〉",**禁止空泛的"←s1产出"**)——指不出具体消费物 = 不依赖。
+> - **否 → 不是工序**:一组并列招式/途径 → 一颗 **What 清单**;几块"各自是什么"的离散构成 → **各拆一颗 What**(原理拆 Why)。
+> 识别信号:①相邻 step 的 output 近义/重复;②打乱顺序成品仍成立;③多个 step 的 input 其实都是工序总输入、彼此不喂给;④这些"步骤"各自是"X 是什么/分几类"。
+> **反驳自检(封 how 前必做)**:逐对说出"s2 用了 s1 产出的什么具体物"——说不出,就拆成 What,别硬编链。
+> ⚠️ 离散构成例(**应拆 What/Why,不是 how**):「故事 = 前提 + 人物 + 冲突」——前提/人物/冲突各自是"是什么/分几类"、互为定义但**无产出→输入传递**(拟定前提并不消费"切入点")→ 拆成「前提构成」「人物维度」「冲突类型」几颗 What(+「冲突靠势均力敌升级」这类原理拆 Why),别硬串成 step1→2→3。
 
 **闸② 走到交付物(最后一步的 output = purpose 承诺的成品吗?)**
 > purpose 用什么名词收尾("一篇成稿"/"一个选题"/"一条脚本"),**最后一步的 output 就必须是那个东西**。
@@ -64,7 +66,7 @@
 
 ### How(工序)— role 主(必须先过 §A2 两道闸)
 `purpose`(把某输入一路做成成品;**它的收尾名词 = 最后一步 output**,见闸②)+ 有序 `steps`(**后步消费前步 output**,见闸①),每步是一次**变换 输入→方法→产出**:
-- `input` 输入(这步**吃什么**:来自 `工序输入` 或上一步的产出,如 `← s1产出`;**首步**写工序总输入
+- `input` 输入(这步**吃什么**:首步=工序总输入;后步**必须实指前步产出物原话**,如 `← s1 的〈赛道圣经句清单〉`,**禁空泛"←s1产出"**——指不出就说明不依赖前步,见 §A2 闸①
 - `directive` 方法(怎么做,含判断标准;**原帖示例必须原文保留** `例:『…』`;不编原文没有的例子)
 - `output` 产出(这步**吐什么**;会成为下一步的 `input`)
 - `出处`(图N / 视频时间)
@@ -149,7 +151,7 @@
       "id": "k1", "type": "how", "role": "主", "parent": null,
       "title": "<框架名,从本帖抽>", "purpose": "<一句话目标>", "业务阶段": ["<灵感/选题/脚本,可多选>"],
       "steps": [
-        {"id":"s1","input":"<这步吃什么:工序总输入 / ← s?产出>","directive":"<方法,含判断标准,原帖示例用 例:『…』 原文保留>","output":"<这步吐什么,会成下一步 input>",
+        {"id":"s1","input":"<这步吃什么:首步=工序总输入;后步实指前步产出物原话,如 ← s1 的〈赛道圣经句清单〉>","directive":"<方法,含判断标准,原帖示例用 例:『…』 原文保留>","output":"<这步吐什么,会成下一步 input>",
          "出处":["<图N/视频时间>"],"创作阶段":"<定向/构思/结构/成文/打磨>","动作":"<这步的具体手法,从内容抽>","作用域":[]}
       ],
       "dropped": ["<剔除项 — 理由>"]

Some files were not shown because too many files changed in this diff