Skip to content

Commit d049f70

Browse files
authored
Merge pull request #71 from JPL-Devin/main
Bump OMG Pilot
2 parents d43be7c + f1ac06b commit d049f70

209 files changed

Lines changed: 9530 additions & 472 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/testing-pilot-corpora-gate/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ gate's own helpers are package-private but reusable (`pilotCorporaGate.files(t)`
171171

172172
`actionlint`, `shellcheck`, `python3 scripts/check-doc-links.py`, `gofmt`, `go vet`,
173173
`go run ./cmd/pilot-diff` (validators pre-downloaded; ~4min, prints e.g.
174-
the headline the committed baseline holds — `356 file(s), 330 fully agreeing; 37 agreed
175-
diagnostic(s), 26 only ours, 58 only the pilot's` after the library-inherited-name gap, so read it from
174+
the headline the committed baseline holds — `357 file(s), 329 fully agreeing; 37 agreed
175+
diagnostic(s), 27 only ours, 75 only the pilot's` after the library-inherited-name gap, so read it from
176176
`docs/project/pilot-differential-baseline.json` rather than from this line)
177177
and `make lint` (staticcheck+gosec, ~2min) all work. There is **no** `yamllint` and **no**
178178
`circleci` CLI, so `.circleci/config.yml` can only be parsed as YAML, not schema-validated — say so

.agents/skills/testing-pilot-differential/SKILL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ GNU-format diagnostics **relative to `--root`**. Consequences for testing:
2121
- The pin `cmd/pilot-diff` reports comes from `build/pilot-sysml-validator/pilot-pin.txt`
2222
(written by the new script), not from the DeciSym `pom.xml`.
2323
- `-validator /nonexistent` now says `run ./scripts/download-pilot-sysml-validator.sh`.
24-
- Measured after closing the library-inherited-name gap, with a fresh library cache: `356 file(s), 330 fully agreeing; 37 agreed,
25-
26 only ours, 58 only the pilot's`, JSON totals `openSysMLDiagnostics 71 / pilotDiagnostics
26-
103 / severityMismatch 8`; ~70 s wall, byte-identical across runs *and* after a from-scratch
24+
- Measured after closing the library-inherited-name gap, with a fresh library cache: `357 file(s), 329 fully agreeing; 37 agreed,
25+
27 only ours, 75 only the pilot's`, JSON totals `openSysMLDiagnostics 72 / pilotDiagnostics
26+
120 / severityMismatch 8`; ~70 s wall, byte-identical across runs *and* after a from-scratch
2727
rebuild of `build/pilot-validator`. `kerml-examples` carries no `syntax` diagnostic on either
2828
side. Refresh this paragraph with every rebaseline, and treat a stale one as a finding.
2929
- **`cmd/pilot-diff` has no `-jobs` flag.** Its full flag set is
@@ -136,7 +136,7 @@ The harness compares OpenSysML diagnostics against the OMG SysML v2 Pilot Implem
136136
committed result of the *last refreshed* run, so **the harness is testable by reproduction**
137137
but only while the baseline is current. Check that first. As of the rebaseline that came with the
138138
library-inherited-name gap it **is**
139-
current: a live run gives `356 file(s), 330 fully agreeing; 37 agreed, 26 only ours, 58 only the
139+
current: a live run gives `357 file(s), 329 fully agreeing; 37 agreed, 27 only ours, 75 only the
140140
pilot's`, byte-identical to the committed baseline, and `docs/project/pilot-differential.md`'s
141141
"Results" table matches. That rebaseline covers two rounds, because the succession-shorthand
142142
removal before it landed without refreshing the baseline; a control run of its merge commit gives

.agents/skills/testing-pilot-execution-referee/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ rather than a verdict against us — the pilot answers `false` for
106106
`pilot-exec-diff: <file>:<line>: model no/such/model.sysml: stat <abs>: no
107107
such file or directory`.
108108
- **Additivity.** `go run ./cmd/pilot-diff` must still print the headline the
109-
committed baseline holds (`356 file(s), 330 fully agreeing; 37 agreed
110-
diagnostic(s), 26 only ours, 58 only the pilot's` after the library-inherited-name gap — read it from the baseline JSON, not from this line, since each
109+
committed baseline holds (`357 file(s), 329 fully agreeing; 37 agreed
110+
diagnostic(s), 27 only ours, 75 only the pilot's` after the library-inherited-name gap — read it from the baseline JSON, not from this line, since each
111111
fix round moves it) and `jq -S` diff clean against
112112
`docs/project/pilot-differential-baseline.json`; `git status --porcelain`
113113
empty at the end.

.agents/skills/testing-pilot-xpect/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,8 @@ census in `w5c_census_test.go` is live two ways: perturb one pinned triple (e.g.
410410
## Regression neighbour
411411

412412
`go run ./cmd/pilot-diff` (~1m12s) must still print the headline the *committed* baseline holds —
413-
after the library-inherited-name gap that is `356 file(s), 330 fully agreeing; 37 agreed diagnostic(s), 26
414-
only ours, 58 only the pilot's`. Read the number out of
413+
after the library-inherited-name gap that is `357 file(s), 329 fully agreeing; 37 agreed diagnostic(s), 27
414+
only ours, 75 only the pilot's`. Read the number out of
415415
`docs/project/pilot-differential-baseline.json` rather than trusting this line, since a landing fix
416416
round moves it. When the baseline is itself stale (it was at `19a3ce03`, holding 273 / 281 / 317), a
417417
failing `cmp` against it is *not* evidence of an Xpect regression — compare the summary line, and see

.agents/skills/testing-sysml-repl/SKILL.md

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ and run the same input through both on camera. A worktree keeps the branch check
2626

2727
```bash
2828
git worktree add /tmp/old<sha> <sha> # e.g. the commit before the fix
29-
(cd /tmp/old<sha> && go build -o /tmp/old-sysml ./cmd/sysml)
29+
(cd /tmp/old<sha> && make build-sysml && cp bin/sysml /tmp/old-sysml)
3030
git worktree remove /tmp/old<sha> # when finished
3131
```
3232

3333
Then `/tmp/old-sysml` vs `./bin/sysml` on identical input is the strongest evidence available —
3434
it rules out "the test would have passed anyway". Especially valuable for diagnostic wording and
35-
line/column numbers, where a screenshot of the new behavior alone proves nothing.
35+
line/column numbers, where a screenshot of the new behavior alone proves nothing. Building through
36+
the Makefile preserves the version ldflags before the binary is copied out of the worktree; plain
37+
`go build` would make `--version` report `dev` / `unknown`.
3638

3739
## Library-cache cold/warm testing (`XDG_CACHE_HOME`)
3840

@@ -155,13 +157,21 @@ parser's file-kind gates are testable through the binary:
155157
2. **Interactive in a GUI terminal (for the recording).** Because the app under test *is* a CLI,
156158
the recording should show a real terminal session. See the recording setup below.
157159

160+
Run shell commands such as `clear` only before launching the REPL. At the `sysml>` prompt they are
161+
parsed as model source; rebuilding the model can restart a running exhibited machine and invalidate
162+
the rest of a walkthrough. Loading a second model into the same session also restarts machines and
163+
shifts instance IDs, so use a fresh REPL session for each model or contrast run.
164+
158165
**At the `sysml>` prompt an expression must go through `%eval`.** Bare text — even a fully
159166
qualified `test::r.cost.v` — is submitted as *model source*, so it answers
160167
`1:1: error: expected a namespace member` and leaves an unresolved buffer error that taints the
161168
next submission with `note: deeper checks may not have run here…` (the same trap as typing
162169
`clear`). On camera this looks like the feature is broken. Type `%eval test::r.cost.v`; if you have
163170
already tainted the session, `%quit`/Ctrl-D and restart rather than continuing.
164171

172+
In Konsole, `xdotool key ctrl+shift+plus` may type a literal `+`; use
173+
`xdotool key ctrl+shift+equal` to enlarge the font before recording.
174+
165175
### Driving a `type: "calc"` conformance fixture from the CLI
166176

167177
Fixtures under `internal/core/runtime/testdata/conformance/` whose `.expected.json` says
@@ -1394,6 +1404,20 @@ from an explicit real interpreter (`/home/ubuntu/.pyenv/versions/3.12.8/bin/pyth
13941404
or `/usr/bin/python3.10`) and verify `<venv>/bin/python -c 'import opensysml'` before blaming the
13951405
client. `$HOME/pv` is created by the blueprint, so prefer reusing it.
13961406

1407+
Do not assume `$HOME/pv` is the one that works: on a session seen in Aug 2026 `~/pv` and
1408+
`~/fprime-venv` both failed `import opensysml` while the *editable* install lived in
1409+
`/home/ubuntu/repos/fprime/fprime-venv/bin/python3` (3.12.8, `grpc` 1.83.0) — which happened to be
1410+
first on the tool shell's `PATH` as plain `python3`. Probe every candidate in one go
1411+
(`for p in /home/ubuntu/pv/bin/python /home/ubuntu/*venv*/bin/python python3; do $p -c 'import
1412+
opensysml,grpc'; done`) and use the absolute path of whichever answers. Critically, **a GUI Konsole
1413+
does not inherit the tool shell's `PATH`**: there `python3` is `/usr/bin/python3` (3.10, no
1414+
`opensysml`), so a demo script that worked in `exec` dies with `ModuleNotFoundError` on camera.
1415+
Always type the absolute interpreter path (or `export PATH=...`) in the recorded terminal.
1416+
1417+
When checking a documented exit status ("a failing check exits nonzero"), never pipe the binary into
1418+
`tail`/`grep``$?` then reports the pager's status and a failing command reads as `exit=0`.
1419+
Redirect to a file and echo `$?` first, then `tail` the file.
1420+
13971421
### Service lifecycle, the stale-service check and `require_capabilities` (PR #181)
13981422

13991423
Since PR #181 `Connection` interrogates whatever is *already* listening (`GetServerInfo`) and
@@ -1427,6 +1451,18 @@ OPENSYSML_GRPC_VERSION=v0.0.7 python -c '...connect(port=50099)...' # -> Stale
14271451
matches your own shell — see the pkill trap below). Refcount behaviour worth asserting within one
14281452
process (two `connect()`s): 1 → 2 → 1, the service still serving the remaining holder and stopped
14291453
only when the last one closes. Across two processes there is nothing to share: each starts its own.
1454+
- **A leftover service may be answering 50051 from a path you never built.** A previous session can
1455+
leave e.g. `/tmp/sysml-grpc` listening, in which case `python -m pytest python/tests/test_runtime_integration.py`
1456+
reports `N passed` in ~0.05 s against *unknown* code — the integration suite neither skips nor
1457+
tells you whose binary served it, so a green run proves nothing about your commit. Before trusting
1458+
any client result, run `pgrep -af sysml-grpc``-x` does find `/tmp/sysml-grpc` (it matches the
1459+
executable's basename, truncated to 15 chars), but only `-af` prints the path that is serving,
1460+
which is the thing you need to see. Kill the PID you found **by number**, start your own
1461+
(`nohup ./bin/sysml-grpc >/tmp/grpc.log 2>&1 &`) and confirm the log's `Connect server listening`.
1462+
When proving a runtime fix, re-point the same test at a service built from the parent revision
1463+
(`git worktree add /tmp/wt-old HEAD~1 && (cd /tmp/wt-old && make build-grpc)`) and require it to
1464+
**fail** — that is the only cheap check that the client assertion is load-bearing rather than
1465+
vacuous.
14301466

14311467
Client API shapes that are easy to get wrong:
14321468

CHANGELOG.md

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,45 @@ Notable changes per release. Format follows [Keep a Changelog](https://keepachan
44
versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Cutting a release
55
is described in [docs/project/releasing.md](docs/project/releasing.md).
66

7-
## Unreleased
7+
## 0.4.0 — 2026-08-28
8+
9+
Release 0.4.0 is about what a model *writes*. An `assign` used to put any value into any feature —
10+
a `String` into a `Real` attribute, a length into a duration — statically and at run time; a write
11+
now answers to the target feature's declared type, multiplicity and, where the target is a quantity,
12+
its dimension, on every path that stores a value. **A model that relied on an unchecked write no
13+
longer validates**, which is why this is a minor rather than a patch.
14+
15+
The runtime also learned the structure it was flattening away: a typed state usage materializes the
16+
content of the definition typing it, a nested action node runs the flow it owns, an assignment target
17+
may be a feature chain, and a performed action's features live on the performance occurrence that
18+
holds them rather than on whatever like-named feature the performer happened to have. A behavior body
19+
now resolves a name where the name is written rather than reaching into the performer for it.
20+
21+
Beyond execution, a view specializing `SequenceView` renders as a sequence diagram, a `Real` prints
22+
as the shortest decimal that reads back as the same value, and the pinned OMG pilot implementation
23+
moves to release `2026-07` (`jupyter-sysml-kernel` 0.61.0) with every oracle baseline re-recorded
24+
against it.
825

926
### Changed
1027

28+
- **A write answers to its target feature's declared type and multiplicity.** An `assign` wrote any
29+
value into any feature: a `Real` attribute accepted a `String`, statically and at run time. KerML's
30+
FeatureWritePerformance "assigns the values of a feature on an occurrence to the given
31+
replacementValues", so those values are values of that feature — the rule already applied to an
32+
initial value. The type pass now walks every body an `assign` may stand in and checks the written
33+
value with the initial-value rule resolved against the target's declaration, and the runtime checks
34+
the same before storing, on every write path. A rejected write leaves the feature as it was.
35+
- **An output a declaration binds is checked too**, so a body-less `out a : Integer = n` no longer
36+
answers with whatever an untyped input carried: the rule holds however an output is given its
37+
value.
38+
- **A written decimal conforms to `Rational`**, as the type tier already read one. The two tiers
39+
disagreed, so a decimal written to a `Rational` feature validated clean and then failed at run
40+
time.
41+
42+
- **A bound or written quantity is judged by the dimension its target declares.** A feature declared
43+
with a quantity value type refuses a quantity measured in another dimension — statically where the
44+
value's dimension is determined, and at run time on every write path.
45+
1146
- **The pinned OMG pilot implementation is now release `2026-07` (`jupyter-sysml-kernel` 0.61.0)**,
1247
with the reference validators, the vendored standard library, the pinned corpora, grammars and
1348
Xpect suites, and every oracle baseline re-recorded at that pin. Two notations the new grammar
@@ -30,6 +65,19 @@ is described in [docs/project/releasing.md](docs/project/releasing.md).
3065

3166
### Added
3267

68+
- **A typed state usage inherits the content of the definition typing it.** The definition's
69+
substates, initial transition, entry/do/exit behaviors, transitions, deferred events and
70+
attributes are materialized per usage rather than shared, including inside a parallel body.
71+
Recursive typing, and content lowering cannot represent, are typed errors rather than silence.
72+
73+
- **A nested action node runs the flow it owns.** A nested node's own members are its
74+
subperformances: lowering carries them as a subgraph and the executor performs that flow before
75+
the node completes. An action usage stating no body of its own resolves to the action definition
76+
typing it, so `%action` on a `perform` usage runs.
77+
78+
- **An assignment target may be a feature chain.** Lowering carries the whole walk and the runtime
79+
writes the feature on the object the chain reaches, resolved in the statement's own scope.
80+
3381
- **A view specializing `StandardViewDefinitions::SequenceView` (or `sv`) renders as a sequence
3482
diagram**, at the prompt (`%render`), from the command line (`sysml -render`) and over the LSP, in
3583
the text form and as a Mermaid `sequenceDiagram`. The occurrences an interaction declares in its
@@ -45,9 +93,57 @@ is described in [docs/project/releasing.md](docs/project/releasing.md).
4593

4694
### Fixed
4795

96+
- **A behavior body resolves a name where the name is written**, rather than reaching into the
97+
object performing it for any like-named feature — which name resolution does not admit. A
98+
performer feature is read and written only where the name resolves to it, and `this` inside an
99+
owned performance denotes the owning object.
100+
101+
- **A performed action's features are written to its performance occurrence.** A performed action's
102+
declared attributes and out parameters are features of the action performance the `perform` usage
103+
holds, so they are initialized from that occurrence's slots and written through it.
104+
105+
- **A state's attributes reach the occurrence exhibiting it**, so an exhibited state and the
106+
occurrence behind it no longer hold divergent data.
107+
108+
- **A send nested in a flow is routed by every flow around it.** A send saw only the action's own
109+
connectors and those of the flow it sat in, so a connector declared by an intermediate flow could
110+
not route it; each activation now carries the connectors of every enclosing flow.
111+
112+
- **An inherited transition retargets to a redeclared substate**, rather than to the substate the
113+
supertype declared.
114+
115+
- **A machine's own supertype is no longer read as recursive typing**, which rejected a state
116+
machine that specialized another.
117+
118+
- **A chained assignment binds no output of a calculation**: the chain's last segment was counted as
119+
the calculation computing an output of that name.
120+
48121
- **Clicking a sequence participant now reveals its declaration, and the cursor highlights it**
49122
using Mermaid's participant data attributes.
50123

124+
- **The site's OpenMBEE links point at the host that serves HTTPS.**
125+
126+
### Project
127+
128+
- **The end-to-end example is one model, driven three ways.** A bomb-disposal robot whose structure,
129+
calculations, fork/join and nested flows, hierarchical state machine, solver cases and views are
130+
the same model throughout, with a walkthrough of the commands that drive it from the CLI, the REPL
131+
and the Python client. A nested action node no longer reports the token-flow limitation when a
132+
view renders it.
133+
134+
- **The dimensional defect in the pilot's `Dynamics.sysml` is a declared erratum**, so the corrected
135+
copy is what the oracles re-run over and the published corpus is still never edited.
136+
137+
- The documentation site states the Open-MBEE and NumFOCUS affiliation in its footer, and the
138+
header's wiki link is labelled Community Wiki.
139+
140+
- **The Python client is unchanged in this release**, so no `opensysml` version is published with
141+
it: the client published as 0.3.2 installs a v0.4.0 `sysml-grpc` by taking the asset's digest from
142+
the release's signed `SHA256SUMS.txt`, which is what an unpinned release's verification is for.
143+
Pinning v0.4.0's digests in `python/opensysml/binary.py` and publishing 0.3.3 remains optional,
144+
and is worth doing only for callers still on `opensysml` 0.3.0, which predates that path and
145+
installs a release it pins no digest for only under `$OPENSYSML_ALLOW_UNPINNED_DOWNLOAD`.
146+
51147
## 0.3.1 — 2026-08-27
52148

53149
A performance patch. Loading a model costs less of everything and answers the same: on a

0 commit comments

Comments
 (0)