Modeller
Reference

Semantic Assembly Format

Low-level explicit-ID grammar used to prove canonical compilation and conformance.

Semantic Assembly Format (SAF) 1.0 is an engineering syntax for proposing Modeller meaning. Modeller.Parsing compiles source documents to the canonical context package, authored model, source provenance, and ordered diagnostics through one interface:

ParseResult DefinitionParser.Parse(
    IEnumerable<SourceDocument> documents,
    ParseOptions options,
    CancellationToken cancellationToken = default)

SAF remains an executable parser input, but it is not the business-facing Readable Modelling Language. Its explicit identities and flat statements support conformance, diagnostics, and parser bootstrapping while RML and its authoring anti-corruption layer are developed.

The syntax is not a second semantic model. Package loading and semantic validation remain authoritative after compilation. The parser does not persist, resolve dependencies, execute expressions, generate output, or supply implicit domain defaults.

Common syntax

  • UTF text is interpreted as lines.
  • Blank lines and lines beginning with # are non-semantic.
  • Each statement begins with a lowercase keyword.
  • Attributes use name=value; values containing spaces use double quotes.
  • Stable identities and semantic relationships use UUIDv7 values.
  • Statement order, document order, filenames, comments, and formatting are non-semantic.
  • One language 1.0 and one context statement are required across the source set.

Language 1.0 statements

StatementRequired attributes
contextid, name, slug, version
decisionid, name, slug, inputs, hit-policy; optional export=true
decision-conclusionowner decision ID, id, name, slug
decision-rowowner, id, name, slug, conditions, conclusion, finding-code; optional missing-findings
entityid, name, slug, lifecycle-id, lifecycle-name, lifecycle-slug
stageowner entity ID, id, name, slug
factid, name, slug, type; optional export=true
ruleid, name, slug, inputs, expression, conclusion identity/name/slug; optional true-findings, false-findings, missing-findings, and export=true
behaviourid, name, slug, entity
outcomeowner behaviour ID, id, name, slug
bindingowner, rule, purpose, facts mappings
transitionowner, id, name, slug, lifecycle, source, target, outcome

Language 1.0 deliberately supports only the explicit and(fact-id,...) rule expression needed by the first ACCS slice. Unsupported expression forms return parse.expression.unsupported; they are never evaluated or coerced. Finding mappings use comma-separated fact-id:stable-code entries and make Child Care explanation meaning explicit rather than inferred by the runtime.

Decision conditions use comma-separated fact-id:true, fact-id:false, or fact-id:any entries. Language 1.0 supports the Unique hit policy: complete typed input combinations match exactly one row. Overlapping or incomplete tables fail at runtime binding; row order never acts as a fallback.

Child Care example

language 1.0
context id=0191...0001 name="Child Care" slug=child-care version=1.0.0
fact id=0191...0006 name="Active enrolment exists" slug=active-enrolment-exists type=Truth export=true
rule id=0191...0008 name="Determine ACCS eligibility" slug=determine-accs-eligibility inputs=0191...0006 expression=and(0191...0006) true-findings=0191...0006:accs.active-enrolment-confirmed missing-findings=0191...0006:accs.active-enrolment-required conclusion-id=0191...0009 conclusion-name="Eligible" conclusion-slug=eligible export=true

The complete fixture compiles to semantic digest sha256:6d1448c32127c49571d2a7ea5982045b7aa74ed28da2d7323ac5360b94ed6728, the same digest as canonical JSON.

The child-care-accs-decision-table.modeller fixture expresses Classify ACCS eligibility with explicit Eligible and Ineligible conclusions. It compiles to semantic digest sha256:63e39411df24b9ee59614cc8d3fae4397e79272f85ac99b8fc2d97eda4e7a37a, the same digest as its Child Care 1.1 canonical package.

Provenance and diagnostics

Every named statement retains a package-relative document, one-based line and column, and span length. Reference paths retain their exact token spans. Validation diagnostics are mapped back through those paths; an unknown input Fact therefore points to the Fact UUID in Determine ACCS eligibility, not merely to the file or Rule.

Malformed or incomplete syntax, unsupported language versions, invalid models, document/statement/token limits, unsafe document names, and cancellation return structured results. Parser or validation exception text is never exposed as a diagnostic.

Limits and security

ParseOptions.Language1 limits a source set to 1,048,576 characters, 10,000 semantic statements, and 100,000 attribute tokens. Source document names must be package-relative and cannot traverse above the package. The grammar is flat, so authored nesting cannot create recursive parser work. Source is tokenized and compiled as data; substitutions, scripts, and expressions are never executed.

Legacy import

LegacyDefinitionAdapter exposes the versioned legacy-domain-root/1.0 path. It supports only a legacy domain plus version and requires an explicit current context UUID, display name, and slug. The adapter records the legacy identifier-to-stable-ID mapping and retains the original source span.

Legacy services lists mix deployment and ownership ideas and are rejected as ambiguous. Entities, endpoints, templates, and other legacy constructs remain unsupported until a reviewed mapping and fixture proves equivalent meaning; the adapter never guesses or silently accepts them.

Editor protocols consume this parser through the editor-integration reference, preserving the same diagnostic identities and source spans rather than defining a second language or validation path.

On this page