Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
14 KiB
任务书 02:rules(研究规则)
写 rules 模块:方法.md 第六部分的全部公式和常数,以及第七部分的余额计算、4.2 的入口分配。它是纯计算:输入数字,输出数字,不碰文件、数据库、模型,也不用全局随机数。
本任务书的内容已由用户和监督者在 2026-10-02 一起确定。下面说的"监督者",是在参考项目目录里和用户讨论设计的另一个会话。
按 CLAUDE.md,这一块是"账本"标准:每条规则都要有独立来源的预期值,而且要另派一个全新上下文的子 Agent 审阅。
开工前先读
CLAUDE.md:全部。docs/结构.md:- 第二部分(rules 在模块表里的位置和"几条边界");
- 第五部分(可替换点,尤其是"为了让换规则的实验做得对"那五条);
- 第八部分(vocab 已经导出的类型)。
docs/方法.md:- 第二部分(核心概念);
- 4.2(入口分配)、4.3 ⑧ ⑫ ⑬ ⑮ ⑰(程序做的决定);
- 第六部分全文,这是公式的唯一依据;
- 第七部分(预算与扣次,2026-10-02 刚改过:计算时间不再是预算,只记录);
- 第九部分(决定的重算、种子、同一格只结算一次);
- 第十一部分(可以换的规则);
- 第十二部分(已知局限)。
WORK_LOG.md、src/vocab/:已经有的东西。- 参考项目(只读,不要改):
/home/iomgaa/Projects/RivalBitssrc/decision/info.ts、src/decision/ablation.ts、src/decision/rules.ts:旧的数学规则;src/budget/rules.ts:旧的扣次规则;src/controller/steps/ablation.ts的结算部分(确认与否定、分不开、结算内容),这部分和写数据库的代码混在一起,只取数学;src/rounds/belief-book.ts里算战绩和合并范围的部分;tests/info.test.ts、tests/ablation.test.ts、tests/rules.test.ts:旧测试,看它测了哪些情况;tests/fixtures/calc15/和research-wiki/设计-15-计算/calc15.py:独立的 Python 计算,见第四部分。
一、范围
对外提供七组函数,都经 src/rules/index.ts 导出。下面写的是"要算什么",函数名、文件怎么分由你来定。分文件时按组分,一组一个或两个文件。
1. 范围与合并分布(方法.md 6.1–6.3)
- 一个人的三个数 → "低于 x 的把握"折线:五个点,两端补尾巴;三个数相等时是宽度为 0 的尖峰。
- 越小越好的任务:合并之后、计算之前换算成改进量,一成和九成对调。
- 开放预留:正向时一次选批里所有人、所有候选共用一个范围;消融时每格各定一个范围。
- 合并:(1 − λ) × 各人平均 + λ × 开放预留。同一人交了几条解释时,他那一份在几条之间平分。
- 从合并分布读出一成、一半、九成,给信念本显示"大家合起来的范围"。
2. 正向:入池、选批、采纳(6.4、6.5)
- 入池判断。
- 批内最好期望 V(S),以及选批。选批有两条规则:
- 批内最好期望:列出全部组合,V 完全相等时按候选编号定;
- 均匀随机:从候选池的全部候选里随机抽,不看入池门槛。
- 分数尺读数,只记录。
- 选批的输出要包含方法.md 6.4"选批记录写入"列的全部内容。
- 采纳线:有已知最好、没有已知最好两种情况,下限 ε/100,B 超过 K* 时也取 ε/100。
- 采纳判断:只看实测分数,最好的有效候选高出采纳线以上才采纳。
3. 消融结算(6.6,4.3 ⑬ ⑰)
- 列格:被采纳改法的每个因子一格。
- 撑几成;G ≤ 0 时报错。
- 相对交互量和配合关系标签,按方法.md 那张表从上往下判。rules 只返回标签代号,"给下一轮的话"这类中文由以后的 materials 写。
- 每格的五种结局:有效分数、证据不足、没测、跑不起来、一起关。只有"有效分数"进入标签的求和。
- "一起关"是对称的:关 p 连带关 q,和关 q 连带关 p,是同一种设置,已有结果就沿用。
- 每条解释在每个有效格上判确认或否定:落在 [q₁, q₉] 内(含两端)记确认,落在外面记否定。
- "现有测法分不开":两条解释在所有有效格上,确认与否定的序列完全相同。
- 消融中发现:某一格的有效分数比当前基线高出采纳线以上,它就成为新基线。几格都过线时取分数最高的;分数相同时取因子编号小的;"一起关"的格也算。
4. 信息价值与选格(6.7、6.8)
-
成分与起始权重:解释合起来占 0.9,研究者之间等权,同一人的几条平分;开放预留占 0.1。
-
方向收益,以及剩余空间 h:有已知最好时 h = max(K* − f(完整), ε/100);没有时 h = 1。
-
信息价值 VOI(S),两种积分:
- 全部格都测:一维积分,逐段多项式精确积分;
- 只测一部分格:网格。小段数的规则按 6.7 原文,m^k ≤ 4,000,000,s = min(20, ⌊m ÷ 段数⌋),段数超过 m 时改为等宽切 m 份。
都是确定的算法,同样的输入算两次,结果逐位相同。
-
价值、成本、净值:u、m′、R̂、ĝ₀,按 6.7 原文。
-
选格有四条规则:
- 信息价值减成本:只考虑格数不超过"余额 − 1"的非空组合,余额为 0 或 1 时不做消融;净值容差 1e-12;平局先取格数少的,再按因子编号比;
- 全测;
- 随机抽同样多的格;
- 都不测。
没选中的格附上原因("剩余次数不够"或"信息价值不足以抵过成本")和它所在组合的净值。
-
押的因子,以及不押的两种情况(6.8)。权重无从更新时保持起始权重。
5. 信息账(6.9)
这一组就是方法里"唯一的尺子",不随选批、选格规则变。
- 格宽 Δ = ε/100,从本批基线 b 起切。
- 世界比特、惊讶、分歧量。
- 事前把握为 0 时,惊讶返回一个明确的状态,比如"事前把握为 0,惊讶算不出",不拿 0 或无穷大顶替。
- 落点四段、覆盖率。
6. 余额与战绩(第七部分、6.10 第 4 条)
-
余额:从运行记录数出已经扣了几次。
- 确认启动的扣一次(启动后失败、超时、取消都算);
- 确认没启动的不扣;
- 已经预留、还没有结果的,也先占着名额。
计算时间不是预算,这里不算 CPU 秒。
-
本轮正向批量 k = min(每批上限, 余额);消融最多测"余额 − 1"格。
-
战绩:中位数偏高几次、偏低几次;被穿过上沿几次、下沿几次;包住几次。另有"作者自评 vs 大家合并"一栏,只收已经跑过、有有效成绩的候选。
- 方法.md 6.10 写的是"分方向写",6.9 写的是"按正向与消融分开"。先按"正向与消融分开"理解,在报告里说明。
信念本里其余的数字,比如每格的撑几成、确认与否定、世界比特、惊讶,结算时已经算好、记在结算记录里,以后由 materials 从记录里取出来写成文字。rules 不另做一份"信念本"函数。
7. 入口分配、种子与规则登记表
- 入口分配:按方法.md 4.2 的四条规则。N = 1 时直接分第一志愿。
- 种子:由研究编号、轮次、版本算出,用 vocab 的
hash。需要随机数时,从种子确定地展开,同一个种子永远得到同一串数。不用Math.random。 - 规则登记表:一张"名字 → 函数"的表,每条规则带名字和版本号(从 1 开始)。
- 选批两条:批内最好期望、均匀随机。
- 选格四条:信息价值减成本、全测、随机同格数、都不测。
- 以后的配置写规则名,flow 写决定记录时,规则名、版本、参数、种子都从这里取。
二、写法要求
- 参数从外面传进来。
- λ、u、衰减 r、ε、已知最好、每批上限、N、M 这些,都作为函数参数传入,来自以后冻结的配置。rules 里不写死,也不读环境变量。
- 方法.md 6.11 标"固定"的常数写成 rules 里的常量:±0.2、0.9、1e-12、4,000,000、20。
- 标"跟随 ε"的量(采纳线上下限、剩余空间下限、格宽 Δ),从传进来的 ε 算,不写成 0.01、0.0001。
- 输入是普通的数字和数组,不是账本记录。 账本还没写,rules 也不应该知道账本长什么样。需要的输入类型 vocab 里有的(比如
Range),用 vocab 的;只有 rules 用的,定义在 rules 里。 - 每个决定的输出要足够写成一条决定记录。 结构.md 第五部分要求决定记录存全部输入和输出,方法.md 6.4、6.7 列了要记哪些数。函数返回值里要有这些中间数,不要只返回"选了谁"。
- 错误:方法.md 写明要报错的(比如 G ≤ 0),直接抛错,写清是哪条规则、什么输入。其余不加防御性检查,输入的格式由上游的字段定义保证。
- 注释:写这段在算方法.md 哪一节的哪个量,用小节名引用。不写修改历史。
三、参考项目的保留与删除
| 处理 | 内容 |
|---|---|
| 改写后保留 | decision/info.ts:折线、开放预留、合并、V(S)、选批、比特、惊讶、落点、覆盖、分歧量 |
| 改写后保留 | decision/ablation.ts:成分模型、信息价值(精确和网格两种)、机会成本、选格、押的因子 |
| 改写后保留 | decision/rules.ts:撑几成、标签、剩余空间、采纳线、消融中发现 |
| 改写后保留 | budget/rules.ts 里"一次运行扣不扣"的规则,只留次数,去掉 CPU 秒和墙钟两道闸门 |
| 从别处抽出 | controller/steps/ablation.ts 里的确认与否定、分不开、结算内容;rounds/belief-book.ts 里的战绩和合并范围 |
| 删除 | budget/ablation.ts 整个文件:份额、照测、欠测、收尾补测、最后一轮预留,以及 RB_TEST_ABLATION_QUOTA_ZERO 测试开关。方法里都已删除 |
| 删除 | ABLATION_QUOTA_SHARE;写死的 0.01、0.0001(改从 ε 推出) |
| 删除 | worldBits 与 worldBitsFrom、surpriseBits 与 surpriseBitsFrom 的重复,各留一个,都从 b 起切 |
| 删除 | rangeRevision:方法里没有这个量 |
| 删除 | budget/compute.ts(ComputeBudget、BudgetExhaustedError):带状态的闸门不属于纯计算,计算时间也不再是预算 |
| 不搬 | proposalCompleteness(归 submissions);changeText("变好 / 基本不变 / 变差",归 export);SYNERGY_TEXT 等标签中文(归 materials);src/replay/ |
参考项目的公式如果和方法.md 不一致,以方法.md 为准,并在报告里写出差别。
四、测试
预期值必须有独立来源,不能从实现里抄公式算预期值。来源有三种,按可信程度排:
-
方法.md 里的手算例子,每个都要变成测试:
- 2.44 / 2.52 / 2.62 时,"低于 2.57"的把握是 0.70;
- X、Y 单独跑都是 0.010,一起跑是 0.015;
- 基线 1.00、完整 1.50,关 p1 得 1.45,关 p2 得 1.10:撑 0.10 和 0.80,i = −0.10,标签"各管各";
- 第七部分的扣次示例表。
-
你自己写的独立 Python 脚本,放在
tests/fixtures/下:- 不 import 本项目代码,直接照方法.md 的文字实现;
- 把算出的预期值写成 JSON,测试读这份 JSON;
- 脚本开头写明用法、对应方法.md 哪一节。
信息价值、选格、押的因子、世界比特这几块必须走这一条。网格和一维精确积分要互相对照:同一组输入在全部格都测时,两种算法的结果应当接近,并写明允许的误差和理由。
-
参考项目的独立计算:
research-wiki/设计-15-计算/calc15.py、tests/fixtures/calc15/。- 它们按旧版方法写,带份额等已经删除的规则。
- 只用和现行方法.md 一致的部分。用之前逐条对照,在报告里写明用了哪些、哪些因为方法变了没用。
- 真实运行数据在
/home/iomgaa/rb-acceptance/,只能复制出来读。
还要覆盖这些情况:
- 每条规则在边界上的行为:三个数相等;入池正好在一半;采纳线的下限和 B 超过 K*;净值在 1e-12 附近;余额为 0、1、2;惊讶的事前把握为 0;G ≤ 0 报错。
- 五种结局里只有有效分数进入标签。
- "一起关"对称沿用。
- 分不开的判定。
- 同样的输入算两次结果逐位相同;同一个种子得到同一个随机结果。
- 规则登记表里的每条规则都至少有一条测试。
不靠删断言、改预期值让测试通过。实现和独立脚本对不上时,先查清是谁错了,查的过程写进报告。
五、独立审阅
全部写完、测试通过后,另派一个全新上下文的子 Agent 审阅。它只拿到方法.md 第六、七部分和 src/rules/、tests/ 的代码,不给它看你的思路。
- 让它逐条对照方法.md 找不一致,找出错后不会被发现的地方(比如格宽、种子、平局规则),交回具体的失败场景。
- 它不写 md 文件,结论直接回复给你。
- 它提出的问题,修了的要附测试,没修的写明理由。
六、规模与文档
- 预期 1700–2200 行(不含测试),在结构.md 第七部分粗估的 1500–2500 之内。超过 2500 行就停下来检查:是需求本身复杂,还是专门处理罕见情况的分支在变多。
- 完成后更新:
docs/结构.md第八部分:补 rules 对外的函数和类型,每项一句话;WORK_LOG.md。
- 不新建其他 md 文件。
七、验收与报告
做完后本地提交,然后在回复里交一份报告,监督者会对着实际文件逐项核对:
- 提交号,新增文件列表,每个文件的行数,rules 的总行数。
npm run check和npm test的完整输出。- 每组规则的预期值来自哪里:手算例子、你的 Python 脚本,还是参考项目的计算。参考项目的计算用了哪些、没用哪些、为什么。
- 独立审阅提出的问题,以及每条怎么处理的。
- 你和这份任务书、方法.md 或参考项目不一致的地方,以及为什么。
- 规则不清楚的地方:读 CLAUDE.md、结构.md、方法.md 时,哪里让你犹豫、哪里两份文件说法不一致、哪里你是靠猜的。方法.md 第六部分写得不够让你直接写成代码的地方,要逐条列出来。没有就写"没有"。