Files
WorkBuddy df56c2c137 初始化提交:contentm_agent 工作区全量快照
内容分四块:
1、产品规划产出 —— MCN 短视频整合营销工作台的①段五份(1a 需求/1b 竞品/1c 画像/1d 策略/1e 场景)、②段两份(2a 功能/2b 布局)、③段界面(DESIGN.md 契约与令牌表 + mcn-workbench.html 原型 + 实测/会诊/审查三份 + 23 张闸门截图)。
2、开源竞品调研 —— 5 个内容工作台项目的取证原始件与 1b 系列分析文档。
3、参考资料 —— 竞品视频抽帧 1145 张 + 2 个源视频 + 功能点截图。
4、机制侧 —— 协作脚本与状态台账、工作区记忆日志、抽帧/OCR 脚本。

.gitignore 只排运行时日志、脚本备份副本与一次性探针输出,其余按原样入库。
2026-10-08 08:13:02 +08:00

94 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""骨架单一可信源闸门:`prd/2b-界面布局.md` §二 ↔ 原型里的 FROZEN 表。
为什么单拎出来:页面里的自检只能证明「渲染出来的板块 == FROZEN 表」,
证明不了「FROZEN 表 == ②段原文」。两张表各改一边就没人发现,所以这条闸门
直接把②段那份 Markdown 当权威读,逐页逐位比。
判据:板块**数量**必须相等,**顺序**必须相等,名字**互为前缀**(②段的名字带
「(可点入)」这类注解,不是给界面抄的标题,⛔ 不逐字比)。
用法:python _tools/check_skeleton.py
"""
import argparse
import os, re, sys
HERE = os.path.dirname(os.path.abspath(__file__))
UI = os.path.abspath(os.path.join(HERE, ".."))
GOAL = os.path.abspath(os.path.join(UI, ".."))
DOC = os.path.join(GOAL, "prd", "2b-界面布局.md")
PROTO = os.path.join(UI, "mcn-workbench.html")
Z2 = "\u3000\u3000" # 全角空格:注释切到右边界用
def from_doc(path=None):
s = open(path or DOC, encoding="utf-8").read()
if "## 二、八页骨架" not in s or "## 三、页面流转" not in s:
raise SystemExit("⛔ 读不到②段的 §二 八页骨架 —— 文件被改结构了?")
seg = s[s.index("## 二、八页骨架"):s.index("## 三、页面流转")]
out, cur = {}, None
for line in seg.split("\n"):
m = re.match(r"^### (P\d) ", line)
if m:
cur = m.group(1).lower()
out[cur] = []
continue
m2 = re.match(r"^\s*(\d+)\.\s*(.+)$", line)
if cur and m2:
out[cur].append(m2.group(2).split("——")[0].strip())
return out
def from_proto(path=None):
s = open(path or PROTO, encoding="utf-8").read()
m = re.search(r"^const FROZEN=\{(.*?)^\};", s, re.S | re.M)
if not m:
raise SystemExit("⛔ 原型里找不到 const FROZEN 表")
out = {}
# ⚠️ 逗号必须可选:表里最后一项后面没有逗号 —— 早前写成必选,p8 被静默漏掉
# (表现为「页面集合不同」,不是静默通过,但那也是漏;已修)
for k, body in re.findall(r"^\s*(p\d):\[(.*?)\],?\s*$", m.group(1), re.M):
items = re.findall(r"'([^']*)'", body)
out[k] = items[1:] # 第 0 项是页面标题
if len(out) != 8:
raise SystemExit("⛔ FROZEN 表只解析出 %d 页(应为 8):%s" % (len(out), sorted(out)))
return out
def norm(x):
return x.split("(")[0].strip()
def main():
ap = argparse.ArgumentParser(description="骨架单一可信源闸门(②段原文 ↔ 原型 FROZEN 表)")
ap.add_argument("--doc", default=None, help="②段界面布局文档(默认 prd/2b-界面布局.md)")
ap.add_argument("--proto", default=None, help="原型 HTML(默认 ui/mcn-workbench.html)")
a = ap.parse_args()
doc, proto = from_doc(a.doc), from_proto(a.proto)
bad = []
if set(doc) != set(proto):
bad.append("页面集合不同:②段 %s / 原型 %s" % (sorted(doc), sorted(proto)))
for p in sorted(set(doc) & set(proto)):
a, b = doc[p], proto[p]
if len(a) != len(b):
bad.append("%s 板块数 ②段 %d ≠ 原型 %d(②段 %s / 原型 %s)" % (p, len(a), len(b), a, b))
continue
for i, (x, y) in enumerate(zip(a, b)):
nx, ny = norm(x), norm(y)
if not (nx.startswith(ny) or ny.startswith(nx)):
bad.append("%s 第 %d 块 ②段「%s」≠ 原型「%s」" % (p, i + 1, x, y))
n = sum(len(v) for v in doc.values())
if bad:
print("FAIL 骨架与②段不一致(②段 %d 个板块):" % n)
for x in bad:
print(" · " + x)
return 1
print("PASS 骨架冻结:八页 %d 个板块,②段 2b-界面布局.md §二 与原型 FROZEN 表逐页逐位一致" % n)
return 0
if __name__ == "__main__":
sys.exit(main())