synps.toml reference

synps.toml describes both reusable packages and root applications. The same manifest vocabulary covers source components, dependencies, toolchains, build domains, compiler policy, weights, and deployable entrypoints.

All paths are relative to the manifest that declares them unless noted otherwise.

Minimal package metadata

[package]
name = "example"
version = "0.1.0"
description = "Optional short description"

package.name and package.version are required. include_directories may add package-level include paths.

[layout]

The default project directories are:

src/
include/
assets/
tests/
examples/

Override them when a repository uses another layout:

[layout]
sources = "source"
includes = "public"
assets = "resources"
tests = "test"
examples = "examples"

[dependencies]

A dependency selects exactly one source form.

[dependencies]
local_codec = { path = "../Quantizations/F16" }
model = { git = "https://github.com/useplx/Qwen3.5.git", version = "v1.0.0" }

Supported forms:

Form Fields
Local path
Git git, optionally rev or version, and optionally subdir
Registry version string/table syntax is parsed, but registry resolution is currently unavailable

The table key is the dependency alias used by package configuration and cross-package references.

[toolchain.<language>.<domain>.<labels>]

[toolchain.cpp.native.aarch64]
compiler = "aarch64-linux-gnu-g++"
flags = ["-O3"]

Fields:

Field Required Meaning
compiler no compiler executable/path
linker no linker executable/path
archiver no archive executable/path
triple no target triple passed by the language driver
flags no additional compiler arguments

Toolchain strings support ~/, ${NAME}, and ${NAME:-fallback} expansion.

The first path component is the language. The optional domain is graph, orchestration, or native; additional labels such as an architecture refine selection. Child tables inherit the fields of their parent. A * label is a fallback for any target.

[build.<domain>]

Build domains declare the artifacts produced by the package.

[build.graph]
toolchain = "cpp"
namespace = "example"
sources = ["src/model.cpp"]
exports = ["model"]

[build.orchestration]
toolchain = "cpp"
sources = ["src/application.cpp"]

[build.native]
toolchain = "cpp"
sources = ["src/tokenizer.cpp"]

Canonical domains are graph, orchestration, native, and driver. Their physical outputs are respectively an IREE compiler plugin, a Wasm module, a native provider, and a runtime driver. Native providers and drivers are both shared libraries, but expose different versioned ABIs.

When a package has several artifacts in one domain, add a stable label:

[build.native.tokenizer]
toolchain = "cpp"
sources = ["src/tokenizer.cpp"]

[build.native.index]
toolchain = "rust"
artifact = "libindex.a"
sources = ["src/index/Cargo.toml"]

Build fields

A project may contain several independently built components:

[build.graph.model]
namespace = "example"
toolchain = "cpp"
sources = ["src/model.cpp"]
includes = ["include"]
exports = ["model"]

[build.orchestration.application]
toolchain = "cpp"
sources = ["src/application.cpp"]

[build.native.tokenizer]
toolchain = "cpp"
sources = ["src/tokenizer.cpp"]
libraries = ["utf8proc"]

Supported fields:

namespace · toolchain · artifact · sources · includes · libraries · defines · library_directories · exports · uses · extends

The build domain determines the runtime. artifact = "*.a" marks a private static-library input: it may be referenced through uses but is not embedded as a loadable runtime provider.

exports lists symbols registered by a build-time graph package, for example graph modules, codecs, hooks, or compatibility objects. It does not configure Native provider symbols or Wasm module exports. Orchestration exposes the implicit forward entrypoint; runtime hooks refer to that export unless an explicit export is provided by the artifact plan.

extends composes another build-package definition. uses links the artifact produced by another build package.

Capabilities and bindings

Reusable packages can declare abstract composition requirements:

[capabilities]
provides = ["generator"]
requires = ["tokenizer"]

If multiple dependencies provide the same required capability, the root project selects one:

[bindings]
tokenizer = "text-tools"

The binding value is a dependency/package alias.

Package variables

A package publishes its configurable values under [package.variables]:

[package.variables]
context = { type = "uint32", default = 2048, min = 1, define = "MODEL_CONTEXT", facets = ["graph", "orchestration"] }
trace = { type = "boolean", default = false, define = "MODEL_TRACE", facets = ["orchestration"] }

Accepted type names are:

string · boolean/bool · integer/int64 · uint32 · float/number · array · table

A schema may use default, required, and numeric min/max constraints. define supplies a scalar value to compiled source. facets optionally limits that definition to named build-package facets; without it, the definition is available to every facet for compatibility. The root configures a direct dependency with:

[packages.model]
context = 4096

Unknown package variables and incompatible values are rejected. facets must be an array of strings.

[weights]

Select exactly one of path or paths:

[weights]
path = "${MODEL_DIR}/model.safetensors"

or:

[weights]
paths = [
  "weights/model-00001-of-00002.safetensors",
  "weights/model-00002-of-00002.safetensors",
]

paths must not be empty. Environment references must resolve.

[scheduling]

Scheduling expresses a high-level compilation preference. It does not select passes or create a PLeX scheduler.

[scheduling]
favor = "min-memory"

Accepted values are:

Value Meaning
min-memory Minimize overlapping live allocations; this is the default.
max-concurrency Expose more independent work to the device at the cost of peak memory.
debug Prefer deterministic, minimally partitioned execution for diagnosis.

The compiler translates this intent to IREE Stream partitioning. Device placement remains controlled by backend policies, and Stream remains responsible for dependencies, transfers and resource lifetime.

Policy loading

Loading policy is independent from dtype, codec and backend placement:

[policies."model.layers.*".loading]
mode = "streamed"
Mode Meaning
resident Retain mapped parameter pages between invocations.
streamed Load through IREE IO Parameters and allow the mapped pages to be discarded after the owning graph scope completes.

Both modes use IREE parameter providers and Stream parameter operations. The difference is host archive residency, not a separate transfer engine. The legacy volatile field inside a scheme remains readable for compatibility; an explicit loading policy takes precedence. cached and prefetch are not accepted yet because this pinned IREE revision does not provide generic LRU policy semantics, and PLeX does not create a parallel prefetch runtime.

[myelin]

[myelin] currently carries global compiler input-format requirements:

[myelin]
formats = ["f16"]

formats names codec exports needed to read/interpret source checkpoint representations even when the deployment policy does not otherwise select that codec.

Policies

Policies are keyed by graph path and inherit from broader paths to more specific ones.

[policies."model"]
dtype = "f16"

[policies."model".backend]
device = "local"

[[policies."model".schemes]]
format = "f16"

Policy fields

Field Meaning
dtype Compute/exposed tensor dtype.
backend.device Target device alias such as local, cuda, or vulkan.
backend.ordinal Optional device ordinal.
backend.flags Backend-specific compiler flags.
optimization_barrier Prevent selected compile-time folding/optimization across the path.
schemes Storage/codec schemes attached to the path.

volatilized has been removed. It previously acted as a misleading alias for optimization_barrier and never controlled memory residency. Weight residency belongs to each scheme through volatile.

Supported dtype spellings are f32, f16, i32, i16, i8, i4, u32, u8, and u4.

Scheme fields

Each scheme requires format. For the currently implemented weight-storage contract, scope, lifetime, and update default to constant, immutable, and none.

[[policies."model.layers.*.mlp.down_proj.weight".schemes]]
format = "q4k"
volatile = true
Field Default Meaning
format required Codec used for persisted bytes.
scope constant Value class matched by the scheme.
lifetime immutable Logical lifetime of the value.
update none Allowed update mode.
volatile false Discard clean host pages after invocation while preserving the package mapping.

volatile = true does not evict device memory and does not make a weight mutable. On a host backend, a later access can fault discarded pages back from the package. The Runtime keeps the mapping valid because IREE parameter providers and VM bytecode retain non-owning views into it.

The current Compiler executes constant/immutable schemes. Invocation- and session-lifetime codec storage remains reserved by the shared contract and is rejected until its runtime semantics are implemented.

Codec references may be qualified as package:export. A bare name can resolve to a homonymous package export when unambiguous.

Generic policy does not define codec-owned keys such as block size, granularity, storage layout, rounding, saturation, or arbitrary parameter maps. Those decisions belong to the codec implementation.

Root policy

A deployable compiler plan requires a root policy with a dtype and a scheme capable of covering immutable constant weights. This makes the default deployment behavior explicit before path-specific overrides are applied.

[entrypoint]

[package]
name = "app"

[entrypoint]
package = "model"

package is the root package name or a direct dependency alias. The selected package must provide a usable entrypoint facet. SYNaPSe derives it in this order: an Orchestration build (Wasm), otherwise a Native build, otherwise a Graph build. For Orchestration and Native, the public forward entrypoint is implicit. A Graph-only package exposes its surviving logical graph path as the entrypoint. Graph exports are discovered from their SDK types, and graph modules own their input specializations.

The current entrypoint resolver looks for the unlabelled [build.orchestration], [build.native], and [build.graph] facets. A package that only declares a labelled facet such as [build.native.tokenizer] does not provide an application entrypoint through that facet; keep the entrypoint component under the canonical unlabelled domain table.

Composition-only packages may omit [entrypoint]. The current graph package adapter supports specialization arities of 1, 2, 3, 4, or 6 tensor inputs.

A deployable root package must select one public entrypoint. The current compiler requires at least one specialization for a graph entrypoint.

[[hooks]]

Graph hooks transform a module boundary during compilation:

[[hooks]]
path = "model.layers.*.attention"
function = "extension:attention-hook"

* matches one path segment. SYNaPSe recognizes this as a graph hook because the referenced facet is a build-time package.

Runtime hooks transform the Buffer entering a represented path:

[[hooks]]
package = "qwen"
path = "qwen3.5"
function = "rag:augmentation"

package must name the root package or one of its direct dependencies and says which composed piece owns the intercepted route. path selects the represented route. function always identifies a package facet. An orchestration facet exports the implicit forward and becomes a runtime hook; a build-time facet becomes a graph hook. Runtime hooks run in declaration order. Direct calls that are not represented as paths do not pass through this router.

Validation workflow

Use the cheapest validation step that answers the question:

synps graph     # dependencies and capability bindings
synps inspect   # effective Compiler and build plan
synps build     # compile and package the artifact

See Diagnostics for diagnostic-code families and Build workflow for ordering.