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

203 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 任务书 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 第六部分写得不够让你直接写成代码的地方,要逐条列出来。没有就写"没有"。