对话笔记直发:8.13 公众号发布工作流v5 Hermes接手文档。分类:AI工程。
title: 公众号发布工作流v5 Hermes接手文档 tags: [公众号, Hermes, 接手文档, 对抗式审查, 测试验收, 排障, wechat-publish-workflow] date: 2026-08-13
公众号发布工作流 v5 —— Hermes 接手文档(对抗式审查后定稿)
本文是 jp(
局域网IP(已脱敏))上 Hermes 接手公众号发布工作流的唯一权威对齐说明。所有命令可直接复制执行。核心编排源:/opt/data/skills/wechat-publish-workflow/SKILL.md(hermes 重启后第一个要读的文件)。
1. 系统与账号事实
| 项 | 值 |
|---|---|
| 服务器 | jp,局域网IP(已脱敏),ssh root@局域网IP(已脱敏)“ |
| hermes 用户 | uid/gid 10000,groups: hermes/openclaw/docker;HOME=/opt/data |
| 微信 AppID | wx9312cd6cc49653f0 |
| 账号类型 | 个人订阅号 → 无 freepublish,只能建草稿、人工后台群发 |
| 出口 IP | 已配微信白名单 |
| 生图模型 | step-image-edit-2(stepfun),base_url https://api.stepfun.com/step_plan/v1 |
| Node | /usr/bin/node v22.23.1(node:sqlite 可用,ExperimentalWarning 属正常) |
| Pillow | 12.2.0,装于 /opt/hermes/.venv/bin/python(系统 python3 无 PIL) |
| 时区 | Asia/Shanghai (CST+8),与 token 缓存时钟一致 |
2. 关键路径总表
| 物 | 路径 |
|---|---|
| 编排层(唯一权威) | /opt/data/skills/wechat-publish-workflow/SKILL.md |
| 封面 AI 生成/归一化 | /opt/data/skills/wechat-publish-workflow/scripts/gzh_cover.py |
| 固定CSS渲染器 | /opt/data/skills/wechat-publish-workflow/scripts/render_fixed.py |
| 占位符硬门 | /opt/data/skills/wechat-publish-workflow/scripts/check_placeholder.sh |
| 主题存档(存档非源) | /opt/data/skills/wechat-publish-workflow/references/fixed-business.css.md |
| v4 备份 | /opt/data/skills/wechat-publish-workflow/SKILL.md.v4.bak |
| peterpan 推送工具 | /opt/data/skills/wechat-publisher/wechat-publisher.mjs(1132 行) |
| 微信凭证 | /opt/data/.wechat-publisher/config.json(600,勿外泄/勿入日志) |
| 生图凭证 | /opt/data/.wechat-publisher/stepfun.json(600,勿外泄/勿入日志) |
| 状态文件 | /opt/data/.wechat-publisher/{token.json,upload-cache.json,drafts.db}(hermes 可写) |
| gzh-design 备选排版 skill | /opt/data/skills/gzh-design/SKILL.md + scripts/validate_gzh_html.py |
3. 铁律(hermes 必须遵守)
- 单推送出口:微信副作用(建草稿/传素材)只允许经 peterpan 的
publish-file/upload-cover/upload-image。禁止 md2wechat--upload/--draft、禁止手写 curl 调微信 API(排除障探测)。 - 排版合规门:交付 HTML 必须 0 ERROR(validate_gzh_html.py)+ 全路径
{{占位符}}硬门(check_placeholder.sh)过关。不得跳过。 - 封面必填:
publish-file --thumb只接受本地图片文件路径(peterpan 内部existsSync判断;传 media_id 字符串 → 静默回退成首张正文图或空 → 40007/40013)。封面 jpg 路径直接传--thumb,peterpan 自动上传并按文件 hash 去重缓存(upload-cover提前传也无害但非必需)。 - 去AI味必做:正式发文前必须
md2wechat humanize <draft.md>(等号形式)取回 prompt 由 LLM 执行后合并。
4. 标准执行步骤(默认路线,逐条命令)
Step 1 写稿
- 产出 Markdown 初稿到 hermes 可写目录(如
/opt/data/工作流/_tmp/,或/tmp)。 - 初稿先发用户确认(铁律5)。
- 正文(含代码示例)不要出现
{{作者名}}/{{简介}}这两个保留 token,示例占位请改写为{{cmd}}之类一般 token。
Step 2 去AI味
md2wechat humanize 稿子.md --intensity=medium必须等号形式。空格形式
--intensity medium会报accepts 1 arg(s), received 2。 解析 JSON:status=="action_required"时取data.request.content,LLM 按 prompt 重写正文,写回稿子.humanized.md。 必须检查success/status字段,success!=true视为失败(进程可能 exit 0)。
Step 3 排版
默认固定CSS确定性渲染:
/opt/hermes/.venv/bin/python /opt/data/skills/wechat-publish-workflow/scripts/render_fixed.py <稿.md> --out <dir> --name <名> [--author 作者名] [--intro 简介]- 产物命名:
{名}_排版_固定商务(fixed-business).html - 自带 validate 0 ERROR + check_placeholder.sh 自检
- 占位符
{{作者名}}/{{简介}}未传对应参数 → fail-fast 退出、不产出文件 - 用户消息中出现
skill排版/用skill→ 走 gzh-design skill(产物同样要过硬门)
Step 4 合规门
- render_fixed 产物自带;gzh-design 路径产物手动补跑:
bash /opt/data/skills/wechat-publish-workflow/scripts/check_placeholder.sh <产物.html>validate_gzh_html.py校验:报 ERROR 必须回头修。
Step 5 封面(三分支)
前置:凭证 /opt/data/.wechat-publisher/stepfun.json。
# 统一格式(务必带 --out/--name,默认会写 /tmp/gzh_cover_out/cover_*.jpg 也好用但建议显式)
/opt/hermes/.venv/bin/python .../gzh_cover.py --out <dir> --name <名> --hint "<一句话概要>" # 默认:无文字+moren
/opt/hermes/.venv/bin/python .../gzh_cover.py --out <dir> --name <名> --text "<文字>" # 文字+moren
/opt/hermes/.venv/bin/python .../gzh_cover.py --out <dir> --name <名> --text ... --style minimal # 文字+风格
/opt/hermes/.venv/bin/python .../gzh_cover.py --out <dir> --name <名> --style minimal... # 无文字+风格
/opt/hermes/.venv/bin/python .../gzh_cover.py --out <dir> --name <名> --image <图> # 用户给图归一化- 输出
<out>/<name>_{no-text|with-text|user-image}.jpg(900x383 ≤1MB) - styles:
minimal/tech/oilpaint/watercolor/ink/vintage(acts >moren 默认) - 带文字封面必须先发用户人工确认,确认后才准上传+发布;超时未回复默认中止(带文字 15 分钟 / 无文字 10 分钟)
--hint仅对「无文字 + moren」档生效——带文字档 hint 被静默忽略- 图片放 hermes 可写目录,必须本地磁盘文件
Step 6 推送(推草稿箱)
export WECHAT_PUBLISHER_DATA_DIR=/opt/data/.wechat-publisher
node /opt/data/skills/wechat-publisher/wechat-publisher.mjs publish-file <html> \
--thumb <封面本地路径>.jpg --title <标题> --digest <摘要> --author <作者>三条硬约束:
--thumb传本地封面 jpg 路径(铁律3)- 必须显式
--title/--digest:render_fixed 产物的 h1 被<span leaf>包裹,peterpan 提取不出 → 不传会产出 “Untitled” 草稿(已实测证实)--dry-run不是零副作用:新图仍会上传占素材配额(上传发生在 dryRun 判定之前);长文预览截断为前 800 字符 —— 预览建议用convert,dry-run 仅作冒烟
Step 7 回报
- 给用户 media_id + 草稿标题,提示”已入草稿箱,请到公众号后台手动群发”
- 发布前 round-trip 回读校验标题,确认非 “Untitled”
5. 封面生成内部参数(gzh_cover.py,调用者无需关心)
- API size 转置(实测):请求
768x1360才返回横版1360x768;请求1360x768返回竖版。脚本内已固化REQ_SIZE="768x1360"。 - 目标 900x383(2.35:1,微信首图标准)≤1MB;quality high,超限循环降 q 到 ≤40 止
- 裁剪:宽/高≥2.35 沿宽居中裁,否则沿高居中裁;绝不非等比缩放
- 用户图归一化:宽>1360 限宽;竖图 WARN 提示确认;超 2.35:1 裁剪
- 失败回退链:生图失败 用户指定图 → 正文首图 → 均无则中止告知,不建草稿
- 重试:脚本内 1 次重试(共 2 次尝试)
6. 错误码速查(微信 API + 脚本 EC-)
| 错误码 | 含义 | 处置 |
|---|---|---|
| 40001 | access_token 无效/不是最新 | 删 /opt/data/.wechat-publisher/token.json 后重试(多客户端并发刷新互作废) |
| 40014 | token 过期 | 同上,重新 auth |
| 40164 | 出口 IP 不在白名单 | 不要反复重试;引导用户后台加白名单 |
| 40013 | 参数错误(常见:缺封面 thumb) | 补 --thumb(传本地文件)后再试 |
| 40007 | invalid media_id(最常见踩坑) | thumb 传了 media_id 字符串或空 → 改传本地封面路径 |
| 42001 | token 刷新过于频繁 | 等待 1 分钟 |
| 48001 | 个人号无 freepublish 权限 | 属正常,只能建草稿人工群发(publish 命令对它永远 48001 且 exit 0) |
| 45009 | API 调用超限 | 等待配额恢复 |
| EC-001 | 生图失败(网络/超时/配额/qualit |
注:本文涉及的服务器公网 IP / Tailnet / 局域网 IP 已脱敏,请替换为你自己的地址。