diff --git a/WORK_LOG.md b/WORK_LOG.md index fd241f6..a4a759d 100644 --- a/WORK_LOG.md +++ b/WORK_LOG.md @@ -23,6 +23,7 @@ - 提交的字段定义放 vocab,submissions 只判收不收;vocab 只放两个函数(规范序列化、哈希)。用户原话:"我都同意"。 - vocab 上限改为 1100 行(多出来的主要是发给模型的字段说明)。用户原话:"同意 A,vocab 上限改为 1100 行。结构.md 由监督者改,你不用动。" - 每份预测只对一个候选、每份挑刺只针对一个目标;入口、因子、实现条款的编号由程序按位置分配;实现提交不设代码字段(程序从工作目录冻结);运行结果用"没启动 / 正常退出 / 超时 / 被取消"一个字段表示启动与结束;四种 token 数都可记测不到。用户原话:"3、4、5、6:同意保留你的写法。方法.md 第五部分的表(入口编号、实现的代码字段)由监督者改。" +- 计算时间不再是预算,只记录;预算只有运行次数(42347e4)。用户原话:"CPU 秒不当预算但是要记录"。 - 解释的每格三个数改为可选,关掉消融时不交。用户原话:"同意 A:解释的 cells 去掉 minItems,改为可选"。 - 答案路径、保障动手次数只记读到的原始内容或读不到的原因;在不在位置表里,由以后拿得到位置表的模块现算,不存。用户原话:"按'能现算的不存',tasks 只记读到的原始内容……对表由以后有位置表的模块现算,把这条记进 WORK_LOG。" @@ -60,4 +61,4 @@ ## 下一步 -任务书 01 已核对通过(97a4359)。下一个是 rules,之后 ledger → …。 +任务书 01 已核对通过(97a4359)。`任务书/02-rules.md` 已写好,等用户另开 Agent 执行,监督者核对。之后是 ledger → …。 diff --git a/任务书/02-rules.md b/任务书/02-rules.md new file mode 100644 index 0000000..03c5269 --- /dev/null +++ b/任务书/02-rules.md @@ -0,0 +1,202 @@ +# 任务书 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 第六部分写得不够让你直接写成代码的地方,要逐条列出来。没有就写"没有"。