Goal
- - Canonical npm package name is
@leeguoo/blog-publish (single source of truth). - Use
blog-publish to publish normal blog content and dynamic section content. - Keep dynamic section publishing compliant with no public
producer leakage. - Reuse one skill across
editorial, hot, news, and ai_news. - Enforce deterministic quality rules so auto-published News/Hot briefs are readable and source-grounded.
- Use the image upload path in
blog-publish to generate CDN-hosted markdown URLs for embedded assets.
When to Use
- - Publishing normal editorial posts.
- Publishing dynamic section posts under
hot/news/ai_news. - Running batch skill sync to ClawHub.
Inputs
- - Required for all entries:
-
locale
-
slug
-
title
-
summary
-
contentMarkdown
- - Required for dynamic sections:
-
section (
hot,
news, or
ai_news)
-
pairId (if omitted, server falls back to
slug)
-
repoUrl
-
sourceUrl
-
publicSourceLabel
-
tags
-
decisionMeta
-
producer (internal only, never for public display)
Quality Gates (Required for hot/news/ai_news)
- Title + short deck (
summary) + structured body.
- Body must contain numbered topics (
## 1) ...,
## 2) ...) and a closing takeaways section.
- Dynamic briefs should normally contain
4-8 topics; reject outputs with only
1-2 thin topics unless the source itself is extremely short.
- Each topic must include exactly five lines:
-
来源/Source
-
证据/Evidence
-
摘要/Summary
-
解读/Interpretation
-
行动建议/Action
-
证据/Evidence must point to a concrete anchor (release bullet / PR / issue / official doc section), not only homepage-level links.
-
摘要/Summary is factual and source-grounded.
-
解读/Interpretation is inference/opinion and must not fabricate facts; include explicit impact level (
P0/
P1/
P2).
-
行动建议/Action must be executable (for example: "upgrade now", "canary first", "hold and monitor").
- Do not publish naked URLs in prose or list items.
- Use Markdown links only:
[来源标题](https://...).
- One topic should have one primary source link + one evidence link when available.
- Avoid same-link repetition across all topics; evidence links should be topic-specific whenever possible.
- No "据说/rumor/未证实" style claims without attribution.
- No placeholder text (
TBD,
待补充,
lorem ipsum).
- No leaked render placeholders (
INLINE_CODE,
RUBYPH,
@@...@@).
- No exposing internal producer identity in byline/meta/body (for example: "generated by skill/openclaw bot").
- Mentioning
OpenClaw is allowed when it is the article subject, not the publisher identity.
Quality Score (Publish Threshold)
- - Score each topic on 3 axes (
0-2 each):
- Evidence quality: traceable and specific.
- Summary clarity: factual, concise, no ambiguity.
- Actionability: recommendation can be executed.
- Any topic total score
< 4, or
- Any topic missing
Evidence/
Action.
Body Template (news / hot / ai_news)
CODEBLOCK0
Preflight Checks
- - Before publish, run dry-run and fail fast on quality violations:
-
blog-publish publish --dry-run --input <file>.json
-
blog-publish publish --dry-run --input <file>.md
- - Quick markdown guardrails (example):
- Reject naked links:
rg -n "(^|[^\\]\\()https?://" against generated markdown files.
- Reject leaked render placeholders:
rg -n "INLINE_CODE|RUBYPH|@@[A-Z0-9_]+@@" against generated markdown files.
- Verify each topic has
Source + Evidence + Summary + Interpretation + Action.
- Verify each interpretation includes risk level label (
P0|P1|P2).
- Verify evidence links are not all identical across every topic.
- If
pairId is missing, ensure
slug is stable because server uses it for localization grouping.
- - Only proceed to real publish when dry-run is clean.
Publishing Rules
- - Default
section is editorial when absent. - INLINECODE69 and
blog-publish update both accept JSON payload files and markdown files with frontmatter. - Use
blog-publish post-list to discover existing locale + slug pairs before editing existing posts. - Use
blog-publish download to export stored content into editable markdown frontmatter, then feed that file back into blog-publish update. - Single-language submit is supported for all sections; server handles auto-localization.
- Auto-generated section content is free by default and does not enter premium gating.
- Keep
producer as internal metadata only; public surfaces must use publicSourceLabel or section label.
Command Playbook
-
pnpm add -g @leeguoo/blog-publish
-
blog-publish login --api-base https://blog.misonote.com --sso-client-id misonote-blog-web --sso-redirect-uri https://blog.misonote.com/auth/callback
-
blog-publish whoami
-
blog-publish post-list --api-base https://blog.misonote.com --locale zh
-
blog-publish download --api-base https://blog.misonote.com --locale zh --slug <slug> --output ./drafts/<slug>.zh.md
-
blog-publish upload --api-base https://blog.misonote.com --file ./assets/cover.png --markdown-only
-
blog-publish upload --api-base https://blog.misonote.com --file ./assets/cover.png --filename cover-final.png
- - Automation Auth (OpenClaw/CI):
- Use service token only:
PUBLISH_API_TOKEN=<secret>
- Preflight:
blog-publish whoami --api-base https://blog.misonote.com
- Never prompt end users to complete browser authorization links.
-
blog-publish publish --dry-run --input <file>.json
-
blog-publish publish --dry-run --input <file>.md
-
blog-publish publish --input <file>.json
-
blog-publish publish --input <file>.md
-
blog-publish update --dry-run --input <file>.md
- INLINECODE92
Media Notes
- - Publish API now uses
MEDIA_CDN_BASE_URL and emits image markdown URLs like:
-
https://img.leeguoo.com/media/<asset-id>/<filename>
- - Repeated uploads of the same file are deduplicated by SHA-256 and return:
-
deduped: true and the existing
asset.id instead of creating a duplicate.
- - Keep
img.leeguoo.com as the canonical image host in generated markdown to leverage Cloudflare CDN + cache. - Skill sync:
-
pnpm clawhub:sync:dry-run
-
pnpm clawhub:sync:all
- - Alias compatible with team wording (
clawdhub sync all):
-
pnpm clawdhub:sync:dry-run
- INLINECODE102
Failure Handling
- Check API status code and error payload first.
- Fix validation issues (required fields, auth scope), then retry.
- If quality gates fail, regenerate the current locale content and retry.
- If login gets wrong client/redirect values, remove environment overrides (
BLOG_PUBLISH_SSO_CLIENT_ID,
BLOG_PUBLISH_SSO_REDIRECT_URI) and rerun strict login command.
- If running in automation and error is
PUBLISH_UNAUTHORIZED, stop interactive login attempts, rotate
PUBLISH_API_TOKEN, then retry publish.
- Record error output and alert maintainers.
- Do not block already-published content visibility.
- Retry sync after login/permission/network issues are resolved.
目标
- - 规范的 npm 包名为 @leeguoo/blog-publish(唯一真实来源)。
- 使用 blog-publish 发布普通博客内容和动态栏目内容。
- 保持动态栏目发布合规,不泄露公开的 producer 信息。
- 在 editorial、hot、news 和 ai_news 之间复用同一技能。
- 强制执行确定性质量规则,使自动发布的新闻/热点简报可读且基于来源。
- 使用 blog-publish 中的图片上传路径,为嵌入资源生成 CDN 托管的 Markdown URL。
使用时机
- - 发布普通编辑文章。
- 在 hot/news/ai_news 下发布动态栏目文章。
- 运行批量技能同步到 ClawHub。
输入
- locale
- slug
- title
- summary
- contentMarkdown
- section(hot、news 或 ai_news)
- pairId(若省略,服务器回退到 slug)
- repoUrl
- sourceUrl
- publicSourceLabel
- tags
- decisionMeta
- producer(仅内部使用,绝不公开显示)
质量门禁(hot/news/ai_news 必需)
- 标题 + 简短摘要(summary)+ 结构化正文。
- 正文必须包含编号主题(## 1) ...、## 2) ...)和结尾的要点总结部分。
- 动态简报通常应包含 4-8 个主题;若来源本身极短,可拒绝仅含 1-2 个单薄主题的输出。
- 每个主题必须恰好包含五行:
- 来源/Source
- 证据/Evidence
- 摘要/Summary
- 解读/Interpretation
- 行动建议/Action
- 证据/Evidence 必须指向具体锚点(发布要点/PR/Issue/官方文档章节),而非仅首页级链接。
- 摘要/Summary 应基于事实和来源。
- 解读/Interpretation 为推理/观点,不得捏造事实;需包含明确影响等级(P0/P1/P2)。
- 行动建议/Action 必须可执行(例如:立即升级、先金丝雀测试、暂缓观察)。
- 不在正文或列表项中发布裸 URL。
- 仅使用 Markdown 链接:
来源标题。
- 每个主题应有一个主要来源链接 + 一个证据链接(如有)。
- 避免所有主题重复相同链接;证据链接应尽可能针对具体主题。
- 不允许无归属的据说/rumor/未证实类表述。
- 不允许占位文本(TBD、待补充、lorem ipsum)。
- 不允许泄露的渲染占位符(INLINE_CODE、RUBYPH、@@...@@)。
- 不在署名/元数据/正文中暴露内部生产者身份(例如:由 skill/openclaw bot 生成)。
- 当 OpenClaw 是文章主题而非发布者身份时,允许提及。
质量评分(发布阈值)
- 证据质量:可追溯且具体。
- 摘要清晰度:基于事实、简洁、无歧义。
- 可操作性:建议可执行。
- 任一主题总分 < 4,或
- 任一主题缺少 证据/Evidence 或 行动建议/Action。
正文模板(news / hot / ai_news)
md
{{title}}
更新时间:{{timestamp}}
数据来源:{{source_set}}
说明:本期每条热点均包含「摘要 + 解读」。
1) {{topic_title}}
2) {{topic_title}}
总结
- 1. {{takeaway1}}
- {{takeaway2}}
- {{takeaway_3}}
预检检查
- - 发布前,运行 dry-run 并在质量违规时快速失败:
- blog-publish publish --dry-run --input
.json
- blog-publish publish --dry-run --input .md
- 拒绝裸链接:对生成的 Markdown 文件运行 rg -n (^|[^\\]\\()https?://。
- 拒绝泄露的渲染占位符:对生成的 Markdown 文件运行 rg -n INLINECODE|RUBYPH|@@[A-Z0-9]+@@。
- 验证每个主题包含 来源 + 证据 + 摘要 + 解读 + 行动建议。
- 验证每个解读包含风险等级标签(P0|P1|P2)。
- 验证证据链接并非所有主题完全相同。
- 若缺少 pairId,确保 slug 稳定,因为服务器将其用于本地化分组。
发布规则
- - 默认 section 为 editorial(当未指定时)。
- blog-publish publish 和 blog-publish update 均接受 JSON 载荷文件和带 frontmatter 的 Markdown 文件。
- 在编辑已有文章前,使用 blog-publish post-list 发现现有的 locale + slug 组合。
- 使用 blog-publish download 将存储内容导出为可编辑的 Markdown frontmatter,然后将该文件反馈给 blog-publish update。
- 所有栏目均支持单语言提交;服务器处理自动本地化。
- 自动生成的栏目内容默认免费,不进入付费门槛。
- 将 producer 仅作为内部元数据保留;公开界面必须使用 publicSourceLabel 或栏目标签。
命令手册
- pnpm add -g @leeguoo/blog-publish
- blog-publish login --api-base https://blog.misonote.com --sso-client-id misonote-blog-web --sso-redirect-uri https://blog.misonote.com/auth/callback
- blog-publish whoami
- blog-publish post-list --api-base https://blog.misonote.com --locale zh
- blog-publish download --api-base https://blog.misonote.com --locale zh --slug --output ./drafts/.zh.md
- blog-publish upload --api-base https://blog.misonote.com --file ./assets/cover.png --markdown-only
- blog-publish upload --api-base https://blog.misonote.com --file ./assets/cover.png --filename cover-final.png
- 仅使用服务令牌:PUBLISHAPITOKEN=
- 预检:blog-publish whoami --api-base https://blog.misonote.com
- 绝不提示最终用户完成浏览器授权链接。
- blog-publish publish --dry-run --input .json
- blog-publish publish --dry-run --input .md
- blog-publish publish --input .json
- blog-publish publish --input .md
- blog-publish update --dry-run --input .md
- blog-publish update --input .md
媒体说明
- - 发布 API 现使用 MEDIACDNBASE_URL,生成类似以下的图片 Markdown URL:
- https://img.leeguoo.com/media//
- - 重复上传相同文件会通过 SHA-256 去重,返回:
- deduped: true 和现有的 asset.id,而非创建重复文件。
- - 在生成的 Markdown 中保持 img.leeguoo.com 作为规范的图片主机,以利用