Matrix 卡片规范
今天改过橙色高亮的段落是 2026-09-04 改的,重点看这些。
真身在桶里 data/_spec/02-card.md,这一页是它逐行渲染出来的,没有增删。冲突时以桶里的为准。
改前的版本备份在 data/_spec/_bak/02-card.md.20260904T030726Z。
<!-- SPEC-STAMP: 2026-09-04T12:30+08 | by=本机 | 1.1 结构整段按实际重写(Top20 榜 + ▸ 分段),删掉在玩什么/七国一览/异常概述/小洞察四节模板与 5.4;4.1 榜改成八列 -->
Matrix 卡片规范 · 群里推送长什么样
本篇是龙虾每天干活前必读的三份规范之一。不要用缓存,不要凭记忆执行。
★ 改这份文件、或改 lint.py,一律走 spec.py,不要直接 tos.put。
2026-08-27 本机推的两份改动被整份覆盖过 —— 两边都直接写 data/_spec/,谁后写谁赢。
python3 spec.py get 02-card.md 拉下来改,python3 spec.py put 02-card.md --by 谁 --note 改了什么 推回去;
期间别人动过就会被拒绝,让你先合并。文件第一行的 SPEC-STAMP 记着最后是谁改的。
```
data/_spec/00-pitfalls.md ★ 踩过的坑 —— 每次干活前第一个读
data/_spec/01-analysis.md 怎么分析 ← 卡片和网页共用
data/_spec/02-card.md 卡片长什么样
data/_spec/03-page.md 网页长什么样
```
00-pitfalls.md 拦的是「算错」,这三份拦的是「写得难看」。
算错比写得难看严重得多 —— 新踩一个坑就往那份里加一条。
三份不重叠。分析思路只写在 01,另外两份引用它,不要复制过去 ——
复制必然会有一份先改一份后改,然后两边说的不一样。
本篇只管形态。 结论怎么得出来的、置信度怎么定、余额闸怎么过 —— 全在 01-analysis.md。
零 · 卡片和网页的分工
| 回答什么 | 读者 | 密度 |
|---|
| 群里的卡片 | 昨天发生了什么、为什么 | Lucas、Zoe(老板视角) | 高密度叙述,一屏读完 |
| 网页 | 具体是哪些数、哪个人、哪一条 | 需要往下查的人 | 明细、可下钻 |
一句话判据:
一个信息如果需要读者自己在脑子里做减法或比较,它就该在卡片里被写成句子;
如果读者只有在追查某个具体的人时才需要它,它就该在页面里。
举例:
| 信息 | 去哪 | 为什么 |
|---|
| 「他玩得比昨天还多,但一分真钱没花」 | 卡片 | 这是结论 |
sp_coin=934090 / sp_recharge=0 | 页面 | 这是支撑结论的原始数 |
| 「今日 20 人一览」表格 | 页面 | 老板不会逐行看 |
| 「8 个人在 8/31 同一天到期」 | 卡片 | 这是模式,不是明细 |
★ 文风总则(2026-08-27 重写)
这一节是文风的唯一入口。 和后文 1.3 用词表、3.2 文风四条、4.3 流程黑话、
3.2 文风四条、4.3 流程黑话冲突时,以这一节为准(那几节保留,当历史看)。
为什么重写:08-20 那天卡片被打回六七次,08-25 又被打回五次,没有一次是算错。
之前的做法是每被打回一次就往规范里补一条,补到六层,互相覆盖,
结果是每天都要重新对一遍规则。这一节按「为什么会写歪」来组织,不按「昨天犯了什么错」。
★.0 先想清楚谁在读
Lucas 早上打开飞书,用不到一分钟扫完这张卡。他要知道的只有一件事:
昨天这批人身上有没有发生我该知道的事。
他不关心我们怎么查出来的,不关心多少人触发了什么,不关心口径。
一整条判断标准贯穿下面所有规则:
这句话如果他要问「这是什么意思」,就不能写。
★.1 三种黑话
① 我们干活时用的词。 这类词在我们脑子里有定义,在读的人那里没有。
| 不许写 | 改成 |
|---|
| 触发判定 / 命中规则 | 直接说发生了什么 |
| 烧余额 / 在烧存货 | 不再充值了,还在花账上剩的币 |
| 静默 / 完全静默 | 没打开过 App / 一整天没说话(说清是哪个) |
| 池子 / 监控池 / 在册 | 这批人 |
| 原子 / 批次 / 落库 | 不出现 |
| 自充率 / 池内中位 | 不出现,要看去网页 |
| 零行为 / 全线归零 | 说清哪几件事没做 |
筛查过程整个不写。「74 个人里 13 个触发,排掉烧余额的,剩 3 件」——
这是我们怎么干活,不是业务信息。改成一句:昨天有三件事值得说。
★ 但那个「昨天」要看事件真实跨度,见 §2.2b。
② 把普通事情说成术语。
| 不许写 | 改成 |
|---|
| 真钱 / 真金白银 | 自己充的钱 |
| 掏钱 / 自己掏的 | 充值(动作)/自己充的(那部分币) |
| 赠送币 | 平台送的币 |
| 总消耗 | 总共花掉的币 |
| 体内循环 | 拿平台送的币在里面转 |
| 断崖 / 暴跌 / 崩塌 | 后面必须紧跟数字。2026-09-02 从硬拦降为提示 |
| 集群效应 / 同步归零 | 几个人同一天一起停了 |
| 赌博 / 赌局 | 概率游戏 |
③ ★ 玩家的黑话原样搬上卡。(2026-08-24 的教训,这条最新也最容易犯)
房间里的人管抽奖池叫「箱子」、管上麦位叫「竞价」。这些是他们的叫法。
上卡之前必须先弄清产品上对应的是什么功能;弄不清就写「弄不清」。
08-24 那张卡把「竞价」当成群聊抽奖的别名写进了判断段,实际是两回事 ——
đấu giá 是上座位的动作,rương 是累计消费之后掉的奖励,
而这两个在流水里都查不到对应商品名。
玩家用的词只能出现在判断之外。 引文本身、以及引文后面括号里的中文翻译,
都算引文的一部分 —— đợi xíu rớt rương(等一下箱子掉) 这样写是对的。
2026-08-27 自测时为了躲这条,把「箱子」躲成了一个错字,比直接写还糟。
★.2 什么叫人味
三条,缺一条就会读起来像报告。
① 每句话都有一个人在做一件事。 主语是人,谓语是他干的事。
名词堆叠、被动式、「呈现」「体现」「反映出」「表现出……特征」,全是没人味的来源。
✗ 消费结构呈现向概率玩法集中的趋势
✅ 七个国家的钱基本都花在概率玩法上
✗ 该用户充值行为于 21:02 发生,随后两分钟内启动抽奖
✅ 21:02 他充了 19,250 币,两分钟后开抽
✗ 表现出较强的社交驱动型消费特征
✅ 抽到的礼物他一件没留,挨个点名让房间里的人上去选
② 按发生的顺序讲。 先发生的先写。
倒着写、总分总、把结论提到最前面再回头解释 —— 这三种都会读起来像 PPT。
唯一的例外是事件标题:标题是结论,正文按时间。
③ 用他们自己的词,不用我们的分类词。
他说「口袋空了」,就写「口袋空了」,不要写「余额耗尽」。
他说「今天分家产」,就写「今天分家产」,不要写「进行了大额礼物分发」。
④ 念一遍。 写完把那段念出来。念着别扭、一句要换三次气、
或者听起来像在念文件,就重写。
这一条机器拦不住,但它比下面所有规则加起来都管用。
前面六层规则之所以要每天修,就是因为它们都在管词,没有一条在管「读起来像不像人说的」。
★.3 不许把思考过程写进去
我们怎么判断的,是我们的事。清单(lint.py 已拦):
得分开看 分开报 以后判 以后看到 更能认人 读法 值得往下查
值得单列 为什么必须分开 这条为什么重要 长得一模一样 我们排除了
分析过程全部落 data/{天}/_analysis.md,卡上只留结论和证据。
唯一的例外:拿不准的时候,在那句话后面加个括号说明,不要展开怎么推的。
写成 (公屏上的说法,流水里查不到)、(按上下文对上的,不一定准) 就够了。
★★ 「查不到」不许单独成一个 ▸ 段(2026-09-04 加)。
被打回的原句:
✗ ▸ 有没有人从他的充值里分到东西,查不到 语音里没说,充值订单里也没有付款人这个字段。
用户原话:「查不到为啥要放进去呢?」
一个只说「我没查到」的段落,读的人拿不走任何东西,它写的是我的过程不是这件事。
而且事件标题已经有置信度标(🟡 存疑),等于把同一件事说了两遍。
处理方式:并成上一段末尾的括号,或者整段删掉。
真正该单独写出来的只有一种 —— 这个字段在数仓里根本不存在,
那是别人复查时会重复踩的坑,写进卡尾的灰字说明里,不占事件的段落。
★.4e ★★★ 【风险】类事件是 ★.4「不写未成年人」的唯一例外(2026-09-03 加)
用户原话:「这个洞察很有意义……因为这样可以让我们判断有没有违规」。
★.4 定的是「卡片不写未成年人」,针对的是把未成年用户当消费样本来写。
违规识别是反过来的用途:某个人在麦上自己报的年龄,就是这条线索成立与否的判据,
抹掉它这条事件就没有意义了。
所以:
- 事件标
【风险】,不标 【个人】。落点是「这件事谁该看一眼」,不是「他为什么花钱」。 - 只写他自己说出来的那句话,加上登记信息作对照(登记生日、注册日期),
两者对不上就照实并列,不要替他下结论说他是不是未成年。
- 不写表演内容本身,只写这个局的规则、谁在主持、拿什么交换。
lint.py 的 未成年|未满 18|1x岁 三条仍然拦着,所以写法上就是引原话(「我还不到十八岁」),
这既过闸也更硬 —— 原话比我的转述可信。
判据来源和写法见 14-voice.md §7。
★.4 ★★ 事实、推断、不知道,三者不许混在一句里
08-24 那张卡最严重的问题不是数字错,是这三样搅在了一起。
| 来源 | 怎么写 |
|---|
| 流水里读出来的 | 直接写,不加限定词 |
| 从公屏原话推出来的 | 必须带一个词标出来:他自己的说法是 公屏上是这么叫的 看起来 |
| 查不到的 | 直接写「查不到」,不要用推断填 |
✗ 反例(08-24 原文):
他的钱花给的是一屋子有固定称呼关系的人,换回的是「爷爷」这个位置。
前半句是事实,后半句是推断,而且那个推断建立在把用户名当成了称号。
✅ 改法:
抽到的礼物他一件没留,背包送出 99,417 币给六个人。
同一时段房里十个人在抽奖,他一个人占 20,270 币里的七成。
★.4b ★★★ 什么不算一条事件
卡片上的每一条都必须是昨天这批人身上发生的事。下面三类不是,写进去就是凑数。
① 常态。 每天都这样的东西不是新闻。
2026-08-27 自测时我写了「Zoo 一天 281 万流水,平台只留下 6.7 万」。
数字没错,但 Zoo 天天如此(08-21 是 4.9%、08-25 是 2.4%、08-26 是 1.7%),
这是这个玩法的固有属性,属于口径文档,不属于日报。
判据:把同一句话套到上周任何一天还成立吗?成立就别写。
② 我自己的错。 口径读错、字段理解错、之前算错,都是我的工作,修掉就行。
同一次自测里我写了「我们数据里的『红包』不是红包」,因为我发现那一列取的是
scene_id=5 的合计。这条对我们有用,对读卡片的人没用 —— 他们本来就不知道我误解过。
这类东西的出口是修 SQL 和口径文档,不是卡片。
③ 把大数字重念一遍。 「某玩法 281 万,其中 109 万来自一个人」,
读完之后没有任何人需要做任何不同的事。
判据:这条如果去掉,谁会少知道一件他该知道的事?答不上来就删。
④ 我这次做不到什么。(2026-09-03 用户打回后加)
「样本不够」「没有可比记录」「这几天不能下判断」「口径所限」「等埋点修好再说」——
这些是我的工作条件,不是昨天发生的事。
被打回的原句(09-02 那张卡):
能不能比 名单 140 人里有 112 人这个月刚进榜,过去六天没有可比记录,
所以「他停了」「他回来了」这类判断这几天都不能下。真正能比的只有 28 人。
用户原话:「你的结论是没意义的为啥要放出来啊」。
判据和 ③ 一样:这条去掉,谁会少知道一件他该知道的事?
「Matrix 这次少做了点」不算一件他该知道的事。
做不到就少写一条。 卡片本来就允许只有一条事件(§3.6),
用一段话解释为什么只有一条,比直接只有一条更差。
例外只有一种:别人需要动手才能修的东西(埋点坏了、字段缺失、分区没落)。
那些走私聊和 12-daily-run 的收尾,不进卡片正文。
★.4d ★★★ 一条事件的落点是动机,不是数字
数字只是入口。读完这条,读的人要知道这个人为什么这么做。 答不出「为什么」,
这条就还没写完,不要因为数字查干净了就发出去。
2026-08-27 的实例。起点是一个数字异常:08-05 名单内花币看着持平,
排掉 Lý Thất Dạ 之后掉三成,他一个人当天花了 482,547 币。
到这里为止只是「一个人花了很多钱」,没有信息量。往下走三步才到落点:
钱去哪了 → 背包进出:抽奖抽出 469 件礼物进背包,当天送出 195 件、111,513 币
给了谁 → 其中 84 件、64,703 币给同一个人,占 58%,前一天给她只有 124 币
为什么 → 私聊:「你现在活动榜第 3」「你好像掉出前 3 了」「拿到两只猫就能上第 3」
落点是「他在给她刷活动榜」,不是「他花了 48 万币」。
追问顺序固定,不许在任何一步停下来说「还没串上」:
| 步 | 问题 | 去哪查 |
|---|
| 1 | 钱变成了什么 | coin_bill 按 commodity_name 拆 |
| 2 | 东西给了谁 | gift_receive_bill 的 target_user_id;背包走 B7 的 source |
| 3 | 为什么给他 | 私聊 ods_soc_chat_msg_v1_sd、公屏 CHAT_ROOM_MESSAGE |
| 4 | 结果是什么 | CP 亲密值、家族贡献、名次 |
「要看 X 才知道」这句话不许出现在卡片上,也不许出现在给用户的回复里。
X 是可以去查的,那就去查。查完还是不知道,写「查不到」并说清卡在哪一步。
★.4c ★★★ 但下面这些就是事件,别被 ★.4b 误伤
★.4b 说的「常态」指的是系统层面的固有属性(某个玩法的返奖率、某张表的口径)。
个人层面的偏离永远是事件,哪怕每天都有某个人在偏离。
判据不是「这种事常不常见」,是「这个人今天和他自己平时比,变了没有」。
已经写在 06-judgment.md 里的信号,卡片要主动去找:
| 信号 | 怎么算 | 出处 |
|---|
| 冲动消费 | 当天充值 ÷ 他自己本月其他有充值日的均值。倍数排序,不看绝对额 | J5「单日充值没有信息量,要看节奏」 |
| 断充 | 连续零充值的天数,同时看这几天他还花不花币。断充+还在花=在烧存货;断充+不花=真停 | J3、J20 |
| 断充之后回来 | 零充值 N 天后突然充。N 越长、回来的金额越大,越值得看 | J20 |
| 关系变化 | CP 名单增减、亲密值单日跳动、私聊对象换人、家族进出 | J4「加码经常发生在关系断裂之后,不是之前」 |
| 支付失败 | 一次失败的支付经常是行为改变的起点 | J17 |
| 平稳 | 一直平稳的人本身也是信号,选人不能只选数字异常的 | J23 |
这几类的共同点:它们都是「这个人变了」,不是「这个盘子一直这样」。
2026-08-27 撤掉的那两条(Zoo 返奖率、红包口径)都是后者。
同一天留下的 Bao 那条是前者:三天零埋点之后回来,第一句话问充值入口。
★ 凑数是根因。 上面两条都是同一个动作的产物:只有一件真事,硬要凑够三条。
规范里本来就写着「没有可说的就整块不出现」,事件层面同样适用。
一条真的,好过三条里有两条是填充。
★.5 句式黑名单
- ~~「不是 X,而是 Y」~~ 2026-09-02 降为提示,不再硬拦。
09-01 那张用户认可的卡在这个句式上用了四处,而且正是撑住结论的那四句
(「不是随口提,是在拉人和卖币」「这不是抱怨,是两个人互相确认退出」)。
仍然要控量:一张卡里别超过两处,多了就成了口头禅。lint.py 只提示不拦。
- 三段式 —— 先铺垫、再转折、最后升华
- 结尾总结句 —— 「这说明……」「值得注意的是……」「背后反映出……」
- 破折号
——,以及它后面那截解释。 一个都不许有。
这是最顽固的一个 AI 腔:抛一句结论,破折号,再补一句解释为什么。
要么把解释写成独立的一句话,要么承认这句解释是多余的,删掉。
> ✗ 他没走,换了个号 —— 花钱一天都没停
> ✅ 他没走,换了个号。花钱一天都没停
> ✗ 全天抽掉 20,270 币 —— 钱进来即刻变成抽奖
> ✅ 21:02 到账,21:04 开抽
- 生造词:「点着」「拉满」「打透」「拉起来了」
- 满屏加粗。一段最多一个加粗,就是段首那个标签
- 感叹号,以及 😂🤣
★.6 数字怎么写
同构的罗列句不算(群聊抽奖 20,270、Zoo 18,227、Lucky777 785 这种读起来不累,随便列)。
这条 lint.py 只提示不硬拦 —— 2026-08-27 拿它回测 08-24 那张已发出去的卡,
硬拦会拦下七处,说明按原样写死是不现实的
- 变化用箭头:
36 → 16,不写「掉了一大半」 - 每个数字都要经得起一句追问:为什么是这个数。 算不出来的就不写
- 临时窗口的均值(「十三天日均」这种)不是口径,不许当基线
- 币一律写币,不折人民币(充值本身除外)
- 时间统一用数仓时间(UTC+8),在口径行里说明一次,正文里不再标时区
★.7 名字
昵称是专有名词,一律原样照抄,不译、不注中文对应,引文里也照抄。
昵称不能当判断依据 —— 它不携带任何行为信息。详见 3.1 ⑦。
★.8 写完自己过一遍(两分钟,机器拦不住的部分)
- [ ] 每段念出来顺不顺
- [ ] 有没有哪句话的主语不是人
- [ ] 有没有把「我怎么判断的」写进去
- [ ] 事实和推断有没有混在同一句里
- [ ] 玩家的黑话有没有跑到判断段里
- [ ] 每个数字能不能回答「为什么是这个数」
- [ ] 最后一句是不是总结句 —— 是就删掉
一 · 结构与形态
1.1 结构(顺序不变)
【1】标题栏 颜色跟当天最高等级,日期是【推送日】(见 1.2)
【2】开场 **本月充值最高的这批人,昨天在干什么** + 两三句
【3】大R的动态 **大R的动态** + **昨天** 当天充值超 ¥1,000 的有几个人、最高的是谁
【4】Top20 榜 **全站本月充值 Top20** + 灰字口径,紧跟一张 tag:"table"
【5】承接句 「昨天有 N 件事值得说」,一句,见 2.2b
【6】今日大事件 最多 5 条。每条一个标题元素 + 若干 ▸ 段,每段一个独立元素
【7】按钮
每一块是一个独立 element,事件的每个 ▸ 段也各占一个 element。
不要把多段塞进同一个 element,否则 lint.py 的分段检查会全部失效。
各块的写法
【2】开场 粗体标题独占第一行,换行后跟两三句。说清三件事:这批人昨天一共充了多少、
花掉多少币、这些币里自己充的占多少。不要用「触发」「命中」这类流程词开头。
【3】大R的动态 粗体小标题 昨天 后面跟一个全角空格再接正文。
写当天充值超过 ¥1,000 的有几个人、分布在哪几个国家、最高的是谁(昵称 + UID + 金额)。
【4】Top20 榜 标题行 全站本月充值 Top20 <font color='grey'>口径</font>,
灰字里写清楚统计窗口、折人民币、名单每天重算、各国分榜在网页里。紧跟一张原生表格:
| name | display_name | align | 宽 |
|---|
no | # | left | 80px |
nick | 昵称 | left | 160px |
cc | 国家 | left | 80px |
month | 本月充值 | right | 100px |
yday | 昨天充值 | right | 100px |
play | 昨天主要在玩 | left | 130px |
net | 昨天净流水 | right | 110px |
uid | UID | left | 110px |
page_size: 20、row_height: "low"、表头 background_style: "grey" + bold: true。
没有充值的那一格写 —,不要写 0。
【6】事件 标题格式见 4.5b,末尾用灰字接置信度:
**1 【个人】昵称(UID 40645486,越南)+ 他做了什么**<font color='grey'> 🟢 最置信</font>
标题下面是若干 ▸ 段,每段一个独立 element,体例:
**▸ 一句能听懂的标签** 这一段的正文。
标签要是一句话(「▸ 停充不是突发,是走了八个月的下坡」),不是分类名(「▸ 数字」「▸ 原话」)。
详见 5.3b。
改动记录 · 2026-09-04(整段重写)
原来这里写的是七块结构:标题栏/在玩什么/七国一览/异常概述/今日大事件/小洞察/按钮。
那套从 08-31 起就不用了,中间那三块(在玩什么、七国一览、小洞察)现在推的卡里一块都没有,
主表也从七国表换成了 Top20 榜。规范拖了五天没改,期间照它做的两张卡:
09-02 那张只发私聊没推群、当天下午被换掉,09-04 早上那张结构是混的。
「在玩什么」「七国一览」「异常概述」「小洞察」四节的模板已随本次一并删除。
没有第八块。 不要加统计摘要、不要加人员一览表、不要加「扫描 N 人」,
也不要再加「判定本身有多准」那一块(2026-08-20 撤,理由见 01-analysis.md §2.4)。
单国卡(For 一百、For 少羽这类)的榜只放他关心的那个国家,其余相同。
1.2 标题栏
飞书卡片 header 的 template 字段跟当天最高等级走:
| 当天最高等级 | template | 标题前缀 |
|---|
| 有高危 | red | 🔴 |
| 只有中危 | orange | 🟠 |
| 没有异常 | green | 🟢 |
标题文案:
| 卡 | 标题 |
|---|
| 总卡(七国) | Matrix · 七国大R Top20 · 2026-08-16 |
| 单国卡 | Matrix · 印尼 Top20 · 2026-08-16 |
2026-08-20 起监控池是七个国家共 74 人,不再只有印尼。
★★ 标题里的日期是【推送日】,不是业务日(2026-09-04 定死)
| 写什么 |
|---|
| 标题 | 今天的日期(推送日)。09-04 推的卡就写 2026-09-04 |
| 正文第一句 | 「昨天是 09-03」。业务日只出现在这里 |
| 桶里的文件名 | site/cards/{推送日}.html、data/_day/{推送日}.card.json,和标题一致 |
| 「看昨天」按钮的 URL | 推送日 −1,lint.py 的 url_day() 已经在查这个 |
自洽判据一句话:标题日期 = 正文「昨天是 X」的 X 加一天。 两者相等就是错的。
★ 这条是 2026-09-04 一次覆盖事故之后定的。 那天把标题写成了业务日 2026-09-03,
文件名跟着标题走,于是 data/_day/2026-09-03.card.json 和 site/cards/2026-09-03.html
覆盖了前一天人已经定稿并推群的那张卡(原件 11,713 字节 / 10 个元素)。
桶没有 delete 也没有版本控制,JSON 结构不可回滚,只能从群消息把正文逐字捞回来,
事故说明留在 data/_day/2026-09-03.card.REBUILT-NOTICE.json。
**所以覆盖任何一个 card.json / cards/*.html 之前,先 GET 一次那个 key。
非空就停下来报,不许直接覆盖。**
名单见 data/_spec/countries.json,各国 n 不同(印尼/菲律宾/越南各 20,
伊拉克 9,泰国 2,沙特 2,埃及 1,土耳其在册 0 已剔除)。
不足 20 人的国家照报,不要因为人少就跳过 —— 埃及只有 1 个人,
他停了就是这个国家的全部。
1.3 ★ 用词表(硬规则,出现即不合格)
已并入 ★文风总则 ★.1,冲突以那边为准。
| 不许写 | 改成 |
|---|
| 静默 / 完全静默 | 没上线 / 没打开过 App / 一整天没说话(看具体指哪个) |
| 真钱 / 真金白银 | 自己充的钱 |
| 掏钱 / 掏真金白银 / 自己掏的 | 充值(动作)/自己充的(那部分币)。 「只有掏钱这个动作停了」→「只有充值这个动作停了」 「那才是他必须重新掏钱的时点」→「那才是他必须重新充值的时点」 榜里的列名也从「自己掏的」改成「自己充的」 |
| 赠送币 | 平台送的币 |
| 总消耗 | 总共花掉的币 |
| 断崖 / 暴跌 / 崩塌 | 后面必须紧跟数字。2026-09-02 从硬拦降为提示 |
| 集群效应 / 同步归零 | 说人话:几个人同一天一起停了 |
| 体内循环 | 拿平台送的币在里面转 |
| 压 / 压在 / 压给 / 压上去 | 花 / 花在 / 投在。「九成压在概率玩法上」→「九成花在概率玩法上」。 「压」是下注的说法,卡片一律不用,跟「赌」同一条线(2026-09-03 用户打回) |
| 能不能比 / 可比性 / 没有可比记录 | 不写。这不是一件事,是我自己的工作条件,见 ★.4b ④ |
原则:任何一个词,如果 Lucas 需要问「这是什么意思」,就不能用。
1.4 ★★ 排版规则(这条决定读不读得下去)
~~一段话不许超过 3 句。~~ 2026-09-02 取消,跟字数上限一起拆的。
段落长短按内容分:一段说一件事,说完换段。
叙述句一句最多 2 个数字,第 3 个就该换句。
同构的罗列句不算(WaltzRomance 抽 2 送 2、FlamingRose 抽 313 送 10 这种),
lint.py 只提示不硬拦。为了躲这条把一句拆成三句、或者干脆少写一个数,
比多一个数字更糟。
总述必须分成 3~4 个自然段,每段讲一件事,不要用破折号和逗号把四件事串成一段。
每条事件的正文也要分段,固定三段:
(第一段)他昨天做了什么
(第二段)他说了什么,带时间
(第三段)判断:……
✗ 反例(250 字一段,没有落点):
昨天这 20 个人的整体消费风变了。头部的人还在玩,但掏真钱的意愿明显缩回去——
充值最高的一位从前一天的 333 万骤降至 6 万,总消耗同步跌了七成多,房间还在泡
但操作量砍了近半。最活跃的那位更极端:操作次数反而涨了三千次到两万三……
✅ 正例(同样的内容,四段):
昨天这 20 个人还在玩,但自己掏钱的明显少了。
充值最高的那位从前一天的 333 万掉到 6 万,房间照泡,操作量砍了近一半。
最活跃的那位反过来 —— 操作次数还涨了三千次,但自己掏的钱从近三万掉到零,
全靠平台送的币在转。他自己说:「运气用完了,以后只下小注。」
另一边有两个同家族的人一整天没上线,前一天他俩还充了近 90 万。
也有反向的:一个前一天没花钱的人突然充了 267 万。
事件标题一行读完。 超过一行就是太长了。
✗ N⃟X⃟ NATTA (31109636) + N⃟X⃟ Vancha (32449161) 同族同日完全静默
✅ 同一个家族的两个人,昨天一起不见了(人名放正文第一句)
1.5 ★★ 视觉规范(2026-08-20 补 —— 「可视化效果一般」的整改)
2026-08-20 更正:之前这里写「等宽代码块是唯一能对齐的东西」,是错的。
飞书卡片支持原生表格组件(tag: "table"),Lai 的《Daily Top-up Report》就是用它做的 ——
有表头底色、斑马纹、右对齐数字、以及带背景色的涨跌胶囊。视觉规格比代码块高一档。
| 手段 | 用在哪 | 注意 |
|---|
原生表格 tag:"table" | Top20 榜,以及以后任何一张主表 | 硬规则,不是首选。 列设对齐和格式,涨跌列用 options 出彩色胶囊 |
等宽代码块 ``` ` ``` | 只准用在不是主表的补充小表 | 不许拿它做主表。 真要退回代码块,必须在卡里写一句为什么 |
块字符 ▁▂▃▄▅▆▇█ | 迷你走势(sparkline) | 放在表格单元格里也能用,因为它就是普通字符 |
条形 █ / ░ | 占比类,固定 10 格 | 只表示 0~100% 的比例,不表示绝对值 |
箭头 → | 变化 | 36 → 16,不写「大幅下降」 |
<font color='grey'> | UID、置信度、次要信息 | 只有 grey / red / green 三种够用 |
不要用:emoji 当图标堆在行首、多列 column_set(窄屏会挤成一坨)、
img 图片(要先上传拿 img_key,多一个失败点,龙虾在云沙箱里渲图这条路没验证过)。
⚠️ 表格组件的 JSON 结构必须先在测试群发一张验证过再用到正式群。
渲染行为跟飞书客户端版本有关,没在真机上看过就不算数。
2.2b ★★ 承接句里的「昨天」不是默认词(2026-09-02 加)
昨天有 N 件事值得说 这一句,只有在事件真的都发生在业务日那天才能这么写。
09-01 那张卡写了「昨天有两件事值得说」,可两条事件一条跨 15 天
(8 月 18 日到 9 月 1 日的 12vibe 扩散),一条跨八个月(cửu nhi 的充值下坡),
没有一件是昨天发生的。用户 09-02 指出来。回查五张卡,三张都这么写。
根子在于卡片有两种时间尺度,被同一句话盖住了:
| 块 | 时间尺度 |
|---|
| 榜单、当天充值、花币、净流水 | 确实是业务日那一天 |
| 事件 | 越写越好之后,多数是趋势和过程,跨天甚至跨月 |
怎么写:
| 事件都在业务日当天 | 昨天有 N 件事值得说 |
| 跨了几天到两周 | 近期有 N 件事值得说 |
| 跨度明确且值得说 | 直接写出来:过去两周有两件事值得说 八月以来有一件事 |
lint.py 会拦:承接句写「昨天」而事件正文里出现 ≥2 个不是业务日的日期,判不合格。
顺带一条:事件跨期不是缺点。 「她走了八个月的下坡」比「她昨天没充值」有用得多。
要改的是那句承接词,不是把事件砍回当天。
没有异常的时候这一块写「今天没有人触发判定」,然后第 5 块整个不出现。
2.3 今日大事件(第 5 块)
最多 5 条。(2026-08-20:原来是 3 条,改成 5) 每条按这个顺序,全文字:
N. 【昵称 (UID)】 一句结论 〔置信度〕
他昨天做了什么 —— 玩了什么、花了多少、在不在房间、和谁在一起。
(时间)他说:「中文翻译」
判断:为什么会这样,最可能的解释 + 排除了什么。
顺序不能反:先行为,再原话,最后判断。 原话孤零零挂着没有意义 ——
读者要知道他说这句话之前在干什么、花了多少钱。
每条都要带置信度,写在标题行末尾,用 <font color='grey'> 灰字。见 01-analysis.md §2.4。
真实例子(08-16 的数据,可以直接用):
1. ꜰᴏᴏʙᴀʀ (12927899) 玩得比前一天还多,但一分钱没自己充 最置信
全天操作 22,983 次、投出 93 万币,比前一天还多了近三千次。
但这 93 万全是平台送的币 —— 自己充的从前一天的 28,788 掉到 0。
07:06 他说:「故意的,让他们充值」
07:07 又说:「我要一直玩,但只下小注,重点是 fruit 下 100」
判断:策略切换,不是流失。他玩得更多了,只是不再自己充。
⚠️ 上面这条之所以能给「最置信」,是因为他自己在聊天里说了为什么。
同样的数字形态,如果聊天里什么都没有,只能给「推测」,而且多半根本不该上卡 ——
见01-analysis.md §2.1 的余额闸。
事件正文的写法(原话怎么串、数字留几个、置信度怎么定、群体事件怎么写)
全部在 01-analysis.md 第二节,这里不重复。
2.3b ★★★ 写今天这条之前,先读前七天的卡片(2026-09-03 加)
用户原话:
比如那个 Joynaaa 什么的,前几天卡片推送,不是说他和 CP 闹掰了吗,还是吵架了,
所以你应该每一天的推送,再参考前几天的卡片的一些事件作为记忆补充去看。
同一个人在卡片上出现第二次,就不能当第一次写。
桶里 site/cards/{日期}.html 存着每天推过的卡,site/cards/_index.json 是目录。
写卡之前把最近 7 天的卡拉下来,按 UID 和昵称各检索一遍。命中的人,三件事必须做:
- 上一次写他的时候,结论停在哪。
「他明天还充不充,是这条能不能坐实的唯一验证」这种话,今天必须给答案。
给不出答案就说「昨天那条的验证还没到」,不能装作没写过。
- 上一次写到的关系、对象、家族、目标,今天还在不在。
CP 断了、家族退了、主收礼对象换人,这些本身就是事件,而且是只有对照前几天才看得见的事件。
- 今天这条和上一条如果矛盾,先说哪一条错了。 不许两条并存。
没有连续性的日报只是七份互不相干的快照。
一个人昨天「一天充掉本月十二倍」,今天不写他充没充,昨天那条就白写了。
lint.py 不查这个,因为它查不了。这条靠 §3.8 的产出前自检。
3.1 硬规则
① 卡片里一个字段名都不许出现。
ch_sent / rm_stay / sp_recharge / pl_like_out / base_days 这些是内部字段名,
读者看到只会问「这是什么」。数字要,字段名不要。
| ✗ 不许写 | ✅ 要写成 |
|---|
ch_sent=0 + rm_stay=0 + pl_like_out=0 | 9 天没发过一条消息、没进过房间、没点过赞 |
ch_recv=5 说明仍有人发消息 | 但这 9 天里有 5 个人给他发过消息,是他单方面不说话 |
sp_recharge 7d=1 vs 基线×7=66644 | 近一周真钱投入几乎归零,前七周平均是六万多 |
② 不许出现裸 UID。
一律「昵称 (UID)」,UID 小字灰色。昵称读 data/id/nick/{最新}.json。
③ 原话只放中文翻译,不放原文。
卡片会被转发和截图。原文留在页面里,信息量不减,风险小得多。
④ 不写建议动作。
「建议运营介入」「可考虑发放福利」这类一律不写。Lucas 明确说过太话术。
⑤ 归因里的对照组和周期假设,必须带数字。
算不出来就不写这句,不要用空话占位。
| ✗ | ✅ |
|---|
| 对照组假设:大盘无同步下降趋势 | 同期另外 19 个人的真钱投入合计还涨了 3% |
| 周期假设:非已知的季节性低谷 | 他过去 60 天出现过 3 次连续零充值,最长 4 天,这次已经 9 天 |
⑥ 不出现同事姓名,不出现「本系统采用……」这类实现自述。
⑦ ★ 昵称是专有名词,一律原样照抄,不译、不注中文对应。
哪怕它字面就是个普通词。ông nội 不写成「爷爷」,chị 13 不写成「十三姐」,
Thập tứ 不写成「十四」,Lǎopó 不写成「老婆」。
引文里的昵称同样保持原文 —— Đúng là ông nội có khác 译作「不愧是 ông nội」。
起因:2026-08-24 越南那张卡把 ông nội 译成「爷爷」,接着推出
「满屋子人管他叫爷爷」「他花钱换回的是『爷爷』这个位置」,整个判断段
建立在把用户名读成尊称上。人家本来就叫这个名字。
昵称永远不能当判断依据,它不携带任何行为信息。
连带一条:越南语的 con/dượng/má、印尼语的 bang/kak 是日常人称代词,
不是角色扮演或亲密关系的证据,不许拿它们推关系。
名单人数有限(七国 110 人),昵称直接固定下来即可,不存在「读者看不懂」的问题。
3.2 ★★ 文风四条(2026-08-19 补)
已并入 ★文风总则 ★.2/★.5/★.6,冲突以那边为准。第 ④ 条「归因必须落到具体的人」仍然有效。
① 「不是 X,而是 Y」少用,不再禁用(2026-09-02 改)。
能用数字说清就用数字;数字说不清「这件事到底是什么」的时候,这个句式是对的。
✗ 不是人走了,是大额用户不见了 ← 这句该换成数字
✅ 人数只少了两成五,人均 36 → 16
✅ 不是随口提,是在拉人和卖币 ← 这句换不掉,它说的是性质不是数量
② 数字用箭头,不要用形容词。
✗ 人均从 36 元掉到 16 元,少了一大半
✅ 人均 36 → 16
✗ 收入暴跌到常态的三分之一
✅ 收入 3,351 → 1,084
③ 文字结论和归因放前面,数字放后面。 数字是支撑,不是主体。
④ ★★ 归因必须落到具体的人。
光有数字变化不叫归因。「大额用户消失了」只是现象。归因是三步:
① 具体是【谁】消失了 —— 昵称 + UID
② 去 data/{cc}/raw/ 里检索这个人【近期的聊天记录】
③ 推测【发生了什么】,能引用原话就引用(只放中文翻译)
实例(2026-08-19 实测,可以照着写):
伊拉克掉到常态的三分之一。四个大额用户在 8 月 12 号前后集体停手,人没走。
عَـلاوي (32699411) 8 月 12 号 07:25 在私聊里说:「够了,我说过之后不再充值」。
当天最后充 1,045 元,之后六天一笔大额都没有。
数字堆砌不是归因。 这是最核心的一条。
3.3 按钮与话题
底部按钮(先都用 URL 跳转)。2026-08-31 换了地址,照抄下面这两行:
B = https://popup-tianwang.tos-s3-ap-southeast-1.bytepluses.com/site/
[ 看大R明细 ] → {B}dr-4b7e19c8a2/index.html?d={D}
[ 看昨天的卡片 ] → {B}cards/index.html?d={前一天}
第二个按钮从前指的是 cards/{前一天}.html 这张单页。
现在指归档站 —— 一个页面里能翻到每一天,翻错一天不会掉进死链。
cards/{D}.html 这张单页照旧要传,归档站读的就是它。
★ 传 site/cards/{D}.html 必须带 ACL='public-read'。
2026-08-28 到 08-30 三天连着漏了这一条,按钮点开是一段 AccessDenied 的 XML。
漏了也不用重传,12-daily-run.md §11 那条收尾命令会扫出来补上。
★ 卡片里不许出现任何「有问题请在话题里问」之类的引导语。(2026-08-20 修)
这句话曾经写在这里,导致卡片底部印了一行「有问题直接在这条消息下开话题问」——
那是废话:话题按 1.7b 是发完卡片自动 reply 开的,用户点开就能问,
不需要卡片自己教。引导语只出现在 1.7b 那条 reply 里,卡片正文里一个字都不要。
3.4 ★★ 话题怎么开(2026-08-19 实测通过)
飞书不需要群开话题模式 —— 任何消息都可以被 reply 起话题。
每张卡片发出之后,立刻在它下面回一条引导语,话题就开了:
1. 发卡片(普通 messages-send) → 拿到 message_id
2. 立刻 messages-reply --message-id <卡片id> --reply-in-thread
发一条引导语 → 话题开了
3. 有人在话题里追问 → 收到带 thread_id 的消息事件
4. messages-reply --message-id <用户消息id> --reply-in-thread 在同一话题里答
引导语的写法:一行,带两三个可以照着抄的例子(形式参照群里审讯局那张卡):
📊 在这个话题里直接问,不用 @我。例:「XXX 这周还充过钱吗」「菲律宾还有谁在代充」
带例子和不带例子的差别很大 —— 不带例子的话没人知道能问到多细,话题就空着。
例子要用当天卡片里真出现过的人和事,不要写通用模板。
为什么每张卡都要单独开话题:一张卡只能挂一个话题。
总卡、For 一百、For 少羽、For 何川 各自一张卡、各自一个话题,
四个人各问各的,问答历史天然按人归档,不会串。
被追问时先查桶,不要重跑数仓。 只有三种情况才回数仓:
字段不在原子里、时间早于回填起点、人不在监控池。
回数仓前先说一句「库里没有,我去数仓跑」,让人知道这次会慢。
3.5 ★★★ 推几张卡:总卡必推 + 个人卡按需追加(2026-08-19 定,别合并)
总卡 每天必推,发全群。各国 Top20 在玩什么、在抱怨什么 ← Lucas 最想看的
没触发个人阈值的人,在总卡里一句话带过就行
个人卡 只在触发【该人自己的阈值】时才追加
For 一百 / For 少羽 / For 何川
没触发就不发 —— 不要为了「今天也有一张」而凑
为什么分卡不分段,理由只有一条:一张卡片只能挂一个话题。
四个人在同一条卡下面追问会串成一锅粥。分开发=一人一个话题,
问答历史天然按人归档,明天回头翻也找得到。
这条不许优化掉。 「合成一张卡、用分隔线分四段」看起来更省事,
但话题会串,追问就废了。
个人卡和总卡的差别
| 总卡 | 个人卡 |
|---|
| 频率 | 每天必推 | 只在触发阈值时 |
| Top20 榜 | 全站 20 人 | 只放他关心的那个国家 |
| 事件 | 七国里最值得说的 5 条 | 只放触发他阈值的那几条 |
| 按钮链接 | 七国总页 | 他自己的页面视角 ?view=yibai / ?view=hechuan / ?view=shaoyu |
| @ 人 | 不 @ | 也不 @(太打扰,2026-08-19 明确定过) |
| 话题 | 单独开 | 单独开 |
各人的阈值
阈值写在 01-analysis.md §2.8,不在这里。 它决定的是「今天该不该给这个人发卡」,
属于判断,不属于形态。这里只说清一件事:
阈值没确认的人,个人卡不要发。 截至 2026-08-20,只有一百的阈值是确认的;
少羽和何川的访谈答卷还没回来。拿总卡的规则凑一张给他们,
等于替他们决定了他们该关心什么。
⚠️ 已知缺口:页面的 ?view= 还没做。 2026-08-19 定的是页面从
「按数据类型分四块」改成「按人分视角」,目前页面还是四块的老结构,
?view=yibai 打开不会有任何变化。个人卡的按钮在这条补上之前只能先指总页。
3.6 零事件和失败态
events 为 0 条时照推,绿色标题,正文只有总述:
今天这个盘子上没有值得单独说的事,20 个人都扫过了。
不要为了填满而编事件。
失败时的处理见《任务书》,但有一条在这里强调:
利用「更新消息」能力,全天只发一条消息,原地更新。
群里全天只出现一条消息,而且只在 11:30 出现。
09:00 ~ 11:30 取数、分析的所有中间状态 → 走单聊 DM,不进群
11:30 群里发一条:最终结果
(跑不出来时) 群里发一条:今天跑不出来,原因是 X
不要发「今天在跑」这种占位卡片 —— 没有信息量,只是多一条消息。
「更新消息」这个能力留给:发出去之后发现错了,原地改掉,而不是再推一条。
3.7 ★★ 出口检查器(不是提示词,是拦截器)
data/_spec/lint.py。卡片 JSON 发出去之前必须跑一遍,不通过不许发。
python3 lint.py card.json # ✅ 通过,无违规 / ❌ N 处违规
它检查的是光靠提示词管不住的东西——同样的错误已经犯过三次:
| 拦什么 | 为什么要机器拦 |
|---|
| 「不是 X,是 Y」及其变体 | §3.2① 早就写了,还是每次都会写出来 |
| 用词表里的禁词 | 静默/真钱/赠送币/总消耗/断崖/体内循环 |
| 「赌」字 | 一律「概率游戏」 |
| 建议动作 | 「建议运营介入」这类 |
| 😂🤣 | 任何输出都不许出现 |
| 字段化表达 | 「零行为」「全线归零」读者看不懂 |
新发现一种写法不合格,就往 BAN 里加一条正则,不要只在规范里写一句「不要这样」。
规范约束的是注意力,检查器约束的是结果。
3.8 产出前自检
不过就不写桶,推一条「自检未通过」+ 原因。
卡片:
- 全文搜
ch_、rm_、sp_、pl_、_cnt、_amt —— 必须 0 命中 - 全文搜纯数字 UID —— 每个都必须跟在昵称后面的括号里
- 原话只有中文,没有原始语言
- 没有「建议」「可考虑」「应该」开头的句子
- 总述段是一整段,不是分点
- 事件最多 5 条(§1.1/§2.3 的口径,2026-09-02 从「不超过 3 条」改回,原来跟正文打架)
6b. 全文搜「静默」「真钱」「真金白银」「体内循环」「集群效应」—— 必须 0 命中
(「断崖」2026-09-02 移出硬拦,后面跟着数字就行)
6c. 没有任何一句超过 2 个数字(罗列句除外);总述分成了 3~4 段
(「每段不超过 3 句」2026-09-02 取消,跟字数上限一起拆的)
6d. 「不是 X,而是 Y」全文不超过两处(2026-09-02 从 0 命中改为 ≤2)
6e. 每条事件的归因都落到了具体的人(昵称+UID),不是只有数字变化
6f. 每张卡发出后都跟了一条 --reply-in-thread 的引导语,话题开了
6i. 信息完整性(2026-09-02 加,防的是「写太简略把信息漏掉」)。
每条事件逐条问一遍,缺一项就是写漏了,不是写短了:
- 有没有可核的具体物?域名、房名、家族名、玩法名、页面标题、订单笔数
- 有没有带人的原话?谁说的写清楚,不要「有人说」「多人表示」
- 有没有时间点?哪天、几点,能精确就别写「最近」
- 有没有对照?跟前一周、跟同一批别的人、跟自己之前比
- 有没有反方向的数?削弱自己结论的那个数字也要写,写了结论才站得住
(09-01 那张五项全有,砍到 90 字之后只剩第一项。)
6g. 推之前重新从桶里拉一次 data/_day/{D}.card.json,不要用上一轮生成的内容。
2026-09-02 出过一次:当天早上生成的卡按旧字数上限写,中午规范改了,
下午原样推出去,三分钟后撤回。规范管「明天怎么写」,管不到已经生成的文件。
6h. 拉下来之后跑一遍 lint.py。 它现在会拦「旧预算指纹」——
事件 ≥2 条而整张卡最长一段 ≤90 字,判不合格。
确实要推短卡,设 MATRIX_LINT_ALLOW_SHORT=1 再跑,别改代码。
- 标题颜色和当天最高等级对得上
页面:
data.json 八个顶层键齐全,缺的填 nullalerts[].why 是数组;events[].evidence 用 k/v;alerts[].evidence 用 label/from/toroster[].series 四条数组各 60 个元素roster[] 每人都有 nick- 全文搜
quote —— 必须 0 命中 site/ 下的对象都是 public-read,data/ 下的都不是
2026-09-03 补三条:
- [ ] 每个段首标签单独念出来,是不是一句能听懂的话(§5.3b)
- [ ] 有没有哪一条写的是「我这次做不到什么」(★.4b ④),有就删掉整条
- [ ] 卡片上出现的人,前七天的卡里出现过吗;出现过,上次那条的结论今天有没有接上(§2.3b)
四 · 2026-08-20 晚 · 五条整改(走查后定,优先级高于前面冲突的写法)
4.1 榜上放「玩得最多的是哪个玩法 · 在这个玩法上投了多少」
操作次数、聊天条数、自己充的,都不要出现在卡片上。
榜的八列固定,见 1.1【4】那张列表:
# | 昵称 | 国家 | 本月充值 | 昨天充值 | 昨天主要在玩 | 昨天净流水 | UID。
改动记录 · 2026-09-04:原来这里写「四列固定」并且写着「列数压到 4~5 列,
超过会横向滚动」。实际在推的榜是八列,08-31 起一直如此,没有出过渲染问题。
按实际改成八列。
- 数据在桶里:
data/{cc}/atom/d/{day}/B2.jsonl,逐人 × 场景,out_c 是当天在这个场景投入的币。
按 (uid, scene_id) 聚合取最大的那个,scene_id 为空的是系统发放,必须先剔掉。
- 玩法名读
data/_profile/_scene_names.json,不要自己起名。表里没有的写「场景 N」。
⚠️ 未决:这一列现在是「币」,用户要的是人民币。
金币折人民币的单价桶里没有、三份规范里也没有,B2 只有币。
拿到单价之前不要自己换算,也不要估。
4.1b ★★★ 名次必须说清是哪张榜(2026-09-04 加)
卡片里那张表是全站总榜,而原子里每个人的 rank 字段是所在国家的分榜。
两者差很多:09-03 那天 U Đô🪽 分榜第 3、总榜第 6;09-02 分榜第 19、总榜第 52。
写事件时用哪张榜,取决于卡片里放的是哪张表。 现在放的是总榜,
所以正文里的名次一律按总榜写,要引分榜必须写明「越南分榜第 N」。
被这条拦住过一次:09-04 那张卡第一版写「从榜上第 19 冲到第 3」,
那是分榜的数,而卡里的表是总榜,读者对不上。正确写法是「从全站第 52 到第 6」。
4.2 池子小的国家不报涨跌
泰国 2 人、沙特 2 人、埃及 1 人。一个人当天没充就是 −100%,那不是信号是噪音。
池内人数 < 10 的国家 只报「N/M 在玩 · 花掉多少币」,不报百分比
这条和一百那句「大R 某天没充是个体波动,不用报」是同一件事。
4.3 不许写流程黑话
已并入 ★文风总则 ★.1 ①。
被打回的原话:
昨天 74 个人里 13 个触发了判定,排掉在烧前几天余额的那些,剩 3 件值得说。
「触发判定」「烧余额」是我们内部的流程词,读的人不知道在说什么。
筛查过程(74 → 17 → 4)是我们怎么干活,不是业务信息,不要写进卡片。
改成:昨天有三件事值得说,前两件已经查到原因。
★ 「昨天」不是默认词,见 §2.2b。
4.4 「自充率 X%,池内中位 Y%」不要出现
自己充的、自充率,卡片上一概不写。要看放页面。
⚠️ 这条覆盖 data/_profile/README.md 里那句
「『他自充率 54%』没意义,『池内中位 19%、他排第 10』才有意义」——
那句说的是内部判断时要配位次,不是说可以写到卡片上。判断照用,别往卡片上写。
4.5 ★★★ 卡片里不许出现没有身份的裸 UID
被打回的原话:
29962452 是谁、他还对谁说过、他自己在不在流失,已经去数仓单独跑,出来补在话题里
问题不在于跑没跑,在于卡片上留了一个光秃秃的号码。
Matrix 存在的意义就是把这种线索查出来,查一半留个 UID 让人自己追问,等于把活推回去。
出卡片之前,正文里出现的每一个 UID 都必须先查过,至少给出:
① 他是谁 —— 昵称/国家/在不在池内/是不是荣耀
② 他在干什么 —— 充值、消费、家族、聊天,给具体数
③ 和这件事的关系
查得到就写进正文。查不到也要写清楚查了哪儿、为什么没有,例如:
查了 08-15 到 08-17 的宽表,三天一行都没有。宽表只覆盖荣耀用户和他们所在的家族
(当天 2,959 人),所以他既不是荣耀也不在这些家族里。要确认得去数仓查全站,已经在跑。
「宽表里没有」不等于「这个人没有行为」。 宽表的落表范围是荣耀用户及其家族成员,
每天约三千人,不是全站。把范围写出来,别让人误读成他已经不活跃了。
4.5b ★★★ 事件标题必须以人开头,写昵称 + UID(2026-09-03 加)
4.5 管的是「有 UID 没身份」,这条管反过来的那一半:有身份没 UID,或者干脆用名次代替人。
被打回的原句(09-03 那张卡):
✗ 【个人】越南榜上第 1 和第 6 整晚在同一个房间互相报下注档位
✗ 【越南】房间里喊了一整晚的人拿到 99 币
用户原话:「不要先说越南啊……而且你也没写名字和UID」「这个是谁啊」。
格式照 09-01 那张(用户认可的)抄:
【个人】昵称(UID 12345678,国家)+ 他做了什么
【个人】💀Diêm Vương🌪(UID 39296764)和 Lý Thất Dạ(UID 36989322,都在越南)……
- 人名在最前面,国家在括号里。标题第一眼要看见是谁,不是看见哪个国家。
- 名次不能代替人名。「越南第 1」是当天名单算出来的一个位置,明天就换人了;
昵称和 UID 是这个人本身。名次可以写在正文里当背景,不能当标题里的主语。
- 正文里出现的每一个人,第一次出现都要带 UID。包括不在名单上的人 ——
尤其是不在名单上的人,因为读的人无从查起。
- 昵称查
dw.dw_user_basic_info_ad(nickname / gender / age / city_name / register_days),
注意 ods.ods_user_info_ad 里没有昵称列,别在那张表上找。
桶里 data/_idn/profiles.jsonl 是快照,改过名的人对不上,以 dw 那张为准。
★★ 只管【个人】和【风险】两类(2026-09-04 收窄)
【机制】【竞品】【反馈】这几类讲的不是某一个人,标题里不该硬塞 UID。
09-01 那张用户认可的卡,【竞品】那条标题就没有 UID,当时被 lint.py 误报过一次。
lint.py 已同步:只在标题带【个人】或【风险】时才要求 UID。
★★ UID 和国家写成灰字,放在置信度前面(2026-09-04 定)
标题正文里不再插 UID 和国家,它们跟置信度一起放到行尾的灰字里:
**1 【个人】U Đô🪽 通道全断的情况下,硬拆成 10 笔充了 ¥2,212**<font color='grey'> UID 40645486 · 越南 🟡 存疑</font>
顺序固定:UID · 国家 置信度。理由是标题第一眼要读到「谁做了什么」,
UID 和国家是查证用的附注,跟置信度同级,不该占据句子中间打断阅读。
lint.py 拦:标题带【个人】或【风险】却没有 UID 就不合格。
4.6 桶里现成能用的两样东西(别重复造)
| 位置 | 是什么 |
|---|
data/_profile/{uid}.json | 大R 半年画像,七国 74 人各一份,窗口 2026-02-18~08-18。含充值节奏、月度曲线、主玩法迁移、爆发日、送礼集中度、池内位次。用法见同目录 README.md |
data/_profile/_scene_names.json | 场景号 → 玩法名 + 是不是概率游戏 + 半年进出总额 |
data/_wide/user_day/d/{day}/A1~A10.jsonl | 逐人逐天行为,覆盖荣耀用户及其家族成员约 3,000 人,可以查池外的人 |
判定命中某个人,先调画像再决定要不要上卡。 他本来就是几天充一次,那今天没充就不是信号。
4.7 已知缺口:桶里只有 4 天
data/{cc}/atom/d/ 目前只有 2026-08-15 ~ 08-18。
卡片上写「近 7 天」的时候,那 7 天不是从桶里来的,是当次跑数时现算的。
要么把窗口写成实际有的天数,要么用 Presto 补齐再画。不要写一个凑不出来的窗口。
4.8 ★★★ 币不许折人民币(2026-08-21 实测,覆盖 4.1 那条「拿到单价就换算」)
4.1 里写的是「投入这一列现在是币,拿到金币单价就换成人民币」。这条作废。
实测 2026-08-20 七国 74 人:
| 值 |
|---|
总共花掉的币 sp_coin | 1,808,906 |
其中自己充的 sp_recharge | 104,547(5.8%) |
平台送的币 sp_give | 1,704,359(94.2%) |
当天真实充值(cash_order 折人民币) | ¥8,122 |
按实测的 11 币=¥1 折算,总币会得出 ¥164,446 —— 和真实充值差二十倍。
那个数不是任何人花的钱,也不是平台收到的钱,写到卡片上必被质疑,而且质疑得对。
硬规则:
sp_coin 写「币」。永远不折人民币
sp_recharge 可以折,但要写清楚是「花掉的币里自己充的那部分」
cash_order 这是唯一的真金白银,人民币只给它
各国自充占比差得极大(越南 1.8%、埃及 0%、印尼 11.9%),
所以「自己充的占比」本身就是一条该上卡的信息,写在国家那一行。
越南当天花掉 95.5 万币而自充只有 1.8%,说的是这批人在拿平台送的币空转。
同理,B2 的 out_c 也是总币(不分充值币/赠送币),逐玩法的投入同样只能写币。
4.9 卡片上不出现外文原句
聊天原文是印尼语/越南语/他加禄语,卡片正文只写中文意思,不贴原句。
原句留在页面和 data/ 里,追问时再给。
理由:读卡片的人不懂这些语言,一段外文占三行还看不懂,把结论挤下去了。
「他们怎么说」不单独成块。 玩法反馈、对运营的意见这些,
直接写进对应那个人的事件里,用中文说明白他说了什么、这话为什么重要。
§5 防发散(2026-08-21 立,龙虾换 Opus 5 之前锁上)
这一天卡片被打回六七次,没有一次是算错,全是写太多:
「把思考过程写出来了」「解释性的灰字又放进去了」「21 天的证据这种话别写」。
结论:自觉管不住 —— 写的时候自己不觉得长。所以改成机器数。
5.1 ★★★ 分析和推送彻底分家
| 写多长 | 落在哪 | 给谁看 |
|---|
| 分析 | 不限。查了多少条 SQL、读了多少条私聊、推翻过什么,全写 | data/{天}/_analysis.md | 自己回头查证 |
| 卡片 | 不限长度,也不要往短里写(见 5.2)。只挑不写 | 推送 | 群里的人 |
卡片只能从分析里【挑】,不能重新【写】。
挑和写是两件事 —— 挑不容易发散,写一定会。
2026-08-20 那天实际查了三十多条 SQL、读了六万多条私聊,卡上最后留四条事件。
5.2 ★★★ 字数不限,而且不要往短里写(2026-09-02 改)
两条一起记,只记住第一条会写错:
- 没有任何字数上限。 段数、每段字数、整张卡的总量,全部不限。
lint.py 那四个常量已经置 0,规则代码留着,以后要收紧改一个数就行。
- 也没有「越短越好」。默认往说清楚写,宁可长一点,不要压。
第二条要单独说,是因为没有方向的时候默认会往短里写 —— 短看着更安全。
但压缩会造成两类损伤,都实际发生过:
① 压出生造词。 正常说法被压掉,就只能自己拼一个短词。
lint.py 的禁词表里有五条专门拦生造词(点着 拉满 睡号 扫号 洗币),
那五条是症状不是病 —— 字数一紧、正常中文又被禁,剩下的出路就是造词。
所以 09-02 同时做了两件事:拆字数上限,并把五条句式硬拦降成提示。
② 压掉可核的信息。 09-01 那张砍到 5 段 90 字之后掉的是:
下载地址长什么样、四个人各说了哪一句、生日那天只在线 26 分钟、
公屏那条线和周充 ¥1,000 以上那档是同一批人。
这些不是修饰,是让别人能自己去复核这个判断的东西。删了,判断就只剩一句主张。
水位参考(不是上限,是「合格的密度长什么样」):
| 09-01 那张 |
|---|
| 每条事件 | 5~6 段 |
| 最长一段 | 300+ 字 |
| 整卡正文 | 约 2,500 字 |
lint.py 会拦「旧预算指纹」:事件 ≥2 条而整卡最长一段 ≤90 字,判不合格。
确实要推短卡,设 MATRIX_LINT_ALLOW_SHORT=1。
原来有一整套预算(每条事件 ≤5 段、每段 ≤90 字、洞察 ≤70 字、整卡 ≤2000 字),
定于 2026-08-21,那天的问题是写太多、把思考过程写进了卡片。
2026-09-02 用户拆掉它,理由是 09-01 那张卡。
那张(12vibe + cửu nhi ❤️)两条事件分别 5 段和 6 段、多处单段超过 200 字,
用户认可的就是那个水位。为了过闸砍成 5 段 90 字之后掉了整整一层:
下载地址长什么样、四个人各说了哪一句、生日那天只在线 26 分钟、
公屏那条线和周充 ¥1,000 以上那档是同一批人。
这些不是凑字数,是让判断站得住的东西。
长不是问题,散才是问题。 散由 5.3 的体例锁和 §1.2b 的用词表拦:
每段带标签、至多一个判断段、洞察放最后、禁行话禁元话语禁元叙述。
写得长但每段都指得回一件具体的事,比砍到 90 字之后谁都看不懂强。
范例:data/_spec/card-demo-2026-09-01-full.md(用户认可的完整版)。
被砍过的那版留档在 data/_day/2026-09-01.card.trimmed-bak.json,是反例。
仍然成立的是 5.1:卡片只能从分析里挑,不能重新写。
去掉字数上限不等于可以把分析过程搬上卡 —— 挑多少条、每条写多细,
判据是「这一句撑不撑得起结论」,不是「还有多少字额度」。
5.3 ★★ 体例锁
- 每段必须以 粗体标签 开头(
判断 …)。标签长度不限 —— 2026-08-27 取消 8 字上限:
标签是让人一眼知道这段在说什么,写清楚比写短重要,「大R名单上的人为什么要蹚这件事」
比「谁在替她跑」好。为了凑字数把标签压成谜语是倒过来了。
- 每条事件至多一个「判断」段,可以没有(2026-08-31 改,原来是「必须有且只有一个」):
- 有的事件就是没有能站住的判断。硬凑一个比没有更糟 ——
08-26 那张卡连写三版判断全被打回(「谁有官方通道」「一次封禁牵动两个人」
「未成年付费占 9.7%」),前两条不是判断,第三条是另一件事,最后确认这件事没有判断。
- 判断不等于要给结论。 把两组数并排放着、让读的人自己看出不对劲,就是合格的判断。
08-30 那张卡的写法可以直接抄:「教的人本月充 ¥314、昨天抽 7 次花 280 金币,
学的人昨天充 ¥3,354、抽 61 次花 37,000 金币。」一句解释都没有,但话说完了。
- 零个判断
lint.py 不拦也不提示。多于一个才拦。 - 卡片里不许有
tag:"note" 灰字(§4 已有,lint.py 拦)
5.3b ★★★ 段首标签必须是一句能听懂的话(2026-09-03 加)
标签是给人读的,不是索引词。四个字以内的名词短语,基本都是压出来的。
09-02 那张卡三个标签全部被打回:
| 写成了 | 病在哪 | 应该写 |
|---|
钱压在哪 | 「压」是压出来的动词,正常说法是「花」 | 七国的币花在哪几个玩法上 |
新钱还是旧钱 | 勉强能懂,但要读者自己猜「新钱」指什么 | 哪些国家花的是自己刚充进来的钱 |
能不能比 | 根本不是一件事,是我在说自己做不到(★.4b ④) | 整条删掉 |
用户原话:「你不要压缩词汇,什么叫压在哪里,是花在哪里」。
判据:把标签单独念出来,如果它不是一句能听懂的话,就是压出来的。
这条和 §5.2 是同一个病的两个位置。§5.2 拆掉了正文的字数上限,
但标签这一层还留着「越短越好」的惯性,所以正文放开了,标签还在造词。
标签长度和正文一样不限,lint.py 不查标签长度,只查里面有没有禁词。
5.5 自检
- [ ] 卡片跑过
lint.py 了吗(带 _quotes.jsonl 一起跑) - [ ] 分析的长版本落到
_analysis.md 了吗