Skip to content

Authoring Assemblies and Modules

Unified Artifact Assembly (UAA) composes deployable output from small, versioned building blocks. A module is one addressable contribution (a file, a named section inside a file, or a directory tree). An assembly is a graph of modules plus the presets and rules that decide, at resolution time, which modules are selected and how their content is bound and merged. This guide covers how to author both, and where authoring happens (CLI, API, or the web workspace).

Definition kinds and qualified identity

Every UAA definition — assembly, module, preset, or rule-set — is identified by a qualified ref in the form <source>:<identity>. source is always one of four values:

Source Meaning Where it lives
builtin Compiled into SkillMeat itself Packaged resources, read-only
user Authored by you, shared across all your projects ~/.skillmeat/ definitions
project Authored for one project ./.skillmeat/*.toml
managed Owned by the database (via the API/CLI, or translated from a legacy template/composite) Local SQLite or enterprise PostgreSQL

builtin/user/project definitions are TOML files you author directly. managed definitions are created and updated through the API/CLI (create, update, import) and are the kind you get back from assembly create without a --file/TOML source, and from the legacy compatibility adapters (see Migration & Compatibility).

Modules

A ModuleDefinition is the smallest addressable contribution:

  • qualified_ref — its own identity, e.g. managed:module/my-skill-section.
  • source_artifact_uuid — the stable artifacts.uuid of the artifact this module's content comes from. Every module traces back to a real artifact; there is no free-floating inline content.
  • module_kind — one of section (a named region inside one file), file (one complete or partially managed file), or tree (a deterministic set of files/directories).
  • output_claims — one or more {path, strategy, order} entries declaring where this module writes and how it merges with anything already at that path. strategy is one of create, replace, managed_block, append_unique, or adapter (invokes a named, allowlisted materialization adapter — see the target-adapter list in Editions).

Assemblies

An AssemblySpec is the graph that ties modules together:

  • root_module_refs — the module refs selected by default.
  • module_edges{child_ref, version_selector, required, order} entries describing the dependency/placement graph (this is what P4 graph selection and ordering reads; output_claims on each module is what actually drives where content is written).
  • slots — named extension points other modules or rules can target.
  • rule_set_refs — rule-sets that can conditionally include/exclude modules or set parameters at resolution time (see Presets & Rules).
  • supported_target_refs — which deployment targets this assembly is valid for.

Authoring via CLI

skillmeat assembly is a thin HTTP client — every command below is a wrapper over /api/v1/assemblies/*; there is no separate CLI-only logic.

# List existing definitions of a kind (assembly is the default kind)
skillmeat assembly list --kind module --format json

# Validate a draft without persisting it
skillmeat assembly validate --kind module --file my-module.json

# Create it for real
skillmeat assembly create --kind module --file my-module.json

# Create the parent assembly, referencing the module by its qualified_ref
skillmeat assembly create --kind assembly --file my-assembly.json

# Show what was stored
skillmeat assembly show managed:assembly/my-assembly --format json

A minimal module body (my-module.json):

{
  "qualified_ref": "managed:module/hello-section",
  "source_artifact_uuid": "3f9c9e2a-...-uuid-of-an-existing-artifact",
  "module_kind": "file",
  "source_version_selector": "sha256:<hex-of-the-artifact-content>",
  "output_claims": [
    {"path": "AGENTS.md", "strategy": "create", "order": 0}
  ]
}

A minimal assembly body (my-assembly.json) referencing it:

{
  "qualified_ref": "managed:assembly/my-assembly",
  "root_module_refs": ["managed:module/hello-section"],
  "module_edges": [
    {"child_ref": "managed:module/hello-section", "version_selector": "sha256:<same-hex>", "required": true, "order": 0}
  ]
}

--set KEY=VALUE layers ad-hoc overrides on top of --file (or in place of it) for both create and update; values are JSON-decoded when possible (--set required=false becomes a boolean, --set order=2 becomes an int).

Updates and deletes use optimistic concurrency — skillmeat assembly show first to read the current etag, then pass it back:

skillmeat assembly update managed:module/hello-section --kind module \
  --expected-etag "$(skillmeat assembly show managed:module/hello-section --kind module --format json | jq -r .etag)" \
  --set "output_claims=[{\"path\":\"AGENTS.md\",\"strategy\":\"replace\",\"order\":0}]"

For TOML-authored (builtin/user/project) definitions, use skillmeat assembly export/import instead of create/update — export round-trips a stored definition to a TOML file you can hand-edit and commit.

Authoring in the web workspace

The Assembly workspace (/assemblies in the web UI) provides a graphical alternative to hand-writing JSON/TOML:

  • A list/detail shell for browsing existing assemblies, modules, presets, and rule-sets.
  • A graph editor (and an equivalent flat-list editor) for wiring root_module_refs/module_edges without hand-computing ordering.
  • Explainability panels that surface the same resolve/preview output the API returns — selected/excluded modules with exclusion reasons, binding provenance, rule decisions, and conflicts — so you can see why a module was or wasn't selected before you apply.
  • A preview/apply flow bound to the same digest-gated contract the CLI and API use (see Lock & Replay) — nothing in the workspace bypasses resolve/preview/apply.

Bounds you'll hit

Authoring is governed by the same policy ceilings the API enforces server-side (GET /api/v1/settings/assembly reports the fully-resolved values for your deployment): a builtin default of 12 for max module-graph depth, 200 for max selected modules per resolution, and 2 MiB for one module's rendered content. An enterprise deployment or your own ~/.skillmeat/config.toml/./.skillmeat/config.toml [assembly] table can narrow these further (never raise them) — see Editions for the full precedence chain.