docs: record real-project run 2026-10-26
This commit is contained in:
1 parent
73fdead337
commit
ed55c9651a
1 file changed
+66
@@ -185,6 +185,72 @@ tests/ 标准库 unittest,验收命令就是 `python3 -m unittest discover -s
|
|||||||
|
|
||||||
## 生产加固(2026-10-26,state 锁 / 项目配置 / 定时自动化)
|
## 生产加固(2026-10-26,state 锁 / 项目配置 / 定时自动化)
|
||||||
|
|
||||||
|
- **state 锁**:`host-state.json.lock` + fcntl 锁,锁只包住读/写
|
||||||
|
短临界区,不包整个模型 turn;保存时在锁里重读磁盘,按任务名
|
||||||
|
覆盖、按自动化名合并,tmp 文件带 pid。
|
||||||
|
实测:两个进程同时加载、睡 0.5 秒、各自加一个任务再保存,
|
||||||
|
最终两个任务都在,没有合并逻辑的话后保存的会把先保存的覆盖掉。
|
||||||
|
- **项目配置**:`host.py init` 生成 `host-config.json`(repo、
|
||||||
|
model、effort、沙箱、审批、codex_home、state,无密钥),
|
||||||
|
`host.py config` 打印有效配置,优先级 CLI > 配置 > 内置默认;
|
||||||
|
dispatch/goal 不传 --repo 时用配置里的 repo,没配则明确报错。
|
||||||
|
实测:/tmp 测试配置 init、config、repo 缺省路径都通;
|
||||||
|
项目里默认没有 host-config.json,旧调用方式不受影响。
|
||||||
|
- **定时自动化**:run-due 现在写 `host-run.log`(派发和跳过都记),
|
||||||
|
`automations --cron-line` 只打印 crontab 行,不装机;
|
||||||
|
`automations --install-cron` 才真正写 crontab 且幂等。
|
||||||
|
实测:未到期的自动化 run-due 输出为空,但日志里有一条 skip;
|
||||||
|
cron 行已验证格式正确,本次没有实际装机——装机后模型任务
|
||||||
|
会自动跑、花中转站额度,所以装机这一步留给用户显式下令。
|
||||||
|
另注意:VM 会被平台回收,crontab 不一定活过回收,常驻机器
|
||||||
|
用 crontab,VM 上更稳的是 Muse cron 定时调 run-due。
|
||||||
|
- **未修 / 已知局限**:锁只能防同一台机器上的多进程竞态,
|
||||||
|
不能防两台机器同时写同一个共享 state 文件;定时任务本身
|
||||||
|
仍需外部调度器(crontab 或 Muse cron)触发,host.py 自己
|
||||||
|
不常驻。
|
||||||
|
|
||||||
|
## 真实项目一轮(2026-10-26 凌晨,用户选“先在真实项目上跑一轮再打包”)
|
||||||
|
|
||||||
|
- **选项目**:没动生产敏感的 wechat-bridge(带 session 凭证),
|
||||||
|
选 codex-app-server 本身做 dogfooding——这是真实代码,不是
|
||||||
|
玩具仓。为此先把本项目初始化成 git 仓(commit b49b9cf、
|
||||||
|
d1e842b):.gitignore 排除 bin/(367M 本机补丁)、work/、
|
||||||
|
host-state*.json、host-run.log、本地 host-config*.json;
|
||||||
|
真实任务用独立 state(host-state-real.json),与玩具任务的
|
||||||
|
host-state.json 分开。
|
||||||
|
- **并行任务**:real-tests(新建 tests/test_host.py,标准库
|
||||||
|
unittest 覆盖 load_state/save_state 合并、task_diff 未追踪
|
||||||
|
文件、_load_config_file 缺失文件,3 个测试全过,不改
|
||||||
|
host.py);real-backup(save_state 锁内加备份轮转,保留
|
||||||
|
.bak/.bak.1/.bak.2,py_compile 通过,临时 state 两次保存
|
||||||
|
后 .bak 存在)。
|
||||||
|
- **评审**:两个 diff 都干净,无无关改动;real-backup 的只读
|
||||||
|
评审指出轮转多步非原子、复制中断可能留截断 .bak、无
|
||||||
|
fsync、无 fcntl 平台上锁失效——前两条做了小修复(见下),
|
||||||
|
后两条是本地单机工具的已知边界,未为此上重型方案。
|
||||||
|
- **修复轮**:real-backup 追加一回合,把 _read_state_file 和
|
||||||
|
save_state 的 open 改成 with open(修掉真实测试跑出的
|
||||||
|
ResourceWarning 未关闭文件),备份复制改成先拷临时文件再
|
||||||
|
os.replace 到 .bak;轮转层数和锁逻辑未改,未新建 tests/。
|
||||||
|
- **合并验收**:real-tests、real-backup 依次 merge 到主仓
|
||||||
|
(commit 7f4e2ed、73fdead,主仓 clean,只剩 work/ 下的
|
||||||
|
本地 job 定义,未进版本控制);主仓 `python3 -m unittest
|
||||||
|
discover -s tests -v` 3 个测试全过,且无 ResourceWarning;
|
||||||
|
主仓手动保存两次,.bak 存的是前一版 state,主文件是
|
||||||
|
合并后版本,备份逻辑正确。
|
||||||
|
- **玩具仓没暴露、真实轮暴露的**:项目本身不是 git 仓时 host
|
||||||
|
的 worktree/merge 门跑不起来,必须先 git init;.gitignore
|
||||||
|
缺失时 367M 的 bin/ 会进版本控制;state 文件和本地配置
|
||||||
|
必须与玩具任务分开,否则真实任务和测试任务混在一个
|
||||||
|
host-state.json 里;save_state 的未关闭文件警告只有在真实
|
||||||
|
测试跑起来后才被看见。
|
||||||
|
- **结论**:host 编排在真实项目上跑通了完整链路(并行 →
|
||||||
|
评审 → 只读评审 → 修复 → 合并 → 主仓测试验收),下一步
|
||||||
|
才是打包:.gitignore 已有、tests/ 已有雏形、备份已落地,
|
||||||
|
打包缺的仍是安装说明、host 快速开始、版本号/changelog、
|
||||||
|
以及 merge 后自动跑主仓测试这一步(本次是手动跑的)。
|
||||||
|
|
||||||
|
|
||||||
- **state 锁**:`host-state.json.lock` + fcntl 锁,锁只包住读/写
|
- **state 锁**:`host-state.json.lock` + fcntl 锁,锁只包住读/写
|
||||||
短临界区,不包整个模型 turn;保存时在锁里重读磁盘,按任务名
|
短临界区,不包整个模型 turn;保存时在锁里重读磁盘,按任务名
|
||||||
覆盖、按自动化名合并,tmp 文件带 pid。
|
覆盖、按自动化名合并,tmp 文件带 pid。
|
||||||
|
|||||||
Reference in new issue
Block a user