拓冰建站拓冰建站
首页 / 资讯中心 / 正文

ZCode 最小受管理模块(Golden Module)契约规范:manifest + 窄端口 + 示例驱动的架构治理实战

【免费下载链接】ZCodeZ.ais coding agent harness. Powerful, intelligent, extensible.项目地址https://gitcode.com/gh_mirrors/zco/ZCode点击查看免费下载本指南以 ZCode 仓库中架构治理技能architecture-governance skill所附的最小受管理模块示例——golden-module 为核心系统讲解一个受架构策略管理的模块应由哪些文件组成、每个文件承担什么职责以及它们如何与仓库根目录的architecture-policy.yaml、可执行策略检查器和 Agent 工作流协同。读完本文你将掌握在 ZCode 中新增或迁移一个受管理模块所需的全部实操步骤module.ts / contract.ts / contract.example.ts / CONTRACT.md 四件套的编写规范并能通过pnpm architecture:check与基线机制验证模块边界是否合规。一、Golden module 是什么架构治理中的“最小受管理模块”在 ZCode 的架构治理体系中golden-module是一个fixture样例夹具它演示了“受管理模块managed module”的最小形态。其说明文档 CONTRACT.md 给出的定义只有一句话却精确概括了全部约束This fixture demonstrates the smallest managed module: a manifest, a narrow port, an example, and no implementation details in the public surface.翻译过来即最小的受管理模块 一个 manifest模块清单 一个窄端口narrow port 一个示例example并且公开表面上不能有任何实现细节。这句话可以拆解为四个可落地的文件它们共同构成模块的“公开契约面”文件角色在本 fixture 中的内容module.ts模块清单manifest声明模块身份、依赖与公开入口声明id: golden、requires: []、provides: [golden-port]、publicEntrypoints: [contract.ts]contract.ts窄端口narrow port模块唯一允许被外部导入的类型契约仅一个GoldenPort接口内含一个ping(): Promiseok方法contract.example.ts示例演示调用方如何通过端口消费能力一个useGolden(port)函数仅依赖contract.ts中的类型CONTRACT.md契约文档记录类型系统无法表达的不变量即本文围绕的这段简短说明整个 fixture 位于 .agents/skills/architecture-governance/references/golden-module/而它背后的完整设计原则记录在同目录的 module-contract.md 中。该文档明确指出A managed module exposes only its contract entrypoint. The contract contains branded identifiers, schemas, typed commands, events, errors, and the semantics required by callers.也就是说受管理模块的契约入口应当包含品牌化标识branded identifiers、数据模式schemas、类型化命令typed commands、事件events、错误类型errors以及调用方所需的行为语义。二、module.ts声明“我是谁、依赖谁、公开什么”golden-module的 manifest 文件 module.ts 全文如下export const goldenModule { id: golden, requires: [], provides: [golden-port], publicEntrypoints: [contract.ts], } as const;四个字段各有明确职责id模块唯一标识须与 architecture-policy.yaml 中modules[].id保持一致requires本模块依赖的其他模块 ID 列表。此处为空数组表示 golden 模块零依赖——这是最小模块的理想状态provides本模块对外提供的能力名这里是golden-port用于表达“我提供什么”publicEntrypoints公开入口文件列表。只有列在这里的文件才允许被其他模块跨模块导入这是deep-import规则的判定依据。从策略模式的描述见 policy-schema.md可知受管理模块在architecture-policy.yaml中还会声明roots、layers、layerOrder、owner等字段而本地module.ts声明的依赖必须与策略文件保持一致——“A managed modulesmodule.tsdeclares local dependencies; keep it consistent with the policy”。当两者冲突时检查器以 manifest 中的requires为准见下文第八节。三、contract.ts窄端口越小越合规contract.ts 是整个模块唯一允许外部触碰的文件export interface GoldenPort { ping(): Promiseok; }这个接口体现了“窄端口”的全部要点公开面极窄只暴露一个方法、一个返回类型没有任何实现类型即文档返回类型直接是字面量ok调用方无需阅读实现即可明确语义不泄漏实现细节没有 import 任何 IO、存储或运行时 API。“窄”在 ZCode 中不仅是设计倡导还有硬性数值约束。architecture-policy.yaml的全局阈值给出global: maxFileLines: 400 maxContractLines: 300 maxPublicMethods: 12 forbidCycles: true forbidDeepImports: true managedOnly: truemaxContractLines300 行任何以contract.开头的文件超过该行数即触发max-contract-lines违规——契约太宽泛时策略建议“拆分能力或缩减公开面”见 rule-catalog.mdmaxPublicMethods12 个contract.ts中公开方法数超过 12 即触发max-public-methods建议“拆分能力或引入更窄的读/写契约”maxFileLines400 行约束整个受管理模块的单文件体量。在 scripts/architecture/index.mjs 中可以看到这三个阈值的实际执行逻辑path.basename(file).startsWith(contract.)的文件会被检查行数名为contract.ts的文件会被countPublicMethods统计公开方法。golden 模块的端口只有 1 个方法、2 行代码远低于所有阈值是“如何通过检查”的正面教材。四、contract.example.ts让调用方学会“用端口”contract.example.ts 演示了消费端的正确写法import type { GoldenPort } from ./contract.js; export async function useGolden(port: GoldenPort): Promiseok { return port.ping(); }这个文件的作用不是实现功能而是展示契约如何被调用它只import type契约类型运行时不产生任何依赖它把GoldenPort作为参数注入而非自行实例化——这正是“domain 纯、IO 在 adapter、消费方只依赖端口”分层思想的缩影它本身也是模块公开面的一部分却依然不含实现细节。为什么示例是硬性要求根据 SKILL.md 的指引“For a new managed module, providemodule.ts,contract.ts,contract.example.ts, and a shortCONTRACT.md”——即新模块必须提供这四件套。同时 module-contract.md 说明“The example is part of the agent context package”示例属于 Agent 上下文包的一部分让编码 Agent 不必读完整实现就能理解契约语义。五、CONTRACT.md记录类型表达不了的不变量原文档虽然只有一句话但它承担着不可替代的职责记录类型系统无法表达的不变量。module-contract.md 中的原话是The shortCONTRACT.mdrecords invariants that types cannot express.类型只能约束“形状”接口签名、字段类型却无法表达行为性约束例如该端口是同步语义还是流式语义调用方的重试边界、幂等键、陈旧结果规则该能力的所有权归属、允许的消费方范围桌面端 continuous 与移动端 replayable 的投递语义差异见下文第九节的决策记录。这些语义正是 ai-guidance.md 中要求 Agent 在写代码前回答的“Time / Remote / Contract”类问题。golden-module 的 CONTRACT.md 用一句极简的话点明“公开面无实现细节”作为 fixture 的契约文档恰到好处——文档要短短到只记录类型之外的关键不变量。六、分层原则domain 纯、app 编排、adapters 执行 IO、ui 消费端口模块契约之所以必须“窄”是因为它服务于严格的四层架构。 module-contract.md 给出明确分工domainstays pure,appowns use-case orchestration,adaptersowns IO and process boundaries, anduiconsumes the module port/read model.domain领域层保持纯净不含任何 IO、进程、网络、定时器依赖判断速记“需要await世界上的东西吗需要就不是 domain”app应用层负责用例编排通过端口port决定副作用adapters适配层负责实际执行 IO 与进程边界判断速记“知道自己底层是 sqlite / MessagePort / 定时器那就是 adapters”ui界面层只消费本模块contract.ts暴露的端口/读模型。这一分层由两条可执行规则强制详见 rule-catalog.mdlayer-direction某层导入了更高实现层即违规正确做法是“依赖更低层端口或移动集成所有权”domain-iodomain 代码 import 了node:、fs、path、http、net、child_process、timers等模块或直接调用fetch、setTimeout、setInterval即违规执行逻辑见 scripts/architecture/index.mjs 与 scripts/architecture/index.mjsui-implementation-importui 层文件直接 import 路径中含repo、runtime、service(s)的实现即违规见 scripts/architecture/index.mjs。golden-module 虽然只有端口与示例其contract.example.ts却正是“消费方只依赖端口”这一规则的示范useGolden不知道也不关心ping的实现是谁、跑在什么 IO 之上。七、在 architecture-policy.yaml 中注册真实模块以 storage 为例fixture 是理论的“最小模型”而architecture-policy.yaml中已有一个真实受管理模块storage可作为对照实例- id: storage roots: [packages/services/src/storage] managed: true requires: [shared, rpc, services] publicEntrypoints: [packages/services/src/storage/contract.ts] layers: { domain: domain, app: app, adapters: adapters } layerOrder: [domain, app, adapters] owner: desktop-settings对照 golden-module 的 manifest可以清晰看到二者的一致性id、requires、publicEntrypoints是策略与本地 manifest 的公共字段真实模块额外声明了roots模块源码根、layerslayerOrder分层及方向与owner状态所有权归属。全局关键项速查来自 policy-schema.md全局键含义maxFileLines受管理源文件行数上限400maxContractLines契约文件行数上限300maxPublicMethods契约公开方法数上限12forbidCycles禁止受管理依赖图出现环forbidDeepImports禁止绕过模块公开入口的深导入managedOnly检查范围仅限受管理模块策略文件还支持exceptions带expires过期时间的例外过期的例外会被expired-exception规则标记见 scripts/architecture/index.mjs。注意分层名与顺序以各模块自身配置为准不存在全局统一的层列表——不要把 storage 的layerOrder当成所有模块的默认值。八、规则目录与检查器守护 golden module 的可执行机制与 golden-module 直接相关的规则完整目录见 rule-catalog.md规则含义典型修复module-dependency跨模块导入未在requires中声明增加公开契约或移交集成所有权deep-import导入绕过了模块公开入口改为导入契约/index 入口cycle受管理依赖图存在环拆分所有者或通过端口反转依赖max-contract-lines契约过宽拆分能力或缩减公开面max-public-methods契约方法过多拆分能力或引入更窄读写契约missing-module-artifact受管理模块缺少 manifest 或契约 fixture补齐契约、示例、测试与 CONTRACT.mdlayer-direction/domain-io/ui-implementation-import分层与 IO 边界被破坏见第六节expired-exception/disable-count例外过期 / 出现 lint 抑制解决根因不静默延期其中missing-module-artifact与 golden-module 的关系最为直接检查器要求每个受管理模块至少存在module.ts和contract.ts两个工件见 scripts/architecture/index.mjs。而 SKILL.md 进一步要求四件套含contract.example.ts与CONTRACT.mdgolden-module 正是用来示范这四件套长什么样的。在检查器的实现中值得注意的机制还有基线baseline已有违规只能通过.architecture-baseline.json抑制检查结果会区分baselineViolations与newViolations新增违规始终是阻塞性的见 scripts/architecture/index.mjs变更范围--changed模式从HEAD差异与未跟踪文件出发并通过反向依赖图把受影响文件一并纳入扫描见 scripts/architecture/index.mjsviolation 指纹每条违规通过 sha256 指纹规则 文件 详情与基线比对确保基线匹配精确见 scripts/architecture/index.mjs。九、Agent 工作流从 SKILL.md 到 bounded context架构治理技能 SKILL.md 定位为“编码前的决策协议 门禁”——目标是让预期架构在生成代码前就显而易见让检查器去“确认决策”而非“事后发现”。完整流程为识别范围pnpm architecture:check --changed找出改动文件及其所属模块生成受控上下文pnpm architecture:context module-id底层为node .agents/skills/architecture-governance/scripts/context-package.mjs module-idcontext-package.mjs生成包含模块 manifest、契约文件、直接依赖契约与边界约束的上下文包避免把整份实现塞进提示词先写 spec 再写实现在 spec 中写明行为、所有权、不变量、失败语义与迁移边界做设计决策遵循“一个所有者 / 一条路径 / 显式边界 / 显式时间 / 受控上下文”五条原则跨模块变更先补契约、再写代码编辑后复查再次运行pnpm architecture:check --changed将新增违规与基线违规分开汇报。context-package.mjs的用法示例如下脚本会打印 用法 提示node .agents/skills/architecture-governance/scripts/context-package.mjs module-id [--output file]其输出结构由 scripts/architecture/index.mjs 中的generateContext生成包含owner、managed、requires、模块文件清单、直接依赖契约清单以及两条边界提示——跨模块导入必须使用已声明依赖与公开入口暴露新能力前先补契约示例。对于有状态变更SKILL.md 给出的速记草图是input → single owner → command admission → state transition → contract/event └── persistence / replay / projection are derived from the owner对于远程/流式变更需显式声明投递边界desktop: continuous ── direct live stream ──┐ ├─ same owner and sequence mobile: replayable ─ snapshot gap repair ┘最后ai-guidance.md 要求 patch 描述包含一段小型决策记录decision record其格式为owner: single state owner command path: entrypoint → owner derived views: what is projected and from where ordering/idempotency: sequence and duplicate handling delivery: desktop-continuous | web-remote-replayable | both contracts/spec/tests: bounded reading and validation set十、常见反模式与故障排查设计阶段应主动拒绝的形态出自 ai-guidance.mdUI 组件直接写持久化、运行时状态或第二条队列两个服务接受同一命令、或都声称拥有某状态字段新增缓存/事件总线/adapter/helper 却与既有路径重复domain 对象 import 文件系统、进程、网络、定时器或平台 API为了省去定义契约而做跨模块深导入远程流式变更混用桌面端continuous与移动端replayable语义未声明迁移边界的、波及无关模块的大规模重构。遇到检查失败时的排查要点详见 troubleshooting.mdmodule-dependency用公开契约或在确认所有权后同时在本地 manifest 与策略中声明依赖deep-import改走目标模块声明的公开入口cycle把共享类型移入契约或通过端口反转依赖missing-module-artifact按检查报告补齐 manifest、契约、示例或契约文档expired-exception解决底层违规后删除过期例外不要静默续期作用域提醒pnpm architecture:check --changed只覆盖HEAD差异与未跟踪文件审查已提交改动时请用全量pnpm architecture:check解析限制当前检查器基于相对导入解析依赖workspace 别名与动态导入需单独审查——检查通过不代表所有依赖都被分析过。结语golden-module 虽然只有四个小文件却是 ZCode 架构治理的“最小范式”module.ts声明身份与边界contract.ts收敛公开面contract.example.ts示范消费方式CONTRACT.md补足类型之外的语义。它同时回答了受管理模块的四个核心问题——谁拥有、依赖谁、公开什么、以何种语义被消费——并在 architecture-policy.yaml 与 scripts/architecture/index.mjs 中拥有完整的可执行约束支撑。新增或迁移模块时以 golden-module 为模板、以 storage 模块为真实参照、以pnpm architecture:check --changed为门禁即可把架构决策前置到编码之前让检查器确认决策而非发现意外。赞分享【免费下载链接】ZCodeZ.ais coding agent harness. Powerful, intelligent, extensible.项目地址https://gitcode.com/gh_mirrors/zco/ZCode点击查看免费下载相关推荐StarRocks BE 模块边界治理实战读懂 be/AGENTS.md 的架构契约与 Harness 工作流StarRocks BE 模块边界治理实战读懂 be/AGENTS.md 的架构契约与 Harness 工作流 StarRocks 的后端BackendB数据库OLAP数据仓库大数据湖仓一体数据分析OpenSandbox 公共 API 契约治理specs 目录规范、OpenAPI 接口契约与变更护栏解析OpenSandbox 公共 API 契约治理specs 目录规范、OpenAPI 接口契约与变更护栏解析 OpenSandbox 以 specs/ 目录作为人工智能AI 应用Agent 沙箱云原生后端代码智能体Formbricks v3 API 契约测试实战用 Schemathesis 驱动真实实例验证 OpenAPI 规范Formbricks v3 API 契约测试实战用 Schemathesis 驱动真实实例验证 OpenAPI 规范 Formbricks 的 v3 管理 A后端前端数据可视化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门