Files
InfoRSI/任务书/02-rules.md
T
2026-10-02 00:08:45 -04:00

14 KiB
Raw Blame History

任务书 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/RivalBits
    • src/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 为准,并在报告里写出差别。

四、测试

预期值必须有独立来源,不能从实现里抄公式算预期值。来源有三种,按可信程度排:

  1. 方法.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,标签"各管各";
    • 第七部分的扣次示例表。
  2. 你自己写的独立 Python 脚本,放在 tests/fixtures/ 下:

    • 不 import 本项目代码,直接照方法.md 的文字实现;
    • 把算出的预期值写成 JSON,测试读这份 JSON;
    • 脚本开头写明用法、对应方法.md 哪一节。

    信息价值、选格、押的因子、世界比特这几块必须走这一条。网格和一维精确积分要互相对照:同一组输入在全部格都测时,两种算法的结果应当接近,并写明允许的误差和理由。

  3. 参考项目的独立计算: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 文件。

七、验收与报告

做完后本地提交,然后在回复里交一份报告,监督者会对着实际文件逐项核对:

  1. 提交号,新增文件列表,每个文件的行数,rules 的总行数。
  2. npm run check 和 npm test 的完整输出。
  3. 每组规则的预期值来自哪里:手算例子、你的 Python 脚本,还是参考项目的计算。参考项目的计算用了哪些、没用哪些、为什么。
  4. 独立审阅提出的问题,以及每条怎么处理的。
  5. 你和这份任务书、方法.md 或参考项目不一致的地方,以及为什么。
  6. 规则不清楚的地方:读 CLAUDE.md、结构.md、方法.md 时,哪里让你犹豫、哪里两份文件说法不一致、哪里你是靠猜的。方法.md 第六部分写得不够让你直接写成代码的地方,要逐条列出来。没有就写"没有"。