Oven and toolchain ownership map¶
This is the checked-in ownership map required by #871: a component-by-component inventory of the Oven/toolchain control plane, classifying every supported responsibility as Incan semantic control, Rust host kernel, or explicitly excluded (compiler-internal, not part of the Incan-vs-Oven axis at all).
The classification and numerical audit were recorded against release/v0.5 (post v0.5 RC3, PR #1076 merged). Paths below have been updated for the settled v0.6 crate extraction; line counts, test counts and migration-risk observations remain historical evidence, not a fresh coverage assessment.
Current ownership is split across loaves/oven/oven_model/ (manifest, lock, workspace and lifecycle models), loaves/oven/oven_store/ (receipts, stores, leases and process containment), and loaves/oven/oven_rustc/ (native plans, Loaf baking, test execution and Cargo compatibility). Compiler-specific composition belongs to loaves/compiler/incan_driver/ and loaves/compiler/incan_provider/; checked provider and manifest contracts live in loaves/compiler/incan_frontend/. The proposed additional Oven crates and toolchain binary moves have not landed.
The classification rule¶
This map does not invent its own criteria. It applies the rule this repo already decided, quoted verbatim:
- RFC 118: "Keep the Incan CLI native Incan while preserving Oven's Rust operational core/API as the explicit cache, store, lease, lifetime, concurrency, and crash-safety exception." Layers affected: "Oven API and operational core — must own planning, resolver/provider choice, policy, target selection, scheduling, artifacts, receipts, caches, stores, leases, and crash-safe publication through language-neutral owned snapshots and opaque handles." Also: "Compiler service API — must expose bounded compilation and semantic services to Oven without making Oven invoke or import the Incan CLI."
- RFC 119: "The Rust core remains narrow but real: ...Oven's operational core/API owns planning, resolution, policy, stores, leases, provider execution, and crash-safe publication in Rust. Its public API is language-neutral and does not leak Rust borrows." And: "Incan-first authoring remains policy: a Rust facet makes Rust projects and explicitly justified mixed work supportable. It does not authorize new Rust in Incan products without a demonstrated limitation and tracked removal path."
- RFC 117: generators/providers are "ordinary typed Incan functions" — provider logic is Incan-owned even where the engine that runs providers is legitimately Rust.
A component is Rust host kernel only if it does planning, resolver/provider choice, policy evaluation, target selection, scheduling, artifact/receipt handling, caching, store/lease management, or crash-safe publication. Everything else currently in Rust is either an Incan semantic control migration candidate, or a compiler-service exception (the frontend/LSP/codegraph — compiler-internal territory this repo already treats as Rust, a different axis than Oven's operational core).
Summary¶
- Confirmed Rust host kernel: the large majority of the audited surface — receipts, crash-safe publication, leases, resolver/provider-choice, scheduling, caches, and direct-rustc/Cargo-boundary invocation all cleanly match the quoted rule.
- Migration candidates (Incan semantic control): a materially-sized, concrete set — see table below. Most are pure data/schema/validation logic with zero filesystem, process, or crash-safety dependency.
- Genuinely uncertain, needs an explicit decision: a smaller set where the code doesn't cleanly match either bucket, or where classification depends on a decision this map surfaces but doesn't make unilaterally.
- Original architectural findings: the audit identified Cargo.lock/manifest reimplementation, LSP→CLI setup calls, and CLI/core mixing. The rows below distinguish those historical findings from the settled driver and Oven ownership after extraction.
- Migration tracking: #1034 is the umbrella for the semantic-control-plane migration. The delivery issues recorded in the done-when checklist below preserve the original component breakdown; the crate extraction does not itself complete an Incan-authoring migration.
- Historical test coverage was mechanically verified per file, not guessed — see the dedicated section below. The one finding worth reading before anything else: the largest migration-candidate block (
library_manifest/{model,wire,type_refs,validation}.rs, 3,500 lines) has zero in-file unit tests.
Confirmed Rust host kernel¶
Test counts are in-file #[cfg(test)] mod tests line/function counts, mechanically grepped — not a coverage-quality judgment, just a presence signal. See "Test coverage" below for how to read these.
| Component | File(s) | Responsibility matched | Tests (lines/fns) |
|---|---|---|---|
| Oven receipts & build-unit identity | loaves/oven/oven_store/src/lib.rs |
Artifacts, receipts, crash-safe publication (staged-file + atomic rename) | 431 / 11 |
| Oven process-tree containment | loaves/oven/oven_store/src/process.rs |
Scheduling/crash-safety around provider execution (process-group isolation/reaping) | 0 / 0 ⚠️ |
| Compiler-suite process capability | loaves/oven/oven_model/src/compiler_suite_env.rs |
Policy (capability admission table), artifacts (resolved closure) | 0 / 0 ⚠️ |
| Interop target requirements & deployment planning | loaves/oven/oven_model/src/oven_interop.rs |
Policy (manifest validation), target selection/locking | 531 / 6 |
| Provider catalog, feature graph, SDK inventory | loaves/compiler/incan_frontend/src/provider/{features,plan,sdk}.rs |
Resolver/provider-choice, policy — the actual engine that runs providers, not provider logic itself | 1,346 / 36 |
| Generated Cargo artifact cache | loaves/compiler/incan_driver/src/generated_cache.rs |
Caches, stores, leases (advisory-locked, size-bounded eviction) | 446 / 18 |
| Provider artifact content-addressing | loaves/compiler/incan_frontend/src/library_manifest/artifact.rs |
Artifacts (deterministic digest identity) | 822 / 13 |
| Dependency resolver | loaves/compiler/incan_provider/src/dependency_resolver.rs |
Resolver/policy over the Cargo dependency graph | 549 / 23 |
| Lockfile crash-safe publication & semantic lock state | loaves/oven/oven_model/src/lock.rs |
Crash-safe publication (stage → sync → atomic rename), lock identity/artifacts | 1,443 / 26 |
| Workspace dependency inheritance, scope resolution, build ordering | loaves/oven/oven_model/src/workspace.rs (back half) |
Resolver/policy (workspace = true inheritance), target selection, scheduling (topological build order) |
566 / 18 (whole file, front/back half not separable) |
| Loaf envelope, generation commit, resolver/policy, toolchain resolution, build-unit identity, baker pipeline | loaves/oven/oven_rustc/src/loaf.rs |
Artifacts/receipts, crash-safe publication, resolver/provider-choice (tie-break policy), target selection | 1,444 / 27 |
| Native test process supervision & scheduling | loaves/oven/oven_rustc/src/native_test.rs (bulk) |
Scheduler, target selection, capability policy, receipt model (RFC 119 test-execution language, matched near-verbatim) | 699 / 19 (whole file, includes the small libtest-parsing migration candidate below) |
| Store data model, publication, leases, inspection/pruning | loaves/oven/oven_store/src/store.rs |
Policy (capacity limits), crash-safe publication, leases (advisory-locked), caches/stores (eviction) | 856 / 25 |
| Interop receipt/plan model, native bake, toolchain/SDK selection, shim compilation | loaves/oven/oven_interop/src/lib.rs (bulk) |
Artifacts/receipts, resolver/provider-choice, provider execution | 2,707 / 20 |
| Rustc artifact manifest/plan, registry-leaf resolution, project inspection authority, direct rustc/rustdoc invocation | loaves/oven/oven_rustc/src/rustc.rs (bulk) |
Planning, artifacts, resolver/provider-choice, stores/leases, direct rustc invocation (named explicitly in RFC 119 point 10) | 2,990 / 47 (whole file, includes the flagged diagnostic-formatting subset below) |
| Direct-Rustc & compiler-suite plan orchestration, Cargo unit-graph translation, subprocess wrapper, registry/SDK staging, publisher lease/lock, capacity accounting | loaves/oven/oven_cargo_compat/src/lib.rs (bulk) |
Planning, artifacts, receipts, leases, crash-safe publication, scheduling — Cargo treated as authoritative per RFC 119's "explicit compatibility operation" | 3,966 / 58 (whole file, includes the flagged Cargo.lock-reimplementation subset below) |
| Explicit Oven Alpha CLI surface | loaves/toolchain/oven-cli/src/commands/oven.rs |
Textbook match for "Oven CLI... implementation language non-normative," covered by the cache/store/lease/crash-safety exception | 2,465 / 45 |
Oven-shaped commands: lock, init/new, env/version, workspace inspect, vocab companion crate compilation |
loaves/toolchain/oven-cli/src/commands/lock.rs, loaves/toolchain/incan-cli/src/commands/{init,lifecycle,workspace}.rs, loaves/compiler/incan_provider/src/vocab_extraction.rs |
Dependency/lock/registry lifecycle, manifest/workspace selection, environments/project mutation — all named explicitly under "oven" in RFC 118's own command-ownership table | 488/14, 315/16, 103/4, 44/1, 294/14 |
Migration candidates (Incan semantic control)¶
| Component | File(s) | Why it doesn't match the Rust-kernel rule | Lines | Tests (lines/fns) |
|---|---|---|---|---|
| Env overlay resolution | loaves/oven/oven_model/src/project_lifecycle/env.rs |
Pure in-memory config merge; own doc comment already excludes CLI parsing, manifest I/O, filesystem updates | 859 | 475 / 18 |
| Project version bump policy | loaves/oven/oven_model/src/project_lifecycle/version.rs |
Pure SemVer string logic, no I/O | 417 | 103 / 10 |
| Toolchain constraint compatibility | loaves/oven/oven_model/src/project_lifecycle/toolchain.rs |
Pure semver comparison, no I/O | 299 | 57 / 4 |
| Library manifest model, wire format, type refs, validation | loaves/compiler/incan_frontend/src/library_manifest/{model,wire,type_refs,validation}.rs |
Schema/serde/structural validation only; carries artifact digests as opaque strings produced elsewhere (in artifact.rs, which stays Rust) — the identity computation and the schema are already cleanly separated in the code |
3,500 | 0 / 0 ⚠️ — the single largest coverage gap found in this audit |
Manifest (loaf.toml) parsing & shape validation |
loaves/oven/oven_model/src/manifest.rs |
TOML deserialization + deny_unknown_fields + structural checks; sits upstream of the resolver rather than doing resolution |
2,505 | 538 / 28 |
| Workspace member discovery (glob expansion, ancestor-directory walking) | loaves/oven/oven_model/src/workspace.rs (front half) |
Structural data-model construction, same character as manifest parsing — flagged with lower confidence than the rest of this table, see Uncertain section for the counter-argument | ~450 of 2,003 | 566 / 18 (whole file, not separable) |
| Libtest transcript parsing (case counts, timings) | loaves/oven/oven_rustc/src/native_test.rs (parse_libtest_*) |
Pure string/JSON extraction from an already-captured transcript, zero I/O | ~130 | 699 / 19 (whole file, not separable) |
| Rustc diagnostic bounding/rendering | loaves/oven/oven_rustc/src/rustc.rs (OvenRustcDiagnosticReport Display, parse_rustc_diagnostics) |
Presentation/truncation policy over rustc's own diagnostic JSON, no Rust-specific dependency | ~580 | 2,990 / 47 (whole file, not separable) |
| Compiled SDK module inventory | loaves/compiler/incan_provider/src/compiled_sdk.rs |
Pure derived-set query over a decision (ProviderPlan) made elsewhere; module doc says as much directly |
73 | 15 / 1 |
inspect bindings, check/explain, fmt, debug flags, stdlib loader |
loaves/toolchain/incan-cli/src/commands/{binding_inspect,diagnostics,format,debug,stdlib_loader}.rs |
Direct-source/semantic work per RFC 118's own command-ownership table row: "Language services and semantic products → incan" | ~1,744 combined | binding_inspect 0/0 ⚠️, diagnostics 0/0 ⚠️, format 0/0 ⚠️, debug 21/1, stdlib_loader 0/0 ⚠️ |
inspect codegraph, tools metadata (metadata/model portion) |
loaves/toolchain/incan-cli/src/commands/codegraph.rs, loaves/toolchain/oven-cli/src/commands/tools.rs |
Same rule as above | ~2,991 + partial of 2,338 | codegraph 115/3 (thin for its size), tools 508/9 (shared with the doctor portion below, not separable) |
| Test discovery, module graph, reporting, types | loaves/compiler/incan_driver/src/testing/{discovery,module_graph,types}.rs, loaves/toolchain/incan-cli/src/test_runner/reporter.rs |
Semantic source-level test discovery and result presentation, no Oven/project state | ~2,740 combined | discovery 828/33, module_graph 127/3, reporter 0/0 ⚠️, types 0/0 ⚠️ |
Genuinely uncertain — needs an explicit decision, not a default¶
| Component | File(s) | The tension | Tests (lines/fns) |
|---|---|---|---|
| Toolchain self-location (stdlib path resolution) | loaves/oven/oven_model/src/toolchain_layout.rs |
Doesn't match any item on the RFC 118/119 list at all. Plausibly justified by bootstrapping (must run before any Incan runtime is located, needs current_exe/filesystem primitives) — but that justification is not stated anywhere in the file, so per RFC 119's "demonstrated limitation and tracked removal path" clause it should be flagged rather than assumed acceptable. |
328 / 14 |
| Workspace member discovery | loaves/oven/oven_model/src/workspace.rs (front half) |
Structurally similar to manifest parsing (migration candidate), but gates workspace-wide command correctness before any command observes a malformed topology — a plausible reason to keep it Rust-adjacent. Judgment call, not asserted either way. | 566 / 18 (whole file, not separable) |
incan build / incan run / incan inspect rust |
loaves/toolchain/incan-cli/src/commands/build.rs, loaves/compiler/incan_driver/src/build/, loaves/oven/oven_rustc/src/plan.rs |
The original audit found plan selection mixed into the CLI. The CLI now delegates build orchestration to incan_driver; native plan composition and selection live in oven_rustc. This records the settled Rust ownership split, not completion of the separate native-Incan CLI goal. |
Historical: 4,599 / 82 in the original combined file |
| Test harness build/execution | loaves/toolchain/incan-cli/src/test_runner/execution.rs |
Same shim-vs-core blur as build.rs — it does call into Oven's plan/store, but also independently constructs build-unit inputs rather than making one clean delegation call. Decided alongside build.rs in #1094; tracked for implementation by #1095. |
513 / 23 |
incan cache, inspect interop-plan, inspect providers/inspect features |
loaves/toolchain/incan-cli/src/commands/{cache,interop_plan,provider_inspect}.rs |
RFC 118's own command-ownership table places caches/providers/interop-plan facts under oven inspect, not incan inspect — these are Oven-operational facts currently surfaced under the wrong CLI surface. Not a Rust-vs-Incan question; a command-placement question. |
cache 16/2, interop_plan 0/0 ⚠️, provider_inspect 0/0 ⚠️ |
commands/common.rs |
retired | Was a grab-bag straddling both sides. Decomposed along the boundary: module collection, the compilation session, typecheck orchestration, project discovery, Cargo policy, and rust-inspect workspace prep are loaves/compiler/incan_driver/src/*; SDK-store identity, inventory discovery, SDK build, and project requirements are loaves/compiler/incan_provider/src/*. Nothing under loaves/compiler/incan_driver/src or loaves/compiler/incan_provider/src imports crate::cli. |
— |
incan tools doctor |
loaves/toolchain/oven-cli/src/commands/tools.rs (doctor portion) |
Neither semantic nor Oven project/artifact work — installation/toolchain-layout diagnostics. Closest to RFC 118's "Distribution and documentation" layer, which sits outside the Incan-vs-Oven split entirely. | shared 508/9 with the metadata/model portion above, not separable |
| Cargo.lock/manifest reimplementation inside the legacy-Cargo boundary | loaves/oven/oven_cargo_compat/src/lib.rs (locked_local_package, prune_lock_to_package, locked_generated_project*, workspace-inheritance merging — ~950 lines) |
This block hand-parses and hand-writes Cargo.lock/Cargo.toml content and reimplements Cargo's own workspace-dependency-inheritance merging in Rust, before re-invoking Cargo to "normalize" the result. The validation half (confirming Cargo's output matches a pinned release graph) is legitimate policy per RFC 118. The construction half sits in tension with RFC 119's explicit statement that Oven must not "reinterpret Cargo results as an Oven-native lock." Needs a narrowing decision, not a default. |
3,966 / 58 (whole file, not separable) |
| LSP service preparation | loaves/toolchain/incan-lsp/src/backend.rs, loaves/compiler/incan_driver/src/rust_inspect_workspace.rs |
The original audit found LSP calls into CLI-owned setup. The LSP now imports driver session, project discovery, Cargo policy and Rust-inspect workspace services. Keep this shared preparation in the driver; do not recreate a dependency on command handlers. | Historical: 7,027 / 48 in the original backend file |
Compiler-service exception (out of scope for the Incan-vs-Oven axis)¶
Confirmed legitimately Rust, but not because of the Oven-core exception — this is the separate, already-accepted "the compiler itself is written in Rust" exception (AGENTS.md), covering semantic analysis rather than project/build orchestration.
| Component | File(s) | Tests (lines/fns) |
|---|---|---|
| LSP protocol implementation, diagnostics conversion, call-site generic-arg helpers | loaves/toolchain/incan-lsp/src/{lib,diagnostics,call_site_type_args,backend}.rs (with service preparation described above) |
diagnostics 78/4, call_site_type_args 47/4, backend 7,027/48 (whole file) |
| Codegraph record schema | loaves/kernel/incan_codegraph/src/lib.rs — explicitly disclaims orchestration in its own README |
78 / 2 |
| Rust-inspect (rust-analyzer embedding for interop metadata) | loaves/compiler/rust_inspect/src/ — inherently Rust (wraps ra_ap_hir), and its loader.rs shows the correct trust direction: it defers to Oven's already-verified "sealed" source selection rather than re-deciding it |
historical inspector entry point 144/2, loader.rs 364/9, extractor.rs 362/9, cache.rs see note below, cache_resolve.rs/generic_params.rs/cache_timing.rs/error.rs 0/0 (small, mechanical, low individual risk) |
| Surface semantics registry | loaves/compiler/incan_frontend/src/semantics_registry.rs — typechecker/IR-lowering plumbing, not on the Oven/CLI axis at all |
0 / 0 (24-line trivial glue, low individual risk) |
Historical test coverage¶
Recorded per #871's own required field ("public APIs, required capabilities, receipts, invariants, migration status, tests, and responsible delivery issue for every component"). Numbers above are in-file #[cfg(test)] mod tests line counts and #[test]-annotated function counts, mechanically grepped against every file in this audit — a presence/scale signal, not a test-quality judgment. A ⚠️ marks zero in-file unit tests found.
Cross-cutting integration coverage exists alongside the in-file numbers above and may cover some of the flagged files even without in-file unit tests: loaves/compiler/incan_oven_facet/tests/oven_pr_regressions.rs, loaves/toolchain/incan-cli/tests/toolchain_installer_tests.rs, and five loaves/compiler/incan_test_support/fixtures/oven_* fixture directories. This audit did not trace which specific files each integration test actually exercises — that would be a separate, deeper pass. Treat the ⚠️ rows below as "no unit-level safety net found in the file itself, verify integration coverage before touching," not as "definitely untested."
One correction against a false positive: loaves/compiler/rust_inspect/src/cache.rs (4,792 lines) greps as having no in-file test module, but its real test coverage lives in a separate cache_tests.rs file (1,756 lines) that this audit was explicitly told to skip when scoping the LSP/codegraph track. It is not a coverage gap — just a different test-file convention than the mod tests pattern used everywhere else in this codebase.
Risks identified by the original audit, to re-check before migration:
library_manifest/{model,wire,type_refs,validation}.rs(3,500 lines, migration candidate, 0 tests). This is the one finding that should change how #1034's work gets sequenced — migrating a 3,500-line, schema/validation layer without in-file tests at the audit baseline with no existing safety net is materially riskier than migrating a well-tested one. Writing characterization tests against current behavior before migrating this block is worth calling out explicitly as prerequisite work, not assumed away.loaves/oven/oven_store/src/process.rs(0 tests) andloaves/oven/oven_model/src/compiler_suite_env.rs(0 tests) — both confirmed Rust host kernel, not migration candidates, but untested low-level OS process/policy code is its own risk category worth someone's attention independent of this migration effort.- A cluster of already-thin CLI commands with zero in-file tests:
binding_inspect.rs,diagnostics.rs,format.rs,stdlib_loader.rs,interop_plan.rs,provider_inspect.rs,reporter.rs,types.rs. Several of these (check/explain,fmt) plausibly have snapshot/integration coverage elsewhere per CONTRIBUTING.md's property-testing section — worth confirming rather than assuming, given they showed up as zero here.
Structural note: the CLI split itself¶
loaves/toolchain/incan-cli/src/lib.rs currently implements a single, universal incan CLI — every Oven-shaped command (init, new, lock, env, workspace, cache, oven ...) is nested under the incan binary today, which is the exact shape RFC 118's "Alternatives considered" section rejects as the wrong end-state ("collapses language semantics, project mutation, cache/store ownership, registry trust... into one ambiguous command family"). This matches RFC 118's own stated release boundary — v0.5 does not backport the two-surface incan/oven split, which targets v0.7 — so it is not a defect this map is flagging as new. It's registered here because it's the container every "Oven CLI (currently under incan)" row above will eventually be carved out of.
Done-when checklist (per #871)¶
- Every supported responsibility has one classification and one rationale, recorded above.
- Tests recorded per component (in-file unit-test presence, mechanically verified) — see "Test coverage."
- One linked acceptance path per responsibility — Done. The confirmed-kernel and compiler-service-exception rows don't need one (no migration implied). Every migration-candidate and uncertain row now has its own delivery issue, filed as a native GitHub sub-issue of #1034: #1081-#1091 cover the straightforward migration candidates, and #1092-#1100 cover the rows that need an explicit maintainer decision before implementation can be scoped (e.g. #1099 for the
legacy_cargo.rsCargo.lock reimplementation, #1100 for the LSP-to-CLI boundary crossing inlsp/backend.rs, #1094/#1095 for thebuild.rsshim-vs-core blur). - The map demonstrates Rust is a bounded host kernel and Incan owns the semantic control plane — confirmed for the large majority of the audited surface; the exceptions and tensions are named explicitly above rather than smoothed over.