0.1.2 — 2026-08-20
A measurement release. Two advisory harnesses now ask the OMG pilot implementation and the
pinned OMG grammars where this implementation differs from them, and most of the behavior below
is what they found — chiefly in KerML, which the pilot's own KerML validator now judges. A
.kerml file is read as KerML rather than as SysML written with other keywords, so a KerML
model 0.1.1 rejected may analyze clean here; notation accepted beyond the grammars now warns
where it used to be silent. Nothing was renamed and no interface changed.
The pilot implementation judges every corpus, KerML included
cmd/pilot-diffcompares our diagnostics against the pinned OMG pilot implementation
(2026-05, jupyter-sysml-kernel 0.60.1) file by file, over 338 files in seven roots: the OMG
training corpus, the pilot's own SysML example and validation corpora, its KerML examples, our
testdata, our examples and our probes. 221 files agree exactly. It is advisory — a harness that
finds work, not a gate — so nothing in CI depends on it, and its committed baseline
(docs/project/pilot-differential-baseline.json) makes a rerun a diff rather than a reading.
On the 100-file training corpus both implementations report nothing at all.- The KerML corpus is judged by the pilot's own KerML validator, not by our reading of the
KerML specification:scripts/pilot-kerml-validator/ValidateKerML.javaregisters the pilot's
KerMLStandaloneSetup, loadssysml.libraryand the corpus into one EMFResourceSet, and
asks the pilot'sIResourceValidatorwithCheckMode.ALL. It contributes no rule of its own,
so a disagreement it prints is the reference's verdict. Over the pilot's 58 KerML examples, the
diagnostics only we reported fell from 439 to 150 as the KerML work below landed — the syntax
class from 360 to 140, and the genuine name-resolution class from 123 to 7 — and 33 of the 58
files now agree exactly. - Six diagnostics the pilot reports and we do not are a defect in the pilot, not a gap here:
EMF's unpaired-bidirectional-reference check firing on the pilot's own
Type::ownedDisjoining/Disjoining::owningTypeopposite, reproducible from three lines
(classifier A; classifier B disjoint from A;) in a fresh resource set. It is recorded with
its reproducer rather than absorbed into our own numbers. cmd/grammar-coveragemeasures the pinned OMG grammars against every corpus we hold:
483 of 727 productions and 802 of 807 notational forms have input-presence evidence. The
number is deliberately an over-approximation — presence of an input a production admits, never
parser-execution coverage or compliance — so the page's useful reading is the five forms with
no evidence anywhere, each adjudicated: the%remainder operator and prefix metadata on a
namespace are implemented but exercised by nothing, and the nameddisjoining,conjugation
andredefinitionrelationship declarations are not implemented.
A .kerml file is analyzed as KerML
- A KerML declaration specializes the library type its keyword implies, so the features of
that library type are inherited:classreachesOccurrences::Occurrence,structreaches
Objects::Object, and so on throughassoc,behavior,function,interaction,
metaclass,datatype,classifierandtype. No library member was inherited before, so
portion focusedState : Camera subsets timeSlices;reported an unresolved reference to a
feature the library declares. A declared generalization suppresses the implicit base only when
it already reaches it, sostruct MyWheel specializes Wheelstill reachesObjects::Object,
and a supertype restored from the index cache keeps those edges. A barefeaturestill gets
no base: the SysML attribute base is not KerML's. - SysML's definition-and-usage checks no longer fire on KerML declarations.
class Person specializes Objectwas reported as "only a definition may specialize; found a usage" — a
distinction KerML does not draw. A.kermlspecialization or typing now requires only that
its target be a type, from an explicit list of what a type is rather than a guess about what
isn't, sometaclass AtomMetadata specializes Metaobjectis accepted while a non-type target
is still reported. The SysML files keep the kind checks they had. - A union conforms through its unioning types —
classifier MyWheel unions MyWheel1, MyWheel2— without unioning becoming a generalization. - A declaration's header sees its own body. Names in a
featured by,crossesor
subsetting clause resolve against the members and imports of the body of the same declaration
before the enclosing scope, and stay reachable afterwards by qualified name and feature chain.
Resolution of a member inherited through an implicit base no longer recurses. - An unknown subsetting target is tolerated rather than reported as a KerML type error about
something else.
KerML notation the reference accepts now parses
featured by, an n-ary connector end list, and a typed or redefining succession parse:
class Owner { member feature inCart : Product featured by Account; },
connector c : A (a, b, c);andsuccession s : Link [1] first paint then dry;— whose own
[1]belongs to the succession rather than to its first end — along with thesuccession redefines s : …spelling. A missingby, a missing target, a missingthenand a trailing
comma are still reported.at,while,mergeanddecideare names in a.kermlfile, where they are not KerML
keywords, asabout,bindand the other SysML-only words already were. The remaining KerML
feature-prefix forms —abstract var feature x [0..*];— are still not parsed and are recorded
as such.
Imports and visibility
- A
publicimport is re-exported to importers of the importing namespace, transitively;
before, re-export stopped after one namespace. A root-level import is visible from a nested
package, an imported name may prefix a qualified name, and an import cycle terminates instead
of recursing. Aprotectedimport is reachable through a specialization of the importing
namespace and from nowhere else. - An import with no visibility indicator warns. The grammar requires one, so
import Lib::*;
now reports[syntax/import-visibility] import without a visibility indicator: SysML v2 requires public, private or protected before 'import'. It is a warning at the syntax tier and
analysis continues through it;exposeis exempt, its grammar supplying protected visibility
implicitly.
SysML notation the parser was refusing
- A connector, interface or flow written with shorthand ends may have a body:
connect x.p to r.p { ... },interface b1.p to b2.p { ... }andflow s1.x to s2.x { ... }
parse with their members. An unclosed body, an interface withouttoand an unterminated flow
body are still reported. - An accept node is an action statement, so
then action engineStopped accept engineOff : EngineOff;parses and executes. An accept in a loop or branch body remains unsupported by
lowering and is reported when reached, rather than accepted and silently skipped. connectrequires its ends and reads a leading multiplicity on each of them:
connect [1] a to [1] b.connect;,connect { ... }and a missing target are reported where
some were accepted and misrepresented.- Eleven words that no grammar production reserves are names again,
onandvaramong
them, sostate on;,part on : On;andattribute var : ScalarValues::Integer;parse as
declarations namedonandvar. Each word remains a keyword in the position its grammar
gives it, sovar a : Integer;without a kind is still reported. - A modifier before a kind prefix keeps the kind, which was dropped from the tree and from
every diagnostic that read it.
Notation accepted beyond the grammars now says so
- A construct we accept that no pinned production admits warns at the syntax tier, from the
conformance audit:namespace,region,choice,junction, an entry/exit/history point,
defer, theinitial/final/decisionnode spellings, andtransition <source> to <target>;.namespace P { }in a.sysmlfile reports "namespaceis KerML notation: the
SysML v2 grammar has no namespace declaration, so writepackagehere or move the declaration
to a .kerml file";featured byin a.sysmlfile reports the same for the featuring clause.
The same notation in a.kermlfile is silent, because there it is standard. These are
warnings — the models that use this notation still parse, and no higher tier is gated — and the
REPL warns for its own buffer, which it reads as SysML.
Analysis corrections
- An alias is followed through every type relationship — specialization, typing, subsetting,
redefinition, multiplicity and invocation inference — sopart def AvionicsLRU :> Box, where
BoxaliasesRectangularCuboid, no longer reports "part cannot specialize alias (kind
mismatch)" and inherits what the aliased definition declares. An alias cycle terminates. - An invocation of an aliased action or function is type-checked against its parameters
instead of going unchecked. - A declaration with a short name is listed once among a document's members, not twice.
- A part typing check that read an unrelated declaration is gone, with the diagnostics it
produced on valid models.
Diagrams in the VS Code extension
SysML: Open Diagramrenders the open model in a panel and keeps it current as the file
changes, over three new LSP requests —opensysml/render,opensysml/viewsand
opensysml/renderChanged— documented indocs/reference/lsp.md. The command is gated on the
server capabilityexperimental.openSysmlRender, and the panel is read-only and makes no
network request.- Go-to-definition locates the identifier of a rendered element, not only its declaration.
Four pilot rules this release does not implement
Recorded in docs/project/spec-compliance.md with the divergence each one produces, rather than
left to be discovered: featuring-type access on a subsetting (validateSubsettingFeaturingTypes),
flow-end subsetting (validateFlowEndSubsetting, so flow of Fuel from tank to thruster; is
accepted here and rejected by the pilot), invocation instantiated type
(validateInvocationExpressionInstantiatedType, so part w = Widget(); on a part def is
reported by the pilot and by nothing here), and model-level evaluability of a filter, which
diverges in both directions.