Files
mcn-short-video/.workbuddy/memory/2026-10-08.md
T
maogeigei f77735b206 工作台:目录改名 mcn-workshop + 任务进度可见 + 会话归属配置化
1. 目录 mcn-work-shop -> mcn-workshop(空间分组名取会话 cwd 的目录名,只改字符串无效,必须真改名)
2. 全仓替换 mcn-work-shop -> mcn-workshop:37 文件 121 处;历史日志按沿革句规矩保留当时目录名
3. 任务进度可见:/api/run/status 产出 已运行时长/工具调用/最近动作/停滞判定(读会话日志尾部),前端新增右下角常驻面板,四处任务入口接入
4. 会话归属目录配置化:新增 config.sessionCwd(留空=工作台自身目录),现指向 D://AI技能//mcn-workshop,使任务显示为命名分组而非「未分组任务」
5. 修前端轮询静默缺陷:连续 3 次查询失败即提示服务断开(原逻辑静默空转到 15 分钟超时,用户零感知)
2026-10-08 13:09:06 +08:00

24 KiB
Raw Blame History

2026-10-08

会话技能加载 + 项目记忆去重

  • 按用户指令加载 session-mechanism:四类必读已读(00-动手前必过.md / rules.md / manifest.md / 01-文档索引.md)+ SKILL.md 第一屏(触发句、第 0 步加载门槛、十条禁令、自决策白名单、现状地图)。
  • 内化判据:边界内自决策(技术选型/实现路径/命名/调参/部署/排查/版本/兼容降级/文档技术内容);只提报三类(功能语义分叉/红线门禁/超边界:花钱·对外承诺·要凭据)。
  • 项目 MEMORY.md 去重重组为 v4(17,841 → 17,315 B):新增 §0 两条指针(工作台 AI 通路 docs/AI链路-本地CLI接入.md、技能侧 WeKnora 调用);§2.1 补 09-29 AI 通路四条硬红线+两段流程模型来源;§4.2/§4.3 降级为「存根+硬红线」;清历史流水。

未决

  • ⚠️ MEMORY.md 体积仍会被注入截断(阈值约 10–12 KB)。解法二选一:① 维持单文件(细节自动可见,但注入截断)② 拆专题文件(不截断,但细节失去自动注入)。无客观优劣 ⇒ 待用户定。

工作台「更新榜单数据」按钮排查(功能正常,是可见性问题)

  • 现象:用户点击后「没有会话执行」。
  • 取证(四处读数):宿主库 automations 有该 once 任务(ACTIVE、next_run_at 已过期、model=hy4-preview、skills=["mcn-data-insight"]);automation_runs.status=IN_PROGRESS + automation_runtime_state.running=1(⚠️ running_conversation_id=null 是常态,不代表没起会话);sessions 已建后台会话 8a085794…(bg=1,10:07:23);会话 jsonl 283 KB 且 mtime 持续更新(10:14),工具调用 30 Bash/14 Read/4 Write ⇒ 任务真的在跑。/api/dsh/ranking-update 返回 files=104、lastUpdateAt 10:13:51 ⇒ 数据已在落盘。
  • 真因两条(都与抓取逻辑无关):① 会话 cwd = …\mcn-work-shop ⇒ 落在侧边栏 mcn-work-shop 空间分组,不在用户当前空间,需切组才可见(这是设计,非 bug);② 工作台服务作为会话后台任务被回收 ⇒ 前端轮询 /api/run/status 持续抛错。
  • 修复:public/data-pages.js updateRankingData() 轮询加失败计数 —— 连续 3 次查询失败即提示「工作台服务已断开,任务仍在后台执行」并结束轮询(原逻辑静默 continue 到 15 分钟超时,用户零感知)。
  • ⚠️ 排查方法论沉淀:判「后台任务有没有在执行」的正确取證链 = automations → automation_runs → automation_runtime_state → sessions → 会话 jsonl 的 mtime/大小。⛔ 别只看 running_conversation_id(常为 null,会误判成没执行)。

工作台目录统一改名 mcn-work-shop → mcn-workshop

  • 动因(用户):「分组已改为 mcn-workshop,需要全部替换;执行会话任务时需要按分组名称显示在会话列表」。 🔑 机制:WorkBuddy 侧边栏空间分组名 = 会话 cwd 的 basename ⇒ 只改字符串无效,必须真改名目录。
  • 执行五步:① 停服务释放句柄(否则 rename 必 WinError 5)→ ② mv mcn-work-shop mcn-workshop(成功)→ ③ 临时脚本全仓替换 mcn-work-shop→mcn-workshop:37 文件 / 121 处;⛔ 按沿革句规矩跳过 .workbuddy/memory/YYYY-MM-DD.md(16 个历史日志保留当时目录名史实)→ ④ 修 2 处被替换改坏语义的注释(server.js L1265 / L1269,原「旧 mcn-workshop/新建 mcn-workshop」被换成同词,已补回三代路径)→ ⑤ 重启验证:app.js/data-pages.js 200,data-pages.js 含 pollFail 修复。
  • ⚠️ 事实澄清(易踩):D:\AI技能\mcn-workshop 不是工作台,是 09-01 路径拼接 bug 留下的垃圾目录(3 个 0 字节文件 + outputs)。工作台本体一直在仓库内 …\V1.0\mcn-workshop。sessions 表取证:该垃圾目录下零会话;未删除会话中仅 1 条 mcn-work 相关,cwd 仍是旧 …\mcn-work-shop。
  • 净效果:新建后台会话 cwd = …\V1.0\mcn-workshop ⇒ 侧边栏分组显示 mcn-workshop ✅
  • 残留:project/…/subskills/mcn-data-insight/scripts/__pycache__/*.pyc(二进制缓存含旧串,会自行重生成,无需处理)。

追加澄清(用户真实意图,⛔ 别再理解成"目录改名")

  • 用户要的不是改目录名,而是:工作台提交 WorkBuddy 定时任务后,产生的 AI 会话应归属哪个「空间分组」。
  • 机制:分组名 = 会话 cwd 的目录名;工作台侧由 server.js 的 SESSION_CWD(当前 = 工作台自身目录)决定 ⇒ 改目录名只是让分组名变成 mcn-workshop 的手段,不是目的本身。
  • ⚠️ 存量不掉头:10:07 那条榜单更新任务 cwd 仍是旧 …\mcn-work-shop ⇒ 显示在旧分组;改名后新建的任务才落到 mcn-workshop。清理用的 SESSION_CWD_PATTERN='%mcn-work%' 覆盖新旧三代,不受影响。
  • 待用户定(功能语义分叉):① 维持工作台专属分组 ② 归入用户当前主项目分组 ③ 自定义独立分组(需目录真实存在且在 workspaces 登记,08-27 即此法)。可选项:把 SESSION_CWD 提升为 config.json 可配字段,换分组只改配置不动代码。

后台任务进度可见(用户:「我需要看到 才知道执行是否正常」)

  • 真需求:不是分组放哪,而是在工作台内直接看到执行状态,判断在跑还是卡住、做了什么。
  • 后端 server.js /api/run/status 增强:automation → 关联它拉起的后台会话(sessions.is_background_automation=1 且创建时间落在任务创建 −15s~+300s)→ 读该会话 jsonl 尾部 256 KB → 新增字段 elapsedMs / sessionId / sessionTitle / lastAction(最近一段文本,截断 160 字)/ toolCalls(按工具名计数)/ updatedAgoMs / stalled(>90 s 无新输出)/ logBytes。
    • ⭐ 会话日志路径换算(可复用):cwd → projects 目录名 = 盘符小写 + 分隔符全转 -(escapeCwdForProjects());基目录 <workbuddy>/projects/<转义名>/<sessionId>.jsonl。
    • ⚠️ stalled 只在 state=running 时有意义(已完成任务日志当然不再写入,会恒 true)。
  • 前端新增 window.TaskProgress(实现在 public/app.js,样式 style.css 的 .tp-*):右下角常驻面板 = 状态/已运行时长/工具调用/最近动作/停滞警告。四处轮询点全接入:app.js executeTask、data-pages.js 的榜单更新/批量更新账号/视频解析。终态保留 8 秒自动收起,运行超时则保留供继续观察。
  • 验证:三文件 node --check 全过;服务起来后 app.js 含 6 处、data-pages.js 含 9 处 TaskProgress,style.css 含 .tp-panel;状态接口返回完整进度字段。

✅ 分组归属定案:就用 mcn-workshop 文件夹对应的分组(已实测)

  • 用户拍板:任务会话归到 mcn-workshop 文件夹对应的那个分组。
  • 实测(提交轻量自检任务取证):新会话 cwd = …\V1.0\mcn-workshop ✅;对照 10:07 那条旧榜单任务仍是 …\mcn-work-shop(两者在侧边栏分属不同分组,属正常存量,不用管)。
  • 结论:不需要再改代码 —— SESSION_CWD = ROOT,目录改名后自动生效。自检任务已删排期。
  • ⚠️ 认知要点:侧边栏分组按 完整 cwd 聚合,不是按文件夹名合并 ⇒ 同名不同路径会是两个分组。

⚠️ 更正(12:2x):分组靠 cwd 命中已打开的工作区,光改目录名不够

  • 上一条只对了一半:目录改名后会话 cwd 是仓库内 …\V1.0\mcn-workshop,不是用户的工作区 ⇒ 仍显示在「未分组任务」区域(用户实测反馈)。
  • 用户纠正:D:\AI技能\mcn-workshop 才是那个工作区。我此前仅凭目录里只有 3 个 0 字节垃圾文件就判它"是垃圾目录"——没查登记表就下结论,违反「判状态先问程序自己」。
  • 🔑 真机制:侧边栏分组 = 会话 cwd 命中已打开过的工作区才显示为命名分组;没命中 ⇒ 落「未分组任务」。
    • 取证:workspaces 表仅 7 行且全是 C:\Users\maidou\WorkBuddy\<时间戳>,不含任何 D:\AI技能\* ⇒ 分组依据不是这张表,而是按会话 cwd 对已打开工作区的聚合。
  • 修法(配置化,⛔ 不写死):load-config.js 增 sessionCwd(默认 '' = 用 ROOT)→ server.js SESSION_CWD = String(CFG.sessionCwd||'').trim() || ROOT → config.json 设 "sessionCwd": "D:\\AI技能\\mcn-workshop"。换分组只改配置,不动代码。
  • 实测:新会话 cwd = D:/AI技能/mcn-workshop ✅;任务在该工作区执行正常(done,结果"成功",73 秒)。对照 12:23 那条仍在仓库内路径 ⇒ 两组并存,旧的会随过期清理消失。
  • ✅ 13:06 二次模拟请求复验一致(用户指示:不测真实功能,只发模拟请求看分组):写入 cwds=["D:\\AI技能\\mcn-workshop"],会话 cwd 同样命中 ⇒ 配置化改法稳定。两次自检排期均已删,会话留在目标工作区供用户肉眼确认。

素材库补采:批 65 收尾 + 批 66/67 完成(30 卡)

  • 承 09-29 进度:批 65(细节专业 15 卡)已 apply 完成,细节专业 40→55。
  • 批 66(细节专业 15 卡):取材 31748 姜乘澜底妆 / 17511 笑笑易 / 19014 俊希做菜 / 24821 烟道逃生 / 25090 姜乘澜画眼线。✅ 本批 5 条原生即教程/实操题材,与细节专业天然契合(不像批 65 从非专业题材硬提)。apply:接受 15/退回 0,问法改写 15 张平均 +32 字。细节专业 55→70。
  • 批 67(自嘲反差 15 卡):取材 26484 路之坑爹感恩宴 / 31816 直男五合一洗护 / 31970 李普不离谱 / 21500 桃气小周买饭 / 26411 老弟受难日记。含 1 张元层面自黑卡(31970 全家崩溃时推销泡面)。apply:接受 15/退回 0,问法改写 15 张平均 +12 字。自嘲反差 56→71。
  • 两批均走完整链路:写 md → _tmp_bNN_spec.py 生成 spec → meta.json → build-pending → cat PROMPT_polish_v3.md + build-pending 组装 prompt → 派 doubao-seed-2-1-pro → _wNN.py 校验落盘 → apply-pending。

本轮新踩坑

  • ⚠️ MCP myai-mcp-production 登录态会过期:批 66 拉第 4 条时报「认证失败」。解法:先 auth_status 确认 → feishu_login 重授权(拉起浏览器)→ 重试即通。连续拉多条详情时中途要留意。
  • ⚠️ spec 脚本里别夹英文单词:批 66 的 neg 句误写「等摊主 processing」,批量产出会污染语料。写完 spec 脚本前先自查。

当前缺口(修正后口径,2026-10-08 10:50)

标签 现有 缺口 候选
食材极致 8 92 ⛔ 0
预见式服务 21 79 ⛔ 2
感官沉浸 59 41 14
细节专业 70 30 22
自嘲反差 71 29 34
视觉冲击 76 24 10

达标:品质对比 110 / 氛围沉浸 106 / 反差 217 / 反常识 128 / 价值观冲击 108。

  • ⛔ 卡点未解:食材极致(缺口 92)与 预见式服务(缺口 79)候选池近乎空,占剩余缺口一半以上。需换关键词或换捞法才能推进。
  • 暂存批累计 24 批(43–52、54–67,缺 53)。

补采续跑:批 68(感官沉浸 15 卡)/批 69(细节专业 9 卡)

批 68 · 感官沉浸(33289 子杭自驾318 ×6 / 31773 萝卜乔乔英国留学回国 ×6 / 30090 姐弟双向送礼 ×3)

  • apply 结果:接受 15/退回 0,问法改写 15 张,平均 +19 字。感官沉浸 59 → 74。
  • ⭐ 两条来源 0 卡,已在 md 写明判据:28012(电焊工试戏)男主嘴配的「滋滋」是谐音梗的音效而非真实声音质感,事件主角是"身在曹营心在焊" → 归 反常识/自嘲反差;28415(男朋友的算计)踩碎眼镜/摔筷子/拍桌的动静是发疯甩锅的附产品 → 归 反差/价值观冲击。
  • 感官通道分布齐全(冷/缺氧失眠/冰雹砸车/撕羊腿/热水澡/久坐腰酸 · 热瓶/苦到脸垮/中药味/红米肠/赶机喘/长途疲惫 · 中暑虚脱/猛灌水/红糖蛋滋啦)。

批 69 · 细节专业(28328 海鲜蒸汽 ×4 / 37316 巧克力棒手作 ×5)= 9 卡

  • apply 结果:接受 9/退回 0,问法改写 9 张,平均 +20 字。细节专业 70 → 79。
  • ⭐ 本批 3 条来源 0 卡,坚持不凑数(沿用批 56 口径):
    • 20461(机票骗局)—— 骗子的"专业"是话术与骗术设计(伪装客服、真退票取信、连环索要卡号),不落在"这一下换普通人来做就做不到位"的操作细节上 → 反差/反常识。这是细节专业最容易误判的一类:话术专业 ≠ 操作专业。
    • 24820(烟道脱困)—— 主角是作死翻车与体力消耗,片尾"专业人士、专业场地、专业操作"是反讽 → 自嘲反差/难度极限;且同账号同题材 24821 已在批 66 取过两卡,本条脱困手法同构,不重复入库。
    • 22163(轮椅游渔岛)—— 倒拖轮椅过软沙滩属体力付出 → 难度极限;其余为情侣互坑 → 反差/自嘲反差。
  • ⭐ 取批命中率下降的信号:细节专业候选池看着有 22 条,但主队列取 5 条只有 2 条可用(命中率 40%)。后续该标签每批卡数会低于 15,属正常,不要为了凑 15 张硬塞。

新增踩坑与复用做法

  • ✅ _wNN.py 用 sed 复用(sed -e 's/_raw68/_raw69/g' -e 's/pending_0068/pending_0069/g' -e 's/^N = 15/N = 9/' _w68.py > _w69.py)—— 卡数变化时记得同步改 N。本轮连续 3 批(67/68/69)一次通过,bad: []。
  • ✅ 超长详情自动落盘:33289 返回 88,150 字符超限 → 工具落盘到 D:\.workbuddy\projects\d-AI技能-mcn-short-video\<sessionId>\tool-results\*.txt,用 Read 直接读(该文件只有 117 行,一次读完)。
  • ⚠️ 派模型改用「让 Agent 自己 Read prompt 文件 → 自己 Write 落盘 _rawNN.txt」——比让模型把 JSON 回吐到对话再手工落盘更省上下文,连续 3 批稳定。

当前缺口(批 69 后):自嘲反差 29(候选 34)|感官沉浸 26(候选 14)|视觉冲击 24(候选 10)|细节专业 21(候选 22)。食材极致 92/预见式服务 79 仍挂起(用户 2026-10-08 决策:先不处理)。

批 70(自嘲反差 15 卡)· 本轮第 5 批 → 复核点

结果:接受 15/退回 0,问法改写 15 张,平均 +27 字(前几批 +19/+20,本批问法增厚更充分)。自嘲反差 71→86(缺口 14)。 来源:35376 唐轩乌龙×6 | 35301 丁浩普信男×6 | 28146 妈妈硬核推理×3。5 条视频里 2 条 0 卡(33593、21923)。

⭐ 自嘲反差口径新增形态「姿态过载」(本批确立):

  • 定义:主角自己把一件小事升格到远超其体量的规格,且全程一本正经(妈妈把女儿回家晚做成刑侦审讯:北风4级/100米/11分37秒 vs 6点12分39秒)。
  • 判据仍落回一句话:笑点落在主角自己身上。妈妈是主角、推理的荒谬感由她自己一本正经地制造 → 收。
  • ⛔ 反向凡尔赛揭晓(语数英 100/98/100 + 兑现平板)→ 笑点在预期被颠覆 → 反常识;儿子 O 型嘴石化 → 笑点落在旁观者受击 → 反差(世界参差)。均不收。

两条 0 卡判据(写入 meta):

  • 33593(张开父子的下场):家族护短复仇爽剧,爽点落在反派父子被制裁上,主角阵营全程降维打击,无一处笑点落在自己身上 → 反差/价值观冲击。其「悲痛段落硬塞洗面奶口播」虽属元层面自黑,但批 67 已收同构卡(C1 全家崩溃时推销泡面)→ 不重复入库。
  • 21923(消防设施瘫痪的代价):真实事件改编的沉重社会悲剧(烟花引火→消防栓被锁→接头拧不上→母亲丧生→儿子一夜白头),全片无笑点 → 价值观冲击。
  • ⭐ 通用判据沉淀:沉重社会悲剧类一律不进自嘲反差;元层面自黑要查是否已收同构卡(批 67 已占一类)。

其他弃卡判据:35376「你那算盘珠子都崩我脸上了」是吐槽他人 → 反差;「我没吃过我妈包的包子」与「我妈不会做饭」是同一场乌龙的两端 → 分作「立 flag」与「揭盅」两卡,不合并(同批 67 B2/B3/B4 细分做法)。35301 防晒植入段属商业植入;丽丽怒骂并入 B4 不单列。

本轮 5 批(66–70)合计 69 卡:66=15 | 67=15(自嘲反差)| 68=15(感官沉浸)| 69=9(细节专业,不凑数)| 70=15(自嘲反差)。 当前缺口(批 70 后):感官沉浸 26(候选 14)→ 视觉冲击 24(10)→ 细节专业 21(22)→ 自嘲反差 14(34)。食材极致 92/预见式服务 79 挂起。 体检:5_tag_coverage.py 卡片总数 1017(源文件 69 个),12 维无自造标签;⛔ 零覆盖仅 难度极限(用户决策不处理),⚠️ 偏少仅 食材极致(8,挂起)。

复核抽查:批 70 卡 6(哭着嚼坚果上供)润色生效——台词前置 + 破折号拍点(「我以后再也不养小仓鼠了,我对不起你」——唐轩把相框平放在桌上…),锁定 4 字段零改动,无编造。spec 回写 sim=3/neg=2、tag 单一、src 3 个,全部符合。

⭐ 入库状态核查(用户问「素材都同步到 wekonra 了吗」→ 答案:没有,两层原因)

  • 流程层:按暂存模式,补采只落 batches/pending_import/,统一入库必须跑 13_import_pending.py --run。截至批 70,27 批 397 卡全部堆在暂存区,一条都没进库(13_import_pending.py --help 盘点:27 批/397 卡/异常 0)。batches/*.md 41 批(早期跑过 2_import_batch.py 的)是唯一进过库的部分。
  • 环境层:WeKnora-app 容器 Exited (127),最后一条日志停在 2026-09-29 23:53(health 200)→ 31607 端口不通,连"库里现有多少条"都查不了。同项目其余容器(frontend 24719 / docreader / postgres / redis)都在跑。整个 10-08 的补采从未连过库。
  • 部署信息:镜像 wechatopenai/weknora-app:latest,restart unless-stopped,compose 工作目录标签 /home/maidou/weknora(WSL 路径,本机 docker ps -a 可见)。拉起命令 docker start WeKnora-app;若仍 127 需查 compose 的 command/entrypoint。
  • 回炉链路同样未完成:「删旧条目 + 重导 + 检索终验」都还没做;回炉批 31–33 也未跑完。
  • ⚠️ 排查口诀补充:问「同步了吗」时先查两处——① 13_import_pending.py --help 看暂存盘点 ② docker ps -a 看 WeKnora-app 是否 Up。两者都要看,只查一处会误判。

⭐ 规则核对:入库前必须补全 question(用户 2026-10-08 追问「是否遵循」→ 核查 27 批结论)

  • 规则依据(能查到的最强出处):RUNBOOK §步骤 6「写 spec.json(检索问法)」=流水线必经步骤;真正的动机在 RUNBOOK 红线:「追加相似问不重建索引(POST /faq/entries/{id}/similar-questions 返回 200 但向量分数按位不变)→ 要改问法只能删 + 重导」。所以「入库前补全」不是形式要求,而是事后补的代价=整批删+重导。
  • ⚠️ 未找到该规则的原始对话出处:conversation_search 两次 0 命中,本地 memory / RUNBOOK 也没有「入库前要补全 question」这句原话。已按「规范 + 红线」等价认定,未擅自当作既有明文规则引用。
  • 核查结论(27 批全量):全部有 spec.json、std 全部非空 → 形式上 100% 遵循。但有 2 批偏离现行规范:
    批 偏离 范围
    43 neg=3 条(现行应为 2),且内容是关键词短语(「白酒带货 / 餐厅推荐 / 商务礼仪培训」)不是问句 15/15 卡
    48 sim=2 条(现行应为 3) 15/15 卡
    其余 25 批:sim=3(批 47 起)或 sim=6(批 44/45/46,合旧规范)/neg=2,全部合规。
  • ⚠️ 文档与执行脱节(待用户裁定):RUNBOOK §步骤 6 明文写 sim「口语问法 4–6 条」,但批 47 起实际统一为 3 条(_wNN.py 校验也写死 != 3)。要么改文档、要么把 sim 补回 ≥4 条。
  • ⭐ 核查脚本口诀:glob('batches/pending_import/batch_*.spec.json') 逐批 Counter(len(x['sim'])) + Counter(len(x['neg'])) 打分布表,一眼看出条数偏离;别用 md 的 ```text 计数 //2 算卡数(会算成一半,以 spec 长度为准)。

⭐ Docker WeKnora 启动失败排查(2026-10-08 · 已修复)

  • 根因(不是应用崩溃,是容器 init 前的 bind mount 失败):docker inspect WeKnora-app 的 .State.Error 给出原文—— OCI runtime create failed: runc create failed: ... error mounting "/run/desktop/mnt/host/wsl/docker-desktop-bind-mounts/Ubuntu-24.04/4f4eee8c…" to rootfs at "/app/config/config.yaml": not a directory: Are you trying to mount a directory onto a file (or vice-versa)?
  • 链路:compose 写 ./config/config.yaml:/app/config/config.yaml(文件→文件,写法正确,源文件 /home/maidou/weknora/config/config.yaml 确实存在且是 6545 B 的文件)→ 但 Docker Desktop 的 bind-mount 代理层(WSL 9P 中转,路径被哈希成 4f4eee8c…)把源识别成了目录 → 挂载失败 → 容器连 init 都没进 → Exit 127(entrypoint ./scripts/docker-entrypoint.sh 根本没执行)。
  • 时间线:StartedAt 09-28 01:45,FinishedAt 10-08 02:51 —— 正常跑了 10 天,今天凌晨有一次重启尝试(Docker Desktop/WSL 层变动)时代理层状态不对而失败。restart unless-stopped 不会救「启动失败」,所以一直停在 Exited。
  • ✅ 修复:docker start WeKnora-app 一次即恢复(Up (healthy),31607 通)→ 属代理层临时状态问题,重试可解。复发时的升级路径:重启 Docker Desktop → docker compose up -d 重建容器(会换新的代理哈希)。治本方向:单文件 bind mount 跨 WSL 本就脆弱,可改 docker cp 或 volume。
  • ⭐ 排查口诀:容器 Exited(127) 先看 docker inspect --format '{{.State.Error}}',不要只看 docker logs(日志只到上次正常运行,看不出启动失败原因)。本次日志最后一条停在 09-29 23:53 health 200,完全看不出问题,是 inspect 的 State.Error 直接给出根因。

库内实测(服务恢复后)

  • FAQ 总数 631(分页抖动,去重拉取 624)。问法 100% 齐全:无 std 0 / 无 sim 0 / 无 neg 0。
  • sim 条数分布 {5:312, 6:222, 3:46, 2:30, 4:14}、neg {2:542, 3:82} —— 历史口径混着(旧 5/6 条、现 3 条、少量 2 条)。
  • 库内 tag_name 分布:反差 172/反常识 117/价值观冲击 93/视觉冲击 67/自嘲反差 44/细节专业 32/感官沉浸 26/氛围沉浸 24/品质对比 19/预见式服务 19/食材极致 9/难度极限 2 → 与本地统计一致,即已入库 = 早期 41 批;暂存 27 批 397 卡确实未进。
  • ⚠️ 接口结构坑:FAQ 列表返回是 data.data({data:{total,page,page_size,data:[...]}})两层嵌套,只取一层会得到空列表;条目标签字段是 tag_name(不是 tag/tags);page_size=total 一次拉全会返回空 → 必须分页 100 逐页 + 按 id 去重。

新增踩坑

  • ⚠️ _tmp_bNN_spec.py 里卡片名提取必须 .replace("###",""):head.split("|")[0].strip() 会带 ### 前缀 → assert name in Q 报 AssertionError: ### 吃包子吃出丧母感。批 70 踩到一次,加 replace 后通过。
  • ✅ prompt 组装字节数核对:模板 7,683 + 载荷 34,647 = 42,330(wc -c 可验),比批 68 记录的 15,772 大是因当时统计口径不同,以 wc -c 为准。