SACM 2.3 specification defects found by implementation
Defects in the normative SACM 2.3 text (formal/23-05-08) and its
machine-readable model (ptc/22-03-13), found while implementing clause-level
validation in libs/sacm. Each was found because a check had to be written
against the clause, which is a different exercise from reading it.
This page is input to the OMG submission, not a description of Assurance Forge. What the library does about each one is recorded in decisions and questions; what it validates is in the conformance matrix. Prepared for #200.
Every quotation is from the published PDF unless marked otherwise.
D1 — Clause 10.5 prints clause 10.6's Constraints
TerminologyPackageInterface (10.5) and TerminologyPackageBinding (10.6) carry
identical Constraints sections:
The participantPackages should be either TerminologyPackage or TerminologyPackageInterface OCL:
self.participantPackage->forall(pp|pp.oclIsKindOf(Terminology::TerminologyPackage))
participantPackage is a binding association. An interface has no
participants — it has implements. So 10.5 states a constraint on a feature its
own class does not have, and the constraint the interface should carry is
absent.
Why it matters. Its siblings both state that constraint: 11.6 says an
ArgumentPackageInterface is "only allowed with isCitation=true and
+citedElement refer to ArgumentAssets within the ArgumentPackage implementation
referred to by implements", and 12.5 says the same for ArtifactPackageInterface.
A TerminologyPackageInterface is left with no content rule at all, so two
conforming tools can disagree about whether one may contain non-citations.
Suggested resolution. Replace 10.5's Constraints with the terminology analogue of 11.6.
D2 — Three clauses state the participant rule four ways
The same concept — what may be a participant of a package binding — is specified four times and agrees with itself nowhere:
OCL below is written with <code> and | rather than a backslash-escaped
pipe inside backticks: a Markdown code span takes the backslash literally, so
\| would render the operator as \| and quietly misquote the specification in
a page whose whole purpose is quoting it accurately.
| Clause | Rule as written |
|---|---|
9.4 AssuranceCasePackageBinding |
forall(pp | pp.oclIsTypeOf(AssuranceCasePackage) or pp.oclIsTypeOf(AssuranceCasePackageInterface)) — exact type; excludes a binding |
10.6 TerminologyPackageBinding |
forall(pp | pp.oclIsKindOf(Terminology::TerminologyPackage)) — kind-of; admits a binding |
11.5 ArgumentPackageBinding |
forall(pp | pp.oclIsTypeOf(Argument::ArgumentPackageInterface)) — interfaces only |
| 11.5 Associations block | participantPackage : ArgumentPackage[2..*] — the general type |
11.5 contradicts itself: its OCL admits only ArgumentPackageInterface while
its own Associations block declares ArgumentPackage.
Why it matters. A validator cannot be written to satisfy all four. A document
whose ArgumentPackageBinding names two plain ArgumentPackages is conformant
under the Associations block and non-conformant under the OCL three lines below
it. Assurance Forge enforces only what all four agree on — that a binding is not
a participant of a binding — at warning severity, and records the reason.
Suggested resolution. Pick one rule and state it identically in all four
clauses. oclIsKindOf(<Family>Package) excluding <Family>PackageBinding is the
reading that satisfies every clause's prose.
D3 — Clause 11.5's OCL is not well-formed
self.argumentationElement->forAll(e|e.isCitation = true and e.citedElement <> null
The expression is unbalanced — one closing parenthesis short — and the sentence ends without a terminator. It is the only statement of the binding-content rule in OCL form.
Suggested resolution. self.argumentationElement->forAll(e | e.isCitation = true and e.citedElement <> null).
D4 — Clause 11.4 and clause 11.6 cannot both be satisfied
11.4 Constraints:
If an ArgumentPackage has nested ArgumentPackages, then it is only allowed to contain ArgumentPackages.
11.6 Semantics:
An ArgumentPackageInterface resides insided [sic] the ArgumentPackage to which it refers.
An ArgumentPackageInterface is an ArgumentPackage (11.6 Superclass), and
11.6 requires it to reside inside the package it describes. So any package that
declares an interface "has nested ArgumentPackages", and 11.4 then forbids it
from containing the claims the interface exists to expose. Every non-empty
package with an interface is non-conformant by construction.
Suggested resolution. Scope 11.4 to nested packages that are neither interfaces nor bindings, which is the reading that makes both clauses hold.
D5 — Resource.location is in the text and absent from the model
12.10 Attributes:
location:Base::MultiLangString(composition) — the path or URL specifying the location of the Resource, can be in multiple languages.
ptc/22-03-13 declares no such attribute on Resource. location is the only
payload the class has: without it a Resource records that a resource exists and
nothing about where.
Why it matters. A producer implementing the text emits <location>; a
consumer implementing the model has nowhere to put it. This is the most
consequential of the divergences here because it is not a spelling difference —
it is the entire content of a class.
Suggested resolution. Add it to the machine-readable model.
D6 — Six further prose/model divergences
Found by holding the text against ptc/22-03-13 attribute by attribute. Listed
with the direction Assurance Forge resolved them and why, in
the metamodel inventory.
These six plus Resource.location (D5, reported separately because its
consequence is different in kind) are the seven the completeness audit found.
| Clause | Text | Model |
|---|---|---|
8.5 MultiLangString.value |
LangString[1..*] composition |
no bounds, i.e. [1..1] |
8.7 UtilityElement.content |
[0..1] |
[1..1] |
8.6 ModelElement.description |
Description[0..1] |
[0..*] |
8.4 ExpressionLangString.expression |
"(composition)" marker with reference wording | plain reference |
| 11.2 / 11.4 member role | argumentationElement |
argumentElement |
10.5 TerminologyPackageInterface superclass |
"TerminologyElement" | TerminologyPackage (the clause's own diagram agrees with the model) |
8.5's is the one with a consequence beyond spelling: at [1..1] a
MultiLangString holds one language, which makes the clause's own uniqueness
constraint — "For each of the LangString in the value feature, their +lang must
be unique" — vacuous.
Suggested resolution. Regenerate the machine-readable model from the text, or state which of the two is normative when they differ. Clause 2 requires importing "XMI documents that conform with the SACM XML Schema produced by applying XMI rules to the normative MOF metamodel", which points at the model; the rest of the specification is the text. Implementers currently have to choose per attribute.
D7 — No instance-document namespace is determined
The normative MOF model declares no nsURI on any package, and the PDF prints
none. Under XMI 2.5.1 an instance document's namespace derives from the
org.omg.xmi.nsURI tag, so nothing in SACM 2.3 determines one.
Consequence, observed. Every producer invents one and no two agree. The EMF
reference implementation (github.com/wrwei/SACM)
declares one namespace per metamodel package (http://omg.sacm/2.2/base,
/argumentation, …); this project pins a single document namespace. Both are
conformant, and neither can read the other without dialect-specific code. That is
the interoperability failure clause 2 exists to prevent.
Suggested resolution. Determine a namespace in 2.4, and say whether it is per-document or per-package.
Related
- GSN / SACM metamodel gaps — the GSN v3 side, for the SCSC ACWG.
- SACM 2.4 watch — the RTF issues that would change this.
- Decisions and questions — what the library does about each defect.