docs: 新增任务书 12(flow 第 1 部分:骨架与第零轮);验收看研究质量、正式与检验代码分开
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -86,8 +86,13 @@
|
||||
### 测试
|
||||
|
||||
- 账本和数学规则的预期值,来自手算、独立脚本或参考项目的固定数据,不从实现里复制公式。
|
||||
- 每个阶段结束时核对几条总账,不符就停。比如:扣掉的运行次数等于已确认启动的正式运行数;每条证据只记一次账。
|
||||
- 其余部分测到能跑通就够。真实模型链路要用真实运行来证明,假模型测试证明不了。
|
||||
- 流程(flow)的验收看研究做得好不好,不只看跑没跑通:用真模型、真 Jev、真 Docker 把同样的配置跑几次,用 Jev 当裁判,对照同类系统和参考项目高分运行的研究路径来判(`docs/结构.md` 第三部分"flow 分四部分写,各自验证")。
|
||||
- 正式代码和检验代码完全分开:
|
||||
- `src/` 只放正式代码;`tests/` 放 `npm test` 跑的不花钱的测试;`eval/` 放真实运行的检验(起研究、回放记录、杀进程、查账本、评研究质量)。
|
||||
- `src/` 不引用 `tests/`、`eval/`;`eval/` 只经 `src/<模块>/index.ts` 用正式代码,像用户一样用:给配置、启动研究、读账本。
|
||||
- `src/` 里不出现为检验写的任何东西:参数、环境变量开关、"回放模式"、假实现、只给检验用的导出。检验要的假模型,用 Pi 自己的模型服务配置(`PI_CODING_AGENT_DIR`)接过去。
|
||||
- 检验跑出来的研究目录和报告放在仓库外,不提交。
|
||||
- 修缺陷时,附一条能复现原问题的测试。
|
||||
- 不为了方便测试而给产品代码加参数或分支。测试要造的情况(例如外部服务不应答),用测试自己的环境去造。
|
||||
- 不靠删断言、改预期值,或只保留成功的运行来让测试通过。
|
||||
|
||||
+4
-1
@@ -58,6 +58,9 @@
|
||||
- 提案、回应、统一的已占用指标编号加 `answer-path`、`safeguard-triggers` 两个保留键(用户选"materials 补进清单")。
|
||||
- Jev 退回的原因只列判"是"的几问,只用 jev 的英文问题名(用户选"只列判是的+只写英文")。
|
||||
- flow 拆成四部分、各自验证;验证一律用真 Jev、真 Docker,同样的输入真实跑几次;模型一侧回放真实记录和真模型两种都做(2026-10-03,细节见结构.md 第三部分)。用户原话:"我建议用一律用真 Jev、真 Docker。因为其实我们现在是在做科学研究,不是在开发程序……我们只需要重复运行多次";对拆分:"你那几个拆分我基本认同";对两种都做:"同意"。
|
||||
- flow 每部分的验收看研究质量,不只看跑通(2026-10-03)。第零轮问六问:入口里有没有关键想法、分到的入口分没分开、好方向分出去没有、是不是改代码的路线、有没有写答案、讨论有没有用;尺子是同类系统和参考项目高分运行的关键想法与死路清单(任务书 12 第五部分)。用户原话:"你要改掉你一直在做程序设计的逻辑。我们现在在做科研……我 care 的是……这个候选的方向是不是真的是正确的……那三个候选方向……是不是真的有分开……让 Jev 去判一下";只靠这部分答不了的问题不放进来:"有一部分是只有这份回答不了的那有啥好评判的"。
|
||||
- 正式代码和检验代码完全分开:`src/` 正式、`tests/` 不花钱的测试、`eval/` 真实运行的检验(CLAUDE.md"测试")。用户原话:"需要把正式代码和测试代码完全分开……我们现在是有一大堆的测试代码是需要监控我们正式代码"。
|
||||
- 基线每份研究都跑一次,不复用别的研究的结果;方法.md 第九部分"每个阶段结束时核对总账"删去,改为由记录方式保证(2026-10-03,监督者建议,用户说"基本可以,你可以写任务书了")。
|
||||
|
||||
## 未完成
|
||||
|
||||
@@ -90,4 +93,4 @@
|
||||
|
||||
## 下一步
|
||||
|
||||
已完成模块收尾完毕,现在由用户和监督者一起过 flow。flow 分四部分写、各自验证,拆分、验证办法和对照用的记录见 `docs/结构.md` 第三部分"flow 分四部分写,各自验证"。用户还要求每部分也拿参考项目真实验收运行的记录(`/home/iomgaa/rb-acceptance/*/board.sqlite`)当对照,原话:"我们也可以把我们的记录作为一个标杆,然后去匹配"。下一步:监督者给用户讲部分 1,定下后写任务书 12。
|
||||
已完成模块收尾完毕,现在由用户和监督者一起过 flow。flow 分四部分写、各自验证,拆分、验证办法和对照用的记录见 `docs/结构.md` 第三部分"flow 分四部分写,各自验证"。用户还要求每部分也拿参考项目真实验收运行的记录(`/home/iomgaa/rb-acceptance/*/board.sqlite`)当对照,原话:"我们也可以把我们的记录作为一个标杆,然后去匹配"。部分 1 已写成任务书 12(`任务书/12-flow-1-骨架与第零轮.md`),等用户另开会话执行,之后监督者核对。
|
||||
|
||||
+2
-2
@@ -145,7 +145,7 @@
|
||||
### 4.1 研究开始
|
||||
|
||||
1. 程序把这份研究的配置冻结进账本,包括 N、M、因子数上限、每批上限、运行次数、各决策点用哪条规则、方法参数、提示词哈希。之后的流程只读这份冻结的配置。
|
||||
2. 已有的结果只有在实验条件完全相符时才能当基线;没有符合条件的结果,就安排一次基线运行,计入运行次数。
|
||||
2. 研究开始时跑一次基线,计入运行次数。不复用别的研究的结果。
|
||||
|
||||
### 4.2 第零轮:各自找不同的入口
|
||||
|
||||
@@ -705,7 +705,7 @@ VOI(S) = E_{S 的结果}[ max_p E(收益_p | S 的结果) ] − max_p E(收益_p
|
||||
- **运行一旦启动,就按实测记账。** 跑完才发现实现有错,也不标为无效重跑。
|
||||
- **不支持中途作废重做某一轮**,也不支持替换提示词模板、放弃某个阶段。想重来,就另开一份新研究。
|
||||
- **开发入口**:研究因为模型交不出合格提交而停下后,开发者可以修好提示词,在同一阶段只重新发起那一个任务。这个入口由配置开关控制,配置里必须写明开还是关:正式研究写关,开发调试时才写开。〔自定〕打开过这个入口的研究,不能当验收证据。
|
||||
- **每个阶段结束时核对几条总账**,不符就停。例如:扣掉的次数等于已确认启动的正式运行数;每条证据只记一次账。
|
||||
- **总账由记录方式本身保证,不另设核对。** 扣掉的次数不单独存,每次从"确认启动"的记录数出来;同一轮的消融结算只能写一条,重复写入直接报错。
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@
|
||||
|
||||
| 部分 | 管哪些步骤 | 自己的验证目标 | 拿哪份真实记录对照 |
|
||||
|---|---|---|---|
|
||||
| 1. 骨架、研究开始、第零轮 | 从账本算出现在到哪;"下一步做什么"的纯函数(步骤先后只写这一处);主循环;恢复入口;派一个模型任务、跑一次正式运行两个共用动作;冻结配置、建镜像、基线;第零轮 | 在各处写账本之后杀掉进程再启动,不重跑、不重扣、不漏写 | 16-real-1 第零轮回放,入口分配和参考项目相同 |
|
||||
| 1. 骨架、研究开始、第零轮 | 从账本算出现在到哪;"下一步做什么"的纯函数(步骤先后只写这一处);主循环;恢复入口;派一个模型任务、跑一次正式运行两个共用动作;冻结配置、建镜像、基线;第零轮 | 第零轮的研究质量六问(任务书 12):入口里有没有关键想法;分到的入口分没分开;好方向分出去没有;入口是不是改代码的路线;入口有没有写答案;讨论有没有用。另杀进程再启动,不重跑、不重扣、不漏写 | 关键想法和死路清单取自同类系统与参考项目高分运行的研究路径;16-real-1 第零轮回放,分配和参考项目相同,并用同样六问打分当对照 |
|
||||
| 2. 开轮到冻结 | 4.3 ①–⑦ | 每次模型调用开始时存下的材料里,没有当时还没公开的东西 | 16-real-1 三轮提案到第二次预测回放;15-tight-2 抄错编号不再卡住 |
|
||||
| 3. 选批到采纳 | ⑧–⑫ | 扣掉的次数等于确认启动的运行数;修复用完不跑、不扣、记事件 | 选批记录的输入和 16-real-1、15-real-1 存下的比;15-tight-2 第 1 轮的修复 |
|
||||
| 4. 消融到收尾 | ⑬–⑱ 与研究结束 | 解释冻结早于任何一格启动;每格只结算一次 | 选格输入和 15-real-1、16-real-1 比;最后整份回放 16-real-1,当四部分合起来的验收 |
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
# 任务书 12:flow 第 1 部分(骨架、研究开始、第零轮)
|
||||
|
||||
flow 是整个系统的核心。参考项目的 flow 太长,很难验证,用户认为"之前其实很多问题都是 flow 没有做好"。所以 flow 拆成四部分写,每部分验证通过以后再写下一部分(`docs/结构.md` 第三部分"flow 分四部分写,各自验证")。这是第 1 部分。
|
||||
|
||||
这部分写完以后,程序能做到:给它一份配置,从零开始冻结配置、跑一次基线、让几位研究者走完第零轮(写入口、讨论、认领),程序分好入口后停下;中途被杀掉,重新启动能接着跑。
|
||||
|
||||
**这部分的验收看研究做得好不好,不只看跑没跑通。** 第零轮产出的入口方向对不对、分没分开,用真模型、真 Jev、真 Docker 跑 3 次来判(第五部分)。
|
||||
|
||||
本任务书已由用户和监督者在 2026-10-03 一起确定。下面说的"监督者",是在参考项目目录里和用户讨论设计的另一个会话。
|
||||
|
||||
## 开工前先读
|
||||
|
||||
- `CLAUDE.md`:全部。尤其是"测试"一节里新加的两条:flow 的验收看研究质量;正式代码和检验代码完全分开。另外看"罕见情况怎么办""不设默认值""中断后怎么恢复"。
|
||||
- `docs/方法.md`:
|
||||
- 4.1 研究开始:基线每份研究都跑一次,不复用别的研究的结果(用户 2026-10-03 定);
|
||||
- 4.2 第零轮;
|
||||
- 第七部分:预算与扣次;
|
||||
- 第九部分:中断与恢复,含开发入口。
|
||||
- `docs/结构.md`:
|
||||
- 第二部分:flow 一行和"几条边界";
|
||||
- 第三部分:步骤清单,以及"flow 分四部分写,各自验证";
|
||||
- 第四部分:账本记录;
|
||||
- 第八部分:config、ledger、runner、tasks、workspace、materials、agents、submissions 各节。flow 只经这些模块的 `index.ts` 用它们。
|
||||
- `WORK_LOG.md`:"未完成"里标"给 flow"的条目,第十部分列了哪几条归这部分。
|
||||
- 参考项目(只读,不要改)。只用来理解它怎么做的,不照搬结构,第二部分末尾写了为什么:
|
||||
- `/home/iomgaa/Projects/RivalBits/src/controller/loop.ts`、`next-step.ts`、`resume.ts`、`task-runner.ts`;
|
||||
- `steps/round-zero.ts`、`steps/forward.ts` 里的 `runB0`;
|
||||
- `src/runner/service.ts` 的 `dispatch`(运行怎么登记、启动、恢复)。
|
||||
|
||||
## 一、这部分管哪些事
|
||||
|
||||
1. **从账本看出"现在到哪了"。** 账本不存"进行到第几步",每次从记录现算。
|
||||
2. **"下一步做什么"的纯函数。** 输入账本记录和冻结的步骤清单,输出下一步要做的一件事。步骤的先后只写在这一处。
|
||||
3. **主循环**:读账本 → 问下一步 → 做这一步 → 回到开头。
|
||||
4. **恢复入口**:每次启动都走同一条路,不分第一次启动、正常重启还是被杀后重启。
|
||||
5. **两个共用动作**:派一个模型任务、跑一次正式运行。后面三部分都用这两个,这里一次写好。
|
||||
6. **研究开始和第零轮**:冻结配置、建镜像、存基线代码、跑基线;写入口 → 讨论(1 或 2 次)→ 认领 → 程序分配。
|
||||
|
||||
走到"开第 1 轮"时,程序停下,原因写"第 1 轮还没写(任务书 13)"。第 2 部分会把这一句换掉。
|
||||
|
||||
## 二、正式代码:`src/flow/`
|
||||
|
||||
对外只导出一个函数(经 `src/flow/index.ts`),以后 plugin 也用它:
|
||||
|
||||
- `runStudy(input)`:输入研究目录、配置、"停下"信号,都必填。
|
||||
- 配置:新研究交 `checkConfig` 检查过的配置;接着跑一份已有的研究时写 `null`,以账本里冻结的那份为准。
|
||||
- 交回两种结局之一:
|
||||
- 停下,附原因;
|
||||
- 被用户停下。
|
||||
|
||||
"研究结束"这种结局第 4 部分才走得到,这次不写。
|
||||
|
||||
文件怎么分由你定。参考:`state.ts`、`next-step.ts`、`loop.ts`、`recover.ts`、`model-task.ts`、`formal-run.ts`,加上 `steps/` 下每个步骤一个小文件。步骤文件里出现公式、字段名单或"谁能看什么"的判断,说明知识漏进来了,要挪回下层模块。
|
||||
|
||||
### 2.1 研究目录里放什么
|
||||
|
||||
全由 flow 管:
|
||||
|
||||
| 路径 | 内容 |
|
||||
|---|---|
|
||||
| `ledger.sqlite` | 账本 |
|
||||
| `repo.git` | workspace 的裸仓库 |
|
||||
| `runs/<运行编号>/` | 一次正式运行:取出的代码、运行目录、判分目录、日志目录。每次运行一个新目录("给 flow":日志目录每次运行一个新的) |
|
||||
| `calls/<调用编号>/` | 一次模型调用:工作目录、会话文件目录、能读的代码版本(materials 的 `codeRoot`) |
|
||||
|
||||
取出代码、建运行目录、建判分目录时,目标目录都是新建的空目录("给 flow":取出时目标目录必须是空的)。
|
||||
|
||||
### 2.2 每一步以哪条记录为准算做完
|
||||
|
||||
参考项目的毛病是"这一步做完没有"靠隐含约定去猜,例如"这条记录公开了没有"。新项目定死:**每一步做完,以下表那条记录出现为准。** 写进代码注释,后面三部分每加一步就加一行。
|
||||
|
||||
| 步骤(config 的 `STUDY_STEPS`) | 看到哪条记录算做完 |
|
||||
|---|---|
|
||||
| `freezeConfig` 冻结配置 | 研究配置记录(`config`) |
|
||||
| `baselineRun` 基线 | 基线代码记录(`code`,对象是 materials 的 `ORIGINAL_BASELINE`),而且有一次基线运行的结果不是"没启动" |
|
||||
| `entryDraft`、`discussion1`、`discussion2`、`claim` | 这个阶段的关闭记录(`stageClose`) |
|
||||
| `assignEntries` 分配 | 第 0 轮的入口分配决定(`decision`,种类 `entries`) |
|
||||
| 按配置跳过的步骤 | 一条"按配置跳过"事件,写明步骤和 config 给的原因 |
|
||||
|
||||
基线运行结果是"没启动"的,不算做完:起一个新的运行编号重跑(结构.md 第四部分"确认没启动、退还名额后要重试,就起一个新编号")。基线判为不算数时,停下,原因写明。
|
||||
|
||||
### 2.3 "下一步做什么"
|
||||
|
||||
`STUDY_STEPS` 从前往后,第一个没做完的步骤就是下一步:
|
||||
|
||||
- **程序自己做的步骤**(冻结配置、基线、分配):做这一步。
|
||||
- **研究者阶段**:
|
||||
- 还没开:开阶段。名单是全部研究者,编号用 materials 的编号规则(见第三部分第 2 条),阶段编号由 flow 起。
|
||||
- 已开、名单上的人都有一份被收下的提交:关阶段。只有交齐了才关("给 flow":阶段关闭只在名单上的人交齐后写)。
|
||||
- 已开、有人还没交上:派这些人的任务。每个人按他最近一次调用怎么结束的来定:
|
||||
|
||||
| 最近一次调用 | 怎么办 |
|
||||
|---|---|
|
||||
| 没有调用 | 派 |
|
||||
| 被用户停下 | 派 |
|
||||
| 出错(包括恢复时补写的"进程中断") | 派 |
|
||||
| 没交(模型自己停下、一份没收下) | 配置里开发入口关着:停下,原因写"交不出合格提交",附调用编号(方法.md 4.3 ②:交不出按内部错误)<br>开发入口开着:派(方法.md 第九部分"开发入口") |
|
||||
|
||||
能派的先全派,派完还有人停在"没交",才停下。
|
||||
- 走到 `rounds`:停下,原因见第一部分最后一段。
|
||||
|
||||
这个函数是纯函数:不读文件、不调模型,同样的记录永远得到同样的下一步。
|
||||
|
||||
### 2.4 主循环与停下
|
||||
|
||||
- 每做完一步都重新读账本,再问下一步。
|
||||
- **一次派发里有人没交上(没交或出错),等这次派发的会话全部结束后停下**,写一条停下事件。
|
||||
- 不打断别人:别人已经在花钱了。
|
||||
- 出错的那个人,下次启动时会按上表重新派(模型服务的问题不是模型的错;Pi 自己已经重试过,`src/agents/session.ts`)。
|
||||
- 收到"停下"信号:正在跑的模型会话立即停(agents 已经支持);正在跑的 Docker 不管它,进程直接返回"被用户停下"。下次启动时,恢复入口会去问 Docker 这个容器怎么样了,不另写"停下"的分支。
|
||||
|
||||
### 2.5 恢复入口
|
||||
|
||||
每次启动按顺序做:
|
||||
|
||||
1. 打开账本。没有研究配置记录就是新研究,主循环从"冻结配置"开始。配置为 `null` 而账本里也没有配置:报错。
|
||||
2. 已有配置:
|
||||
- 用 config 的 `checkConfig` 把冻结的配置再检查一遍。
|
||||
- 核对冻结的镜像编号本机还在(`runner.hasImage`),不在就停下,不重建(结构.md"依赖跟着任务走")。
|
||||
- 核对提示词目录里每个文件的哈希和冻结时一样;不一样而开发入口关着,就停下。开发入口开着就照常往下走:每次模型调用开始时已经存下了当时用的材料。
|
||||
3. `ledger.pending()` 里"开始了还没结束"的模型调用,各补一条结束记录:出错,原因"进程中断",墙钟时间测不到(结构.md 第四部分第 10 种)。
|
||||
4. `ledger.pending()` 里"登记了还没结果"的正式运行,按容器名去问 Docker(`runner.status`):
|
||||
|
||||
| 有没有"确认启动" | Docker 的回答 | 怎么办 |
|
||||
|---|---|---|
|
||||
| 没有 | 没有这个容器,或建了没启动 | 写结果"没启动"(退还名额);建了没启动的删掉 |
|
||||
| 没有 | 在跑,或已结束 | 写"确认启动"(扣次),然后等它、判分、写结果 |
|
||||
| 有 | 在跑,或已结束 | 等它、判分、写结果 |
|
||||
| 有或没有 | 问不到 | 写一条"状态未知"事件,停下,等用户决定(方法.md 第七部分) |
|
||||
|
||||
"已经确认启动、容器却不见了"真实运行里没出现过,不专门写:`runner.wait` 会报错,按内部错误停下。
|
||||
5. 进入主循环。
|
||||
|
||||
### 2.6 共用动作一:派一个模型任务
|
||||
|
||||
一个研究者阶段里,名单上要派的人同时跑,各自一个会话。一个人在同一阶段的几个任务按先后跑;第零轮每人每阶段只有一个任务。
|
||||
|
||||
一个任务按这个顺序:
|
||||
|
||||
1. 用 materials 的 `buildMaterial` 生成材料。`StudyFacts` 从冻结的配置和任务事实取;`changes`、`artifacts` 第零轮写 `null`。
|
||||
2. 按材料里"能读的代码版本",把每个版本取出到它写的目录(`workspace.checkoutVersion`,目录新建)。
|
||||
3. 写"模型调用开始":调用编号用 materials 的 `callId`,尝试序号是这个任务已有的调用数加 1;材料整份存进去。先开始、后结束的顺序由这个入口保证("给 flow")。
|
||||
4. 用 agents 的 `runSession` 开会话:
|
||||
- **查询**:交给 `queryMaterial`。
|
||||
- **提交**:
|
||||
- 形状不合格(agents 交来的原样参数和原因):直接写一条退回,不经 submissions("给 flow":形状不合格的提交由 flow 直接记退回)。
|
||||
- 形状合格:交给 submissions 的 `receive`,对号清单用材料里的那份,提交之后才知道的东西(`known`)第零轮三种都是 `null`。收下就写提交,退回就写退回。
|
||||
- 替换、版本号照 ledger 的约定。回给模型的编号、单份种类没写"替换哪一份"又交第二次怎么办,照 agents、ledger、materials 已有的约定。约定没写清的,在报告第 6 条列出你怎么做的。
|
||||
- **用量**:每次回复写一条用量。
|
||||
- **写私人笔记**:写一条笔记记录。
|
||||
- **停下**信号:传给会话。
|
||||
5. 写"模型调用结束",带结局和墙钟时间。
|
||||
|
||||
### 2.7 共用动作二:跑一次正式运行
|
||||
|
||||
按这个顺序,前后由这个入口保证("给 flow":确认启动前要先登记运行):
|
||||
|
||||
1. 起运行编号。基线用 `base-1`,没启动就重跑,用 `base-2`,依次往后。
|
||||
2. 写"登记要跑"(占名额)。内容:运行编号、用途、轮次、对象、运行定义;运行定义用 tasks 的 `formalRun`。
|
||||
3. 取出代码,用 tasks 的 `prepareRun` 准备运行目录。
|
||||
4. `runner.start`:
|
||||
- 启动了:写"确认启动"(扣次)。
|
||||
- 没启动:写结果"没启动",退还名额,把 Docker 的报错原文记进结果。
|
||||
5. `runner.wait`,日志写进这次运行自己的日志目录。
|
||||
6. 判分:`prepareJudging`,需要时让 runner 在镜像里跑校验器,再 `judge`。判分不扣次数,不写"登记要跑"。
|
||||
7. 写结果,删掉容器。
|
||||
|
||||
容器名:
|
||||
- 正式运行用 `inforsi-<研究编号>-<运行编号>`,判分容器另起名字。两份研究同时跑不会撞名,这是参考项目 9b 真实出过的问题("给 flow":容器名在本机所有研究之间唯一)。
|
||||
- `docker run` 因重名失败时,runner 已经按名字再查一次。
|
||||
- 恢复时重新判分:判分目录重新建空的;判分容器如果还在,先删掉再用。
|
||||
|
||||
**种子**:同一份研究的全部运行用同一个种子。由研究编号经 vocab 的 `hash` 算出,取前 8 位十六进制转成整数,冻结进研究配置记录。
|
||||
|
||||
### 2.8 研究开始和第零轮各步
|
||||
|
||||
- **冻结配置**:
|
||||
1. 读任务(`loadTask`)、读提示词(`readPrompts`);
|
||||
2. 建镜像(`runner.buildImage`,标签带研究编号);
|
||||
3. 建裸仓库;
|
||||
4. 一次写进研究配置记录:配置、步骤清单(config 的 `stepList`)、提示词每个文件的哈希、镜像编号、任务事实、种子。
|
||||
|
||||
这条记录的形状写在 materials 里(第三部分第 3 条),export 以后也要读。之后只认这份记录,不再读配置文件和 task.json。参考项目推进时还在读当前的配置,这是它的毛病之一。
|
||||
- **基线**:
|
||||
1. 用 `saveVersion` 存任务的基线目录,"不存"清单用任务事实里的 `unversionedNames`;
|
||||
2. 写代码记录:对象 `ORIGINAL_BASELINE`,位置表 `null`;
|
||||
3. 用共用动作二跑一次。
|
||||
|
||||
方法.md 4.1:每份研究都跑,计入运行次数。
|
||||
- **第零轮的三个研究者阶段**:用 2.3 和 2.6,阶段名对上 vocab 的 `STAGES`。讨论开 1 次还是 2 次,看步骤清单。
|
||||
- **分配**:
|
||||
1. 从账本取每人最后一份认领、最终有效的入口;
|
||||
2. 交给 rules 的 `assignEntries`;
|
||||
3. 写一条决定:种类 `entries`,第 0 轮,规则名和版本照 rules 登记表的写法(`assignEntries` 不在登记表里,规则名就写 `assignEntries`,版本 1),种子 `null`,输入是全部志愿和入口,输出是分配结果。
|
||||
|
||||
决定的形状照 materials 的 `DecisionShapes`。"最终有效的入口"materials 已经算过一遍,导出来共用,不另写一份(第三部分第 1 条)。
|
||||
- **按配置跳过的步骤**:只有一位研究者时不讨论,config 的步骤清单已经标了跳过。flow 写一条"按配置跳过"事件,接着往下走。
|
||||
|
||||
### 2.9 参考项目不搬的
|
||||
|
||||
| 内容 | 为什么 |
|
||||
|---|---|
|
||||
| 写权续租(`loop.ts`) | 以后 plugin 用文件锁 |
|
||||
| 本轮重来、取代清单(`resume.ts` 后半) | 方法.md 第九部分:不支持中途作废重做 |
|
||||
| 换模板登记、哈希比对后写更换记录 | 改成核对提示词哈希,加上开发入口 |
|
||||
| 疑似运行暂停、违规事故处置、核销 | 方法.md 第八部分:不设"暂停等人处置" |
|
||||
| 基线单独公开、"公开了没有"这套判断 | 新项目阶段关闭就是公开;做完以第 2.2 节的记录为准 |
|
||||
| 判分时问 Jev 审查段、Jev 审实验员命令 | 方法.md 已删 |
|
||||
| 最大轮数、最后一轮预留 | 不设轮数上限 |
|
||||
| "做完一步账本没多就暂停"的空转检测 | 每一步都以一条确定的记录为准,没写成的步骤会被重做或报错,不会悄悄空转 |
|
||||
| 步骤先后散在 8 处 | 只写在"下一步做什么"一处 |
|
||||
|
||||
## 三、要改的别的模块(都很小)
|
||||
|
||||
1. **materials 导出"最终有效的入口"**:现在 `src/materials/blocks.ts` 的 `validEntries(board)` 只在内部用。导出一个按账本取的版本给 flow 分配时用,认领的对号清单和分配用同一份,不另写。
|
||||
2. **materials 加研究者编号规则**:`researcherId(i)`,第 i 位研究者(从 0 数)编号 `researcher-<i+1>`,和其他编号规则放在一起。这样正好和参考项目的写法一样,回放时不用改编号(参考项目入口编号 `researcher-1-e4` 对新项目的 `e-researcher-1-4`)。
|
||||
3. **materials 加研究配置记录的形状**:`StudyRecord`,内容见 2.8,和 `FrozenProtocol` 等放在一起。materials 不能引用 config、tasks,配置和任务事实的部分先写成 Json,flow 读回时用 `checkConfig`、`checkTaskFacts` 再检查。
|
||||
4. **dependency-cruiser 和 tsconfig**:
|
||||
- `npm run check` 也检查 `eval/`(tsc 的 include 加上 `eval/**/*.ts`,depcruise 加上 `eval`);
|
||||
- 加一条规则:`eval/` 只能经 `src/<模块>/index.ts` 用正式代码;
|
||||
- `src/` 不能引用 `tests/`、`eval/`,现有的 `outside-src` 规则已经管住了,确认一下。
|
||||
|
||||
## 四、正式代码和检验代码完全分开(用户 2026-10-03 特别强调)
|
||||
|
||||
用户原话:经常"把这两个混在一起……完全没法用。因为其实我们现在是有一大堆的测试代码是需要监控我们正式代码,是不是按照我们效果运行的"。
|
||||
|
||||
| 目录 | 放什么 | 怎么跑 |
|
||||
|---|---|---|
|
||||
| `src/flow/` | 正式代码,以后 plugin 直接用 | — |
|
||||
| `tests/` | 不花钱、不联网的测试,几秒到几十秒 | `npm test` |
|
||||
| `eval/` | 真实运行的检验:起研究、回放记录、杀进程、查账本、评研究质量。要花钱、要联网、要 Docker | `npm run eval:…` |
|
||||
|
||||
硬规矩,核对时逐条查:
|
||||
|
||||
1. `src/` 里不出现为检验写的任何东西:参数、环境变量开关、"回放模式"、假实现、只给检验用的导出、`if (测试)` 分支。`runStudy` 的参数就是 plugin 将来要传的那几样。
|
||||
2. 检验代码像用户一样用正式代码:写一份配置、调 `runStudy`、跑完用 `Ledger.open` 读账本。它不改正式代码的行为,不替换模块里的函数,不往账本里补写或改写记录。
|
||||
3. 回放用的假模型,照 `tests/agents.test.ts` 的做法:本机起一个兼容 OpenAI 的服务,用 Pi 自己的 `PI_CODING_AGENT_DIR` 指一份 models.json 过去。正式代码不知道对面是假模型。
|
||||
4. 检验跑出来的研究目录和报告放在仓库外:`/home/iomgaa/inforsi-eval/<日期-名字>/`,不提交。
|
||||
5. `eval/` 里的东西按用途分开:
|
||||
- `eval/lib/`:后面三部分也要用的工具:
|
||||
- 起研究的命令行入口;
|
||||
- 回放假模型;
|
||||
- 给检验用的 Jev 客户端;
|
||||
- 读账本的小工具。
|
||||
- `eval/round-zero/`:这部分专用的:
|
||||
- 想法清单;
|
||||
- 检验用的配置;
|
||||
- 回放脚本;
|
||||
- 质量评估;
|
||||
- 杀进程脚本。
|
||||
6. 检验用的 Jev 问题是检验自己的问题,写在 `eval/` 里,不加进 `src/jev/`。Jev 客户端在 `eval/lib/` 自己写一个小的,请求格式参照 `src/jev/jev.ts` 和 `/home/iomgaa/Projects/RivalBits/research-wiki/reference/参考-Jev使用指南.md`。不为了检验去改 `src/jev/` 的导出。
|
||||
7. 密钥:Jev 用环境变量 `TYPESAFE_API_KEY`,值在 `/home/iomgaa/Projects/RivalBits/.env`。在子 shell 里用 `set -a && . /home/iomgaa/Projects/RivalBits/.env && set +a` 加载,不要打印,不要复制进项目。
|
||||
|
||||
## 五、怎么验收:研究质量(重点)
|
||||
|
||||
### 5.1 尺子:关键想法清单和死路清单
|
||||
|
||||
26 圆填圆这道题,同类系统和参考项目的高分运行走过的路,监督者已经调研过,结论如下。写成 `eval/round-zero/ideas.json`:每条一个编号、中文名、给 Jev 看的英文说明(照下表"是什么"写,一两句)、出处。出处照抄下表。
|
||||
|
||||
我们的基线(0.9598)和 ShinkaEvolve 的起点程序逐字节相同,OpenEvolve、ThetaEvolve、AdaEvolve 也是同一个布局,所以它们的路径可以直接拿来当标杆。
|
||||
|
||||
**关键想法**(高分系统几乎都按"起点 → 联合优化 → 扰动重优化 → 收尾"的顺序走):
|
||||
|
||||
| 编号 | 名字 | 是什么 | 出处与作用 |
|
||||
|---|---|---|---|
|
||||
| K1 | 联合优化 | 把 26 个圆的圆心和半径(78 个数)一起交给带约束的连续优化器(如 scipy SLSQP),约束是都在正方形内、两两不重叠 | 最大的一跳:OpenEvolve 2.377→2.634;AdaEvolve 2.541→2.610;参考项目 12-real-1、12-real-2 第 1 轮采纳;16-real-1 关掉它少 0.132 |
|
||||
| K2 | 扰动重优化 | 从当前最好解出发,给圆心加中等幅度扰动(约 0.01–0.06),再跑联合优化,只收更好的;包括退火式接受、停滞后加大扰动 | AlphaEvolve、ShinkaEvolve、Discovery Loop;参考项目 12-real-2 第 2 轮靠它从 2.6155 到 2.635983,15-tight-2 也到了 2.635983 |
|
||||
| K3 | 结构化起点与多起点 | 从六角、错排行布局,或很多个随机起点出发,各跑一次优化,取最好 | ThetaEvolve、TTT-Discover 只靠"错排起点 + 一次 SLSQP"就到 2.635983;CodeEvolve 10 次重启 |
|
||||
| K4 | 固定圆心求最优半径 | 圆心不动,用线性规划求半径和最大 | ShinkaEvolve 容差 0 那次的第一步、Discovery Loop 的种子;16-real-1 消融撑 28% |
|
||||
| K5 | 严格合法收尾 | 最后统一缩一个极小量或精修,让结果在容差 0 下合法 | ShinkaEvolve、ThetaEvolve 严格版;本任务容差为 0(TASK.md) |
|
||||
|
||||
**死路**:
|
||||
|
||||
| 编号 | 名字 | 是什么 | 证据 |
|
||||
|---|---|---|---|
|
||||
| D1 | 只做几何构造 | 圆心按手排的规则摆(六角、方格、同心环),不用连续优化去移动圆心,只调排法和参数 | 各家卡在 2.2–2.54;等半径六角的上限是 2.438966;OpenEvolve 第一阶段提示词要求只写构造,卡在 2.377;参考项目 9a、9b-real-2 卡在 2.517、2.541 |
|
||||
| D2 | 只优化半径 | 圆心不动,只改怎么分半径,当作整条路线(不是当辅助步骤) | 上限受布局限制,2.5414 是反复出现的平台 |
|
||||
|
||||
### 5.2 六个问题
|
||||
|
||||
用户关心的不是程序跑没跑通,而是第零轮产出的东西好不好。第零轮跑完,对它的产出问下面六个问题。全部只看第零轮的产出就能回答。要等第 1 轮以后才看得到的(分工能维持多久、入口真的产出分数没有),留给第 2 部分。
|
||||
|
||||
"入口全体"指分配时最终有效的全部入口;"分到的入口"指分配结果里每人分到的那个。
|
||||
|
||||
| # | 问题 | 怎么判 | 通过的条件 |
|
||||
|---|---|---|---|
|
||||
| 1 | 方向对不对:入口全体里有没有关键想法 | 每个入口对 K1–K5 各问一次 Jev:"按这个入口走,会直接走到这个想法吗" | 入口全体里至少有一个指向 K1。K1–K5 各被几个入口覆盖,照实报 |
|
||||
| 2 | 分没分开:分到的几个入口是不是不同的路 | 分到的入口两两问 Jev:"从这两个入口出发的两位研究者,多半会做同一类代码改动吗" | 没有一对判"是" |
|
||||
| 3 | 好方向分出去没有 | 用第 1 问的结果看分到的入口;再对分到的入口各问一次 Jev:"这个入口的路线是不是只停在 D1 或 D2" | 分到的入口里至少有一个指向 K1,而且没有一个判为只停在 D1、D2 |
|
||||
| 4 | 入口是不是改代码的路线 | 每个入口问 Jev:"这是一条改程序代码来提高分数的路线吗?还是只读规则、只测量、只分析,没有打算改代码" | 分到的入口全部判"是" |
|
||||
| 5 | 入口有没有写答案 | 每个入口问 Jev:"入口有没有写出具体应该把代码改成什么,或者预计的分数、提升量"(方法.md 4.2:只写起点) | 分到的入口全部判"否";入口全体里判"是"的照实报 |
|
||||
| 6 | 讨论有没有用 | 闭门写完时的入口全体(写入口阶段的提交)和讨论后的入口全体,各算一次:不同作者的入口两两问第 2 问的那个问题,算判"是"的比例(重合度);再用第 1 问算 K1–K5 覆盖了几条 | 不设通过线,报讨论前后两组数,和参考项目的对照放在一起看 |
|
||||
|
||||
**问 Jev 的规矩**:
|
||||
- 问题用英文,一问只问一件事,照 `src/jev/questions.ts` 的写法:带材料说明、判"是"判"否"的说明、反例。
|
||||
- 入口原文是中文,原样放进材料。
|
||||
- 这六问的阈值都没有校准过:一律以概率大于 0.5 判"是",报告里同时给出原始概率,并注明"阈值未校准"。
|
||||
- 监督者会翻原文抽查 Jev 判得对不对。
|
||||
|
||||
**通过**:同样的配置真实跑 3 次,第 1 到 5 问每一次都通过,才算通过。只有一次做到不算。
|
||||
|
||||
**质量不通过时怎么办**:
|
||||
1. 先查是不是 flow 或 materials 写错了。看第一次运行每个阶段"模型调用开始"里存的材料,是否符合方法.md 4.2 那张表:
|
||||
- 写入口时:有任务说明、基线代码、基线分数,看不到别人的入口;
|
||||
- 讨论时:有全部入口(标明作者)和之前各次讨论;
|
||||
- 认领时:有最终的入口和全部讨论。
|
||||
|
||||
错了就修,修完重跑 3 次。
|
||||
2. 材料对,质量仍不通过,那是研究方法或提示词的问题,是要交给用户的发现。**不许为了通过去改提示词、改 Jev 问题、改阈值、改想法清单。** 照实报告,附上你看到的原因。
|
||||
|
||||
### 5.3 对照:参考项目 16-real-1 的第零轮
|
||||
|
||||
16-real-1 是参考项目唯一跑过第零轮的运行,也是唯一从头跑到尾没暂停的。它的第零轮原样放进新 flow 回放一遍,有两个用处:
|
||||
|
||||
1. **验证分配**。把它三位研究者当年交的入口、讨论、认领,按原顺序交给新 flow。分完以后,每人分到的入口、是第几志愿,必须和参考项目当年的分配记录相同:researcher-1 → e4,researcher-2 → e2,researcher-3 → e6,都是第 1 志愿。第零轮不问 Jev、没有随机,所以要求完全相同。不同就说明 flow 取志愿、取入口时出了错。
|
||||
2. **当质量对照**。回放出来的账本也按 5.2 的六问打一遍分,作为"参考项目第零轮的成绩",和新项目 3 次真实运行的成绩放在同一张表里。
|
||||
|
||||
已知的情况:讨论中研究者 2 指出"圆心和半径一起交给优化器"这条路没人站,研究者 1、3 随后补了这样的入口(e5、e7),但认领时三人选的是 e4、e2、e6。也就是说,K1 在入口全体里,却没有分出去。
|
||||
|
||||
**怎么取当年的记录**:
|
||||
- 账本:`/home/iomgaa/rb-acceptance/16-real-1/board.sqlite`,只读,一律用 `sqlite3 -readonly` 或 node 的只读方式打开。
|
||||
- 第零轮的提交在 `submissions` 表,按 `stages.phase` 区分:`entry-draft`、`entry-discuss`、`entry-claim`。按 `created_seq` 排序,在 21–77 之间,第零轮没有退回。
|
||||
- 分配结果在 `facts` 表 `kind='entry-assignment'`。
|
||||
- 格式转换:
|
||||
- 当年入口是 `{name, startFrom, whyWorth}`,新项目是 `{name, body}`。`body` 拼成"从哪里开始看:……"加一个空行加"为什么值得走:……"。
|
||||
- 讨论的 `body` 照搬;讨论里有 `entries` 的,同样转换。
|
||||
- 认领的 `choices` 从 `researcher-1-e4` 改成 `e-researcher-1-4`。
|
||||
- 回放的假模型:每位研究者一个模型名,按这个人当年交的先后,每次被派任务时交出下一份,然后回一句话结束。新 flow 退回了其中某一份时,假模型没有别的可交,回放到这里就停。这时照实报告:哪一份、退回原因、按方法谁对。不改回放内容去凑。
|
||||
- 回放时基线照样用真 Docker 跑。
|
||||
|
||||
### 5.4 程序能不能接着跑(必要,但不是重点)
|
||||
|
||||
用户说过,这类检查重要,但不是他最关心的。做一遍,报告里简短写结果。
|
||||
|
||||
**杀进程**:在下面三处各杀一次控制进程(`SIGKILL`),再启动,让它跑完第零轮:
|
||||
1. 基线容器正在跑;
|
||||
2. 研究者 2 正在写入口;
|
||||
3. 某个阶段最后一份提交刚收下、阶段还没关。
|
||||
|
||||
第 3 处时间窗口很短,打不中就报告实际杀在哪里:杀之前记下账本最后一条记录。
|
||||
|
||||
每次跑完,查这几条:
|
||||
- 基线只扣了 1 次(`runStarted` 只有一条有效的),Docker 里没有第二个基线容器;
|
||||
- 被杀那次调用有结束记录,结局"出错",原因"进程中断";
|
||||
- 被杀时没交上的人被重新派了,交过的人没被重派;
|
||||
- 每个阶段最后都关上了;每人每阶段只有一份最终收下的提交;
|
||||
- 分配照常写出。
|
||||
|
||||
**两份研究同时跑**:两个不同研究编号的研究同时启动,都跑到基线结束。两边各扣各的、容器不撞名。
|
||||
|
||||
### 5.5 检验用的配置
|
||||
|
||||
`eval/round-zero/research.json`:
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| 研究者 | 3 位,模型都用 glm-5.3(provider 名和思考档位照 `tests/agents-pi.ts` 用的那份) |
|
||||
| 讨论次数 | 2 |
|
||||
| `runs` | 13 |
|
||||
| `batchLimit` | 2 |
|
||||
| `proposalLimit` | 1 |
|
||||
| `factorLimit` | 3 |
|
||||
| `devEntry` | `false` |
|
||||
| 其余方法参数 | 照方法.md 6.11 的现行值 |
|
||||
|
||||
运行次数、每批上限、提案上限、研究者人数和 16-real-1 相同,方便对照。
|
||||
|
||||
## 六、不花钱的测试(`tests/`)
|
||||
|
||||
只测"下一步做什么"这个纯函数:手写几组账本记录,看它给出的下一步。至少覆盖:
|
||||
- 空账本 → 冻结配置;
|
||||
- 有配置、没有基线 → 跑基线;
|
||||
- 基线最近一次是"没启动" → 用新编号再跑;
|
||||
- 阶段开着、一人已交、两人没交 → 派那两人;
|
||||
- 都交了 → 关阶段;
|
||||
- 有人最近一次是"没交":开发入口关着停下,开着重新派;
|
||||
- 有人最近一次是"出错"或"进程中断" → 重新派;
|
||||
- 只有一位研究者 → 讨论写跳过;
|
||||
- 分配做完 → 停下,原因"第 1 轮还没写"。
|
||||
|
||||
其余都由第五部分的真实运行来证明,不另写假模型、假 Docker 的测试(用户 2026-10-03 定:一律真 Jev、真 Docker)。
|
||||
|
||||
## 七、审阅
|
||||
|
||||
这部分涉及运行登记、扣次和恢复(CLAUDE.md"工作方式")。写完后另派一个全新上下文的子 Agent 审阅一轮,只看 2.5 恢复入口和 2.7 跑一次正式运行。审阅只防 CLAUDE.md"罕见情况怎么办"里的三类情况,提了别的照列不改。
|
||||
|
||||
## 八、规模
|
||||
|
||||
- `src/flow/` 这部分预期 900–1200 行,不含测试和检验。超过 1200 行就停下来检查:是需求本身复杂,还是专门路径在变多。
|
||||
- materials 的改动预期 40 行以内。materials 上限 1900 行,现在 1868 行。
|
||||
- `eval/` 预期 600–1000 行,不算进 flow。
|
||||
|
||||
## 九、文档
|
||||
|
||||
完成后更新:
|
||||
- `docs/结构.md` 第八部分:新加 flow 一节,写 `runStudy`,以及 2.2 那张"做完以哪条记录为准"的表。表只写在这里,代码注释指向它。materials 一节补上第三部分的三处。
|
||||
- `docs/结构.md` 第七部分:flow 的预期行数先不改。
|
||||
- `package.json`:加 `eval:` 开头的几个命令。每个命令要能直接跑,命令名和用途写进结构.md 第八部分 flow 一节的末尾。
|
||||
- `WORK_LOG.md`:
|
||||
- "已完成"补一条;
|
||||
- 删掉第十部分列的、这次已经做到的"给 flow"条目;
|
||||
- 3 次真实运行的研究目录路径写进"已完成"那一条。
|
||||
|
||||
不新建 md 文件。
|
||||
|
||||
## 十、"给 flow"的条目里归这部分的
|
||||
|
||||
WORK_LOG"未完成"里的:
|
||||
- 确认启动前要先登记运行;模型调用要先开始再结束;阶段要先开再关(2.6、2.7、2.3);
|
||||
- 容器名要在本机所有研究之间唯一;日志目录每次运行一个新的(2.1、2.7);
|
||||
- 取出时目标目录必须是空的(2.1);
|
||||
- 阶段关闭只在名单上的人交齐后写(2.3)。同一条里冻结协议、解封的写入时机归第 2、4 部分,那半句留着;
|
||||
- 形状不合格的提交由 flow 直接记退回,不经 submissions(2.6)。同一条里"修复的差异块按本批基线算"归第 3 部分,那半句留着。
|
||||
|
||||
其余"给 flow"条目归后面三部分,这次不做。
|
||||
|
||||
## 十一、验收与报告
|
||||
|
||||
做完后本地提交,然后在回复里交一份报告。监督者会对着实际文件、账本和检验输出逐项核对:
|
||||
|
||||
1. 提交号;新增和修改的文件列表,分 `src/`、`tests/`、`eval/` 三组列;每个文件的行数;`src/flow` 总行数、`eval` 总行数、materials 总行数。
|
||||
2. `npm run check`、`npm test` 的完整输出。
|
||||
3. **研究质量**:
|
||||
- 一张表:行是 3 次真实运行加 16-real-1 回放,列是六问的结果和是否通过;
|
||||
- 每次运行分到的三个入口的名称,以及入口全体的名称;
|
||||
- Jev 原始概率所在的 JSON 文件路径;
|
||||
- 3 次运行的研究目录路径。
|
||||
4. 16-real-1 回放的分配结果,和参考项目当年的对照;回放中如果有提交被退回,列出来。
|
||||
5. 杀进程和两份同时跑的结果,按 5.4 那几条逐条写。
|
||||
6. 你和这份任务书、结构.md、方法.md 不一致的地方,以及为什么。
|
||||
7. **规则不清楚的地方**:哪里让你犹豫、哪里你是靠猜的。没有就写"没有"。没有真实证据的可能情况,在这里提一句就够,不写进 WORK_LOG。
|
||||
8. 正式代码和检验代码分开的自查:逐条对照第四部分的 7 条,写"做到了"或"没做到、为什么"。
|
||||
Reference in New Issue
Block a user