Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

RFD-0032 — Shared-base package classification for workspace-vendored deps

Accepted Opened 2026-05-06 · Status: Accepted (Phase 1)

Question

When a customer overlay vendors a foundational package (UFO, std, …) as a workspace member instead of pulling it from the registry, how does the bundle assembler classify that member so the kernel-side compile path treats it as SharedBaseProvided rather than as a tenant-emitted overlay?

Context

The oxc_runtime::PackageRole enum has four variants — Root, WorkspaceMember, Dependency, SharedBaseProvided. The kernel-side compile pipeline (kernel/api/src/v2/schema/compile.rs) filters emit output for SharedBaseProvided packages so their declarations don’t land as tenant axioms — the kernel’s base tenant (SHARED_BASE_TENANT_ID) carries equivalent declarations already, and per-tenant duplication would shadow-collide on reload (OE7062).

The classification happens in argon/ox/src/bundle.rs::build_virtual_source_bundle. Before this RFD it consulted BundleBuildOptions::shared_base_policy only for locked external deps — packages installed into ~/.argon/packages/ and pinned in ox.lock. Workspace members got Root (for the package being compiled) or WorkspaceMember (for siblings) regardless of policy.

That left a gap for codebases that vendor foundational packages as workspace members:

  • The Sharpe internal overlay (sharpe-ontology) keeps UFO source as a sibling workspace member of the customer’s domain package. Hand-authoring UFO concepts inside the same workspace is convenient; pulling UFO from the registry would force a publish-rebuild loop on every UFO edit.
  • The Argon examples/lease-story demo vendors UFO + economic-foundation packages as workspace members for similar reasons.

Without the workspace-member policy consult, both setups end up uploading UFO twice: once via the bundle (as WorkspaceMember, emit-output stored as overlay axioms), and once into the kernel’s base tenant via the out-of-band base-loader path. The second store wins on read but pollutes the overlay’s storage and triggers shadow-collision warnings.

Workarounds before this RFD:

  • Drop the foundational package from the workspace and pin it as a registry dep instead. Defeats the “edit UFO inline” workflow.
  • Manually massage the bundle’s PackageRole after the fact. Bypasses the public API; brittle.
  • Live with the duplicate-emit cost. What the customer overlay was effectively doing.

Decision

build_virtual_source_bundle consults BundleBuildOptions::shared_base_policy for non-Root workspace members. Role precedence becomes:

  1. Root — the package the bundle is centered on (selection target). Always Root regardless of policy. A modeler editing UFO directly inside a workspace where they own UFO’s source is the package’s author — they want emit output back from the kernel.
  2. SharedBaseProvided — non-Root members whose canonical name matches policy.is_shared_base_provided(name). The kernel filters their emit; the kernel base provides equivalent declarations.
  3. WorkspaceMember — every other non-Root member.

The default BundleBuildOptions::default() constructs an empty policy, so codebases that have not opted in keep the prior WorkspaceMember classification. BundleBuildOptions::kernel_v2() (used by first-party loaders for the kernel-api v2 endpoint) seeds the policy with the kernel’s authoritative shared-base list (std, ufo, core, coex, cofris, ccf).

Locked-dep classification is unchanged — Arm 1 (workspace member root precedence) does not apply to lockfile packages, and the existing locked-dep path already consults the policy.

Consequences

For modelers. Customer overlays that vendor UFO as a workspace member now have UFO classified as SharedBaseProvided automatically, when uploading through a first-party loader. No bundle-level surgery, no manual policy override per call site.

For codebases on BundleBuildOptions::default(). No change. Empty policy preserves the prior classification.

For examples/lease-story. Loaders using BundleBuildOptions::kernel_v2() will now classify lease-story’s vendored ufo / coex / cofris / ccf as SharedBaseProvided. The kernel filter strips their emit — matches the existing locked-dep behavior. Lease-story’s local-toolchain-only tests (which don’t involve the kernel) are unaffected.

For the LSP and InfoView. The LSP doesn’t run the bundle assembler; this change is invisible to editor-side resolution. Only the kernel-upload path sees the new classification.

Implementation

Landed on kernel/base-schema-compile-resolution (Phase 1). Changes:

  • argon/ox/src/bundle.rs::build_virtual_source_bundle — workspace-member role assignment now consults options.shared_base_policy. Same precedence for Root. New SharedBaseProvided arm for non-Root members.
  • argon/ox/src/bundle.rs::tests — three new tests covering (a) workspace-member shared-base classification, (b) Root precedence over policy, (c) empty-policy backwards-compat.

No changes to public API. No changes to wire format. No changes to the policy endpoint or storage layer.

Phase 2 (planned, separate RFD)

The kernel-side base loader has loose ends that this RFD does not address:

  • Source-of-truth coupling. The hardcoded SHARED_BASE_PROVIDED_PACKAGES list in kernel/api/src/v2/schema/package_policy.rs does not consult the actual base-tenant content. A customer who renames or repartitions UFO would have to update the kernel binary’s policy list to match — coupling at compile time when the kernel and customer overlays could be on different release cadences. The fix is for the policy endpoint to read the live base-tenant package metadata.
  • Argon-source base loading. The current base loader (orca-db-resetkernel/owl-loader) loads UFO from OWL2 EL++ Turtle files. A future Phase 2 ships a canonical Argon-source UFO package, compiles it kernel-side at DB-reset time, and stores axioms under SHARED_BASE_TENANT_ID directly from CoreModule. Drops a translation layer; aligns content-hash provenance.
  • Customer override. A customer who wants a different UFO variant (or a non-default foundational stack) needs a way to pin it. The natural surface is a per-tenant config row that overrides the default base packages; the kernel’s policy endpoint then returns the per-tenant overrides instead of the global default.

These are tracked as RFD-0033 (planned).

Open questions

  • What should BundleBuildOptions::default() ship with? Today it returns an empty policy, which preserves backwards-compat. The argument for changing the default to SharedBasePolicy::kernel_v2() is that it’s the right thing for the dominant first-party-loader case. The argument against is silent-behavior-change for any third-party code consuming bundle::build_virtual_source_bundle directly. Phase 1 keeps the conservative empty default; revisit when Phase 2 lands.
  • Should SharedBasePolicy::kernel_v2() continue to be a hardcoded list, or read from a feed? Hardcoded works while the base content is stable. A feed (e.g., served by the kernel-api alongside the policy endpoint) lets the kernel evolve the base without forcing a toolchain rebuild on every consumer. Tracked alongside the policy endpoint redesign in Phase 2.