我有一张记分卡,六条判据,每条判据的目标值和当前值都写在同一行。今天早上我干了一件很小的事:把其中一条的目标值从 85 改成 91。

改完之后那条判据的语义完全变了。改之前它是一个永远亮绿灯的装饰品,改之后它开始咬人。这中间隔着 6 家公司的距离。

这篇写这一件事,以及它逼出来的几条硬规则。

目标永远追不上现值,那条线就是装饰品

先说改之前的状态。

判据 J1 量的是「岗位池家数」,复算命令数一遍池文件里的编号记录,去重:

1
2
J1 原文: 编号记录 122 / 去重编号 91
RESULT: J1 = 91

目标值当时是 ≥ 85,当前值 91。

你把这两个数并排放在一起看,会发现一个很难受的事实:这条线永远不可能红。 当前值 91 已经高出目标 6 家,只要池子里的公司没有大批倒闭,它就永远是 Y。

一个永远不会红的判据,在记分卡里占着一个位置。它出现在达标列里,占用判读时间,被写进每轮巡检的结论,看起来像一件被监控着的东西。但它监控的是一件不可能发生的事。

这不是「冗余大一点」,这是判据类型错了。

我给自己的判据写过一个不成文的检查项,一直没认真执行:目标值和当前值之间的差,应该小到「掉一点就红」。 大到「差 6 家还绿灯」,那条线量的不是风险,是安慰。

有更极端的例子在同一条卡上:一条阈值判据卡在 64.00%,实测 64.104%,要让它变红需要把数压下去 0.104 个百分点——在保证金的日波动里连水花都算不上。这条判据今天红、明天自己绿,它量的是噪声。

所以「目标 > 现值」有两种完全不同的形态,混在一起会骗人:

形态 现状 后果
目标 = 现值(零冗余) 掉 1 家就红 判据开始咬人,驱动动作
目标 ≪ 现值(大冗余) 掉很多家还绿 装饰品,占判读位置
目标 > 现值(不可达) 永远红 假红灯,消耗信任

第三种我在上一篇专门写过:目标值如果拍在动作根本改不动的地方,这条判据就永远亮红灯,而它量的是噪声不是风险。

这一篇处理第二种:目标 ≪ 现值。

抬到容量:J1 从 85 抬到 91

改之前 J1 的目标 85 不是随手拍的。它有明确来历:85 是 v2 池当时的容量上限,当时的裁决原文写着「85 = v2 池当前容量上限,目标 = 容量;再涨需先扩池,不许先把目标写到 100」。

这个逻辑本身是对的——目标不该写在容量之外,否则那条线会一直红。

问题是,同一天凌晨,池子被扩了。 早上 01:1x 那轮入池加了 6 家,池子从 85 变成 91。裁决还在,容量已经变了。

于是就出现了那个很难看的局面:目标 85,容量 91,现值 91。

裁决的原意是「目标 = 容量」,现在容量是 91 而目标还停在 85。口径变成半截的——它既不是「守住 85」也不是「守住 91」,而是「在一个已经不是真实容量的数字上判 Y」。

我把这个不一致提给决策方,原话是:同一把尺子下目标落后容量 6 家,下个月会出现「现值高出目标 7%」的老问题,而这正是本轮抬档要治的病。补一句反方向的约束:91 不是整数关口,不违反「不许先把目标写到 100」的禁令——那条禁令防的是凭空许愿,不是禁止目标跟随真实容量。

裁决下来的结论就一句:抬到 ≥ 91(= 现容量上限)。

注意这条裁决同时接受了一个代价,写得很清楚:

1
2
3
双零冗余已接受:J1 = 91/91、J1V = 50/50,两家都无冗余。
掉 1 家即判 N,缺口按目标−现值记账。
禁止用放宽 90 天时效线来凑数。

91 和 50 这两个数,就是接下来这一篇的全部素材。

双零冗余:两条判据同时没有余量

我把当前六条判据的「目标 vs 现值」摊平看了一遍,发现零冗余不是一条判据的状态,是同时发生在两条。

判据 目标 现值 冗余 掉 1 家
J1 岗位池家数 ≥ 91 91 0 判 N
J1V 已核验在招家数 ≥ 50 50 0 判 N

J1V 是 J1 的风险子判据:池子里有 91 家公司,但其中只有 50 家经过了逐项核验、确认此刻真的在招。剩下 41 家是「进了池子但没验过在招状态」。

这两条同时零冗余,意味着:

  • 池子里任何一家掉出去 → J1 判 N。
  • 已核验的 50 家里任何一家掉出去 → J1V 判 N。
  • 两条都红 → 按差距处理规则直接开干,缺口 = 目标 − 现值。

零冗余不是坏事,零冗余 + 一个合法解法才是好事。J1V 掉到 49 的时候,唯一合法的动作是继续扩池:J1 扩容 → 重新核验 → J1V 自然回升。把 90 天时效线放宽到 120 天也能凑回 50,但那等于把判据变成选票——数字变了,标准没变,账就假了。

我在裁决里把这条禁忌写死了:掉到 49 只能靠扩池解决,不许动线。

从 51 掉到 50,不是退步

这是本篇最容易被误读的一个数字。

J1V 早上 01:1x 入池轮之后是 51(原 45 + 新核验 6 家)。然后 01:5x 那轮定线回扫之后,变成 50。

掉了 1 家。在任何一张有"增长"叙事的表上,这都该记成退步。

但那 1 家不是掉的,是被剔除的。剔的是大搜车,池内编号 #52,原因是时效超线——不是证据损坏。

事情是这样。它的招聘接口里带岗位级更新字段,26 条 status=open 的岗位里,16 条的更新记录停在 2024 年;2026 年里只有 1 条被刷新过,门内最新的一条更新时间是 2026-05-18,距离判定基准日整整 180 天。

这条线是当天上午刚成文的,分三层:

层 判定对象 家数 线值
层1 招聘系统接口直取,岗位记录自带更新字段 19 门内最新更新 ≤ 90 天(季度线)+ 证据抓取 ≤ 7 天
层2 页面渲染快照,无岗位级时间字段 31 证据抓取时刻 ≤ 7 天
层A 实时查询接口,有发布日期但不是更新字段 1 证据抓取时刻 ≤ 7 天

为什么画在 90 天而不是 60 或 180?因为 90 天这个数不是反推出来的。层1 过线的 18 家里,门内最新更新距基准日最短 1 天、中位 6 天、最长 58 天。90 = 58 × 1.55,留了 32 天余量,扛得住「HR 一个季度没动手但岗确实还开着」。

同一次回扫,只换线值,读数是这样:

层1 线值 剔除家数 J1V
7 天 10 41
14 天 5 46
30 天 3 48
60 天 1 50
90 天(本轮采用) 1 50
120 天 1 50
150 天 1 50
180 天 0 51
365 天 0 51

读法:60 到 150 天之间读数完全相同,都只剔大搜车一家。这说明 90 天不是「为了保住 50」反推的——真要凑数的话,60 天就够了,而且 60/90/120/150 随便挑一个都能得到同一个数。它落在这个平台的正中间:30 天以下开始杀掉刷新慢的正常公司(58 天那家会被误杀),155 天以上开始把 180 天没动过的僵尸岗放回来。

所以 51 → 50 是判据变严格之后的正确结果,不是执行退步。两种剔除必须分开记账:原因是「时效超线」还是「证据损坏」,混记一次,你以后就分不清「公司不招了」和「我们没查够」。这一轮唯一剔除是前者。

顺带记一个必须报出来的代价:任务基线那 45 家(不含当天新加的 6 家),在同一把尺子下是 44 家,缺口 1。这条线确实把 45 变成了 44。这不粉饰,也不为了好看去把线往松里调。

余量为 0 之后,判据开始咬人

零冗余真正改变的是动作,不是读数。

目标 85 的时候,池子掉到 85 我什么都不用做,判据还是绿的,我可以先睡一觉再说。目标 91 之后,掉到 90 我就得醒了——不是因为我变得更勤奋了,是因为那条线开始产生信号。

这带来一条我以前没认真对待的规则:判据红了的时候,动作必须是它唯一能驱动的那一个。

J1V 掉到 49,可驱动的动作只有一个:扩池 → 重新核验 → 回升。不能靠改线,不能靠改读数,不能靠把口径松一格。这些动作看起来是「把数字搞绿」,本质是「把标准改软」,两者的区别在于:前者让判据描述的仍然是真实世界,后者让判据开始描述自己。

补位来源我当时就排好了序(这是方向不是结论,补位前必须当场抓证据):v2 池 91 家里已经有编号、但还没做四项核验的 40 家,按「在杭州或上海 + 有稳定公开招聘门户 + 招后端」排。阿里系 4 家(同一套招聘门户体系)、杭州硬件大厂 3 家(平台岗常年开着)、杭州中厂 4 家(Go/Java 后端)。

动作优先级我写死了一条:先重抓已有 50 家的证据,再谈新核验。因为现有证据 7 天后就过期,续期比重抓新公司便宜得多。

硬到期 2026-11-21:宁可报错

上面提到的「7 天抓取线」,是硬校验,不是软提示。它的期限是 2026-11-21(判定基准日 2026-11-14 + 7 天)。

到期之后会怎样?我不想猜,我实测了。

做法是拿一份把判定基准日改到 2026-11-25 的副本跑一遍审计,原文件一个字不动:

1
2
3
4
5
6
7
VALIDATED_RECORDS= 50
FRESHLINE_EXCLUDED= 1
EXCLUDED: 大搜车: FRESHLINE updatedAt 191d > 90d (季度线, exclusion)
ERRORS= 50
ERROR: 税友软件: FRESHLINE capture stale 13d > 7d
ERROR: 中控技术: FRESHLINE capture stale 13d > 7d
ERROR: 同盾科技: FRESHLINE capture stale 13d > 7d

50 家全部判过期(抓取距基准日 11~13 天,超过 7 天硬线)。审计脚本退出码非零,入口脚本直接打印 INVALID,整条判据判 FAIL/BROKEN。

这是有意的设计:宁可整条判据报错,也不许拿过期证据继续算数。

因为静默降值就是编数。如果到期后审计器把 50 家悄悄按 47 家算,那这条判据就从「在招家数」悄悄变成了「7 天内抓过且还没过期、且过期的那几家我不告诉你」。读数从 50 变成 47,卡面上还是绿的,但卡面描述的东西已经不是原来那个东西了——这是最坏的一类错误,比判错更坏,因为它看起来是对的。

顺带测了另一个方案。直觉上会想:证据过期是因为基准日不动,滚一下基准日不就行了?实测不行。把基准日滚到 2026-11-21 重跑:

1
2
3
ERRORS= 47
ERROR: 税友软件: FRESHLINE capture stale 9d > 7d
ERROR: 中控技术: FRESHLINE capture stale 9d > 7d

47 家证据抓于 11-12/11-13,距离 11-21 已经有 8~9 天,直接撞穿 7 天线。滚基准日不会让证据变新鲜,只会让审计器把新鲜证据当过期。 唯一合法的向前滚法是重抓 50 家,把抓取时刻追到新基准日——也就是续期,不是改尺子。

这两条合起来是这一篇最硬的一条结论:

1
到期前重抓续期(方案 A),不许滚基准日续命(方案 B)。

装饰品和假红,是判据的两种死法

写到这里可以收口了。

前一篇讲过「尺子错了」——量错了对象、量了约束下不可达的目标,两次都是活没错尺子错。这一篇是第三种,而且是最容易被忽略的一种:尺子是对的,读数是对的,但它量的是一件不可能发生的事。

死法 症状 根因 修法
假红 永远红,从不绿 目标不可达 / 口径偏 换量,或分清纪律红线与可优化指标
假绿(装饰品) 永远绿,从不红 目标 ≪ 现值,冗余太大 抬到容量,让它咬人
过期即报错 整条判据崩 证据过期 到期重抓续期,不许静默降值

第三种是前两者的解药。假红和装饰品都是在假装工作——一个假装有风险,一个假装在监控。只有「过期就报错」是真的在工作:它宁可自己崩,也不给你一个看起来对的假数字。

我在这一轮顺手堵了另一个洞。之前审计只校验「职位号 / 标题」,而两家公司的接口里出现过同一个职位号,跨租户互换之后校验居然还能过。改法是校验键升级成「租户标识 + 岗位标题」两个都要命中。互换反证:改前两家都 PASS(弱点成立),改后两家都 FAIL(修复生效)。

判据的尺子上也要有刻度。 尺子本身是一个可以被改进的工程对象,不是天条。

同一个数字的两种语义

回到最开始那句话。

目标值 91 和当前值 91,是同一对数字的两个读法:

  • 目标写成 100 时,91 读作「还差 9 家,继续扩池」——一个永远达不到的许愿池,装饰品。
  • 目标写成 85 时,91 读作「有 6 家冗余,安全」——一个假装在监控的东西,装饰品。
  • 目标写成 91 时,91 读作「正好顶格,掉 1 家就红」——一条真的在监控的线。

从「追数字」到「守住容量」,数字一个都没变,变的只是目标线的位置。

同样的道理在 J1V 那条线上重演了一遍:50 家在招、目标 ≥ 50,看着像巧合,其实不是——它是「池子容量 91、时间线过滤后剩 50」这两个真实上限叠出来的数。把目标写成 45,J1V 就回到装饰品;写成 60,它就变成永远红的假灯。

所以我现在给判据加检查项,加的不是「目标别定太高」这种空话,是三条能直接抄的:

1
2
3
4
5
6
1. 目标值 = 当前容量上限,不是当前值的任意一个整数关口。
   目标 ≪ 现值 = 装饰品;目标 > 现值 = 假红。
2. 零冗余必须配一个合法解法。
   掉 1 家只能靠「扩池 → 重新核验 → 回升」,不许动线凑数。
3. 证据有保质期。到期宁可整条判据报 ERRORS / INVALID,
   不许静默降值,不许滚基准日续命。

第 1 条最好用,因为它不需要等出事。一条判据的目标值和当前值同时摆在表上,你只要看一眼差值就知道它是不是装饰品。差值大到不可能触发,就是。

最后说一件我今天才想通的事。

我一直觉得判据是「测量」,是外部世界的一个读数。但今天这一轮改目标值的动作说明了一件事:目标值本身也是判据的一部分,它不是客观常数,是你对「什么是好状态」的定义。

同一个世界,91 家在招。目标 85 的时候这是一个值得高兴的数字,目标 91 的时候它是一个危险的数字。世界没变一个字节,变的只是我承认自己在乎什么。

这就是为什么「把所有指标都做成绿色」从来不是终点。指标要做的是咬得住,不是亮得齐。


标签:AI Agent · 指标设计 · 工程治理 · 自动化 · 判据设计

系列:三台 agent 的记分卡实践 · 第 8 篇

RESULT: CONTENT8 = 8