2.0.0 (SBDL Compiler), 26.6 (SBDL Language) [#e316992]
The SBDL compiler: reads distributed SBDL, builds and verifies one model, and projects it into many output forms. Flat sibling modules rather than a package, so that sbdl.py stays directly runnable.
A quality the design is built to achieve.
| Goal | Rationale | Principles | Evidence |
|---|---|---|---|
| Every element and every diagnostic is traceable to the file and line that caused it | — | dp_stage_gate, dp_source_reference |
— |
| Identical input produces byte-identical output | Generated artefacts are committed, published and diffed in CI; churn hides real changes | dp_sorted_output, dp_stable_arithmetic |
t_native_renderer |
| Runs unmodified on CPython and PyPy with no compiled extensions on the core path | Large models are routinely compiled under pypy3 | dp_external_rasteriser,
dp_stable_arithmetic |
t_native_renderer |
| The entry script runs directly from a checkout, from an installation or as a frozen binary | — | dp_flat_modules |
— |
| New output modes, directives and rendering backends are added without changing the compilation pipeline | — | dp_outputs_namespace, dp_single_model, dp_mode_registry, dp_writer_contract, dp_injection_over_import |
t_renderer_backend |
| A command line that once worked keeps working | Mode names live in user Makefiles, BATCH directives and deployment scripts | dp_mode_registry, dp_renderer_backend |
t_mode_aliases |
| Compile, filter and render time grows roughly linearly with model size | Production models hold thousands of elements; quadratic passes made some modes unusable | dp_incoming_index |
t_incoming_index |
| The core path and the SVG diagram path need nothing beyond the Python standard library | Removing the Java and Graphviz dependency was the reason for the native renderer | dp_renderer_backend,
dp_external_rasteriser |
— |
| The language server never stalls the editor while a compile is running | — | dp_off_the_event_loop |
t_lsp_smoke |
| A second implementation of the language can be qualified against this one | — | dp_semantic_comparison,
dp_corpus_checks_itself |
t_compliance_self |
| The shipped, minified compiler behaves identically to the source | — | dp_shared_namespace,
dp_test_the_build |
t_distribution |
A band of modules holding one position in the import order.
Leaf of the import graph: imports no sibling.
sbdl_core.pyConfiguration, printing, progress, lazy imports and run-state reset.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_config |
Configuration store: registered defaults, -C overrides, SBDL_* environment snapshot, provenance by comparison with defaults | sbdl_core.py:45 |
cmp_reset |
reset() and the hook registry through which any module registers global state to clear between compilations | sbdl_core.py:432 |
cmp_lazy_import |
Optional dependencies imported on first use; offers installation only when stdin can answer | sbdl_core.py:500 |
cmp_printing |
f_print: decides whether to print before formatting; errors and warnings to stderr, output never interleaved with stdout | sbdl_core.py:603 |
cmp_progress |
Progress bars and terminal title on stderr, inert unless enabled and stderr is a terminal | sbdl_core.py:664 |
The language: parser, metamodel, element graph and every reader.
Depends on lyr_foundation.
sbdl_model.pyParser, semantics, element hierarchy, AST and the input layer. One module because the metamodel is internally cyclic and the parser and readers are mutually coupled.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_parser |
SBDL_Parser: statement scanning, key-value parsing, tokens, attributes and directive expansion | sbdl_model.py:38 |
cmp_directives |
Compiler directives: definitions, imports, embedding context, cross-references, Prolog assertions and batch jobs | sbdl_model.py:169 |
cmp_semantics |
SBDL_Semantics: the type tables (properties and permitted relations per type) and the registry of custom types | sbdl_model.py:1710 |
cmp_statements |
SBDL_Statement hierarchy: declarations, using, scope, depends and relation operators, as parsed | sbdl_model.py:2447 |
cmp_elements |
SBDL_Element hierarchy: one class per metamodel type, each verifying its own properties and links | sbdl_model.py:2625 |
cmp_ast |
SBDL_AST: turns statements into the element set, applies filters, verifies, and answers relation queries | sbdl_model.py:3714 |
cmp_readers |
Input readers: native and embedded SBDL, JSON, YAML, CSV matrix and SQL, all producing parser elements | sbdl_model.py:4949 |
cmp_ast_cache |
Pickled AST cache for single-file inputs, validated before reuse | sbdl_model.py:5481 |
Principles: dp_single_model, dp_immutable_elements.
Projections of a verified model into other forms; consumers of the
model only. Depends on lyr_model.
sbdl_outputs.pyThe output namespace: text, tabular, SQL, template and PlantUML
writers, batch dispatch and trace verification. Also imports mod_openfmea, mod_sysmlv2.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_plantuml_writers |
PlantUML diagram writers: the plantuml rendering backend | sbdl_outputs.py:38 |
cmp_text_writers |
compile, query, matrix:csv, tree:json, tree:yaml and type-info writers | sbdl_outputs.py:1040 |
cmp_sql_backend |
Normalised SQLite writer, behind a backend seam reserved for remote databases | sbdl_outputs.py:1237 |
cmp_template_fill |
template:fill: the model as a Jinja2 context, plus Office document templating | sbdl_outputs.py:1535 |
cmp_mode_loader |
Loads --custom-mode modules and their MODES dictionaries | sbdl_outputs.py:1668 |
cmp_batch |
Batch dispatch: runs the jobs declared by BATCH directives against copies of the AST | sbdl_outputs.py:1703 |
cmp_model_machine |
SBDL_Model_Machine: replays trace elements against the functions and state machines of the model | sbdl_outputs.py:1830 |
Principles: dp_outputs_namespace, dp_writer_contract.
sbdl_openfmea.pyOpenFMEA import and export: the cause, mode and effect table and its portfolio form.
sbdl_sysmlv2.pyTranslation of the model into SysML v2 textual notation.
sbdl_native_svg.pyDiagram-agnostic SVG basis: theme, text metrics, layouts, routing, labels and canvas.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_theme |
Theme tokens and style packs: every visual decision is a registered configuration key | sbdl_native_svg.py:13 |
cmp_layouts |
Containment packing, layered (Sugiyama-lite), tree and force-directed layouts | sbdl_native_svg.py:531 |
cmp_routing |
Orthogonal and curved edge routing around obstacles, with a spatial grid for scale | sbdl_native_svg.py:1104 |
cmp_canvas |
Canvas: frame, header tab, footer and final document fitting | sbdl_native_svg.py:1783 |
Principles: dp_measure_equals_draw,
dp_external_rasteriser.
sbdl_native_sysml.pyThe native rendering backend: SysML-style diagrams drawn directly as
SVG. Also imports mod_native_svg, mod_outputs.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_structure_diagrams |
Aspect, requirement, element and use case diagrams | sbdl_native_sysml.py:456 |
cmp_behaviour_diagrams |
Sequence (function), activity (function-process) and state machine diagrams | sbdl_native_sysml.py:673 |
cmp_analysis_diagrams |
FMEA failure-chain and type-affinity diagrams, which have no PlantUML counterpart | sbdl_native_sysml.py:3255 |
Principles: dp_machine_readable_svg.
Long-running or remote ways of reaching a compiled model. Depends on
lyr_model.
sbdl_lsp.pyLanguage server: diagnostics, symbols, hover, completion and the model explorer snapshot.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_completion |
Completion as a pure function of the line prefix, testable without an editor | sbdl_lsp.py:260 |
cmp_model_snapshot |
The model served to the explorer: the widest open model that contains the document | sbdl_lsp.py:396 |
cmp_lsp_server |
The pygls server and its handlers, built as closures inside lsp_start | sbdl_lsp.py:509 |
cmp_doc_worker |
One worker per open document, compiling off the event loop and coalescing requests | sbdl_lsp.py:605 |
sbdl_mcp.pyRead-only Model Context Protocol server over a compiled model.
Principles: dp_injection_over_import.
sbdl_remote.pyStandalone RPC client for the remote REST service, shipped separately from the compiler.
The command line: the only module that knows every other. Depends on
lyr_writers, lyr_services.
sbdl.pyArgument handling, the mode table and the single compilation run.
| Component | Responsibility | Defined at |
|---|---|---|
cmp_mode_table |
operating_modes: the common modes, extended by the selected rendering backend | sbdl.py:39 |
cmp_main |
main: one compilation run, staged and gated by check_step | sbdl.py:114 |
cmp_arguments |
Argument parsing and pre-execution handling: configuration, -C, progress and flags that exit early | sbdl.py:277 |
Principles: dp_never_import_entry.
Evidence that the compiler does what it claims. Depends on lyr_writers.
sbdl_compliance.pyCompliance corpus and runner that qualify an external compiler against this one. Shipped: the corpus is inline data, so it runs from an installation with no repository.
Principles: dp_semantic_comparison,
dp_corpus_checks_itself.
sbdl_tests.pyThe unit and integration suite, driven largely through the real command line. Not shipped: it needs the test fixtures. Holds the one sanctioned upward reference to the entry.
Principles: dp_test_through_cli.
Build, release and editor tooling around the compiler.
helpers/Source rewriters run on the distribution copies: explicit imports, f-string compatibility, comprehension shadowing.
release_public.shPublishes one commit per release to the public repository, filtered by a manifest.
Principles: dp_snapshot_releases.
build_dist.shDistribution build: copy, rewrite star imports, minify, repair, package.
Principles: dp_test_the_build.
A design decision that holds across the compiler.
The compiler is a set of
flat sibling modules, not a package. Keeps sbdl.py directly
runnable however it is launched; the entry puts its own directory on
sys.path first. Consequence: A bare copy of sbdl.py no longer
works alone; every sibling must travel with it.
Applies to lyr_entry;
serves goal_runnable
Imports form a directed
acyclic graph: core, then model, then writers and services, then the
entry. Each layer can be read, tested and replaced knowing only
the layers beneath it. Consequence: The native renderer reaches
outputs through a plain module import, the one tolerated cycle, resolved
at call time.
Applies to sbdl_compiler
No module imports the
entry; the test suite alone reaches it, through one guarded
helper. When the entry runs as __main__, importing it
re-executes it as a second module and rebuilds the configuration
snapshot.
Applies to mod_entry
Modules reconstitute
one shared namespace with star imports; the build rewrites them into
explicit imports. Keeps the split invisible to code moved out
of the original single file, while letting the minifier rename locals in
the shipped copy. Consequence: Underscore names do not cross a
star import and must be imported explicitly.
Applies to lyr_foundation; serves goal_correct_build;
evidenced by t_distribution
Global state that must
not survive a compilation registers a reset hook with the core.
The language server and the test suite compile many models in one
process; the core stays a leaf while any module can register
state.
Applies to cmp_reset
The entry imports
output modes from the outputs module and nowhere else. Adding a
writer then touches only the mode table, never the entry imports.
Consequence: A writer carved into its own module must be
re-exported by the outputs module or the mode table fails at run
time.
Applies to mod_outputs;
serves goal_extensible
Every input form is read
into the same element graph, verified once, and only then
projected. Writers never parse and never verify, so every
output agrees on what the model is.
Applies to mod_model;
serves goal_extensible
Each compilation stage ends
at a gate that counts errors and aborts before the next stage.
A later stage never runs on a model an earlier stage rejected, unless
the user asks for that with --skip-errors.
Applies to cmp_main;
serves goal_traceable
Diagnostics cite an
element by source_reference, never by reference. reference is a
display value a model may override; source_reference is the parser
location and cannot be overridden. Consequence: The language
server recovers squiggle positions from diagnostic text, so a wrong
reference pins it to line 0.
Applies to cmp_elements; serves goal_traceable
Relation queries take a
table of incoming relations, built once by whoever holds the element
set. An element stores only the relations it declares; finding
the reverse half by scanning makes every query linear and every pass
quadratic.
Applies to cmp_ast; serves
goal_scalable; evidenced by t_incoming_index
related is an ordinary
relation, exposed through its own view and excluded from links.
Relation verification type-checks each link against its target, which a
related link could never satisfy.
Applies to cmp_elements
A group organises the
model and is not part of it: it may end a connectivity path but never
bridge one. Adding an element to a review package must not
change the answer to a question about the system. Consequence:
Connectivity semantics are implemented twice, in the AST walk and in the
SQL query, and must change together.
Applies to cmp_ast;
evidenced by t_filter_semantics
A filter reduces the
model; a diagram root leaves the model whole and moves only where a
diagram starts. Diagram writers reach outwards while drawing,
so filtering to one element culls what is needed to draw it.
Applies to cmp_ast;
evidenced by t_diagram_root
Elements are defined
once and never modified; membership and relation may be declared from
either side. Definitions are distributed across files the
author may not own, so the model is assembled, never edited.
Applies to mod_model
Every output mode is one
row in a mode table: name, writer, output kind, description and older
spellings. Help, discovery, batch validation and the MCP tools
all read the same table, so a new mode appears everywhere at once.
Consequence: Deprecated spellings are kept as aliases and
omitted from help, which is deprecation by omission.
Applies to cmp_mode_table; serves goal_extensible, goal_stable_cli; evidenced by
t_mode_aliases
A writer takes the AST,
the output path, a file opener, the arguments and a print function, and
returns an error count. One signature lets the entry, batch,
the MCP server and custom modes all drive any writer the same way.
Consequence: A writer reads its own mode name from the
arguments, never from a literal of its own.
Applies to mod_outputs;
serves goal_extensible;
evidenced by t_renderer_backend
A mode that reads input
is registered twice: in the mode table, and with the reader for its
format. Readers and writers vary independently; most reading
modes share one writer. Consequence: A reading mode registered
only once parses its input as SBDL and produces wrong output rather than
an error.
Applies to cmp_mode_table; evidenced by t_mode_aliases
Diagram modes come from
a selected rendering backend, so one mode name dispatches to a different
writer per backend. Lets the native renderer replace PlantUML
behind unchanged command lines, and an unknown backend fails rather than
drawing nothing.
Applies to cmp_mode_table; serves goal_stable_cli, goal_dependency_light;
evidenced by t_renderer_backend
A service that
needs the writers receives the mode table as an argument instead of
importing it. Keeps services such as the MCP server below the
entry in the import graph and free of mode-specific code.
Applies to mod_mcp; serves
goal_extensible; evidenced
by t_mcp_server
Outputs project the model;
they never restate it or invent what it does not say. A diagram
that asserts something absent from the model is worse than one that
leaves it out, as with an inferred initial state.
Applies to lyr_writers
Anything measured
and then drawn is computed by one function used for both.
Separate copies drift: labels were sized at one position and painted at
another, and clipped.
Applies to mod_native_svg
A style pack changes
paint and spacing only, never shape, notation or layout. Every
machine-readable hook in the SVG stays identical across styles, which
the editor and the tests rely on.
Applies to cmp_theme
Every drawn element
carries data-sbdl attributes naming the model element it shows.
Tests count hooks instead of geometry, so they survive layout changes,
and the editor makes diagrams clickable.
Applies to mod_native_sysml; evidenced by
t_native_renderer
PNG output pipes SVG
through an external command rather than a Python binding.
Bindings are C extensions that break PyPy; a missing rasteriser fails
loudly instead of writing SVG into a file named png.
Applies to mod_native_svg; serves goal_portable, goal_dependency_light
Sets are never iterated on
an output path without sorting. String set order varies per
process under hash randomisation, so it silently became property order
in several writers.
Applies to sbdl_compiler; serves goal_reproducible
Layouts use only
correctly rounded operations and a summation that is identical on every
interpreter. A layout is a feedback loop: one bit of difference
in a sum steers every later iteration.
Applies to cmp_layouts;
serves goal_reproducible,
goal_portable; evidenced by t_native_renderer
Tests drive the real
command line or protocol wherever the wiring is part of the
behaviour. Flag wiring, configuration loading and mode
registration are exactly what an in-process call skips.
Applies to mod_tests
The suite runs against
the minified distribution before a release, not only against the
source. Some defects exist only in the minified form, where a
renamed name meets an interpreter optimisation.
Applies to mod_build;
serves goal_correct_build;
evidenced by t_distribution
Compliance compares
meaning, not text: both outputs are recompiled by the reference and the
canonical forms compared. compile is idempotent, so formatting
differences dissolve and only changes of meaning remain.
Applies to mod_compliance; serves goal_qualifiable; evidenced by
t_compliance_self
Every compliance
case states its expected outcome, and a case the reference disagrees
with blames the corpus. A deliberate change of behaviour then
surfaces as a corpus disagreement instead of silent drift.
Applies to mod_compliance; serves goal_qualifiable; evidenced by
t_compliance_self
Standard output carries
only the requested output; everything for humans goes to standard
error. The default output is stdout, and the language and MCP
servers speak their protocols over it.
Applies to cmp_printing; evidenced by t_mcp_server
The compiler
never waits for an answer that nobody can give. An install
prompt inside CI or a captured child process blocks forever and
invisibly.
Applies to cmp_lazy_import
Compiling and
building model snapshots happen on worker threads, never on the language
server event loop. A request waiting on a compile delays every
request behind it, including shutdown.
Applies to cmp_doc_worker; serves goal_responsive_editor;
evidenced by t_lsp_smoke
The public repository
receives one dated commit per release, built from a manifest of the
private one. Working history and timestamps stay private; a new
file stays private until listed.
Applies to mod_public_release
A wire or file format through which other programs drive or consume the compiler.
| Protocol | Description | Owned by |
|---|---|---|
if_cli |
The command line: sources, a mode, filters, configuration and an output path | mod_entry |
if_sbdl_text |
SBDL itself, native or embedded in other files, read and written by compile | mod_model |
if_tree_formats |
JSON tree, YAML tree and CSV matrix, written and read back | cmp_readers |
if_sql_schema |
The normalised SQLite schema: elements, properties, relations with derived reverse halves, custom types | cmp_sql_backend |
if_openfmea |
OpenFMEA documents, written and read | mod_openfmea |
if_sysmlv2 |
SysML v2 textual notation, written | mod_sysmlv2 |
if_svg |
Native SVG diagrams with data-sbdl hooks and a stated ground colour | mod_native_sysml |
if_lsp |
Language Server Protocol over stdio, plus the sbdl/model request and sbdl/modelUpdated notification | mod_lsp, ext_editor |
if_mcp |
Model Context Protocol over local HTTP or stdio: five read-only tools | mod_mcp, ext_ai_client |
if_rpc |
REST RPC to a remote compilation service | mod_remote |
A seam through which the compiler is extended without editing it.
| Extension point | Description | Owned by |
|---|---|---|
if_custom_mode |
A module exposing a MODES dictionary of writers, loaded with --custom-mode; its modes replace built-in ones of the same name | cmp_mode_loader |
if_custom_directive |
A file of custom compiler directives, loaded with --custom-directive | cmp_directives |
if_customtype |
customtype declarations, with optional embedded Python verifiers: the language profile mechanism | cmp_semantics |
if_template_context |
The model as a dictionary inside Jinja2: identifiers to properties and relation lists | cmp_template_fill |
if_ast_hooks |
Pre- and post-verification hooks called with the AST, configured as lists of functions | cmp_main |
Software outside the compiler that it calls, or that calls it.
| Software | Description | Dependency | Relates to |
|---|---|---|---|
ext_plantuml |
PlantUML, invoked as a subprocess by the plantuml rendering backend | optional | cmp_plantuml_writers |
ext_rasteriser |
An SVG rasteriser such as rsvg-convert, used only when a native diagram is written as PNG | optional | cmp_canvas |
ext_pygls |
pygls, the language server framework under the lsp mode | optional | cmp_lsp_server |
ext_jinja2 |
Jinja2, the template engine under template:fill | optional | cmp_template_fill |
ext_prolog |
SWI-Prolog through pyswip, for the Prolog assertion directives | optional | cmp_directives |
ext_editor |
The VS Code extension: a language client plus explorer, previews and tables that shell out to the compiler | consumer | mod_lsp |
ext_ai_client |
An MCP client such as Claude Code or Claude Desktop | consumer | mod_mcp |
ext_minifier |
python-minifier, run by the distribution build | build | mod_build |
| Use case | Actor | Description | Function | Goal |
|---|---|---|---|---|
uc_compile |
Modeller | Compile distributed sources and produce an artefact | fn_compile_run |
goal_traceable |
uc_edit |
Modeller | Write SBDL in an editor with live diagnostics, completion and a model explorer | fn_lsp_document |
goal_responsive_editor |
uc_ask |
AI assistant | Ask questions about a model and look at its diagrams | fn_mcp_call |
— |
uc_build |
Build system | Generate a project’s documents and diagrams from one compilation | fn_batch |
goal_reproducible |
uc_verify_runtime |
Test engineer | Check captured runtime logs against the behaviour the model defines | fn_trace_verify |
— |
uc_qualify |
Tool implementer | Qualify another SBDL compiler against the reference | fn_compliance |
goal_qualifiable |
uc_release |
Maintainer | Build, test and publish a release | fn_release |
goal_correct_build |
fn_compile_runOne compilation: configuration, reading, parsing, model construction,
filtering, verification and the mode. Defined at
sbdl.py:117, owned by mod_entry.
Input: Source files, a mode and options. Output: The mode’s artefact, and the total error count as exit status. Invariant: Every stage ends at check_step.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_pre_exec |
Load configuration, apply -C and environment overrides, and handle flags that exit early | cmp_arguments |
sbdl.py:428 |
ev_select_reader |
Choose the reader from the mode; any other mode reads by content, detecting databases among the inputs | cmp_main |
sbdl.py:204 |
ev_read_inputs |
Read every input into parser elements carrying file, line indexes and host context | cmp_readers |
sbdl.py:226 |
ev_extract_embedded |
Take native files whole and lift sbdl-prefixed statements out of host files | cmp_readers |
sbdl_model.py:4899 |
ev_sniff_context |
Record the host construct each statement sits in, such as the enclosing function, for context directives | cmp_directives |
sbdl_model.py:4633 |
ev_build_ast |
Build the AST from parser elements, or load it from the cache | cmp_ast |
sbdl.py:230 |
ev_split_statements |
Scan text into statements, keeping the line index of each | cmp_parser |
sbdl_model.py:1591 |
ev_expand_directives |
Expand compiler directives in place: definitions, imports, version checks, batch jobs | cmp_directives |
sbdl_model.py:939 |
ev_construct_elements |
Turn statements into the element set | cmp_ast |
sbdl.py:237 |
ev_apply_scope |
Apply using defaults, scope prefixes, nesting and relation operators | cmp_ast |
sbdl_model.py:3860 |
ev_resolve_depends |
Read each depends target once, failing on a missing file | cmp_readers |
sbdl_model.py:3788 |
ev_register_types |
Register custom types in the semantic tables, documenting each by its description | cmp_semantics |
sbdl_model.py:3867 |
ev_resolve_crossrefs |
Substitute cross-references to other elements’ properties | cmp_directives |
sbdl_model.py:3954 |
ev_register_filters |
Register the -f filters on the AST; from:sql has already applied them as SQL | cmp_main |
sbdl.py:241 |
ev_verify |
Verify every element: its own properties, then each relation’s existence and permitted type (if verification enabled) | cmp_elements |
sbdl.py:245 |
otherwise
ev_skip_verification |
Report verification as skipped and continue | cmp_main |
sbdl.py:255 |
ev_dispatch_mode |
Look the mode up in the operations table and call its writer with the AST | cmp_mode_table |
sbdl.py:261 |
ev_report |
Report timings and return the error count | cmp_main |
sbdl.py:266 |
fn_lsp_documentThe life of one open document in the language server. Defined at
compiler_design.sbdl:472, owned by mod_lsp.
Input: Document notifications from the editor. Output: Diagnostics, symbols and model snapshots.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_lsp_open |
A document is opened, changed or saved; its worker is asked to compile | cmp_lsp_server |
sbdl_lsp.py:761 |
ev_lsp_compile |
The worker compiles the document and its depends, coalescing requests that arrive meanwhile | cmp_doc_worker |
sbdl_lsp.py:689 |
ev_lsp_diagnostics |
Compiler messages become diagnostics positioned from their source reference | cmp_lsp_server |
sbdl_lsp.py:715 |
ev_lsp_model_updated |
The client is told the model changed | cmp_lsp_server |
sbdl_lsp.py:720 |
ev_lsp_snapshot |
The explorer’s model request is answered on a thread from the cached element set | cmp_model_snapshot |
sbdl_lsp.py:897 |
ev_lsp_close |
The document closes; its elements, file set and snapshot are dropped | cmp_lsp_server |
sbdl_lsp.py:786 |
fn_mcp_callOne MCP tool call against the model compiled at start-up. Defined at
sbdl_mcp.py:35, owned by mod_mcp.
Input: A JSON-RPC request. Output: Text or image content.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_mcp_receive |
Read a request from POST /mcp or a stdin line, refusing a non-local origin | mod_mcp |
sbdl_mcp.py:204 |
ev_mcp_dispatch |
Route the method to its handler; notifications get no reply | mod_mcp |
sbdl_mcp.py:174 |
ev_mcp_run_writer |
Run an injected writer on the loaded AST into a temporary directory (if the tool renders or exports) | mod_outputs |
sbdl_mcp.py:68 |
ev_mcp_reply |
Return the result as content, or as a tool error the model can read | mod_mcp |
sbdl_mcp.py:154 |
fn_batchRun the jobs declared by BATCH directives against the one compiled
model. Defined at sbdl_outputs.py:1709, owned by cmp_batch.
Output: One artefact per job.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_batch_collect |
Batch directives met while parsing record their command lines | cmp_directives |
sbdl_model.py:860 |
ev_batch_job |
For each command: validate the mode, copy the AST, run in the foreground or as a background job (if commands remain) | cmp_batch |
sbdl_outputs.py:1746 |
ev_batch_wait |
Wait for background jobs, counting completions rather than dispatches | cmp_batch |
sbdl_outputs.py:1728 |
fn_trace_verifyReplay trace elements against the statically defined behaviour.
Defined at sbdl_outputs.py:2017, owned by cmp_model_machine.
Input: A model and the trace elements found in logs. Output: A verdict per step, as prose or JSON.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_trace_walk |
Take each trace in definition order, which is log order (if traces remain) | cmp_model_machine |
sbdl_outputs.py:2030 |
ev_trace_function |
A function trace sets the active function and its expected event sequence | cmp_model_machine |
sbdl_outputs.py:1935 |
ev_trace_event |
An event trace must be the next expected event; it may fire transitions that move the state | cmp_model_machine |
sbdl_outputs.py:1994 |
ev_trace_assert |
State, aspect and transition traces assert where the machine already is | cmp_model_machine |
sbdl_outputs.py:1969 |
ev_trace_verdict |
Report every divergence with the log file and line it came from | cmp_model_machine |
sbdl_outputs.py:1863 |
fn_complianceQualify a candidate compiler against the reference. Defined at
compiler_design.sbdl:498, owned by mod_compliance.
Input: A candidate command line. Output: A per-profile verdict with its scope of claim.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_baseline_gate |
Compile one minimal valid model first (if the candidate compiles the baseline) | mod_compliance |
compiler_design.sbdl:506 |
otherwise
ev_cannot_qualify |
Report that nothing can be qualified, rather than a pass over zero cases | mod_compliance |
compiler_design.sbdl:512 |
ev_probe_modes |
Probe each mode with a trivial input; an unsupported mode skips its cases instead of failing them | mod_compliance |
compiler_design.sbdl:513 |
ev_run_case |
Run each case on both compilers and compare canonical forms (if cases remain) | mod_compliance |
compiler_design.sbdl:514 |
ev_compliance_report |
Report exercised cases only, never the corpus size | mod_compliance |
compiler_design.sbdl:519 |
fn_releaseBuild, test and publish a release. Defined at
compiler_design.sbdl:521, owned by mod_build.
Output: A distribution and one public commit.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_dist_copy |
Copy the modules and inject the version | mod_build |
build_dist.sh:32 |
ev_dist_rewrite |
Rewrite each star import into the exact explicit equivalent | mod_build_helpers |
build_dist.sh:45 |
ev_dist_minify |
Minify, renaming locals and keeping the global names that form the library API | mod_build |
build_dist.sh:48 |
ev_dist_repair |
Repair what the minifier breaks: f-string forms for older interpreters, comprehension variables shadowing closures | mod_build_helpers |
build_dist.sh:56 |
ev_dist_check_lists |
Fail when a copied module is missing from the installed module list | mod_build |
build_dist.sh:68 |
ev_dist_test |
Run the suite against the minified build in a scratch directory | mod_tests |
compiler_design.sbdl:528 |
ev_public_export |
Export the committed tree through the manifest and scan it for private content | mod_public_release |
compiler_design.sbdl:529 |
ev_public_commit |
Commit as one release with pinned author and date, and tag it; never push | mod_public_release |
compiler_design.sbdl:530 |
fn_native_renderHow every native diagram mode draws. Defined at
compiler_design.sbdl:534, owned by mod_native_sysml.
Input: The AST and the resolved diagram roots. Output: SVG, or PNG through an external rasteriser.
| Step | What happens | Where | Defined at |
|---|---|---|---|
ev_render_collect |
Project the model into nodes and edges for this kind of diagram | mod_native_sysml |
compiler_design.sbdl:542 |
ev_render_measure |
Measure every box from text metrics, captions and reserved overhangs | cmp_layouts |
sbdl_native_svg.py:682 |
ev_render_layout |
Place nodes with the layout the notation calls for: packed, layered, tree, timeline or force | cmp_layouts |
sbdl_native_svg.py:529 |
ev_render_route |
Route edges around obstacles, fanning endpoints that share a side | cmp_routing |
sbdl_native_svg.py:1375 |
ev_render_labels |
Place edge labels at the least overlap, sliding along the edge before nudging off it | cmp_routing |
sbdl_native_svg.py:1518 |
ev_render_paint |
Paint in a fixed order: boxes, then edges, then labels, each tagged with its model element | cmp_canvas |
sbdl_native_svg.py:1807 |
ev_render_emit |
Fit the canvas and write the document (if output is not named png) | cmp_canvas |
sbdl_native_sysml.py:401 |
otherwise
ev_render_rasterise |
Pipe the SVG through the configured rasteriser, failing loudly when it is absent | cmp_canvas |
sbdl_native_sysml.py:414 |
| Event | What happens | Where | Defined at |
|---|---|---|---|
ev_stage_failed |
A stage gate counted errors and --skip-errors is not set (if errors greater than zero) | cmp_main |
sbdl.py:140 |
| State | Description | Within | Where |
|---|---|---|---|
st_run |
A compilation run in progress | — | cmp_main |
st_configuring |
Arguments and configuration being applied | st_run |
cmp_arguments |
st_reading |
Inputs being read | st_run |
cmp_readers |
st_parsing |
Statements being parsed into the AST | st_run |
cmp_parser |
st_constructing |
The element set being constructed | st_run |
cmp_ast |
st_verifying |
The element set being verified | st_run |
cmp_elements |
st_writing |
The mode writing its output | st_run |
mod_outputs |
st_complete |
Run finished; exit status is the error count | — | cmp_main |
st_aborted |
Run stopped at a stage gate | — | cmp_main |
st_doc_closed |
Nothing held for the document | — | mod_lsp |
st_doc_open |
The document is open | — | mod_lsp |
st_doc_compiling |
A compile is running | st_doc_open |
cmp_doc_worker |
st_doc_current |
Diagnostics and model reflect the latest text | st_doc_open |
cmp_lsp_server |
| Transition | From | To | On | Description |
|---|---|---|---|---|
tr_read |
st_configuring |
st_reading |
ev_read_inputs |
Reading starts |
tr_parse |
st_reading |
st_parsing |
ev_build_ast |
Parsing starts |
tr_construct |
st_parsing |
st_constructing |
ev_construct_elements |
Construction starts |
tr_verify |
st_constructing |
st_verifying |
ev_verify |
Verification starts |
tr_verify_skipped |
st_constructing |
st_verifying |
ev_skip_verification |
Verification is skipped |
tr_write |
st_verifying |
st_writing |
ev_dispatch_mode |
The mode runs |
tr_finish |
st_writing |
st_complete |
ev_report |
The run completes |
tr_abort |
st_run |
st_aborted |
ev_stage_failed |
Any stage fails |
tr_doc_open |
st_doc_closed |
st_doc_compiling |
ev_lsp_open |
Open |
tr_doc_compiled |
st_doc_compiling |
st_doc_current |
ev_lsp_diagnostics |
Compiled |
tr_doc_changed |
st_doc_current |
st_doc_compiling |
ev_lsp_compile |
Edited again |
tr_doc_close |
st_doc_open |
st_doc_closed |
ev_lsp_close |
Closed |
A way the design is known to be broken by a plausible change.
| Hazard | Failure mode | Effect | Control | Detection |
|---|---|---|---|---|
| A writer iterates a set of strings on an output path | Output differs between runs of identical input | Committed and published artefacts change without a model change, hiding real changes in review | Every set on an output path is sorted | Render twice and compare, then again with the hash seed fixed: stable only with the seed means a set is being iterated |
| A submodule imports the entry by name | The configuration-default snapshot is rebuilt mid-process | Configuration bleeds between compilations and between tests | Submodules import only core and model; upward references are deferred to call time | — |
| A reading mode is added to the mode table but not to the reader table | Input in another format is parsed as SBDL | Wrong output with no error | Both registrations are documented together beside the mode table | Every reading mode round-trips through its own reader |
| A writer gathers relations without the incoming-relations table | A pass rescans every element for every element | Modes take minutes on production-sized models | The outermost scope holding the element set builds the table and passes it down | Indexed walks are compared with scanning ones and checked for rescans |
| The minifier gives a comprehension variable the name of a closure cell its function passes through | A NameError raised only by the minified build | A released compiler fails where the source passed every test | A build step renames such comprehension variables to fresh names | The language server smoke test, run against the minified build |
| An optional dependency is missing where stdin cannot answer | A child process blocks on a prompt nobody sees | A build or compliance run hangs with no indication why | Prompts are offered only when stdin is a terminal, and compliance children run with stdin closed | — |
| Test | What it shows | Goals | Principles | Defined at |
|---|---|---|---|---|
t_filter_semantics |
FilterSemanticTests: every filter’s result set written out, including SQL-layer fidelity | — | dp_group_is_not_model |
sbdl_tests.py:415 |
t_distribution |
DistributionTests and ComprehensionShadowTests: the import rewrite is exact and the minifier is never blocked | goal_correct_build |
dp_shared_namespace,
dp_test_the_build |
sbdl_tests.py:797 |
t_lsp_smoke |
LSPSmokeTests: a real server over stdio, and a model request that does not stall it | goal_responsive_editor |
dp_off_the_event_loop |
sbdl_tests.py:901 |
t_incoming_index |
IncomingRelationsTests and CMEGraphIndexTests: indexed walks equal scanning ones and do not rescan | goal_scalable |
dp_incoming_index |
sbdl_tests.py:1172 |
t_renderer_backend |
RendererBackendTests: each backend covers the shared diagram names, writers keep the contract, -C selects a backend | goal_extensible |
dp_renderer_backend,
dp_writer_contract |
sbdl_tests.py:1280 |
t_mcp_server |
MCPServerTests: the MCP server driven over stdio as a client would | — | dp_injection_over_import,
dp_stdout_is_output |
sbdl_tests.py:1549 |
t_diagram_root |
DiagramRootTests: a root keeps what a filter loses | — | dp_filter_versus_root |
sbdl_tests.py:2084 |
t_mode_aliases |
ModeNameAliasTests: deprecated spellings render identically and never appear in help; every reader round-trips | goal_stable_cli |
dp_mode_registry, dp_two_registries |
sbdl_tests.py:2184 |
t_native_renderer |
NativeRendererTests: counts by data-sbdl hooks, parity with PlantUML, well-formed XML, identical layout on every interpreter | goal_reproducible, goal_portable |
dp_machine_readable_svg,
dp_stable_arithmetic |
sbdl_tests.py:2437 |
t_compliance_self |
The compliance self-check: the reference against itself, where any failure is a runner or corpus bug | goal_qualifiable |
dp_semantic_comparison,
dp_corpus_checks_itself |
compiler_design.sbdl:546 |