---
name: publish-workflow
description: AI工具人PM内容自动发布工作流：审核、发布、归档。技术平台→publish.py（只发CSDN，图片传CSDN图床；其他平台用CSDN同步助手手动分发），公众号→wechat_publish.py（本地图直传微信图床），目录状态机统一，不跨渠道。
---

# 发布工作流（publish-workflow）

> 全局技能包清单见 `~/.claude/CLAUDE.md`。本文件仅含发布流程专项约束。

---

## 目录规范（2026-09-02 定）

### 技术平台

```
06 - 长期记忆库/
├── 待发布/                          ← 定时任务每日 10:00 扫描顶层 *.md
│   ├── AI工具-XXX.md                ← 等待发布（created 升序，最多 3 篇/天）
│   ├── _草稿/                       ← 写作阶段暂存，不被定时任务扫到
│   │   └── AI工具-XXX.md            ← 写完了但图片还没传 CSDN 图床，先放这里
│   └── imgs/                        ← 配图素材（按主题分目录）
└── 已发布/                          ← 发布成功后自动归档
    ├── csdn/  juejin/  zhihu/  url/
```

**流转规则：**
- 写作阶段（①-⑤）：文章落 `待发布/_草稿/`，图片落 `待发布/imgs/<主题>/`
- 图片传 CSDN 图床后：**手动或发布时**把文章从 `_草稿/` 移到 `待发布/` 顶层
- 定时任务只扫 `待发布/` 顶层 `*.md`，不递归 `_草稿/`，**不会误触未就绪的文章**

### 微信公众号

```
06 - 长期记忆库/
└── 公众号-产品小游AI提效笔记/
    ├── _草稿/                       ← 写作阶段暂存
    │   └── 标题.md
    ├── imgs/                        ← 配图素材（按主题分目录）
    └── 已推草稿/                    ← wechat_publish.py 推成功自动移入
        └── 标题.md                  ← 人工后台点发表后，改 frontmatter status: 已发表
```

**流转规则：**
- 写作阶段（①-⑤）：文章落 `_草稿/`
- 推草稿成功：`wechat_publish.py` 自动移入 `已推草稿/`，frontmatter 改 `已推草稿`
- 人工发表：改 frontmatter `status: 已发表`，文件不动（已推草稿/ 即为公众号归档）

---

## 触发词

「审核发布」「归档这篇文章」「发布待发布文章」「查看待发布」「推送公众号」「发布公众号」

---

## 渠道区分

| | 技术平台 | 微信公众号 |
|---|---|---|
| 写作目录 | `待发布/_草稿/` | `公众号-产品小游AI提效笔记/_草稿/` |
| 就绪目录 | `待发布/*.md`（定时任务扫） | `_草稿/`（推时指定路径） |
| 发布脚本 | `vault-scripts/publish.py` | `vault-scripts/wechat_publish.py` |
| 推送方式 | 定时每天 10:00 自动跑 | 手动一条一条推 |
| 归档目录 | `已发布/csdn/` | `已推草稿/`（同公众号目录） |
| 状态字段 | `status: 草稿 → 待发布 → 已发布` | `status: 草稿 → 已推草稿 → 已发表` |

---

## 状态机（两渠合一，各自独立）

```
[技术平台]                          [微信公众号]
  草稿（_草稿/）                      草稿（_草稿/）
   │                                  │
   │  脱敏通过、图片传CSDN图床        │  脱敏通过（图片无需传图床，
   ▼                                  ▼   wechat_publish 推时本地直传）
  待发布（/待发布/）                  已推草稿（/已推草稿/）
   │                                  │
   │  publish.py 发布到 CSDN          │  wechat_publish.py 推草稿
   ▼                                  ▼
  已发布（/已发布/csdn/）             已发表（status 字段改）
   │
   └── CSDN 同步助手（浏览器手动）→ 知乎/掘金/微博/百家号/博客园等草稿箱 → 人工终审发布
```

**关键规则：**
- 技术平台：写作阶段文章在 `待发布/_草稿/`；图片传完 CSDN 图床后**移入 `待发布/` 顶层**，才进入定时任务调度
- **只发 CSDN**（2026-09-18 起）：知乎/掘金直发模块已退役（`vault-scripts/legacy/`）。发布成功后源文件直接归档 `已发布/csdn/`
- 其他平台分发：浏览器打开已发布的 CSDN 文章 → CSDN 同步助手选平台 → 进各平台**草稿箱** → 人工后台终审发布
- 微信公众号：写文章和推草稿都针对 `_草稿/`，wechat_publish.py 推成功后**自动移到 `已推草稿/`**
- 公众号人工发表后：手动改 frontmatter `status: 已发表`，无需移文件
- 两个渠道的 `_草稿/` 和已归档目录**互不干扰**

---

## 流程六步

```
① 审核（脱敏+图片）→ ② 待发布目录检查 → ③ 发布 → ④ 归档确认 → ⑤ 状态更新 → ⑥ 矩阵索引刷新
```

### ① 审核（脱敏 + 图片传 CSDN 图床）

```bash
# 脱敏检查
python vault-scripts/sensitive_check.py "文章路径"

# 传图片到 CSDN 图床并回填公网 URL（须已压缩；imagebed 入口会再压一次大图兜底）
python vault-scripts/publish.py --images "文章路径"
# 公众号渠道图片：无需传图床，wechat_publish 推送时本地图直传微信图床
python vault-scripts/wechat_publish.py --dry-run --file "文章路径"  # 先预览 HTML，确认图片正确
```

**⛔ 未脱敏不发布，图片 URL 未回填不发布。**

### ② 待发布目录检查 & 文章移送

```bash
# 查看待发布目录（定时任务会扫这些）
python -c "
from pathlib import Path
import re
root = Path('06 - 长期记忆库/待发布')
for f in sorted(root.glob('*.md')):
    if f.name.startswith('README'): continue
    text = f.read_text(encoding='utf-8')
    cr = re.search(r'created:\s*(\S+)', text)
    st = re.search(r'status:\s*(\S+)', text)
    print(f'{cr.group(1) if cr else \"?\":10s}  {st.group(1) if st else \"?\":8s}  {f.name}')
"

# 查看 _草稿/ 中待移送的文章
ls "06 - 长期记忆库/待发布/_草稿/" | grep '\.md$'
ls "06 - 长期记忆库/公众号-产品小游AI提效笔记/_草稿/" | grep '\.md$'

# 移送文章：图片传 CSDN 图床后，从 _草稿/ 移到待发布顶层
mv "06 - 长期记忆库/待发布/_草稿/文章.md" "06 - 长期记忆库/待发布/"
mv "06 - 长期记忆库/公众号-产品小游AI提效笔记/_草稿/文章.md" \
   "06 - 长期记忆库/公众号-产品小游AI提效笔记/"
```

**⛔ _草稿/ 目录是写作暂存区，定时任务不扫。只有移入顶层才进入调度。**

### ③ 发布

**技术平台（定时 + 手动）：**
```bash
# 手动发布指定文章
python vault-scripts/publish.py --file "06 - 长期记忆库/待发布/文章名.md"

# 查看全部待发布（dry-run）
python vault-scripts/publish.py --dry-run

# 定时运行（守护进程）
python vault-scripts/daily_publish.py
```

**微信公众号（手动逐篇）：**
```bash
# 推草稿箱（默认，人工后台点发表）
python vault-scripts/wechat_publish.py --file "06 - 长期记忆库/公众号-产品小游AI提效笔记/_草稿/文章名.md"

# 直接发布（每天限 1 次，慎用）
python vault-scripts/wechat_publish.py --file "文章名.md" --publish
```

### ④ 归档确认

**技术平台：** 发布成功后源文件自动从 `待发布/` 移入 `已发布/{平台}/`，确认日志。

**微信公众号：** 推草稿成功后自动从 `_草稿/` 移到 `已推草稿/`，确认文件存在。

```bash
# 查技术平台归档
ls "06 - 长期记忆库/已发布/"
# 查微信公众号已推
ls "06 - 长期记忆库/公众号-产品小游AI提效笔记/已推草稿/"
```

### ⑤ 状态更新

**技术平台：** publish.py 自动更新 frontmatter，无需手动操作。

**微信公众号：** 人工发表后，手动改 frontmatter：
```bash
# 在 Obsidian 里把微信文章 frontmatter 的 status 改为：
status: 已发表
```

### ⑥ 矩阵索引刷新

```bash
# 刷新内容矩阵（已发布+待发布汇总）
python vault-scripts/daily_publish.py --status
```

---

## 硬规则（non-negotiables）

- ⛔ **脱敏必须在前，图片传图床在后**——先过 sensitive_check，再跑 --images
- ⛔ **图片必须先压缩再传**——article-illustrations 生图脚本落盘即压；这里 `--images` 是第二道。未压缩的 6MB PNG 上传慢且可能触发接口限制
- ⛔ **技术平台写作阶段文章必须放 `待发布/_草稿/`**——移入 `待发布/` 顶层才进入定时任务调度
- ⛔ **微信公众号写作阶段文章必须放 `公众号-产品小游AI提效笔记/_草稿/`**——推成功后自动进 `已推草稿/`
- ⛔ **两个渠道互不混**——技术平台不发微信，微信不发技术平台
- ⛔ **公众号每日最多 1 次 `--publish`**——默认只推草稿，人工后台点发表
- ⛔ **脚本只发 CSDN**——知乎/掘金等由 CSDN 同步助手（浏览器插件）分发到草稿箱，人工终审；不要再写多平台直发
- ✅ **定时任务只扫 `/待发布/` 顶层 `*.md`**——不递归 `_草稿/`，写作中的文章不会被误触
- ✅ **`_草稿/` 中的文章必须补 `imgs/` 引用后才会被 publish.py --images 正确处理**

---

## 常用命令速查

| 动作 | 命令 |
|------|------|
| 技术平台：查看待发布文章 | `python -c "..."`（见步骤②） |
| 技术平台：移送 _草稿→待发布 | `mv "待发布/_草稿/文章.md" "待发布/"` |
| 技术平台：发布单篇 | `python vault-scripts/publish.py --file "待发布/文章.md"` |
| 技术平台：dry-run 预览 | `python vault-scripts/publish.py --dry-run` |
| 技术平台：定时运行 | `python vault-scripts/daily_publish.py` |
| 技术平台：状态报告 | `python vault-scripts/daily_publish.py --status` |
| 微信公众号：推草稿 | `python vault-scripts/wechat_publish.py --file "公众号-产品小游AI提效笔记/_草稿/文章.md"` |
| 微信公众号：直接发表 | `python vault-scripts/wechat_publish.py --file "文章.md" --publish` |
| 微信公众号：预览 HTML | `python vault-scripts/wechat_publish.py --file "文章.md" --dry-run` |
| 微信公众号：手动改状态 | 在 Obsidian 改 frontmatter `status:` |
| 全量脱敏 | `python vault-scripts/sensitive_check.py "06 - 长期记忆库/待发布/_草稿"` |

---

## 跨会话协作

换会话后，触发词「审核发布」「发布待发布」「归档这篇文章」等自动唤起本 skill。

本 skill 不依赖外部状态，所有命令均为幂等操作，可安全重试。
