首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >WorkBuddy 复盘:审核器把好稿判成 REJECT,根因是我把红线词写进了批注

WorkBuddy 复盘:审核器把好稿判成 REJECT,根因是我把红线词写进了批注

原创
作者头像
用户12800671
发布于 2026-10-20 09:15:57
发布于 2026-10-20 09:15:57
1310
举报

一、现象:正文一个字都没问题,审核岗就是不盖章

我这套自动化里有个「两岗制」:生产岗负责写、审核岗负责判,判过了才能发。审核岗是一个独立脚本,退出码 3 就代表 REJECT,闸门用独立子进程调用它,fail-closed —— 审核器崩了、超时了、返回未知码,一律当「没审过」,不发。

这套东西一直好用,直到今天上午出了一件很荒谬的事。

我手工补写了三份短文案,落在同一个 .md 文件里,结构大致是这样:

代码语言:bash
复制
## 稿一
(正文三百字)

---
写作纪律:只做引流用,不含包过/保证/绝对,第一个数字是举例不是承诺

正文我逐句看过,干净。然后跑审核:

代码语言:bash
复制
python tools/prepublish_check.py --kind text --file 热点创意/content-2026-10-20.txt

输出:

代码语言:bash
复制
审核结果:REJECT
  ✗ 文案 出现站外导流词「引流」
  ✗ 文案 出现绝对化用语「保证」(广告法风险)
  ✗ 文案 出现绝对化用语「绝对」(广告法风险)
  ⇒ 不得发布;进待修清单。

被拦下的三处,全在我自己写的那行「写作纪律」里。

二、根因:审核器没有「批注区」这个概念

翻审核器的源码,问题一目了然:

代码语言:python
复制
IDENTITY = ["辅导员", "教师", "班主任", "学校", "班级", "家长会", "同事", "学生家长"]
AD_LAW   = ["最好", "第一", "唯一", "国家级", "保证", "包过", "稳赚",
            "永久有效", "绝对", "100%"]
TRAFFIC  = ["加微信", "加V", "vx", "VX", "私域", "引流", "扫码加", "进群"]

def scan_text(text, where):
    errs, warns = [], []
    for w in IDENTITY:
        if w in text:
            errs.append("%s 出现身份红线词「%s」" % (where, w))
    for w in TRAFFIC:
        if w in text:
            errs.append("%s 出现站外导流词「%s」" % (where, w))
    for w in AD_LAW:
        if w in text:
            warns.append("%s 出现绝对化用语「%s」(广告法风险)" % (where, w))
    return errs, warns

关键就是那个 if w in text。text 是整份文件的原文,从头扫到尾,没有段落、没有注释、没有「这是给人看的说明」这一层语义。对它来说,「引流」这两个字出现在正文里和出现在批注里,是完全同一件事。

而我的写作纪律,恰好是用「我要避免的词」写成的 —— 我写「不含包过、保证、绝对」,就是把三个违禁词原封不动抄进了文件。

这是我自己给自己下套:用违禁词去声明「我没有用违禁词」。

三、修法:不要给审核器开口子,去改文件的形状

第一反应会是「给审核器加个规则,跳过注释段」。我没这么做,理由很实际:审核器的全部价值就在于它不讲人情。今天给它开一个「批注不算」的口子,明天就会有人把这个口子当成逃生通道 —— 真违规的那句话会被悄悄挪进注释块,然后一切照旧放行。

所以我改的是生产侧的文件形状,不是审核侧的规则:

可发布的纯文案,单独存 .txt**;给它看的元注释(写作纪律、选题理由、口径来源、待办)留在** .md**。**

代码语言:bash
复制
热点创意/
  content-2026-10-20.txt   ← 只有能直接贴出去的正文,零批注
  content-2026-10-20.md    ← 选题理由、写作纪律、口径出处、批注

规则一句话:送审的文件,必须和最终发布出去的文件字节一致。 只要两者不是同一份东西,审核结论就不能代表线上效果 —— 不管是多审了不该审的,还是少审了该审的。

改完之后重跑,同一批文案 PASS,三份稿进队列。

四、这一类坑比「某个脚本写错了」更值得记

我把这次的根因归成一类:把「检查规则」和「被检查内容」放在同一个容器里,检查器就一定会误判自己。

这不是本项目的特殊问题,同类问题到处都是:

  1. 代码里写 # TODO: 不要用 xxx 函数,某个 grep 风格的静态检查把注释一起扫,报一个「违规调用」;
  2. 单元测试里的假手机号、假身份证被数据合规扫描扫到,测试文件被标红;
  3. 反爬规则文件里用正则写下要拦截的关键词,结果这个规则文件本身被下游的敏感词过滤拦掉。

它们的共同点:检查是纯文本的、无语义的,而人是带语义写字的。 只要不把两者隔开,人的解释就会变成机器的证据。

工程上正确的做法只有两个方向,没有第三个:

  • 方向 A(我选的):让被检查对象变干净 —— 送审文件里只留要发出去的东西;
  • 方向 B:让检查器有结构 —— 不再吃自由文本,而是吃带字段的 JSON,{"body": "...", "notes": "..."},只扫 body。

方向 A 便宜、当天能落;方向 B 更彻底,但要改所有生产脚本的输出格式。对小团队,A 够用,B 等真出第二次同类事故再上。我选 A,并把「送审文件与发布文件必须同源」写成了硬规则。

五、顺手记两个同批踩到的小坑

坑 1:同一批脚本连跑两次,台账出现重复行。 我误跑了两遍入库脚本,收益台账里出现了同一组的两行记录。处理方式不是去删原文件的行(那属于删数据,风险高于收益),而是读端按 (日期, 标题) 去重,原文件原样保留。台账是流水,流水可以脏,报告不能脏。

坑 2:给审核器传路径时别用相对路径。 审核器里 REC_DIR 是相对项目根算的,但 --file 如果给相对路径,换个工作目录跑就会找不到文件,报出来的错是「文案只有 0 字,太短」,看起来像内容问题,其实是路径问题。报错信息指向的地方,往往不是出错的地方 —— 这条已经踩过很多次了,这次又踩了一次。

六、一句话结论

审核器没错,它只是把「你说过的话」当成了「你要发出去的话」。

要让它只审该审的,别去削弱它,去把送审的那份文件洗干净。


本文记录的是本地自动化流水线里的真实排障过程,工具链为 WorkBuddy 桌面端的自动化任务 + 自写 Python 脚本;文中命令与代码片段来自本机实际运行的版本。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、现象:正文一个字都没问题,审核岗就是不盖章
  • 二、根因:审核器没有「批注区」这个概念
  • 三、修法:不要给审核器开口子,去改文件的形状
  • 四、这一类坑比「某个脚本写错了」更值得记
  • 五、顺手记两个同批踩到的小坑
  • 六、一句话结论
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档