diff --git a/docs/project/omg-issues.md b/docs/project/omg-issues.md index f20593dc3..d1f0a86db 100644 --- a/docs/project/omg-issues.md +++ b/docs/project/omg-issues.md @@ -775,8 +775,8 @@ and not from a disagreement alone. | `org.omg.sysml.xtext` — `checkTransitionFeatureMembership` (`validateTransitionFeatureMembershipGuardExpression`) | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | `TransitionUsage_invalid.sysml.xt` expects `Must be a Boolean expression.` at `if "test"`, yet the pinned validator with the full standard library accepts a `String` or arithmetic guard in the same shape | [pilot-rejection.md](pilot-rejection.md#constraints-the-pilot-declares-but-does-not-enforce) — established by running the pinned pilot's own SysML validator on the fixture's shape, not from a disagreement alone | **not filed** — question drafted below, awaiting maintainer authorisation | | `org.omg.sysml.xtext` — `SysMLValidator.checkControlNode`, `checkDecisionNode`, `checkForkNode`, `checkJoinNode`, `checkMergeNode` | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a fork or decision node with two incoming successions, a join or merge node with two outgoing, and a succession end whose written multiplicity is not the one SysML v2 §7.17.3 requires all validate clean; only `validateControlNodeOwningType` is reported | established from the pilot's source: eight of the nine constraints are `// TODO: Check validate… (?)` comments in the check methods (`SysMLValidator.xtend:857–888` at `c7fc737`); the reproducers are `tools/referee/reject/testdata/negative/semantic/cn01`–`cn04`, `cn06`–`cn09`, run through the pinned batch validator | **not filed** — drafted below, awaiting maintainer authorisation | | `org.omg.kerml.xtext` — `KerMLValidator.checkFeature`, the `validateFeatureOwnedCrossSubsetting` check | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a feature with two `crosses` clauses reports `Error executing EValidator` instead of `At most one cross subsetting is allowed`: the loop indexes `refSubsettings` (the reference subsettings, collected for the check above it) with the cross-subsetting index, and throws | established from the pinned `KerMLValidator.xtend` line 649 and reproduced with `tools/referee/reject/testdata/negative/semantic/k42-two-cross-subsettings.kerml`; [pilot-rejection.md](pilot-rejection.md#permissiveness-gaps) records the case as a gap of ours | filed upstream as [Systems-Modeling/SysML-v2-Pilot-Implementation#794](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/794), **fixed** upstream (ST6RI-966, commit `241aea55`, 2026-09-05: the loop now indexes `crossSubsettings`) and shipped in `2026-08`, where the pinned validator reports `At most one cross subsetting is allowed`; body below | -| `org.omg.kerml.xtext` — `KerMLValidator.checkMultiplicityRange`, the `validateMultiplicityRangeResultTypes` check | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a multiplicity bound naming a package-level feature typed by `ScalarValues::Natural` or `Integer` (`feature k : Natural; feature d [k];`, both owned by a package) reports `Must have a Natural value`; the same bound inside a type (`class T { feature k : Natural; feature d [k]; }`) is accepted | established from the pinned `KerMLValidator.xtend` lines 1333–1339, `FeatureReferenceExpression_modelLevelEvaluable_InvocationDelegate` and `MultiplicityRange_valueOf_InvocationDelegate`: a reference to a feature with no featuring type and no value is deemed model-level evaluable, its evaluation yields the feature rather than a `LiteralInteger`, `valueOf` returns the `-2` null marker and the check reports it; a reference to a type's member is not evaluable and is judged by its type through `isInteger`. The method carries `// TODO: Correct validateMultiplicityBoundResults OCL from KERML-199`. Reproduced with the model below through `validate-kerml` at `2026-07` and again at `2026-08` (0.62.0); the lines are unchanged on `master` at `5cca16d8` (2026-09-12). [pilot-differential.md](pilot-differential.md#multiplicity-bound-result-types-round) records how OpenSysML judges both spellings by the referent's type | **ready to file** — approved for filing, body below is the report as it is to be submitted | -| `org.omg.sysml.logic` — `Type_multiplicity_SettingDelegate`, behind `KerMLValidator.checkFeature`'s `validateFeatureMultiplicityDomain` check and `checkClassifier`'s `validateClassifierMultiplicityDomain` check | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a feature whose body holds an `alias` for a `multiplicity` member of the enclosing class, or whose value references one (`class E { multiplicity em [1..4]; feature k : Integer { alias a for em; } }`), reports `Multiplicity must have same featuring types as it feature`, and a classifier holding an alias for a feature's multiplicity (`class C { alias m for K::f::m; }`) reports `Multiplicity must not have a featuring type`, although neither type owns a multiplicity; the spec-genuine violation, a standalone `featuring of C::k::m by D;` on a feature's owned multiplicity, is accepted | established from the pinned `Type_multiplicity_SettingDelegate.getMultiplicityOf` (lines 43–48 at `c7fc737`), which takes the first `Multiplicity` among the members of every `ownedMembership` — aliases and reference memberships included — where KerML 1.1 8.3.3.1.10 `deriveTypeMultiplicity` reads `ownedMember->selectByKind(Multiplicity)`; and from `Feature_featuringType_SettingDelegate.basicGet` (lines 39–51), which reads `ownedTypeFeaturing` where 8.3.3.3.4 `deriveFeatureFeaturingType` reads every `typeFeaturing`. Reproduced with the models below through `validate-kerml` at `2026-07` and again at `2026-08` (0.62.0); the delegate is unchanged on `master` at `5cca16d8` (2026-09-12), and upstream [#708](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/708) fixed the same alias-membership mistake in `TypeUtil.addMultiplicityTo`. [validation-constraints.md](validation-constraints.md) records both census rows | **ready to file** — approved for filing, body below is the report as it is to be submitted | +| `org.omg.kerml.xtext` — `KerMLValidator.checkMultiplicityRange`, the `validateMultiplicityRangeResultTypes` check | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a multiplicity bound naming a package-level feature typed by `ScalarValues::Natural` or `Integer` (`feature k : Natural; feature d [k];`, both owned by a package) reports `Must have a Natural value`; the same bound inside a type (`class T { feature k : Natural; feature d [k]; }`) is accepted | established from the pinned `KerMLValidator.xtend` lines 1333–1339, `FeatureReferenceExpression_modelLevelEvaluable_InvocationDelegate` and `MultiplicityRange_valueOf_InvocationDelegate`: a reference to a feature with no featuring type and no value is deemed model-level evaluable, its evaluation yields the feature rather than a `LiteralInteger`, `valueOf` returns the `-2` null marker and the check reports it; a reference to a type's member is not evaluable and is judged by its type through `isInteger`. The method carries `// TODO: Correct validateMultiplicityBoundResults OCL from KERML-199`. Reproduced with the model below through `validate-kerml` at `2026-07` and again at `2026-08` (0.62.0); the lines are unchanged on `master` at `5cca16d8` (2026-09-12). [pilot-differential.md](pilot-differential.md#multiplicity-bound-result-types-round) records how OpenSysML judges both spellings by the referent's type | filed upstream as [Systems-Modeling/SysML-v2-Pilot-Implementation#803](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/803), body below is what was submitted | +| `org.omg.sysml.logic` — `Type_multiplicity_SettingDelegate`, behind `KerMLValidator.checkFeature`'s `validateFeatureMultiplicityDomain` check and `checkClassifier`'s `validateClassifierMultiplicityDomain` check | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a feature whose body holds an `alias` for a `multiplicity` member of the enclosing class, or whose value references one (`class E { multiplicity em [1..4]; feature k : Integer { alias a for em; } }`), reports `Multiplicity must have same featuring types as it feature`, and a classifier holding an alias for a feature's multiplicity (`class C { alias m for K::f::m; }`) reports `Multiplicity must not have a featuring type`, although neither type owns a multiplicity; the spec-genuine violation, a standalone `featuring of C::k::m by D;` on a feature's owned multiplicity, is accepted | established from the pinned `Type_multiplicity_SettingDelegate.getMultiplicityOf` (lines 43–48 at `c7fc737`), which takes the first `Multiplicity` among the members of every `ownedMembership` — aliases and reference memberships included — where KerML 1.1 8.3.3.1.10 `deriveTypeMultiplicity` reads `ownedMember->selectByKind(Multiplicity)`; and from `Feature_featuringType_SettingDelegate.basicGet` (lines 39–51), which reads `ownedTypeFeaturing` where 8.3.3.3.4 `deriveFeatureFeaturingType` reads every `typeFeaturing`. Reproduced with the models below through `validate-kerml` at `2026-07` and again at `2026-08` (0.62.0); the delegate is unchanged on `master` at `5cca16d8` (2026-09-12), and upstream [#708](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/708) fixed the same alias-membership mistake in `TypeUtil.addMultiplicityTo`. [validation-constraints.md](validation-constraints.md) records both census rows | filed upstream as [Systems-Modeling/SysML-v2-Pilot-Implementation#802](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/802), body below is what was submitted | | `org.omg.sysml.logic` — `ConnectorAdapter.getDefaultSupertype`, with `KerMLValidator.checkConnectorBinarySpecialization` | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | a connector owning two ends that redefine two ends of a three-ended general (`connector m : N { end redefines a references x; end redefines b references y; }`) reports `Cannot have more than two ends`, while the same shape spelled as an association (`assoc B specializes N { end redefines a : T; end redefines b : T; }`) is accepted | established from the pinned `ConnectorAdapter.xtend` (`getDefaultSupertype` counts `TypeUtil.getOwnedEndFeaturesOf(target)`, two here, so the connector is given `Links::binaryLinks`) and `KerMLValidator.xtend` (`checkConnectorBinarySpecialization` then counts three `connectorEnd`s), reproduced with the model below through `validate-kerml`; KerML 1.1 8.3.4.5.3 implies `Links::binaryLinks` only for `connectorEnd->size() = 2`, which counts the inherited end. [pilot-differential.md](pilot-differential.md#binary-link-specialization-round) records how OpenSysML counts effective ends for the base | **not filed** — question drafted below, awaiting maintainer authorisation | | `org.omg.sysml.xtext` — `SysMLValidator`/`KerMLValidator`, invocation argument count | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | an invocation that leaves a default-less `in` parameter unbound validates clean in every form: positional (`F(1.0)`, `F()` against `calc def F { in x : Real; in y : Real; … }`), named (`F(x = 1.0)`, `F(y = 2.0)`), with the omitted parameter declared `[1]` or `[1..*]`, on a calc, a behavior (`Act(1.0).r`, `Act()`), a constructor (`new P()`, `new P(1.0).q`) and an invocation heading a feature chain; only an argument past the last parameter is reported, `Must correspond to one input parameter of the invoked type` (`arity.sysml:38:32` for `F(1.0, 2.0, 3.0)`; `arity.kerml:30:30` for the KerML twin). The pinned evaluator forms and evaluates the same calls: `F(1.0)`, `F(x = 1.0)`, `F(y = 2.0)` and `F()` answer the unreduced `OperatorExpression +`, `F(1.0, 2.0)` `LiteralRational 3.0`, `D(1.0)` (`in y default 1.0`) `2.0`, `Opt(1.0)` (`in y [0..1]`) `1.0` | established by running the pinned `validate-sysml-batch` and `validate-kerml` over a 20-form probe of the above and `build/pilot-evaluator/eval-sysml --cases` over its evaluable rows (transcript below); earlier, `2026-05` (0.60.1) over the whole `airbus/apollo-11-sysml-v2` model at `6e9c93f` was silent on `ln(m0 / mf)` and `calculateDeltaV(isp, initialMass, finalMass)` ([performance.md](../internals/performance.md#a-real-model-apollo-11)), and the pilot's own `kerml-examples/Simple Tests/Behaviors.kerml:14` (`A().y` against `behavior A { in x; … }`) is silent under `validate-kerml` with `ParsingTests_Behaviors.kerml.xt` declaring the file error-free. **Adjudicated as the specification's reading, not a pilot defect:** KerML 1.0 §8.3.4.8.8 lists no `InvocationExpression` constraint on the count of arguments — `validateInvocationExpressionParameterRedefinition` and `…NoDuplicateParameterRedefinition` bound each argument *written* to one input, and the pinned validator's `Must correspond to one input parameter`, `Parameter already bound` and `Must be an in parameter` are those — so the unbound parameter is a property of the instance the call describes, not of the expression. OpenSysML therefore reports the omission as the advisory `unbound-parameter` (a warning in every conformance mode) identically at a bare call and at a chain head, and refuses the evaluation at run time with `ErrUnboundParameter` | **not filed** — a question, not a defect report, drafted below; a maintainer may still want to confirm the reading | | `org.omg.sysml.xtext` — `SysMLValidator.isDuration`/`isTime`, behind `validateTriggerInvocationActionAfterArgument` and `…AtArgument` | `2026-07` (`jupyter-sysml-kernel` 0.61.0) | with `d : DurationValue` and `t : TimeInstantValue`, `accept after d * d` and `accept at t * t` validate clean although the product has dimension T², while `accept after 10 [m] / 2 [m/s]`, whose quotient has dimension T, is refused | established from the pinned `SysMLValidator` class: an operator argument is a duration or an instant when its operator is one of `-`, `+`, `*`, `%`, `^`, `**` (`isQuantityOperator`) and every operand is itself one — `/` is not in the list and no dimension is computed; reproduced with the pinned batch validator, transcript below | **not filed** — question drafted below, awaiting maintainer authorisation | @@ -1216,9 +1216,9 @@ help. ### A bound naming a package-level feature is rejected whatever its type (pilot `2026-07`) -**Ready to file.** Approved for filing against -`Systems-Modeling/SysML-v2-Pilot-Implementation`; the body below is the report as -it is to be submitted, and nothing has been posted yet. Reproduced with +Filed as +[Systems-Modeling/SysML-v2-Pilot-Implementation#803](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/803); +the body below is what was submitted. Reproduced with `validate-kerml` at `2026-07` (0.61.0) and again at `2026-08` (0.62.0); the lines cited are unchanged on `master` at `5cca16d8` (2026-09-12). OpenSysML reads the referenced feature's declared type @@ -1306,9 +1306,9 @@ than that it lacks a Natural value. ### A multiplicity is found through aliases and references (pilot `2026-07`) -**Ready to file.** Approved for filing against -`Systems-Modeling/SysML-v2-Pilot-Implementation`; the body below is the report as -it is to be submitted, and nothing has been posted yet. It covers both symptoms +Filed as +[Systems-Modeling/SysML-v2-Pilot-Implementation#802](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/802); +the body below is what was submitted. It covers both symptoms of the one delegate — the feature-side `validateFeatureMultiplicityDomain` and the classifier-side `validateClassifierMultiplicityDomain` — in one report. Reproduced with `validate-kerml` at `2026-07` (0.61.0) and again at `2026-08` diff --git a/docs/project/pilot-differential.md b/docs/project/pilot-differential.md index 52535d586..eeea64846 100644 --- a/docs/project/pilot-differential.md +++ b/docs/project/pilot-differential.md @@ -2826,7 +2826,7 @@ adjudicated toward the specification rather than the referee: sides. The specification asks for the result's type, which for a feature reference is the referent's wherever it is owned; [omg-issues.md](omg-issues.md#a-bound-naming-a-package-level-feature-is-rejected-whatever-its-type-pilot-2026-07) - holds the report, approved for filing. + holds the report, filed as [Systems-Modeling/SysML-v2-Pilot-Implementation#803](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/issues/803). - **`**` and `^` keep an Integer whole only under a Natural exponent.** The pilot's `isIntegerOperator` lists both alongside `+`, `-`, `*` and `%`, so `2 ** n` with `n : Integer` passes its check. `IntegerFunctions::'**'` is declared `in y : Natural`, and an Integer diff --git a/docs/project/validation-constraints.md b/docs/project/validation-constraints.md index 7934e06a7..e0f75ad7f 100644 --- a/docs/project/validation-constraints.md +++ b/docs/project/validation-constraints.md @@ -104,7 +104,7 @@ parser/resolver location. *Our message* is given only where OpenSysML's wording | `validateBindingConnectorTypeConformance` | KerML | The two features a binding connector binds have conforming types, on the explicit `bind`/`binding` and on the bindings the language implies: a feature value to its feature, a result expression to the result parameter, a `satisfy … by` operand and a nested requirement's or case's subject to the subject they fill, and each operator or invocation argument to the parameter of the function it fills (warning) | internal/check/passes/w9c_bound_feature_types.go:W9CBoundFeatureTypesPass.Run; internal/check/passes/typecheck_value.go:exprChecker.checkValueConformance; internal/check/passes/w9c_argument_bindings.go:exprChecker.judgeArgumentBinding | same wording and position for `bind`/`binding` (feature-chain ends included), result expressions, `satisfy … by` and nested subjects, and for an operator or invocation argument whose static type does not conform to the selected function's parameter (`w + 1` and `sum(masses)` against a `Real` parameter, at the argument of an invocation and at the whole operator expression), with the same silence where the callee is unresolved or ambiguous, the argument's type unknown or collection-valued, or the parameter typed by a `Collection` or `Element`; and the same silence for a Boolean-valued `{ … }` against `BooleanEvaluation` and an expression body against a feature typed by an `Evaluation` in either direction; the implicit binding of a feature value `part x : D = c;` or `return : D = c;` is the typechecker's error `cannot bind a value of type C to a feature typed by D` at the value where the pilot warns at the feature, and that check also judges a `default` value and a narrowing literal (`attribute i : Integer = 1.5;`), which the pilot leaves silent; a `predicate`'s or `bool`'s non-Boolean result expression is likewise the typechecker's error `constraint expression must be Boolean, found D` at the expression (internal/check/passes/typecheck_expr.go:exprChecker.checkBoolean) where the pilot warns at the predicate. Stays approximate: the value/feature typing judgment is the type tier's and a mismatch is an error there, so it cannot become the pilot's constraint-tier warning without letting the constraint tier run over an ill-typed model; the `default` and narrowing-literal cases the pilot leaves silent are spec-genuine. | none | ⚠️ approximate | | `validateClassSpecialization` | both | A class (KerML) or an occurrence, port, action, state, calculation, constraint, requirement, case, metadata, view, connection, interface, flow or allocation definition (SysML) cannot specialize a data type or, unless it is itself an association, an association — through `specializes` or `:>`, and through a chain of generals only at the classifier that names the offending general | internal/check/passes/w11a_kerml_specialization.go:W11AKerMLSpecializationPass.Run | same wording in both notations (`Cannot specialize data type or association`, `Cannot specialize attribute definition`) at the general | `semantic/k21-class-specializes-datatype.kerml` | ✅ faithful | | `validateClassifierDefaultSupertype` | KerML | A classifier directly or indirectly specializes its kind's default supertype (`Must directly or indirectly specialize {supertype}`); observable only through conjugation, which stops the pilot adding the implicit specialization (`TypeAdapter.computeImplicitGeneralTypes`): `struct S ~ D` with `class D` draws `Objects::Object`, `function F ~ B` with `behavior B` draws `Performances::Evaluation`, likewise a predicate, metaclass, association or interaction. ⚠️ because OpenSysML also requires a two-end association's binary base: `assoc A ~ B { end feature a; end feature b; }` draws `Links::BinaryLink` where the pilot's `checkClassifier` validates only the generic default and says `Links::Link`, `assoc struct AS ~ Objects::LinkObject` with two ends draws `Objects::BinaryLinkObject` where the pilot is silent, and `interaction I ~ Links::Link` with two ends draws `Links::BinaryLink` and `Performances::Performance` where the pilot (whose `InteractionImpl` maps to the association default alone) is silent — KerML 8.3.4.7 `checkAssociationBinarySpecialization` requires the binary base and a conjugated type owns no specialization to supply it (`validateSpecializationSpecificNotConjugated`), see `omg-issues.md`. Stays approximate: the `Links::BinaryLink` requirement is KerML §8.3.4.7 and is kept. | internal/check/passes/w11e_implicit_base.go:implicitBaseChecker.checkDefaultSupertype | — | `semantic/k46-conjugated-structure-not-an-object.kerml` | ⚠️ approximate | -| `validateClassifierMultiplicityDomain` | KerML | A classifier's multiplicity has no featuring type (`Multiplicity must not have a featuring type`). The pilot reports it only for `class C { alias m for K::f::m; }` — its `Type.multiplicity` scans alias memberships and finds the *feature's* multiplicity — but KerML 8.3.3.1 derives `multiplicity` from `ownedMember`, which an alias's target is not, so that model is valid and OpenSysML declines to report it (the report, approved for filing, is in `omg-issues.md`). Every direct spelling is grammar-unconstructable: `multiplicity` admits no `featured by`, a multiplicity owned by a classifier has no featuring type, and a standalone `featuring C::m by D` leaves the pilot silent. Shapes tried: `class C [2]`, an owned `multiplicity m [3]` in a class, data type, structure, association and behavior, `featuring` in every position, a classifier nested in a feature, an alias from a subclass | — | — | none | ⛔ deliberate | +| `validateClassifierMultiplicityDomain` | KerML | A classifier's multiplicity has no featuring type (`Multiplicity must not have a featuring type`). The pilot reports it only for `class C { alias m for K::f::m; }` — its `Type.multiplicity` scans alias memberships and finds the *feature's* multiplicity — but KerML 8.3.3.1 derives `multiplicity` from `ownedMember`, which an alias's target is not, so that model is valid and OpenSysML declines to report it (filed as Systems-Modeling/SysML-v2-Pilot-Implementation#802; the report is in `omg-issues.md`). Every direct spelling is grammar-unconstructable: `multiplicity` admits no `featured by`, a multiplicity owned by a classifier has no featuring type, and a standalone `featuring C::m by D` leaves the pilot silent. Shapes tried: `class C [2]`, an owned `multiplicity m [3]` in a class, data type, structure, association and behavior, `featuring` in every position, a classifier nested in a feature, an alias from a subclass | — | — | none | ⛔ deliberate | | `validateCollectExpressionOperator` | KerML | A collect expression's operator is `collect` (`Operator must be 'collect'`); derived-property — `CollectExpressionImpl` initializes `operator` to `collect` and the grammar builds a collect expression only from `.{ }`, so text cannot set another operator. Shapes tried: `x.{in a; a.y}`, `x.z.{in a; a}`, a chained `x.y.?{...}.z`, spaced `x . y` | — | — | none | ❔ unknown — no case and no identifiable pass yet | | `validateConnectorBinarySpecialization` | KerML | A connector with more than two ends cannot specialize a binary connector (`Cannot have more than two ends`) | internal/check/passes/constraint.go:checkBinaryConnectorEnds | `c has 3 ends but specializes a binary link (Links::BinaryLink), which cannot have more than two; drop the extra ends or specialize an n-ary link instead` — counts positional `(x, y, z)` and `from … to` ends, declared `end` features and inherited ends | `semantic/k26-binary-connector-three-ends.kerml` | ✅ faithful | | `validateConnectorRelatedFeatures` | KerML | A connector has at least two related features | internal/check/passes/w10b_related_elements.go:W10BRelatedElementsPass.Run | same wording; a parenthesized KerML end list with one end is a parse error (`expected at least two connector ends in a parenthesized end list`) | `xpect/p20-connection-with-one-end.sysml` | ✅ faithful | @@ -134,7 +134,7 @@ parser/resolver location. *Our message* is given only where OpenSysML's wording | `validateFeatureEndNotDerivedAbstractCompositeOrPortion` | KerML | An end feature is not derived, abstract, composite or portion (`End feature cannot be derived, abstract, composite or portion`): SysML `end derived a`, `end abstract a`, `end variation a` (a variation is abstract); KerML's `EndFeaturePrefix` admits none of the four, and a SysML `end part a` is not composite in either tool, so the probe is SysML and the composite and portion halves are grammar-unconstructable | internal/check/passes/end_feature.go:EndFeaturePass.Run | — | `semantic/s87-end-derived-or-abstract.sysml` | ✅ faithful | | `validateFeatureHasType` | KerML | A feature has at least one type (`Features must have at least one type`); observable only through conjugation, which stops the pilot adding the implicit `Base::things` subsetting that types every plain `feature f;`: `feature f ~ D` with `class D`, nested `class C { feature g ~ D; }`, a `step` or `expr` conjugating a class; `feature f2 ~ f1` of a typed `f1` is fine | internal/check/passes/w11e_implicit_base.go:implicitBaseChecker.checkFeatureHasType | — | `semantic/k45-conjugated-feature-without-type.kerml` | ✅ faithful | | `validateFeatureIsVariable` | KerML | A variable feature is owned by an occurrence type | internal/check/passes/w8c_variable_feature.go:VariableFeaturePass.Run | — | `xpect/p03-variable-in-datatype.kerml` | ✅ faithful | -| `validateFeatureMultiplicityDomain` | KerML | A feature's multiplicity has the same featuring types as the feature (`Multiplicity must have same featuring types as it feature`). The genuine violation is a standalone `featuring of C::x::m by D;` on a feature-owned multiplicity; OpenSysML reports it on the featuring relationship member, while a target that is the feature's owner or specializes it is accepted. The pinned pilot is silent on this genuine form because its `featuringType` reads only owned type featurings. Its only observable trigger is the defective alias/reference derivation recorded in [omg-issues.md](omg-issues.md#a-multiplicity-is-found-through-aliases-and-references-pilot-2026-07), which stays a valid model here. | internal/check/passes/multiplicity_domain.go:MultiplicityDomainPass.Run | same wording | none | ✅ faithful | +| `validateFeatureMultiplicityDomain` | KerML | A feature's multiplicity has the same featuring types as the feature (`Multiplicity must have same featuring types as it feature`). The genuine violation is a standalone `featuring of C::x::m by D;` on a feature-owned multiplicity; OpenSysML reports it on the featuring relationship member, while a target that is the feature's owner or specializes it is accepted. The pinned pilot is silent on this genuine form because its `featuringType` reads only owned type featurings. Its only observable trigger is the defective alias/reference derivation recorded in [omg-issues.md](omg-issues.md#a-multiplicity-is-found-through-aliases-and-references-pilot-2026-07) and filed as Systems-Modeling/SysML-v2-Pilot-Implementation#802, which stays a valid model here. | internal/check/passes/multiplicity_domain.go:MultiplicityDomainPass.Run | same wording | none | ✅ faithful | | `validateFeatureOwnedCrossSubsetting` | KerML | A feature owns at most one cross subsetting; the `2026-07` pilot crashed on the probe with `Error executing EValidator` instead of reporting it, fixed upstream at `2026-08` (see `omg-issues.md`) | internal/check/passes/w10b_cross_features.go:checkW10BCrossFeatures | `At most one cross subsetting is allowed` — the message the pilot's source intends | `semantic/k42-two-cross-subsettings.kerml` | ✅ faithful | | `validateFeatureOwnedReferenceSubsetting` | KerML | A feature owns at most one reference subsetting | internal/check/passes/w8c_reference_subsetting.go:ReferenceSubsettingPass.Run | — | `semantic/k09-two-reference-subsettings.kerml` | ✅ faithful | | `validateFeaturePortionNotVariable` | KerML | A portion feature is not variable | internal/check/passes/w8c_variable_feature.go:VariableFeaturePass.Run | — | `semantic/k10-portion-var-feature.kerml` | ✅ faithful |