Spec-vs-Pilot Gap Register¶
Overview¶
OpenSysML is validated largely by differential harnesses against the OMG SysML v2 pilot
implementation. Those harnesses find where OpenSysML disagrees with the pilot; they cannot find
where both fall short of, or read ambiguously, the KerML 1.0 and SysML v2 specification text.
The redefinition of a feature chain (attribute :>> mid.leaf.value = 99.0;) was such a case: both
tools accepted it and both silently gave it no effect, until the specification authors confirmed
that the chain's host feature is redefinable (fixed in #634).
This register lists every place found where OpenSysML's behaviour rests on "the pilot does this" or on no recorded rationale at all, and where the pilot itself is known or suspected to fall short of, or to interpret ambiguously, the specification. Each retained item carries the model text, what each tool does, the clauses that bear on it, an assessment, and a question that could be put to the specification authors. Items are ranked by modeler impact: silent wrong results > spurious errors > missed diagnostics > cosmetic.
Pilot: SysML v2 Pilot Implementation
release 2026-08, commit 692170b71867353b8f90341e61556f49a5beb0e5 — the pin in
scripts/pilot-pin.sh. Where a source record observed an earlier release (2026-05, 2026-07),
the item says so; those observations have not been re-run against 2026-08 for this register
unless stated.
Specification text: the clause numbers and quotations below were taken from the OMG
publications downloaded on 2026-09-27: KerML 1.0 at https://www.omg.org/spec/KerML/1.0/PDF,
whose title page reads formal/2026-03-01, and SysML v2.0 Part 1 (Language) at
https://www.omg.org/spec/SysML/2.0/Language/PDF, formal/2026-03-02. The KerML revision
requested for this audit, formal/2025-12-01, is not what that URL serves today and no copy exists
in the repository or the pilot pin (scripts/download-pilot-grammars.sh fetches the pilot's Xtext
grammars, not the OMG documents). Clause numbers are therefore those of formal/2026-03-01/-02; a
reader checking them against formal/2025-12-01 should expect the same numbering but must verify.
Every "the specification says" statement below is backed by text found in those two PDFs; every
"the pilot does" statement is either an observation recorded in the linked docs/project/ record
or a reading of the pinned validator source, and is labelled as one or the other.
The register does not change any behaviour. Behaviour changes are follow-ups, each of which should cite the item it closes.
Summary table¶
The Class column is the audit's verdict on the item: spec clear, both short (the specification says X, both tools do Y), spec ambiguous (needs an author opinion), pilot short, ours follows spec (a pilot gap this register keeps because differential runs alone would have accepted the pilot's silence), or pilot-following justified (a candidate that turned out to rest on a clause after all — retained so it is not re-audited).
| # | Impact | Item | Pilot | OpenSysML | Class |
|---|---|---|---|---|---|
| 1 | Silent wrong result | Redefinition whose target is a feature chain (the motivating case) | accepts, no effect | redefines the chained feature (since #634) | spec clear (author-confirmed); pilot short |
| 2 | Silent wrong result | Natural / Natural evaluates to a Rational against a Natural[1] return declaration |
evaluates 5/2 to 2.5 |
types the operator Rational, as the pilot; the named function NaturalFunctions::'/' follows its declaration |
spec ambiguous (library text vs. evaluator) |
| 3 | Silent wrong result | Two enabled branches of one choice (state machine or decide); which is taken |
no executor; not exercised | first enabled in declaration order | spec silent |
| 4 | Silent wrong result | Filter conditions that read through a multi-hop feature chain, or a computed value, rooted in an unfeatured feature | evaluates them | reported as not evaluated and the filter not applied; fixed in #642 | spec clear; ours short |
| 5 | Silent wrong result | Repeated literal values bound to a unique multi-valued feature (Integer[*] = (1, 1)) |
silent | reports the duplicate | spec clear; pilot short |
| 6 | Silent wrong result | Invocation leaving a required in parameter unbound (F(1.0) with two inputs) |
silent | advisory only | spec ambiguous (no constraint stated) |
| 7 | Spurious error | Bare import X::*; without a visibility indicator |
parse error | warning, then imports | pilot-following justified by the grammar; severity is ours |
| 8 | Spurious error | send x to port warned to use via |
warning (checkSendActionUsage) |
same warning | spec has no such constraint; pilot-following |
| 9 | Spurious error | validateClassifierMultiplicityDomain fired on a classifier reached through an alias |
error on a valid model | not reported | spec clear; pilot short (filed upstream) |
| 10 | Spurious error | A calculation usage named as a value is the calculation, not its result (n as String) |
warns | warns, as the pilot | spec ambiguous |
| 11 | Missed diagnostic | Eight control-node succession constraints (SysML §8.3.17) | unimplemented TODOs |
reported | spec clear; pilot short |
| 12 | Missed diagnostic | Non-Boolean transition guard | accepted with the full library | rejected | spec clear; pilot short |
| 13 | Missed diagnostic | Indistinguishable memberships reported as a warning; repeated anonymous perform a; depends on bodies in the pilot |
warning; silent for bodiless repeats | warning for every repeat | spec clear (a validation constraint), both tools under-report |
| 14 | Missed diagnostic | Constraints the pilot declares but never reports, absent from the published specification (validateSubsettingPortionConformance, validateBindingConnectorArgumentTypeConformance, validatePartUsageType, validateItemUsageType, …) |
declared, unreported | not implemented | needs author opinion: are these normative? |
| 15 | Missed diagnostic | Lower-tier errors suppress later diagnostics the pilot still reports | reports secondary diagnostics over unresolved names | gates higher tiers | not a spec matter; recorded so it is not mistaken for one |
| 16 | Missed diagnostic | Body expression { … } as a value typed BooleanEvaluation when its result is Boolean |
so typed | as the pilot | spec ambiguous (implied typing of an expression body) |
| 17 | Cosmetic | Identifiers restricted to ASCII letters, digits and _ |
rejects non-ASCII basic names | same | pilot-following justified by KerML §8.2.2.3 |
| 18 | Cosmetic | Every reference subsetting after the first is reported | reports each extra | same | pilot-following justified by KerML §8.3.3.3 (at most one) |
| 19 | Cosmetic | part p : ItemDef; — a part typed only by a non-part definition |
accepted | accepted | pilot-following justified: parts supplies Part through subsetting |
| 20 | Cosmetic | Alias identity: an alias is a name, not an element |
resolves to the aliased element | fixed to match | pilot-following justified by KerML §8.3.2.4 (Membership) |
Grouped inventories follow the detailed items: the spec-compliance.md rows whose
justification is the pilot or nothing,
the code comments that rest on the pilot,
and the negative-corpus cases.
Detailed items¶
1. Redefinition whose target is a feature chain¶
Model text
part def Leaf { attribute value : Real = 1.0; }
part def Mid { part leaf : Leaf; }
part def Top { part mid : Mid; attribute :>> mid.leaf.value = 99.0; }
Pilot: parses the declaration and reports nothing; mid.leaf.value keeps 1.0
(observation recorded in the #634 discussion; not a diagnostic difference, so no differential
harness saw it).
OpenSysML: the same until #634; since #634 the chain's host feature redefines value and the
evaluator answers 99.0.
Specification: KerML §7.3.4.6 Feature Chaining — a feature chain in a feature declaration
"parses to a feature hosting the chain"; §8.3.3.3.4 Feature: chainingFeature, and
deriveFeatureType: "If the Feature has chainingFeatures, then the union also includes the types
of the last chainingFeature." §8.3.3.3.8 Redefinition places no restriction on a redefined
feature being chained. The reading that the host is redefinable was confirmed with the
specification authors (recorded in #634).
Assessment: spec clear, both tools were short; ours is fixed. Kept as item 1 because it is
the template for everything below: no rule in spec-compliance.md cited a clause for it, and the
implicit justification was the pilot's silence.
Question for the authors: none outstanding — closed by the confirmation recorded in #634.
2. Natural / Natural — the declared Natural[1] return against the pilot's Rational answer¶
Model text
attribute a : ScalarValues::Natural = 5;
attribute b : ScalarValues::Natural = 2;
attribute q : ScalarValues::Natural = a / b;
Pilot: evaluates a / b to LiteralRational 2.5 and reports nothing on q
(observation, pilot 2026-05, recorded in omg-issues.md).
Its evaluator dispatches on the value's kind, so the division runs through
RationalFunctions::'/'.
OpenSysML: the type checker types Natural/Natural and Integer/Integer division as
Rational "as the reference evaluator types it" (spec-compliance.md, operator result types);
the runtime answers a Real, and a non-whole quotient bound to a Natural-typed feature is
reported rather than truncated. The function called by name, NaturalFunctions::'/'(a, b),
follows its declaration and reports a non-whole quotient as an arithmetic-domain error.
Specification: KerML §9 Kernel Function Library, NaturalFunctions:
function '/' specializes IntegerFunctions::'/' { in x: Natural[1]; in y: Natural[1]; return : Natural[1]; }
(quoted from the vendored library, which is the normative library text). IntegerFunctions::'/'
returns Rational[1]. A specializing function's return that is Natural where the general
function's is Rational is well-formed as a redefinition; the text says nothing about how an
operator on two Natural operands is dispatched.
Assessment: spec ambiguous. The library declares a Natural result and the pilot never
produces one; OpenSysML follows the pilot for the operator and the declaration for the named
function, which is two answers to one question. A modeler binding a / b to a Natural attribute
gets a silently non-integral value from the pilot and an error from us.
Question for the authors: is NaturalFunctions::'/' meant to return Rational[1] (matching
IntegerFunctions::'/'), or is a conforming evaluator expected to truncate (or reject) a
non-whole quotient of two Natural operands written with the / operator?
3. Two enabled branches of one choice¶
Model text (the shape of fixture state_choice_dynamic_conflict)
state def M {
attribute level : ScalarValues::Integer; attribute route : ScalarValues::Integer;
state idle; state low; state high;
transition first idle accept Go do assign level := 8 then pick; // pick is a choice
transition first pick if level > 5 then low; // both guards hold
transition first pick if level > 7 then high;
}
Pilot: the pinned pilot has no state-machine executor; no observation.
OpenSysML: reads the branches in declaration order and takes the first enabled one, recording
the choice; exploration reports the admissible set {low, high} (recorded as Open: which
enabled branch is taken in behavior-semantic-oracle.md).
Specification: ControlPerformances.kerml DecisionPerformance::outgoingHBLink :
HappensBefore[1] — exactly one branch follows; TransitionPerformances.kerml places the
segment's effect before what the segment leads to, so both guards are read after level := 8.
Nothing found in the library or in SysML §8.3.18 (TransitionUsage) ranks two branches whose
guards both hold. (SysML §8.3.17 DecisionNode has the same shape for actions.)
Assessment: spec silent. Any deterministic choice is an implementation policy; a model whose guards overlap has an execution result that differs between conforming executors without any diagnostic.
Question for the authors: when more than one outgoing transition of a choice (or succession
of a decide node) has a guard that evaluates true, is the choice implementation-defined, is
declaration order normative, or should a validator report the overlap?
4. Filter conditions read through a feature chain¶
Model text
package P {
feature root { feature n : ScalarValues::Integer = 1; feature m : ScalarValues::Integer = n + 1;
feature inner { feature k : ScalarValues::Integer = 3; } }
}
package Q { private import P::*[root.inner.k == 3]; } // likewise [root.m == 2]
Pilot: evaluates the condition (recorded in the code comment chainLimitation of
internal/semantic/semantics/filter.go before #642: "the reference accepts chains rooted in a
feature with no featuring type").
OpenSysML: before #642, only a one-hop chain to a literal value (root.n == 1) was evaluated;
root.inner.k and root.m were reported as not evaluated and the filter was not applied. #642
evaluates every hop and the read feature's value expression; a chain through a feature with its
own value, a non-numeric/boolean terminal value, or a metaclass feature still reports the
limitation.
Specification: KerML §8.3.4.13.2 ElementFilterMembership,
validateElementFilterMembershipConditionIsModelLevelEvaluable: "The condition Expression must be
model-level evaluable." §8.3.4.8.5 FeatureReferenceExpression::modelLevelEvaluable: evaluable
if the referent "has no featuringTypes and, if it has a FeatureValue, the valueExpression is
model-level evaluable." §8.3.4.8.4 FeatureChainExpression is an OperatorExpression over its
argument, so a chain rooted in an unfeatured feature is evaluable when the rooted reference is.
Assessment: spec clear, ours is short and the pilot is right; the limitation is honest (reported, not silent) but a filtered import with an unfiltered result is a wrong model. Listed because the only rationale recorded is the pilot's acceptance, not the clause above.
Question for the authors: none needed for the rule; the follow-up is #642.
5. Repeated values bound to a unique feature¶
Model text
attribute xs : ScalarValues::Integer[*] = (1, 1);
attribute os : Collections::OrderedSet { :>> elements = (1, 1, 2); }
Pilot: silent (observation, pilot-differential.md).
OpenSysML: reports the repeated value on the unique feature.
Specification: KerML §7.3.4.2: "The default is that the feature is unique"; §8.3.3.3.1
+isUnique : Boolean = true; nonunique is the one piece of concrete syntax that sets it
false. Collections.kerml declares Collection::elements nonunique and every redefinition
carries a note "Redefinition of 'elements' is unique by default", with no nonunique keyword —
the redefinition therefore is unique by the §7.3.4.2 default (the note is descriptive).
Recorded in omg-issues.md.
Assessment: spec clear, pilot short; kept because a differential run adjudicated it as
"only ours" and a maintainer could reasonably have read that as a spurious diagnostic. The
residual question is about the library: whether the UniqueCollection redefinition relying on the
default is intended, or whether Collection::elements being nonunique was meant to be inherited.
Question for the authors: is a value binding that repeats a value on a feature with
isUnique = true a well-formedness error (to be reported by a validator), an evaluation-time
matter, or neither?
6. Invocation leaving a required input parameter unbound¶
Model text
Pilot: the SysML and KerML validators report nothing; the evaluator forms and evaluates the
call (observation, pilot 2026-07, omg-issues.md).
OpenSysML: adjudicated the pilot's behaviour as the specification's reading and reports an advisory only.
Specification: KerML §8.3.4.8.8 InvocationExpression constrains the arguments an
invocation writes (validateInvocationExpressionParameterRedefinition,
validateInvocationExpressionNoDuplicateParameterRedefinition) and states no constraint on
parameters left without an argument. A bare input parameter has the effective range [0..*];
y[1] explicitly requires one value, so the instance described has a feature with no value
where one is required, but no constraint on the expression says so.
Assessment: spec ambiguous; both tools accept, and a modeler gets a result computed with an unbound operand (the pilot) or an advisory (ours). This is the closest analogue to item 1: the "validates clean" verdict rests on the pilot.
Question for the authors: is an InvocationExpression that leaves an input parameter of the
invoked type unbound — no argument, no default, lower bound 1 — intended to validate clean, and
if so what value does its result have?
7. Bare import without a visibility indicator¶
Model text
Pilot: mismatched input 'import' expecting '}' — a parse error that also breaks the rest of
the file (observation, pilot-differential.md).
OpenSysML: parses it, reports a warning, and imports as if private.
Specification: KerML §8.2.3.4.2 Import = visibility = VisibilityIndicator 'import' ...
with VisibilityIndicator = 'public' | 'private' | 'protected' — the assignment is not optional,
unlike the member prefix, where the indicator is. The SysML grammar (SysML.xtext
ImportPrefix) matches.
Assessment: pilot-following is justified by the grammar clause; the specification is not
ambiguous. What is ours alone is the recovery (warning rather than error), which
pilot-differential.md records as deliberate. Listed because the project record says the
question of mandatory visibility "is not settled", which the grammar text above settles.
Question for the authors: none about the grammar. A question worth putting is whether a
tool may recover a bare import as private import (the pilot's reading of the default
visibility for members) without being non-conforming.
8. send … to port warned to use via¶
Model text
Pilot: warns that a receiver that is a PortUsage should be given with via
(SysMLValidator.checkSendActionUsage; reading of the pinned source, and observed).
OpenSysML: validateSendActionUsageReceiver — the same warning, "the specification places no
such constraint, so the diagnostic is a warning as the reference's is" (spec-compliance.md).
Specification: SysML §8.3.17.15 SendActionUsage: deriveSendActionUsageReceiverArgument
("The receiverArgument of a SendActionUsage is its third argumentExpression"),
validateSendActionParameters; nothing in the constraint list distinguishes a port from any other
receiver. The via clause populates the sender/receiver pair per §7.16 textual notation, but
the text found does not forbid a port as a to target.
Assessment: the specification has no such constraint; the warning exists because the pilot's does. It is advisory, so its cost is a spurious warning on a model the specification accepts.
Question for the authors: is send x to <port> (a PortUsage as receiver, rather than as
the via argument) meant to be discouraged or ill-formed, or is the pilot's warning a style
preference?
9. validateClassifierMultiplicityDomain fired through an alias¶
Model text
Pilot: reports "A classifier's multiplicity has no featuring type" on a valid model in which the classifier is reached through an alias or reference membership (observation, shape recorded in validation-constraints.md and omg-issues.md; filed as Systems-Modeling/SysML-v2-Pilot-Implementation#802).
OpenSysML: does not report it; the multiplicity is owned by C, which has no featuring type.
Specification: KerML §8.3.3.2.2 Classifier, validateClassifierMultiplicityDomain: the
multiplicity of a Classifier, if any, must have no featuringType. §8.3.3.1.10 Type:
multiplicity is the Multiplicity among the type's owned members, not one reached through an
alias or reference membership.
Assessment: spec clear, pilot short; OpenSysML declines to follow the pilot. Retained so that the next differential run does not re-open the disagreement.
Question for the authors: none; this is a pilot defect already filed upstream.
10. A calculation usage named as a value is the calculation, not its result¶
Model text
calc def Name { return : ScalarValues::String; }
part def P { calc n : Name; attribute s = n as ScalarValues::String; }
Pilot: warns that n does not conform to String (observation recorded in the code comment
in internal/semantic/semantics/operator_conformance.go).
OpenSysML: featureResultTypes treats n as the calculation, as the pilot does, and warns.
Specification: KerML §7.4.9.4 Base Expressions — a feature reference expression whose
referent is an Expression evaluates to the result of that expression when it is
model-level evaluable (§8.3.4.8.5); SysML §8.3.19.3 CalculationUsage is an Expression. Whether
naming a calculation usage as an operand denotes the calculation (a feature typed by a function)
or its result (its result parameter) is not stated in one place; the two readings give
different conformance verdicts.
Assessment: spec ambiguous. The consequence is a warning on a model that, under the other reading, is well-typed.
Question for the authors: when a calc usage is named as an operand of a cast or an operator,
does the name denote the calculation feature (typed by the calculation definition) or its
result parameter?
11. Eight control-node succession constraints the pilot does not implement¶
Model text
action def A {
fork f; action a; action b;
first a then f; first b then f; // two incoming successions to a fork
}
Pilot: SysMLValidator declares nine ControlNode constants and reports only
validateControlNodeOwningType; the eight succession constraints are TODOs (reading of the
pinned source, recorded in omg-issues.md).
OpenSysML: reports each (internal/check/passes/control_node.go); the nine ours-only
negative-corpus cases (inventory C) are these.
Specification: SysML §8.3.17.2–§8.3.17.6 ControlNode, DecisionNode, ForkNode,
JoinNode, MergeNode — e.g. validateForkNodeIncomingSuccessions "A ForkNode must have at
most one incoming Succession", validateJoinNodeOutgoingSuccessions,
validateMergeNodeOutgoingSuccessions, validateDecisionNodeIncomingSuccessions, and the
outgoing/incoming counterparts.
Assessment: spec clear, pilot short, ours follows the specification. Retained because the pilot's silence on these would have been indistinguishable from acceptance in a differential run.
Question for the authors: none.
12. Non-Boolean transition guard¶
Model text
Pilot: checkTransitionFeatureMembership implements the check and its own Xpect fixture
expects "Must be a Boolean expression." — but only with a reduced library; with the full library
loaded the guard is accepted (observation, pilot 2026-07,
omg-issues.md).
OpenSysML: rejects the guard.
Specification: SysML §8.3.18.8 TransitionFeatureMembership,
validateTransitionFeatureMembershipGuardExpression: a guard transitionFeature must be an
Expression whose result specializesFromLibrary('ScalarValues::Boolean').
Assessment: spec clear, pilot short in its shipped configuration.
Question for the authors: none.
13. Indistinguishable memberships: severity, and anonymous performed actions¶
Model text
Pilot: Duplicate of other owned member name as a warning; for perform a; perform a;
it warns only when the repeats have bodies (observation, pilot 2026-07,
adjudications.md).
OpenSysML: a warning for every repeat, bodies or not; part def A; part def A; is likewise
a warning.
Specification: KerML §8.3.2.4.5 Namespace, validateNamespaceDistinguishibility (so spelt in the PDF): "All
memberships of a Namespace must be distinguishable from each other." §8.3.2.4.3
Membership::isDistinguishableFrom compares memberShortName/memberName. §8.3.3.3.4
Feature::effectiveName: a feature with no declared name takes the effective name of its
namingFeature(); SysML §8.3.17.14 PerformActionUsage::namingFeature "is its performedAction".
Two perform a; therefore both have memberName a, whatever their bodies.
Assessment: spec clear on both counts. The rule is a validate… constraint — a violating model
is not well-formed — so a warning under-reports it; both tools do so (a warning was chosen so that
duplicated names in the training corpus do not fail its clean gate). The body-sensitivity is the
pilot's alone; ours follows the specification.
Question for the authors: is a namespace with indistinguishable memberships intended to be
rejected (an error) or is a tool free to report it as a warning and keep resolving? And for
two perform a; in one body, are the memberships indistinguishable regardless of whether the
usages have bodies?
14. Constraints the pilot declares that the published specification does not contain¶
Model text
classifier C { portion feature p : C; }
classifier D :> C { feature q :> p; } // subsets a portion feature, is not itself a portion
Pilot: KerMLValidator/SysMLValidator declare the constants and messages
validateSubsettingPortionConformance ("A feature subsetting a portion feature is a portion"),
validateBindingConnectorArgumentTypeConformance, validatePartUsageType,
validateItemUsageType and others listed under declared, unreported in
validation-constraints.md; none is reported by any @Check
(reading of the pinned source).
OpenSysML: does not implement them.
Specification: none of these names appears in KerML formal/2026-03-01 or SysML
formal/2026-03-02 (a search of both extracted texts). The neighbouring constraints that do
exist are cited in validation-constraints.md. validatePartUsagePartDefinition (SysML
§8.3.11.3) exists and is satisfied by checkPartUsageSpecialization for every part usage (item
19); validatePartUsageType does not.
Assessment: needs author opinion. Either these are constraints that were dropped from the published text and the pilot's declarations are stale, or they are intended and the text is missing them. Neither tool reports them, so a model violating one passes both.
Question for the authors: are validateSubsettingPortionConformance and
validateBindingConnectorArgumentTypeConformance (a feature subsetting a portion feature must be
a portion; a binding connector's ends must have conforming types) normative constraints that a
future revision will carry, or were they deliberately withdrawn?
15. Tier gating suppresses diagnostics the pilot still reports¶
Model text
Pilot: reports the unresolved Nowhere and then type-checks the partially resolved model,
reporting Bound features should have conforming types on b (observation,
pilot-differential.md, the class of secondary diagnostics over an
unresolved reference).
OpenSysML: reports Nowhere and gates the type tier behind it (AGENTS.md §4), so b is not
reported until a resolves.
Specification: the specification defines well-formedness, not diagnostic ordering; no clause bears on it.
Assessment: not a specification question. Listed so the difference is not mistaken for a missing rule: the type-conformance rule exists on our side and fires once the lower tier is clean.
Question for the authors: none.
16. { … } written as a value is typed as an evaluation¶
Model text
Pilot: types the body expression as a BooleanEvaluation when its result is Boolean
(observation recorded in the code comment bodyExprType, internal/semantic/semantics/valuetype.go).
OpenSysML: the same, "as the pilot reads it".
Specification: KerML §7.4.9.4 Base Expressions: an expression body { … } "is an
expression whose result is that of its result expression"; §8.3.4.8 Expression implied
specialization is of Performances::Evaluation. The text found does not say the body expression
implicitly specializes BooleanEvaluation when its result is Boolean — that is the pilot's
implied-typing rule.
Assessment: spec ambiguous at the level of implied typing; the modeler-visible effect is a
conformance verdict on cond, which the two readings may differ on.
Question for the authors: does an expression body whose result is Boolean implicitly
specialize Performances::BooleanEvaluation, or only Performances::Evaluation?
17. ASCII-only basic names¶
Model text
Pilot: rejects; the name must be quoted 'Größe' (observation, negative corpus).
OpenSysML: the same.
Specification: KerML §8.2.2.3 Names: BASIC_NAME = BASIC_INITIAL_CHARACTER
BASIC_NAME_CHARACTER*, ALPHABETIC_CHARACTER = any character 'a' through 'z' or 'A' through 'Z';
UNRESTRICTED_NAME allows "any printable character other than backslash or single_quote"
between single quotes.
Assessment: pilot-following justified by clause; the code comment cites the pilot where it could cite §8.2.2.3.
Question for the authors: none.
18. Every reference subsetting after the first is reported¶
Model text
Pilot / OpenSysML: each ::> after the first is reported (code comment in
internal/check/passes/w8c_reference_subsetting.go: "as the pilot does").
Specification: KerML §8.3.3.3.4 Feature: ownedReferenceSubsetting : ReferenceSubsetting
[0..1] — at most one. Which of several to report is a diagnostic-placement choice.
Assessment: pilot-following justified by the multiplicity; only the placement is the pilot's.
Question for the authors: none.
19. A part typed only by a non-part definition¶
Model text
Pilot / OpenSysML: accepted (both).
Specification: SysML §8.3.11.3 PartUsage, validatePartUsagePartDefinition: "At least one
of the itemDefinitions of a PartUsage must be a PartDefinition." But checkPartUsageSpecialization
requires every PartUsage to specialize Parts::parts, whose type is Parts::Part, and KerML
§8.3.3.3.4 deriveFeatureType makes a feature's type "the union of the types of its typings and
the types of the Features it subsets", so partDefinition is never empty. §7.10's note says as
much: "every part usage is always directly or indirectly defined by at least one part definition,
implicitly if not explicitly."
Assessment: pilot-following justified by clause; the validation-constraints.md row that
marks the constraint "unobservable" is right for the reason above, and can cite it.
Question for the authors: none.
20. An alias is a name, not an element¶
Model text
Pilot: test::A_alias resolves to the element whose qualified name is test::A
(observation, pilot-xpect.md).
OpenSysML: answered test::A_alias until the alias was made a second membership of the
existing element; now the same as the pilot.
Specification: KerML §8.3.2.4.3 Membership: an alias declares a Membership whose
memberElement is the existing element and whose memberName is the alias; §7.2.5 Namespaces
(alias members).
Assessment: pilot-following justified by clause and fixed. Listed because the adjudication record says "the pilot was right" without the clause.
Question for the authors: none.
Inventory A — spec-compliance.md rows justified by the pilot or by nothing¶
Every row of docs/project/spec-compliance.md was classified as (a) citing a specification
clause, (b) citing the pilot or reference behaviour, or (c) citing neither. The extraction script
and its output are described under How this list was produced.
Of the rows examined, 442 cite a clause, 290 cite the pilot or reference (some also cite a
clause), and 217 cite neither. The (b) and (c) rows fall into the groups below; a row is
semantic when it decides what a model means or whether it is well-formed, and implementation
when it describes a surface the specification does not govern.
Section of spec-compliance.md |
(b) pilot-citing | (c) uncited | Nature | Disposition |
|---|---|---|---|---|
| Current Implementation Status | 2 | 3 | status prose | none needed |
| Detailed Semantic Compliance Map | 290 | 217 | semantic | see below |
| What We Don't Yet Support | 3 | 3 | limitations | none needed |
| Model Persistence and RDF Interchange | 4 | 25 | implementation (RDF vocabulary, round-trip) | not a spec matter; the SysML v2 API/RDF mapping is a separate OMG document not audited here |
| Source-Preserving Model Editing | 1 | 12 | implementation | none needed |
| gRPC Service Layer | 3 | 32 | implementation | none needed |
| Language Server | 1 | 4 | implementation | none needed |
| Analysis Engines | 1 | 4 | implementation | none needed |
| Constraint Solving | 8 | 50 | implementation (SMT encoding) | none needed; the encoding is an OpenSysML extension |
Within the Detailed Semantic Compliance Map, the pilot-citing rows are of four kinds:
- Rows whose rule cites a clause and whose wording, severity or placement cites the pilot (the majority of the 290). These are conformance rows; the pilot reference is about the diagnostic text or where it is anchored. Nothing to adjudicate beyond items 13 and 18 above.
- Rows whose rule itself rests on the pilot — the source of items 2, 8, 10 and 16, plus the rows grouped as "SysML Notation the Reference Accepts and We Reject — the ten classes", which record where we are stricter than the pilot with a grammar citation for each (no gap).
- Rows recording a pilot gap ("the pinned pilot implements only …", "adjudicated as pilot gaps") — items 9, 11, 12, and the declared, unreported set of item 14.
- Rows on evaluation gating ("matching the pilot's model-level-evaluable gating",
internal/semantic/semantics/eval.go) — the gating is KerML §8.3.4.8modelLevelEvaluable, so the citation should be the clause; behaviourally covered by item 4.
The 217 uncited semantic rows are of two kinds. Most are implementation-mapping rows (rule →
file:function → test → status) whose rule name is a validate…/check… constraint name from
the specification, so the name is the citation; this audit checked the names quoted in the
detailed items against the PDF text but did not verify every one of the 217 individually, which
is the first thing a re-run should do (search the extracted PDF text for each name). The rest are
OpenSysML-specific passes (multiplicity bound ordering, specialization cycles, unresolved
references) whose justification is well-formedness rather than a clause; none decides model
meaning.
Inventory B — Go comments that rest on the pilot¶
Of the pilot-mentioning comments in non-test sources under internal/ and tools/, those that
record a behaviour decision are:
| File | Decision | Item |
|---|---|---|
internal/semantic/semantics/operator_conformance.go featureResultTypes |
a calculation usage as an operand is the calculation, not its result | 10 |
internal/semantic/semantics/filter.go chainLimitation |
chains rooted in an unfeatured feature are evaluable (the reference does; we do not) | 4 |
internal/semantic/semantics/valuetype.go bodyExprType |
{ … } is a BooleanEvaluation when Boolean |
16 |
internal/semantic/semantics/eval.go |
unsupported-evaluation gating "matching the pilot's model-level-evaluable gating" | 4 (rule is KerML §8.3.4.8) |
internal/check/passes/w8c_reference_subsetting.go |
every extra reference subsetting reported | 18 |
internal/check/passes/w10b_usage_typing.go |
usage-typing diagnostics worded and placed as the pilot's | justified: SysML /…Definition {redefines definition} typing (e.g. /occurrenceDefinition : Class) |
internal/check/passes/w8d_connector_featuring.go |
connector-end featuring checks alongside the pilot's | the file cites its clauses; the pilot reference is for placement |
internal/check/passes/variant_owner.go |
variant-owner check | justified: cites SysML §7.20 alongside the pilot |
internal/check/passes/behavior/state_transition.go |
diagnostic wording from the pilot | wording only |
The remaining hits are rendering styles, DOT/diagram output, XMI and API shape, keyword lists derived from the pilot grammars, and test-harness plumbing — implementation compatibility, not model semantics. The full hit list with its per-hit classification is reproduced by the command under How this list was produced.
Inventory C — negative corpus¶
tools/referee/reject/testdata/negative/ holds 306 cases; the committed baseline is
bothReject 297, pilotOnlyRejects 0, oursOnlyRejects 9, bothAccept 0. Every case carries a
rationale line, and every rationale cites either a specification clause or a grammar production
(the one that looked uncited, grammar/g60-alias-keyword-as-name.sysml, cites AliasMember /
Identification, terminal ID, i.e. KerML §8.2.2.3 — item 17's clause). No case is rejected
because the pilot rejects it without a clause. The nine oursOnlyRejects are the control-node
succession cases of item 11 — cases where the pilot accepts and the specification rejects — and
are the negative corpus's evidence for that item.
How this list was produced, and how to keep it current¶
The register is an audit of four sources, each re-runnable from the repository root:
spec-compliance.mdrows. Every table row and list item under each##section was classified by regular expression: (a) mentionsKerML/SysMLwith a§or8.xclause number; (b) mentionspilot,reference,Xpect,jupyter-sysml-kernel,SysMLValidatororKerMLValidator; (c) neither. A row can be both (a) and (b). Re-run with a short script overdocs/project/spec-compliance.mdand compare the per-section counts in Inventory A; a count that moves means a row was added or reworded and should be classified into one of the four kinds above.- Adjudication records.
pilot-differential.md,pilot-corpora.md,pilot-xpect.md,pilot-rejection.md,pilot-execution-referee.md,adjudications.md,validation-constraints.md,omg-issues.md,behavior-semantic-oracle.md,training-examples.md,errata-overlay.mdandtools/oracle/errata/errata.gowere searched forpilot is right,follow(s|ing) the pilot,as the pilot,ambiguous,needs (an )?opinion,unclear,not settled,spec(ification)? is silent,Open:,Question, not a bug report. Each hit was read in context; the errata registry had none (its entries carry clause citations). - Go sources.
rg -n -i 'pilot|spec is silent|not in the spec|ambiguous|unclear|TODO' internal tools --glob '!*_test.go', then each hit was classified as a behaviour decision, wording/placement, or implementation compatibility. Only the first kind is listed. - Negative corpus. Every case's rationale line was checked for a clause or grammar citation
against the committed referee baseline (
tools/referee/reject, see pilot-rejection.md).
Specification text. Download the two PDFs from the OMG URLs in the overview, extract text
(any PDF text extractor; this audit used pypdf), and grep for the constraint names quoted in an
item. Record the document numbers printed on the title pages; if they differ from the ones stated
above, re-verify every clause number before editing an item.
When to add an item. Any change that (a) adds a rule or a behaviour whose rationale in
spec-compliance.md, a code comment or a PR is "the pilot does this" without a clause, (b)
adjudicates a differential disagreement as "the pilot is right" or "ambiguous", or (c) declines
to evaluate or report something the specification requires, gets a row here with the six fields
of the detailed items. Close an item by linking the PR or the upstream answer that settles it, and
move it to a Closed section rather than deleting it, so that the next audit does not re-derive
it.
Author questions. The open questions are items 2, 3, 5, 6, 7, 8, 10, 13, 14 and 16. They are drafted for a maintainer to raise with the specification authors (as with the nested-redefinition question); nothing has been posted upstream from this register, and the register should be updated with the answer when one arrives.