# Peri Code: blog-writer skill 如何用负反馈循环稳定输出风格

> **[Peri Code](https://github.com/konghayao/peri)** — 用 Rust 写的开源 Coding Agent，兼容 Claude Code 生态。<https://github.com/KonghaYao/peri>

[流式协议踩坑篇](https://github.com/konghayao/peri/blob/main/docs/blogs/streaming-protocol-traps/streaming-protocol-traps.md)写完第一稿后，我们自己重读了一遍。每隔两段就有一句话孤零零占一整行——这三个 bug 看似无关，根因却指向同一个机制。一层兜底不够，两层勉强够，三层才把三种失败模式全部覆盖。单独看每句话都没问题，但它们悬在段落之间的空行里，读起来节奏不断被打断。

我们把这些孤立单句全标出来，一共十一处。分析后分成三类——预告句（这篇文章记录这三个坑）、过渡总结（同一个根因，两种失败模式）、收束提炼（一句话，每一层都用 X 覆盖 Y）。处理方式逐类写死——预告句直接删，过渡总结合并进前后段落，收束提炼融进论证。这是我们第一次把读着不对翻译成能逐条检查的规则，写进 [blog-writer skill](https://github.com/konghayao/peri/blob/main/.claude/skills/blog-writer/SKILL.md)。blog-writer skill 就是这样做出来的——每写完一篇博客，找到一处最刺眼的反感，把它固化成一条可执行规则，skill 边写边长，到今天有十几个章节和几十条规则。

## 三段风格偏好描述在第二个题材失效

最早的 blog-writer skill 只有三段话——用第一人称、结论前置、代码块尽量少。[Peri 介绍篇](https://github.com/konghayao/peri/blob/main/docs/blogs/introducing-peri/introducing-peri.md)按这个写出来还能看，轮到[内存优化篇](https://github.com/konghayao/peri/blob/main/docs/blogs/perf-optimization/perf-optimization.md)就走样了——模型在性能调优题材下自动切回默认句式，段落重新对称、结论又沉到章尾。

根源是偏好描述对模型来说无法量化。代码块尽量少是一个连续谱——三块算少还是零块算少？模型没有判断标准，输出结果无法确定。要让风格稳定，必须把每一条偏好拆成一串可检查的硬规则。比如代码块尽量少被拆成两条禁令——整篇代码块不超过两个，只用于真实报错信息和极简前后对比，其余所有行为用白话讲。拆完之后，模型不需要靠输出统计相似度来碰运气，核对就行。这是 blog-writer skill 的第一课——风格稳定不来自偏好描述的精美程度，来自规则的硬度和可检查性。

## 孤立单句分类后每种类型走不同处理分支

孤立单句被标出来后，我们不是直接写一条禁止单句成段就收工，而是把十一处样本摊开分类。分类的价值在于每种类型有不同的处理分支——预告句能删就删，因为它是给读者预告还没发生的事，删了信息不丢失。过渡总结是上一段已经说过的事换了个说法，所以不删但并进下一段，变成段首的一句。收束提炼如果本身是前文没出现过的精炼判断，融进论证过程而不是单独提一句。

分类之后，规则不再是一条笼统的禁令，而是一个带判断流程的小型决策树——扫到孤立单句 → 看类型 → 走对应分支。这条规则后来成了整个 skill 里执行最到位的禁令。

## 每一条模糊反感拆成几条可逐项检查的正面禁令

单句成段禁令做完之后，一个更底层的问题浮出来——skill 里有太多否定式描述。不要写得像 AI、段落别太对称、不要金句收尾。写出来之后发现模型完全不知道什么叫像 AI 和不要太对称。否定描述没有正面锚点——模型只能从训练数据里去匹配 AI 味的统计模式，而不同题材下这个模式偏移剧烈。

我们把每一条模糊反感逐个拆成一组正面禁令——

不要写得像 AI 被拆成禁用填充词（综上所述、值得注意的是）、禁用设问句式（为什么不 X、因为 Y）、禁止故事性叙事（模型拟人化、戏剧口语替代后果、叙事过渡引子）。这三条禁令全部可逐项检查——扫到值得注意的是就是违规，扫到为什么不 X 就是违规，扫到模型撒谎就是违规。没有灰度地带。

段落不要太对称被拆成两条——正文段落不少于两句、禁止段尾对仗式概括。对称感来自同构句型的重复，规定段落必须两句以上起步和禁止段尾对仗，就从结构上打断了两句一轮、四段一循环的节奏。

拆完之后，最开始的几十条否定式反馈，经过逐条拆解全变成了可执行禁令。skill 从一个随手写几段的备忘录，变成了两组表格——禁用词表（左列禁用，右列替换）和禁用模式表（左列模式，右列判断条件）。模型要做的不是理解风格，是对照这两张表逐条检查输出。

## 规则过阈值后按作用阶段分成三层

规则数过了某个阈值之后出现了新问题——模型每次写文章前会过一遍全部规则，但某些规则在写作过程中被系统性遗漏。最常漏的是一类靠后的细节禁令，比如中文冒号禁用和小标题禁止破折号。这些规则在过一遍的注意力权重里靠后，写作到后半段时已经不在模型的即时记忆里了。

我们按作用阶段把规则拆成三层——流程层管写之前和写之后——写前必须走 grill（质询式对齐流程，逐轮追问直到核心命题确认）对齐核心命题、写后必须走独立 subagent（全新上下文中的子 Agent，不带生成历史）审查；结构层管骨架——开头三段以内、结论前置、每个章节服务核心论点、结尾回应开头；语言层管血肉——禁用词、禁用标点、禁用模式、句子结构、小标题写法。

分层之后，模型不再一次性处理全部规则。先走流程和结构层规则规划骨架，再走语言层规则写句子。每层只过该层的规则，漏检不再集中出现在写作后半段的细节禁令上。

## 生成和审查用不同上下文后违例检出翻倍

这个 fix 是我们踩坑踩出来的。写完一篇按 skill 严格生成的文章后，让同一个上下文（模型当前能看到的全部对话历史加系统提示词）再执行一次 SKILL.md 逐条审查，产出的问题清单只有实际违规量的一半不到。skill 在生成时已经影响过它的上下文分布，第二次审查用的是被同一个 skill 塑造过的注意力（模型对输入各部分的关注权重分布）。两个上下文高度相关、互相盲区。

改成独立 subagent 做审查。subagent 用全新上下文、只看文本不看生成历史。同一个 SKILL.md（即 blog-writer skill 风格规则文件全文），同一个文本，检出量翻了一倍以上。生成和审查的上下文隔离，是把规则执行从走过场变真检查的关键一步。这个改动花了一周就写进 skill，但它把负反馈循环的执行率从大概一半拉到了接近全部——每一处生成时的规则遗漏，都有独立上下文来兜底抓。

## 全部规则以可执行检查清单组织

当初我们在流式协议踩坑篇的十一个孤立单句上打标记时，blog-writer skill 还不存在。现在把它和按最终版 skill 写出来的[多智能体篇](https://github.com/konghayao/peri/blob/main/docs/blogs/multi-agent-patterns/multi-agent-patterns.md)、[Web 工具篇](https://github.com/konghayao/peri/blob/main/docs/blogs/web-search/web-search.md)放在一起——这些文章都在 `docs/blogs/` 目录下，GitHub 上直接可读。读者扫一眼能看出变化——后者的段落密度连续，小标题全是机制描述而不是态度表达，术语第一次出现都跟着一句白话解释。

这个变化不是一次性 prompt 调出来的。每一轮这里不对的反感都被我们拆成了可执行规则，每一条规则都配了判断条件，skill 里没有一条模糊偏好。blog-writer skill 不是一次性设计完成的，是每发现一处反感就补一条规则、逐条累积形成的。

项目地址：[github.com/konghayao/peri](https://github.com/konghayao/peri)
