feat(python): generated metaclass classes and a standalone metamodel JSON reader - #873
Merged
Merged
Conversation
…core (20250201) Read the pinned pilot implementation's SysML.ecore instead of the 202407 OWL rendering, record each property's ordering, derivation, redefinitions, subsettings and opposite and each class's abstractness, and fail CI when the table drifts from the pin. Write nonunique as isUnique false and own the flow, payload, end, terminate and instantiation metaclasses through a FeatureMembership, still reading graphs earlier releases wrote. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…f:type Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ilot-metamodel Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # Makefile
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ilot-metamodel Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # Makefile
…cluded Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Merged
6 tasks done
HuiJun
added a commit
that referenced
this pull request
Oct 5, 2026
* Merge pull request #746 from someshSandbox/feat/731-library-names feat(export): name the standard library elements a converted model references (#731) * Merge pull request #749 from someshSandbox/feat/732-convert-id-form feat(grpc): Convert takes the id form, as sysml -id does (#732) * Merge pull request #751 from Open-MBEE/fix/grpc-parser-warnings * fix(grpc): report the parser's warnings as the workspace does ParseFile and ParseSources handed the analysis passes an empty parse-diagnostic list and never read parser.Parser.Warnings, so a reserved keyword written as a name loaded with no diagnostic where sysml -validate reports the reserved-keyword-name error, and strict conformance never escalated a parser nonstandard-notation warning. parser.AsDiagnostics is the one conversion of a parse's errors and warnings to pass diagnostics; the workspace, the REPL, the gRPC service and the edit validator all use it. The service reports each document's diagnostics once, through the passes, instead of the raw parse errors beside them. Co-Authored-By: jason.han <hanhuijun@gmail.com> * test(conformance): quote the reserved keyword the verification fixture uses as a name The fixture named a part 'analysis' bare, which the service now reports as the reserved-keyword-name error the command line always reported, so every scenario over it errored. Co-Authored-By: jason.han <hanhuijun@gmail.com> * test(grpc): quote the reserved keyword the symbol_attributes fixture uses as a name Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #747 from someshSandbox/feat/733-query-element-id feat(query): report the elementId Convert writes (#733) * Merge pull request #761 from someshSandbox/fix/760-succession-ends fix(export): first a then b owns its connector ends (#760) * Merge pull request #789 from someshSandbox/fix/760-requirement-constraint-refs fix(export): a bare assume, require or assert names its constraint by reference (#760) * Merge pull request #790 from someshSandbox/fix/760-variant-reference fix: variant x is a VariantReference to x (#760) * Merge pull request #748 from someshSandbox/fix/726-implicit-subsetting-uniqueness fix(check): conformance of an implicit subsetting (#726) * Merge pull request #794 from Open-MBEE/fix/733-element-id-by-declaration * fix(query): report each scoped element's own elementId (#793) ElementIDs recorded the ids a conversion writes by qualified name, so of two elements one name in two identity scopes declares, a query reported the id written last for both. Record them by declaration node too, as each encoder wrote them, and look a symbol's id up by its declaration first. Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(ci): re-run checks after the static job timed out Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #805 from someshSandbox/fix/transition-source-member fix(export): a transition owns its source member and parameters; chained ends stay chains (#803) * Merge pull request #846 from Open-MBEE/fix/default-built-against-release * fix(clients): download the release a client was built against when none is named Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(clients): clarify built-against release fallbacks Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(clients): separate implicit binary release from service requirements Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(clients): isolate fallback test cache and format Rust Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(rust): satisfy clippy in binary resolution Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): resolve built-against prerelease tags Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): retry unpinned prerelease candidates Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #849 from Open-MBEE/feature/rust-release-digest-stamp * feat(rust): stamp each release's service digests into the published crate Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci(rust): install python3 for the crate digest stamp when the image lacks it Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(release): sync client digest copies when stamping the shared table Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #860 from Open-MBEE/feature/python-release-digest-stamp * feat(python): stamp the release's sysml-grpc digests into the wheel The committed release-digests.json pins only the releases that existed when it was last back-filled, and the wheel for a tag was built before that tag's service binaries, so every released opensysml had to verify its own release through the signed manifest and the sigstore package at run time. The release workflow now builds the binaries first (build-release-binaries), and build-python-package hashes them with pin_release_checksums.py --from-binaries dist/grpc into the table copy the wheel and sdist package before python -m build, then fails unless both pin all five assets for the tag. build-release assembles the release from the two workspaces, writes SHA256SUMS.txt over the final distribution, fails unless the wheel's pins are the manifest's service digests, and signs it as before. Published bytes are the bytes those jobs verified. A download refused because sigstore cannot be imported now raises SigstoreUnavailableError naming the package, the install command, and that this arises only for another release or an older client; the binary is still never downloaded unverified. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(release): persist only build-release's own files and name the missing verifier module build-release attached build-release-binaries' dist/ layer and persisted the whole tree again. Workspace layers are additive and a path persisted by two upstream jobs fails the attach in every job downstream of both, which is every publish job; build-release now persists only the manifest, its signature and provenance bundles, the .sha256 sidecars and the Python distribution. A hygiene test holds the config to disjoint layers. _load_sigstore reported "the sigstore package is not installed" for any ImportError, including one from cryptography, which _Sigstore imports first. The refusal now names the module that failed to import, as sigstore or a package sigstore depends on, with the same install command. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #873 from Open-MBEE/feature/python-metamodel-reader * feat(ontology): generate the metamodel table from the pilot's SysML.ecore (20250201) Read the pinned pilot implementation's SysML.ecore instead of the 202407 OWL rendering, record each property's ordering, derivation, redefinitions, subsettings and opposite and each class's abstractness, and fail CI when the table drifts from the pin. Write nonunique as isUnique false and own the flow, payload, end, terminate and instantiation metaclasses through a FeatureMembership, still reading graphs earlier releases wrote. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): check a multiply-typed subject as its most specific rdf:type Co-Authored-By: jason.han <hanhuijun@gmail.com> * feat(ontology): record the metamodel's enumerations and their literals Co-Authored-By: jason.han <hanhuijun@gmail.com> * feat(python): generate metaclass classes and read metamodel JSON Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): treat an upper bound above one as multi-valued Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): refine metamodel reader contracts Co-Authored-By: jason.han <hanhuijun@gmail.com> * docs(python): add a metamodel classes and JSON guide page Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): fix API docs and CI type checking Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci(python): install protobuf stubs for the metamodel type check Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): validate reference ranges and unwrap standalone envelopes Co-Authored-By: jason.han <hanhuijun@gmail.com> * feat(python): let read_json skip the reference range check Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): treat an ecore upper bound above one as multi-valued Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): read ecore upper bounds as EMF does, -2 unspecified included Co-Authored-By: jason.han <hanhuijun@gmail.com> * style(ontology): preserve generator test spacing Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): keep the upstream upper-bound rule after merging Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(build): restore the build-release-wasm recipe lost in a merge Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * docs(python): publish a short README to PyPI and keep the developer guide in DEVELOPING.md The README PyPI renders as the opensysml project description was the full developer document, with paragraphs that ran for forty lines. Keep the install, quickstart and documentation links in README.md, and move the complete walkthrough to DEVELOPING.md, where the comments and guides that cited it now point. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): import read_json where __all__ exports it Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(release): 0.9.2 Fold the changelog fragments into the 0.9.2 entry and set every version surface — opensysml, @openmbee/opensysml and its platform packages, the Java client and the editors — to 0.9.2 in lockstep with the core. Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(release): scrub Sonar findings carried by 0.9.2 and restore metamodel Make targets Split the pymetamodel generator's generate, newModel and linearize into focused helpers and factor the cached-binary decision out of _ensure_binary_locked, so each stays under the cognitive-complexity threshold without changing generated output or download behavior. Name the repeated Ecore classifier kinds and the .sha256 sidecar suffix once. Give each exception test a single raising call. Exclude the generated Python metaclasses from analysis like the other generated code, and record why built_against_releases returns one or two candidate tags. The release Makefile listed ontology-table(-check) and python-metamodel(-check) as phony targets but lost their recipes, so CI's make calls were silently no-ops; restore them from develop. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(export,python): refuse an untargeted first-then end and a reference where a scalar is declared initialEndsAgree skipped a connector end with no ReferenceSubsetting or sysml:references target, so writing `first a then b` from the succession's sourceFeature/targetFeature invented the end's target on the way back. Refuse it as standardEndText does. The metamodel reader's _convert followed any @id object, so a primitive or enumeration property holding a reference returned the referenced element instead of raising MalformedValue. Reject reference objects for scalar ranges before resolving them. Co-Authored-By: jason.han <hanhuijun@gmail.com> * docs(project): performance record for 0.9.2 against 0.9.1 Every benchmark package on both revisions (six counts each, benchstat), the rows left in doubt re-run interleaved, and whole-binary wall time and RSS on the generated, example and Apollo 11 models. Parity: no row regresses once interleaved, the model loader allocates +0.4-0.7% bytes per element, the binary is 128 KiB larger. Co-Authored-By: jason.han <hanhuijun@gmail.com> * Merge pull request #756 from Open-MBEE/fix/dimension-one-identity * fix(quantity): absorb MeasurementReferences::one as the identity of the unit product A factor written in the library's dimensionless unit survived as a named power of the composed unit product, so 800 [W] * 120 [s] * 0.7 [one] spelt [SI::'kg⋅m²⋅s⁻²'*one] and never folded to SI::J. normalizeProduct now absorbs the identity: it leaves any product it shares with another unit and any power of it alone is itself. The identity is recognised by structure (Model.IsIdentityUnit): a unit of DimensionOneUnit itself, of no specialization such as AngularMeasureUnit, reducing to scale one — so rad, sr and a percent scaling one by convention stay in the product. Co-Authored-By: jason.han <hanhuijun@gmail.com> * docs(skills): record how to test the dimension-one identity end to end Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(quantity): keep the absorbed identity for when the rest of the product cancels An identity power (one) a product absorbs is remembered on UnitProduct.Identity and is the unit again once every other power cancels, by symbol or by reduction, so grouping does not change the result: (2 [one] * 3 [m]) / 3 [m] and 2 [one] * (3 [m] / 3 [m]) are both 2.0 [one]. Two identity declarations (one, unity : DimensionOneUnit = one) are the same unit to normalisation, so one * unity and unity * one agree and their measurement references compare equal. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit bf0df66) * Merge pull request #763 from Open-MBEE/fix/orthogonal-initial-entry * fix(migrate): write an initial into an orthogonal region as that region's entry A SysML v1 initial pseudostate whose transition enters a sibling orthogonal region was refused and its own region written with no entry, so the runtime stopped the machine at initialization. The entry is now settled per machine before any region is written, and the writer, the owner's default-entry note and the ledger read that one plan: a region's own initial is the one entering it; a stray initial is written as the entry of the region owning its target, coincides with that region's own entry into the same vertex, or is refused when it conflicts with one into another. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(migrate): donate initials only across orthogonal regions, and past a transition-less initial An initial whose transition enters a region of another, non-orthogonal state is refused instead of being written as that region's entry. An initial pseudostate no transition leaves is no entry, so a stray initial of an orthogonal region may enter its region, and the owner's default entry is gated on written entries only. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit a29c3e0) * Merge pull request #795 from Open-MBEE/fix/758-nonunique-composites * fix(examples): drop nonunique from the messages demo's channel messages A message in a part implicitly subsets the unique Parts::Part::ownedActions, so the two channel messages cannot be nonunique. The example validates clean, leaves the known-failure list (which held only it), and the pilot-differential baseline re-records the examples digest. Fixes #758 Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(migrate): write no nonunique where the v2 usage must be unique A v1 property with isUnique=false, or a MagicDraw [] / [n] type modifier, that becomes a usage implicitly subsetting a unique library feature, or that redefines or subsets a feature written unique, is written without nonunique; the report notes the dropped modifier and marks the entry approximated. The decision reuses the checker's implicit-subsetting rules: semantics now exposes ImplicitSubsettingCandidates over declaration kinds alone, and the migrator reads the candidates' uniqueness from the bundled library. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(migrate): judge a repeated slot value by the feature's written uniqueness slotConflict read the v1 isUnique flag, so a repeated instance in a slot of a nonunique composite property passed although the part is now written unique. It asks featureWrittenUnique instead, which also admits a repeat on a feature an array type modifier writes nonunique. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit 341aa21) * Merge pull request #802 from Open-MBEE/fix/repl-ctrl-c-exits * fix(repl): exit on Ctrl-C at an empty prompt, discard the continuation otherwise Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci: give the static and integrity job 30 minutes make lint alone takes about 12 of its 20 minutes, so the job was cancelled before its last corpus gates ran. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit c5bff06) * fix(export): load sysml-toolkit api-json exports Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit addc9f8) * fix(export): preserve toolkit API JSON round trips Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit 7076103) * fix(export): refuse named flow ends in a flow head Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit 9bef894) * fix(export): preserve kindless API JSON returns Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit afaf845) * chore(release): fold the 0.9.2 changelog fragments for the added fixes Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Jason Han <jason.han@jpl.nasa.gov> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com>
HuiJun
added a commit
that referenced
this pull request
Oct 5, 2026
* Merge pull request #746 from someshSandbox/feat/731-library-names feat(export): name the standard library elements a converted model references (#731) * Merge pull request #749 from someshSandbox/feat/732-convert-id-form feat(grpc): Convert takes the id form, as sysml -id does (#732) * Merge pull request #751 from Open-MBEE/fix/grpc-parser-warnings * fix(grpc): report the parser's warnings as the workspace does ParseFile and ParseSources handed the analysis passes an empty parse-diagnostic list and never read parser.Parser.Warnings, so a reserved keyword written as a name loaded with no diagnostic where sysml -validate reports the reserved-keyword-name error, and strict conformance never escalated a parser nonstandard-notation warning. parser.AsDiagnostics is the one conversion of a parse's errors and warnings to pass diagnostics; the workspace, the REPL, the gRPC service and the edit validator all use it. The service reports each document's diagnostics once, through the passes, instead of the raw parse errors beside them. Co-Authored-By: jason.han <hanhuijun@gmail.com> * test(conformance): quote the reserved keyword the verification fixture uses as a name The fixture named a part 'analysis' bare, which the service now reports as the reserved-keyword-name error the command line always reported, so every scenario over it errored. Co-Authored-By: jason.han <hanhuijun@gmail.com> * test(grpc): quote the reserved keyword the symbol_attributes fixture uses as a name Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #747 from someshSandbox/feat/733-query-element-id feat(query): report the elementId Convert writes (#733) * Merge pull request #761 from someshSandbox/fix/760-succession-ends fix(export): first a then b owns its connector ends (#760) * Merge pull request #789 from someshSandbox/fix/760-requirement-constraint-refs fix(export): a bare assume, require or assert names its constraint by reference (#760) * Merge pull request #790 from someshSandbox/fix/760-variant-reference fix: variant x is a VariantReference to x (#760) * Merge pull request #748 from someshSandbox/fix/726-implicit-subsetting-uniqueness fix(check): conformance of an implicit subsetting (#726) * Merge pull request #794 from Open-MBEE/fix/733-element-id-by-declaration * fix(query): report each scoped element's own elementId (#793) ElementIDs recorded the ids a conversion writes by qualified name, so of two elements one name in two identity scopes declares, a query reported the id written last for both. Record them by declaration node too, as each encoder wrote them, and look a symbol's id up by its declaration first. Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(ci): re-run checks after the static job timed out Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #805 from someshSandbox/fix/transition-source-member fix(export): a transition owns its source member and parameters; chained ends stay chains (#803) * Merge pull request #846 from Open-MBEE/fix/default-built-against-release * fix(clients): download the release a client was built against when none is named Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(clients): clarify built-against release fallbacks Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(clients): separate implicit binary release from service requirements Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(clients): isolate fallback test cache and format Rust Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(rust): satisfy clippy in binary resolution Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): resolve built-against prerelease tags Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): retry unpinned prerelease candidates Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #849 from Open-MBEE/feature/rust-release-digest-stamp * feat(rust): stamp each release's service digests into the published crate Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci(rust): install python3 for the crate digest stamp when the image lacks it Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(release): sync client digest copies when stamping the shared table Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #860 from Open-MBEE/feature/python-release-digest-stamp * feat(python): stamp the release's sysml-grpc digests into the wheel The committed release-digests.json pins only the releases that existed when it was last back-filled, and the wheel for a tag was built before that tag's service binaries, so every released opensysml had to verify its own release through the signed manifest and the sigstore package at run time. The release workflow now builds the binaries first (build-release-binaries), and build-python-package hashes them with pin_release_checksums.py --from-binaries dist/grpc into the table copy the wheel and sdist package before python -m build, then fails unless both pin all five assets for the tag. build-release assembles the release from the two workspaces, writes SHA256SUMS.txt over the final distribution, fails unless the wheel's pins are the manifest's service digests, and signs it as before. Published bytes are the bytes those jobs verified. A download refused because sigstore cannot be imported now raises SigstoreUnavailableError naming the package, the install command, and that this arises only for another release or an older client; the binary is still never downloaded unverified. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(release): persist only build-release's own files and name the missing verifier module build-release attached build-release-binaries' dist/ layer and persisted the whole tree again. Workspace layers are additive and a path persisted by two upstream jobs fails the attach in every job downstream of both, which is every publish job; build-release now persists only the manifest, its signature and provenance bundles, the .sha256 sidecars and the Python distribution. A hygiene test holds the config to disjoint layers. _load_sigstore reported "the sigstore package is not installed" for any ImportError, including one from cryptography, which _Sigstore imports first. The refusal now names the module that failed to import, as sigstore or a package sigstore depends on, with the same install command. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * Merge pull request #873 from Open-MBEE/feature/python-metamodel-reader * feat(ontology): generate the metamodel table from the pilot's SysML.ecore (20250201) Read the pinned pilot implementation's SysML.ecore instead of the 202407 OWL rendering, record each property's ordering, derivation, redefinitions, subsettings and opposite and each class's abstractness, and fail CI when the table drifts from the pin. Write nonunique as isUnique false and own the flow, payload, end, terminate and instantiation metaclasses through a FeatureMembership, still reading graphs earlier releases wrote. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): check a multiply-typed subject as its most specific rdf:type Co-Authored-By: jason.han <hanhuijun@gmail.com> * feat(ontology): record the metamodel's enumerations and their literals Co-Authored-By: jason.han <hanhuijun@gmail.com> * feat(python): generate metaclass classes and read metamodel JSON Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): treat an upper bound above one as multi-valued Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): refine metamodel reader contracts Co-Authored-By: jason.han <hanhuijun@gmail.com> * docs(python): add a metamodel classes and JSON guide page Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): fix API docs and CI type checking Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci(python): install protobuf stubs for the metamodel type check Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): validate reference ranges and unwrap standalone envelopes Co-Authored-By: jason.han <hanhuijun@gmail.com> * feat(python): let read_json skip the reference range check Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): treat an ecore upper bound above one as multi-valued Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): read ecore upper bounds as EMF does, -2 unspecified included Co-Authored-By: jason.han <hanhuijun@gmail.com> * style(ontology): preserve generator test spacing Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(ontology): keep the upstream upper-bound rule after merging Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(build): restore the build-release-wasm recipe lost in a merge Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> * docs(python): publish a short README to PyPI and keep the developer guide in DEVELOPING.md The README PyPI renders as the opensysml project description was the full developer document, with paragraphs that ran for forty lines. Keep the install, quickstart and documentation links in README.md, and move the complete walkthrough to DEVELOPING.md, where the comments and guides that cited it now point. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(python): import read_json where __all__ exports it Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(release): 0.9.2 Fold the changelog fragments into the 0.9.2 entry and set every version surface — opensysml, @openmbee/opensysml and its platform packages, the Java client and the editors — to 0.9.2 in lockstep with the core. Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(release): scrub Sonar findings carried by 0.9.2 and restore metamodel Make targets Split the pymetamodel generator's generate, newModel and linearize into focused helpers and factor the cached-binary decision out of _ensure_binary_locked, so each stays under the cognitive-complexity threshold without changing generated output or download behavior. Name the repeated Ecore classifier kinds and the .sha256 sidecar suffix once. Give each exception test a single raising call. Exclude the generated Python metaclasses from analysis like the other generated code, and record why built_against_releases returns one or two candidate tags. The release Makefile listed ontology-table(-check) and python-metamodel(-check) as phony targets but lost their recipes, so CI's make calls were silently no-ops; restore them from develop. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(export,python): refuse an untargeted first-then end and a reference where a scalar is declared initialEndsAgree skipped a connector end with no ReferenceSubsetting or sysml:references target, so writing `first a then b` from the succession's sourceFeature/targetFeature invented the end's target on the way back. Refuse it as standardEndText does. The metamodel reader's _convert followed any @id object, so a primitive or enumeration property holding a reference returned the referenced element instead of raising MalformedValue. Reject reference objects for scalar ranges before resolving them. Co-Authored-By: jason.han <hanhuijun@gmail.com> * docs(project): performance record for 0.9.2 against 0.9.1 Every benchmark package on both revisions (six counts each, benchstat), the rows left in doubt re-run interleaved, and whole-binary wall time and RSS on the generated, example and Apollo 11 models. Parity: no row regresses once interleaved, the model loader allocates +0.4-0.7% bytes per element, the binary is 128 KiB larger. Co-Authored-By: jason.han <hanhuijun@gmail.com> * Merge pull request #756 from Open-MBEE/fix/dimension-one-identity * fix(quantity): absorb MeasurementReferences::one as the identity of the unit product A factor written in the library's dimensionless unit survived as a named power of the composed unit product, so 800 [W] * 120 [s] * 0.7 [one] spelt [SI::'kg⋅m²⋅s⁻²'*one] and never folded to SI::J. normalizeProduct now absorbs the identity: it leaves any product it shares with another unit and any power of it alone is itself. The identity is recognised by structure (Model.IsIdentityUnit): a unit of DimensionOneUnit itself, of no specialization such as AngularMeasureUnit, reducing to scale one — so rad, sr and a percent scaling one by convention stay in the product. Co-Authored-By: jason.han <hanhuijun@gmail.com> * docs(skills): record how to test the dimension-one identity end to end Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(quantity): keep the absorbed identity for when the rest of the product cancels An identity power (one) a product absorbs is remembered on UnitProduct.Identity and is the unit again once every other power cancels, by symbol or by reduction, so grouping does not change the result: (2 [one] * 3 [m]) / 3 [m] and 2 [one] * (3 [m] / 3 [m]) are both 2.0 [one]. Two identity declarations (one, unity : DimensionOneUnit = one) are the same unit to normalisation, so one * unity and unity * one agree and their measurement references compare equal. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit bf0df66) * Merge pull request #763 from Open-MBEE/fix/orthogonal-initial-entry * fix(migrate): write an initial into an orthogonal region as that region's entry A SysML v1 initial pseudostate whose transition enters a sibling orthogonal region was refused and its own region written with no entry, so the runtime stopped the machine at initialization. The entry is now settled per machine before any region is written, and the writer, the owner's default-entry note and the ledger read that one plan: a region's own initial is the one entering it; a stray initial is written as the entry of the region owning its target, coincides with that region's own entry into the same vertex, or is refused when it conflicts with one into another. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(migrate): donate initials only across orthogonal regions, and past a transition-less initial An initial whose transition enters a region of another, non-orthogonal state is refused instead of being written as that region's entry. An initial pseudostate no transition leaves is no entry, so a stray initial of an orthogonal region may enter its region, and the owner's default entry is gated on written entries only. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit a29c3e0) * Merge pull request #795 from Open-MBEE/fix/758-nonunique-composites * fix(examples): drop nonunique from the messages demo's channel messages A message in a part implicitly subsets the unique Parts::Part::ownedActions, so the two channel messages cannot be nonunique. The example validates clean, leaves the known-failure list (which held only it), and the pilot-differential baseline re-records the examples digest. Fixes #758 Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(migrate): write no nonunique where the v2 usage must be unique A v1 property with isUnique=false, or a MagicDraw [] / [n] type modifier, that becomes a usage implicitly subsetting a unique library feature, or that redefines or subsets a feature written unique, is written without nonunique; the report notes the dropped modifier and marks the entry approximated. The decision reuses the checker's implicit-subsetting rules: semantics now exposes ImplicitSubsettingCandidates over declaration kinds alone, and the migrator reads the candidates' uniqueness from the bundled library. Co-Authored-By: jason.han <hanhuijun@gmail.com> * fix(migrate): judge a repeated slot value by the feature's written uniqueness slotConflict read the v1 isUnique flag, so a repeated instance in a slot of a nonunique composite property passed although the part is now written unique. It asks featureWrittenUnique instead, which also admits a repeat on a feature an array type modifier writes nonunique. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit 341aa21) * Merge pull request #802 from Open-MBEE/fix/repl-ctrl-c-exits * fix(repl): exit on Ctrl-C at an empty prompt, discard the continuation otherwise Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci: give the static and integrity job 30 minutes make lint alone takes about 12 of its 20 minutes, so the job was cancelled before its last corpus gates ran. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com> (cherry picked from commit c5bff06) * fix(export): load sysml-toolkit api-json exports Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit addc9f8) * fix(export): preserve toolkit API JSON round trips Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit 7076103) * fix(export): refuse named flow ends in a flow head Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit 9bef894) * fix(export): preserve kindless API JSON returns Co-Authored-By: jason.han <hanhuijun@gmail.com> (cherry picked from commit afaf845) * chore(release): fold the 0.9.2 changelog fragments for the added fixes Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci(sonar): ignore the HTTP-URL rule on the migrator's profile namespaces and register the candidate-tag ignore Co-Authored-By: jason.han <hanhuijun@gmail.com> * ci(release): escape the publish-crates heredoc so the release workflow compiles Co-Authored-By: jason.han <hanhuijun@gmail.com> * chore(release): bump the version surfaces develop added since 0.9.1 to 0.9.2 The release line never had the @openmbee/opensysml-wasm peer dependency, the Java API reference's Maven snippet or the Java agent skill, so the back-merge left them at 0.9.1 while every other surface moved to 0.9.2; the Node package test checks the peer matches the client version. Regenerated package-lock.json against the published 0.9.2 platform packages, which the release's lockfile had dropped. Co-Authored-By: jason.han <hanhuijun@gmail.com> --------- Co-authored-by: Jason Han <jason.han@jpl.nasa.gov> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: jason.han <hanhuijun@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Adds a read-only Python view of the SysML/KerML metamodel, separate from
opensysml.generate(which builds classes for a user's model definitions):tools/gen/pymetamodelgeneratesclient/python/opensysml/metamodel/_generated.pyfrom the ontology table: one class per metaclass (175) with the spec parents as real Python bases (C3 checked in the generator), each of the 415 properties declared once on its defining class with its JSON key, range, many/ordered and derived flags, the 7 enumerations asstrenums,REGISTRY, and a header naming the metamodel version and pilot commit.make python-metamodel-check(-check) runs in CircleCI and GitHub Actions next to the ontology table check.__getattr__),is_kept on booleans, trailing_only for hard keywords,tuple[T, ...]for multi-valued reads,builtins.type[...]in annotations, per-classJSON_KEYSwithfrom_json_key/json_key, and a closedRUNTIME_MEMBERSset (METACLASS,JSON_KEYS,from_json_key,json_key,json_id,json_type,json_value,graph,metaclass_name). The generator fails if a spec name meets a runtime member or a name the class bodies reference, if two related classes declare one name, or if C3 fails.opensysml.metamodel.read_json(andopensysml.read_json) reads a file path, bytes, a mapping or a list of element mappings: the API element form (array or single object,@id/@type,{"@id"}references), DataVersion (identity/payload) and Commit (change) envelopes, sysml-toolkit full/compact JSON, andsysml:/SysML-IRI-prefixed types. It indexes by@idand wraps and resolves lazily.graph.all(PartUsage),graph[id]andgraph.roots()are provided. An unknown@typefalls back to the nearest known ancestor via an optionalsupertypesmapping, elseElement, and keeps the written type injson_type. An absent key raisesNotSupplied(never[]/None; only explicitnull/[]mean empty); a dangling@idor an@refraisesUnresolvedReferenceon access; wrong shapes, non-finite reals and a reference to an element outside the property's range raiseMalformedValue/MalformedDocument;read_json(..., check_ranges=False)skips the range check and returns such targets as written. A standalone DataVersion envelope is unwrapped like an array entry, androots()excludes namespaces with anowningRelationship,ownerorowningNamespace. No notation conversion, no service contact, no write-back.Manyfix for the two features whose ecore upper bound is2(MultiplicityRange::bound,Flow::flowEnd), because the toolkit writesboundas an array.docs/clients/python/metamodel.md("Metamodel classes and JSON", in the nav after Typed classes), with the scope-note example, how it differs fromopensysml.generate, naming, inputs, and what OpenSysML's api-json export does and does not carry; a matching section in the Python API reference; pointers from the typed-classes page and the clients guide.Operations are left out. Follow-ups: metamodel operations (e.g.
Namespace::resolve,Type::inheritedMemberships), engine-served derived properties, loading JSON into the engine.Apollo 11 measurements
All 28
.sysmlfiles of airbus/apollo-11-sysml-v2; Python 3.12,read_json(path), median of 3 fresh processes; memory is process RSS.read_jsonsysml -convert api-json--to full-json --lib <pilot sysml.library>Reading every effective property of every element once (wrapping all elements: 0.14 s / 0.16 s):
NotSuppliedUnresolvedReferenceMalformedValueoperand)MalformedValuecounts references whose target is outside the property's range, read from the files as written. api-json: 57ConstructorExpression::functionpointing to anAttributeDefinitionand 1InvocationExpression::functionpointing to aCalculationUsage; neither target is aFunction. toolkit full-json: 369membershipOwningNamespaceand 369owningNamespacepointing to aDependency, which is not aNamespace; 296RequirementDefinition::resultand 296subjectParameter, plus 3AnalysisCaseDefinition::result, pointing to the definition itself rather than to aFeature. Withcheck_ranges=Falseboth sources read with 0MalformedValueand the other columns unchanged.The api-json export carries owned properties plus some derived ones (
ownedFeature,owner,qualifiedName, …) but notfeature,inheritedFeatureordefinition, andtypeon 1,813 of 3,789 usages. It also writes nonulland no[](0 of either on Apollo), so unset owned properties (an unnamed element'sdeclaredName,aliasIds,documentation,ownedElement, …) are absent too — that is most of the 75 % owned-read rate. Unresolved references in both sources point at standard-library elements the document does not include.Specification basis
SysML v2 / KerML metamodel 20250201 as published in the pilot implementation's
SysML.ecore(tag 2026-08, commit 692170b7). TheManyfix follows the ecoreupperBound(any value other than 1 is multi-valued). No behaviour row indocs/project/spec-compliance.mdmoves.How it was verified
go build ./...,go vet ./...,gofmt -l .(empty),go test ./...;go test -C tools ./gen/ontology ./gen/pymetamodel(drift, and each generator failure rule on synthetic tables);make ontology-table-check python-metamodel-check; RDF corpus round trip with the corpora required.tests/test_metamodel.py: alias identity for every class and key, each descriptor declared once,RUNTIME_MEMBERSequals the base's public names and is disjoint from every spec key and snake name,json_key(from_json_key(k)) == keverywhere, metadata spot checks.tests/test_metamodel_typing.py:mypy --strictand pyright strict over a usage file (with negative lines that must error) and the package; CI installs pinned mypy/pyright and setsOPENSYSML_REQUIRE_TYPECHECKERS=1.tests/test_metamodel_reader.py/test_metamodel_toolkit.py: an api-json export made by the service in the test, a checked-in toolkit full-json fixture (sysml-sdk's Apache-2.0bigger.sysml, converted with sysml-toolkit 0.10.0, credited in its README), and hand-built documents covering envelopes, unknown types, dangling references,NotSupplied, explicit empties and malformed input.make docs-check,python3 scripts/changelog.py check; wheel listing includes the metamodel package andpy.typed.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelogLink to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/49a79b80527e41829b7d7050fa1043b3
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/49a79b80527e41829b7d7050fa1043b3?variant=devin
Requested by: @HuiJun