Assembly Presets and Rules¶
Presets and rules are how an assembly's module selection and parameter bindings adapt to context — target platform, project type, or explicit invocation choices — without hand-editing the assembly itself for every situation.
Presets and qualified identity¶
A PresetDefinition is a named, inheritable bundle of parameter bindings.
Like every other UAA definition it uses the four-source qualified ref
convention:
builtin:<name>— shipped with SkillMeat.user:<name>— authored in~/.skillmeat/for use across your projects.project:<name>— authored in./.skillmeat/*.tomlfor one project.managed:<id>— created via the API/CLI or by a legacy compatibility adapter, stored in the database (local SQLite or enterprise PostgreSQL).
A preset can declare an ordered parent_refs list. Resolving a preset's
lineage walks each declared parent, in the exact order it was declared,
before moving to the next — never dict/set iteration order, thread
scheduling, or registry-source registration order. The result is an acyclic,
deduplicated (first-occurrence-wins) chain from the oldest ancestor to the
preset itself.
skillmeat assembly show managed:preset/web-app-strict --kind preset --format json
skillmeat assembly validate --kind preset --file candidate-preset.json
A minimal preset body:
{
"qualified_ref": "managed:preset/web-app-strict",
"parent_refs": ["builtin:web-app-base"],
"bindings": {"lint_level": "strict"},
"recommended_target_ref": "claude_code"
}
Binding precedence¶
When an assembly resolves, every candidate value for a given parameter is ranked by an ordered, eight-layer precedence chain (low to high — later layers win over earlier ones):
artifact_default— the module/artifact's own built-in default.preset_ancestor— values from a selected preset's ancestor lineage.selected_preset_target_recommended— a preset selected because it's the recommended preset for the resolved target profile.selected_preset_rule_selected— a preset a rule chose to apply (select_presetaction).rule_set_parameter— a value a rule set directly to a parameter (set_parameteraction) — a synthetic, rule-derived layer.selected_preset_explicit— a preset you named explicitly (--preseton the CLI, orexplicit_preset_refsin the API request body).project_default— the target project's own configured default.invocation_override— a value passed directly on this one invocation (invocation_overridesin the API request body). Always wins.
resolve/preview/apply responses expose the winning value and every
overridden candidate per binding (binding_provenance in the JSON response,
the binding-provenance panel in the web workspace) — you can always see which
layer won and what it beat.
skillmeat assembly resolve managed:assembly/my-assembly \
--preset managed:preset/web-app-strict \
--format json
# lint_level resolves to "strict" here — the value from the explicitly
# selected preset (layer 6) — and binding_provenance shows the module/preset
# lineage's own defaults (layers 1-2) as overridden candidates.
The CLI's --set KEY=VALUE on resolve/preview/apply sets a context
fact (context_facts in the request body — the typed facts rule
conditions read, e.g. a user_fact), not a parameter binding. --preset
(repeatable) is the CLI's only way to reach the explicit-preset layer today.
The project_bindings and invocation_overrides layers are part of the API
request body (POST /assemblies/{id_or_ref}/resolve|preview|apply) but are
not yet exposed as CLI flags — call the API directly (or from the web
workspace) if you need to override a single binding for one invocation
without adding a preset:
curl -s -X POST "$SKILLMEAT_API/api/v1/assemblies/managed:assembly/my-assembly/resolve" \
-H "Authorization: Bearer $SKILLMEAT_TOKEN" -H "Content-Type: application/json" \
-d '{"explicit_preset_refs": ["managed:preset/web-app-strict"], "invocation_overrides": {"lint_level": "relaxed"}}'
# lint_level now resolves to "relaxed" (invocation_override, layer 8, beats
# every preset layer), and binding_provenance shows the preset's "strict"
# value as the overridden candidate.
Bounded declarative rules¶
A RuleSet is a collection of Rule entries, each with a priority, an
optional condition tree, and one or more actions. Rules are intentionally
bounded — there is no executable/arbitrary-code path:
Allowed actions (RuleActionType): include_module, exclude_module,
select_preset, set_parameter, choose_target_profile, emit_validation.
Any other value is rejected at construction time.
Allowed condition operators: boolean combinators all, any, not; leaf
comparisons eq, neq, in, not_in, contains, starts_with,
matches_glob, gt, gte, lt, lte.
Allowed facts (FactType — a rule condition can only read these
declared, typed facts, never arbitrary context): project_identity,
project_type, target_profile, platform, os, architecture,
tool_version, dependency_version, capability, edition, user_fact,
invocation_mode.
One condition tree is capped at depth 8, 128 total nodes, and one rule-set at 64 total actions — construction fails closed if a rule exceeds any of these.
{
"qualified_ref": "managed:rule/codex-only-docs",
"rules": [
{
"rule_id": "prefer-codex-docs",
"priority": 10,
"condition": {"operator": "eq", "fact": "target_profile", "value": "codex"},
"actions": [
{"action_type": "include_module", "target_ref": "managed:module/codex-notes"},
{"action_type": "set_parameter", "parameter_name": "doc_style", "parameter_value": "concise"}
]
}
]
}
skillmeat assembly validate --kind rule --file codex-only-docs.json
skillmeat assembly create --kind rule --file codex-only-docs.json
rule_decisions in every resolve/preview/apply response records, per
rule, which condition evaluated true/false and which actions actually fired —
the same trace the web workspace's rule-decision panel renders.
Secret redaction¶
Preset bindings (and module/rule-set metadata) must never carry resolved
secret material directly — a secret's identifier belongs in that
definition's secret_refs list, never the secret value itself. Any
API/CLI/log output derived from a binding candidate that references a secret
is redacted with a fixed sentinel (<redacted:secret_ref>) rather than the
real value, and this redaction is applied consistently everywhere a binding
candidate can surface — resolve/preview responses, the web workspace's
binding-provenance panel, and the skillmeat.lock/SkillBOM provenance
written by apply (see Lock & Replay). If you
need a resolved secret value at materialization time, your target adapter
resolves it out-of-band from secret_refs; it is never round-tripped through
the resolution/provenance surface.
Related guides¶
- Authoring — creating the modules and assemblies these presets and rules apply to.
- Lock & Replay — how binding provenance and rule
decisions get committed on
apply. - Editions — where policy ceilings on rule actions and source scopes are configured.