diff --git a/AGENTS-CN.md b/AGENTS-CN.md index b0ba9d19b9..3bf286f4fc 100644 --- a/AGENTS-CN.md +++ b/AGENTS-CN.md @@ -12,7 +12,7 @@ BitFun 是一个由 Rust workspace 与 React 前端组成的项目。 2. 日常开发使用下方主要产品循环;surface 专属的替代命令由最近的应用指南维护。 3. 修改 Rust 文件后,优先使用 `pnpm run fmt:rs`,只格式化已改动或已暂存的 `.rs` 文件。只有在你明确需要更大范围格式化时才使用 `cargo fmt`。 4. 改完后从离改动最近的 `AGENTS.md` 选择 focused 验证命令;下方仓库级验证章节只维护跨模块检查原则。 -5. Rust workspace 依赖应在根清单中统一版本,而由消费 crate 按自身职责声明所需 feature;仅测试所需的 feature 应放入 `dev-dependencies`,受 crate feature 控制的服务能力应只在对应 feature 中启用。禁止使用 `tokio/full` 绕过依赖边界设计。 +5. Rust workspace 依赖应在根清单中统一版本,而由消费 crate 按自身职责声明所需 feature;仅测试所需的 feature 应放入 `dev-dependencies`,受 crate feature 控制的服务能力应只在对应 feature 中启用。第三方依赖的默认 feature 若不是所有 consumer 的稳定契约,应在 `[workspace.dependencies]` 统一关闭,成员只增加自身需要的切片。仓内 crate 的 `default` 已由边界契约保证为空时,不在每条依赖边重复写 `default-features = false`;ACP 这类有意保留兼容默认的 crate 仍由窄 consumer 显式关闭。被单独复制到 Docker 构建上下文的 manifest 无法继承 workspace 根,必须继续维护显式版本和默认策略。禁止使用 `tokio/full` 绕过依赖边界设计。 ## 分层模块索引 diff --git a/AGENTS.md b/AGENTS.md index 00781ad2f3..0fb6666158 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,8 +18,15 @@ Repository rule: **keep product logic platform-agnostic, then expose it through 5. Workspace Rust dependencies own compatible versions, not broad capability unions. Each crate must select the dependency features it actually uses; keep test-only features in dev-dependencies and attach feature-gated service - capabilities to the owning crate feature. `tokio/full` is forbidden in the - root workspace and workspace members. + capabilities to the owning crate feature. Disable third-party defaults in + `[workspace.dependencies]` when they are not part of every consumer's + contract; members inherit that policy and add only their needed slices. For + internal crates whose guarded `default` is empty, do not repeat + `default-features = false` on every edge. Narrow consumers of an intentional + compatibility default, such as ACP, must still disable it explicitly. + Manifests copied into a standalone Docker build context must keep explicit + versions and default policy because they cannot inherit the workspace root. + `tokio/full` is forbidden in the root workspace and workspace members. ## Layered Module Index diff --git a/Cargo.lock b/Cargo.lock index 4fce6abf53..b927be029d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3990,15 +3990,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "getopts" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" -dependencies = [ - "unicode-width 0.2.0", -] - [[package]] name = "getrandom" version = "0.2.17" @@ -6325,26 +6316,9 @@ checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.11.1", "block2 0.6.2", - "libc", "objc2 0.6.4", - "objc2-cloud-kit", - "objc2-core-data", "objc2-core-foundation", "objc2-core-graphics", - "objc2-core-image", - "objc2-core-text", - "objc2-core-video", - "objc2-foundation", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-av-foundation" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478ae33fcac9df0a18db8302387c666b8ef08a3e2d62b510ca4fc278a384b6c0" -dependencies = [ - "objc2 0.6.4", "objc2-foundation", ] @@ -6359,35 +6333,12 @@ dependencies = [ "objc2-foundation", ] -[[package]] -name = "objc2-core-audio" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" -dependencies = [ - "dispatch2", - "objc2 0.6.4", - "objc2-core-audio-types", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-core-audio-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" -dependencies = [ - "bitflags 2.11.1", - "objc2 0.6.4", -] - [[package]] name = "objc2-core-data" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.11.1", "objc2 0.6.4", "objc2-foundation", ] @@ -6438,31 +6389,6 @@ dependencies = [ "objc2-foundation", ] -[[package]] -name = "objc2-core-media" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ec576860167a15dd9fce7fbee7512beb4e31f532159d3482d1f9c6caedf31d" -dependencies = [ - "bitflags 2.11.1", - "dispatch2", - "objc2 0.6.4", - "objc2-core-audio", - "objc2-core-audio-types", - "objc2-core-foundation", - "objc2-core-video", -] - -[[package]] -name = "objc2-core-ml" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201b055e6acfa0f9f15568255d3f03ce2b54bc86d1814442dc69138e36813e18" -dependencies = [ - "objc2 0.6.4", - "objc2-foundation", -] - [[package]] name = "objc2-core-text" version = "0.3.2" @@ -6475,19 +6401,6 @@ dependencies = [ "objc2-core-graphics", ] -[[package]] -name = "objc2-core-video" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" -dependencies = [ - "bitflags 2.11.1", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-io-surface", -] - [[package]] name = "objc2-encode" version = "4.1.0" @@ -6516,17 +6429,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "objc2-image-io" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b0446e98cf4a784cc7a0177715ff317eeaa8463841c616cfc78aa4f953c4ea" -dependencies = [ - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-core-graphics", -] - [[package]] name = "objc2-io-kit" version = "0.3.2" @@ -6552,16 +6454,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "objc2-javascript-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" -dependencies = [ - "objc2 0.6.4", - "objc2-core-foundation", -] - [[package]] name = "objc2-osa-kit" version = "0.3.2" @@ -6586,17 +6478,6 @@ dependencies = [ "objc2-foundation", ] -[[package]] -name = "objc2-security" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" -dependencies = [ - "bitflags 2.11.1", - "objc2 0.6.4", - "objc2-core-foundation", -] - [[package]] name = "objc2-ui-kit" version = "0.3.2" @@ -6634,17 +6515,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfc194758a2d5d7540b1ad283bfb9ca318ec608991892326e95b428230b2689b" dependencies = [ - "block2 0.6.2", "objc2 0.6.4", - "objc2-av-foundation", "objc2-core-foundation", - "objc2-core-graphics", - "objc2-core-image", - "objc2-core-media", - "objc2-core-ml", - "objc2-core-video", "objc2-foundation", - "objc2-image-io", ] [[package]] @@ -6659,8 +6532,6 @@ dependencies = [ "objc2-app-kit", "objc2-core-foundation", "objc2-foundation", - "objc2-javascript-core", - "objc2-security", ] [[package]] @@ -7851,18 +7722,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" dependencies = [ "bitflags 2.11.1", - "getopts", "memchr", - "pulldown-cmark-escape", "unicase", ] -[[package]] -name = "pulldown-cmark-escape" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" - [[package]] name = "pulp" version = "0.22.3" diff --git a/Cargo.toml b/Cargo.toml index bc9983d5b7..7e16b968da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,10 +79,10 @@ undocumented_unsafe_blocks = "warn" [workspace.dependencies] # Async runtime tokio = { version = "1.52", default-features = false } -tokio-stream = "0.1.18" +tokio-stream = { version = "0.1.18", default-features = false } tokio-util = "0.7.18" async-trait = "0.1.89" -futures = "0.3.31" +futures = { version = "0.3.31", default-features = false, features = ["std"] } futures-util = "0.3.31" # Serialization @@ -102,12 +102,12 @@ thiserror = "2" # Logging log = "0.4" -tracing = "0.1" +tracing = { version = "0.1", default-features = false, features = ["std"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] } # Utilities uuid = { version = "1.0", features = ["v4", "serde"] } -chrono = { version = "0.4", features = ["serde", "clock"] } +chrono = { version = "0.4", default-features = false, features = ["serde", "clock", "std"] } chrono-tz = "0.10.4" cron = "0.15.0" # Tauri 2.9.2 utilities conflict with time 0.3.48 on current stable Rust. @@ -171,7 +171,7 @@ clap = { version = "4.6.1", features = ["derive"] } crossterm = "0.28" ratatui = "0.29" unicode-width = "0.2" -pulldown-cmark = "0.11" +pulldown-cmark = { version = "0.11", default-features = false } syntect = { version = "5", default-features = false, features = ["default-syntaxes", "default-themes", "regex-onig"] } once_cell = "1" libc = "0.2" @@ -194,7 +194,7 @@ similar = "2.5" urlencoding = "2.1" oxc = { version = "0.138.0", default-features = false, features = ["ast_visit", "codegen", "semantic", "transformer"] } oxc-parse = { package = "oxc", version = "0.138.0", default-features = false } -rquickjs = { version = "0.9", default-features = false, features = ["classes", "properties", "macro"] } +sqlx = { version = "0.8", default-features = false } # Tauri (desktop only) tauri = { version = "2.11", features = ["unstable", "macos-private-api", "tray-icon"] } @@ -222,10 +222,10 @@ foreign-types = "0.5" dispatch = "0.2" block2 = "0.6" objc2 = "0.6" -objc2-foundation = "0.3" -objc2-app-kit = "0.3" -objc2-vision = { version = "0.3.2", features = ["VNRecognizeTextRequest", "VNRequest", "VNObservation", "VNRequestHandler", "VNUtils", "VNTypes", "objc2-core-foundation"] } -objc2-web-kit = { version = "0.3", features = ["WKWebView", "WKSnapshotConfiguration", "WKPDFConfiguration", "block2", "objc2-app-kit"] } +objc2-foundation = { version = "0.3", default-features = false } +objc2-app-kit = { version = "0.3", default-features = false } +objc2-vision = { version = "0.3.2", default-features = false } +objc2-web-kit = { version = "0.3", default-features = false } tempfile = "3" webview2-com = "0.38" windows = "0.61" @@ -255,7 +255,7 @@ local-ip-address = "0.6" hostname = "0.4" # QR code generation -qrcode = "0.14" +qrcode = { version = "0.14", default-features = false } # WebSocket client tokio-tungstenite = { version = "0.29", features = ["rustls-tls-native-roots"] } diff --git a/docs/architecture/rust-build-dependency-boundaries.md b/docs/architecture/rust-build-dependency-boundaries.md index b815918605..c55326667f 100644 --- a/docs/architecture/rust-build-dependency-boundaries.md +++ b/docs/architecture/rust-build-dependency-boundaries.md @@ -47,10 +47,9 @@ Cargo 会统一同一 package 在依赖图中的 feature;workspace dependency ### 3.2 产品入口显式选择 Core 能力 -`src/apps/*`、`src/crates/interfaces/*` 和 installer app 直接依赖 `bitfun-core` 时必须同时: - -1. 设置 `default-features = false`; -2. 声明非空 `features` 列表。 +`src/apps/*`、`src/crates/interfaces/*` 和 installer app 直接依赖 `bitfun-core` 时必须声明非空 +`features` 列表。Core 的 `default` 由 Core 自身和边界检查保证为空,因此仓内 consumer 不重复声明 +`default-features = false`;能力边界仍由 consumer 的显式 feature 集合决定。 入口应选择真实需要的 owner feature;`product-full` 只能描述确实需要完整产品装配的兼容入口,不能作为尚未完成 feature/owner 分解时的占位解法。缩小某个产品的 capability 集合时必须从实际 construction/command path 反推,并保留行为等价或明确 unsupported-state 测试。 @@ -83,6 +82,11 @@ Plugin Source 和完整 domain feature 集合一起带回 Agent Runtime。产品 ### 3.3 Workspace dependency 只提供共同底座 - workspace 声明负责版本和真正跨产品共享的最小 feature; +- 第三方依赖的默认 feature 若不是每个 consumer 的稳定契约,在 workspace 声明统一关闭;成员继承该策略, + 只增加自身实际使用的 feature,不在各 manifest 重复 `default-features = false`; +- 仓内 crate 的空默认值由被依赖 crate 拥有并由边界检查锁定,consumer 不重复关闭;只有 ACP 这类有意保留 + 非空兼容默认的 crate,窄 consumer 才必须显式关闭默认值并选择角色; +- 被 Docker 等独立构建上下文单独复制的 manifest 无法继承 workspace 根,继续显式声明版本与默认策略; - runtime、HTTP、TLS、crypto、codec 等产品特定 feature 留给实际 app/service/adapter owner; - `full` feature 只有在所有真实消费者都需要且更窄集合不能稳定维护时才允许; - target-specific dependency 放在最接近平台实现的 owner,不因单一平台需求污染跨平台 crate; @@ -103,8 +107,8 @@ Plugin Source 和完整 domain feature 集合一起带回 Agent Runtime。产品 或复制公共类型。feature 关闭时 API 不可见是明确的编译期契约变化;feature 开启后必须保留原公开路径、序列化 形状和错误语义。 -- contract crate 的 `default` 保持空,consumer 的每条 normal/dev/build/target dependency edge 都显式关闭 - default features,并只选择实际消费的切片; +- contract crate 的 `default` 保持空并由目标 crate 的边界契约看护;consumer 继承该空默认值,只选择实际 + 消费的切片,不在每条 normal/dev/build/target dependency edge 重复关闭 default features; - feature 名描述稳定能力,例如 Agent API、workspace/terminal/remote/Git port、协议 bridge 或 Computer Use contract,不描述某个临时调用方、PR 或测试; - 不提供 `full`、`service-ports`、`all-contracts` 等重新合并全部表面的 umbrella。只有多个 owner 共同消费且 diff --git a/docs/performance/01-compile-performance.md b/docs/performance/01-compile-performance.md index e552d84a53..a8037a5939 100644 --- a/docs/performance/01-compile-performance.md +++ b/docs/performance/01-compile-performance.md @@ -1,8 +1,8 @@ # BitFun 编译与依赖治理计划 -> 最近核实:2026-08-12 +> 最近核实:2026-08-13 > -> 实现复核基线:`gcwing/main@a4e06cae3` +> 实现复核基线:`gcwing/main@a4d944e5b` > > 性能 A/B 基线:`gcwing/main@1f538b96d` > @@ -23,6 +23,7 @@ | Core 默认值不再代表完整产品 | Core library 的默认 feature 集合为空,能力内部实现依赖回到实际 owner;最新三平台 feature-free 闭包继续减少 30/31/31 个 package instance | | ACP 按实际宿主拆分角色 | 兼容默认值仍为 client + server;Desktop 只选择 client,CLI 选择两者。Desktop 独立构建不再编译 ACP 的 4,211 行 server/runtime 源码,产品协议与远程行为不变 | | 完整产品行为保持 | `product-full` 显式组合全部 capability owner;Core 自身不再携带 Desktop host transport而减少 1 个 package,Desktop 闭包不变。CLI 显式保留原先实际生效的 Oniguruma 高亮后端,ACP 默认组合保持原能力 | +| 默认 feature 责任已集中 | 仓内空默认由被依赖 crate 和边界检查负责;workspace member 的 `default-features = false` 从 70 处降到 6 处,仅保留 ACP 两个窄 consumer 与 Relay 独立 Docker 上下文的 4 处必要声明。第三方默认策略尽可能回到 workspace 根,根 lock 只删除 11 个 package、无新增 | | Installer 删除未使用的直接能力 | 独立 manifest 的直接 dependency 从 18 降到 10,Windows normal/build 闭包减少 6;不把 Installer 并入根 workspace,本 PR 按要求不提交其生成 lockfile | | focused test 仍保持精确 | 同 owner、feature、平台和进程语义的源文件进入分组 target;使用 `--test ::` 运行单模块 | @@ -243,7 +244,7 @@ workspace 读取由 `workspace-text-runtime` 选择,诊断日志脱敏与本 已全部迁移,完整产品的运行时事件、翻译和服务行为不变,但这些源码迁移不能描述为对未知外部 consumer 零影响。 -根 lock package 仍为 1169,新增、升级、降级 package 均为 0。由于 Core 删除本地 +该轮结束时根 lock package 为 1169,新增、升级、降级 package 均为 0。由于 Core 删除本地 `bitfun-transport` 直接边,`Cargo.lock` 的 Core dependency record 同步删除这一行;这是依赖边 收敛,不是 package 集合增长,也不通过保留无 owner 的 optional dependency 伪造字节不变。 @@ -279,6 +280,34 @@ wire shape 与行为不变。 Runtime Ports 的 owner-specific integration targets 保持彼此独立,避免为了减少 executable 数重新制造 feature union。 +以下以 `gcwing/main@a4d944e5b` 为变更前基线,统一默认 feature 的责任位置。该主线相对前次测量 +没有 Cargo 输入变化;统计继续使用同样三个 +target triple 和 `normal,build` 版本化 package instance 去重口径;它只描述编译图,不直接代表墙钟时间: + +| 闭包 | Windows | macOS | Linux | 结果 | +|---|---:|---:|---:|---| +| Core feature-free | 63 → 63 | 51 → 51 | 50 → 50 | 空默认与显式 owner feature 不变;只删除 consumer 侧冗余开关 | +| Core `product-full` | 569 → 569 | 556 → 556 | 600 → 600 | 完整产品 owner 集合与运行能力不变 | +| CLI | 642 → 640 | 641 → 639 | 664 → 662 | Markdown 只使用 parser,退出未消费的 `getopts` 与 HTML renderer | +| Desktop | 790 → 790 | 805 → 793 | 887 → 887 | BitFun 的 macOS Objective-C 直接依赖边按实际 imports 选择 feature;Tauri/wry 等第三方仍合并自身所需 feature | +| Relay Service | 190 → 190 | 193 → 193 | 192 → 192 | 独立 Docker manifest 保持显式版本与默认策略,闭包不变 | +| Services Integrations feature-free | 26 → 26 | 28 → 28 | 27 → 27 | Qrcode 的 PNG/SVG 能力仍由 `remote-connect` owner 显式选择 | + +workspace member 中显式 `default-features = false` 从 70 处降到 6 处:62 个仓内空默认重复声明删除, +MiniApp/Skin Market 的 2 个 SQLx 声明改为继承 workspace 根策略。剩余 6 处中,两处是 Desktop/CLI 对 ACP +的必要例外,因为 ACP 有意保留 `client + server` 兼容默认,而两个产品入口必须分别选择 client-only 和 +双角色;另 4 处属于 Relay Server、Relay Service 和 Page Function Runtime,它们会被 Docker 单独复制、 +无法继承 workspace 根,因此继续显式声明 Tokio、SQLx 与 RquickJS 的默认策略。 + +第三方默认收敛只处理有源码与构建证据的依赖:Futures 保留 `std`,Tracing 保留 `std`,Chrono 保留 +`serde + clock + std`;Tokio Stream 的真实 consumer 只使用 feature-free 的 Receiver/iter wrappers; +Remote Connect 显式选择 qrcode 的 `image + svg`;Pulldown-Cmark 不启用 CLI 未使用的命令行/HTML renderer; +BitFun 的 macOS Objective-C binding 直接依赖边只选择源码导入的类型和所需 `std`;Cargo 的最终 +feature union 仍包含 Tauri、wry、notification、updater 等第三方路径的需求。根 `Cargo.lock` 从 1169 +降到 1158,新增 package 为 0;删除项仅来自 +Pulldown-Cmark 的 `getopts`/HTML escape 子图和未使用的 Objective-C framework binding。未关闭 Axum、Tauri、 +Clap、Tracing Subscriber、Notify 等默认即产品契约或缺少独立收益证据的依赖。 + | 状态 | 范围 | 处理结论 | |---|---|---| | 已稳定 | 根 `Cargo.lock`、Reqwest Rustls 单栈、workspace Tokio 最小基线 | 不重复治理 | diff --git a/scripts/check-core-boundaries.test.mjs b/scripts/check-core-boundaries.test.mjs index 1fb76273a2..067a4578db 100644 --- a/scripts/check-core-boundaries.test.mjs +++ b/scripts/check-core-boundaries.test.mjs @@ -70,6 +70,79 @@ test('Core and ACP defaults preserve their explicit assembly contracts', async ( ); }); +test('consumers do not repeat guarded empty internal defaults', async () => { + const cargoBoundaries = await import( + './core-boundaries/cargo-dependency-boundaries.mjs' + ); + assert.equal( + typeof cargoBoundaries.findRedundantInternalDefaultFeatureDisables, + 'function', + ); + + const emptyOwner = { + ...packageAt('empty-owner', 'src/crates/contracts/empty-owner/Cargo.toml'), + features: { default: [] }, + }; + const compatibilityOwner = { + ...packageAt('compatibility-owner', 'src/crates/interfaces/compatibility-owner/Cargo.toml'), + features: { default: ['client', 'server'] }, + }; + const unguardedEmptyOwner = { + ...packageAt('unguarded-empty-owner', 'src/crates/contracts/unguarded-empty-owner/Cargo.toml'), + features: { default: [] }, + }; + const consumer = packageAt('consumer', 'src/apps/consumer/Cargo.toml', [ + pathDependency('src/crates/contracts/empty-owner', { + name: 'empty-owner', + usesDefaultFeatures: false, + }), + pathDependency('src/crates/interfaces/compatibility-owner', { + name: 'compatibility-owner', + usesDefaultFeatures: false, + }), + pathDependency('src/crates/contracts/unguarded-empty-owner', { + name: 'unguarded-empty-owner', + usesDefaultFeatures: false, + }), + ]); + + const violations = cargoBoundaries.findRedundantInternalDefaultFeatureDisables( + [emptyOwner, compatibilityOwner, unguardedEmptyOwner, consumer], + { + root: TEST_ROOT, + guardedManifests: ['src/crates/contracts/empty-owner/Cargo.toml'], + }, + ); + assert.equal(violations.length, 1); + assert.match(violations[0].message, /empty-owner.*redundant/); +}); + +test('guarded internal defaults stay explicitly empty', async () => { + const cargoBoundaries = await import( + './core-boundaries/cargo-dependency-boundaries.mjs' + ); + const manifestPath = 'src/crates/contracts/empty-owner/Cargo.toml'; + const owner = { + ...packageAt('empty-owner', manifestPath), + features: { default: [] }, + }; + assert.deepEqual( + cargoBoundaries.findGuardedInternalDefaultFeatureViolations( + [owner], + { root: TEST_ROOT, guardedManifests: [manifestPath] }, + ), + [], + ); + + owner.features.default = ['expanded']; + const violations = cargoBoundaries.findGuardedInternalDefaultFeatureViolations( + [owner], + { root: TEST_ROOT, guardedManifests: [manifestPath] }, + ); + assert.equal(violations.length, 1); + assert.match(violations[0].message, /guarded default feature must stay explicitly empty/); +}); + test('portable contract crates expose only capability-local feature slices', async () => { const [runtimePortsManifest, agentToolsManifest] = await Promise.all([ readFile(new URL('../src/crates/contracts/runtime-ports/Cargo.toml', import.meta.url), 'utf8'), @@ -830,7 +903,7 @@ test('multiple crate feature gates combine as required feature AND conditions', assert.match(violations[0].message, /second/); }); -test('product entrypoints must disable bitfun-core default features', () => { +test('product entrypoints may inherit the guarded empty bitfun-core default', () => { const core = packageAt('bitfun-core', 'src/crates/assembly/core/Cargo.toml'); const app = packageAt('entry', 'src/apps/example/Cargo.toml', [ pathDependency('src/crates/assembly/core', { @@ -844,8 +917,7 @@ test('product entrypoints must disable bitfun-core default features', () => { { root: TEST_ROOT, crateLayoutRules }, ); - assert.equal(violations.length, 1); - assert.match(violations[0].message, /default-features = false/); + assert.deepEqual(violations, []); }); test('Core Agent Runtime baseline excludes concrete capability unions', () => { @@ -3452,7 +3524,7 @@ test('closed feature profiles reject product-full hidden behind a child feature' ); }); -test('capability contract consumers must select only their reviewed dependency features', async () => { +test('capability contract consumers may inherit empty defaults but must select reviewed features', async () => { const cargoBoundaries = await import( './core-boundaries/cargo-dependency-boundaries.mjs' ); @@ -3487,7 +3559,7 @@ test('capability contract consumers must select only their reviewed dependency f ], ).map((violation) => violation.message); - assert.ok(messages.some((message) => /default-features = false/.test(message))); + assert.doesNotMatch(messages.join('\n'), /default-features = false/); assert.ok(messages.some((message) => /plugin-runtime/.test(message))); }); diff --git a/scripts/core-boundaries/cargo-dependency-boundaries.mjs b/scripts/core-boundaries/cargo-dependency-boundaries.mjs index fd31e4bfab..4cc3edeb2c 100644 --- a/scripts/core-boundaries/cargo-dependency-boundaries.mjs +++ b/scripts/core-boundaries/cargo-dependency-boundaries.mjs @@ -6,6 +6,7 @@ import { acpClientCoreFeatures, acpServerCoreFeatures, capabilityContractDependencyRules, + guardedEmptyInternalDefaultManifestPaths, servicesReqwestOwnerFeatures, } from './rules/feature-rules.mjs'; @@ -1131,13 +1132,6 @@ export function findProductEntrypointCoreFeatureViolations( if (targetPackage?.name !== 'bitfun-core') { continue; } - if (dependency.uses_default_features !== false) { - violations.push({ - path: sourcePackage.manifest_path, - line: 1, - message: `product entrypoint ${sourcePackage.name} must set default-features = false for its bitfun-core ${dependencyDescription(dependency)}`, - }); - } const roleOwnedAcpDependency = sourcePackage.name === 'bitfun-acp' && dependency.optional === true; if ( @@ -1216,7 +1210,7 @@ export function findProductEntrypointCoreFeatureViolations( continue; } const allowedCoreFeatures = new Set( - reviewedActiveCoreFeatureClosures.get(rootName) ?? [], + ['default', ...(reviewedActiveCoreFeatureClosures.get(rootName) ?? [])], ); const rootSelectedFeatures = Object.keys(rootPackage.features ?? {}) .filter((feature) => feature !== 'default'); @@ -1474,6 +1468,95 @@ function featureTransitivelyReaches(featureGraph, sourceFeature, destinations, s && featureTransitivelyReaches(featureGraph, reference, destinations, seen)); } +export function findRedundantInternalDefaultFeatureDisables( + packages, + { + root, + guardedManifests = guardedEmptyInternalDefaultManifestPaths, + } = {}, +) { + if (!root) { + throw new Error('redundant internal default-feature check requires the repository root'); + } + + const packageByManifest = new Map( + packages.map((pkg) => [normalizedPath(pkg.manifest_path), pkg]), + ); + const guardedTargets = new Set( + guardedManifests.map((path) => normalizedPath(join(root, path))), + ); + const violations = []; + + for (const consumer of packages) { + for (const dependency of consumer.dependencies ?? []) { + if (dependency.uses_default_features !== false || !dependency.path) { + continue; + } + const targetPackage = packageByManifest.get( + normalizedPath(join(dependency.path, 'Cargo.toml')), + ); + const targetFeatures = targetPackage?.features ?? {}; + if ( + !targetPackage + || !guardedTargets.has(normalizedPath(targetPackage.manifest_path)) + || !Object.hasOwn(targetFeatures, 'default') + || !sameStringSet(targetFeatures.default, []) + ) { + continue; + } + violations.push({ + path: consumer.manifest_path, + line: 1, + message: `${consumer.name} ${targetPackage.name} dependency has redundant default-features = false because the target default is guarded empty`, + }); + } + } + + return violations; +} + +export function findGuardedInternalDefaultFeatureViolations( + packages, + { + root, + guardedManifests = guardedEmptyInternalDefaultManifestPaths, + } = {}, +) { + if (!root) { + throw new Error('guarded internal default-feature check requires the repository root'); + } + + const packageByManifest = new Map( + packages.map((pkg) => [normalizedPath(pkg.manifest_path), pkg]), + ); + const violations = []; + + for (const manifestPath of guardedManifests) { + const targetPackage = packageByManifest.get(normalizedPath(join(root, manifestPath))); + if (!targetPackage) { + violations.push({ + path: join(root, manifestPath), + line: 1, + message: `guarded internal empty-default target is missing: ${manifestPath}`, + }); + continue; + } + const targetFeatures = targetPackage.features ?? {}; + if ( + !Object.hasOwn(targetFeatures, 'default') + || !sameStringSet(targetFeatures.default, []) + ) { + violations.push({ + path: targetPackage.manifest_path, + line: 1, + message: `${targetPackage.name} guarded default feature must stay explicitly empty`, + }); + } + } + + return violations; +} + export function findCapabilityContractConsumerViolations( packages, rules = capabilityContractDependencyRules, @@ -1568,13 +1651,6 @@ export function findCapabilityContractConsumerViolations( } const unmatchedExpectedEdges = [...consumerProfile.edges]; for (const dependency of managedDependencies) { - if (dependency.uses_default_features !== false) { - violations.push({ - path: consumer.manifest_path, - line: 1, - message: `${consumer.name} ${rule.packageName} dependency must set default-features = false`, - }); - } const matchIndex = unmatchedExpectedEdges.findIndex((edge) => dependencyEdgeMatches(dependency, edge)); if (matchIndex === -1) { @@ -2085,6 +2161,8 @@ export function checkCargoDependencyBoundaries({ root, crateLayoutRules }) { packages, { root, crateLayoutRules }, ), + ...findGuardedInternalDefaultFeatureViolations(packages, { root }), + ...findRedundantInternalDefaultFeatureDisables(packages, { root }), ...findCapabilityContractConsumerViolations(packages, undefined, { root }), ...findFeatureGatedTestTargetViolations(packages), ...findRuntimeServicesTestSupportFeatureViolations(packages), diff --git a/scripts/core-boundaries/rules/feature-rules.mjs b/scripts/core-boundaries/rules/feature-rules.mjs index caec2d0f1d..2bb2832f70 100644 --- a/scripts/core-boundaries/rules/feature-rules.mjs +++ b/scripts/core-boundaries/rules/feature-rules.mjs @@ -15,6 +15,18 @@ export const servicesReqwestOwnerFeatures = [ 'web-tools', ]; +export const guardedEmptyInternalDefaultManifestPaths = [ + 'src/crates/assembly/core/Cargo.toml', + 'src/crates/assembly/product-capabilities/Cargo.toml', + 'src/crates/contracts/product-domains/Cargo.toml', + 'src/crates/contracts/runtime-ports/Cargo.toml', + 'src/crates/execution/tool-contracts/Cargo.toml', + 'src/crates/execution/tool-execution/Cargo.toml', + 'src/crates/execution/tool-provider-groups/Cargo.toml', + 'src/crates/services/services-core/Cargo.toml', + 'src/crates/services/services-integrations/Cargo.toml', +]; + export const optionalDependencyFeatureOwnerRules = [ { crateName: 'services-core', diff --git a/scripts/core-boundaries/rules/source/required-rules.mjs b/scripts/core-boundaries/rules/source/required-rules.mjs index 4d96e196ed..94ee305d00 100644 --- a/scripts/core-boundaries/rules/source/required-rules.mjs +++ b/scripts/core-boundaries/rules/source/required-rules.mjs @@ -3924,12 +3924,12 @@ export const requiredContentRules = [ patterns: [ { regex: - /bitfun-tool-packs = \{ path = "\.\.\/\.\.\/execution\/tool-provider-groups", default-features = false, optional = true \}/, + /bitfun-tool-packs = \{ path = "\.\.\/\.\.\/execution\/tool-provider-groups", optional = true \}/, message: 'bitfun-tool-packs dependency must stay optional and not force product-full outside the core feature graph', }, { regex: - /bitfun-services-integrations = \{ path = "\.\.\/\.\.\/services\/services-integrations", default-features = false, optional = true \}/, + /bitfun-services-integrations = \{ path = "\.\.\/\.\.\/services\/services-integrations", optional = true \}/, message: 'bitfun-services-integrations dependency must stay optional so local workspace profiles do not compile remote integrations', }, @@ -3987,13 +3987,13 @@ export const requiredContentRules = [ }, { regex: - /bitfun-product-domains = \{ path = "\.\.\/\.\.\/contracts\/product-domains", default-features = false, optional = true \}/, + /bitfun-product-domains = \{ path = "\.\.\/\.\.\/contracts\/product-domains", optional = true \}/, message: 'bitfun-product-domains dependency must stay optional and not force product-full outside the core feature graph', }, { regex: - /bitfun-product-capabilities = \{ path = "\.\.\/product-capabilities", default-features = false, optional = true \}/, + /bitfun-product-capabilities = \{ path = "\.\.\/product-capabilities", optional = true \}/, message: 'bitfun-product-capabilities dependency must stay optional and not force product-full outside the core feature graph', }, diff --git a/scripts/core-boundaries/self-test.mjs b/scripts/core-boundaries/self-test.mjs index c05c1043c7..5f0253e82d 100644 --- a/scripts/core-boundaries/self-test.mjs +++ b/scripts/core-boundaries/self-test.mjs @@ -4413,11 +4413,11 @@ export function runManifestParserSelfTest({ { path: 'src/crates/assembly/core/Cargo.toml', contracts: [ - 'bitfun-product-capabilities = \\{ path = "\\.\\.\\/product-capabilities", default-features = false, optional = true \\}', + 'bitfun-product-capabilities = \\{ path = "\\.\\.\\/product-capabilities", optional = true \\}', 'bitfun-ai-adapters = \\{ path = "\\.\\.\\/\\.\\.\\/adapters\\/ai-adapters", optional = true \\}', - 'bitfun-tool-packs = \\{ path = "\\.\\.\\/\\.\\.\\/execution\\/tool-provider-groups", default-features = false, optional = true \\}', - 'bitfun-services-integrations = \\{ path = "\\.\\.\\/\\.\\.\\/services\\/services-integrations", default-features = false, optional = true \\}', - 'bitfun-product-domains = \\{ path = "\\.\\.\\/\\.\\.\\/contracts\\/product-domains", default-features = false, optional = true \\}', + 'bitfun-tool-packs = \\{ path = "\\.\\.\\/\\.\\.\\/execution\\/tool-provider-groups", optional = true \\}', + 'bitfun-services-integrations = \\{ path = "\\.\\.\\/\\.\\.\\/services\\/services-integrations", optional = true \\}', + 'bitfun-product-domains = \\{ path = "\\.\\.\\/\\.\\.\\/contracts\\/product-domains", optional = true \\}', 'dep:bitfun-ai-adapters', 'ai-adapter-runtime', 'canvas-runtime', diff --git a/src/apps/cli/Cargo.toml b/src/apps/cli/Cargo.toml index c77704ee14..068903cead 100644 --- a/src/apps/cli/Cargo.toml +++ b/src/apps/cli/Cargo.toml @@ -30,7 +30,7 @@ path = "tests/terminal_process_contracts.rs" [dependencies] # Internal crates -bitfun-core = { path = "../../crates/assembly/core", default-features = false, features = [ +bitfun-core = { path = "../../crates/assembly/core", features = [ "agent-runtime", "document-read", "subscription-auth", @@ -55,11 +55,11 @@ bitfun-core-types = { path = "../../crates/contracts/core-types" } bitfun-acp = { path = "../../crates/interfaces/acp", default-features = false, features = ["client", "server"] } bitfun-agent-runtime = { path = "../../crates/execution/agent-runtime" } bitfun-agent-runtime-ipc = { path = "../../crates/adapters/agent-runtime-ipc" } -bitfun-runtime-ports = { path = "../../crates/contracts/runtime-ports", default-features = false, features = ["agent-api", "git-port", "permission", "plugin-runtime", "workspace-ports"] } +bitfun-runtime-ports = { path = "../../crates/contracts/runtime-ports", features = ["agent-api", "git-port", "permission", "plugin-runtime", "workspace-ports"] } bitfun-runtime-services = { path = "../../crates/execution/runtime-services" } -bitfun-services-core = { path = "../../crates/services/services-core", default-features = false, features = ["dispatch-workspace", "local-storage", "process-runtime", "runtime-ownership"] } -bitfun-agent-tools = { path = "../../crates/execution/tool-contracts", default-features = false } -bitfun-product-domains = { path = "../../crates/contracts/product-domains", default-features = false, features = ["external-sources"] } +bitfun-services-core = { path = "../../crates/services/services-core", features = ["dispatch-workspace", "local-storage", "process-runtime", "runtime-ownership"] } +bitfun-agent-tools = { path = "../../crates/execution/tool-contracts" } +bitfun-product-domains = { path = "../../crates/contracts/product-domains", features = ["external-sources"] } bitfun-app-server = { path = "../../crates/interfaces/app-server" } bitfun-app-server-client = { path = "../../crates/interfaces/app-server-client" } bitfun-app-server-protocol = { path = "../../crates/interfaces/app-server-protocol" } diff --git a/src/apps/desktop/Cargo.toml b/src/apps/desktop/Cargo.toml index d01c4d4b53..6ee211984c 100644 --- a/src/apps/desktop/Cargo.toml +++ b/src/apps/desktop/Cargo.toml @@ -19,14 +19,14 @@ serde_json = { workspace = true } [dependencies] # Internal crates -bitfun-core = { path = "../../crates/assembly/core", default-features = false, features = ["product-full"] } +bitfun-core = { path = "../../crates/assembly/core", features = ["product-full"] } bitfun-relay-service = { path = "../../crates/services/relay-service" } bitfun-agent-runtime = { path = "../../crates/execution/agent-runtime" } -bitfun-runtime-ports = { path = "../../crates/contracts/runtime-ports", default-features = false, features = ["agent-api", "permission", "workspace-ports"] } -bitfun-product-domains = { path = "../../crates/contracts/product-domains", default-features = false, features = ["appearance-market"] } -bitfun-services-integrations = { path = "../../crates/services/services-integrations", default-features = false, features = ["canvas-runtime", "miniapp-market", "speech"] } +bitfun-runtime-ports = { path = "../../crates/contracts/runtime-ports", features = ["agent-api", "permission", "workspace-ports"] } +bitfun-product-domains = { path = "../../crates/contracts/product-domains", features = ["appearance-market"] } +bitfun-services-integrations = { path = "../../crates/services/services-integrations", features = ["canvas-runtime", "miniapp-market", "speech"] } bitfun-core-types = { path = "../../crates/contracts/core-types" } -bitfun-agent-tools = { path = "../../crates/execution/tool-contracts", default-features = false, features = ["element-token"] } +bitfun-agent-tools = { path = "../../crates/execution/tool-contracts", features = ["element-token"] } bitfun-transport = { path = "../../crates/adapters/transport", features = ["tauri-adapter"] } bitfun-events = { path = "../../crates/contracts/events" } bitfun-webdriver = { path = "../../crates/adapters/webdriver" } @@ -97,9 +97,9 @@ dispatch = { workspace = true } foreign-types = { workspace = true } libc = { workspace = true } objc2 = { workspace = true, features = ["exception"] } -objc2-foundation = { workspace = true } +objc2-foundation = { workspace = true, features = ["std", "NSArray", "NSData", "NSDictionary", "NSError", "NSString"] } objc2-app-kit = { workspace = true } -objc2-vision = { workspace = true } +objc2-vision = { workspace = true, features = ["std", "VNRecognizeTextRequest", "VNRequest", "VNObservation", "VNRequestHandler", "VNUtils", "VNTypes", "objc2-core-foundation"] } [target.'cfg(windows)'.dependencies] win32job = { workspace = true } diff --git a/src/apps/sdk-host/Cargo.toml b/src/apps/sdk-host/Cargo.toml index 834d86cd79..269d51daa1 100644 --- a/src/apps/sdk-host/Cargo.toml +++ b/src/apps/sdk-host/Cargo.toml @@ -14,7 +14,7 @@ path = "src/main.rs" anyhow = { workspace = true } async-trait = { workspace = true } bitfun-agent-runtime = { path = "../../crates/execution/agent-runtime" } -bitfun-core = { path = "../../crates/assembly/core", default-features = false, features = [ +bitfun-core = { path = "../../crates/assembly/core", features = [ "agent-runtime", "document-read", "subscription-auth", diff --git a/src/apps/server/Cargo.toml b/src/apps/server/Cargo.toml index 187c3a5b66..c7f9a8f475 100644 --- a/src/apps/server/Cargo.toml +++ b/src/apps/server/Cargo.toml @@ -10,7 +10,7 @@ name = "bitfun-server" path = "src/main.rs" [dependencies] -bitfun-core = { path = "../../crates/assembly/core", default-features = false, features = ["product-full"] } +bitfun-core = { path = "../../crates/assembly/core", features = ["product-full"] } # App-server surface: an in-process JSON-RPC server/client pair over an # in-memory channel transport. The websocket handler routes agent kernel RPCs diff --git a/src/crates/adapters/agent-runtime-ipc/Cargo.toml b/src/crates/adapters/agent-runtime-ipc/Cargo.toml index cae949c9a8..06d6e78a34 100644 --- a/src/crates/adapters/agent-runtime-ipc/Cargo.toml +++ b/src/crates/adapters/agent-runtime-ipc/Cargo.toml @@ -13,8 +13,8 @@ crate-type = ["rlib"] [dependencies] async-trait = { workspace = true } bitfun-events = { path = "../../contracts/events" } -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["agent-api", "git-port"] } +bitfun-product-domains = { path = "../../contracts/product-domains" } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["agent-api", "git-port"] } dunce = { workspace = true } fs2 = { workspace = true } serde = { workspace = true } diff --git a/src/crates/adapters/ai-adapters/Cargo.toml b/src/crates/adapters/ai-adapters/Cargo.toml index 12cd71a50e..772f1e5721 100644 --- a/src/crates/adapters/ai-adapters/Cargo.toml +++ b/src/crates/adapters/ai-adapters/Cargo.toml @@ -24,7 +24,7 @@ async-trait = { workspace = true } base64 = { workspace = true, optional = true } bitfun-agent-stream = { path = "../../execution/agent-stream" } bitfun-core-types = { path = "../../contracts/core-types" } -bitfun-services-core = { path = "../../services/services-core", default-features = false, optional = true } +bitfun-services-core = { path = "../../services/services-core", optional = true } chrono = { workspace = true } dirs = { workspace = true, optional = true } keyring-core = { workspace = true, optional = true } diff --git a/src/crates/adapters/claude-code-adapter/Cargo.toml b/src/crates/adapters/claude-code-adapter/Cargo.toml index 4cceb1484a..5afe861df7 100644 --- a/src/crates/adapters/claude-code-adapter/Cargo.toml +++ b/src/crates/adapters/claude-code-adapter/Cargo.toml @@ -11,8 +11,8 @@ name = "bitfun_claude_code_adapter" crate-type = ["rlib"] [dependencies] -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources"] } -bitfun-services-core = { path = "../../services/services-core", default-features = false, features = ["markdown"] } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources"] } +bitfun-services-core = { path = "../../services/services-core", features = ["markdown"] } bitfun-static-hook-support = { path = "../static-hook-support" } dirs = { workspace = true } dunce = { workspace = true } diff --git a/src/crates/adapters/codex-adapter/Cargo.toml b/src/crates/adapters/codex-adapter/Cargo.toml index 92b9350337..11e15c9f6e 100644 --- a/src/crates/adapters/codex-adapter/Cargo.toml +++ b/src/crates/adapters/codex-adapter/Cargo.toml @@ -11,8 +11,8 @@ name = "bitfun_codex_adapter" crate-type = ["rlib"] [dependencies] -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources"] } -bitfun-services-core = { path = "../../services/services-core", default-features = false } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources"] } +bitfun-services-core = { path = "../../services/services-core" } bitfun-static-hook-support = { path = "../static-hook-support" } dirs = { workspace = true } dunce = { workspace = true } diff --git a/src/crates/adapters/opencode-adapter/Cargo.toml b/src/crates/adapters/opencode-adapter/Cargo.toml index 52da74c34a..0dbcc24215 100644 --- a/src/crates/adapters/opencode-adapter/Cargo.toml +++ b/src/crates/adapters/opencode-adapter/Cargo.toml @@ -13,9 +13,9 @@ crate-type = ["rlib"] [dependencies] async-trait = { workspace = true } bitfun-plugin-runtime-client = { path = "../../execution/plugin-runtime-client" } -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources", "plugin-source"] } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["plugin-runtime"] } -bitfun-services-core = { path = "../../services/services-core", default-features = false, features = ["markdown"] } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources", "plugin-source"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["plugin-runtime"] } +bitfun-services-core = { path = "../../services/services-core", features = ["markdown"] } bitfun-static-hook-support = { path = "../static-hook-support" } dirs = { workspace = true } dunce = { workspace = true } @@ -32,8 +32,8 @@ urlencoding = { workspace = true } url = { workspace = true } [dev-dependencies] -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["script-tool-runtime"] } -bitfun-services-integrations = { path = "../../services/services-integrations", default-features = false, features = ["plugin-source", "script-tool-runtime"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["script-tool-runtime"] } +bitfun-services-integrations = { path = "../../services/services-integrations", features = ["plugin-source", "script-tool-runtime"] } tokio = { workspace = true, features = ["macros", "rt"] } tempfile = { workspace = true } diff --git a/src/crates/adapters/static-hook-support/Cargo.toml b/src/crates/adapters/static-hook-support/Cargo.toml index 3159aae70e..4ed3f3a7f9 100644 --- a/src/crates/adapters/static-hook-support/Cargo.toml +++ b/src/crates/adapters/static-hook-support/Cargo.toml @@ -10,8 +10,8 @@ name = "bitfun_static_hook_support" crate-type = ["rlib"] [dependencies] -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources"] } -bitfun-services-core = { path = "../../services/services-core", default-features = false } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources"] } +bitfun-services-core = { path = "../../services/services-core" } serde_json = { workspace = true } toml = { workspace = true } hex = { workspace = true } diff --git a/src/crates/adapters/webdriver/Cargo.toml b/src/crates/adapters/webdriver/Cargo.toml index 615fcd4908..309426f905 100644 --- a/src/crates/adapters/webdriver/Cargo.toml +++ b/src/crates/adapters/webdriver/Cargo.toml @@ -24,9 +24,9 @@ image = { workspace = true } [target.'cfg(target_os = "macos")'.dependencies] block2 = { workspace = true } objc2 = { workspace = true } -objc2-app-kit = { workspace = true, features = ["NSImage", "NSImageRep", "NSBitmapImageRep"] } -objc2-foundation = { workspace = true, features = ["NSString", "NSData", "NSError", "NSDictionary"] } -objc2-web-kit = { workspace = true } +objc2-app-kit = { workspace = true, features = ["std", "NSImage", "NSImageRep", "NSBitmapImageRep"] } +objc2-foundation = { workspace = true, features = ["std", "NSString", "NSData", "NSError", "NSDictionary"] } +objc2-web-kit = { workspace = true, features = ["std", "WKContentWorld", "WKWebView", "WKSnapshotConfiguration", "WKPDFConfiguration", "block2", "objc2-app-kit"] } [target.'cfg(target_os = "windows")'.dependencies] tempfile = { workspace = true } diff --git a/src/crates/assembly/core/Cargo.toml b/src/crates/assembly/core/Cargo.toml index 14492bb3b4..61af6a74cf 100644 --- a/src/crates/assembly/core/Cargo.toml +++ b/src/crates/assembly/core/Cargo.toml @@ -73,28 +73,28 @@ bitfun-agent-runtime = { path = "../../execution/agent-runtime", optional = true bitfun-harness = { path = "../../execution/harness", optional = true } # Product capability pack contracts -bitfun-product-capabilities = { path = "../product-capabilities", default-features = false, optional = true } +bitfun-product-capabilities = { path = "../product-capabilities", optional = true } # Ecosystem-neutral external source lifecycle coordinator bitfun-external-sources = { path = "../external-sources", optional = true } # Agent tool contracts -bitfun-agent-tools = { path = "../../execution/tool-contracts", default-features = false, optional = true } +bitfun-agent-tools = { path = "../../execution/tool-contracts", optional = true } # Tool pack provider plan -bitfun-tool-packs = { path = "../../execution/tool-provider-groups", default-features = false, optional = true } +bitfun-tool-packs = { path = "../../execution/tool-provider-groups", optional = true } # Core service owner crate -bitfun-services-core = { path = "../../services/services-core", default-features = false, features = ["json-io"] } +bitfun-services-core = { path = "../../services/services-core", features = ["json-io"] } # Integration service owner crate -bitfun-services-integrations = { path = "../../services/services-integrations", default-features = false, optional = true } +bitfun-services-integrations = { path = "../../services/services-integrations", optional = true } # Product domain owner crate -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, optional = true } +bitfun-product-domains = { path = "../../contracts/product-domains", optional = true } # Tool runtime -tool-runtime = { path = "../../execution/tool-execution", default-features = false, optional = true } +tool-runtime = { path = "../../execution/tool-execution", optional = true } # terminal terminal-core = { path = "../../services/terminal", optional = true } @@ -113,7 +113,7 @@ tokio-tungstenite = { workspace = true, optional = true } # Event layer dependency (lowest layer) bitfun-core-types = { path = "../../contracts/core-types" } bitfun-events = { path = "../../contracts/events" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["permission", "workspace-ports"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["permission", "workspace-ports"] } bitfun-runtime-services = { path = "../../execution/runtime-services", optional = true } # Reviewed product-full plugin composition root. diff --git a/src/crates/assembly/external-sources/Cargo.toml b/src/crates/assembly/external-sources/Cargo.toml index de2dcbaa97..47c0554c53 100644 --- a/src/crates/assembly/external-sources/Cargo.toml +++ b/src/crates/assembly/external-sources/Cargo.toml @@ -11,7 +11,7 @@ name = "bitfun_external_sources" crate-type = ["rlib"] [dependencies] -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources"] } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources"] } futures = { workspace = true } log = { workspace = true } tokio = { workspace = true, features = ["rt", "sync", "time"] } diff --git a/src/crates/assembly/product-capabilities/Cargo.toml b/src/crates/assembly/product-capabilities/Cargo.toml index f6bfc2f969..06f00221a1 100644 --- a/src/crates/assembly/product-capabilities/Cargo.toml +++ b/src/crates/assembly/product-capabilities/Cargo.toml @@ -14,16 +14,19 @@ crate-type = ["rlib"] name = "product_capability_contracts" path = "tests/product_capability_contracts.rs" +[features] +default = [] + [dependencies] bitfun-harness = { path = "../../execution/harness" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["plugin-runtime"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["plugin-runtime"] } bitfun-runtime-services = { path = "../../execution/runtime-services" } -bitfun-tool-packs = { path = "../../execution/tool-provider-groups", default-features = false } +bitfun-tool-packs = { path = "../../execution/tool-provider-groups" } [dev-dependencies] async-trait = { workspace = true } bitfun-agent-runtime = { path = "../../execution/agent-runtime" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["agent-api"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["agent-api"] } bitfun-runtime-services = { path = "../../execution/runtime-services", features = ["test-support"] } tokio = { workspace = true, features = ["macros", "rt"] } diff --git a/src/crates/contracts/runtime-ports/Cargo.toml b/src/crates/contracts/runtime-ports/Cargo.toml index 509f8c99e0..aef7843ee7 100644 --- a/src/crates/contracts/runtime-ports/Cargo.toml +++ b/src/crates/contracts/runtime-ports/Cargo.toml @@ -33,7 +33,7 @@ required-features = ["workspace-ports"] [dependencies] anyhow = { workspace = true, optional = true } async-trait = { workspace = true } -bitfun-product-domains = { path = "../product-domains", default-features = false, optional = true } +bitfun-product-domains = { path = "../product-domains", optional = true } bitfun-core-types = { path = "../core-types", optional = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/src/crates/execution/agent-runtime/Cargo.toml b/src/crates/execution/agent-runtime/Cargo.toml index 8990b87d0a..936c9e1a4a 100644 --- a/src/crates/execution/agent-runtime/Cargo.toml +++ b/src/crates/execution/agent-runtime/Cargo.toml @@ -16,11 +16,11 @@ default = [] [dependencies] async-trait = { workspace = true } bitfun-agent-stream = { path = "../agent-stream" } -bitfun-agent-tools = { path = "../tool-contracts", default-features = false } +bitfun-agent-tools = { path = "../tool-contracts" } bitfun-core-types = { path = "../../contracts/core-types" } bitfun-events = { path = "../../contracts/events" } bitfun-harness = { path = "../harness" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["agent-api", "git-port", "permission", "plugin-runtime", "remote-workspace-ports", "runtime-event-port", "terminal-port", "workspace-ports"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["agent-api", "git-port", "permission", "plugin-runtime", "remote-workspace-ports", "runtime-event-port", "terminal-port", "workspace-ports"] } bitfun-runtime-services = { path = "../runtime-services" } dashmap = { workspace = true } hex = { workspace = true } diff --git a/src/crates/execution/agent-stream/Cargo.toml b/src/crates/execution/agent-stream/Cargo.toml index 491201d4a1..47245168bb 100644 --- a/src/crates/execution/agent-stream/Cargo.toml +++ b/src/crates/execution/agent-stream/Cargo.toml @@ -24,7 +24,7 @@ tokio-util = { workspace = true } uuid = { workspace = true } [dev-dependencies] -bitfun-agent-tools = { path = "../tool-contracts", default-features = false } +bitfun-agent-tools = { path = "../tool-contracts" } tokio-stream = { workspace = true } [lints] diff --git a/src/crates/execution/plugin-runtime-client/Cargo.toml b/src/crates/execution/plugin-runtime-client/Cargo.toml index 42f2f9a9f2..6ac82e4db5 100644 --- a/src/crates/execution/plugin-runtime-client/Cargo.toml +++ b/src/crates/execution/plugin-runtime-client/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["rlib"] [dependencies] async-trait = { workspace = true } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["plugin-runtime"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["plugin-runtime"] } tokio = { workspace = true, features = ["sync", "time"] } [dev-dependencies] diff --git a/src/crates/execution/runtime-services/Cargo.toml b/src/crates/execution/runtime-services/Cargo.toml index db90b78737..78a4bbdaf0 100644 --- a/src/crates/execution/runtime-services/Cargo.toml +++ b/src/crates/execution/runtime-services/Cargo.toml @@ -15,7 +15,7 @@ test-support = [] [dependencies] bitfun-events = { path = "../../contracts/events" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["git-port", "remote-exec-port", "remote-workspace-ports", "runtime-event-port", "terminal-port", "workspace-ports"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["git-port", "remote-exec-port", "remote-workspace-ports", "runtime-event-port", "terminal-port", "workspace-ports"] } anyhow = { workspace = true } async-trait = { workspace = true } log = { workspace = true } diff --git a/src/crates/execution/tool-contracts/Cargo.toml b/src/crates/execution/tool-contracts/Cargo.toml index 752eb65dac..4ef3cf024c 100644 --- a/src/crates/execution/tool-contracts/Cargo.toml +++ b/src/crates/execution/tool-contracts/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["rlib"] serde = { workspace = true } serde_json = { workspace = true } bitfun-core-types = { path = "../../contracts/core-types" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports" } async-trait = { workspace = true } indexmap = { workspace = true } diff --git a/src/crates/execution/tool-execution/Cargo.toml b/src/crates/execution/tool-execution/Cargo.toml index 069b67986a..b83d183315 100644 --- a/src/crates/execution/tool-execution/Cargo.toml +++ b/src/crates/execution/tool-execution/Cargo.toml @@ -10,9 +10,9 @@ web-readable = ["dep:htmd", "dep:legible", "dep:readability-js", "dep:regex"] [dependencies] anydoc = { workspace = true, optional = true } -bitfun-agent-tools = { path = "../tool-contracts", default-features = false } +bitfun-agent-tools = { path = "../tool-contracts" } bitfun-events = { path = "../../contracts/events" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports" } dashmap = { workspace = true } globset = { workspace = true } dunce = { workspace = true } diff --git a/src/crates/interfaces/acp/Cargo.toml b/src/crates/interfaces/acp/Cargo.toml index 64b2d9163e..2d6ad2dbd0 100644 --- a/src/crates/interfaces/acp/Cargo.toml +++ b/src/crates/interfaces/acp/Cargo.toml @@ -42,9 +42,9 @@ server = [ name = "bitfun_acp" [dependencies] -bitfun-core = { path = "../../assembly/core", default-features = false, optional = true } +bitfun-core = { path = "../../assembly/core", optional = true } bitfun-agent-runtime = { path = "../../execution/agent-runtime", optional = true } -bitfun-agent-tools = { path = "../../execution/tool-contracts", default-features = false, optional = true } +bitfun-agent-tools = { path = "../../execution/tool-contracts", optional = true } bitfun-events = { path = "../../contracts/events" } bitfun-core-types = { path = "../../contracts/core-types", optional = true } diff --git a/src/crates/interfaces/app-server-protocol/Cargo.toml b/src/crates/interfaces/app-server-protocol/Cargo.toml index c1858269f0..f758c59ee3 100644 --- a/src/crates/interfaces/app-server-protocol/Cargo.toml +++ b/src/crates/interfaces/app-server-protocol/Cargo.toml @@ -12,8 +12,8 @@ name = "bitfun_app_server_protocol" agent-client-protocol = { workspace = true } bitfun-events = { path = "../../contracts/events" } bitfun-core-types = { path = "../../contracts/core-types" } -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources"] } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["agent-api", "git-port"] } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["agent-api", "git-port"] } serde = { workspace = true } serde_json = { workspace = true } ts-rs = { workspace = true, optional = true } diff --git a/src/crates/interfaces/app-server/Cargo.toml b/src/crates/interfaces/app-server/Cargo.toml index a947bbab0c..8917efedd1 100644 --- a/src/crates/interfaces/app-server/Cargo.toml +++ b/src/crates/interfaces/app-server/Cargo.toml @@ -14,11 +14,11 @@ bitfun-app-server-protocol = { path = "../app-server-protocol" } # Host-service handlers use the reviewed Agent Runtime owner closure. Add a # narrower Core owner feature when a newly registered domain needs it; the # protocol surface must not inherit the broad bitfun-core/product-full union. -bitfun-core = { path = "../../assembly/core", default-features = false, features = ["external-sources", "git", "i18n-runtime", "remote-connect"] } +bitfun-core = { path = "../../assembly/core", features = ["external-sources", "git", "i18n-runtime", "remote-connect"] } bitfun-agent-runtime = { path = "../../execution/agent-runtime" } bitfun-events = { path = "../../contracts/events" } -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, features = ["external-sources"] } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["agent-api"] } +bitfun-product-domains = { path = "../../contracts/product-domains", features = ["external-sources"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["agent-api"] } tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] } tokio-util = { workspace = true, features = ["compat"] } futures = { workspace = true } diff --git a/src/crates/interfaces/sdk-host/Cargo.toml b/src/crates/interfaces/sdk-host/Cargo.toml index 8ded3c266c..7e7b60a1f2 100644 --- a/src/crates/interfaces/sdk-host/Cargo.toml +++ b/src/crates/interfaces/sdk-host/Cargo.toml @@ -13,7 +13,7 @@ async-trait = { workspace = true } bitfun-agent-runtime = { path = "../../execution/agent-runtime" } bitfun-core-types = { path = "../../contracts/core-types" } bitfun-events = { path = "../../contracts/events" } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["agent-api"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["agent-api"] } futures-util = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -23,7 +23,7 @@ tracing = { workspace = true } uuid = { workspace = true } [dev-dependencies] -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["permission"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["permission"] } [lints] workspace = true diff --git a/src/crates/services/miniapp-market-service/Cargo.toml b/src/crates/services/miniapp-market-service/Cargo.toml index c15336869a..c221641e79 100644 --- a/src/crates/services/miniapp-market-service/Cargo.toml +++ b/src/crates/services/miniapp-market-service/Cargo.toml @@ -23,7 +23,7 @@ serde_json = { workspace = true } semver = { workspace = true } sha2 = { workspace = true } similar = { workspace = true } -sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite"] } +sqlx = { workspace = true, features = ["runtime-tokio", "sqlite"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["fs", "rt", "sync", "time"] } tower-http = { version = "0.6.11", features = ["fs", "set-header", "trace"] } diff --git a/src/crates/services/services-core/Cargo.toml b/src/crates/services/services-core/Cargo.toml index 8082b940d3..657c87eaa1 100644 --- a/src/crates/services/services-core/Cargo.toml +++ b/src/crates/services/services-core/Cargo.toml @@ -15,7 +15,7 @@ anyhow = { workspace = true, optional = true } async-trait = { workspace = true, optional = true } bitfun-core-types = { path = "../../contracts/core-types", optional = true } bitfun-events = { path = "../../contracts/events", optional = true } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, optional = true } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", optional = true } tokio = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/src/crates/services/services-integrations/Cargo.toml b/src/crates/services/services-integrations/Cargo.toml index f8280f2bec..6120c284ee 100644 --- a/src/crates/services/services-integrations/Cargo.toml +++ b/src/crates/services/services-integrations/Cargo.toml @@ -17,18 +17,18 @@ serde_json = { workspace = true } log = { workspace = true } ts-rs = { workspace = true, optional = true } bitfun-agent-runtime = { path = "../../execution/agent-runtime", optional = true } -bitfun-agent-tools = { path = "../../execution/tool-contracts", default-features = false, optional = true } +bitfun-agent-tools = { path = "../../execution/tool-contracts", optional = true } bitfun-events = { path = "../../contracts/events" } bitfun-core-types = { path = "../../contracts/core-types", optional = true } -bitfun-product-domains = { path = "../../contracts/product-domains", default-features = false, optional = true } -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, optional = true } +bitfun-product-domains = { path = "../../contracts/product-domains", optional = true } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", optional = true } aes-gcm = { workspace = true, optional = true } aes = { workspace = true, optional = true } anyhow = { workspace = true, optional = true } argon2 = { workspace = true, optional = true } async-trait = { workspace = true, optional = true } base64 = { workspace = true, optional = true } -bitfun-services-core = { path = "../services-core", default-features = false, optional = true } +bitfun-services-core = { path = "../services-core", optional = true } bzip2 = { workspace = true, optional = true } chrono = { workspace = true, optional = true } dunce = { workspace = true, optional = true } @@ -47,7 +47,7 @@ mac_address = { workspace = true, optional = true } md5 = { workspace = true, optional = true } notify = { workspace = true, optional = true } oxc = { workspace = true, optional = true } -qrcode = { workspace = true, optional = true } +qrcode = { workspace = true, features = ["image", "svg"], optional = true } rand = { workspace = true, optional = true } reqwest = { workspace = true, features = ["http2"], optional = true } semver = { workspace = true, optional = true } diff --git a/src/crates/services/skin-market-service/Cargo.toml b/src/crates/services/skin-market-service/Cargo.toml index f7affb139f..f5ed1471f8 100644 --- a/src/crates/services/skin-market-service/Cargo.toml +++ b/src/crates/services/skin-market-service/Cargo.toml @@ -22,7 +22,7 @@ semver = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } -sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite"] } +sqlx = { workspace = true, features = ["runtime-tokio", "sqlite"] } tokio = { workspace = true, features = ["fs", "rt", "sync", "time"] } tokio-util = { workspace = true, features = ["io"] } tower-http = { version = "0.6.11", features = ["fs"] } diff --git a/src/crates/services/terminal/Cargo.toml b/src/crates/services/terminal/Cargo.toml index 53f649ac63..bf63756457 100644 --- a/src/crates/services/terminal/Cargo.toml +++ b/src/crates/services/terminal/Cargo.toml @@ -10,7 +10,7 @@ name = "terminal_core" path = "src/lib.rs" [dependencies] -bitfun-runtime-ports = { path = "../../contracts/runtime-ports", default-features = false, features = ["terminal-port"] } +bitfun-runtime-ports = { path = "../../contracts/runtime-ports", features = ["terminal-port"] } # Async runtime tokio = { workspace = true, features = ["io-util", "macros", "process", "rt", "sync", "time"] }