sysml2kit 0.0.1__tar.gz → 0.2.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 (102) hide show
  1. sysml2kit-0.2.0/CHANGELOG.md +55 -0
  2. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/PKG-INFO +23 -6
  3. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/README.md +20 -5
  4. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/SPEC.md +21 -0
  5. sysml2kit-0.2.0/docs/api-client.md +28 -0
  6. sysml2kit-0.2.0/docs/backends.md +39 -0
  7. sysml2kit-0.2.0/docs/cli.md +24 -0
  8. sysml2kit-0.2.0/docs/concepts.md +46 -0
  9. sysml2kit-0.2.0/docs/index.md +24 -0
  10. sysml2kit-0.2.0/docs/interchange.md +31 -0
  11. sysml2kit-0.2.0/docs/mcp.md +34 -0
  12. sysml2kit-0.2.0/docs/quickstart.md +47 -0
  13. sysml2kit-0.2.0/docs/reference.md +31 -0
  14. sysml2kit-0.2.0/docs/rf-library.md +33 -0
  15. sysml2kit-0.2.0/docs/traceability.md +47 -0
  16. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/mkdocs.yml +10 -0
  17. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/pyproject.toml +18 -2
  18. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/__init__.py +5 -3
  19. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/_version.py +2 -2
  20. sysml2kit-0.2.0/src/sysml2kit/api/__init__.py +7 -0
  21. sysml2kit-0.2.0/src/sysml2kit/api/client.py +120 -0
  22. sysml2kit-0.2.0/src/sysml2kit/api/errors.py +12 -0
  23. sysml2kit-0.2.0/src/sysml2kit/api/models.py +36 -0
  24. sysml2kit-0.2.0/src/sysml2kit/backends/__init__.py +31 -0
  25. sysml2kit-0.2.0/src/sysml2kit/backends/protocol.py +38 -0
  26. sysml2kit-0.2.0/src/sysml2kit/backends/sysmlpy.py +445 -0
  27. sysml2kit-0.2.0/src/sysml2kit/cli.py +232 -0
  28. sysml2kit-0.2.0/src/sysml2kit/diff.py +106 -0
  29. sysml2kit-0.2.0/src/sysml2kit/graph.py +36 -0
  30. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/reader.py +2 -2
  31. sysml2kit-0.2.0/src/sysml2kit/interop/__init__.py +5 -0
  32. sysml2kit-0.2.0/src/sysml2kit/interop/requirements.py +113 -0
  33. sysml2kit-0.2.0/src/sysml2kit/mcp/__init__.py +1 -0
  34. sysml2kit-0.2.0/src/sysml2kit/mcp/_common.py +23 -0
  35. sysml2kit-0.2.0/src/sysml2kit/mcp/server.py +57 -0
  36. sysml2kit-0.2.0/src/sysml2kit/mcp/tools_model.py +240 -0
  37. sysml2kit-0.2.0/src/sysml2kit/mcp/tools_requirements.py +76 -0
  38. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/container.py +8 -0
  39. sysml2kit-0.2.0/src/sysml2kit/query.py +133 -0
  40. sysml2kit-0.2.0/src/sysml2kit/text/__init__.py +5 -0
  41. sysml2kit-0.2.0/src/sysml2kit/text/keywords.py +52 -0
  42. sysml2kit-0.2.0/src/sysml2kit/text/writer.py +179 -0
  43. sysml2kit-0.2.0/src/sysml2kit/validation.py +186 -0
  44. sysml2kit-0.2.0/src/sysml2kit/views.py +92 -0
  45. sysml2kit-0.2.0/src/sysml2kit/workspace.py +22 -0
  46. sysml2kit-0.2.0/tests/conftest.py +46 -0
  47. sysml2kit-0.2.0/tests/fixtures/RFParts.sysml +36 -0
  48. sysml2kit-0.2.0/tests/fixtures/RFRequirements.sysml +33 -0
  49. sysml2kit-0.2.0/tests/fixtures/SatcomTerminal28GHz.sysml +109 -0
  50. sysml2kit-0.2.0/tests/fixtures/vehicle.sysml +27 -0
  51. sysml2kit-0.2.0/tests/test_api_client.py +87 -0
  52. sysml2kit-0.2.0/tests/test_backend_fidelity.py +172 -0
  53. sysml2kit-0.2.0/tests/test_backend_sysmlpy.py +54 -0
  54. sysml2kit-0.2.0/tests/test_cli.py +87 -0
  55. sysml2kit-0.2.0/tests/test_cli_fmt.py +99 -0
  56. sysml2kit-0.2.0/tests/test_diff.py +61 -0
  57. sysml2kit-0.2.0/tests/test_interchange.py +56 -0
  58. sysml2kit-0.2.0/tests/test_interop.py +104 -0
  59. sysml2kit-0.2.0/tests/test_mcp.py +111 -0
  60. sysml2kit-0.2.0/tests/test_model.py +105 -0
  61. sysml2kit-0.2.0/tests/test_query.py +59 -0
  62. sysml2kit-0.2.0/tests/test_roundtrip_json.py +45 -0
  63. sysml2kit-0.2.0/tests/test_roundtrip_text.py +44 -0
  64. sysml2kit-0.2.0/tests/test_text_writer/test_vehicle_golden.sysml +27 -0
  65. sysml2kit-0.2.0/tests/test_text_writer.py +51 -0
  66. sysml2kit-0.2.0/tests/test_validation.py +82 -0
  67. sysml2kit-0.2.0/tests/test_values_units.py +42 -0
  68. sysml2kit-0.2.0/tests/test_views/test_trace_contains_all_edge_kinds.trace.mmd +9 -0
  69. sysml2kit-0.2.0/tests/test_views/test_tree_contains_hierarchy.tree.mmd +10 -0
  70. sysml2kit-0.2.0/tests/test_views.py +37 -0
  71. sysml2kit-0.2.0/tests/test_workspace.py +24 -0
  72. sysml2kit-0.2.0/tools/conformance/run_oracle.py +100 -0
  73. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/uv.lock +492 -2
  74. sysml2kit-0.0.1/CHANGELOG.md +0 -12
  75. sysml2kit-0.0.1/docs/index.md +0 -19
  76. sysml2kit-0.0.1/src/sysml2kit/cli.py +0 -26
  77. sysml2kit-0.0.1/tools/conformance/run_oracle.py +0 -70
  78. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/.gitignore +0 -0
  79. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/.pre-commit-config.yaml +0 -0
  80. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/.python-version +0 -0
  81. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/CITATION.cff +0 -0
  82. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/CLAUDE.md +0 -0
  83. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/CONTRIBUTING.md +0 -0
  84. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/LICENSE +0 -0
  85. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/NOTICE +0 -0
  86. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/SECURITY.md +0 -0
  87. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/scripts/slopcheck.sh +0 -0
  88. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/__init__.py +0 -0
  89. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/typemap.py +0 -0
  90. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/interchange/writer.py +0 -0
  91. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/__init__.py +0 -0
  92. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/analysis.py +0 -0
  93. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/base.py +0 -0
  94. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/builder.py +0 -0
  95. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/metadata.py +0 -0
  96. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/relations.py +0 -0
  97. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/requirements.py +0 -0
  98. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/structure.py +0 -0
  99. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/model/values.py +0 -0
  100. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/py.typed +0 -0
  101. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/src/sysml2kit/units.py +0 -0
  102. {sysml2kit-0.0.1 → sysml2kit-0.2.0}/tests/test_package.py +0 -0
@@ -0,0 +1,55 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0 — 2026-08-21
4
+
5
+ - **Parse fidelity**: the sysmlpy backend now walks the raw ANTLR dict
6
+ (`load_grammar_antlr`) instead of the lossy wrapper objects. Short names,
7
+ feature typing (incl. cross-package), multiplicity, attribute values with
8
+ units, requirement subjects and text, docs, and satisfy statements survive
9
+ a text parse. Upstream visitor losses (dependency statements, allocate and
10
+ connect endpoints, verification cases) are pinned by tests, documented in
11
+ SPEC.md, and filed upstream (sysmlpy #4, #5).
12
+ - **MCP server** (`pip install sysml2kit[mcp]`; `sysml2kit mcp serve`):
13
+ eight tools — model_show, model_validate, model_diff, model_export,
14
+ model_diagram, requirements_trace, requirements_extract, library_load.
15
+ - **`fmt` command** with a loss-refusing safety gate (grammar-signature and
16
+ model-diff comparison; `--lossy` to override, `--check` for CI).
17
+ - **Mermaid views** (`sysml2kit.views`): ownership tree and requirement
18
+ trace diagrams; `export --to mermaid` and the model_diagram tool.
19
+ - **Conformance oracle** pinned to windtrader-java 0.1.1 (sha256-verified,
20
+ out-of-process pilot parser); weekly workflow green.
21
+ - Downstream bridges landed as PRs: phased-array-systems#1 (op-form
22
+ RequirementSet) and aedl#1 (bound-form requirements); the RequirementSpec
23
+ field set is now frozen by a schema test.
24
+
25
+ ## 0.1.0 — 2026-08-21
26
+
27
+ First working release.
28
+
29
+ - Object model: the pragmatic profile (~20 element kinds) as pydantic
30
+ classes, `Model` container with identity/ownership/qualified names,
31
+ `assign_stable_ids()` (UUIDv5), fluent builder API, `AttributeValue` with
32
+ unit text and provenance, pint-backed unit helpers.
33
+ - JSON interchange: Systems Modeling API serialization reader/writer,
34
+ deterministic output, `OpaqueElement` passthrough for unknown `@type`s;
35
+ json→model→json fixpoint property-tested.
36
+ - Textual notation writer: deterministic `.sysml` output; verified against
37
+ the sysmlpy parser (write → parse → structural compare).
38
+ - Traceability queries: satisfied_by/verified_by/derived_from,
39
+ unsatisfied/unverified requirements, allocation table, trace matrix.
40
+ - Validation: rules S2K001–S2K009 with severities and stable ids.
41
+ - Diff: element-level with `--by-name` matching for regenerated ids.
42
+ - API client: hand-written httpx client for the Systems Modeling API
43
+ (projects/branches/commits/elements reads, create_project, push_model).
44
+ - Parser backends: `ParserBackend` protocol; sysmlpy adapter behind the
45
+ `parse` extra.
46
+ - Interop: `extract_requirements` reading the metricKey convention, with
47
+ dual-form thresholds for operator-style and bound-style engines.
48
+ - CLI: `show` (`--traceability`), `validate`, `diff`, `export`
49
+ (`--stable-ids`), `version`.
50
+ - Docs site, conformance-oracle workflow scaffold, prose lint tooling.
51
+
52
+ ## 0.0.1 — 2026-08-21
53
+
54
+ - Package skeleton published to claim the PyPI name. Importable, no usable
55
+ functionality yet.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sysml2kit
3
- Version: 0.0.1
3
+ Version: 0.2.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
@@ -30,6 +30,8 @@ Requires-Dist: pydantic>=2.7
30
30
  Requires-Dist: typer>=0.12
31
31
  Provides-Extra: graph
32
32
  Requires-Dist: networkx>=3.2; extra == 'graph'
33
+ Provides-Extra: mcp
34
+ Requires-Dist: mcp<2,>=1.26; extra == 'mcp'
33
35
  Provides-Extra: parse
34
36
  Requires-Dist: sysmlpy<0.37,>=0.36.2; extra == 'parse'
35
37
  Description-Content-Type: text/markdown
@@ -44,8 +46,10 @@ Description-Content-Type: text/markdown
44
46
  API-first Python tooling for building, querying, validating, and automating
45
47
  SysML v2 models.
46
48
 
47
- > **Status: pre-alpha.** The 0.0.x releases claim the package name and publish
48
- > the skeleton while the core lands. Pin an exact version if you depend on it.
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.
49
53
 
50
54
  `sysml2kit` is the requirements/architecture/traceability layer for
51
55
  engineering automation stacks: build a system model in Python, emit standard
@@ -131,9 +135,22 @@ SysML v2 model library consumed through this package.
131
135
 
132
136
  ## For agents
133
137
 
134
- The CLI (`sysml2kit show | validate | diff | export`) is the current
135
- automation surface. An MCP server is planned for v0.2 under
136
- `sysml2kit.mcp`.
138
+ An MCP server ships behind the `mcp` extra with eight tools: `model_show`,
139
+ `model_validate`, `model_diff`, `model_export`, `model_diagram`,
140
+ `requirements_trace`, `requirements_extract`, `library_load`. Artifacts are
141
+ returned as file paths, not payloads.
142
+
143
+ ```bash
144
+ pip install "sysml2kit[mcp,parse]"
145
+ sysml2kit mcp serve # stdio; --transport http also supported
146
+ ```
147
+
148
+ ```json
149
+ {"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
150
+ ```
151
+
152
+ The CLI (`sysml2kit show | validate | diff | export | fmt`) covers the same
153
+ operations for shell use.
137
154
 
138
155
  ## Development
139
156
 
@@ -8,8 +8,10 @@
8
8
  API-first Python tooling for building, querying, validating, and automating
9
9
  SysML v2 models.
10
10
 
11
- > **Status: pre-alpha.** The 0.0.x releases claim the package name and publish
12
- > the skeleton while the core lands. Pin an exact version if you depend on it.
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.
13
15
 
14
16
  `sysml2kit` is the requirements/architecture/traceability layer for
15
17
  engineering automation stacks: build a system model in Python, emit standard
@@ -95,9 +97,22 @@ SysML v2 model library consumed through this package.
95
97
 
96
98
  ## For agents
97
99
 
98
- The CLI (`sysml2kit show | validate | diff | export`) is the current
99
- automation surface. An MCP server is planned for v0.2 under
100
- `sysml2kit.mcp`.
100
+ An MCP server ships behind the `mcp` extra with eight tools: `model_show`,
101
+ `model_validate`, `model_diff`, `model_export`, `model_diagram`,
102
+ `requirements_trace`, `requirements_extract`, `library_load`. Artifacts are
103
+ returned as file paths, not payloads.
104
+
105
+ ```bash
106
+ pip install "sysml2kit[mcp,parse]"
107
+ sysml2kit mcp serve # stdio; --transport http also supported
108
+ ```
109
+
110
+ ```json
111
+ {"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
112
+ ```
113
+
114
+ The CLI (`sysml2kit show | validate | diff | export | fmt`) covers the same
115
+ operations for shell use.
101
116
 
102
117
  ## Development
103
118
 
@@ -46,6 +46,27 @@ not drop elements the profile lacks classes for.
46
46
  - **Documentation is a field** (`Element.doc`), not an owned `Documentation`
47
47
  element; the writer emits `doc /* ... */` bodies.
48
48
 
49
+ ## Text parse fidelity (sysmlpy backend, 0.36.x)
50
+
51
+ The backend parses via ``sysmlpy.load_grammar_antlr`` and walks the raw
52
+ ANTLR dict (the wrapper-object loader rebuilds usage bodies lossily and is
53
+ not used). What survives a text round trip:
54
+
55
+ | Round-trips | Lost upstream (sysmlpy visitor discards it) |
56
+ |---|---|
57
+ | names, short names | `dependency A to B;` statements (how the writer emits verify/derive) |
58
+ | docs (package/part/requirement scope) | `allocate X to Y;` endpoints |
59
+ | feature typing, incl. cross-package | `connect a.pa to b.pb;` endpoints |
60
+ | multiplicity | `verification` case usages (dropped entirely) |
61
+ | attribute values with units | value provenance (`source`/`confidence` have no textual slot) |
62
+ | requirement subject and text | |
63
+ | satisfy (package level and inside part bodies) | |
64
+
65
+ Consequence: **satisfy traceability survives text; verify/derive/allocate
66
+ require the JSON interchange.** The losses are pinned by tests in
67
+ `tests/test_backend_fidelity.py` so an upstream sysmlpy fix surfaces as a
68
+ test failure.
69
+
49
70
  ## Identity and ownership
50
71
 
51
72
  - Every element has a UUID `element_id`, mapping to the API JSON `@id`.
@@ -0,0 +1,28 @@
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
+ Server compatibility note: the pilot API-Services implementation has JSON
27
+ quirks relative to the spec; compatibility is tested best-effort behind the
28
+ `api` pytest marker against a local server, not in default CI.
@@ -0,0 +1,39 @@
1
+ # Parser backends
2
+
3
+ sysml2kit does not implement the SysML v2 grammar. Reading textual notation
4
+ goes through a `ParserBackend` (see `sysml2kit.backends.protocol`):
5
+
6
+ ```python
7
+ from sysml2kit.backends import get_backend
8
+
9
+ backend = get_backend("sysmlpy")
10
+ model = backend.parse(text)
11
+ model = backend.parse_files([path_a, path_b])
12
+ ```
13
+
14
+ ## The sysmlpy backend
15
+
16
+ `pip install sysml2kit[parse]` installs
17
+ [sysmlpy](https://github.com/mycr0ft/sysmlpy) (MIT, ANTLR4-based). The
18
+ backend parses with `sysmlpy.load_grammar_antlr` and walks the raw ANTLR
19
+ dict — sysmlpy's own wrapper loader rebuilds usage bodies lossily, so the
20
+ wrappers are not used.
21
+
22
+ Fidelity: names, short names, docs, feature typing (including
23
+ cross-package), multiplicity, attribute values with units, requirement
24
+ subjects, and satisfy statements survive a text parse. What cannot
25
+ round-trip is what sysmlpy's visitor discards before we see it: `dependency`
26
+ statements (how the writer emits verify/derive), `allocate` and `connect`
27
+ endpoints, and `verification` cases (filed upstream as sysmlpy #4 and #5).
28
+ The fidelity table lives in SPEC.md and is pinned by
29
+ `tests/test_backend_fidelity.py`. Use JSON interchange when you need the
30
+ full traceability graph.
31
+
32
+ The dependency is capped (`sysmlpy>=0.36.2,<0.37`) because it has a single
33
+ maintainer; bumps are deliberate, after reading the release notes.
34
+
35
+ ## Conformance oracle
36
+
37
+ A scheduled workflow (`conformance.yml`) downloads the EPL-2.0 OMG pilot
38
+ implementation at run time (never vendored) and checks it accepts every
39
+ `.sysml` file our writer emits. See `tools/conformance/run_oracle.py`.
@@ -0,0 +1,24 @@
1
+ # Command line
2
+
3
+ `sysml2kit` accepts `.json` interchange files everywhere; `.sysml` inputs
4
+ need the parse extra (`pip install sysml2kit[parse]`).
5
+
6
+ ```bash
7
+ sysml2kit show model.json # element tree + counts
8
+ sysml2kit show model.json --traceability # + requirement-to-part matrix
9
+ sysml2kit validate a.json b.sysml # exit 1 on error-severity issues
10
+ sysml2kit diff old.json new.json # exit 1 when models differ
11
+ sysml2kit diff old.json new.json --by-name # match by qualified name, not id
12
+ sysml2kit export model.sysml --to json -o model.json
13
+ sysml2kit export model.json --to sysml
14
+ sysml2kit export model.json --to json --stable-ids # UUIDv5 ids for committing
15
+ sysml2kit export model.json --to mermaid --diagram trace # or tree
16
+ sysml2kit fmt model.sysml # refuses lossy rewrites; --lossy overrides
17
+ sysml2kit fmt model.sysml --check # CI mode: exit 1 if it would change
18
+ sysml2kit mcp serve # MCP server (mcp extra)
19
+ sysml2kit version
20
+ ```
21
+
22
+ Exit codes: `validate` returns 1 when any error-severity issue is found;
23
+ `diff` returns 1 when the models differ; `fmt --check` returns 1 when the
24
+ file would change. All suit CI gates.
@@ -0,0 +1,46 @@
1
+ # Concepts
2
+
3
+ ## The pragmatic profile
4
+
5
+ sysml2kit implements ~20 element kinds (packages, part/port/attribute
6
+ definitions and usages, interfaces, connections, requirements, constraints,
7
+ analysis cases, metadata, and four traceability relationships), not the full
8
+ ~270-metaclass abstract syntax. Anything outside the profile round-trips
9
+ through `OpaqueElement`: on JSON import an unrecognized `@type` keeps its raw
10
+ record and ownership links, and re-exports unchanged.
11
+
12
+ The repo's `SPEC.md` lists the profile, the pinned spec release
13
+ (`SysML-v2-Release` tag `2026-05`), and every known deviation.
14
+
15
+ ## Identity, ownership, refs
16
+
17
+ - Every element has a UUID `element_id`, matching the API JSON `@id`.
18
+ - Cross-references are `Ref` objects (UUID wrappers) resolved through the
19
+ model, never direct Python references, so any element serializes alone.
20
+ - Ownership lives in the `Model` container (owner/owned maps), not on
21
+ elements.
22
+ - `Model.assign_stable_ids()` rewrites ids as UUIDv5 hashes of qualified
23
+ names, so generated interchange files diff cleanly under version control.
24
+ Run it before committing generated models.
25
+
26
+ ## Values with units and provenance
27
+
28
+ `AttributeValue` holds a literal plus optional `unit` (text, e.g. `"dBW"`),
29
+ `source`, and `confidence`. Units stay text in the model for round-trip
30
+ fidelity; `sysml2kit.units` (pint) checks them during validation and offers
31
+ conversion helpers.
32
+
33
+ ## Two output formats, one lossless
34
+
35
+ - **JSON interchange** (`sysml2kit.interchange`) is the lossless format and
36
+ what the Systems Modeling API speaks.
37
+ - **Textual notation** (`sysml2kit.text`) is deterministic and parseable, but
38
+ relationship kinds without a standalone textual statement (verify, derive)
39
+ emit as marked dependencies. Round-tripping text preserves structure;
40
+ round-tripping JSON preserves everything.
41
+
42
+ ## Spec churn policy
43
+
44
+ The `@type` vocabulary lives in one module
45
+ (`sysml2kit/interchange/typemap.py`). The spec pin moves at most quarterly,
46
+ in a minor release, noted in the changelog.
@@ -0,0 +1,24 @@
1
+ # sysml2kit
2
+
3
+ API-first Python tooling for building, querying, validating, and automating
4
+ SysML v2 models.
5
+
6
+ ```bash
7
+ pip install sysml2kit # build, write, query, validate, diff
8
+ pip install "sysml2kit[parse]" # + read .sysml files (sysmlpy backend)
9
+ ```
10
+
11
+ `sysml2kit` is the requirements/architecture/traceability layer for
12
+ engineering automation stacks: build a system model in Python, emit standard
13
+ SysML v2 textual notation and Systems Modeling API JSON, answer traceability
14
+ questions (which requirements are unsatisfied? unverified? allocated where?),
15
+ validate, and diff.
16
+
17
+ Reference spec release: OMG `SysML-v2-Release` tag `2026-05`. The element
18
+ subset and known deviations are documented in
19
+ [concepts](concepts.md) and the repo's `SPEC.md`.
20
+
21
+ Start with the [quickstart](quickstart.md), then the
22
+ [traceability](traceability.md) page — the queries there are the point of the
23
+ package. For antenna/RF domain content, see
24
+ [the RF library](rf-library.md).
@@ -0,0 +1,31 @@
1
+ # Interchange
2
+
3
+ ## JSON (lossless)
4
+
5
+ `sysml2kit.interchange` reads and writes the Systems Modeling API
6
+ serialization: a flat list of records like
7
+
8
+ ```json
9
+ {"@id": "…", "@type": "PartUsage", "declaredName": "battery",
10
+ "owningRelatedElement": {"@id": "…"}, "definition": {"@id": "…"}}
11
+ ```
12
+
13
+ - `model_to_json(model)` / `write_json(model, path)` — deterministic output:
14
+ elements sorted by qualified name, keys sorted per record, so committed
15
+ files diff cleanly. Pair with `model.assign_stable_ids()` for generated
16
+ models.
17
+ - `model_from_json(records_or_path)` — unknown `@type` records become
18
+ `OpaqueElement` and re-export byte-identically.
19
+
20
+ `json -> model -> json` is a fixpoint; the property is tested with hypothesis.
21
+
22
+ ## Textual notation (readable, parseable)
23
+
24
+ `sysml2kit.text.write_model(model)` emits deterministic `.sysml` text:
25
+ ownership order, four-space indent, values as `= 52.0 [dBW]`, requirement
26
+ statements as `doc` bodies, `satisfy X by Y;` / `allocate X to Y;`
27
+ statements. Verify and derive have no standalone textual statement in the
28
+ grammar, so they emit as `dependency from A to B; // verify` — the JSON keeps
29
+ the precise kind.
30
+
31
+ Reading text back goes through a [parser backend](backends.md).
@@ -0,0 +1,34 @@
1
+ # MCP server
2
+
3
+ `pip install "sysml2kit[mcp]"` and run:
4
+
5
+ ```bash
6
+ sysml2kit mcp serve # stdio (default)
7
+ sysml2kit mcp serve --transport http # streamable HTTP
8
+ ```
9
+
10
+ Client config:
11
+
12
+ ```json
13
+ {"mcpServers": {"sysml2kit": {"command": "sysml2kit", "args": ["mcp", "serve"]}}}
14
+ ```
15
+
16
+ Every tool takes model file paths (`.json` interchange always works;
17
+ `.sysml` needs the `parse` extra), returns a JSON dict with a `status` key,
18
+ and reports failures as `{"error": ..., "status": "failed"}` instead of
19
+ raising. Artifacts are returned as file paths, not payloads.
20
+
21
+ | Tool | What it does |
22
+ |---|---|
23
+ | `model_show(path, traceability)` | Element tree, kind counts, optional trace matrix |
24
+ | `model_validate(path)` | S2K rule issues with severity counts |
25
+ | `model_diff(path_a, path_b, by_name)` | Element-level differences (capped list) |
26
+ | `model_export(path, out, to, stable_ids)` | Convert to interchange JSON or `.sysml` |
27
+ | `model_diagram(path, out, kind)` | Write a mermaid `.mmd` (trace or tree view) |
28
+ | `requirements_trace(path)` | Matrix plus unsatisfied/unverified lists |
29
+ | `requirements_extract(path)` | `RequirementSpec` list (the adapter payload) |
30
+ | `library_load(name, out)` | Write a packaged rf-library model as JSON |
31
+
32
+ A typical agent loop: write a `.sysml` file, `model_validate` it, fix issues,
33
+ `requirements_trace` to check coverage, `model_export --stable-ids` to commit
34
+ the interchange form, `model_diagram` to explain the result.
@@ -0,0 +1,47 @@
1
+ # Quickstart
2
+
3
+ Build a model, run the traceability queries, and emit both output formats.
4
+
5
+ ```python
6
+ from sysml2kit import Model, builder
7
+ from sysml2kit.query import trace_matrix, unverified_requirements
8
+ from sysml2kit.text import write_model
9
+ from sysml2kit.interchange import write_json
10
+ from sysml2kit.validation import validate
11
+
12
+ model = Model()
13
+ pkg = builder.pkg(model, "Vehicle")
14
+ battery = builder.part(model, "battery", owner=pkg)
15
+ range_req = builder.req(
16
+ model,
17
+ "REQ-001",
18
+ "Range",
19
+ owner=pkg,
20
+ text="The vehicle shall travel at least 400 km on one charge.",
21
+ )
22
+ builder.satisfy(model, source=battery, target=range_req)
23
+
24
+ print(unverified_requirements(model)) # [REQ-001] - nothing verifies it yet
25
+ print(trace_matrix(model).render()) # requirement-by-part grid
26
+ for issue in validate(model):
27
+ print(issue.rule_id, issue.severity, issue.message)
28
+
29
+ print(write_model(model)) # SysML v2 textual notation
30
+ write_json(model, "vehicle.json") # Systems Modeling API interchange
31
+ ```
32
+
33
+ The same operations from the command line:
34
+
35
+ ```bash
36
+ sysml2kit show vehicle.json --traceability
37
+ sysml2kit validate vehicle.json
38
+ sysml2kit export vehicle.json --to sysml
39
+ ```
40
+
41
+ Reading `.sysml` text back requires the parse extra:
42
+
43
+ ```python
44
+ from sysml2kit.backends import get_backend
45
+
46
+ model = get_backend("sysmlpy").parse(open("vehicle.sysml").read())
47
+ ```
@@ -0,0 +1,31 @@
1
+ # API reference
2
+
3
+ ## Model and elements
4
+
5
+ ::: sysml2kit.model.container.Model
6
+
7
+ ::: sysml2kit.model.base
8
+
9
+ ## Builder
10
+
11
+ ::: sysml2kit.model.builder
12
+
13
+ ## Queries
14
+
15
+ ::: sysml2kit.query
16
+
17
+ ## Validation
18
+
19
+ ::: sysml2kit.validation
20
+
21
+ ## Diff
22
+
23
+ ::: sysml2kit.diff
24
+
25
+ ## Interop
26
+
27
+ ::: sysml2kit.interop.requirements
28
+
29
+ ## Units
30
+
31
+ ::: sysml2kit.units
@@ -0,0 +1,33 @@
1
+ # The RF library
2
+
3
+ sysml2kit stays domain-general. Antenna/RF vocabulary lives in
4
+ [sysml2kit-rf-library](https://github.com/jman4162/sysml2kit-rf-library):
5
+
6
+ ```bash
7
+ pip install sysml2kit-rf-library
8
+ ```
9
+
10
+ ```python
11
+ from sysml2kit_rf_library import load_model
12
+ from sysml2kit.interop import extract_requirements
13
+ from sysml2kit.query import trace_matrix
14
+
15
+ model = load_model("satcom-terminal-t3001")
16
+ print(trace_matrix(model).render())
17
+ for spec in extract_requirements(model):
18
+ print(spec.id, spec.metric_key, spec.op, spec.value, spec.units)
19
+ ```
20
+
21
+ It ships four library packages (RFVocabulary quantity kinds with units,
22
+ RFParts part/port definitions, RFRequirements requirement definitions using
23
+ the metricKey convention, RFAnalyses analysis case definitions) plus
24
+ **SatcomTerminal28GHz** — a worked example mirroring the aedl `t3-001`
25
+ benchmark: a 28 GHz LEO uplink phased-array terminal with eight
26
+ machine-checkable requirements (worst-case link margin, sidelobe level,
27
+ independent link crosscheck, clear-sky and gain agreement, prime-power and
28
+ unit-cost ceilings, grating-lobe margin), each satisfied by a part and
29
+ verified by an analysis.
30
+
31
+ The library demonstrates the intended division of labor: domain vocabulary
32
+ as SysML v2 model content, generic mechanics in the kit, physics engines
33
+ downstream.
@@ -0,0 +1,47 @@
1
+ # Traceability
2
+
3
+ The queries in `sysml2kit.query` answer the questions a requirements-driven
4
+ workflow actually asks:
5
+
6
+ | Question | Call |
7
+ |---|---|
8
+ | What satisfies this requirement? | `satisfied_by(model, req)` |
9
+ | What verifies it? | `verified_by(model, req)` |
10
+ | What does it derive from? | `derived_from(model, req)` |
11
+ | Which requirements have no satisfier? | `unsatisfied_requirements(model)` |
12
+ | Which have no verifier? | `unverified_requirements(model)` |
13
+ | What is allocated where? | `allocation_table(model)` |
14
+ | The whole grid at once? | `trace_matrix(model).render()` |
15
+
16
+ The four relationship kinds are first-class elements
17
+ (`SatisfyRelationship`, `VerifyRelationship`, `DeriveRelationship`,
18
+ `AllocateRelationship`) created through the builder:
19
+
20
+ ```python
21
+ builder.satisfy(model, source=battery, target=mass_req)
22
+ builder.verify(model, source=range_analysis, target=range_req)
23
+ builder.derive(model, source=mass_req, target=range_req)
24
+ builder.allocate(model, source=range_req, target=battery)
25
+ ```
26
+
27
+ ## Handing requirements to an engine: the metricKey convention
28
+
29
+ A requirement usage that owns attributes `metricKey` (string), `threshold`
30
+ (number with unit), `op` (`>=`, `<=`, `==`, `>`, `<`), and optionally
31
+ `severity` (`must`/`should`/`nice`) is machine-checkable.
32
+ `sysml2kit.interop.extract_requirements` turns each into a `RequirementSpec`
33
+ carrying the threshold in both operator form (`op` + `value`) and bound form
34
+ (`minimum`/`maximum`), plus the satisfy/verify trace as qualified names:
35
+
36
+ ```python
37
+ from sysml2kit.interop import extract_requirements
38
+
39
+ for spec in extract_requirements(model):
40
+ print(spec.id, spec.metric_key, spec.op, spec.value, spec.satisfied_by)
41
+ ```
42
+
43
+ Both forms are always populated (`>= 40` also sets `minimum=40`), so an
44
+ operator-style requirements engine (phased-array-systems) and a bound-style
45
+ one (aedl) each need only a small adapter, which lives in those packages.
46
+ The metric key names the entry in the engine's metrics dict; the model never
47
+ computes anything itself.
@@ -31,3 +31,13 @@ plugins:
31
31
 
32
32
  nav:
33
33
  - Home: index.md
34
+ - Quickstart: quickstart.md
35
+ - Concepts: concepts.md
36
+ - Traceability: traceability.md
37
+ - Interchange: interchange.md
38
+ - Command line: cli.md
39
+ - MCP server: mcp.md
40
+ - API client: api-client.md
41
+ - Parser backends: backends.md
42
+ - RF library: rf-library.md
43
+ - Reference: reference.md
@@ -50,6 +50,8 @@ dependencies = [
50
50
  # after checking the release notes.
51
51
  parse = ["sysmlpy>=0.36.2,<0.37"]
52
52
  graph = ["networkx>=3.2"]
53
+ # mcp 2.0.0 removed mcp.server.fastmcp; stay on 1.x until the surface is ported.
54
+ mcp = ["mcp>=1.26,<2"]
53
55
 
54
56
  [project.scripts]
55
57
  sysml2kit = "sysml2kit.cli:app"
@@ -70,11 +72,13 @@ test = [
70
72
  ]
71
73
  lint = ["mypy>=1.15", "ruff>=0.16"]
72
74
  parse-test = ["sysmlpy>=0.36.2,<0.37"]
75
+ mcp-test = ["mcp>=1.26,<2"]
73
76
  docs = ["mkdocs-material>=9.5", "mkdocstrings[python]>=0.27"]
74
77
  dev = [
75
78
  { include-group = "test" },
76
79
  { include-group = "lint" },
77
80
  { include-group = "parse-test" },
81
+ { include-group = "mcp-test" },
78
82
  { include-group = "docs" },
79
83
  ]
80
84
 
@@ -137,9 +141,16 @@ files = ["src/sysml2kit"]
137
141
  plugins = ["pydantic.mypy"]
138
142
 
139
143
  [[tool.mypy.overrides]]
140
- module = ["sysmlpy.*", "pint.*", "networkx.*"]
144
+ # sysml2kit_rf_library is an optional runtime peer, not a dependency.
145
+ module = ["sysmlpy.*", "pint.*", "networkx.*", "sysml2kit_rf_library", "sysml2kit_rf_library.*"]
141
146
  ignore_missing_imports = true
142
147
 
148
+ [[tool.mypy.overrides]]
149
+ # The MCP server class is typed loosely (SDK 1.x/2.x compatibility), so its
150
+ # tool decorator is Any; the tools themselves stay fully annotated.
151
+ module = "sysml2kit.mcp.*"
152
+ disallow_untyped_decorators = false
153
+
143
154
  [[tool.mypy.overrides]]
144
155
  module = "tests.*"
145
156
  disallow_untyped_defs = false
@@ -150,7 +161,12 @@ minversion = "8.0"
150
161
  testpaths = ["tests", "src/sysml2kit"]
151
162
  addopts = ["-ra", "--strict-markers", "--strict-config", "--doctest-modules"]
152
163
  xfail_strict = true
153
- filterwarnings = ["error"]
164
+ filterwarnings = [
165
+ "error",
166
+ # The mcp SDK's FastMCP settings model trips this pydantic-settings warning
167
+ # internally; not ours to fix.
168
+ "ignore::pydantic_settings.exceptions.IncompleteFieldDefinitionWarning",
169
+ ]
154
170
  markers = [
155
171
  "parse: requires the sysmlpy parse extra",
156
172
  "api: requires a live Systems Modeling API server",
@@ -1,14 +1,16 @@
1
1
  """API-first Python tooling for building, querying, validating, and automating SysML v2 models.
2
2
 
3
- The 0.0.x releases are a published skeleton; the object model, writer, and
4
- queries land in 0.1.0. See https://github.com/jman4162/sysml2kit.
3
+ See https://github.com/jman4162/sysml2kit and SPEC.md for the element subset
4
+ (the "pragmatic profile") and the pinned spec release.
5
5
  """
6
6
 
7
7
  from importlib.metadata import PackageNotFoundError, version
8
8
 
9
+ from sysml2kit.model import Model, builder
10
+
9
11
  try:
10
12
  __version__ = version("sysml2kit")
11
13
  except PackageNotFoundError: # running from a source tree without an install
12
14
  __version__ = "0.0.0.dev0"
13
15
 
14
- __all__ = ["__version__"]
16
+ __all__ = ["Model", "__version__", "builder"]