对话笔记直发:8.16 公众号落盘改造与hermes手动发布衔接。分类:AI工程。


tags:

  • 公众号
  • wechat
  • fns
  • obsidian
  • publish-pipeline
  • skill
  • telegram
  • hermes
  • 自动化
  • 落盘 title: 公众号落盘改造与 hermes 手动发布衔接 date: 2026-08-16

公众号落盘改造与 hermes 手动发布衔接

全程目标:让云服务器 Hermes(你的服务器IP(已脱敏))公众号发布流水线与 Telegram 交互式 hermes 全面对齐——统一 FNS 落盘到 000_Raw/10_项目/公众号/文章/ 子目录,并让 hermes 手动写文时复用已验证的 publish_pipeline.py 确定性管线,保证”确认稿 = 推送稿”。

一、环境基线(已做脱敏)

  • 云服务器:你的服务器IP(已脱敏)(Hermes,/opt/data 为主工作目录),脚本用 /opt/data/.venv/bin/python、Node v22 在 /opt/data/.nvm/versions/node/v22.23.2/bin/。
  • 公众号发布流水线:/opt/data/scripts/publish_pipeline.py(cron job3 调用,publish_wrapper.sh 入口)→ humanize → LLM 改写(stepfun)→ render_fixed 排版 → 合规门 → no-text 封面 → FNS 写盘 → publish-file 推微信草稿箱 → Telegram 回报。
  • 微信草稿箱:个人订阅号无 freepublish,只能建草稿人工群发。凭证 /opt/data/.wechat-publisher/config.json(600)。
  • FNS(Fast Note Sync):https://notes.unixcs.eu.org,vault feng,token 缓存 /opt/data/.fns-token.json,User-Agent 绑定 Mozilla/5.0 (hermes-cron fns-writer)。
  • skill:wechat-publish-workflow(v2.1.0 → 2.2.0)、wechat-publisher、gzh-design、byted-web-search 均已注册启用。

二、本次会话累计变更清单

1. 落盘路径统一到 文章/ 子目录

  • 用户要求:FNS 落盘统一改到 000_Raw/10_项目/公众号/文章/ 子目录(cron 与 hermes 手动都统一),文件名 文章/{标题}.md(中文标题风格,与既有 3 篇一致)。
  • 子代理两轮评审:初版【否决】(M1–M8),修正后再次【否决】(R1–R3,argv 解析、确认稿漂移、DELETE 端点),第三次【通过】后实施。

2. fns_write.py 改造

  • 新增 ALLOWED_SUBDIR = "文章/",write_note 校验放宽支持 文章/ 子目录;裸 文章(不带尾斜杠)精确拒绝,防与目录同名笔记污染。
  • 子路径校验:非空、不含 /、反斜杠、%、..、不以 . 开头(防 .md 隐藏文件)。
  • 新增 delete_note(full_path) + CLI --delete:DELETE /api/note?path=<quote(safe="/")>&vault=feng,统一 UA + token 缓存。
  • 顺手修复既有 bug:DELETE 请求若带 Content-Type: application/json,服务端不解析 query(报 305 Invalid Params);_req 对 DELETE 不再设该头。

3. publish_pipeline.py 改造(v2)

  • 三形态参数解析(argparse 替换 len(sys.argv)!=2 守卫):
    • publish_pipeline.py <digest.md>(默认,读全局 .publish-mode)
    • publish_pipeline.py --mode auto|manual <digest.md>(显式覆盖)
    • publish_pipeline.py --resume <manifest.json>(复用 MANIFEST 产物,只推草稿+TG,不重跑 LLM/渲染/封面)
  • 新增 sanitize_title(title, date) 产出独立 safe_title(显示 title 不受污染):去 /\:*?"<>|#%& + 控制符 + 全角空格、折叠空白、去尾部 . 和 …、空串回退 AI日报_{date}。
  • FNS 写盘上移到 manual 分支之前:manual 也落盘 文章/{标题}.md,仅 publish 被 hold 并产出 MANIFEST。
  • MANIFEST 补字段:safe_title、clean_md、date、publish_cmd。

4. publish_wrapper.sh(cron 入口)

  • 改为 exec ... --mode auto "$DIGEST",cron 显式 auto,不再依赖全局 .publish-mode 文件(防 hermes 手动串扰导致 cron 静默变 manual)。

5. SKILL.md wechat-publish-workflow v2.2.0

  • 新增”手动发布路径(复用自动管线)“章节:两段确认流程(产稿→--mode manual→成品确认→--resume),明确 manual→resume 之间不得清理 out_*/ 与 MANIFEST。

三、本次执行细节(测试验收)

测试1 fns_write 单测

  • 写 文章/测试标题.md ✅、根目录兼容形态 ✅
  • 边界全拒:文章/..x、文章/.md、文章/文章/x.md、文章(裸)、文章/../x.md、Compat_x/y.md 全 ERR ✅
  • --delete 往返:写→删→再删报 “Note does not exist” ✅
  • 修复后 文章/ 目录污染清理干净。

测试2 manual 冒烟

  • --mode manual digest_part1_models.md:humanize OK → LLM rewrite OK(1477 字)→ render rc=0 → validate+placeholder OK → cover OK → FNS_OK 落盘 文章/今日 AI 大模型动态(2026-08-15 AIHOT 日报.md→ MANIFEST 产出,不推微信 ✅
  • sanitize 初版保留 … 导致文件名 ….md,已改为剥尾部 …(纯观感)。

测试3 resume 冒烟

  • --resume manifest_...json:RESUME 日志(无 humanize/LLM/render/cover 步骤)→ publish rc=0 → DRAFT_OK(media_id)→ TG_OK → 确认稿=推送稿(复用同一 html 路径)✅

测试4 cron 回归(wrapper --mode auto)

  • 完整链路:humanize→LLM(1415 字)→render→cover→FNS 落盘(覆盖写幂等)→publish→TG_OK ✅

清理

  • 微信草稿箱 5 篇测试草稿全删(4 篇”今日 AI 大模型动态…” + 1 篇”123”),目前 0 篇。
  • FNS 测试笔记全删;main/ 与 文章/ 均只留用户原有笔记。
  • /opt/data/linuxdo_daily/work/ 测试产物清空并重建(700 权限)。
  • 服务器 4 文件与本地版本 diff 全部 identical。

四、当前状态(全量对账)

组件状态
fns_write.py支持 文章/ 子目录 + --delete + DELETE Content-Type 修复 ✅
publish_pipeline.py三形态解析 + sanitize + FNS 上移 manual + resume ✅
publish_wrapper.shcron 显式 --mode auto ✅
SKILL.md v2.2.0手动发布路径章节 ✅
微信草稿箱0 篇(干净)
FNS 文章/仅用户 3 篇 ✅
cron job3改后publish_wrapper.sh 显式 auto 回归通过 ✅
  • 备份:/opt/data/backups/wxpub_chg_20260816_011549/(改动前 4 文件)。
  • .publish-mode 文件保留(兼容/调试),当前值为 auto。

五、待办

  • 上线验证:在 Telegram 对 hermes 说”写一篇公众号文章并发布到草稿箱”,验证手动路径端到端(产稿→manual→确认→resume→草稿箱)。
  • 观察 cron 每日自动发布(job3 wrapper 显式 auto)前几轮是否稳定。
  • (可选)draft_link(http://mp.weixin.qq.com/s?...media_id=...#rd)有效性待验证,暂未列入本次范围。
  • (可选,范围外)fns_write.py 明文硬编码 PASSWORD,建议日后移入环境变量/密钥文件。

六、回滚与风险备忘

  • 回滚:/opt/data/backups/wxpub_chg_20260816_011549/ 内有改动前 4 文件,直接 scp 回 /opt/data/scripts/ 与 /opt/data/skills/wechat-publish-workflow/ 即可。
  • DELETE 若报 305 Invalid Params:确认是否又引入了 Content-Type(DELETE 不应带该头)。
  • FNS 401 “Browser (UA) restricted”:所有请求必须同一 UA Mozilla/5.0 (hermes-cron fns-writer)。
  • --mode manual 产物必须先展示用户确认再 --resume;确认期间不得清 out_*/ 与 MANIFEST。

七、Hermes 对齐诊断与《对齐文档》落盘(同日追加)

场景:用户在 Telegram 让 Hermes”推送到公众号草稿箱”,Hermes 回复”不知道如何推送、缺少公众号 AppID 和 Key、发布半截从没搭过”。经调查:非权限问题、非未搭好,是 Hermes 认知缺失。

1. 根因诊断(实测证据)

  • Hermes gateway 真实进程:hermes 用户(uid 997)、HOME=/opt/data、HERMES_HOME=/opt/data(曾误判 HOME=/root,系 pgrep 误匹配到自身 bash)。
  • 以 hermes 用户实测:读 /opt/data/.wechat-publisher/config.json ✅、auth → token valid(7072s)✅、draft list 正常 ✅。
  • .openclaw 目录不存在,不劫持 DATA_DIR;凭证解析命中 /opt/data/.wechat-publisher/config.json。
  • 结论:公众号后半截(凭证/发布脚本/cron)已全部搭好且 hermes 可访问。Hermes 报缺凭证是因为它查环境变量 WECHAT_APP_ID/WECHAT_APP_SECRET(.env 无),没去读 config.json——纯认知问题。
  • 风险提示:不能放任 Hermes”给我凭证重新写脚本”——会重复造轮子、可能破坏已跑通的 job3 管线。应让它复用 publish_pipeline.py。

2. 对齐方案落地

  • 用户倾向:生成一篇 Markdown 文档存 Obsidian,让 Hermes 读取快速对齐。
  • 调查发现 Hermes 无 FNS/Obsidian 读取能力(skills 无对应项),但可直接读本地文件(/opt/data 属主)。故双落点:本地技能目录 + FNS sop。

3. 产物

  • 《公众号发布链路_对齐.md》(8.2KB,§1-7:现状结论/环境事实/已搭链路/pipeline 三用法/操作指引/错误速查/运营提醒,凭证只写路径不写明文 secret):
    1. 本地:/opt/data/skills/wechat-publish-workflow/公众号发布链路_对齐.md(hermes 属主、644,与 enabled skill 同目录)
    2. FNS:000_Raw/10_项目/公众号/sop/公众号发布链路_对齐.md(id 2788)

4. 顺带改动:fns_write.py 白名单扩展

  • ALLOWED_SUBDIR(单值)→ ALLOWED_SUBDIRS(元组 ("文章/", "sop/")),_check_rel 遍历匹

注:本文涉及的服务器公网 IP / Tailnet / 局域网 IP 已脱敏,请替换为你自己的地址。


相关: 00-索引-AI工程索引 8.13 公众号发布工作流v5 Hermes接手文档