其他语言: English, Español, Português, 日本語, Deutsch, Français, 한국어, Italiano, हिन्दी · 全部中文指南
声明:Carbon Forge 由 100monkeys.ai 开发,因此请把这篇指南当作开发方的说明来读。它由我们的一个 AI 智能体根据公开文档(英文)起草,主要是 MCP tools catalog: Semantics 中的 symbols.drift 和 Governed seams 两节,以及 The Carbon paradigm 中的 "Drift between prose and code",并经公司审阅;这个简体中文版是英文原版指南的译文。表格和调用都是文档自己的示例,引文保留英文原文,译文附在旁边。文档没有回答的问题,最后一节会说明。
这份报告是什么
范式页面的一句话:"A workspace's reserved .governed-seams page declares which pages govern which definitions of a code tree"(工作区保留的 .governed-seams 页面声明哪些页面管辖代码树中的哪些定义)。symbols.drift "joins every definition a lane adds, removes or re-signs to the seams that govern it and reports each as changed with or without a patch to its governing page on the same lane, from the syntax index alone, so the same lane and the same seams page answer the same report byte for byte."(把 lane 新增、删除或改了签名的每个定义,与管辖它的 seam 关联起来,并报告每一个是在同一条 lane 上带着还是没带着对其管辖页面的补丁而改变的;只依据语法索引,所以同一条 lane 和同一个 seams 页面会给出逐字节相同的报告。)没有任何模型去读任何东西。还有一个要记住的限制:"The report advises and never refuses a landing."(报告只提建议,从不拒绝落地。)
第 1 步:挑出页面所描述的定义
先从那些一旦代码在其下变动就会误导读者的页面开始:关于计费的架构页面、关于登录的指南。用语义索引找到它们描述的定义:
symbols.search { "tree": "app", "query": "charge", "prefix": true } 定义来自 tree-sitter 针对 TypeScript 和 TSX、JavaScript、Python、Go、Rust、C、C++、C#、Java、Ruby、PHP、Scala 和 Bash 的 tags 查询。CSS、HTML、JSON、YAML、TOML 和 HCL 会得到语法树,"but no definitions or references"(但没有定义或引用),所以覆盖这些文件的 seam 什么也不会报告。名称是 "matched by name, not by type checking"(按名称匹配,而不是靠类型检查)。
第 2 步:编写 .governed-seams 页面
在保留路径 .governed-seams 创建一个页面,其第一个 Markdown 表格的表头是 tree | glob | symbols | records。文档的示例:
| tree | glob | symbols | records |
| --- | --- | --- | --- |
| app | src/billing/** | chargeCard, refund | architecture/billing |
| app | src/auth/*.ts | * | guides/login, architecture/security | tree:代码树的路径。glob:针对代码树文件路径的一条规则,使用导入忽略规则的语法,不以!开头。symbols:逗号分隔的定义名称,或单独一个*,表示 glob 下的所有定义。records:逗号分隔的页面路径,即管辖这些定义的页面。
"A seam is declared, never inferred: no link, tag, metadata key or embedding makes one."(seam 是声明出来的,从不推断:任何链接、标签、元数据键或嵌入都不会产生 seam。)这个页面从 trunk 读取,"so a lane cannot ungovern its own change."(所以一条 lane 无法让自己的修改脱离管辖。)要在它要监视的工作之前把它落地到 trunk。格式错误的页面会让所有报告停止,直到修好为止,并给出一句指明行号的话:The governed seams page .governed-seams is malformed at line <n>, ...
第 3 步:在 lane 上修改受管辖的代码
报告读取的是 lane,所以修改必须在 lane 上:先 lanes.create,再用带 lane 的 trees.apply_patch 或 trees.put,如 Working in lanes 所示。比如,给 chargeCard 加一个参数,改变它的签名。
第 4 步:阅读漂移报告
symbols.drift { "lane": "agent/7/fix-login" } 加上 tree 可以只读一个代码树。回答如下:
{ lane, composition_hash, report_sha256, findings, pending, governed_rows } 每条发现都给出 tree、path、symbol 和 kind,trunk 上的 from_signature 和 lane 上的 to_signature(某一侧没有时为 null),形如 { path, updated_on_lane } 的 records,以及 callers,即 lane 上对该名称的引用数。class 是结论:当 lane 上没有对管辖页面的有效补丁时,为 seam_changed_without_record。这就是你那份过时的文档,在落地前被发现了。
在相信一份空报告之前,先读 pending:它列出 seam 的 glob 下已改动、但索引 "cannot answer yet"(还无法回答)的文件,而 "the report is complete when pending is empty."(pending 为空时报告才完整。)处于冲突中的 lane 会被拒绝,直到冲突解决。
第 5 步:在同一条 lane 上更新管辖页面
用 pages.apply_patch 和同一个 lane 编辑 architecture/billing,这样页面和代码一起等待。把一次代码修改和它的文档放进同一个 changeset 落地这篇指南讲了这一部分。
第 6 步:再读一遍报告,然后落地
再运行一次 symbols.drift。这条发现现在是 seam_changed_with_record,它的 record 显示 updated_on_lane。把报告和审阅放在一起:composition_hash 是它读取的 lane 组合的哈希,report_sha256 覆盖报告的规范文本,"so a report is bound to the exact change it read."(所以一份报告绑定在它读取的那次确切修改上。)之后的补丁会让两者都改变。然后把这条 lane 作为一个 changeset 落地。
因为报告只提建议,强制执行要由你来加。一个模式(是我们的,不是文档的):在受保护的 trunk 上,在 .landing-rules 里写上受管辖代码的 glob,把管辖页面的负责人设为审批人,并让这位审批人先读漂移报告。
文档没有回答的问题
- 谁可以写
.governed-seams。文档规定.landing-rules仅限管理员;对 seams 页面,只说它从 trunk 读取,"whoever wrote it"(无论是谁写的)。 - 应用中的视图。文档描述了工具和它的回答,没有描述在浏览器中显示报告的页面。
- Markdown "not parsed yet"(尚未解析),所以页面本身不能作为受管辖的一方。