Weld is graph-first. Generated files are an output of the graph and plan, not the primary internal model.

Core Stages

  1. Weld.Manifest loads and validates a repo-local manifest.
  2. Weld.Workspace.Discovery finds projects from manifest globs, blitz_workspace, or filesystem fallback.
  3. Weld.Workspace loads each Mix project sequentially and normalizes dependencies.
  4. Weld.Graph stores project nodes, classified edges, publication roles, external deps, and violations.
  5. Weld.Plan resolves one artifact boundary and computes the selected closure.
  6. Weld.Projector generates the standalone Mix project (routing to Weld.Projector.Monolith for monolith artifacts), merged application module when needed, and lockfile.
  7. Weld.Verifier validates the generated project using a mode-specific gate.
  8. Weld.Release prepares and archives deterministic release bundles.

Graph Model

Projects are classified independently from publication role.

Classification:

  • :runtime
  • :tooling
  • :proof
  • :ignored

Publication role:

  • :default
  • :internal_only
  • :separate
  • {:optional, feature_id}

Internal edges are classified by execution meaning:

  • :runtime
  • :compile
  • :test
  • :docs
  • :tooling
  • :dev_only

Views such as :package, :test, and :docs are computed by filtering those edge kinds.

External dependencies are also normalized. If a selected workspace project refers to an external package through :path, :git, or :github, the manifest must declare the canonical publishable dependency shape. The graph and plan operate on that normalized external edge, not the local transport detail. Dependencies without a version requirement are permitted when opts includes :git or :github.

Projection Modes

Package-Projection Mode (default)

Artifacts with mode: :package_projection (or no mode key) generate a component-preserving layout under dist/hex/<package>/:

dist/hex/<package>/
  mix.exs
  projection.lock.json
  lib/<otp_app>/application.ex
  components/
    apps/core/
    apps/web/
    core/contracts/
  test/

This keeps the source graph legible inside the generated package without turning the output into a second hand-maintained source tree.

Monolith Mode

Artifacts with mode: :monolith merge all selected packages into a single flat project under dist/monolith/<package>/:

dist/monolith/<package>/
  mix.exs
  projection.lock.json
  lib/<otp_app>/application.ex
  lib/
    (merged sources from all selected packages)
  test/
    <package_slug>/
      (tests per selected package)
    support/
      <package_slug>/
        (test support per selected package)
      weld_helpers/
        <slug>_test_helper.exs
  config/
    config.exs
    dev.exs / test.exs / prod.exs
    sources/
      <slug>/config.exs  (sanitized: workspace-app config calls stripped)
    runtime_sources/
      <slug>/config.exs  (original, used at runtime bootstrap)
  priv/
    repo/migrations/          (single-repo layout)
    weld_repos/<slug>/        (multi-repo layout)

Key behaviors in monolith mode:

  • File merging: conflicting source files are renamed with a <slug>__ prefix. A file_remaps list in the projection result records all renames.
  • Config sanitization: static config copies strip workspace-app config calls so they do not interfere with the merged config tree. Original files are kept under runtime_sources/ for bootstrap reads at startup.
  • Migration merging: migrations with the same timestamp prefix are re-stamped with a deterministic offset derived from project_id, filename, and sort index. A .weld_remap.json records any renames.
  • Test helper synthesis: each selected package's test_helper.exs is parsed, ExUnit.start calls are extracted and merged, and a root test/test_helper.exs is generated that dispatches to per-package helper fragments.
  • Explicit source-only test support: when monolith tests depend on non-selected workspace projects, monolith_opts[:test_support_projects] turns that source-only support set into an explicit manifest contract and the copied support code is staged under test/support/weld_projects/.
  • Monolith application module: the generated Application module bootstraps per-package config at startup using Config.Reader.read_imports! before starting any OTP application children, and the bootstrap app allowlist is derived only from staged bootstrap sources.
  • Test baseline gate: verification runs each selected package's own test suite first, then asserts the monolith test count is at least the baseline sum.

Constraints

  • project probing stays sequential because Mix.Project.in_project/4 mutates global Mix state
  • file copying and verification are deterministic
  • publish-unsafe external transports must be rewritten through manifest dependency declarations
  • the generated artifact is normal Mix, not a custom runtime
  • monolith mode rejects source files that use Application.ensure_all_started/1 or Application.app_dir/1 targeting a selected package's OTP app, as these assume standalone package identity that is lost in the merge