资讯动态

IronClaw 的 Cargo Features 治理:每个 Feature 都必须“挣得“自己的构建

发布时间:2026/9/23 2:32:27 来源:尧图企业网站定制
人工智能AI 应用交互助手AI Agent【免费下载链接】ironclawIronClaw is an Agent OS focused on privacy, security and extensibility项目地址https://gitcode.com/gh_mirrors/iro/ironclaw点击查看免费下载本文以 IronClaw 仓库的编码规范 .claude/rules/cargo-features.md 为核心主体结合仓库内各 crate 的真实Cargo.toml、CI 工作流与审计记录展开。你将掌握什么样的 feature 才有资格进入 IronClaw 的 workspace、2026-07 特性审计中 20 个 feature 被删除的具体失败模式、添加与删除 feature 时必须遵守的操作清单以及如何在 code review 中快速识别不该存在的 feature。这份治理规范面向任何以 Cargo workspace 形式组织的 Rust 项目IronClaw 用一次真实的大规模审计证明了它的必要性。核心哲学Feature 不是可选的借口而是工作区的第二次构建IronClaw 对 Cargo feature 的定位非常明确原文措辞是A Cargo feature is not a way to say this part is optional, this is still beta, or the substrate should work without this. Every one of those readings produced a feature this repo later deleted. A feature is asecond build of the workspacethat someone has to compile, lint, test, and keep working — forever.翻译过来即feature 不是表达这部分是可选的这还在 beta 期substrate 没有它也能工作的手段——这三种理解都在本仓库中产生过后来被删除的 feature。feature 意味着工作区多出一次构建而这次构建必须有人去编译、lint、测试并永远保持可用。这个定位决定了 IronClaw 对待 feature 的全部态度新增一个[features]条目不是记录意图而是在给整个团队增加一份长期维护负担。因此IronClaw 用一份准入门槛the bar来裁决每一个 feature 的生死。五大合法判据一个 feature 凭什么挣得构建权仓库规则规定新增[features]条目必须且只能命中以下五条判据之一重量级可选依赖heavy optional dependency——默认构建不应该编译它。例如bedrock三个 AWS SDK crate和clipboardarboardimage。判据的关键在于收益必须是你能点名的真实依赖而不是少写点代码这种模糊理由。真实交付的构建形态genuinely shipped build shape——仓库实际产出某种产物且该产物关闭这个 feature 构建。反过来说如果Dockerfile、reborn-release-compile.yml、scripts/ci/package-feature-flags.sh全都把它打开那它就不是一种构建形态而是产品本身。CI lane 选择器——只用于门控测试目标而非生产代码例如integration、replay、libsql-restart-tests。这类 feature 在生产 crate 代码中携带零#[cfg]。仅开发用的接缝dev-only seam——必须被排除在生产二进制之外。IronClaw 规定这类 feature 只允许有一个名字test-support。不允许叫testing、contract-tests、dev-in-memory-session等任何其他名字。类型系统无法表达的权限边界privilege boundary——例如host-auth-mint只有 host runtime 才能铸造经过验证的认证证据。这类 feature 很罕见且必须在 manifest 注释中显式声明这一理由。如果以上五条都不满足正确答案是运行时配置runtime configuration部署形态属于DeploymentConfig和[storage]不属于#[cfg]。IronClaw 的仓库结构profiles/ 下的local.toml、server.toml等正是这一原则的体现——不同部署形态通过配置文件和存储绑定表达而不是通过编译期开关。源码实证bedrock与test-support如何命中判据在 crates/domains/ironclaw_llm/Cargo.toml 中可以看到判据 1 与判据 4 的真实实现[features] bedrock [dep:aws-config, dep:aws-sdk-bedrockruntime, dep:aws-smithy-types] # Opt-in registry-provider factory for composition roots that already own # provider resolution and do not want v1 SessionManager plumbing. registry-provider-factory [] # Opt-in StubLlm credentials helpers for downstream test code. test-support []bedrock精确命中了判据 1它把三个 AWS SDK crate 全部声明为optional true见同文件 依赖区默认构建完全不会碰它们。test-support则命中判据 4其注释Opt-in StubLlm credentials helpers for downstream test code明确点出它只服务于下游测试代码。注意registry-provider-factory同样有注释说明其存在理由——这正是规则要求的manifest 注释要说明命中的判据。test-support在 workspace 中的传播方式也完全符合规则。在 crates/app/ironclaw_composition/Cargo.toml 中test-support将依赖各 crate 的同名 feature 统一聚合成一个接缝test-support [ ironclaw_network/test-support, ironclaw_extension_host/test-support, ironclaw_extension_manager/test-support, ironclaw_auth/test-support, ironclaw_host_runtime/test-support, ironclaw_loop_host/test-support, ironclaw_outbound/test-support, ironclaw_assistant/test-support, ironclaw_turn_runner/test-support, ]而根 workspace 的 Cargo.toml 中所有[dev-dependencies]通过features [test-support]把该接缝注入测试二进制例如ironclaw_host_api { ..., features [test-support] }、ironclaw_llm { ..., features [test-support] }。这正是dev-only seam 只进测试构建、不进 release 二进制的落地方式。源码实证memory-mem0的转发正确写法规则强调一个只转发到另一个 crate feature 的 feature应该放在依赖声明上而不是新建一个 feature 条目。IronClaw 中memory-mem0是一个例外但有正当理由的转发案例见 crates/app/ironclaw_cli/Cargo.toml[features] # Compile in the (off-by-default) mem0 third-party memory provider so an # ironclaw-reborn binary can point the compose-time [memory] binding at a # self-hosted mem0 OSS server. Mirrors the same feature on ironclaw_composition; # without it a default binary carries no mem0 code or its reqwest/rustls # transport and a mem0 binding fails closed. memory-mem0 [ ironclaw_composition/memory-mem0, ]它之所以合法是因为它是产品二进制入口CLI 包对下游 crate 特性的显式选择并且 off-by-default——默认二进制不携带 mem0 代码及其 reqwest/rustls 传输层。同文件的test-support注释则直接标注了判据编号Feature bar 4 (dev-only seam): compile the loopback-only OAuth provider endpoint constructor used by hermetic standalone E2E tests且明确release builds fail closed if the vars are present——这正是dev-only seam 被排除在生产二进制之外的强制保证。规则在对抗什么2026-07 特性审计的真实失败案例这份规则不是凭空制定的而是 IronClaw 在 2026-07 特性审计中的直接产物。那次审计在四个 commit 中删除了 20 个 feature 和约 1,100 个#[cfg]站点。规则原文承认The failure modes, all of which looked reasonable when introduced——所有失败模式在引入时看起来都合情合理。逐类复盘如下-beta/-v2后缀的影子产品776 个#[cfg]与 25 个死实现webui-v2-beta、slack-v2-host-beta、telegram-v2-host-beta、openai-compat-beta、webhook-serve这五个 feature 被删除。它们合计携带776 个#[cfg]站点和 25 个死掉的备选实现全部是为了保护一个从未交付过的构建。审计发现每一个实际产物都启用了所有这些 feature——-beta后缀早已名不副实这些功能就是产品本身。这正是判据 2 的逆命题当一个 feature 被所有交付产物无条件启用时它不是可选形态而是产品本体应当去掉开关、无条件编译。root-llm-provider把运行时状态拼成了编译期拼写root-llm-provider关闭后产出的二进制能启动但每个请求都会因 no LLM gateway wired 而失败。规则原文的评语一针见血That is a compile-time spelling of a runtime state——这本质是一个运行时状态未配置 LLM gateway却被错误地表达成了编译期开关。正确做法是让它在运行时配置中表达例如DeploymentConfig中的 LLM 绑定并用运行时错误在组合阶段失败而不是产出一个半残的二进制。投机性门控pr3180-ready、pr7-ready这两个 feature 是为从未落地的 PR准备的投机性开关零#[cfg]站点却在 manifest 里躺了两个月。它们不控制任何代码路径纯粹是占位符。这违反了判据 15 的全部精神没有真实依赖、没有真实构建形态、不门控测试、不是 dev seam、不是权限边界。幽灵转发libsql/postgres声明了却没人读ironclaw_resources已退役的 run-state crate与ironclaw_outbound上声明的libsql/postgresfeature被三个 crate 转发引用但从未被读取。后果是它们把libsql、deadpool-postgres、tokio-postgres拉进了根本用不到这些依赖的构建。这正是判据 1 的反面教材——可选依赖必须真的被条件性使用否则就是白付编译成本。别名与命名混乱full别名、六个 dev-seam 名字ironclaw包上的full是一个没有任何构建调用过的别名。而仅开发用的接缝这一概念在仓库里居然有六个名字——这正是规则强制统一为test-support一个名字的原因。命名统一不是风格洁癖它让package-feature-flags.sh之类的自动化工具和 reviewer 都能一眼识别 dev-only 接缝也让全局搜索test-support即可审计所有测试接缝。添加一个 feature 的硬性规则当新 feature 确认命中五大判据之一后还必须满足以下四条硬性规则规则一manifest 注释必须点名命中的判据# 反例只复述 feature 名字的注释 # slack-v2-host-beta — the Slack host beta # 正例点名判据与收益 # Feature bar 2 (shipped build shape): ... # Feature bar 1 (heavy optional dependency): pulls in aws-sdk-bedrockruntime ...规则原文A comment that only restates the feature name ... tells a reviewer nothing只复述 feature 名字的注释对 reviewer 毫无信息量。上述bedrock、test-support、memory-mem0的注释都是正例。规则二必须有关闭它的构建且 CI 必须证明如果唯一能关闭该 feature 的配置是裸的cargo test -p crate那你只是用额外步骤写了死代码。IronClaw 用 scripts/ci/package-feature-flags.sh 实现这一证明它为每个包显式指定 CI 构建用的 feature 组合例如ironclaw_assistant构建--features test-support、ironclaw_composition构建--features test-support,memory-mem0其余包走有default就启用default的 fallback 逻辑。而发布侧的 .github/workflows/reborn-release-compile.yml 中7 个目标平台的发布构建步骤是裸的cargo build --locked --profile dist --package ironclaw --bin ironclaw --target $TARGET其步骤摘要明确写着 Backend features: unconditional——发布产物不带任何 feature 开关从而在编译期证明所有可选形态都被真正排除在交付物之外。规则三禁止#[cfg(not(feature ...))]的解释性替代实现不允许为了解释这个 feature 缺失而添加一个报错、返回 stub、或返回None的备选实现。这是审计中删除最多的形态。正确的做法是在组合阶段以运行时错误失败fail at composition with a runtime error。IronClaw 的memory-mem0注释中a mem0 binding fails closedmem0 绑定在未启用时失败关闭正是这一原则的体现——不提供假的空实现而是让缺失在运行时被明确暴露。规则四转发 feature 放在依赖声明上禁止用 feature 消音 lint只转发到另一个 crate feature的 feature 应该写成foo { path …, features [bar] }而不是新建一个[features]条目。根 Cargo.toml 中大量features [test-support]的写法正是这种依赖级转发的标准形态。永远不要用 feature 让 lint 消失。#[cfg_attr(not(feature x), allow(dead_code))]意味着该项在某个构建里是死的——应该修复构建形态而不是消音它。根 Cargo.toml 中dead_code、unreachable_pub、unused_must_use等 workspace lint 的设置表明IronClaw 宁可直面死代码问题也不允许用 feature 掩盖。修改或删除一个 feature 的完整清单三腿验证--all-features看不见 feature-gated 死代码规则原文点出了一个极易踩坑的 CI 盲区Feature-gated dead code does not show up under--all-features.一个只能被#[cfg(feature x)]调用者触达的辅助函数开了 feature 是活的不开就是-D warnings编译错误。而 PR CI 只跑精简的all-featureslane所以这一类问题能在 PR 全绿的情况下弄坏main。因此规则要求在添加、移动或删除任何 gate 时必须在本地跑齐三条腿——详见 .claude/rules/testing.md 的 Validation 一节即分别以默认 features关闭该 feature--all-features三种方式构建/测试而不是只依赖 CI 的单一 lane。删除一个 feature 远不止删#[cfg]行规则给出了删除 feature 时的完整检查清单任何一项遗漏都会留下死代码或错误构建#[cfg(not(...))]备选实现直接删除——它们是死备选dead alternates。因 feature 变成强制的 optional dependencies从optional true改为普通依赖。所有依赖 manifest 中的转发条目逐 crate 清理features [...]引用。[[test]]/[[bin]]目标上的required-features同步移除。.github/workflows/中的 feature 引用例如reborn-release-compile.yml、reborn-tests.yml等。Dockerfile*检查构建参数中是否引用了该 feature。scripts/ci/package-feature-flags.sh及其自测删除对应 recipe 分支。docs/internal/plans/composition-pubuse.snapshot当公共门面public facade变化时同步更新。持久化字符串不是 feature 引用规则特别警告嵌在持久化 secret-store 键前缀里的 feature 名不是 feature 引用。如果一个门控持久化键的 feature 被重命名全局查找替换会破坏已存在的数据库行。因此在重命名任何门控持久化键的 feature 之前必须先检查是否存在这类持久化字符串。代码评审速查Review flags.claude/rules/cargo-features.md为 reviewer 提供了可直接套用的红旗清单任何一条命中都应打回新增[features]条目其 manifest 注释没有点名命中哪条判据。新增#[cfg(not(feature ...))]块内含 stub、bail!或点名该 feature 的错误字符串——即解释性替代实现。dev-only 接缝的 feature 名字不是test-support叫testing、contract-tests等一律否决。带-beta/-preview/-v2后缀、且被所有交付产物启用的 feature——它就是产品开关应当删除。以让 substrate 在没有 X 的情况下也能构建为由添加 feature但实际上没有任何构建真的在没有 X 的情况下构建。给其他 Rust workspace 的实践启示IronClaw 的这份规则的价值在于可迁移性把feature 第二次构建写进团队共识——每一次[features]新增都是对编译矩阵的永久扩容而不是一次无成本的声明。用关闭它的构建 CI 证明作为准入门槛——无法证明 off 形态存在的 feature就是死代码。用唯一命名收敛 dev-only 接缝——test-support一个名字让自动化与人工审计都有唯一入口。用真实审计清理存量——IronClaw 通过一次 20 feature / 1,100#[cfg]的删除证明了看起来合理的 feature 会如何积累成维护负担任何长期项目都值得做一次同样的存量审计并让本次删除的失败模式beta 影子产品、运行时状态的编译期拼写、投机门控、幽灵转发、别名冗余成为后续 review 的对照表。延伸阅读本规则是 IronClaw .claude/rules/ 规范体系的一部分与其配套的 .claude/rules/testing.md测试分层与验证、.claude/rules/architecture.md依赖与组合边界共同构成了仓库的工程质量护栏根 Cargo.toml 中的[features]、[[test]]目标与 scripts/ci/package-feature-flags.sh 是本文所有原则的活体示例。赞分享人工智能AI 应用交互助手AI Agent【免费下载链接】ironclawIronClaw is an Agent OS focused on privacy, security and extensibility项目地址https://gitcode.com/gh_mirrors/iro/ironclaw点击查看免费下载相关推荐为什么每个Python开发者都必须掌握certifi库5个关键理由为什么每个Python开发者都必须掌握certifi库5个关键理由 在当今的网络编程中SSL证书验证是确保数据安全传输的基石。Python开发者经常会遇到S网络安全Frappe Island 架构决策实录为什么每个 App 必须自带完整的 Island 构建产物Frappe Island 架构决策实录为什么每个 App 必须自带完整的 Island 构建产物 Frappe 的 Desk 岛式架构Island Arc后端Web框架低代码前端认证鉴权sleek终极跨平台todo.txt管理器10个高效生产力技巧sleek终极跨平台todo.txt管理器10个高效生产力技巧 sleek是一款免费开源的跨平台todo.txt管理器支持Linux、Windows和ma桌面应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价