Project Resolution
This document defines how module paths are resolved, how the project graph is built from Project.proj, and how imports are validated.
It also defines the build/run dependency lifecycle used by CLI commands:
- Discover manifest.
- Resolve project DAG.
- Sync
Project.lock. - Materialize dependency sources under
obj/beskid. - Build in dependency-first order.
- Run selected target.
Graph implementation: daggy (Dag<ProjectNode, DependencyEdge>), with petgraph traversal utilities available through Daggy re-exports when needed.
Terminology
Section titled “Terminology”- Project root: directory containing
Project.proj. - Source root:
project.rootfield insideProject.proj(defaultSrc). - Module path: dotted path like
Net.Http.
Project Graph Construction
Section titled “Project Graph Construction”- Start at the root project
Project.proj. - Parse manifest to collect project identity, targets, and dependencies.
- Canonicalize manifest path and intern a node key for the root project.
- For each dependency, create an edge from consumer project -> dependency project.
- For
source = "path", resolve and recursively load dependency manifests. - For providers that are not enabled in current runtime scope (
git,registryin v1), fail resolution with provider diagnostics. - Reject cycles at edge insertion time and report chain.
Provider Scope (v1)
Section titled “Provider Scope (v1)”- Enabled provider:
path. - Deferred providers with reserved infrastructure:
git,registry. - Policy: build/run never proceeds with unresolved external dependency nodes.
Daggy Node and Edge Model
Section titled “Daggy Node and Edge Model”- ProjectNode
- Root project node
- Resolved local path dependency node
- Unresolved git dependency node
- Unresolved registry dependency node
- DependencyEdge
- dependency alias (
dependency "Name"label) - source kind (
path/git/registry) - raw source metadata for diagnostics
- dependency alias (
The graph keeps project identity canonicalized by manifest path to prevent duplicated nodes for equivalent relative paths.
Deterministic Build Projection
Section titled “Deterministic Build Projection”- Derive compile order from the project DAG in deterministic topological order.
- Dependencies are emitted before dependents.
- Stable tie-break for same-rank nodes: canonical manifest path lexical order.
- The projected ordered compile units are consumed by CLI and analysis pipelines.
Unresolved Dependency Policy (v1)
Section titled “Unresolved Dependency Policy (v1)”path: must resolve to an existingProject.proj; otherwise error.git/registry: provider-disabled in runtime scope; must fail before compile.- Build/run does not continue past resolution stage when any dependency is unresolved.
Materialization and Build Staging
Section titled “Materialization and Build Staging”Before build or run:
- Resolve all path dependencies transitively.
- Copy dependency source trees into
obj/beskid/deps/src/<PackageId>. - Copy policy: copy when source file timestamp is newer than materialized file.
- Use materialized source roots for compile units.
Build outputs and state directories:
obj/beskid/deps/src/- materialized dependency sources.obj/beskid/build/- compilation outputs by profile/target.obj/beskid/state/- resolver and lock sync metadata.
Lockfile Lifecycle
Section titled “Lockfile Lifecycle”- Lockfile path:
Project.lockat project root. - Lockfile is created automatically when missing during resolve/build/run.
- Lockfile is updated automatically when dependency graph changes.
- Future strict flags (
--frozen,--locked) can tighten this behavior without changing lifecycle stages.
File-to-Module Mapping
Section titled “File-to-Module Mapping”- File
Src/Net/Http.bdmaps to module pathNet.Http. - The file path relative to
rootdetermines the module path. - The last segment is the module name (file stem).
Resolution Order (name lookup)
Section titled “Resolution Order (name lookup)”For identifiers and paths inside a module:
- Local scope (params, let bindings).
- Enclosing scopes.
- Imports (
usealiases). - Module-level items.
This order is consistent with docs/spec/name-resolution.md.
Module Graph (Inferred)
Section titled “Module Graph (Inferred)”The module graph is inferred from mod declarations and file layout. The manifest does not list modules explicitly.
mod Declarations
Section titled “mod Declarations”mod Net;declares a submodule.- The compiler searches for
root/Net.bdorroot/Net/Mod.bd(configurable). - Error if not found.
use Imports
Section titled “use Imports”use Net.Http.Client;resolves against the module graph.- If multiple imports provide the same name without aliasing, emit
AmbiguousImport.
Visibility
Section titled “Visibility”- Items are private by default.
pubitems are visible across modules.- Access to non-
pubsymbols from another module is an error.
Error Conditions
Section titled “Error Conditions”- Missing
Project.proj. - Duplicate project names in dependency graph.
- Project cycles.
- Missing path dependency manifest.
- Provider-disabled dependency source in active runtime scope.
- Lockfile read/parse/update mismatch errors.
- Materialization copy failures.
- Import path not found.
- Visibility violations.
- Ambiguous imports.
Manifest-specific error conditions
Section titled “Manifest-specific error conditions”- Unknown
sourcekind independencyblock. - Missing
entryintargetblock. - Target entry path outside source root.
- Duplicate target names.
Future Extensions
Section titled “Future Extensions”- Virtual modules for generated code.
- Workspace manifests (
Workspace.proj) for monorepo builds. - Registry lockfile integration.
Standard Library (Std) Graph Behavior
Section titled “Standard Library (Std) Graph Behavior”Stdis treated as a normal dependency node in the project DAG.- If a resolvable
Stddependency node exists, stdlib prelude fallback injection must be disabled. - Feature-gated fallback remains only as a compatibility path when no resolvable
Stdnode is present.