fix: 补齐六处"文档承诺了但代码里没有"的缺口 - #1
Open
arena-ai-coding-agent[bot] wants to merge 2 commits into
Open
Conversation
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
这一批的共同点:文档或配置已经承诺了某件事,而实现是空的。 它们的失效方式都很安静——在本地什么都不报错,只有照着文档去用的人才会撞上。 1. LICENSE 不存在 两份 README 结尾都写着 [MIT](LICENSE),package.json 也没有 license 字段。 一个写了 Contributing 流程的开源项目,仓库里没有许可证文本, 法律上等于"保留所有权利"。补 LICENSE + license 字段。 2. docs/MIGRATION.md 不存在,却被引用三次 其中一处是 ARCHITECTURE.md 的"见 MIGRATION.md 的进度表"—— 把"这个项目还没做什么"整个外包给了一个不存在的文件。 改成把诚实清单内联进 ARCHITECTURE.md(表格:缺什么/现状/影响)。 3. web_search 是一条完整的死配置 config.js 解析 WEB_SEARCH_HOST/TENANT_CODE、run-service 一路传进工具上下文, 然后没有任何东西读它;.env.example 还专门写了一节。部署方配好搜索网关重启, 什么都不会发生,也没有一行日志说不对。整条删除,并在 src/tools/index.js 写明为什么不留、以及将来要补时的正确顺序(先写工具再加配置)。 4. 架构文档的"诚实清单"已经不诚实 它说没有"断线续接",但那个功能做完了(run-registry 缓冲 + /v1/runs/:runId/events + /healthz 的 runResume 宣告 + 专门的测试)。 同时两份 README 都缺 /v1/runs 与 /v1/runs/:runId/events 两条接口—— 做完了的功能对外不可见。补上接口表与"断线接回"一节。 5. CI 从未跑过 MySQL 存储契约 README 写着"CI should do that, since it is what catches the double drifting", 而 workflow 里没有 mysql service。唯一能发现内存替身与真库漂移的闸, 一次都没关过。⚠️ 改动放在 docs/patches/ci-mysql-service.patch,需要有权限的人手工应用—— GitHub App 没有 workflows 权限,带着 .github/workflows/ 的改动推分支会被 服务端拒绝。补丁已验证:apply 干净、产物与本地验过的版本逐字节一致、YAML 可解析。 6. 依赖安全告警一直红着,没有结论 实为 4 条 advisory(2 high + 2 low),全部来自 pi。逐条判可达性后结论是 四条都不可达,依据写进 docs/SECURITY-NOTES.md(含复核方法与回看条件)。 注:npm audit fix --force 会把 pi 降到 0.49.3,且修不了—— 影响范围 <=0.73.1 而 0.73.1 就是最新版,上游尚无修复版本。 顺带修掉过程中发现的三个同类问题: - 新增 test/docs-links.test.js(扫全仓库 markdown 的相对链接),当场又抓出两条: managed-skills → ../skill-libs/README.md 不存在(补上,写清与 managed-skills 的分工:一个进 worker 镜像一个进 agent 镜像);sandbox-manager → docs/PROTOCOL.md 不存在且被引用 3 次(那份文档未随仓库开源,改指真实存在的 sandbox-worker/PROTOCOL.md 与代码,并删掉一整块描述不存在目录的目录树)。 - docs/ISOLATION-CONTRACT.md 不存在,却被 4 处引用,其中一处是隔离检查失败时 打印给人的第一指引。这比断链严重——它是整个项目安全前提的落点。 按代码实况补齐:九条规则逐条写明 要求/为什么/在哪/谁守着, 并标注边界之外的东西(内核逃逸、额度不是安全边界、agent 侧出站白名单为空)。 - 补静态规则 R2-AgentSession 必须保持 noTools: builtin。 在此之前这个总闸只由代码注释守着,而它在 diff 里只有一个单词,改掉之后 功能照常、命令却不再跑在沙盒里。它同时是上面两条 high 告警"不可达"的前提。 (规则第一版的否定环视因 \s* 回溯把两处写对的地方全判红了,已在注释里记下。) 验证:npm run check 全绿(1347 项,较之前 +22),web 构建通过, 隔离检查 9 条规则零命中,并单独验证了新规则确实能抓到故意写坏的 noTools。 Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这个 PR 做什么
修掉六处**"文档或配置已经承诺了,而实现是空的"**的缺口,外加过程中发现的三个同类问题。
它们的共同点是失效时一声不响:在本地什么都不报错,Markdown 照常把断链渲染成蓝色,
配置照常被解析 —— 只有照着文档去用的人才会撞上,而那个人通常是第一次来的读者。
六条
1.
LICENSE不存在两份 README 的结尾都写着
[MIT](LICENSE),package.json也没有license字段。一个对外开源、README 里还写了 Contributing 流程的项目,仓库里没有许可证文本,
法律上等于"保留所有权利":任何人都不能合法使用它。这不是排版问题。
→ 补
LICENSE(MIT)+package.json的license字段。2.
docs/MIGRATION.md不存在,却被引用三次其中一处是
ARCHITECTURE.md的"见 MIGRATION.md 的进度表" ——把"这个项目还没做什么"这个问题整个外包给了一个不存在的文件。
→ 诚实清单内联进 ARCHITECTURE.md,改成表格(缺什么 / 现状 / 影响),
不再指望一个外部文件。
3.
web_search是一条完整的死配置config.js解析WEB_SEARCH_HOST/WEB_SEARCH_TENANT_CODE、run-service.js一路传进工具上下文,然后没有任何东西读它 ——全仓库没有名为
web_search的工具。.env.example还专门写了一节。部署方照着
.env.example配好搜索网关、重启,什么都不会发生,也没有一行日志说不对。比"没这个功能"更难查。
→ 整条删除,并在
src/tools/index.js写明为什么不留、以及将来要补时的正确顺序:先写工具再加配置,用现成的能力闸门
(
requires: ['webSearch'],后端没配就不注册,模型压根不知道有这回事)。4. 架构文档的"诚实清单"已经不诚实了
它说当前骨架没有断线续接 —— 但那个功能做完了:
src/agent/run-registry.js缓冲事件、runService.attach()、HTTP 面
/v1/runs/:runId/events、/healthz的runResume能力位、以及
test/run-resume.test.js专门测的序号/重放/丢帧/归属校验。顺带:
/v1/runs和/v1/runs/:runId/events两条接口在两份 README 里都没有 ——做完了的功能对外不可见。
→ 纠正清单;两份 README 补上接口表和「断线接回」一节,
写清三个设计决定:为什么是 GET 而不是重发 POST(一次抖动 = 又跑一轮又烧一份 token)、
为什么归属校验必须在写下任何字节之前(
200写出去就收不回来了)、为什么丢帧要发
resync而不是装作接上了(缺了几句又看不出缺过的回答更糟)。5. CI 从未跑过 MySQL 存储契约
README 明确写着 "CI should do that, since it is what catches the double drifting",
而 workflow 里没有 mysql service。
生产只有 MySQL 一种后端,测试却全跑在内存替身上。替身最大的风险不是"它错了",
而是**"它自己对了,但跟真的不一样"。
test/storage-drivers.test.js早就把每条断言跑两遍来挡这个,但真库那一遍在没有
AP_TEST_MYSQL_URL时整块跳过** ——也就是说,唯一能发现替身漂移的那道闸,一次都没关过。
6. 依赖安全告警一直红着,没有结论
→ 逐条判可达性,结论写进
docs/SECURITY-NOTES.md(含复核方法和"什么时候必须回来重看")。
实际是 4 条 advisory(2 high + 2 low),全部来自
@mariozechner/pi-coding-agent:find/grep下载 fd/rg 时用到,而内置工具全关AuthStorage.inMemory(),从不落盘npm audit fix --force不仅是破坏性降级(pi → 0.49.3),而且修不了 ——影响范围
<=0.73.1,而 0.73.1 就是当前最新版,上游尚无修复版本。正确动作是盯上游,不是动版本号。
写这份文件而不是让它继续红着的理由:一个
npm audit长期红着的项目,最后一定没人看它 ——于是真出现一条该管的告警时,它和这几条一起被划过去。要么修掉,要么写清楚为什么不修,没有第三种状态。
过程中发现的三个同类问题(一并修了)
第 1 条那个断链是人眼看出来的。既然要修,就顺手写了一条测试去扫全仓库所有
markdown 的相对链接 —— 结果它当场又抓出两条我没看见的:
managed-skills/README.md→../skill-libs/README.md(不存在)→ 补上,写清
skill-libs/与managed-skills/的分工:一个进 worker 镜像、一个进 agent 镜像,
搞混的表现是"模型说有这个技能、进去却找不到脚本",而且不报错。
sandbox-manager/README.md→docs/PROTOCOL.md(不存在,被引用 3 次)→ 那份协议文档没有随仓库开源。三处引用改指真实存在的
sandbox-worker/PROTOCOL.md与代码;并删掉一整块描述不存在目录的目录树(
workers/、modules/、docs/—— 照着找的人会以为自己 clone 少了东西),换成实际的
src/结构。第三条是修第 6 条时撞见的,比断链严重:
docs/ISOLATION-CONTRACT.md不存在,却被 4 处引用 ——包括
scripts/check-isolation-rules.js在检查失败时打印的"详见 docs/ISOLATION-CONTRACT.md"(人看到报错时的第一指引),
以及
run-turn.js开头的"改这个文件前先读"。它是这个项目全部安全前提的落点。
→ 按代码实况补齐:九条规则逐条写明 要求 / 为什么 / 在哪 / 谁守着,
并诚实标注边界之外的东西(内核逃逸、额度不是安全边界、agent 侧出站白名单是空的)。
由此补上的一个真缺口
写第 9 条时发现:
noTools: 'builtin'(pi 内置工具的总闸,也是上面两条 high"不可达"的前提)此前只由代码注释守着 —— 旁边写着"不要改",
而它在 diff 里只有一个单词,改掉之后功能照常工作、没有任何征兆,
只是命令不再跑在 sandbox 里了。现有的 R2 规则拦的是
createBashTool(/createCodingTools(,覆盖不到这种写法。→ 新增静态规则
R2-AgentSession 必须保持 noTools: builtin。单独验证过它确实能抓到故意写坏的值(临时把一处改成
'all',规则报红,改回后零命中)。验证
git diff确认逐字节一致)。git apply --check干净、产物与验过的版本逐字节一致、YAML 可解析。审阅建议
按这个顺序看最快:
docs/FEATURE-REVIEW.md—— 完整盘点,P0 那节标了每条的结论docs/ISOLATION-CONTRACT.md—— 新增,是否与你心里的契约一致(这份最需要你确认)docs/SECURITY-NOTES.md—— 四条可达性判断是否认可src/三个文件共 -7 行 +9 行(删死配置 + 一段注释),scripts/check-isolation-rules.js加一条规则需要你决定的两件事
LICENSE的版权署名目前写的是2026 AgentPod contributors—— 要换成具体个人或公司请直接改。