Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 13 additions & 13 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ jobs:
name: Lint the protobuf schema
command: make proto-lint

# Baseline is an ancestor of HEAD, never live `origin/main` (a merge landing meanwhile
# would read as deletions): the first parent on main, the previous release on a `v*` tag.
# Baseline is an ancestor of HEAD, never a live branch tip (a merge landing meanwhile would
# read as deletions): the first parent on main or develop, the previous release on a `v*` tag.
- run:
name: Check the protobuf schema for breaking changes
command: |
Expand Down Expand Up @@ -1510,46 +1510,46 @@ jobs:
workflows:
version: 2

# Build and test every merge into main; pull requests run .github/workflows/pr.yml instead.
# Build and test every merge into main or develop; pull requests run .github/workflows/pr.yml instead.
# The Go suite is the four `Go …` jobs, and everything downstream requires all of them.
build-test:
jobs:
- go-static:
name: Go static checks
filters: &main-only
filters: &integration-branches
branches:
only: main
only: [main, develop]
tags:
ignore: /.*/
- go-race-test:
name: Go race tests
filters: *main-only
filters: *integration-branches
- go-coverage:
name: Go coverage profile
filters: *main-only
filters: *integration-branches
- go-gates:
name: Go gates and binaries
filters: *main-only
filters: *integration-branches
- python-test:
name: Python client tests
requires: &go-suite
- Go static checks
- Go race tests
- Go coverage profile
- Go gates and binaries
filters: *main-only
filters: *integration-branches
- rust-test:
name: Rust client tests
requires: *go-suite
filters: *main-only
filters: *integration-branches
- java-test:
name: Java client tests
requires: *go-suite
filters: *main-only
filters: *integration-branches
- node-test:
name: Node client tests
requires: *go-suite
filters: *main-only
filters: *integration-branches
- scan:
name: SonarCloud scan
# Matched exactly, like PyPI below; this context holds SONAR_TOKEN.
Expand All @@ -1566,7 +1566,7 @@ workflows:
- Python client tests
- Java client tests
- Node client tests
filters: *main-only
filters: *integration-branches

# Build and release on tags. The suite runs here too: a tag can point at any
# commit, so a release is only published from a revision proven green.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: PR

# The only CI a pull request runs. Pushes to main and tags are covered by the
# CircleCI config; this workflow mirrors its build-test workflow, not release.
# The only CI a pull request runs. Pushes to main and develop, and tags, are covered
# by the CircleCI config; this workflow mirrors its build-test workflow, not release.
on:
pull_request:

Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ It provides a hand-written lexer/parser, semantic engine, execution runtime, LSP
1. **Correctness over expedience.** No shortcuts, no stubs left behind, no lossy conversions. If a proper fix is large, do it properly or stop and flag it.
- **For features specifically: do not minimize code changes or dodge complexity.** Implement the feature fully and correctly even if it touches many files, adds new types, or requires refactoring. Completeness beats diff size. See §8.
2. **Root-cause first.** Before editing, confirm *why* something fails (read the code, add a temporary debug print, write a focused test). Then make the minimal correct change.
3. **Never regress.** `main` is green. Any test passing on `main` must still pass on your branch. Diff against `main` if unsure: `git stash && git checkout main && go test ./... ; git checkout - && git stash pop`.
3. **Never regress.** `develop` is green. Any test passing on `develop` must still pass on your branch. Diff against `develop` if unsure: `git stash && git checkout develop && go test ./... ; git checkout - && git stash pop`.
4. **Respect the architecture invariants** (see §4). The AST is immutable; semantics live in side tables; execution consumes lowered IR — do not bypass these.
5. **Tests are the contract.** Existing tests encode intended behavior (including *when* and *where* errors surface). Make code satisfy tests, not the reverse — unless the test is provably wrong, in which case explain before changing it.
6. **Leave no dead code.** Remove superseded helpers/structs. Run `go vet ./...` to catch it.
Expand Down Expand Up @@ -139,7 +139,7 @@ Then update `docs/project/spec-compliance.md` mapping: semantic rule → impleme

## 6. Development Workflow

1. **Understand first.** Grep/read the relevant package and its tests. Diff the branch against `main` to see what changed and why.
1. **Understand first.** Grep/read the relevant package and its tests. Diff the branch against `develop` to see what changed and why.
2. **Reproduce.** Run the failing test(s) and read the exact error before changing anything.
3. **Locate the root cause** in the correct layer (lexer vs parser vs lower vs runtime). Bugs in specialized layers are often upstream of where they surface.
4. **Implement the correct fix.** For bug fixes, keep edits minimal and scoped. For features, implement completely (see §8) — "minimal" means *no unrelated changes*, never *under-built*. Match existing style; keep imports at the top.
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ release is described in [docs/project/releasing.md](docs/project/releasing.md).
- **A verification case runs and reports the verdict of its body.** `sysml -analysis`, `%analysis` and the `RunAnalysis` RPC accept a `verification def` or `verification` usage and run it the way they run an analysis case — the same lowering, subject and input binding, and step execution. The `VerdictKind` the body produced is reported: `pass` or `fail` as the library's own `VerificationCases::PassIf` calculation computes it, a `VerdictKind` literal the body binds as it stands, `inconclusive` for a body that produced no verdict value, and `error`, carrying the message, for a body whose run failed.
- **The body verdict is reported beside requirement satisfaction, not instead of it.** `-requirement`, `-satisfy`, `%requirement`, `%satisfy` and the `VerifyRequirement`/`VerifySatisfaction` RPCs add one line per verification case verifying the requirement; what the requirement engine decided, and the exit status, are unchanged. A case performed as a step of another is reported on its own, marked as a subcase, since the library states no roll-up. Over gRPC the verdicts are added fields (`verification_verdicts` on `VerifyRequirementResponse`, `VerifySatisfactionResponse` and `RunAnalysisResponse`), advertised as the `verification_verdicts` capability, and `sysml -json` reports them under `verifications`. Each carries the `requirement_id` it was reported for, matching the `requirement_id` a `satisfy` verdict carries, so a satisfaction response covering several requirements is read per requirement. The Go and Python clients report the verdicts as `Verifications`/`verifications`, giving each satisfaction verdict the cases of its own requirement.

- **A worked walkthrough of analysis cases, `examples/analysis-demo`.** One lander model asked every way the tool answers: an analysis whose action steps feed each other and whose objective is a requirement, run bound, with arguments and on an object; a verification case whose body verdict is reported beside its objective; a parameter sweep and a seeded sample; two trade studies choosing among three landers, one swept over its cost parameter; and an action and a state machine due at the same instant of the shared clock, run under the default and `declared` scheduling policies and under `explore`. Each command is shown with its output and what to read in it, with `-trace` and `-json`, the REPL forms and the same questions asked through the Python client in `lander_demo.py`.

### Changed

- **What may differ from 0.6.0.** A model that mixes actions and state machines can take another
Expand Down Expand Up @@ -244,6 +246,11 @@ release is described in [docs/project/releasing.md](docs/project/releasing.md).

- **The SonarCloud findings outside cognitive complexity are cleared again.** Duplicated literals are named constants, same-typed parameters share a declaration, `encodeMember` takes its member head as a struct, marker methods state their contract, unnecessary locals are inlined, the release-gate script reports errors on stderr, the MSI script names its positional parameters, the Java transport catches connect timeouts in their own block, and the Java and Python tests hold one call per exception assertion. The exhaustive switches of the AST codec and the planners' error kinds, and the sealed code-generation IR, are documented exclusions. No behavior changes.

- Development moved to a `develop` integration branch; `main` now carries releases only.
Feature and fix pull requests target `develop`, releases reach `main` through
`release/x.y.z` pull requests and are tagged there, and CircleCI builds and tests both
branches. `make proto-breaking` compares against `origin/develop` by default.

### Fixed

- **A transition's `accept` with no `via` no longer takes a transfer addressed to a port.** An accept naming no port receives as the performer of the machine (SysML v2 §7.16.7), and a port is a sub-occurrence of its part, not the part, so `send new Ping() to alpha.inPort` — or a send routed to `inPort` over a connector — is now taken only by `accept Ping via inPort`; a via-less `accept Ping` on the same state is not enabled by it and no choice point is reported between the two. A transfer addressed to the part itself, `send new Ping() to alpha`, is still taken by the via-less accept and not by the `via` one. The state executor now judges every message by the same rule its dispatch check and the action executor already applied, so the two agree on what a machine can react to; call and change triggers are unaffected.
Expand Down Expand Up @@ -285,6 +292,8 @@ release is described in [docs/project/releasing.md](docs/project/releasing.md).

- **Loading a model no longer merges the library's visible member set once per declaration.** The inherited-name conflict rule looks each name up in the memoized member maps of a declaration's library bases and passed-through types instead of copying them into a fresh map per part, attribute, action and state; its diagnostics are unchanged. The OOSEM method rule memoizes a type's classification, so an attribute type shared by many features is conformance-checked once. Loading and validating a 4 000-element model is 15% faster and allocates a third fewer bytes than before; `sysml -validate` on 3 000–12 000-element models is now at or ahead of release 0.4.2. `docs/project/performance-release-0.6-vs-0.4.2.md` records the comparison, the remaining costs of the validation rules added since 0.4.2, and how to repeat it. The Apollo 11 load figure on the landing page and in `docs/internals/performance.md` is re-measured at 0.43 s: the earlier 0.37 s was taken while the model's three calculation-arity findings were still errors, before the higher validation tiers ran.

- **A long action run no longer grows the memory of a race-instrumented binary step by step.** Each step of a token used to run on a coroutine of its own so that a breakpoint or a wait on the clock inside it could pause the token, and Go's race detector keeps a coroutine's state after it ends, so a run of a million steps under `go test -race` took gigabytes and could be killed for memory. The steps of a run now share one coroutine, which only a paused step keeps for as long as it is paused; breakpoints, clock waits, `Release` and the deadlock reported for an abandoned pause behave as before. The step-budget tests of the runtime package now peak at a few hundred megabytes under the race detector rather than several gigabytes.

## 0.6.0 — 2026-09-07

### Added
Expand Down
30 changes: 23 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ make proto # regenerate the Go, Java and Python stubs
make proto-buf # Go and Java stubs only
make python-proto # Python stubs only (needs grpcio-tools; PYTHON=... picks the interpreter)
make proto-lint # lint the schema, as CI does
make proto-breaking # reject wire-breaking changes against main, as CI does
make proto-breaking # reject wire-breaking changes against develop, as CI does

# Python gRPC bindings
make python-install # install opensysml package
Expand Down Expand Up @@ -144,14 +144,26 @@ docs: update Quick Start guide with new commands
test(semantics): add conformance checking test cases
```

## Branches

The repository follows git-flow with two long-lived branches:

- `develop` is the integration branch and the default branch. Every `feature/`, `fix/`, `docs/`,
`ci/` and `test/` branch is cut from `develop`, and its pull request targets `develop`.
- `main` is the release branch. It receives only `release/x.y.z` pull requests (cut from
`develop`, with the changelog fragments folded in) and `hotfix/` pull requests. Release tags —
`v*` and the client package tags — are created on `main`. After a release is tagged, `main`
is merged back into `develop` (a plain merge, no rebase) so hotfixes and the folded changelog
flow down. See [docs/project/releasing.md](docs/project/releasing.md).

## Pull Request Process

1. **Fork** the repository
2. **Create a branch** from `main`: `git checkout -b feat/my-feature`
2. **Create a branch** from `develop`: `git checkout -b feat/my-feature`
3. **Make changes** with clear commit messages
4. **Run tests**: `go test ./...`
5. **Push** to your fork
6. **Open a Pull Request** targeting `main`
6. **Open a Pull Request** targeting `develop`

### PR Guidelines

Expand All @@ -168,14 +180,17 @@ test(semantics): add conformance checking test cases
### Creating a Release

1. **Update version** (if needed in code)
2. **Tag the release:**
2. **Merge the `release/x.y.z` pull request** into `main` (see
[docs/project/releasing.md](docs/project/releasing.md))
3. **Tag the release** on `main`:
```bash
git tag -a v0.1.0 -m "Release v0.1.0: Initial public release"
git push origin v0.1.0
```
3. **CI automatically:**
4. **CI automatically:**
- Builds binaries for all platforms
- Publishes to GitHub Releases
5. **Merge `main` back into `develop`**

### Release Checklist

Expand All @@ -200,7 +215,8 @@ A release is a **PATCH** when everything the previous release accepted still beh
result into the one the Kernel Semantic Library derives; that is compatible and is listed under
*Fixed*.
- No CLI flag, REPL command, RPC or wire field is removed or renamed. The protobuf
wire-compatibility check, `make proto-breaking`, passes.
wire-compatibility check passes against the previous release's schema:
`make proto-breaking BUF_BREAKING_REF=origin/main` on the release branch.

New features, new flags, new capabilities and new wire fields are all patch material.

Expand Down Expand Up @@ -243,7 +259,7 @@ is over-tested rather than untested — teach the script about it, and add a cas

`.circleci/config.yml` runs after a merge and on tags, never on a pull request branch:

**On every push to `main`:**
**On every push to `main` or `develop`:**
- The same suite, gates, client tests and conformance runs as the pull-request workflow, over
the merged tree, plus the host binaries
- SonarCloud scan, fed by the Go and client coverage reports
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ GO_WINRES_VERSION := v0.3.3

# buf drives all protobuf codegen; override BUF to use an already-installed binary.
BUF ?= go run github.com/bufbuild/buf/cmd/buf@$(BUF_VERSION)
# Wire-compatibility baseline: the schema as it stands on the main branch.
BUF_BREAKING_REF ?= origin/main
# Wire-compatibility baseline: the schema as it stands on the develop branch.
BUF_BREAKING_REF ?= origin/develop

# go-winres embeds a VERSIONINFO resource into the Windows binaries (a build
# tool only; nothing of it ships). The .syso it writes carries a _windows_amd64
Expand Down Expand Up @@ -253,7 +253,7 @@ proto-lint: ## Lint the protobuf schema
$(BUF) lint
@echo "✓ Proto lint passed"

proto-breaking: ## Check the protobuf schema for wire-breaking changes against main
proto-breaking: ## Check the protobuf schema for wire-breaking changes against develop
@# An archive, not the .git directory: buf would clone that, which a blobless (CI) checkout cannot serve.
baseline=$$(mktemp -t proto-baseline.XXXXXX) && trap 'rm -f "$$baseline"' EXIT && \
git archive --format=tar -o "$$baseline" '$(BUF_BREAKING_REF)' api/proto && \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ github.com/Open-MBEE/OpenSysML
- **Grammar source:** OMG pilot Xtext grammars (`SysML.xtext` and `KerMLExpressions`)
- **Spec compliance:** [OMG SysML v2.1 Beta 1 / KerML 1.1](https://www.omg.org/spec/SysML/2.0) (2026-07 release)
- **Standard library:** 94 files from [SysML v2 Pilot Implementation 2026-07](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/releases/tag/2026-07), byte-identical, plus the non-normative `OpenSysML Libraries/OpenSysMLMathFunctions.kerml` extension
- **CI/CD:** GitHub Actions checks pull requests; CircleCI builds and tests `main` and publishes releases from tags
- **CI/CD:** GitHub Actions checks pull requests; CircleCI builds and tests `main` and `develop` and publishes releases from tags

## Releases

Expand Down
1 change: 0 additions & 1 deletion changes/unreleased/analysis-walkthrough.added.md

This file was deleted.

Loading
Loading