Skip to content

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/*.toml for 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):

  1. artifact_default — the module/artifact's own built-in default.
  2. preset_ancestor — values from a selected preset's ancestor lineage.
  3. selected_preset_target_recommended — a preset selected because it's the recommended preset for the resolved target profile.
  4. selected_preset_rule_selected — a preset a rule chose to apply (select_preset action).
  5. rule_set_parameter — a value a rule set directly to a parameter (set_parameter action) — a synthetic, rule-derived layer.
  6. selected_preset_explicit — a preset you named explicitly (--preset on the CLI, or explicit_preset_refs in the API request body).
  7. project_default — the target project's own configured default.
  8. invocation_override — a value passed directly on this one invocation (invocation_overrides in 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.

  • 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.