[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f8qSElBRMQvQ0TzKohSdY2j4dt-y4rc0nk_MjIn0ASkA":3},{"item":4,"related":51},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":39,"sourceName":40,"sourceUrl":41,"status":42,"seoTitle":43,"seoDescription":44,"canonicalUrl":45,"isFeatured":46,"sno":47,"sortOrder":48,"publishedAt":49,"updatedAt":50,"createdAt":50},"b12a5d11-9995-4996-9517-451945ab9267","article","Hermetic Build：让构建不再偷偷依赖你的电脑","hermetic-builds-ai-coding","Hermetic Build 通过隔离工具、依赖和环境，减少“在我电脑上能运行”的问题，让 AI 编程更容易获得稳定反馈。","## Hermetic Build：让构建不再偷偷依赖你的电脑\n\n“在我电脑上能运行”是软件开发中最常见、也最让人头疼的一句话。问题往往不是代码本身，而是电脑上安装了不同版本的编译器、系统库、命令行工具、环境变量或缓存。Hermetic Build，也就是封闭式构建，试图让构建过程只依赖被明确声明的输入。\n\n## 封闭到底封闭了什么\n\n一个更接近封闭的构建系统，会固定源代码、工具版本、依赖和配置，并尽量隔离主机环境。相同输入和配置应该产生相同或可解释的输出，而不是因为某台电脑恰好装过某个工具就成功。\n\n这并不意味着所有项目都必须立刻迁移到大型构建系统。更基本的做法包括：在干净容器中构建，锁定运行时版本，明确声明依赖，不从用户家目录读取隐形配置，并让 CI 在全新的机器上重建项目。\n\n## AI 编程为什么特别需要它\n\nAI Agent 可能在本机、云端沙箱和 CI 里轮流工作。如果每个环境看到的工具和依赖不同，Agent 会把环境问题误判成代码问题，然后反复修改源文件。一个干净、可描述的构建环境，能让错误反馈更接近真实原因。\n\n封闭构建还可以减少缓存误导。Agent 可能看到某个本地缓存导致测试通过，但换到干净环境就失败。把构建输入和缓存边界分清楚，才能判断“代码真的正确”还是“环境刚好帮了忙”。\n\n## Hermetic 不等于安全绝对\n\n封闭构建降低了隐形依赖，却不能自动证明依赖没有漏洞，也不能防止构建脚本主动执行危险行为。它解决的是可控和可复现问题，仍需配合权限、依赖审查和产物验证。\n\n## 一个适合个人项目的起点\n\n让 AI 为项目写一个明确的构建说明：需要什么版本、从哪里安装依赖、如何在空目录执行、怎样运行测试。然后在干净环境里真正执行一次。只要能把“我的电脑状态”逐步变成“项目声明”，就已经开始接近封闭式构建。\n\n关于 Hermeticity 的定义、收益与常见泄漏来源，可阅读 [Bazel 官方说明](https:\u002F\u002Fbazel.build\u002Fconcepts\u002Fhermeticity)。","\u002Fuploads\u002F2026-09-14\u002F0a4eec65-0454-4f9d-9d96-e55b7644618d.jpg",[],[],"Foundit","https:\u002F\u002Ffoundit.cn","foundit-ai-editorial",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31,35],{"id":24,"name":25,"slug":26},"0848beb4-db26-4fb8-b391-f852a11be192","AI编程","ai-coding",{"id":28,"name":29,"slug":30},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":32,"name":33,"slug":34},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev",{"id":36,"name":37,"slug":38},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug","官方资料","Bazel","https:\u002F\u002Fbazel.build\u002Fconcepts\u002Fhermeticity","published","Hermetic Build 是什么？如何解决环境不一致","理解封闭式构建，以及为什么 AI Agent、本机和 CI 需要尽量使用同一套构建条件。",null,false,49,0,"2026-09-14T00:00:00.000Z","2026-09-14T15:01:37.834Z",[52,60,68],{"id":53,"type":6,"title":54,"slug":55,"summary":56,"coverUrl":57,"authorName":14,"sno":58,"publishedAt":49,"createdAt":59},"54d83c94-d588-400d-9d13-42daa20331e2","CAS：文件的身份可以由内容决定","content-addressable-storage-ai-coding","内容寻址存储 CAS 用内容摘要识别文件和构建产物，解释 AI 编程工具、容器和缓存为什么能复用结果。","\u002Fuploads\u002F2026-09-14\u002F3fab23b3-8bcd-4a3b-bf5a-2ab895ce3a10.jpg",41,"2026-09-14T15:01:41.114Z",{"id":61,"type":6,"title":62,"slug":63,"summary":64,"coverUrl":65,"authorName":14,"sno":66,"publishedAt":49,"createdAt":67},"1be15b45-ad30-4bbf-b711-718a9ffc58b3","Tree-sitter：为什么编辑器不用每次重读整个文件？","tree-sitter-incremental-parsing-ai-coding","Tree-sitter 用增量解析和语法树帮助编辑器与 AI 编程工具只处理代码变化的局部，让搜索、补全和结构化修改更高效。","\u002Fuploads\u002F2026-09-14\u002Fc4a4730d-34e0-43bb-8d5c-bd79b20e1969.jpg",47,"2026-09-14T15:01:26.675Z",{"id":69,"type":6,"title":70,"slug":71,"summary":72,"coverUrl":73,"authorName":14,"sno":74,"publishedAt":49,"createdAt":75},"373f9a49-3705-46dc-823c-7ef1923f1b54","OpenAPI 如何让 AI 同时写前后端不“各说各话”？","openapi-ai-frontend-backend-contract","AI 可以分别生成前端和后端，却容易在字段、错误和时间格式上互相错位。本文解释 OpenAPI 如何把接口输入输出变成共同契约，再连接生成代码和契约测试。","\u002Fuploads\u002F2026-09-14\u002F4e99751f-020c-45dd-a87d-1a9fbb8f0f83.jpg",48,"2026-09-14T11:00:08.021Z"]