sysml2kit 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/CHANGELOG.md +27 -0
  2. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/PKG-INFO +37 -12
  3. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/README.md +34 -11
  4. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/SPEC.md +27 -0
  5. sysml2kit-0.3.0/docker/compose.yaml +35 -0
  6. sysml2kit-0.3.0/docs/api-client.md +49 -0
  7. sysml2kit-0.3.0/docs/verification.md +87 -0
  8. sysml2kit-0.3.0/docs/views.md +24 -0
  9. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/mkdocs.yml +2 -0
  10. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/pyproject.toml +5 -1
  11. sysml2kit-0.3.0/scripts/wait_for_api.sh +17 -0
  12. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/_version.py +2 -2
  13. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/api/client.py +42 -1
  14. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/cli.py +170 -1
  15. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/interchange/reader.py +30 -2
  16. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/mcp/server.py +1 -1
  17. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/mcp/tools_requirements.py +57 -0
  18. sysml2kit-0.3.0/src/sysml2kit/verify/__init__.py +33 -0
  19. sysml2kit-0.3.0/src/sysml2kit/verify/binding.py +120 -0
  20. sysml2kit-0.3.0/src/sysml2kit/verify/engines.py +81 -0
  21. sysml2kit-0.3.0/src/sysml2kit/verify/runner.py +251 -0
  22. sysml2kit-0.3.0/tests/test_api_live.py +123 -0
  23. sysml2kit-0.3.0/tests/test_cli_api.py +70 -0
  24. sysml2kit-0.3.0/tests/test_cli_verify.py +120 -0
  25. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_mcp.py +24 -0
  26. sysml2kit-0.3.0/tests/test_verify.py +216 -0
  27. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/uv.lock +24 -1
  28. sysml2kit-0.2.0/docs/api-client.md +0 -28
  29. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/.gitignore +0 -0
  30. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/.pre-commit-config.yaml +0 -0
  31. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/.python-version +0 -0
  32. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/CITATION.cff +0 -0
  33. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/CLAUDE.md +0 -0
  34. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/CONTRIBUTING.md +0 -0
  35. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/LICENSE +0 -0
  36. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/NOTICE +0 -0
  37. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/SECURITY.md +0 -0
  38. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/backends.md +0 -0
  39. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/cli.md +0 -0
  40. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/concepts.md +0 -0
  41. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/index.md +0 -0
  42. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/interchange.md +0 -0
  43. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/mcp.md +0 -0
  44. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/quickstart.md +0 -0
  45. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/reference.md +0 -0
  46. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/rf-library.md +0 -0
  47. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/docs/traceability.md +0 -0
  48. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/scripts/slopcheck.sh +0 -0
  49. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/__init__.py +0 -0
  50. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/api/__init__.py +0 -0
  51. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/api/errors.py +0 -0
  52. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/api/models.py +0 -0
  53. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/backends/__init__.py +0 -0
  54. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/backends/protocol.py +0 -0
  55. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/backends/sysmlpy.py +0 -0
  56. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/diff.py +0 -0
  57. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/graph.py +0 -0
  58. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/interchange/__init__.py +0 -0
  59. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/interchange/typemap.py +0 -0
  60. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/interchange/writer.py +0 -0
  61. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/interop/__init__.py +0 -0
  62. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/interop/requirements.py +0 -0
  63. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/mcp/__init__.py +0 -0
  64. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/mcp/_common.py +0 -0
  65. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/mcp/tools_model.py +0 -0
  66. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/__init__.py +0 -0
  67. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/analysis.py +0 -0
  68. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/base.py +0 -0
  69. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/builder.py +0 -0
  70. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/container.py +0 -0
  71. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/metadata.py +0 -0
  72. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/relations.py +0 -0
  73. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/requirements.py +0 -0
  74. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/structure.py +0 -0
  75. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/model/values.py +0 -0
  76. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/py.typed +0 -0
  77. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/query.py +0 -0
  78. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/text/__init__.py +0 -0
  79. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/text/keywords.py +0 -0
  80. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/text/writer.py +0 -0
  81. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/units.py +0 -0
  82. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/validation.py +0 -0
  83. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/views.py +0 -0
  84. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/src/sysml2kit/workspace.py +0 -0
  85. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/conftest.py +0 -0
  86. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/fixtures/RFParts.sysml +0 -0
  87. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/fixtures/RFRequirements.sysml +0 -0
  88. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/fixtures/SatcomTerminal28GHz.sysml +0 -0
  89. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/fixtures/vehicle.sysml +0 -0
  90. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_api_client.py +0 -0
  91. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_backend_fidelity.py +0 -0
  92. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_backend_sysmlpy.py +0 -0
  93. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_cli.py +0 -0
  94. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_cli_fmt.py +0 -0
  95. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_diff.py +0 -0
  96. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_interchange.py +0 -0
  97. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_interop.py +0 -0
  98. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_model.py +0 -0
  99. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_package.py +0 -0
  100. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_query.py +0 -0
  101. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_roundtrip_json.py +0 -0
  102. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_roundtrip_text.py +0 -0
  103. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_text_writer/test_vehicle_golden.sysml +0 -0
  104. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_text_writer.py +0 -0
  105. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_validation.py +0 -0
  106. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_values_units.py +0 -0
  107. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_views/test_trace_contains_all_edge_kinds.trace.mmd +0 -0
  108. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_views/test_tree_contains_hierarchy.tree.mmd +0 -0
  109. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_views.py +0 -0
  110. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tests/test_workspace.py +0 -0
  111. {sysml2kit-0.2.0 → sysml2kit-0.3.0}/tools/conformance/run_oracle.py +0 -0
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 — 2026-08-21
4
+
5
+ - **Verification execution** (`sysml2kit.verify`): `verificationBinding`
6
+ metadata binds an analysis case to an engine resolved by name from the
7
+ `sysml2kit.engines` entry-point group (model text never names code paths).
8
+ `run_verification` executes bound analyses and checks each metricKey
9
+ requirement with margins; `apply_results` writes metrics and verdicts back
10
+ into the model with provenance, idempotently. CLI `sysml2kit verify`, MCP
11
+ tool `requirements_verify` (nine tools now), `verify` extra for YAML
12
+ configs, and a `docs/verification.md` flagship page. First engine:
13
+ phased-array-systems (PR #2 there).
14
+ - **Live-server harness**: `docker/compose.yaml` runs the pilot
15
+ implementation (digest-pinned) + postgres; `api`-marked round-trip tests
16
+ pass against the real server; weekly advisory `live-api` workflow. Live
17
+ testing hardened the client and reader for the pilot dialect: list-typed
18
+ endpoints/typing/text adapted on push and tolerated on read, verify/derive
19
+ pushed as Dependency, multiplicity/doc dropped by the server, server-minted
20
+ element ids; known-@type records that do not fit the profile now degrade to
21
+ OpaqueElement instead of failing the read.
22
+ - **`api` CLI group**: `projects`, `pull` (newest commit by default),
23
+ `push --create`; `SYSML2KIT_API_URL`/`SYSML2KIT_API_TOKEN` env vars;
24
+ `SysMLApiClient.head_commit`.
25
+ - **Diagrams docs page** and a README refresh for the 0.3 surface.
26
+ - Upstream sysmlpy fixes submitted for the two pinned parse losses:
27
+ dependency statements (mycr0ft/sysmlpy#7) and allocate endpoints
28
+ (mycr0ft/sysmlpy#6).
29
+
3
30
  ## 0.2.0 — 2026-08-21
4
31
 
5
32
  - **Parse fidelity**: the sysmlpy backend now walks the raw ANTLR dict
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysml2kit
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: API-first Python tooling for building, querying, validating, and automating SysML v2 models
5
5
  Project-URL: Homepage, https://github.com/jman4162/sysml2kit
6
6
  Project-URL: Source, https://github.com/jman4162/sysml2kit
@@ -34,6 +34,8 @@ Provides-Extra: mcp
34
34
  Requires-Dist: mcp<2,>=1.26; extra == 'mcp'
35
35
  Provides-Extra: parse
36
36
  Requires-Dist: sysmlpy<0.37,>=0.36.2; extra == 'parse'
37
+ Provides-Extra: verify
38
+ Requires-Dist: pyyaml>=6.0; extra == 'verify'
37
39
  Description-Content-Type: text/markdown
38
40
 
39
41
  # sysml2kit
@@ -42,20 +44,25 @@ Description-Content-Type: text/markdown
42
44
  [![PyPI](https://img.shields.io/pypi/v/sysml2kit)](https://pypi.org/project/sysml2kit/)
43
45
  [![Python](https://img.shields.io/pypi/pyversions/sysml2kit)](https://pypi.org/project/sysml2kit/)
44
46
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
47
+ [![Docs](https://img.shields.io/badge/docs-jman4162.github.io-blue)](https://jman4162.github.io/sysml2kit/)
45
48
 
46
49
  API-first Python tooling for building, querying, validating, and automating
47
50
  SysML v2 models.
48
51
 
49
- > **Status: pre-alpha.** The 0.1.x line has a working core (model, writer,
50
- > interchange, queries, validation, diff, API client, parse backend); the API
51
- > may still move between minor versions. Pin an exact version if you depend
52
- > on it.
52
+ > **Status: pre-alpha.** The 0.3.x line covers the full loop: model, writer,
53
+ > interchange, queries, validation, diff, mermaid views, parse backend, MCP
54
+ > server, API client with a live-server harness, and verification execution.
55
+ > The API may still move between minor versions; pin an exact version if you
56
+ > depend on it. Changes: [CHANGELOG.md](CHANGELOG.md).
53
57
 
54
58
  `sysml2kit` is the requirements/architecture/traceability layer for
55
59
  engineering automation stacks: build a system model in Python, emit standard
56
60
  SysML v2 textual notation and Systems Modeling API JSON, run traceability
57
61
  queries (which requirements are unsatisfied? unverified? allocated where?),
58
- validate, and diff. It targets the OMG SysML v2 standard, not any vendor tool.
62
+ validate, diff, and **execute verification**: analyses bound to registered
63
+ engines run for real, and their metrics check the model's requirements. It
64
+ targets the OMG SysML v2 standard, not any vendor tool. Docs:
65
+ https://jman4162.github.io/sysml2kit/
59
66
 
60
67
  ## What it does
61
68
 
@@ -72,8 +79,15 @@ validate, and diff. It targets the OMG SysML v2 standard, not any vendor tool.
72
79
  - **Traceability queries**: unsatisfied/unverified requirements, allocation
73
80
  tables, requirement-to-part trace matrices.
74
81
  - **Validation and diff**: rule-based model checks and element-level diffs.
82
+ - **Verification execution**: `verificationBinding` metadata binds an
83
+ analysis case to an engine from the `sysml2kit.engines` entry-point group;
84
+ `sysml2kit verify` runs it and checks each requirement with margins, and
85
+ can write results back into the model with provenance.
86
+ - **Mermaid views**: ownership-tree and requirement-trace diagrams.
87
+ - **MCP server**: nine tools for agents (`sysml2kit mcp serve`).
75
88
  - **API client**: a thin HTTP client for the OMG Systems Modeling API and
76
- Services endpoints.
89
+ Services endpoints, plus a docker compose harness running the pilot
90
+ implementation for live round-trip testing.
77
91
 
78
92
  ## Install
79
93
 
@@ -81,6 +95,8 @@ validate, and diff. It targets the OMG SysML v2 standard, not any vendor tool.
81
95
  pip install sysml2kit # core: build, write, query, validate, diff
82
96
  pip install "sysml2kit[parse]" # + read .sysml files (sysmlpy backend)
83
97
  pip install "sysml2kit[graph]" # + NetworkX export
98
+ pip install "sysml2kit[mcp]" # + MCP server for agents
99
+ pip install "sysml2kit[verify]" # + YAML verification-binding configs
84
100
  ```
85
101
 
86
102
  ## Quick start
@@ -119,9 +135,13 @@ sysml2kit
119
135
  ├── query # traceability queries
120
136
  ├── validation # rule-based checks (S2K001...)
121
137
  ├── diff # element-level model diff
138
+ ├── views # mermaid diagrams (trace, tree)
139
+ ├── verify # verification bindings, engine registry, runner
122
140
  ├── api # Systems Modeling API HTTP client
123
141
  ├── backends # parser backends (sysmlpy behind the [parse] extra)
124
142
  ├── interop # tool-agnostic requirement extraction
143
+ ├── mcp # MCP server (behind the [mcp] extra)
144
+ ├── graph, units, workspace # NetworkX export, pint helpers, path safety
125
145
  └── cli # `sysml2kit` command line
126
146
  ```
127
147
 
@@ -131,13 +151,17 @@ The spec pin, element subset, and known deviations are documented in
131
151
 
132
152
  Domain content lives outside the kit. For antenna/RF systems engineering, see
133
153
  [sysml2kit-rf-library](https://github.com/jman4162/sysml2kit-rf-library), a
134
- SysML v2 model library consumed through this package.
154
+ SysML v2 model library consumed through this package. Downstream bridges are
155
+ merged in [phased-array-systems](https://github.com/jman4162/phased-array-systems)
156
+ (`interop.sysml`: requirement sets and the `phased-array-systems` verification
157
+ engine) and [aedl](https://github.com/jman4162/aedl-electromagnetic-design-agent)
158
+ (`aedl.interop`: bound-form requirements).
135
159
 
136
160
  ## For agents
137
161
 
138
- An MCP server ships behind the `mcp` extra with eight tools: `model_show`,
162
+ An MCP server ships behind the `mcp` extra with nine tools: `model_show`,
139
163
  `model_validate`, `model_diff`, `model_export`, `model_diagram`,
140
- `requirements_trace`, `requirements_extract`, `library_load`. Artifacts are
164
+ `requirements_trace`, `requirements_extract`, `requirements_verify`, `library_load`. Artifacts are
141
165
  returned as file paths, not payloads.
142
166
 
143
167
  ```bash
@@ -149,8 +173,9 @@ sysml2kit mcp serve # stdio; --transport http also supported
149
173
  {"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
150
174
  ```
151
175
 
152
- The CLI (`sysml2kit show | validate | diff | export | fmt`) covers the same
153
- operations for shell use.
176
+ The CLI covers the same operations for shell use:
177
+ `sysml2kit show | validate | diff | export | fmt | verify | api | mcp serve`
178
+ (`export --to mermaid` renders diagrams).
154
179
 
155
180
  ## Development
156
181
 
@@ -4,20 +4,25 @@
4
4
  [![PyPI](https://img.shields.io/pypi/v/sysml2kit)](https://pypi.org/project/sysml2kit/)
5
5
  [![Python](https://img.shields.io/pypi/pyversions/sysml2kit)](https://pypi.org/project/sysml2kit/)
6
6
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
7
+ [![Docs](https://img.shields.io/badge/docs-jman4162.github.io-blue)](https://jman4162.github.io/sysml2kit/)
7
8
 
8
9
  API-first Python tooling for building, querying, validating, and automating
9
10
  SysML v2 models.
10
11
 
11
- > **Status: pre-alpha.** The 0.1.x line has a working core (model, writer,
12
- > interchange, queries, validation, diff, API client, parse backend); the API
13
- > may still move between minor versions. Pin an exact version if you depend
14
- > on it.
12
+ > **Status: pre-alpha.** The 0.3.x line covers the full loop: model, writer,
13
+ > interchange, queries, validation, diff, mermaid views, parse backend, MCP
14
+ > server, API client with a live-server harness, and verification execution.
15
+ > The API may still move between minor versions; pin an exact version if you
16
+ > depend on it. Changes: [CHANGELOG.md](CHANGELOG.md).
15
17
 
16
18
  `sysml2kit` is the requirements/architecture/traceability layer for
17
19
  engineering automation stacks: build a system model in Python, emit standard
18
20
  SysML v2 textual notation and Systems Modeling API JSON, run traceability
19
21
  queries (which requirements are unsatisfied? unverified? allocated where?),
20
- validate, and diff. It targets the OMG SysML v2 standard, not any vendor tool.
22
+ validate, diff, and **execute verification**: analyses bound to registered
23
+ engines run for real, and their metrics check the model's requirements. It
24
+ targets the OMG SysML v2 standard, not any vendor tool. Docs:
25
+ https://jman4162.github.io/sysml2kit/
21
26
 
22
27
  ## What it does
23
28
 
@@ -34,8 +39,15 @@ validate, and diff. It targets the OMG SysML v2 standard, not any vendor tool.
34
39
  - **Traceability queries**: unsatisfied/unverified requirements, allocation
35
40
  tables, requirement-to-part trace matrices.
36
41
  - **Validation and diff**: rule-based model checks and element-level diffs.
42
+ - **Verification execution**: `verificationBinding` metadata binds an
43
+ analysis case to an engine from the `sysml2kit.engines` entry-point group;
44
+ `sysml2kit verify` runs it and checks each requirement with margins, and
45
+ can write results back into the model with provenance.
46
+ - **Mermaid views**: ownership-tree and requirement-trace diagrams.
47
+ - **MCP server**: nine tools for agents (`sysml2kit mcp serve`).
37
48
  - **API client**: a thin HTTP client for the OMG Systems Modeling API and
38
- Services endpoints.
49
+ Services endpoints, plus a docker compose harness running the pilot
50
+ implementation for live round-trip testing.
39
51
 
40
52
  ## Install
41
53
 
@@ -43,6 +55,8 @@ validate, and diff. It targets the OMG SysML v2 standard, not any vendor tool.
43
55
  pip install sysml2kit # core: build, write, query, validate, diff
44
56
  pip install "sysml2kit[parse]" # + read .sysml files (sysmlpy backend)
45
57
  pip install "sysml2kit[graph]" # + NetworkX export
58
+ pip install "sysml2kit[mcp]" # + MCP server for agents
59
+ pip install "sysml2kit[verify]" # + YAML verification-binding configs
46
60
  ```
47
61
 
48
62
  ## Quick start
@@ -81,9 +95,13 @@ sysml2kit
81
95
  ├── query # traceability queries
82
96
  ├── validation # rule-based checks (S2K001...)
83
97
  ├── diff # element-level model diff
98
+ ├── views # mermaid diagrams (trace, tree)
99
+ ├── verify # verification bindings, engine registry, runner
84
100
  ├── api # Systems Modeling API HTTP client
85
101
  ├── backends # parser backends (sysmlpy behind the [parse] extra)
86
102
  ├── interop # tool-agnostic requirement extraction
103
+ ├── mcp # MCP server (behind the [mcp] extra)
104
+ ├── graph, units, workspace # NetworkX export, pint helpers, path safety
87
105
  └── cli # `sysml2kit` command line
88
106
  ```
89
107
 
@@ -93,13 +111,17 @@ The spec pin, element subset, and known deviations are documented in
93
111
 
94
112
  Domain content lives outside the kit. For antenna/RF systems engineering, see
95
113
  [sysml2kit-rf-library](https://github.com/jman4162/sysml2kit-rf-library), a
96
- SysML v2 model library consumed through this package.
114
+ SysML v2 model library consumed through this package. Downstream bridges are
115
+ merged in [phased-array-systems](https://github.com/jman4162/phased-array-systems)
116
+ (`interop.sysml`: requirement sets and the `phased-array-systems` verification
117
+ engine) and [aedl](https://github.com/jman4162/aedl-electromagnetic-design-agent)
118
+ (`aedl.interop`: bound-form requirements).
97
119
 
98
120
  ## For agents
99
121
 
100
- An MCP server ships behind the `mcp` extra with eight tools: `model_show`,
122
+ An MCP server ships behind the `mcp` extra with nine tools: `model_show`,
101
123
  `model_validate`, `model_diff`, `model_export`, `model_diagram`,
102
- `requirements_trace`, `requirements_extract`, `library_load`. Artifacts are
124
+ `requirements_trace`, `requirements_extract`, `requirements_verify`, `library_load`. Artifacts are
103
125
  returned as file paths, not payloads.
104
126
 
105
127
  ```bash
@@ -111,8 +133,9 @@ sysml2kit mcp serve # stdio; --transport http also supported
111
133
  {"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
112
134
  ```
113
135
 
114
- The CLI (`sysml2kit show | validate | diff | export | fmt`) covers the same
115
- operations for shell use.
136
+ The CLI covers the same operations for shell use:
137
+ `sysml2kit show | validate | diff | export | fmt | verify | api | mcp serve`
138
+ (`export --to mermaid` renders diagrams).
116
139
 
117
140
  ## Development
118
141
 
@@ -77,6 +77,33 @@ test failure.
77
77
  - `Model.assign_stable_ids()` rewrites ids as UUIDv5 hashes of qualified
78
78
  names so generated interchange files diff cleanly under version control.
79
79
 
80
+ ## Verification binding convention
81
+
82
+ A ``MetadataUsage`` named ``verificationBinding`` annotating an
83
+ ``AnalysisCaseUsage`` binds that analysis to an executable engine. Values
84
+ (flat scalars, per the metadata model):
85
+
86
+ | key | type | meaning |
87
+ |---|---|---|
88
+ | ``engine`` | str, required | registry name, e.g. ``"phased-array-systems"`` |
89
+ | ``configRef`` | str, optional | ``.yaml``/``.yml``/``.json`` payload file next to the model file (resolved relative to its directory, containment-checked; no ``..``) |
90
+ | ``payload.<dotted>`` | scalar, optional | override deep-merged over the loaded config; dotted keys expand to nested dicts |
91
+
92
+ Engines resolve **by name** against a registry populated from the
93
+ ``sysml2kit.engines`` entry-point group and explicit caller registration.
94
+ Model text never names importable code paths — models are data. The runner
95
+ does not interpret payload contents; each engine owns its payload schema
96
+ (engines needing a config plus scalar arguments define reserved top-level
97
+ keys such as ``config``/``args``).
98
+
99
+ Results written back by ``sysml2kit.verify.apply_results`` are attributes on
100
+ the analysis (``source`` starts with ``sysml2kit.verify``) and a
101
+ ``verificationVerdict`` metadata on each requirement; both replace prior
102
+ same-named results, so reruns do not accumulate.
103
+
104
+ Bindings are an interchange-JSON feature: metadata values round-trip through
105
+ JSON, while textual-notation fidelity for metadata is not yet pinned.
106
+
80
107
  ## Provenance on values
81
108
 
82
109
  `AttributeValue` carries optional `source` and `confidence` fields, following
@@ -0,0 +1,35 @@
1
+ # Local Systems Modeling API server (the OMG pilot implementation) for
2
+ # live-client testing: docker compose -f docker/compose.yaml up -d
3
+ # then scripts/wait_for_api.sh and pytest -m api with
4
+ # SYSML2KIT_API_URL=http://localhost:9000.
5
+ #
6
+ # The app image is the MBSE-mashup containerization of the pilot, pinned by
7
+ # digest (tag 244c221a..., pushed 2025-12-12). Its entrypoint rewrites
8
+ # persistence.xml from the JDBC_*/HIBERNATE_* env vars; hbm2ddl=update
9
+ # creates the schema on first boot. amd64-only: Apple-silicon hosts run it
10
+ # under emulation (the platform key below).
11
+ services:
12
+ db:
13
+ image: postgres:16
14
+ environment:
15
+ POSTGRES_PASSWORD: mysecretpassword
16
+ POSTGRES_DB: sysml2
17
+ healthcheck:
18
+ test: ["CMD-SHELL", "pg_isready -U postgres -d sysml2"]
19
+ interval: 5s
20
+ timeout: 3s
21
+ retries: 24
22
+
23
+ api:
24
+ image: mbsemashup/sysmlv2-api.pilotimpl@sha256:ac5607986dd529fc98a55aa391ac9f51b275c36f74f946285121c896f7e914c6
25
+ platform: linux/amd64
26
+ depends_on:
27
+ db:
28
+ condition: service_healthy
29
+ ports:
30
+ - "9000:9000"
31
+ environment:
32
+ JDBC_URL: jdbc:postgresql://db:5432/sysml2
33
+ JDBC_USER: postgres
34
+ JDBC_PASSWORD: mysecretpassword
35
+ HIBERNATE_HBM2DDL: update
@@ -0,0 +1,49 @@
1
+ # API client
2
+
3
+ `sysml2kit.api.SysMLApiClient` is a hand-written httpx client for the OMG
4
+ Systems Modeling API and Services endpoints (the REST binding any conformant
5
+ model server exposes).
6
+
7
+ ```python
8
+ from sysml2kit.api import SysMLApiClient
9
+
10
+ with SysMLApiClient("https://models.example.com", token="…") as client:
11
+ for project in client.list_projects():
12
+ print(project.id, project.name)
13
+ model = client.list_elements(project_id, commit_id) # -> sysml2kit Model
14
+ client.push_model(project_id, model, message="update")
15
+ ```
16
+
17
+ Covered in v0.1: `list_projects`, `get_project`, `list_branches`,
18
+ `list_commits`, `get_commit`, `get_element`, `list_elements` (returns a
19
+ `Model` via the interchange reader), `create_project`, and `push_model`
20
+ (POSTs a commit whose change set inserts the model's records). Branch
21
+ management and merges are not covered yet.
22
+
23
+ Failures raise `ApiError(status, detail)`. The client sends the bearer token
24
+ to whatever base URL you configure; use HTTPS.
25
+
26
+ ## Local live server and the pilot dialect
27
+
28
+ `docker compose -f docker/compose.yaml up -d` starts the pilot
29
+ implementation (sha-pinned image + postgres); `scripts/wait_for_api.sh`
30
+ polls until it answers, and `SYSML2KIT_API_URL=http://localhost:9000
31
+ pytest -m api` runs the live round-trip suite (a weekly advisory workflow
32
+ does the same in CI). The CLI mirrors the client:
33
+
34
+ ```bash
35
+ export SYSML2KIT_API_URL=http://localhost:9000
36
+ sysml2kit api projects
37
+ sysml2kit api push model.json --project demo --create
38
+ sysml2kit api pull demo -o pulled.json
39
+ ```
40
+
41
+ The pilot speaks the full abstract syntax, so `push_model` adapts records on
42
+ the way out and the interchange reader tolerates the differences on the way
43
+ back. What survives a server round trip: element kinds, names, short names,
44
+ requirement text. What does not (documented degradations — full fidelity
45
+ lives in interchange JSON files): ownership (the pilot models it as
46
+ OwningMembership elements and ignores our owner key), verify/derive kinds
47
+ (pushed as `Dependency`), multiplicity and doc strings (dropped), and
48
+ element ids (the server mints its own, so stable-id workflows are
49
+ local-file-only).
@@ -0,0 +1,87 @@
1
+ # Verification execution
2
+
3
+ `sysml2kit.verify` closes the loop the traceability queries only describe:
4
+ it runs the analyses a model's verify links point at and checks each
5
+ requirement against real metrics.
6
+
7
+ ## The binding convention
8
+
9
+ An analysis case becomes executable when it carries a `verificationBinding`
10
+ metadata (see SPEC.md for the normative statement):
11
+
12
+ ```python
13
+ from sysml2kit.model import builder
14
+
15
+ analysis = builder.analysis(model, "pasStudy", owner=pkg, subject=terminal)
16
+ builder.verify(model, source=analysis, target=link_margin_req, owner=pkg)
17
+ builder.metadata(
18
+ model,
19
+ analysis,
20
+ {"engine": "phased-array-systems", "configRef": "study.yaml"},
21
+ name="verificationBinding",
22
+ )
23
+ ```
24
+
25
+ - `engine` names an entry in the engine registry — never a code path.
26
+ Models are data; the registry decides what runs.
27
+ - `configRef` points at a YAML/JSON payload next to the model file.
28
+ - `payload.<dotted>` values override entries in the loaded config
29
+ (`payload.scenario.range_km: 500`).
30
+
31
+ ## Engines
32
+
33
+ An engine is a callable: payload dict in, flat metrics mapping out.
34
+ Packages ship engines through the `sysml2kit.engines` entry-point group:
35
+
36
+ ```toml
37
+ [project.entry-points."sysml2kit.engines"]
38
+ phased-array-systems = "phased_array_systems.interop.sysml:run_study"
39
+ ```
40
+
41
+ Installing such a package makes its engine available by name. The CLI also
42
+ accepts operator-supplied engines (`--engine name=module:function`), and
43
+ library callers register directly on an `EngineRegistry`.
44
+
45
+ ## Running
46
+
47
+ ```bash
48
+ sysml2kit verify model.json --report run.json
49
+ sysml2kit verify model.json --write-back -o annotated.json
50
+ ```
51
+
52
+ ```python
53
+ from sysml2kit.verify import run_verification, apply_results
54
+
55
+ run = run_verification(model, model_path=path)
56
+ print(run.passed)
57
+ for verdict in run.requirements:
58
+ print(verdict.requirement_id, verdict.status, verdict.margin)
59
+ apply_results(model, run) # record results into the model, idempotent
60
+ ```
61
+
62
+ Each requirement verdict carries the metric key, operator, threshold,
63
+ actual value, and margin; `passed` is true only when every must-severity
64
+ requirement passes and no engine errored. Metrics that are absent or
65
+ non-numeric yield `unknown`, which does not pass. Engine exceptions are
66
+ captured per analysis, never raised.
67
+
68
+ Write-back records each checked metric as an attribute on its analysis with
69
+ a provenance `source` (`sysml2kit.verify <engine>==<version> <timestamp>`)
70
+ and a `verificationVerdict` metadata on each requirement, replacing prior
71
+ results so reruns do not accumulate.
72
+
73
+ Over MCP, the `requirements_verify` tool runs the same flow with
74
+ entry-point engines only, returning `passed`, must-failures, and the report
75
+ path.
76
+
77
+ ## End to end with the RF library
78
+
79
+ With `phased-array-systems` and `sysml2kit-rf-library` installed:
80
+
81
+ ```bash
82
+ MODEL=$(python -c 'import sysml2kit_rf_library as m; print(m.models_dir())')/interchange/satcom_terminal_pas.json
83
+ sysml2kit verify "$MODEL" --report run.json
84
+ ```
85
+
86
+ runs a phased-array study and checks link margin, EIRP, sidelobes, prime
87
+ power, and cost against the model's thresholds.
@@ -0,0 +1,24 @@
1
+ # Diagrams
2
+
3
+ `sysml2kit.views` renders two mermaid views; output is deterministic, so
4
+ diagrams diff cleanly and render anywhere mermaid fences do (these docs,
5
+ GitHub, Claude artifacts).
6
+
7
+ ```python
8
+ from sysml2kit.views import to_mermaid_trace, to_mermaid_tree
9
+
10
+ print(to_mermaid_trace(model)) # requirements, parts, analyses + edges
11
+ print(to_mermaid_tree(model)) # package/part/port ownership
12
+ ```
13
+
14
+ ```bash
15
+ sysml2kit export model.json --to mermaid --diagram trace -o trace.mmd
16
+ sysml2kit export model.json --to mermaid --diagram tree
17
+ ```
18
+
19
+ The trace view draws requirements as hexagons, analyses as parallelograms,
20
+ and parts as rounded boxes, with edge styles per relationship kind: solid
21
+ `satisfy`, dotted `verify`/`derive`, thick `allocate`. Only elements that
22
+ participate in a relationship appear, so large models stay readable.
23
+
24
+ Over MCP, the `model_diagram` tool writes the same views to a `.mmd` file.
@@ -34,7 +34,9 @@ nav:
34
34
  - Quickstart: quickstart.md
35
35
  - Concepts: concepts.md
36
36
  - Traceability: traceability.md
37
+ - Verification: verification.md
37
38
  - Interchange: interchange.md
39
+ - Diagrams: views.md
38
40
  - Command line: cli.md
39
41
  - MCP server: mcp.md
40
42
  - API client: api-client.md
@@ -52,6 +52,8 @@ parse = ["sysmlpy>=0.36.2,<0.37"]
52
52
  graph = ["networkx>=3.2"]
53
53
  # mcp 2.0.0 removed mcp.server.fastmcp; stay on 1.x until the surface is ported.
54
54
  mcp = ["mcp>=1.26,<2"]
55
+ # YAML verification-binding configs; JSON configs work without it.
56
+ verify = ["pyyaml>=6.0"]
55
57
 
56
58
  [project.scripts]
57
59
  sysml2kit = "sysml2kit.cli:app"
@@ -70,15 +72,17 @@ test = [
70
72
  "hypothesis>=6.130",
71
73
  "respx>=0.22",
72
74
  ]
73
- lint = ["mypy>=1.15", "ruff>=0.16"]
75
+ lint = ["mypy>=1.15", "ruff>=0.16", "types-PyYAML>=6.0"]
74
76
  parse-test = ["sysmlpy>=0.36.2,<0.37"]
75
77
  mcp-test = ["mcp>=1.26,<2"]
78
+ verify-test = ["pyyaml>=6.0"]
76
79
  docs = ["mkdocs-material>=9.5", "mkdocstrings[python]>=0.27"]
77
80
  dev = [
78
81
  { include-group = "test" },
79
82
  { include-group = "lint" },
80
83
  { include-group = "parse-test" },
81
84
  { include-group = "mcp-test" },
85
+ { include-group = "verify-test" },
82
86
  { include-group = "docs" },
83
87
  ]
84
88
 
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+ # Wait for a Systems Modeling API server to answer; used locally and in CI.
3
+ set -u
4
+
5
+ URL="${SYSML2KIT_API_URL:-http://localhost:9000}"
6
+ DEADLINE=$((SECONDS + ${WAIT_FOR_API_TIMEOUT:-180}))
7
+
8
+ echo "[wait_for_api] polling ${URL}/projects"
9
+ while [ $SECONDS -lt $DEADLINE ]; do
10
+ if curl -sf "${URL}/projects" >/dev/null 2>&1; then
11
+ echo "[wait_for_api] server is up (${SECONDS}s)"
12
+ exit 0
13
+ fi
14
+ sleep 3
15
+ done
16
+ echo "[wait_for_api] timed out after ${WAIT_FOR_API_TIMEOUT:-180}s" >&2
17
+ exit 1
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.0'
22
- __version_tuple__ = version_tuple = (0, 2, 0)
21
+ __version__ = version = '0.3.0'
22
+ __version_tuple__ = version_tuple = (0, 3, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -101,6 +101,37 @@ class SysMLApiClient:
101
101
  payload["description"] = description
102
102
  return Project.model_validate(self._post("/projects", payload))
103
103
 
104
+ @staticmethod
105
+ def _to_server_record(record: dict[str, Any]) -> dict[str, Any]:
106
+ """Adapt one interchange record to the pilot server's dialect.
107
+
108
+ The abstract syntax types relationship ``source``/``target`` as lists
109
+ of related elements; sysml2kit's records carry a single ``{"@id"}``
110
+ (a documented profile simplification). Wrap them on the way out; the
111
+ interchange reader unwraps single-element lists on the way back.
112
+ """
113
+ adapted = dict(record)
114
+ for key in ("source", "target", "definition"):
115
+ value = adapted.get(key)
116
+ if isinstance(value, dict) and set(value) == {"@id"}:
117
+ adapted[key] = [value]
118
+ # Profile simplifications with no server-side shape are dropped on
119
+ # push (multiplicity is opaque text here, a Multiplicity element
120
+ # there). Fidelity lives in interchange JSON files, not the server.
121
+ adapted.pop("multiplicity", None)
122
+ # RequirementUsage/RequirementDefinition `text` is List<String> there.
123
+ if isinstance(adapted.get("text"), str):
124
+ adapted["text"] = [adapted["text"]]
125
+ # The pilot's type vocabulary has no DeriveRequirementUsage or
126
+ # VerifyRequirementUsage; those push as Dependency (client/supplier),
127
+ # losing the kind distinction on pull — same degradation class as the
128
+ # textual notation. Full fidelity lives in interchange JSON files.
129
+ if adapted.get("@type") in ("DeriveRequirementUsage", "VerifyRequirementUsage"):
130
+ adapted["@type"] = "Dependency"
131
+ adapted["client"] = adapted.pop("source", None) or []
132
+ adapted["supplier"] = adapted.pop("target", None) or []
133
+ return adapted
134
+
104
135
  def push_model(
105
136
  self,
106
137
  project_id: str,
@@ -110,7 +141,10 @@ class SysMLApiClient:
110
141
  message: str | None = None,
111
142
  ) -> Commit:
112
143
  """Create a commit whose change set inserts every element of the model."""
113
- change = [{"@type": "DataVersion", "payload": record} for record in model_to_json(model)]
144
+ change = [
145
+ {"@type": "DataVersion", "payload": self._to_server_record(record)}
146
+ for record in model_to_json(model)
147
+ ]
114
148
  payload: dict[str, Any] = {"@type": "Commit", "change": change}
115
149
  if message:
116
150
  payload["description"] = message
@@ -118,3 +152,10 @@ class SysMLApiClient:
118
152
  if branch:
119
153
  path += f"?branchId={branch}"
120
154
  return Commit.model_validate(self._post(path, payload))
155
+
156
+ def head_commit(self, project_id: str) -> Commit:
157
+ """Return the newest commit of a project; raises ApiError when empty."""
158
+ commits = self.list_commits(project_id)
159
+ if not commits:
160
+ raise ApiError(404, f"project {project_id} has no commits")
161
+ return commits[-1]