Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
f523dbd
fix(export): refuse a decision branch that states a trigger
devin-ai-integration[bot] Oct 8, 2026
0dbdf55
fix(export): check a decision branch's source through either sysml:so…
devin-ai-integration[bot] Oct 8, 2026
6fe7f95
docs(export): record the decision branches the RDF decoder refuses
devin-ai-integration[bot] Oct 8, 2026
5a3f72a
fix(export): refuse a decision branch stating a second source
devin-ai-integration[bot] Oct 8, 2026
ab8d62c
fix(export): compare a decision branch's stated source as a whole RDF…
devin-ai-integration[bot] Oct 8, 2026
565d3b8
ci: run internal/exec/runtime as two race shards split by test name
devin-ai-integration[bot] Oct 8, 2026
5eb0e14
ci: check the tree out before merging the race shards' profiles
devin-ai-integration[bot] Oct 8, 2026
3ba97e8
ci: shorten the runtime shard comments to two lines
devin-ai-integration[bot] Oct 8, 2026
4ab836d
fix(jupyter): bind the kernel's channels in Listen, on free ports whe…
devin-ai-integration[bot] Oct 8, 2026
7d5f8ff
fix(jupyter): close a listened kernel's channels when its context end…
devin-ai-integration[bot] Oct 8, 2026
4ef088a
feat(cli): list a model's documents, views and diagrams with -list, %…
devin-ai-integration[bot] Oct 8, 2026
64eaa48
fix(cli): refuse -list with -import flags and with -html-default-css
devin-ai-integration[bot] Oct 8, 2026
76a200f
Merge pull request #1012 from Open-MBEE/feat/list-views
HuiJun Oct 9, 2026
25576b9
feat(editors): generate the CodeMirror syntax table beside the TextMa…
devin-ai-integration[bot] Oct 8, 2026
b5ea62b
feat(jupyterlab): jupyterlab-opensysml, SysML v2 and KerML highlighti…
devin-ai-integration[bot] Oct 8, 2026
486332d
feat(jupyter): ship the JupyterLab extension in every kernel wheel an…
devin-ai-integration[bot] Oct 8, 2026
2acc6f0
fix(jupyterlab): color the qualifying segments of a qualified name
devin-ai-integration[bot] Oct 8, 2026
d80411f
ci: quote the --only-binary argument of the JupyterLab install step
devin-ai-integration[bot] Oct 8, 2026
6e12ddf
fix(editors): highlight //* notes to their */ and keep a mid-line %co…
devin-ai-integration[bot] Oct 8, 2026
6872c5f
ci(nightly): stamp the JupyterLab extension manifest with the snapsho…
devin-ai-integration[bot] Oct 8, 2026
f3cf532
Merge pull request #1010 from Open-MBEE/ci/split-runtime-race-shard
HuiJun Oct 9, 2026
8235c5d
Merge pull request #1011 from Open-MBEE/fix/jupyter-kernel-test-ports
HuiJun Oct 9, 2026
9728ca6
Merge pull request #1008 from Open-MBEE/fix/decision-branch-refusals
HuiJun Oct 9, 2026
96bae2b
Merge pull request #1003 from Open-MBEE/feat/jupyterlab-syntax-highli…
HuiJun Oct 9, 2026
4d7ab00
feat(repl): draw named elements on demand with the pilot kernel's %viz
devin-ai-integration[bot] Oct 8, 2026
224c37a
fix(repl): draw value bindings, keep typed case in %viz completion, d…
devin-ai-integration[bot] Oct 8, 2026
2810637
Merge pull request #1000 from Open-MBEE/feat/viz-command
HuiJun Oct 9, 2026
9370591
feat(repl): load the SysML code cells of a Jupyter notebook with %load
devin-ai-integration[bot] Oct 8, 2026
b0c4252
feat(repl): report the picked cells of one notebook as one file
devin-ai-integration[bot] Oct 8, 2026
d79ced5
test(hygiene): place internal/workspace/notebook in the workspace layer
devin-ai-integration[bot] Oct 8, 2026
adb1f83
refactor(repl): drop the unused pathArgs helper
devin-ai-integration[bot] Oct 8, 2026
0ff8fde
fix(repl): reload a notebook's picked cells by identity, and refuse t…
devin-ai-integration[bot] Oct 8, 2026
37b4a17
perf(runtime): describe a body write's host only when the binding che…
devin-ai-integration[bot] Oct 9, 2026
70242d8
perf(grpc): convert a cached model's diagnostics to protobuf once
devin-ai-integration[bot] Oct 9, 2026
7998950
ci(nightly): install JupyterLab wheel-only like every other pip install
devin-ai-integration[bot] Oct 9, 2026
e4fde53
perf(grpc): keep diagnostics cache comments to two lines
devin-ai-integration[bot] Oct 9, 2026
4b4b351
perf(symbols): stop copying re-export claims for change checks
devin-ai-integration[bot] Oct 9, 2026
8bd97fc
perf(runtime): memoize the succession-cycle check while no behavior i…
devin-ai-integration[bot] Oct 9, 2026
24aaa39
test(grpc): pin cached diagnostics against a fresh conversion, state …
devin-ai-integration[bot] Oct 9, 2026
367ca7e
perf(semantic): compare a symbol's qualified name without building it
devin-ai-integration[bot] Oct 9, 2026
4a1b937
perf(runtime): pack compiled calc scalars into three words
devin-ai-integration[bot] Oct 9, 2026
c6bdb49
perf(grpc): keep the modelDiagnostics comment to two lines
devin-ai-integration[bot] Oct 9, 2026
d0390c4
Merge pull request #1016 from Open-MBEE/ci/nightly-jupyterlab-wheel-only
HuiJun Oct 9, 2026
b7a5990
Merge pull request #1004 from Open-MBEE/feat/load-notebook
HuiJun Oct 9, 2026
a33a0b9
feat(repl): repository commands %repo, %projects, %load and %publish …
devin-ai-integration[bot] Oct 8, 2026
af2b085
fix(repl): %publish commits on the branch %load read when --branch is…
devin-ai-integration[bot] Oct 8, 2026
16e7410
fix(repl): confine %publish to its root and server, follow element pa…
devin-ai-integration[bot] Oct 8, 2026
aaff41f
fix(repl): find the published root on the branch by its effective id,…
devin-ai-integration[bot] Oct 8, 2026
22476c2
test(repl): drop an unused count in the root-confinement test
devin-ai-integration[bot] Oct 8, 2026
04ba69c
fix(interop): compare a redirect's server by host name and effective …
devin-ai-integration[bot] Oct 8, 2026
f458e77
fix(interop): a redirect carrying a token never leaves https, loopbac…
devin-ai-integration[bot] Oct 8, 2026
da43446
fix(repl): a %load of --cells alone is the file load's, and Tab offer…
devin-ai-integration[bot] Oct 9, 2026
8427187
fix(repl): a lone name beginning with one dash still names a project …
devin-ai-integration[bot] Oct 9, 2026
5bf4555
Merge pull request #1005 from Open-MBEE/feat/repl-repository-commands
HuiJun Oct 9, 2026
589660e
Merge pull request #1017 from Open-MBEE/perf/grpc-cache-diagnostics-p…
HuiJun Oct 9, 2026
ff94994
Merge pull request #1018 from Open-MBEE/perf/registration-snapshot-cl…
HuiJun Oct 9, 2026
1fe7a5b
Merge pull request #1019 from Open-MBEE/perf/lazy-binding-check-descr…
HuiJun Oct 9, 2026
2c2fd27
Merge pull request #1021 from Open-MBEE/perf/succession-cycle-memo
HuiJun Oct 9, 2026
89a964d
Merge pull request #1022 from Open-MBEE/perf/compiled-calc-scalar-path
HuiJun Oct 9, 2026
4cb3d63
Merge pull request #1023 from Open-MBEE/perf/cache-symbol-fqn
HuiJun Oct 9, 2026
fca4d03
Merge remote-tracking branch 'origin/develop' into hotfix/0.10.0-deve…
devin-ai-integration[bot] Oct 9, 2026
ce7a7a8
chore(release): fold the fragments develop gained since 0.10.0 was cut
devin-ai-integration[bot] Oct 9, 2026
1d21553
chore(release): bump the version surfaces develop added since 0.10.0 …
devin-ai-integration[bot] Oct 9, 2026
b79122d
migrate: find item flow ends through the parts and blocks a tool names
devin-ai-integration[bot] Oct 9, 2026
5dee1a6
fix(repl): print every line of a usage error at the prompt
devin-ai-integration[bot] Oct 9, 2026
683f0ae
skills: testing-sysml-repl covers v1 migration audits and inherited-s…
devin-ai-integration[bot] Oct 9, 2026
44b0ad6
ci: rerun
devin-ai-integration[bot] Oct 9, 2026
79f848f
migrate: an item flow whose ends stand for both connector ends is not…
devin-ai-integration[bot] Oct 9, 2026
576d763
fix(sysmlapi): keep the bearer token on the configured server and the…
devin-ai-integration[bot] Oct 9, 2026
cf5451a
Merge pull request #1025 from Open-MBEE/devin/1791544054-migrate-item…
HuiJun Oct 9, 2026
714c459
Merge pull request #1026 from Open-MBEE/devin/1791546128-skill-migrat…
HuiJun Oct 9, 2026
697c1bc
refactor(repl): keep usage-error comments to two lines
devin-ai-integration[bot] Oct 9, 2026
b3f3375
fix(sysmlapi): publish by name only through a tracked id the server s…
devin-ai-integration[bot] Oct 9, 2026
e19b663
Merge pull request #1029 from Open-MBEE/fix/sysmlapi-client-hardening
HuiJun Oct 9, 2026
c1718f8
Merge remote-tracking branch 'origin/develop' into hotfix/0.10.0-deve…
devin-ai-integration[bot] Oct 9, 2026
d681851
Merge pull request #1027 from Open-MBEE/devin/1791545278-repl-usage-e…
HuiJun Oct 9, 2026
29ff9c4
Merge remote-tracking branch 'origin/develop' into hotfix/0.10.0-deve…
devin-ai-integration[bot] Oct 9, 2026
82f0fac
chore(release): fold the migration, prompt and API client fixes into …
devin-ai-integration[bot] Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .agents/skills/testing-sysml-repl/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6309,6 +6309,36 @@ None for these local REPL/gRPC checks.
- Validate saved Turtle independently with rdflib; check real triples and declarations rather than
trusting the save confirmation.


## Migration and state-rendering comparisons

- Migrate real Cameo archives through `bin/sysml model.mdzip -migrate sysml
-o output.sysml -migration-report output.report.txt`; source XMI is normally
`com.nomagic.magicdraw.uml_model.model` inside the archive.
- Compare reports by element XMI ID, not line number or name: repeated names
can move records into the approximated section even when their notation was
successfully emitted. Preserve counts and inspect the notation as well.
- For direction checks, resolve `informationSource`, `informationTarget`,
`realizingConnector`, connector ends' `partWithPort`/`role`, and part/port
types from XMI. A conveyed item's emitted path should end in the actual
flow property of the connector's port type. Include a reversed connector
order fixture and an unrelated-end negative control.
- A compiler/lowering fix may repair an old migrated `.sysml` without
changing its state declarations. Comparing old and new notation under the
same new binary is not a negative control: use a separately built
pre-change binary to demonstrate the old empty graph.
- Use `-render '#state:M' -render-form text` for a small state definition,
and `-graphs M` to inspect inherited vertices, parent IDs and transitions.
Unsupported inherited members may produce an empty rendering plus a
`cannot be inherited` note while the CLI still exits zero. Exit status and
strict validation alone do not establish a nonempty graph.
- For positioned migrated views, default DOT may omit unpositioned inherited
nodes. Read `not represented` comments; use `-render-unplaced strip` to
include those nodes below the original drawing. Do not confuse omitted
placement with failed graph lowering. Named rendering may also print
validation warnings from other views; separate requested-view warnings
from whole-model warnings.

### Devin Secrets Needed

None for native local CLI/REPL tests.
32 changes: 30 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ executors:
- image: cimg/python:3.11
resource_class: medium

# The -node variant of the same image: the Jupyter kernel package builds
# its JupyterLab extension with Node before it builds the wheels.
python-node-executor:
docker:
- image: cimg/python:3.11-node
resource_class: medium

rust-executor:
docker:
- image: cimg/rust:1.83
Expand Down Expand Up @@ -1682,7 +1689,7 @@ jobs:
# platform bundles that platform's kernel, so `pip install` alone registers
# it; the sdist carries none and downloads by the pins.
build-jupyter-kernel-package:
executor: python-executor
executor: python-node-executor
steps:
- checkout
- rehearsal-tag
Expand All @@ -1691,9 +1698,11 @@ jobs:
- attach_workspace:
at: .

# jupyterlab provides `jupyter labextension build`, which bundles the
# extension every distribution ships (make jupyterlab-build).
- run:
name: Install build tooling
command: python -m pip install --upgrade pip build twine packaging
command: python -m pip install --upgrade pip build twine packaging jupyterlab==4.6.4

- run:
name: Resolve the version from the tag
Expand Down Expand Up @@ -1778,6 +1787,25 @@ jobs:
# The kernelspec `install` would write names the binary it copies in.
/tmp/verify-kernel-wheel/bin/python -m jupyter_opensysml_kernel kernelspec

# The same wheel, installed alone, put the prebuilt JupyterLab extension
# where JupyterLab 4 and Notebook 7 load federated extensions from.
- run:
name: Check the installed wheel registered the JupyterLab extension
command: |
/tmp/verify-kernel-wheel/bin/python - \<<'EOF'
import json
import os
import sys

root = os.path.join(sys.prefix, "share", "jupyter", "labextensions", "jupyterlab-opensysml")
with open(os.path.join(root, "package.json")) as f:
manifest = json.load(f)
load = manifest["jupyterlab"]["_build"]["load"]
if not os.path.isfile(os.path.join(root, load)) or not os.path.isfile(os.path.join(root, "install.json")):
raise SystemExit(f"Error: {root} is not a loadable federated extension (load={load!r})")
print(f"jupyterlab-opensysml {manifest['version']} installed at {root}, loading {load}")
EOF

# A distribution whose table lacks any of the five kernel assets for the
# tag, or pins a digest other than the one its binary hashes to, fails
# the job here: every platform wheel and the sdist. The installed wheel
Expand Down
20 changes: 18 additions & 2 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,18 @@ jobs:
- name: Build the Jupyter kernel sdist and platform wheels
env:
PYPI_VERSION: ${{ steps.version.outputs.pypi }}
NPM_VERSION: ${{ steps.version.outputs.npm }}
run: |
# The sdist, then one wheel per platform bundling the kernel from dist/jupyter;
# the script opens each and checks what it carries.
# jupyterlab provides `jupyter labextension build`, which bundles the
# JupyterLab extension every distribution ships (make jupyterlab-build).
python -m pip install --only-binary ":all:" jupyterlab==4.6.4
# `jupyter labextension list` reports the extension's manifest version, so the
# manifest is stamped with the snapshot's npm version first; `npm version` keeps
# the lock file in step, as `npm ci` requires.
(cd editors/jupyterlab && npm version --no-git-tag-version "$NPM_VERSION")
git diff --stat -- editors/jupyterlab/package.json editors/jupyterlab/package-lock.json
# The extension, the sdist, then one wheel per platform bundling the kernel
# from dist/jupyter; the script opens each and checks what it carries.
"$KERNEL_DIST_SCRIPT" dist/jupyter client/jupyter-kernel/dist
# The version is PEP 440 in canonical form and the build tools normalize the
# name, so these are the files.
Expand All @@ -344,6 +353,13 @@ jobs:
echo "::error::expected five platform wheels for ${PYPI_VERSION}, found $#: $*"
exit 1
fi
stamped=$(unzip -p "$1" '*.data/data/share/jupyter/labextensions/jupyterlab-opensysml/package.json' \
| python -c 'import json, sys; print(json.load(sys.stdin)["version"])')
if [ "$stamped" != "$NPM_VERSION" ]; then
echo "::error::the labextension in $1 carries version '$stamped', not the '$NPM_VERSION' it is being published as."
exit 1
fi
echo "ok: the labextension carries $stamped"
python -m twine check --strict client/jupyter-kernel/dist/*

# Like the client's wheel: this platform's wheel must import at the snapshot
Expand Down
65 changes: 59 additions & 6 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
julia: ${{ steps.areas.outputs.julia }}
matlab: ${{ steps.areas.outputs.matlab }}
vscode: ${{ steps.areas.outputs.vscode }}
jupyterlab: ${{ steps.areas.outputs.jupyterlab }}
mdk: ${{ steps.areas.outputs.mdk }}
syson: ${{ steps.areas.outputs.syson }}
steps:
Expand All @@ -77,10 +78,11 @@ jobs:
needs: changes
if: needs.changes.outputs.go == 'true'
# The shards split the suite's slowest packages across runners so each gets its own job cap (see scripts/race-shard.sh).
# internal/exec/runtime alone outruns a job under -race, so it is two shards split by test name (see make test-shard).
strategy:
fail-fast: false
matrix:
shard: [runtime, model, export, rest]
shard: [runtime, runtime-corpus, model, export, rest]
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -251,8 +253,8 @@ jobs:
- name: Download the Reference-FMUs
run: ./scripts/download-reference-fmus.sh

# Per-package timeout: under -race the runtime package runs 31-47 minutes on
# these runners. Matches `make test-shard`.
# Per-package timeout: under -race the whole runtime package ran 31-57 minutes
# on these runners, hence its two shards. Matches `make test-shard`.
- name: Run Go race tests
env:
SHARD: ${{ matrix.shard }}
Expand All @@ -272,8 +274,12 @@ jobs:
permissions:
contents: read
timeout-minutes: 5
# The shard package sets are disjoint, so their blocks concatenate under one mode line.
# The shards' blocks concatenate under one mode line; the two runtime shards instrument
# the same package, so their duplicate blocks are collapsed as make coverage does.
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Download shard profiles
uses: actions/download-artifact@v4
with:
Expand All @@ -285,12 +291,12 @@ jobs:
set -euo pipefail
profiles=(shards/coverage-*/coverage.txt)
# One per race-tests shard.
if [ "${#profiles[@]}" -ne 4 ]; then echo "error: expected 4 shard profiles, found ${#profiles[@]}" >&2; exit 1; fi
if [ "${#profiles[@]}" -ne 5 ]; then echo "error: expected 5 shard profiles, found ${#profiles[@]}" >&2; exit 1; fi
for f in "${profiles[@]}"; do
[ "$(head -n 1 "$f")" = "mode: atomic" ] || { echo "error: $f is not an atomic-mode profile" >&2; exit 1; }
done
{ echo "mode: atomic"; for f in "${profiles[@]}"; do tail -n +2 "$f"; done; } > coverage.txt
wc -l coverage.txt
python3 scripts/dedupe-coverage.py coverage.txt
- name: Upload coverage artifact
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -797,6 +803,7 @@ jobs:
- rust-test
- static-and-integrity
- vscode-extension
- jupyterlab-extension
- wasm-gate
- xpect-oracle
runs-on: ubuntu-latest
Expand All @@ -823,6 +830,7 @@ jobs:
RUST_TEST_RESULT: ${{ needs.rust-test.result }}
STATIC_AND_INTEGRITY_RESULT: ${{ needs.static-and-integrity.result }}
VSCODE_EXTENSION_RESULT: ${{ needs.vscode-extension.result }}
JUPYTERLAB_EXTENSION_RESULT: ${{ needs.jupyterlab-extension.result }}
WASM_GATE_RESULT: ${{ needs.wasm-gate.result }}
XPECT_ORACLE_RESULT: ${{ needs.xpect-oracle.result }}
run: |
Expand All @@ -844,6 +852,7 @@ jobs:
! ok "$RUST_TEST_RESULT" ||
! ok "$STATIC_AND_INTEGRITY_RESULT" ||
! ok "$VSCODE_EXTENSION_RESULT" ||
! ok "$JUPYTERLAB_EXTENSION_RESULT" ||
! ok "$WASM_GATE_RESULT" ||
! ok "$XPECT_ORACLE_RESULT"; then
echo "changes=$CHANGES_RESULT"
Expand All @@ -863,6 +872,7 @@ jobs:
echo "rust-test=$RUST_TEST_RESULT"
echo "static-and-integrity=$STATIC_AND_INTEGRITY_RESULT"
echo "vscode-extension=$VSCODE_EXTENSION_RESULT"
echo "jupyterlab-extension=$JUPYTERLAB_EXTENSION_RESULT"
echo "wasm-gate=$WASM_GATE_RESULT"
echo "xpect-oracle=$XPECT_ORACLE_RESULT"
exit 1
Expand Down Expand Up @@ -978,6 +988,49 @@ jobs:
path: editors/vscode/opensysml-sysml.vsix
if-no-files-found: error

jupyterlab-extension:
name: JupyterLab extension
needs: changes
if: needs.changes.outputs.jupyterlab == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: editors/jupyterlab/package-lock.json

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

# jupyterlab provides `jupyter labextension build`, which bundles the
# extension the kernel package ships. The generated syntax table is
# gated by go test ./editors/... in the Go suite.
- name: Install JupyterLab
run: pip install --only-binary ":all:" jupyterlab==4.6.4

- name: Test the tokenizer
run: make jupyterlab-test

- name: Build the prebuilt extension
run: make jupyterlab-build

- name: Upload JupyterLab extension artifact
uses: actions/upload-artifact@v4
with:
name: jupyterlab-extension
path: client/jupyter-kernel/labextension
if-no-files-found: error

mdk-plugin:
name: OpenSysML MDK plugin
needs: [changes, build]
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ cmd/*/rsrc_windows_*.syso

# The kernel a platform wheel bundles, staged by the release pipeline (setup.py)
/client/jupyter-kernel/jupyter_opensysml_kernel/bin/
/client/jupyter-kernel/labextension/
Loading
Loading