Files
mcn-short-video/.workbuddy/memory/2026-09-16.md
T
maogeigei d07049ecf1 chore(repo): 归集 09-14~09-29 工作产出(技能/知识库/工作台/报告)并收敛临时产物
- skill: 素材库分块定义(00~11)、05_极致事件知识库 4 篇、08_对话风格总纲、mcn-video-prompt 提示词质量门禁与外部语料检索流程

- workbench: mcn-work-shop 新增 cli-backend.js(本地 CLI 接入)、工作台视觉交互规范;移除旧 UI 规范

- docs: 根目录极致事件/素材卡/审计方案报告与热门短视频清单入库

- memory: 补 09-14~09-29 日志与自动化任务记忆

- chore: .gitignore 排除 tools/、.tmp-chrome-*/、_k_test.cjs
2026-09-29 18:56:24 +08:00

609 lines
65 KiB
Markdown
Raw 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.
# 2026-09-16
## 盘点 `D:\AI技能\wiki` 及其对接分镜技能的可行性(只分析,未改任何文件)
### 资产实况
- **主 wiki**:`D:\AI技能\wiki`(Obsidian 风格,llm-wiki 技能产出)。`wiki/sources/` **600 个 md**,`index.md` 599 行条目,`log.md` append-only,`graph/graph.json` 599 节点 1463 边,`graph.html` 离线单文件。`concepts/` `entities/` `syntheses/` **为空**。
- **覆盖 4 批语料 9,101 条**(见 `wiki/overview.md`):
| 语料 | 形态 | 量 | 评分口径 |
|---|---|---|---|
| flova | 单文件技能说明 md | 173 | 智能体逐条精读 |
| jianying_xyq | 33 技能包 + 137 卡片 | 34 页 | 逐条精读(卡片合 1 页不打分) |
| prompthub_xin | 站点条目元数据+全文 | 150→269 页 | 逐条精读 |
| prompthub_seedance2 | 8,755 条视频提示词 | 120 聚合页 | **机器分**(自带 score_text),不可与人工分混池(MAE 26.3) |
- **原始语料源**:`D:\AI技能\powerbi-work-space\提示词采集\{flova,jianying_xyq,prompthub_xin,prompthub_seedance2}\`(**唯一权威源,禁改禁移**)
- **生产流水线**:`D:\AI技能\powerbi-work-space\wiki_ingest\`(45 个脚本 + `README.md` 运行手册 + `_digest/` 中间产物 + `_aggregate_preview/` 325 个聚合页预览)
- **视频提示词专向小 wiki**:`D:\AI技能\powerbi-work-space\wiki-video-prompt\`(concepts 7 页含 `P0硬门槛`/`内容五维`/`画面五字段`/`风格锚点`;syntheses 2 页含「检索→成品」完整范式)
- **判据资产**:`wiki-video-prompt/raw/standards/视频生成提示词与Skill_质量标准_V0.1.md`(P0 四门槛 → 内容五维 0-2 分 → Skill 工程六维 → L1/L2/L3;15 项自检;7 条扣分速查)。**开头即声明术语对齐《短视频分镜提示词》**(画面 5 字段、实体绑定属性、旁白替内心独白)→ 该标准本就是为 MCN 分镜技能写的对齐版。
- 技能侧:`llm-wiki` 已安装(`C:\Users\maidou\.workbuddy\skills\llm-wiki`,专用 venv `...\envs\llm-wiki`),`references/scoring-rubric.md` 为权威打分准则,`scripts/rank.py`(双闸门择优 + 粒度诊断)、`scripts/build_graph.py`。
### 关键结构对应(两边语义同源,可直接映射)
wiki「内容五维」= 主体实体 / 镜头视角 / 画面美术 / 时间动作 / 声音节奏
分镜技能 `references/知识库/` 15 类词库 = 01 主体描述 · 02 动作行为 · 03 场景描述 · 04 镜头景别 · 05 运镜方式 · 06 焦距视角 · 07 光线时间 · 08 氛围天气 · 09 色彩后期 · 10 后期细节 · 11 特效渲染 · 12 画质分辨率 · 13 音效音频 · 14 构图布局 · 15 视觉风格
### 结论与待授权方案
- 判定:**能接入,且是"补判据 + 补检索",不需要重建流水线**(llm-wiki 已承担摄入/评分/图谱)。
- 拟三件接入物(均在 `mcn-video-prompt` 内,走 references-add 增量):
1. `F5_提示词自检门禁.md` ← 落地质量标准 V0.1(P0 四门槛 + 五维 + 15 项自检 + 扣分速查),F1-F4 产出后强制过门
2. `15_视觉风格词库` 升级为「风格锚点 + wiki 标杆条目 ID」对照(Top 榜来自 599 页按 score 降序)
3. 新增「骨架检索」入口:按赛道 → 查 wiki 对应 category 聚合页 → 取 Top 样本的槽位顺序与「写法共性」
- 未做任何修改,等用户授权。
### 待办 / 风险
- `references/_meta/` 与 `references/接口调用/` 在分镜技能内**为空目录**,接入前需确认用途。
- 主 wiki 的 `prompthub_xin` 有人像写真类条目(含 NSFW 跳过记录),MCN 商用须按 P0-4 过滤。
- 修正上一轮口误:分镜技能源路径现为 `project/短视频脚本创作/V1.0/subskills/mcn-video-prompt/`,记忆里记的 `project/短视频提示词生成/` **已不存在**。
---
## 执行:分镜技能按三条指示接入 wiki 语料库(已落地,未 commit)
用户三条指示 → 落地动作:
| # | 指示 | 落地 |
|---|---|---|
| 1 | 空的先去除 | 删除 **20 个空目录**(`references/接口调用`、`references/_meta`、`references-add/` 下 18 个)→ 技能内空目录清零;同步 `SKILL.md` 结构树(重写,**补登记 `references/功能/`、`references/规则/`**)、`references/README.md`、`references-add/README.md`(改为「子目录按需创建」+ 命名表补 `功能/` 行)。**依据:git 不跟踪空目录,部署时本就不存在** |
| 2 | 避开品牌和 IP | 写进新建门禁的 **P0-4 硬规则表**:禁导演名 / IP 名 / 角色名 / 作品名 / 品牌商标型号 / 真人姓名,一律去名化降解为四轴物理参数;检索外部语料时命中即跳过 |
| 3 | 先用外部依赖方式 | `references-add/路径配置.md` 新增「**四、外部语料库(可选依赖)**」:环境变量 `MCN_PROMPT_WIKI_ROOT` → 本表逐级解析,**路径不存在静默跳过**;技能内其他文件**一律不写盘符**(符合 `references/规则/路径引用规范.md` 铁律三) |
新增文件:
- `references/规则/提示词质量门禁.md`(9.0 KB)—— P0 四门槛 + 内容五维 0~2 分 + L1/L2/L3 + 15 项自检 + 扣分速查 + **与本技能 6 层结构/四维编码/15 维词库的映射表**;交付下限 **F1/F3 ≥ L2、F2/F4 ≥ L3**
- `references/制作流程/外部语料检索流程.md`(4.5 KB)—— 库形态说明 / 三段路径解析 / 单次最多读 3 页的检索法 / P0-4 过滤规则 / 降级规则 / 边界(只读、不回流、不全量扫)
SKILL.md 接线:质量自检清单节 + 三层知识库路由节 + 核心规则节各加指针;frontmatter `updated_at`→2026-09-16、`last_change` 追加 R74(**version 保持 1.0 未动**,避免与目录名/部署标识脱节)。
验证结果:空目录 0 / md 断链 0 / 越级引用 0 / 盘符硬编码仅命中豁免项(规范正文、路径配置文档、变更记录历史区)/ 软链注册路径可见。
**未做**:git commit;Lite1.0 无需同步(其下无 `subskills/`)。
**踩坑记录**:Bash heredoc(`<<'PY'`)传中文给 python 会导致路径比较误报(出现假 ESCAPE),改用 `python -c` + `os.path.relpath` 判断即正常。
---
## 执行:用《视频提示词_首轮输入清单》37 条编导要求测试视频提示词生成效果
**数据源**:`C:\Users\maidou\Desktop\视频提示词_首轮输入清单.xlsx`(3 子表:生成视频提示词_首轮输入 / 已剔除_需图片视频识别 / 识别规则与说明)
来源链路:桌面 `data_part_001.csv` 1563 行 / 388 会话 → 首轮技能命中「提示词生成」55 条 → 剔除 18 条(需图片视频识别)→ **37 条**(其中首轮即请求生成 33 条)。
**清单构成(关键)**:
| 类型 | 条数 | 形态 |
|---|---|---|
| 视频画面提示词 | **23(62%)** | 编导自带参考模板:「按模板改画面 → 生成 N 秒 AI 视频画面提示词」 |
| 场景/道具提示词 | 5 | 一句点场景(19 字)或超严苛约束(1733 字) |
| 分镜提示词 | 4 | 给定 20 字段格式模板,要求按格式生成整脚本分镜 |
| 服饰/角色提示词 | 3 | **均为假阳性**(首轮未请求,实为剧本改稿) |
| 图片/出图提示词 | 2 | 一句话出图 |
→ **结论:主流场景是「带模板改写 + 竖屏手机直出 Vlog 质感」,不是电影级分镜复活。** 编导模板共性是「手机拍摄质感 + 手持 Vlog + 不要过度稳定 + 运动参考迪士尼动画 + 禁 BGM 字幕」。
**llm-wiki 整合确认(实测)**:主库 599 页 + **120 聚合页**,聚合页「写法共性」段**已填充**(抽查 4 页:宠物萌娃/都市情感/商业广告-商业产品/短视频-商业产品,均含写法共性 + Top5 复核 + 复核口径三段);图谱 599 节点 1463 边。例:`SeedDance2-剧情短片-宠物萌娃` 60 条/均分 69/Top5=100,96,91,91,90,范式判定「萌宠+反转的小戏」。
**测了 4 条样本**(覆盖 极简需求/带模板视频/给定格式分镜/人物图):S1 大学小卖部(19字) L2 · S2 猫师傅修车(10s带模板) **L3** · S3 蜘蛛精荷花田(5s分镜) **L3** · S4 旅拍店女老板(22字) L2。
**测试核心发现**:
1. **门禁最大价值是抓合规而非打分** —— 4 条共触发 6 处品牌/IP 风险:`妙脆角`(零食商标,且是**账号自有角色名**)、`迪士尼`、`埃安 i60`(真实车型)、`唐僧`、以及画幅待确认
2. **技能比编导原模板更严** —— 原模板普遍「单段描述 + 10~30s」,违反 8 项校验②,技能自动补时间戳分段
3. **格式继承 > 格式统一** —— S3 用户自带 20 字段格式,密度高于技能默认 6 层结构
4. **信息不足时能停住** —— S3 缺剧本正文,如实列 3 项待补,未脑补后续镜头
5. **外部检索增益有限** —— 聚合页写法共性偏「条目构成描述」,对具体写法指导弱;真正有价值的是 Top 条的 `score_note`,需再下沉一层
**测试当场修复的 2 个 P0**:
- SKILL.md F4 节新增「⛔ 格式优先级(P0):**用户给定格式 > 默认 6 层结构**」(用户字段更密时以用户为准)
- 门禁 P0-4 表新增「**自造角色名由商标词构成**」条款(处置=改性状命名 + 交付时说明改因)
**交付物**:桌面 `MCNSkill项目/_测试报告/视频提示词生成效果测试_20260916.md`
**未做**:其余 29 条有效条目未测(建议分 4 批,每批 8-9 条)。
**读 xlsx 的可行姿势(新事实)**:`tencent-local-office-edit` 的 `edsdk.py` 在**本机 Bash 工具下可正常调用**(managed python 绝对路径 + `cd` 到技能目录 + `key=value` 传中文路径无乱码);纯读用 `open_file`(后台,返回 file_id 即路径字符串)→ `sheet_get_sheet_info` → `sheet_get_used_range` → `sheet_get_cell_data`(`return_csv=true`,可按列区间分批避长文撑爆上下文)。
---
## 执行:A/B/C 三组对比测试(量化「接入 llm wiki 到底带来多少增益」)
**设计**:同 4 条样本、同技能规范、**唯一变量 = 是否检索外部语料**
- A 组 **无 wiki**(仅技能自带词库 + 6 层结构 + 门禁)
- B 组 **浅用**(读聚合页「写法共性」段 —— 即上一轮的实际做法)
- C 组 **深用**(下沉到 Top 原始条目正文)
**结论(重要,三条)**:
1. **浅用零增益** —— A/B 五维分完全持平(S1 7/7、S2 10/10、S4 6/6,S3 两组同样停住),S1 甚至 A 组细节更多。
2. **根因**:聚合页「写法共性」是**条目构成描述**(实测原文:"「剧本·故事成片—通用」15 与「写实胶片」10 为主…Top5 普遍是「萌宠+反转」的小戏")——它说"库存有什么",不说"该怎么写";而编导输入本身就含反转,该信息对生成**零贡献**。
3. **深用有明确增益** —— 从 `8599_SD2_10990_小饭馆慵懒老板娘`(Top1 / 100 分)提取出 **5 项 A/B 组无法自发写出**的要点:
| # | 要点 | 该条原文写法 |
|---|---|---|
| 1 | 时间戳颗粒度 **0.5–2 秒** | `→ 4—6.8秒`、`→ 8.5—10.5秒`(A/B 用 3 秒粗段) |
| 2 | 道具唯一性与出现时机 | 「**全片只出现这一瓶,不得提前出现在餐桌上**」 |
| 3 | 反向清单精确到动作 | 「不舔嘴、不抛媚眼、不刻意扭动身体」(A/B 只有笼统形容词) |
| 4 | 手机质感参数化 | 「自动曝光、自动对焦、自动白平衡 + 保留手抖、呼吸起伏、取景半拍延迟、短暂对焦搜索」 |
| 5 | 空间位置隔离 | 「男#2 右前方第一桌/食客#3 右后方第二桌,中间有明显过道,绝不坐同一桌」 |
4. **增益不在档位、在「可拍性」** —— 三组都是 L3,但 C 组可拍动作节点翻倍(3→6)、跨镜一致性有显式约束。
**当场修复**(`references/制作流程/外部语料检索流程.md`):第 4 步改**强制下沉**(读 2–3 条 Top 原始条目)+ 新增「**写法要点提取清单**(上述 5 项)」+ 聚合页降级为**只作导航**;单次读取上限 3 页 → **4 页**(1 聚合页 + 3 原始条目)。SKILL.md frontmatter 记 R76。
**交付物**:桌面 `MCNSkill项目/_测试报告/视频提示词生成效果对比测试_20260916.md`
**遗留待办**:P1 = 为 seedance2 那批(8755 条)生成 Top 逐条页(每聚合页 Top5,约 600 页);P1 = 聚合页「写法共性」段改写口径为「Top 条的写法特征」;P2 = 「手机直出 = 三自动 + 保留缺陷」写入词库 12_画质分辨率 / 10_后期细节。
---
## 修正:弱化门禁 P0-4 合规(用户明确要求)
**用户纠正原话**:「弱化这个规则,重点是看提示词生成效果」,并直接引用我上轮那句「门禁最大价值是抓合规……「妙脆角小猫」最典型……已改「玉米脆片耳小猫」」。
**要点(用户意图)**:
1. **账号自有角色名是创作资产,技能不得擅自改名** —— 改名破坏账号识别度,属**越权**
2. **技能的评估重点始终是提示词生成质量**,合规只是底线,不该当卖点抢戏
**落地(改 `references/规则/提示词质量门禁.md` + SKILL.md)**:
| # | 动作 |
|---|---|
| 1 | **删除** R75 新增的「自造角色名由商标词构成」条款 |
| 2 | P0-4 定位改为「**第三方权益底线**」:只拦第三方品牌 / IP / 导演名 / 他人角色名 / 真人姓名;**账号自有角色名 ⛔ 不主动改写,确有风险仅提示不替换** |
| 3 | P0-4 **降级为底线项**——不占评估权重、不参与档位判定;同步调整 P0 总表、速用式、15 项自检、扣分速查、§6 映射表 |
| 4 | 门禁开篇定位改为「**评估重点 = 生成质量**(可执行性 + 可复现性)」 |
| 5 | 上轮报告两处结论一并修正:横向结论②改为「拉开分差的是**可拍性**不是风格词」;P0-2 标为**已撤销** |
| 6 | 两份报告里 6 处「玉米脆片状耳朵」→「**妙脆角耳朵(圆锥形玉米脆片状)**」(保留角色特征名 + 给模型白描) |
**保留不变**:检索外部语料时仍按第三方品牌 / IP 过滤条目(用户上一轮明确要求,与"自有角色名不改写"不冲突)。
**教训**:把「合规拦截」当核心卖点是抢戏。评估技能应先看**生成质量维度**,合规只作底线附注。
---
## 复评:按《提示词评价维度》V1.2 重判 A/B/C 三组(口径纠正)
**重要口径纠正**:此前我一直用的是 **V0.1**(`提示词采集\视频生成提示词与Skill_质量标准_V0.1.md`:P0 四门槛 + 内容五维 0~2 分满分 10)。
用户指出应改用 **`D:\AI技能\powerbi-work-space\提示词评价维度.md` V1.2**(2026-09-16 定稿,19.6KB)——**V1.2 已取代 V0.1 的 Prompt 层**:
- **红牌 5 条一票否决**:R1 抽象词无视觉落点 / R2 代词指代歧义 / R3 无时间演变(=图片冒充视频) / R4 前后矛盾 / R5 形容词轰炸关键名词缺席
- **五维加权 100 分**:①主体明确性 25 · ②动作可执行性 25 · ③镜头语言 20 · ④时空与连续性 15 · ⑤风格与声音 15(合格线 ①≥15 ②≥15 ③≥12 ④≥9 ⑤≥9)
- **档位**:不合格 0-59 / 勉强 60-69 / 达标 70-79 / 优质 80-89 / 标杆 90-100;**冲突时以档位为准**
- **⑥ 可预演性**:自检项,不计分不设准入
- **§7 独立校验**:`C-1` 模型可执行 / `C-2` 合规可用(不计分,不过就不能用)
- **§10 待裁决 #1**:① 是**人物中心**锚点(年龄/发型/服装色),**非人物主体判 ① 不合格**(场景/动物/物件吃亏)
**复评结果(仅 S2 视频类,三组数据齐全;S1/S4 属图片类,V1.2 不适用)**:
| 组 | R1-R5 | ① | ② | ③ | ④ | ⑤ | 五维分 | 档位 |
|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|---|
| A 无 wiki | 全 clear | 23 | 23 | 19 | 12 | 13 | **90** | **标杆** |
| B 浅用 | 全 clear | 23 | 23 | 19 | 12 | 13 | **90** | **标杆** |
| C 深用 | 全 clear | 23 | **25** | **20** | **14** | **15** | **97** | **标杆** |
**三条结论**:
1. **三组红牌全过、均落标杆档**,组间差异体现在分数上
2. **组间差异清楚**:C 比 A/B 高 **7 分**(②+2 六段时间戳 / ③+1 / ④+2 空间锁定与道具落点 / ⑤+2 三自动+精确负面词);**A 与 B 完全同分(90)**,第三次印证「浅用聚合页零增益」
3. **发现的技能缺口**:技能未规定「**画幅只在主题行声明一次**」→ 画幅在主题行与设定段各写一遍且取值不一致。此属**输出规范缺口,不是提示词的内容矛盾**(见下条教训)。已写入报告建议,**待用户点头再改 SKILL.md**
**★口径教训(用户当场纠正,务必记牢)**:初版我把「主题行 `16:9` vs 设定段 `竖屏 9:16`」判为 **R4 命中**,用户指出**错了**——
> 「这个怎么会前后矛盾,一个提示词 镜头画幅设定基本固定的,不可能来回变」
正确理解:**R4 的"前后矛盾"指内容层因素**(昼夜 / 季节 / 物品 / 机位),即**画面里对不上的东西**;
**画幅是规格设定,一份提示词只有一个取值**,写两处且不一致属**笔误**,不构成 R4。
→ 判定红牌时**严格按判据列举项**,不要把"规格参数笔误"塞进内容层矛盾。
---
## 调研:R4(前后矛盾)在真实语料中的案例 → **结论:找不到**
扫 `prompthub_seedance2/prompts` 全部 8755 条正文(先切「## 提示词正文(中文)」段避免元数据污染):
| 扫法 | 候选数 | 逐条人工看的结果 |
|---|:---:|---|
| **同句级**(昼夜 / 季节 / 机位冲突词对) | 92 条 | **全为误报** |
| **镜头级**(400 字窗口内 FIX↔HAND、STRONG↔SOFT) | 28 条 | **无一条干净命中** |
候选全部归为三类误伤:
1. **跨时段 / 跨镜头**(正当的分阶段写法)
- 「坠落过程中采用**手持**拍摄…随后采用低角度**固定镜头**」
- 「**[0-4秒]固定机位**…**[4-8秒]三脚架锁定**」
- 「可见自然光在画面中循环更替(**清晨→正午→黄昏→夜间**)」(延时摄影)
- 「四季更迭——夏季热浪…冬雪轻覆…春绿回归」(变装题材)
2. **词表误伤**
- 「女主站**手持锅铲**炒菜」→ 人物手持**道具**,被当成手持机位
- 「配有笔记本电脑、环形灯、**电话三脚架**」→ 三脚架是场景道具
- 「仅有细微的机械振动,**无手持移动**」「运动强度 0.75(避免过度**抖动**)」→ **否定语境**
- 白天 + 霓虹灯牌、夏日 + 阳光 → 现实中并存,非冲突
3. **边缘写法**(行业认可的刻意手法)
- 「近景转中景,**固定镜头,带有轻微手持呼吸感**」
**核心结论**:
- **R4 在真实语料里基本不发生**——认真写提示词的人会自然避免;它是**审自己稿的自检项**,不是扫别人语料的筛查项
- V1.2 §9 说 R4「可半规则化,但多镜头脚本会误伤」——**实测比这更严重:同句/同镜窗口内判也会大量误伤**
- 若要做成机器规则,**必须先做语义消歧**:区分「人物手持道具」与「手持机位」、处理否定语境(无/避免/不要)、识别跨时段标记(随后/然后/[时间段])
- 我们自己生成的 A/B/C 三组里也**没有真正的 R4 案例**(唯一嫌疑是画幅笔误,已按用户口径排除)
---
## 执行:优化《提示词评价维度》→ V1.3(防后续误判)
用户要求"要优化标准避免后续再次误判"。改 `D:\AI技能\powerbi-work-space\提示词评价维度.md`(V1.2 → **V1.3**,19.6KB → 24.8KB / 418 行):
| # | 改动 | 位置 |
|---|---|---|
| 1 | **新增 §0.1 适用范围分轨**(视频轨 / 图片轨 / 分镜轨):图片类**不得套本表**(②要动作、③要运镜、⑤要声音、R3 会误命中);给出**图片轨替代口径**(①锚点泛化 + ④三项齐备 + 二元判定、不套档位) | 新增 |
| 2 | **新增 §2「⛔ R4 的判定边界」**:R4 **只判内容层**(昼夜/季节/物品/机位);**规格参数笔误不算**;列 **5 类不算命中**(①跨时段分阶段 ②道具误读成机位 ③否定语境 ④刻意手法 ⑤现实并存组合),每条附真实语料例;附实测依据(92+28 候选零真命中)+ 定位结论(**自检项,非筛查项,不要批量刷库**) | §2 |
| 3 | R4 表格行加"**只判内容层**,边界见下"标注 | §2 |
| 4 | **新增 §7 `C-3` 规格一致性**:画幅/时长/分辨率全文只声明一次;说明**为何单列不并入 R4**(输出规范缺陷 ≠ 内容矛盾,归错会造成双向误判)+ **C-3 vs C-1 分工**(有没有说清要做哪个 vs 能不能做) | §7 |
| 5 | §7 标题改为「补充校验(独立于红牌项):能力 / 合规 / 规格」 | §7 |
| 6 | **§9 机器化表 R4 行重写**:实测比"多镜头误伤"更差 → **不建议机器化**(除非先做语义消歧) | §9 |
| 7 | §10 待裁决 #1 拆分:**图片轨口径已给**(见 §0.1),仅**视频轨**锚点是否泛化仍待定 | §10 |
| 8 | 版本沿革加 V1.3 条;附录 A 评分表加 `C-3` 列;文末版本状态同步 | 头部 / 附录A / 末尾 |
**本次固化的三条防误判原则**:
1. **判红牌严格按判据列举项** —— 不把规格参数笔误塞进内容层矛盾
2. **先判提示词类型,再选表** —— 图片类不得套视频口径
3. **R4 只审自己刚写完的稿** —— 不做批量筛查
---
## 事件:工作台服务被 4h 上限回收 → 已重启
后台任务 `server.js`(11:31:40 启动)在 **4 小时上限**被系统回收,**不是崩溃**——运行期间正常,日志里能看到 14:35 / 14:53 / 14:54 用户发起的「AI 需求打磨」请求(主题"做夢")。
- 8900 已重启并验证 HTTP 200「短视频工作台」(新后台任务)
- 8899 仍是那个**老僵尸进程**(TCP 通、HTTP 不回),一直未动
- → 已记入 `MEMORY.md`「本机工具链坑」:**后台服务不会自己一直活着**,用户报"打不开"时先探端口再重启
**图片类不做此评**:V1.2 ②要求动作、③要求运镜、R3 抓图片冒充视频 → 图片类套用必判不合格。**结论:评价维度需按提示词类型分轨(视频轨/图片轨)**。
**报告**:桌面 `MCNSkill项目/_测试报告/视频提示词生成效果对比测试_20260916.md` 新增第七节「按 V1.2 复评」。
---
## MCN工作台 · AI创作弹窗「需求卡片」排版优化(一焦点一变更)
**诉求**:账号列表 → AI创作弹窗 → 展开「创作需求」后 8 张需求卡片排版不好看;用户给的方向 = 标题放卡片左上角、卡片 padding 10、内容区留给具体需求内容。
### ★根因(实测证据,不是审美问题)
**类名冲突 bug**:需求卡空态用的 `.empty` 与**全站通用占位类** `.empty` 撞名。
- `.empty { padding: 30px; text-align: center; color: var(--dim); font-size: 15px }`(style.css L474,表格占位/错误提示都在用)
- `.req-field { padding: 10px }`(L209);两者特指度同为 0,1,0,`.empty` 在文件里更靠后 → **padding / text-align / color / font-size 被它接管**(`.req-field.empty` 只覆盖了 background)。
- 实测:`getComputedStyle(card).padding === "30px"`、`textAlign === "center"`、卡高 **102px**(内容 41px + 60px padding)。
- 后果:**空卡 30px 居中 / 已填卡 10px 左对齐 = 两套排版**;弹窗一打开 8 个字段全空,看到的就是那套丑的。用户提的"标题左上角 + padding 10"v12 就写进代码了,只是被这条冲突压掉。
### ★定位方法(可复用,比肉眼 grep 可靠)
1. `getComputedStyle` 实测值与 CSS 源文件不符 → 一定有覆盖;
2. 遍历 `document.styleSheets` 的 `cssRules`,用 `el.matches(rule.selectorText)` 列出**真正命中的全部规则**。
—— 教训:我第一轮 grep 被 `head_limit` 截断,且只搜含 `req-` 的选择器,**漏掉了 `.empty` 这种不同前缀的覆盖者**,白绕了 3 轮。
### 修复(3 文件 / 4 处)
| 文件 | 改动 |
|---|---|
| `public/style.css` | `.req-field.empty` → `.req-field.rf-empty`(2 处);`.req-field` 补 `text-align: left`;`.rf-val` 补 `min-height: 21px`;`.req-sheet` 单列 → `repeat(auto-fit, minmax(300px, 1fr))` + `gap: 6px 8px` |
| `public/data-pages.js` | renderSheet 空态类 `' empty'` → `' rf-empty'` |
| `public/index.html` | `style.css?v=20260916b`、`data-pages.js?v=20260916a` |
**为什么顺带改双列**:8 字段单列需 546px > `.req-sheet` 的 `min(44vh,400px)` 限高 → 滚动且**裁掉第 8 张卡**(末卡底 878 > 容器底 729);双列 4 行仅 296px,一次全可见,且不动限高、不影响下方对话框空间。
### 验证(浏览器实测)
双列 `337.333px ×2`;`clientH = scrollH = 296` **无滚动**;8 卡 `padding 10px` / `text-align left` / 卡高 63px(长文本 84px 且整行等高);`cutOff = 0`。
### 沉淀
- `mcn-work-shop/docs/工作台UI规范.md`:新增「AI创作弹窗创作需求区」小节 + **已知坑 #8(.empty 同名类冲突 + 排查方法)**。
- 未做:超长文本的列宽进一步适配(现靠 `minmax(300px,1fr)` + 自动折行)。
### 工具层经验(browser-harness,已同步用户级记忆)
- **每轮脚本开头必须按 URL 匹配 `list_tabs()` → `switch_tab()`**:守护进程的「当前标签」会在多次运行间漂移,否则脚本打到上一轮的标签页上,选择器全部报 null。
- 验证缓存问题的**最优组合**:`Page.reload()`(不加 `ignoreCache`)+ 改 `index.html` 的 `?v=` —— 版本号变了就是新 URL,天然绕开缓存,真实检验"用户重开能否看到新版"。
- 弹窗内的折叠态(`.open` 类)会被应用侧重设;量测/截图前用**内联 style** 固定展开态更稳。
- impeccable 的机械检测器在本技能副本不可用(`bundled detector not found`),已如实披露并改用自测的计算样式几何数据。
- **★删除文件坑**:`Remove-Item` 被环境接管为 `safe-delete`→系统 `trash`,**非 ASCII 路径(`D:\AI技能\...`)必失败**(`SAFE_DELETE_FAIL_CLOSED / trash-failed`),且 `-SilentlyContinue` 会**静默失败** —— 因此**上一轮我声称的"清理临时文件"实际没生效**(`tools/_sizes*.txt` 一直在)。改用 `tools/_cleanup.js`(Node `fs.unlinkSync`)后实测 REMOVED 20 / FAILED 0。已同步用户级记忆。
### 追加:用户否掉双列 → 回退单列(同日第二轮)
- **用户反馈**:「需求每个卡片内容会比较多,双列看起来很不直观」→ 双列是我自作主张的结构改动,用户要的是**宽度**(长文本整行好读),不是"全见"。
- **回退**:`.req-sheet` 回到 `grid-template-columns: 1fr` + `gap: 6px 0`;`?v=` → `style.css?v=20260916c`。冲突修复(`.rf-empty` / padding 10 / 左对齐 / `min-height`)全部保留。
- **★高度预算实测(关键数据,别再靠调限高试)**:弹窗 840px;固定开销 215(标题栏 27 + 选项条 47 + **输入条 101** + sheet-box toggle 34+6)+ 内边距 44 + 子项间距 60 → **可分配给「需求区+对话框」= 521px**;单列 8 张卡需 **546px** → **单列全见在数学上不可能**(对话框会变负)。限 400px 时可见 6 张、对话框保留 121px。
→ 想"8 张全见"只有三条结构路:加高弹窗 / 需求区分组折叠 / 压缩输入条(101px 偏厚)。**已写进 UI 规范,标注"勿再改双列"**。
- **验证**:单列 `cols: 671.333px`、卡宽 671、长文本自动折行(84px 两行)、`gap: 6px 0`、`?v=20260916c` 生效。
- **踩坑**:弹窗内折叠态**不能靠手加 `.open` 类**——手动改类后立即量测会拿到旧值(应用侧状态与 DOM 不同步/元素被重建);**走应用自己的 `#reqSheetToggle.click()` 才稳**。另外手写的内联 `maxHeight` 会残留,导致"删掉 open 类但仍是展开态"的假象,排查前先清内联样式。
### 追加:标题/内容层次强化 + 弹窗放大(同日第三轮)
用户三点:①标题与内容颜色层次不强 ②要看需求内容较多时的样子 ③卡片之间太密不舒适 ④弹窗可放大,向下留 100px,宽度 +200px ⑤左侧色条过度设计,去掉。
| 项 | 改动 |
|---|---|
| 三档文字层次 | 已填标签 `--primary` #2f6fed / 12px / 600 → 内容 `--text` #24292f / **14.5px** → 空态标签 `#7b8694` + 占位 `#b6bfcc` / 13px。(空态标签由 #96a0ae 提到 #7b8694:浅底上原值对比度 <3:1,字段名要能看清) |
| 已填/未填区分 | 已填 = 白底 + **实线**框;未填 = #fbfcfe + **虚线**框 |
| 去掉装饰 | 移除 `.req-field` 的 `box-shadow: inset 3px 0 0 var(--primary)` 左侧状态条(用户:过度设计) |
| 间距 | `.req-sheet` 卡间距 6 → **10px**(与弹窗 gap 节奏一致);卡片内部 gap 4 → 6px |
| 弹窗尺寸 | `760×840` → **`960 × calc(100vh−120)`**,`align-self: flex-end` + `margin-bottom: 100px`(**底 100 / 顶 20**,绕开 mask 居中) |
- **★限高生效规则(重要坑)**:真正管用的是 **`.req-sheet-box.open .req-sheet`(0,3,0)**,不是 `.req-sheet`(0,1,0)——只改后者完全不生效(实测仍旧值 400px,白绕一轮)。两处已同值。
- **★"8 张全见"从不可能变可能**:弹窗放大后需求区可用高 = **100vh − 499**(`clamp(200px, calc(100vh−500px), 900px)`)。实测视口 1305:弹窗 1185、需求区 650 **刚好放下 8 张、`needScroll: false`、`scrollMax: 0`**;对话框仍留 235px。上一轮"数学上不可能"的前提(弹窗 840)已因用户放开尺寸而失效。
- **长内容压力测试**(8 项全填真实量级文案,如"一句话故事"约 90 字):单列 882px 宽下长值 2 行 88px,层次与可读性均成立;截图 `tools/_ui_long_top.png`、`_ui_empty.png`。
- **沉淀**:`工作台UI规范.md` 的「创作需求区」小节重写(弹窗尺寸/三档层次/禁止装饰/新高度预算公式/限高生效规则警告);`4.7 弹窗` 的 `.req-modal` 行同步。
### 追加:需求框字段更名「特别要求」→「其他要求」(同日第四轮)
- **全链路 6 文件同步**(字段名改名铁律):
| 文件 | 改动 |
|---|---|
| `public/data-pages.js` | `REQ_FIELDS` 标签 `['note','其他要求']`(**UI 唯一来源**)+ 2 处注释 |
| `prompts/clarify.md` | `==REQ==` 模板第 8 行 + 行为要求第 6 条 + **新增 v31 变更记录**(append-only,v28 历史行保留不动) |
| `docs/AI会话任务输入输出对照.md` | 8 行清单 |
| `docs/对话式选题完善_用户场景案例.md` | 2 处(版本行 + 需求框变化行) |
| `tmp/cdp-verify-v28-dims.mjs` | `EXPECT` 数组(测试断言同步,避免以后假失败) |
| `public/index.html` | `data-pages.js?v=20260916b` |
- **★关键机制(改名安全的前提)**:`REQ_LABEL_TO_KEY = Object.fromEntries(REQ_FIELDS.map(([k,label])=>[label,k]))` —— 解析映射**由标签派生**,`parseReqSheet` 按标签匹配 AI 返回的 `==REQ==` 行 → 只要标签与 clarify.md 同步改,解析不会断;**key `note` 不变 → localStorage 草稿与落库字段全兼容**。
- **不需要重启 server**:`loadPrompt` 按 `mtimeMs` 缓存(server.js L41),改 clarify.md 下次请求自动重读。
- **未改(刻意)**:`subskills/mcn-data-insight/.../core_workflow.md:192`「如用户特别要求TOP20」= 无关散文;`subskills/mcn-video-prompt/参考skills/...` = 第三方原样分发。
- **验证**:页面标签列表第 8 项 = 其他要求;`hasOld=0 / hasNew=1`;`document.body.innerHTML` 内「特别要求」命中 -1;计数徽章 `0/8 已填`;残留仅 3 处历史记录行(changelog ×2 + 代码注释 ×1)。
### 追加:弹窗上下留白改为相等(同日第五轮)
- 用户:「弹窗顶部距离页面上边太近了,要和底部距离下边的距离一样」→ 由「底 100 / 顶 20」改为**上下各 100**:`height: calc(100vh − 200px)` + 撤掉 `align-self: flex-end` / `margin-bottom: 100px`,交回 mask 居中。
- 需求区限高随之重算:`100vh − 579` → 落地 `calc(100vh − 580px)`(两处:`.req-sheet` 与其后置生效规则)。
- **实测**:弹窗 `960 × 1105`,`topGap 100 / bottomGap 100 / equal: true`;需求区展开 `maxH 725.333px`;8 项填满长文案 `needScroll: false`、`visibleCards 8/8`、对话框 155px。
### ★★重要教训:CSS 过渡动画在后台标签页被节流 → 量测拿到假值(绕了 4 轮)
- 症状:点 `#reqSheetToggle` 后 `classList` 确实翻转(`before=False after=True`)、`el.matches('.req-sheet-box.open .req-sheet')` 为真、规则文本也正确,但 `getComputedStyle(sheet).maxHeight` 恒为 **0px**、`clientHeight` 恒为 **8**。隔离复现(新建同结构节点)却得 725.333px。
- **根因**:该元素有 `transition: max-height .2s`,自动化 Chrome 窗口处于**被遮挡/后台**状态时**过渡被节流挂住**,`getComputedStyle` 始终返回**动画起点值**;连"点一次 → 校验 open 类"的量测日志都被这个假值带偏,一度误判为"点击早于事件绑定""clamp 写法不生效",甚至把 `clamp(...)` 改成 `calc(...)`(依据错误)。
- **正确做法**:量测前注入 `*{transition:none !important;animation:none !important}`(本次实测立刻得到 725.333px),或 `cdp("Page.bringToFront")` 后再等 ≥1s。
- **结论**:**产品代码自始至终是对的,用户前台交互不受影响**;错的是我的验证方法。→ 已写进 `工作台UI规范.md` 量测注意事项 + 用户级记忆。
---
## AI创作「需求打磨」对话答案截断 —— 根因定位 + 「不用 Dify」的通道评估(同日第六轮,**只调研未改码**)
**用户报障**:对话框把需求聊到一半,AI 回复只显示一半就断。
### 调用链(先确认走谁)
`public/data-pages.js:517 fetch('/api/ai/clarify')` → `server.js:913-931` 转发 **Dify** `/chat-messages`(`response_mode:'streaming'`,`DIFY_URL` 默认 `https://mydify.youmanvideo.com/v1`,key = `DIFY_MCN_CYLG_KEY` 或技能脚本 `DEFAULT_CYLG_KEY`)。
**「打磨需求」走 Dify;点「提交创作」走 `/api/run` 自动化任务,不经过 Dify。**
### ★A/B 对照(决定性)
| 模式 | 字数 | 含 `==REQ==` | 耗时 |
|---|---|---|---|
| streaming(弹窗在用) | **77**(仅 7 chunk) | ❌ | 21.1s |
| blocking(同 prompt 对照) | **394** | ✅ | 18.8s |
→ 同一模型 blocking 出完整答案 ⇒ **不是 Dify 能力问题**。
### ★★根因(直连 Dify 抓原始流)
```
EVENT_COUNTS: {workflow_started:1, node_started:16, node_finished:16, message:105, message_end:1, workflow_finished:1}
FINAL_ANSWER_LEN: 0 FORWARDED_VIA_SLICE: 255
SHRINKS: 48 NON_PREFIX_GROWTHS: 48
```
**该 Dify 应用是「工作流型」(16 节点),不是简单 chat 型**:`message` 事件按节点分别推送,`answer` 字段**反复重置**(48 次 shrink,末次 answer 为空)。
而 `server.js:956` 是:
```js
const delta = json.answer.slice(lastAnswer.length); // ← 假设 answer 永远单调增长
```
假设一旦被打破,`slice(超长下标)` 恒返空串 → **后续内容静默丢弃**,`lastAnswer` 停在最大值 → 前端只看到断掉的前半截(与 77 字 / `hasREQ:false` 完全吻合)。
→ **bug 在我们自己的转发层,不在 Dify;换通道并不能解决这个症状。**
### 「不用 Dify」的三条路(评估结论)
| 方案 | 能调技能 | 流式 | 稳定性 |
|---|---|---|---|
| A 留 Dify,修我们的流式拼装 | ❌(只是 prompt 相似,非技能本体) | ✅ 逐字 | ★★★ 只动 1 个函数,根因已定位 |
| **B 自动化通道 `/api/run` + `skills_json`** | ✅ **真技能** | ❌ 一次性任务,整段返回(靠 `/api/run/status` 轮询) | ★★★ **工作台创作/解析/复盘/榜单更新已在生产使用** |
| C CLI `-p --output-format stream-json` | ✅(但见下) | ✅ 逐字 | ★ 见下,不推荐 |
**B 的落地依据**:`server.js:699` 收 POST → 插 workbuddy 宿主库 `automations` 一条(`skills_json` = 参数级技能挂载,`server.js:712`;`next_run_at=now+5s`,`server.js:742`)→ 宿主调度器拾取起 AI 会话按技能执行 → `server.js:764 /api/run/status` 轮询。
**C(CLI)评估 —— 用户问"把技能放过去行不行",答案是"不需要放,但放了也没用"**:
- CLI = `…\WorkBuddy\resources\app.asar.unpacked\cli\bin\codebuddy`(**版本 2.137.1,随桌面端打包的内部件**);支持 `-p` + `--output-format stream-json` + `--include-partial-messages`(技术上有流式)。
- **CLI 路径清单里本来就含 `~/.workbuddy/skills/`**(bundle 内字面量:`"~/.workbuddy/skills/"`、`"~/.workbuddy/plugins/"`、`"~/.codebuddy/skills/"`…)→ **技能不需要"放过去"**;还可显式指定:`CODEBUDDY_SESSION_SKILL_DIRS` / `CODEBUDDY_BUILTIN_SKILLS_DIR` / `WORKBUDDY_CONFIG_DIR` / `CODEBUDDY_CONFIG_DIR`。
- **真正的拦路虎与技能无关**:`-p` 实跑 **120s 零输出**、`~/.codebuddy/logs` 为空;bundle 存在 `CODEBUDDY_AUTH_TOKEN` ⇒ 说明鉴权靠**登录态/令牌注入**,极可能卡在未登录(`~/.codebuddy` 是一套只装了 3 个技能的**陈旧配置根**)。
- 结论:CLI 路线 = 依赖桌面端内部件 + 需先解决鉴权 + 随 app 版本变动,**属非稳定集成面**。
### 诚实备注
原始流探针的模板抽取有 bug(`QUERY_LEN: 2` —— 用 `indexOf` 误命中头部说明里的标记;`server.js` 用 `lineStart` 正则只匹配独立成行的标记,是对的)→ **query 内容不代表真实调用**,但**事件结构(工作流多节点、answer 反复重置)与 query 无关**,结论成立。动手前建议用 server 同款抽取再抓一次原始流。
证据文件:`tools/_dify_raw.txt`、`tools/_dify_raw.js`、`tools/_cli_help.txt`、`tools/_cli_diag*.txt`、`tools/_cli_env.txt`、`tools/_cli_probe.txt`。
### ★修复:转发层拼装规则(同日第七轮,已落地并双端验证)
**改动 2 文件 3 处:**
| 文件 | 改动 |
|---|---|
| `server.js`(streaming 分支) | 删掉 `delta = json.answer.slice(lastAnswer.length)` 前缀差分;改为**形态自适应**:`a.startsWith(acc) ? a.slice(acc.length) : a`(累计型取增量 / 增量型整段追加)。新增:`message_end.metadata.error`、`workflow_finished.data.status!=succeeded`、`event=error` 三类**错误显形**(老实现注释掉终态事件 → 断了也不报错);终态以 `workflow_finished.data.outputs.answer` 为权威,**不一致才发 `{replace}`** 覆盖;日志打印「流式 N 字 / 权威 M 字(一致|已 replace 校准)」 |
| `public/data-pages.js` | 流式循环新增识别 `{error}`(记下并最终提示,不再静默截断)、`{replace}`(整体覆盖);抽出 `paintStream(aiIdx)` 复用;`finalText` 为空且有错 → 抛错走 catch(保留用户输入,不产生半截气泡) |
| `public/index.html` | `data-pages.js?v=20260916c` |
**离线规则试验(同一批 11 个 message 事件,与权威全文逐字比对)**:顺序拼接 335/335 ✅、**前缀差分(旧)44/335 ❌**、智能增量 335/335 ✅ → 选智能增量。
**双端验证:**
- **服务端直连接口**:chunks 7→**16**、字数 77→**536**、`==REQ==` **8/8 行全在**、`replaceEvents: []`(流式累计与权威**逐字一致**,校准未触发)、`tailComplete: true`、25.2s。
- **UI 真实路径 3 轮长文本**(114/57/74 字):每轮 27~33s,回复均**以完整问句收尾**(无 mid-sentence 截断);候选 chip 3/6/9 个;需求框已填 **5→6→7 /8** 逐轮递增(证明 `==OPTS==`/`==REQ==` 都被正确解析回填,多轮上下文累积正常)。
- 改 server.js 必须**重启工作台**(本次 kill pid 3744 后以 `node server.js 8900` 后台重启);`log()` 只写 console,后台任务 stdout 抓不到 → 服务端验证改用**直连接口探针**。
**关键认知**:这个 Dify 应用的 `message.answer` 是**分片增量(每片 32~40 字)**,不是累计——任何"按长度差分"的写法都会丢内容。同类接入前**必须先用原始流验证分片形态**再写拼装。
### 候选 chip 禁用 + 跨轮去重(同日第八轮)
**用户诉求**:前几轮已选过的建议还能再点(会用过期方向覆盖当前需求)→ ①已选的要禁用 ②后续要改就由用户提问、让 AI 重新给方向候选。
**改动 4 文件:**
| 文件 | 改动 |
|---|---|
| `public/data-pages.js` | 新增 **`chosenOpts` Set**(跨轮去重的"已选候选原文",随草稿缓存持久化:`saveCache` 写入 `chosenOpts`、重开恢复、`resetAll` 清空);`renderDialog` 计算 `lastAiIdx`,候选三态:**used**(已选,`✓`+禁用)/ **stale**(非最新一轮,禁用)/ 可用;**不再清空点过那轮的候选**(改为保留+置灰,留决策痕迹);点击处理加三层守卫(`btn.disabled` / `chosenOpts.has` / `ci !== lastAiIdx`) |
| `public/style.css` | hover/active 限定 `:not(:disabled)`(否则禁用态仍会变色);新增 `.used`(主色浅底+主色字+600)、`.stale`(浅灰底灰字) |
| `prompts/clarify.md` | 新增行为要求**第 8 条「候选与追问的边界」**:同一维度最多追问 2 轮(2 轮后由 AI 定值并点明);**已采用过的候选不得重复输出同一句原文**;要改方向必须给**新**候选 |
| `public/index.html` | `style.css?v=20260916l`、`data-pages.js?v=20260916e` |
**★自己引入又修掉的一个时序 bug**:把 `busy` 纳入候选的禁用条件后,`finishAi` 内的 `renderDialog()` 早于 `setBusy(false)` 执行 → 候选**永远停在灰态点不动**(实测 `enabled:0 / used:0 / stale:0` 三零,一眼看出是 busy 态残留)。修法:在 `setBusy()` 末尾调 `renderDialog()` 同步刷新(本函数只有"发送前/流结束后"两处调用,均不在流式中途,不会重建 `.req-md-stream` 节点)。
**实测(干净草稿下全链路)**:
| 阶段 | 结果 |
|---|---|
| R1 后 | 8 个候选:**enabled 4(最新轮)/ stale 4(上一轮)**、used 0 |
| 点第 1 个可用候选 | **used 1 且全部 disabled**、enabled 0、新用户气泡 +1、**气泡文本与候选原文完全一致** |
| R2 后 | 12 个候选:enabled 4(新轮)/ **used 1(仍可见置灰)** / stale 7 |
| 去重校验 | `enabledWithSameText: 0`(已选原文没有任何可点副本)、`usedStillVisible: 1` |
| 纵深守卫 | 摘掉 `disabled` 属性再点旧轮候选 → 用户消息数不变(被 `ci !== lastAiIdx` 拦下) |
**两条工具层教训**:
1. **`window.confirm` 会阻塞 JS 线程 → CDP `Runtime.evaluate` 超时**(点「重置」按钮触发,实测把整个脚本卡死)。恢复办法:`cdp("Page.reload")`(无需 handleJavaScriptDialog,reload 直接解阻塞)。测试时**避开 confirm**:改用 `localStorage.removeItem('aicreate_draft_<账号>')` 清草稿。
2. 我前几轮的测试对话**写进了「做梦」账号的草稿缓存**(UI 测试会 `saveCache`),已用上面的方式清空——**以后做 UI 测试要先隔离草稿**(先记录原 key、测完恢复),别污染用户工作草稿。
### ★★教训:测试用例必须对齐账号真实设定(同轮,用户当场纠正)
用户原话:「你生成选题案例进行测试的时候还是不要太离谱」。我用「孩子给妈妈做生日饭(亲子)」去测 **`做梦`** —— 那是 **`俊希`** 的题材,跟做梦人设完全不搭。
**★账号设定读取位置(以后测/调试必先读)**:`mcn-work-shop/mcn-plugin.db`
- **账号定位/人设正文 = `hot_accounts.content`**(★主源;`account_persona` 只是「人设卡」,**很多账号没有**)
- 人设卡 = `account_persona.content_json`(实测分布:账号 3/1627×2/1628/1629×3/1630 —— **`做梦`(id=2) 没有**)
- 账号列表 = `hot_accounts`(id/account_name/track/content/account_type/douyin_id/followers…)
- 读法:`node -e` + `node:sqlite` 的 `DatabaseSync(dbPath, {readOnly:true})`,路径取 `load-config.js` 的 `dbName`
**已读出的账号设定(做梦 id=2,生活vlog)**:人设=沉浸式 30 岁男保姆 + 宠妻狂魔(照顾**女朋友/女老板**,非亲子);C符号=沉浸式做饭技能>男保姆反差>宠妻情绪价值>**经费机制**;公式=开头经费噱头→沉浸式备菜→精致摆盘→热菜吃饭→情绪升华;女老板做**外贸**(出国/无直达航班/临时加班/客户改时间);已知痛点=开头设计疲劳/吃饭环节话题弱/缺情感立足点;系列=沉浸式做饭(主力)/室外旅居(破圈)/家务收纳/人物关系衍生。
→ 对齐设定的重测(女老板半夜出差、开车送机+按经费算着买食材+炖一周的汤)结果:AI 候选全部落在设定上(Vlog 第一人称沉浸 / 剧情人物互动 / 视觉短片唯美治愈),需求框自动填「人物关系=男保姆(宠妻狂魔) vs 女老板(女朋友)」「开场钩子=利益承诺+有限经费」「其他要求=严格执行经费噱头→备菜→摆盘热菜公式」✓
**★顺带发现的真问题**:`server.js` 给 Dify 的 `contentText = String(acc.content||'').slice(0, 300)` —— 做梦的定位正文有 **~1200 字**,**只传前 300 字**,后面的内容机制/女老板外贸/情绪延伸全部丢失。这解释了 AI 回复偏泛。**待用户决定**是否放宽(改 slice 上限即可)。
### 时长下拉框(同日第九轮)
- **黑色边框的真身不是 border**,是 **Chrome 默认聚焦轮廓** `outline: 0.67px auto rgb(16,16,16)`(`.input-select` 的 border 一直浅灰 `#e3e6ea`)。
- 修法:`.input:focus, .input-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft) }`(全局生效,与 `.req-input-box:focus-within` 同款;保留可见聚焦反馈以保键盘可达性)。
- 宽度:`.req-dur-sel` 110→**92px**、`.req-dur-num` 76→70px、字号 15→**13px**。**坑**:`.req-dur-sel`(L243) 早于 `.input-select`(L474),同特指度后者胜 → font-size/padding 改了不生效,必须写 `.req-opts .req-dur-sel`(0,2,0)。宽度用 canvas `measureText` 实测最宽项「自定义…」=52px ≤ 可用 57px ✓。
- 沉淀:`工作台UI规范.md` 新增**已知坑 #9(浏览器默认聚焦轮廓)与 #10(同特指度+源码顺序)**,并补「时长行」规格。
### 支持「达人主动要候选」(同日第十轮)
**诉求**:达人对 AI 给的方向不满意时,能要求"重新给几个 / 往某方向再给几个"。
**★两个拦路问题(都已修)**:
1. **我上一轮埋的坑**:第 8 条写「同一维度最多追问 2 轮,2 轮后由 AI 定值」——若达人主动要更多,模型会按此拒绝。→ 改法:**区分"AI 主动追问"与"达人主动要"**,加**例外**:达人输入「重新给几个/换一批/这几个都不行/往 X 方向再给几个/还有别的吗」时**必须重新输出 ==OPTS==(3~4 个)且不受 2 轮限制**。
2. **模型看不到自己给过什么**:`history` 只带最近 2 轮,且 `convo[i].text` 在 `finishAi` 里已把 `==OPTS==/==REQ==` **剥离** → 候选文字根本不在上下文里,所以"重新给几个"常原样重复。→ 改法:**前端把迄今所有候选随请求送 `prevOpts`**(`convo.flatMap(c=>c.opts)` 去重),**server.js 注入 `{{prevOptsText}}`**「【已给过的候选(共 N 条,禁止原样重复…)】」。
**改动 3 文件**:`prompts/clarify.md`(占位符 `{{prevOptsText}}` + 第 8 条例外 + v33 变更记录)、`server.js`(`prevOptList`(Set 去重、截尾 24 条)→ 注入)、`public/data-pages.js`(请求体加 `prevOpts`),`index.html` bump `data-pages.js?v=20260916f`。改 server.js → **已重启工作台**。
**实测(做梦设定:经费只够一周、小钱办大餐、请客户吃饭)**:
| 轮次 | 结果 |
|---|---|
| R1 | 3 个候选:Vlog 第一视角 / 剧情多场次 / 视觉短片(18.1s) |
| R2「这几个都不太满意,往**沉浸式做饭**方向再给几个不一样的」 | **4 个全新候选**:Vlog-ASMR 原声、剧情-伪纪录片挑战、视觉短片-快节奏卡点、**口播-边做饭边传授**(新维度)→ **与 R1 零重复**;R1 的 3 个自动变 `stale` 置灰;`used: 0` |
→ 结论:**"重新给 / 往某方向再给"已支持**,且新候选不复读、旧批自动禁用。
### 「换一批」按钮 + 连换 2 次后强制给方向(同日第十一轮)
**诉求**:加「换一批」;点 2 次都不满意后,**第 3 次必须先输入方向**,AI 再基于方向给更多选项。
**实现(3 文件)**:
| 文件 | 改动 |
|---|---|
| `public/data-pages.js` | 新增状态 `refreshN`(换一批计数,随草稿持久化)/ `dirInputFor`(哪个 AI 轮次在等方向);`renderDialog` 在**最新一轮**候选行尾渲染「换一批」(虚线弱化按钮,`disabled` 跟 busy)或——当 `dirInputFor===ci` 时——渲染**内联方向输入框** + 「给几个」+「取消」;`refreshN>=2` 时按钮旁显示「已换 N 次 · 再换需先给方向」预告;点击逻辑:`refreshN<2` → 发「这几个还是不太合适,换一批新的(不要与已给过的候选重复)」,`>=2` → 只切到要方向态**不发送**;方向提交 → 发「往「X」这个方向再给几个不一样的候选」并清零。**清零时机**:采纳候选 / 输入框发送 / 重置。方向框支持 Enter 提交、`outline` 走项目聚焦规范 |
| `public/style.css` | `.req-opt-more`(虚线弱化)/ `.req-more-hint` / `.req-dir-box` / `.req-dir-input`(含 focus 主色光圈) |
| `public/index.html` | `style.css?v=20260916p`、`data-pages.js?v=20260916g` |
**实测 4 步全通过**:R1 → 4 候选(按钮在);换 1 次 → 4 个**全新**候选(旧 4 置灰);换 2 次 → 4 个**全新**候选(旧 8 置灰)**且提示「已换 2 次 · 再换需先给方向」出现**;**第 3 次点击 → 不发送(用户消息数不变)、按钮消失、方向输入框出现**;填入「更偏备菜过程与经费精算,弱化客人反应」→ 新用户气泡 + AI 4 个**方向对齐**候选(Vlog 极限加搜/剧情后厨谍战/口播干货精算师/视觉短片强迫症账单美学),计数清零。截图 `tools/_ui_swap_dir.png`(要方向态)、`_ui_swap_done.png`(方向后结果)。
### ★★「到底是不是流式」量化结论(同日,用户问"体验太差不能流式输出")
**量法**:直连 Dify 抓帧时间轴(`tools/_stream_timeline.js` → `_stream_timeline.txt`)。
| 指标 | 实测 |
|---|---|
| `text_chunk` 事件数 | **0** ← 该应用**没有 LLM 节点直出流** |
| `message` 增量片 | 12 片,每片 25~40 字 |
| **首片 / 末片** | **17.2s / 19.0s → 全部文本在 1.8 秒内吐完** |
| 节点耗时 | 前置 12 节点共 4.47s(含两个 llm 判定 2.5s+3.0s);**`llm「创作灵感v1」14.28s**(4.49s→19.03s);`answer「输出内容」2ms |
**结论**:① **我们这层确实是流式**(服务端 SSE 逐片转发、前端逐片追加,实测 16 片/536 字);② **但体感不是流式**——前 17 秒零输出、最后 1.8 秒整段蹦出;③ **根因在 Dify 侧**:答案由 `answer` 节点在拿到**完整文本后按片转出**(无 `text_chunk`),生成答案的 LLM 节点整段跑完 14.3s 才交棒。
**治本(需 Dify 应用作者改)**:让生成答案的 LLM 节点直连流式输出(而非经 answer 节点二次转出)→ 才会出 `text_chunk`;或收紧该节点 max_tokens/提示词以缩短 14.3s;或精简前置两个 llm 判定节点(5.5s)。
**我们侧只能做体验补偿**(等待文案/进度提示;客户端渐进铺字属障眼法,用户禁止临时绕过,**未擅自做**)。
**换通道不能改善**:自动化通道一次返回、CLI 也非逐 token(且卡登录态)。
### 弹窗 UI 再收三轮(同日第十二批,用户连续反馈)
| 诉求 | 改动 | 实测 |
|---|---|---|
| 「放弃的选项 / 被选中的选项」看不明显 | `.req-opt-chip.used` 由**浅蓝底+蓝字** → **主色实底 + 白字 + ✓ + 600**;`.stale` → `#f1f3f7` 底 + **虚线边** + `#9aa3b0` 字 + opacity .85 | 三态实测:used `bg rgb(47,111,237)/color #fff/600/有✓`;stale `bg rgb(241,243,247)/color rgb(154,163,176)/dashed`;可点 `白底/深字/solid` ✓ |
| 「要完全抛弃现有选题是否有整体重置」 | **本来就有**(标题栏 `[data-reset]`),但用户没找到 → 改名 **「重置」→「清空重来」+ refresh 图标**,tooltip 改「放弃这次选题:清空对话与已填需求,从头开始」,确认文案同步;**连带修正 5 处遗留文案**(`showToast('已重置…')`、草稿恢复提示里的「点「重置」清空」、3 处注释) | 按钮 `text=清空重来 / hasIcon=true / visible` ✓ |
| 用户气泡太抢眼(主色实底) | `.req-bubble-mine` → **`--primary-soft` 底 + `--text` 字 + `1px #d7e5fd` 描边**(AI 侧本来就无气泡,左右天然可辨) | 实测 `bg rgb(234,241,254)/color rgb(36,41,47)/border rgb(215,229,253)` ✓ |
| 用户气泡与 AI 回复间距太小 | `.req-dialog { gap: 6 → 12px }` | 实测相邻 12 条消息两两间距 **全部 12px** ✓ |
- version:`style.css?v=20260916s`、`data-pages.js?v=20260916i`
- 沉淀:`工作台UI规范.md` 新增「AI创作弹窗对话区 + 候选」小节(消息间距/用户气泡/候选三态色值/只有最新一轮可点/换一批流程/清空重来 + confirm 阻塞提醒)
- ⚠️ 本轮 UI 测试同样在「做梦」草稿里累积了 12 条消息,**测试后已清空草稿**(沿用先记录 key → 测完 removeItem 的做法)
### 弹窗 UI 再收两条(同日第十三批)
| 诉求 | 改动 | 实测 |
|---|---|---|
| 「已选」候选改用**浅青色**当背景 | `.req-opt-chip.used` 由**主色实底白字** → **浅青底 `#e1f4f6` + 青字 `#0f7f8f` + 边 `#9fd8e0` + ✓ + 600**(取设计里 refresh 图标的青绿家族,保持 token 一致) | `bg rgb(225,244,246) / color rgb(15,127,143) / border rgb(159,216,224) / fw 600 / hasCheck true` ✓;stale 仍灰底虚线不变 |
| 「创作需求」文字前的**圆圈符号去掉** | 删除 `.req-sheet-box.has-filled .rst-label::before`(6px 主色小圆点)。该点是"已填"提示,与右侧 `n/8 已填` 徽章重复(徽章本身会变色)→ 删点不丢状态 | `::before content: "none"`;`has-filled` 时仍为 none;徽章 `2/8 已填` 正常 ✓ |
- version:`style.css?v=20260916t`;`工作台UI规范.md` 的候选三态行同步为浅青底,并新增「创作需求标题无前置圆点」一行。
### 弹窗 UI 第十四批:「清空重来」按钮改浅色
- 用户原话「重新开始的按钮也**用浅色样式**」——界面里**没有**「重新开始」这个文案(已 grep 确认),指的应是标题栏重置按钮(现名「清空重来」,tooltip 写"从头开始")。
- 改动:`data-reset` 的类由 `btn btn-ghost btn-sm`(白底 + 实线边)→ **`.req-reset-btn`(透明底 + 虚线细边 #cfd8e6 + `--dim` 字 + 13px + r8,hover 转主色)**,与 AI 回复里「换一批」同一视觉语言。实测 `bg transparent / border dashed rgb(207,216,230) / color rgb(107,114,128) / 92×31` ✓
- version:`style.css?v=20260916u`、`data-pages.js?v=20260916j`;UI 规范同步。
- ⚠️ 若用户本意是"纯文字无边框",说一句即可再改(当前保留虚线边以便仍可被识别为按钮)。
### 视觉交互规范成文 + 入库 IMA「视觉交互」(同日第十五批)
**诉求**:把工作台迭代过程中**所有页面样式与交互的最终状态**整理成一份规范文档,存到 IMA 知识库「视觉交互」。
**产出(1 份文档,单一权威)**:`mcn-work-shop/docs/工作台视觉交互规范.md`(**29,982 字节 / 288 行**)——由 `工作台UI规范.md` **合并升级并重命名**,旧文件已删(避免双源分叉)。
结构:§0 全局速查 → §1 设计 Token(含 AI创作弹窗专用色)→ §2 布局框架 → **§3 页面清单与最终态(9 路由逐页:首页/ranking/accounts/account:id/video:id/rewrites/reviews/files/help)** → §4 组件规范(含 AI创作弹窗四小节:结构/需求区+高度预算/对话区+候选/对比三段式)→ **§5 关键交互链路(路由与面包屑、筛选分页排序、AI 任务触发链路、AI创作弹窗状态机、缓存与刷新)** → §6 已知坑 12 条 + 排查三招 → §7 本文件变更记录(append-only)。
- 权威分工写进 §0/§5.3:入口契约指向 `AI会话任务输入输出对照.md`、调度机制指向 `自动化任务调度机制.md`,**本文件不重复定义**(避免双源)。
- 当日迭代成果全部固化为"最终态"并在 §7 记录:弹窗 960×calc(100vh−200)/需求卡单列+三档层次+实线↔虚线、对话区间距 12px+用户气泡浅色+候选三态浅青/灰虚线、换一批(连换2次强制给方向)、清空重来(浅色虚线)、去掉「创作需求」前置圆点、聚焦统一主色光圈、转发层分片拼装修复、支持达人主动要新候选。
**入库 IMA**(连接器 `ima-mcp`,只有一个连接器故无需先问;用户已明确"合并成一个文档"= 单条链路):
- 目标库:**视觉交互**(个人知识库,id `7492154893013467`,入库前 0 条)
- 链路:`create_media`(file_size=29982 / text/markdown) → **COS 上传**(skill 的 `scripts/cos_upload.py`,HTTP 200)→ `add_knowledge`(`DUPLICATE_NAME_STRATEGY_SAVE`)
- **核验**:`knowledge_total_size` **0 → 1**、`size 29982` 与文件字节数一致、标题 `短视频工作台_视觉交互规范.md`、`media_type 7`(MD)、`can_preview/can_fetch_content=true`、`media_state 1`(解析中,异步)
- 收尾:**含临时凭证的 `tools/ima_upload.json` 已删**,保留 `tools/ima_upload.result.json` 审计
**沉淀**:项目 MEMORY.md 里「UI 规范文档」指针已改为新路径 + 标注已入库 IMA。
### 新增「选题列表」(同日第十六批)
**诉求**:生成好的选题要**保存下来**,方便后续基于选题列表回看对应脚本;列表放**账号详情 tab** 里管理。
**★现状(改造前的缺口)**:选题(8 字段需求 + 时长)**只活在浏览器草稿 `localStorage` 与任务 prompt 里,从未落库** → 脚本生成后无从追溯;`rewrite_log` 虽有 `topic` 字段但常年为空;`creative_log` 是空的历史表。
**实现(4 文件)**:
| 层 | 改动 |
|---|---|
| `dsh-data.js` | 新表 **`topic_log`**(`account_id/title/req_json/rewrite_id/status/created_time/updated_time`,首次 `saveTopic` 自动 `CREATE TABLE IF NOT EXISTS`);新增 `saveTopic`(落 pending)/ `listTopics(accountId)`(LEFT JOIN rewrite_log 带 `script_title/script_len`;**表不存在时 catch 返回 []**)/ `getTopicScript(topicId)`;**`saveScript` 签名加 `topicId`**:插完 rewrite_log 后用同一连接回填选题 `rewrite_id` + `status='done'`(失败不影响脚本入库);导出 3 个新函数 |
| `server.js` | `/api/dsh/script-save` 透传 `topicId`;新增 **`POST /api/dsh/topic-save`**、**`GET /api/dsh/topics?accountId=`**、**`GET /api/dsh/topic-script?topicId=`** |
| `public/data-pages.js` | ① `saveHintOf` 支持 `topicId`(context 有值时多输出一行 `"topicId": N`)②「确认提交创作」**先 POST topic-save 拿 id 再提交任务**(失败不阻断,topicId=0)③账号详情 **新增第 4 个 tab「选题列表」**(tabs 数组 + hash 白名单 `['info','persona','analysis','topics']` + `topicsCache` 惰性拉取:`null`→`'loading'`→数组,避免重复请求)④「查看脚本」只读弹窗(`/api/dsh/topic-script` + `renderMarkdown`) |
| `index.html` | `data-pages.js?v=20260916k` |
**端到端自检(真实接口,测完即删)**:topic-save → `{ok,id:1}`;script-save 带 topicId → `{ok,id:39}`;`/api/dsh/topics?accountId=3` 命中该条且 **`rewrite_id:39 / status:'done' / script_title / script_len:81`**;`/api/dsh/topic-script?topicId=1` 返回脚本全文 81 字 ✓
**UI 实测**:`#/account/3/topics` → tab 高亮「选题列表」、表头(选题(一句话故事)/状态/时长/创建时间/操作)、行显示 `已出脚本 / 60秒 / 2026-09-16 17:59:50 / 查看脚本`、底部「共 1 条 · 选题在「提交创作」时自动保存,脚本生成后自动关联」;点「查看脚本」弹窗标题「选题脚本 · 【联调测试】脚本(测完即删)」+ 脚本正文渲染 ✓(截图 `tools/_ui_topics_tab.png`)
**清理**:测试数据已删(`rewrite_log` 28→27、`topic_log` 1→0,已核验)
**沉淀**:`AI会话任务输入输出对照.md` 新增「选题列表(09-16 新增)」节(三段链路 + topic_log 结构 + 说明"只改落库指令体、不影响入口契约,检查清单 7 项照旧");`工作台视觉交互规范.md` §3.4 补 4 tab 与选题列表规格、§5.4 第 7 步补选题保存。
**⚠️ 测试踩坑**:查弹窗时用 `document.querySelector('.modal-mask')` 命中了 DOM 里**残留的旧遮罩**("项目文件地址"设置弹窗),拿到错的 title/len → 应改用**遍历全部 `.modal-mask` 按标题匹配**(或取最后一个)。
---
### 选题列表操作分流 + 弹窗统一(同日第十七批)
**诉求**:①「查看脚本」要用**通用那个弹窗**;②先确认展示的是**选题**还是**脚本**,若为选题则弹窗应是「AI创作」同款;③选题列表要做到"可回看历史选题、复制选题继续创作新选题,**已出脚本的只能克隆、未出脚本的可编辑继续**"。
**确认结论(映射无误)**:点标题 → **选题**(8 项需求);「查看脚本」→ **脚本**(`script_text`)。原「查看脚本」是自造简易弹窗 → 按要求换成通用弹窗。
**改动(3 文件,改完 bump `style.css?v=20260916v` / `data-pages.js?v=20260916m`)**:
| 位置 | 改动 |
|---|---|
| 行内按钮 | `data-topic-view=<topic id>` → **`data-topic-script=<rewrite_id>`**(通用弹窗要的是 rewrite_id) |
| 「查看脚本」 | 删自造弹窗 → **`openScriptModal({rewriteId})`**(与账号详情/原创选题/复盘页同一套:版本条 + 源脚本/AI脚本 + 脚本诊断/分镜提示词 + 删除) |
| 「点标题」选题详情 | 重写为 **与「AI创作」同款外壳**:`.modal.req-modal` + `.req-sheet-box.open` 创作需求区(`.rst-count`「N/8 已填」)+ **8 张 `.req-field` 按 `REQ_FIELDS` 顺序铺满**(缺项 `.rf-empty`「待完善」,未知行追加在后);底部动作按状态给「编辑继续」/「复制为新选题」 |
| `style.css` | 新增 `.req-sheet-toggle.static`(只读变体去按钮态 + hover 变色) |
**状态分流(全部由 `t.rewrite_id` 驱动)**:已出脚本 → 行内「查看脚本 + 复制」、详情弹窗只给「复制为新选题」;未出脚本 → 行内「编辑继续 + 复制」、详情弹窗给「编辑继续」。**不可编辑三重防线** = 列表按钮 / 详情按钮 / `openAiFromTopic` 内 `throw`。
**UI 实测(专用 Chrome 9333,4 轮脚本,测完即删)**:
1. 列表:4 个 tab、4 行,`已出脚本 → [查看脚本,复制]` / `待创作 → [编辑继续,复制]` ✓
2. 点标题 → 选题详情:`isReqModal:true`、`创作需求 8/8 已填`、8 字段、动作 `[编辑继续]`、**w=960(与 AI创作 同宽)top 266 / bottom 265(居中)** ✓
3. 编辑继续 → AI 弹窗:`正在编辑选题 #3 · 可继续与 AI 对话修改,提交后更新该选题` + 8 项预填 ✓
4. 复制 → AI 弹窗:`从选题复制 · 提交后会生成一条新选题` + 8 项预填 ✓
5. 已出脚本详情:动作 `[复制为新选题]`、**无「编辑继续」**;点复制 → 同样进 AI 弹窗 ✓
6. 查看脚本 → 通用弹窗:右 tab `[脚本诊断, 分镜提示词]`、`.md-body` 正文、`删除` 按钮齐备 ✓
**★两处新坑(已入规范文档 §6 #13/#14)**:
- **站内 hash 跳转不重新请求文档** → 只改 `location.hash` 时 `?v=` 与刚改的代码都**看不到**(第一轮实测因此拿到旧 JS,误以为"新功能没做出来",白绕一轮)。改静态资源必须**整页重载**(`Page.reload`)再验。
- **同一文件并行下发多条 Edit 会互相覆盖**:本次 `index.html` 的 `style.css?v=` 生效、`data-pages.js?v=` 被静默吞回旧值 → **同文件多次修改必须串行**,改完回读/`curl` 校验。
**注意**:服务端静态资源带 `Cache-Control: no-store`,所以"没生效"与本机缓存无关,纯属**没重新请求文档**。
**清理**:测试选题 4 条 + 关联 `rewrite_log` 2 条已删(核对 `topic_log(acct2)=0`、`rewrite_log(acct2)=0`);临时脚本与多余截图已删,保留 `tools/_t_a_script_modal.png`、`tools/_t_b_topic_detail.png` 两张取证图。
**沉淀**:`工作台视觉交互规范.md` §3.4 重写选题列表规格、新增 **§5.6 选题列表交互**(三条链路 + 状态分流表 + 三重防线 + 铺卡铁律)、§6 补 2 条坑、§7 补变更记录;`AI会话任务输入输出对照.md`「选题列表」节补 `topic-save` 带 `id`=UPDATE / 不带=INSERT、列表接口字段、查看脚本与选题详情各自入口。