+ 标题
+ +导语:80~140 字。从一个具体细节、问题或场景切入,不要以「近日/据报道」起笔。
+ +具体的小节标题(写清本节讲什么)
+正文段落
+
与题材相关的具体问题(禁止用「怎么看」「总结」)
+2~3 段编辑判断,可出现「我们认为」「值得留意的是」。
+diff --git a/news-item-templates.mjs b/news-item-templates.mjs
new file mode 100644
index 0000000..fc00bce
--- /dev/null
+++ b/news-item-templates.mjs
@@ -0,0 +1,213 @@
+/**
+ * 单条新闻落地页的模板契约。
+ *
+ * 这份契约同时约束两端:Agent 按它生成 HTML,news-engine 的块解析器按它把 HTML
+ * 拆成可编辑的块。类名是两端唯一的接口,改动必须同步 lib/wechat-draft-blocks.mjs。
+ */
+
+export const NEWS_ITEM_VERSION = '2026-09-22-v4-human-voice';
+
+export const NEWS_ITEM_MIN_IMAGES = 6;
+export const NEWS_ITEM_MIN_SECTIONS = 5;
+export const NEWS_ITEM_MIN_CHARS = 1200;
+
+export const NEWS_ITEM_STYLES = Object.freeze({
+ 'wechat-feature': {
+ id: 'wechat-feature',
+ label: '公众号深度稿',
+ description: '导语 + 可选过渡 + 5~7 个小节(长短可不一,每节配图)+ 结尾编辑观点',
+ minImages: NEWS_ITEM_MIN_IMAGES,
+ minSections: NEWS_ITEM_MIN_SECTIONS,
+ minChars: NEWS_ITEM_MIN_CHARS,
+ },
+ brief: {
+ id: 'brief',
+ label: '快讯图文',
+ description: '紧凑结构:导语 + 3~4 个小节,适合突发短讯',
+ minImages: 4,
+ minSections: 3,
+ minChars: 700,
+ },
+});
+
+const BRIEF_CATEGORIES = new Set(['快讯', '突发', 'breaking']);
+
+export function resolveNewsItemStyle(newsItem = {}, env = process.env) {
+ const explicit = String(env.MEMIND_NEWS_ITEM_STYLE ?? '').trim();
+ if (explicit && NEWS_ITEM_STYLES[explicit]) return explicit;
+ const requested = String(newsItem.layoutStyle ?? '').trim();
+ if (requested && NEWS_ITEM_STYLES[requested]) return requested;
+ const category = String(newsItem.category ?? '').trim().toLowerCase();
+ if (BRIEF_CATEGORIES.has(category)) return 'brief';
+ return 'wechat-feature';
+}
+
+// ---------------------------------------------------------------------------
+// 结构契约(写进 Agent 提示词,也是块解析器的依据)
+// ---------------------------------------------------------------------------
+
+const STRUCTURE_CONTRACT = `【HTML 结构硬约束|类名不可改,下游要按类名解析】
+ 导语:80~140 字。从一个具体细节、问题或场景切入,不要以「近日/据报道」起笔。 正文段落 2~3 段编辑判断,可出现「我们认为」「值得留意的是」。
+ 标题
+
+ 具体的小节标题(写清本节讲什么)
+ 
与题材相关的具体问题(禁止用「怎么看」「总结」)
+ :hero 1 张 + 每个 article-section 各 1 张。
+2. 先 load_skill → image-generation 生成配图,再 load_skill → static-page-publish 落盘。
+3. hero 用 hero preset;小节配图用 inline_image preset。
+4. 已有新闻原图可作为 hero 参考,但小节配图必须逐个生成,不允许复用同一张。
+5. 禁止 SVG 占位图、禁止 data: URI、禁止出现没有配图的 article-section。
+6. 必须与 hero-img 同源。`;
+
+const WRITING_RULES = `【写作硬约束】
+1. 正文纯文字不少于 {{MIN_CHARS}} 字(不含标签与空白)。
+2. 每个 article-section 1~5 段均可,段落长短错落;不要写成「首先/其次/最后」的要点罗列。
+3. 小节标题必须具体(写清这一节讲什么),禁止「背景」「影响」「怎么看」「总结」等空标题。
+4. 只使用