Repository navigation
feat(dotnet): add typed OpenSysML .NET client, C# generation, and metamodel reader - #1
Merged
Merged
Conversation
Add client/dotnet/, the build for a C# client of sysml-grpc that is consumed from a checkout by ProjectReference and never published to NuGet. The library targets net10.0 only and has no public API yet: this sets up the build, test, coverage and CI gates, and the service operations come later. Build: - The repository-root global.json pins SDK 10.0.402 (latestPatch, no prereleases) and opts dotnet test into Microsoft.Testing.Platform; the VSTest form is unsupported with xunit.v3 4.x. - Directory.Build.props sets the policy every project shares: Version 0.10.1, net10.0, nullable, deterministic, warnings as errors, Recommended analyzers, code style enforced in build, XML docs with CS1591 as an error, lock files, and ContinuousIntegrationBuild plus locked restore when CI=true. Nothing is packable. - Directory.Packages.props pins every package centrally with transitive pinning (Google.Protobuf 3.36.2, Grpc.Net.Client 2.84.0, Logging Abstractions 10.0.13, PublicApiAnalyzers 5.6.0, xunit.v3 4.0.2, coverlet.MTP 10.1.0); each project commits its packages.lock.json. - nuget.config restores from nuget.org alone; .editorconfig holds the formatting and style rules dotnet format and the build enforce. Library (src/OpenMBEE.OpenSysML): - Empty PublicAPI.Shipped.txt/Unshipped.txt: any public symbol must be declared there and documented, or the build fails. - release-digests.json, a synced copy of client/release-digests.json, embedded as a resource; scripts/sync-release-digests.py now writes and checks it. - Internal ReleaseDigests: a validating, exact-match reader of the embedded pin table (lowercase 64-hex digests, no duplicate or empty names). Tests (test/OpenMBEE.OpenSysML.Tests, 43 tests): - Every test declares Category=Unit or Integration, and a test fails on one without, since a Category filter otherwise drops it silently. - ServiceGate decides run/skip/fail from OPENSYSML_GRPC_BINARY and OPENSYSML_REQUIRE_SERVICE as a pure decision the unit tests assert (xUnit v3 records Assert.Skip even when caught); with the service required, a missing binary fails rather than skips. - An integration test runs the configured sysml-grpc -version. - Build-environment tests: net10 runtime and target, the root global.json pin and runner, no nested global.json, the assembly version equals the declared Version, nothing packable. - The embedded digest table equals client/release-digests.json byte for byte and agrees with it entry for entry; malformed tables are rejected. Sample: samples/Vehicle references the library as a project and prints its version and target framework from assembly metadata. Gates: - client/dotnet/scripts/dotnet-gates.py: `preflight` requires the exact pinned SDK from the repository root and a .NET 10 runtime; `coverage` requires a nonempty Cobertura report measuring only client/dotnet/src and no generated file. Self-tests in dotnet-gates-test.py. - make dotnet-preflight, dotnet-build (locked restore, -warnaserror), dotnet-test (format check, tests with a minimum test count, JUnit, the sample's output, gate self-tests, digest sync check) and dotnet-coverage (coverlet.MTP with the generated Wire files excluded by path). Version lockstep: check_version.py --dotnet checks the Version in client/dotnet/Directory.Build.props against the core version and the release tag, with pytest cases including the real-tree lockstep test. CI: - ci-changed-areas.sh: a dotnet area for client/dotnet/ and global.json, part of the service fan-out; a Directory.Build.props change also runs the Python version tests. New routing cases cover these. - PR workflow: a Linux dotnet-test job installs the pinned SDK alone in its own directory, then runs preflight, dotnet-test with the service required, and dotnet-coverage, and uploads the reports; it is in the build condition and the Build and test aggregate. - CircleCI: a dotnet-executor on mcr.microsoft.com/dotnet/sdk:10.0.402-noble pinned by digest, and a dotnet-test job in build-test only (nothing is released). - sonar-project.properties excludes client/dotnet/**: no job here builds it, and its own job gates it with the analyzers, API tracking, format and coverage. Also: .gitignore covers client/dotnet bin/, obj/ and TestResults/; client/dotnet/README.md documents status, requirements, ProjectReference use, commands and build policy; a changelog fragment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…entory Generate C# message classes and a gRPC client stub from api/proto/sysml.proto and commit them, add an internal method registry read from their descriptor, and add an inventory of everything the .NET client must cover. Tests now fail on a schema change until the inventory accounts for it. Apart from the generated protocol code, the library still has no public API. Generation: - api/proto/buf.gen.csharp.yaml, separate from the Go template: managed mode overrides only csharp_namespace (OpenMBEE.OpenSysML.Wire) and disables every other file option, so the Go stubs stay byte-identical. It uses remote plugins protocolbuffers/csharp v36.2 and grpc/csharp v1.84.0 (no_server), matching the Google.Protobuf 3.36.2 and Grpc.Net.Client 2.84.0 pins. - make proto-csharp writes src/OpenMBEE.OpenSysML/Wire/Sysml.cs and SysmlGrpc.cs, is part of make proto, and is byte-identical on repeat. .gitattributes marks the files linguist-generated. - The library references Google.Protobuf and Grpc.Net.Client. Transitive pinning lifts Logging.Abstractions to 10.0.13, and the three lock files are updated. - An exact-path .editorconfig section marks the two files as generated code and turns off RS0016/RS0041 for them alone. Nothing else is suppressed, and the build has 0 warnings. Method registry (internal, Internal/RpcMethods.cs): - Built from SysMLService.Descriptor, not a hand-maintained table: every method in schema order, with its qualified name, request and response CLR types, and parsers. - Find accepts a bare name (ParseFile) or a qualified one (sysml.SysMLService/ParseFile), matched exactly. - TryResolve<TRequest, TResponse> returns the typed method, or a reason naming both pairings when the name is unknown or the types are not the method's own, so a caller can refuse the call before anything is sent. - Each method gets one shared typed instance carrying a unary gRPC Method with buffer-writer marshallers, because a channel caches what it learns per method object. Parity inventory (test/testdata/parity.json): - One row per RPC, in schema order: request and response messages, the public methods that will call it, the area that delivers it, its status (deferred), every conformance scenario ID, the request fields that carry Values, and the capability gates the service applies, each with its field and predicate, in the order the service checks them. - Every Value arm with its send gate (ungated, response-only or a capability) and receive capability, and every EditOperation arm with its gates; each section records its gate order. - The response fields the service fills only under a capability. - Every field of every message an RPC reaches, classified as deferred. Typed, raw-only and unsupported classifications must name a test; raw-only and unsupported ones also need a reason. Tests (50 new, 93 in total): - ParityChecker compares the inventory with the descriptor, the scenario files and the service's declared capability names as sets, not counts. It reports missing, stale or duplicated rows, fields, arms and scenarios; a changed request or response type; misordered rows; gates that name an undeclared capability or field; and a scenario capability that no gate, arm or governed field of its RPC accounts for. - Altered schemas (an added or renamed RPC, field, message or arm, a changed request type, a new Value request field) and altered inventories must each produce the expected problem. - Registry tests: descriptor order, agreement with the generated stub's methods, accepted and rejected spellings, mismatch messages, a shared instance under concurrency, and marshaller round trips that keep unknown fields. - Public API boundary tests: no Wire symbol in the handwritten API baseline, every public Wire type is generated code, the Wire directory holds only the two generated files, handwritten code neither declares nor imports the Wire namespace (its Array would shadow System.Array), and the Makefile and .editorconfig exemptions name exactly those files. Gates: - dotnet-gates.py coverage now resolves Cobertura filenames against the report's <sources>. coverlet writes them relative to a shared directory once the library has more than one source file, and the gate had rejected them. Four new self-tests cover this. - DOTNET_MIN_TESTS is now 93. - The PR dotnet-test job installs buf (pinned by checksum), runs make proto-csharp and fails when the committed Wire files differ. Also: client/dotnet/README.md documents the protocol code and the parity inventory; a changelog fragment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add the client's first public API: open a connection to a service that is already running, ask it what it is and what it supports, call any of its methods through a raw call checked against the schema, and report every failure as a typed exception. The client does not yet start a service of its own, speak the Connect protocol, load models or offer typed service operations. Public API (PublicAPI.Unshipped.txt, written by the RS0016 code fix): - Connection.OpenAsync(ConnectionOptions? options = null, CancellationToken) connects to the service ConnectionOptions.Address names, or else $OPENSYSML_SERVICE. A null options argument means ConnectionOptions.Default. It is one overload because RS0026 refuses two with optional parameters. OpenAsync asks GetServerInfo once and keeps the answer as ServerInfo (Version, Capabilities, Answered). It then checks an exact Version (StaleServiceException) and RequireCapabilities (CapabilityException), and closes the channel again if the open fails. A service that answers GetServerInfo Unimplemented claims no capability and is logged as a warning. With no service named, OpenAsync fails with ServiceStartException, since starting a private one is not available yet. AutoStart stays true by default. - Connection.CallAsync<TRequest, TResponse>(method, request) calls a method named bare or qualified with the generated Wire messages. A name or message pairing the schema does not have fails with InvalidRequestException before anything is sent. It checks no capability and interprets no result. - ConnectionOptions holds Address, Protocol, AutoStart, RequestTimeout (60 s), Headers, RequireCapabilities, Version, Logger (NullLogger), HttpMessageHandler and MaxRequestSize/MaxResponseSize (512 MiB each). Collections are copied when set, and every value is checked at open. An address is host:port, a bracketed IPv6 address with a port, or an http/https URL with nothing after its port. Headers may not override what the protocol controls (content type and encoding, timeouts, host, grpc-* and connect-*), may not be binary -bin metadata, and are never logged. - Capabilities has a constant for each of the 73 capabilities the service declares, generated from its Go declarations and their docs, plus Has, Require, None and set equality. StatusCode numbers its values as gRPC does. Protocol has a single value, Grpc. - Exceptions: OpenSysMLException is the base of ServiceException (StatusCode, ServiceMessage, Method), TransportException (StatusCode, Method, cause), CapabilityException, InvalidRequestException and ServiceStartException, which StaleServiceException extends. Caller cancellation is an OperationCanceledException carrying the caller's token, and use after disposal is an ObjectDisposedException. Transport (internal): - ITransport is the seam each protocol implements. GrpcTransport owns one GrpcChannel: identity encoding only, so MaxResponseSize bounds the inflated message rather than a compressed frame; no service config or retries; ThrowOperationCanceledOnCancellation off. It uses its own SocketsHttpHandler (5-minute pooled connection lifetime), or borrows the caller's handler through a non-disposing HttpMessageInvoker. - A status is the service's only when the response itself carried that grpc-status and the library attached no local cause. A delegating handler records each call's response to check this. Every status the library makes up is a TransportException. DeadlineExceeded is always a TransportException. When the caller's token and the deadline both fired, the caller's cancellation is reported. A completed answer is returned whatever happens to the token afterwards. - Where Grpc.Net.Client disagrees with gRPC's own status definitions, the client follows gRPC, deciding on exception types and never on message text. A response that does not parse is Internal, and a connection that could not be established (name lookup, refusal, TLS, proxy tunnel) is Unavailable. An HTTP/2 protocol error is reported as an endpoint that may speak only HTTP/1.1. - DisposeAsync refuses new calls, cancels the calls in flight, waits for them and closes the channel. It is idempotent, safe to call concurrently, and never throws: a failure to close is logged as a warning. Tests (170 new, 263 in total): - Unit tests over a fake handler that frames real gRPC responses: every non-OK status, an unknown status, twelve malformed response shapes, request and response size limits at and one byte over the limit, the headers, deadline and identity encoding sent on the wire, cancellation before and during a call, deadlines and both orders of the deadline and cancellation race, disposal, borrowed versus owned handlers, and the option, header and address rules. They also check that the capability constants equal the service's declared set. - Unit tests over real loopback sockets: a refused port, an unresolvable host, an https URL to an endpoint that does not speak TLS, and an endpoint that speaks only HTTP/1.1. - Integration tests against a sysml-grpc the tests start and reach by address, run for both its connect and grpc transports: server info against -version and the server-info conformance scenario, an address taken from the environment, a raw call and a live NotFound, concurrent calls, Version and RequireCapabilities, a response limit one byte under the measured uncompressed answer, and an external service that is still running after its connections close. Sample and gates: - The Vehicle sample prints the service's ServerInfo when $OPENSYSML_SERVICE is set. - dotnet-gates.py sample runs the sample twice: with no service, and against a sysml-grpc it starts on a kernel-chosen port and stops. Under $OPENSYSML_REQUIRE_SERVICE, a missing binary is a failure. Nine new self-tests cover it. make dotnet-test runs it in place of the inline identity check. - The library references Microsoft.Extensions.Logging.Abstractions directly, and the three lock files are updated. DOTNET_MIN_TESTS is now 263. - parity.json marks GetServerInfo implemented, with its tests, and types ServerInfoResponse.version and .capabilities. - The client README documents connecting, raw calls and failures, and a changelog fragment is added. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ConnectionOptions.Protocol = Protocol.Connect makes each call one HTTP/1.1 POST with a protobuf body or, with MessageEncoding.Json, a JSON one; JSON over gRPC is refused before anything is sent, and a connection never falls back to another protocol. Connect calls send Connect-Timeout-Ms and enforce the deadline themselves, accept gzip answers bounded after inflation with their gzip trailer checked, and follow no redirect. A refusal is the service's only when its body is a Connect error; otherwise its status is inferred from the HTTP status and it quotes an excerpt of the answer. The transport-independent tests run over gRPC, Connect with protobuf and Connect with JSON, against fakes and against a live service. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Value is a closed hierarchy with one sealed nested class per arm of the schema's Value, named by ValueKind, beside an exact Rational, Quantity with its UnitTerm, and the ValueList<T> and ValueDictionary<TValue> collections. Values compare by content, a set in any order, an enumeration literal by its declaration and a metaobject by its element; numbers never pass through a double, and Reals keep NaN, the infinities and negative zero. No type outside the library can derive from Value. Answers are read only in the schema's canonical form: a malformed value is a TransportException naming where it is, and one of an unknown kind an UnsupportedValueException rather than a null. A value is refused before sending when no service reads it as an argument, and needs each capability the service gates by the service's own predicates and order; a Rational a double holds is sent as that double to a service without rational_values. The tests hold every arm to the schema, the parity inventory and the service's source, compile an outside consumer to prove derivation is refused, and send every kind through a live service over gRPC, Connect with protobuf and Connect with JSON. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Parse files, inline SysML/KerML, and multiple source documents, and create handles for models cached by hash - Expose immutable symbols, diagnostics, type facts, and instance graphs - Add symbol lookup, lint selection, scoped and subject-based expression evaluation, and instantiation with instance-reference resolution - Match Python difflib suggestions for Unicode, tie ordering, and popular-character handling on long names - Validate capabilities before sending requests and distinguish model, symbol, file, service, and malformed-response failures - Add one-shot owning models and make concurrent disposal callers wait for the same connection close - Update API and parity inventories, documentation, changelog fragments, and the Vehicle sample and its output gate - Expand unit and live service coverage and raise the test floor to 902 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Allow connections and one-shot model loads to start a locally installed sysml-grpc when no service address is configured. Preserve explicit and environment-selected service connections without starting or stopping an external service. Binary discovery and verification: - Resolve BinaryPath, OPENSYSML_GRPC_BINARY, the shared local cache, then PATH. - Treat explicitly selected binaries as authoritative; never silently fall back when they are missing or unusable. - Follow symbolic links before subsequent parent-directory components, including inside link targets, before hashing or executing the binary. - Reject paths that traverse missing directories or regular files. - Hash resolved binaries for service identity and optionally enforce ExpectedBinarySha256 before startup. - Add actionable binary-not-found, checksum-mismatch, and unsupported-platform exceptions; report that release downloads are not yet implemented. Private-service lifecycle: - Start children on kernel-selected ports with address reporting and exit-with-parent enabled. - Validate the first stdout line as a loopback service address and continuously drain both output streams into bounded diagnostic tails. - Share compatible children within the client assembly's load context using binary path, digest, startup/shutdown timeouts, and expected version. - Support isolated services with connection-local ownership. - Coordinate concurrent opens through startup reservations and leases. - Cancel startup only after its last waiter leaves, and release reservations after cancellation, startup failure, or failed handshake checks. - Close stdin on final release, wait for orderly shutdown, then terminate the owned process tree when the shutdown grace period expires. - Invalidate existing leases after unexpected child death without restarting the child or moving connections to a replacement service. - Add StopSharedServicesAsync, aggregate failures from both new and already running shutdowns, and expose a copied, read-only failure collection. - Mark pending starts as stopping during unload so children that finish starting after cancellation are also stopped. Connection, sample, and test integration: - Keep transport settings and call cancellation local to each connection while compatible connections share a child process. - Release private-service leases after connection disposal and failed opens, including capability and version validation failures. - Add a standalone fake-service executable, in-memory lifecycle fixtures, concurrency regressions, and real-service integration coverage. - Exercise the Vehicle sample with no service, a named service, and a binary started privately. - Update public API tracking, lifecycle documentation, changelog, and the minimum test-count gate from 902 to 1016. Validation on macOS arm64 with .NET SDK 10.0.402: - Full .NET suite: 1016 passed, zero skipped. - Warnings-as-errors build and formatting verification passed. - Coverage gate passed with 2642 of 2708 handwritten lines covered. - All sample modes and 34 Python gate tests passed. - Release-digest, changelog, documentation-label, and whitespace checks passed. - Go build, vet, and formatting checks passed. - Full Go tests failed in unchanged packages, including a ten-minute timeout in the code-generation suite; no Go source was modified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add process-boundary, collectible-load-context, and concurrency tests for the .NET client's private-service ownership and shutdown guarantees. Harden the test harness so failures and deadlocks produce bounded, actionable failures without leaving owned child processes behind. Add orphan-process verification: - Introduce a standalone probe that opens a private sysml-grpc service through the client and starts unrelated sibling processes. - Verify that killing the probe alone ends its service while siblings remain alive, across gRPC, Connect protobuf, and Connect JSON. - Repeat synchronized service/sibling startup races with eight siblings. - Add a negative control using dup or DuplicateHandle to deliberately leak the service's stdin write handle into a sibling. - Require the detector to observe service survival while that handle is retained and service exit after the holder is terminated. Add collectible assembly-load-context verification: - Load three independent copies of the client and its dependencies into collectible contexts without loading the client in the default context. - Verify that two connections within each copy share one service while separate copies start distinct services. - Exercise explicit disposal, unloading with live connections, and unloading while service startup is still pending. - Check per-copy shutdown isolation, weak-reference collection, orderly startup cancellation, and process exit without retained foreground threads or static handler roots. Harden lifecycle concurrency tests and resource ownership: - Run 200 synchronized registry-state-machine rounds covering shared and isolated holders, cancellation, concurrent stop-all calls, and death. - Exercise concurrent close, duplicate close, stop-all, and opens racing the last close against stand-in children and the real service. - Await background death cleanup before asserting terminal registry state, with a deterministic held-stop regression test. - Bound race rounds to 30 seconds, propagate cancellation through barrier entry and operations, and report unfinished parties on timeout. - Observe late task faults and retain barriers until participating tasks have completed. - Add an asynchronous ownership scope for connection attempts and resolved child PIDs, including partial acquisition and assertion failures. - Bound orderly cleanup to 10 seconds, then kill and await only owned processes while preserving timeout failures. - Clean up children that resolve after scope disposal has begun. Wire the probes and platform gates: - Add both probe projects, dependency lock files, and build-only test project references to the solution. - Expose the minimal internal registry/stdin access needed by the probes and reuse the existing child-runtime discovery helper. - Add full-tier native macOS and Windows CI jobs with native Go service builds, pinned SDK preflight, locked restore, warning-free builds, required-service tests, minimum-count enforcement, and report uploads. - Include native matrix results in the aggregate build-and-test gate. - Add 42 test cases and raise the suite minimum from 1016 to 1058. Document registry scope, unload behavior, probe controls, race deadlines, failure cleanup, and platform-validation limits. Add the client delivery plan and changelog fragments, recording implementation completion without claiming unobserved Windows or hosted CI validation. Validation: - macOS arm64, .NET SDK 10.0.402 and runtime 10.0.13. - make dotnet-test: 1058/1058 passed, zero skipped, including the sample and 34 gate self-tests. - Focused lifecycle selection: 42/42 passed in three consecutive runs. - make dotnet-coverage: 1058/1058 passed on rerun; 2643/2709 handwritten lines covered. The initial run encountered an unexplained local HTTP 401 response during a Connect-protobuf handshake. - Build, formatting, changelog, release-digest, documentation-label, and whitespace checks passed. - go build, go vet, and gofmt checks passed. - Full Go tests ran but failed in eight untouched packages; failure details are recorded in the delivery plan. - Native Windows and hosted CI execution remain outstanding. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix the Linux and Windows failures exposed by the first hosted .NET client CI runs. Handle HTTP/2 version-negotiation failures alongside protocol errors: - Recognize HttpRequestError.VersionNegotiationError and report Internal regardless of the status assigned by the gRPC library. - Preserve the original cause and provide the HTTP/1.1 endpoint diagnosis and Protocol.Connect guidance. - Accept either typed runtime failure in the real-socket test while retaining its status and diagnostic assertions. - Add regression cases for negotiation failures reported by gRPC as Internal or Unavailable. Make Python gate output compatible with legacy Windows consoles: - Replace Unicode checkmarks with ASCII OK markers in preflight, sample, and coverage success messages. - Add strict cp1252 output tests for every success path. - Avoid requiring a CI-only UTF-8 environment workaround. Raise the minimum .NET test count from 1058 to 1060 and update the client documentation, delivery-plan evidence, and changelog. Validation: - Required-service make dotnet-test: 1060/1060 passed, zero skipped. - Python gate self-tests: 37/37 passed. - Transport/network tests: 43/43 passed on macOS and Linux arm64. - make dotnet-coverage with PYTHONIOENCODING=cp1252: 1060/1060 passed, with 2650/2715 handwritten lines covered. - Formatting, warning-free build, documentation, whitespace, and Go build/vet/gofmt checks passed. Hosted CI confirmation remains pending. The original native macOS job passed; Windows stopped in preflight before any .NET tests executed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement the .NET conformance suite engine independently of transport adapters and command-line orchestration. Keep the core internal to a separate, non-packable assembly without changing the wire schema, public client API baseline, or RPC implementation-status inventory. Add strict scenario loading and request construction: - Read scenario files in UTF-8 filename order, then declaration order. - Reject unknown or repeated members, incorrect value kinds, missing identifiers or RPCs, ambiguous model forms, and duplicate scenario IDs. - Resolve whole-string model-hash, fixture-text, and fixture-base64 placeholders and decode requests through generated RPC descriptors. - Refuse fixtures outside the fixture directory and report invalid or unreadable paths as scenario errors without aborting subsequent cases. - Normalize decimal and exponent spellings of 64-bit integers exactly, including quoted forms, signed/unsigned boundaries, and negative zero. - Bound exponent expansion before allocation and reject fractional or out-of-range integer requests without floating-point rounding. Implement normalization and comparison: - Normalize set fields with protobuf presence and default semantics. - Preserve integer, unsigned, and Real kinds; render enums by schema name and bytes as protobuf-JSON base64. - Replace versions, model hashes, and absolute paths with placeholders. - Label runtime instance IDs deterministically by first appearance across field-number order, sorted map keys, and list order. - Support named-field comparisons, exact list lengths and order, defaults, wildcard paths, contains checks, non-empty/absent checks, and counts. - Compare integers by exact digits for every whole-number spelling and finite Reals within the documented relative tolerance of 1e-9. - Reject numeric overflow, nonzero underflow, and infinity-versus-finite matches; retain explicit textual comparisons for special Real values. - Follow the documented numeric contract rather than reproducing the Go reference comparator's rounding and non-finite tolerance defects. Add scenario execution and reporting: - Define the adapter seam for public-API-backed calls, model parsing, answered/refused outcomes, and unexpressible-request skips. - Apply capability gating and without-capability expectations. - Cache successful model parses once per run, distinguishing a file parse from a one-document source-list parse. - Enforce independent parse/call deadlines even when an adapter ignores cancellation, observe late faults, and never cache late parse hashes. - Propagate caller cancellation with its original token instead of converting it into a skip, success, or recorded scenario error. - Record deterministic logs, verbose observations, durations, and totals. - Write reference-shaped JSON and JUnit reports. - Replace XML-invalid characters in JUnit text and attributes while preserving valid characters, surrogate pairs, and original JSON strings. Wire the core into the solution and existing gates: - Add conformance library/test projects and dependency lock files. - Reuse the strict scenario loader in parity-inventory tests, removing their duplicate reader. - Raise the aggregate minimum test count from 1060 to 1333. - Document the core, remaining adapter/CLI boundary, validation evidence, and intentional reference differences. - Add the client delivery plan and feature/fix changelog fragments. Add 273 conformance tests, including 85 review regression cases, scripted adapters, fixture suites, and JSON/JUnit/log goldens. Confirm 53 regression cases fail before the production fixes. Validation: - Required-service make dotnet-test: 1333/1333 passed on macOS arm64, zero skipped, including the sample and 37 Python gate self-tests. - Conformance tests: 273/273 passed on Linux arm64 and in three repeated macOS runs with golden updates disabled. - make dotnet-coverage: 1333/1333 passed with two accepted reports. Combined source coverage: core 1061/1074, client library 2649/2715. - Locked restore, warning-free Release build, formatting, changelog, documentation-label, and whitespace checks passed. - Go build, vet, and gofmt checks passed. Transport adapters, CLI orchestration, and live conformance differential execution remain follow-up work. Hosted Windows/CI confirmation of this implementation is pending. The unchanged Go suite was not rerun; its previously recorded local failures remain outside this change's scope. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run the language-independent conformance suite through the .NET client's public typed APIs over gRPC, Connect protobuf, and Connect JSON. Judge what callers receive rather than bypassing the facade with raw RPC calls. Adapters and response rendering: - Make the conformance project executable while retaining its shared scenario-loading and comparison code for both test projects. - Add typed adapters for GetServerInfo, ParseFile, ParseSources, GetSymbol, GetDiagnostics, Evaluate, and Instantiate. - Register adapters by RPC with explicit request types and expressible fields; report unsupported requests with stable skip reasons. - Render symbols, diagnostics, instances, feature values, and every public value variant back into schema-shaped responses. - Preserve in-band errors and diagnostics, service refusal statuses and messages, transport statuses, and client-side capability refusals. - Reuse the scenario reader and protobuf field-presence helpers instead of duplicating their rules. Skip accounting and service lifecycle: - Add a strictly parsed expected-skips list covering 24 deferred RPCs and the source-less parse request the public API cannot express. - Fail on unexpected skips, changed skip reasons, stale entries, and scenarios that run despite being listed as expected skips. - Validate that withheld capabilities exactly match the requested set. - Require fallback expectations to execute, with explicit notes when every fallback belongs to a reviewed, uncovered RPC. - Run default and withheld-capability configurations with one service per configuration and one connection per protocol. - Move the service-process harness into the conformance project, size its model cache for the suite, and bound retained service output. CLI and negative controls: - Support private binaries, existing services, scenario filtering, protocol and transport selection, capability withholding, JSON and JUnit reports, verbosity, and explicit skip-policy overrides. - Reject unknown, repeated, incomplete, and contradictory arguments. - Prevent another option from being consumed as a missing flag value; support -flag=value for literal dash-prefixed values. - Report JSON and JUnit filesystem failures with their format, destination, and underlying cause, returning exit 1 rather than terminating with an unhandled exception. - Add perturb-reals, truncate-lists, and rewrite-strings mutations that corrupt response copies without changing map keys or original data. Reference differential and CI: - Add conformance-dotnet and conformance-dotnet-check Make targets, a configurable service binary, and shared withheld-capability defaults. - Compare report structure, totals, scenario outcomes, statuses, missing capabilities, fallback selection, and normalized responses against the reference runner, excluding only reviewed skips. - Validate JUnit suite and testcase ordering and every testcase's disposition against JSON, rejecting missing, incorrect, duplicate, or conflicting outcome elements even when declared totals agree. - Run the conformance targets in GitHub Actions and CircleCI, provision Go for the reference runner where needed, and retain report artifacts on failure. Client correctness and regression coverage: - Preserve the service's original missing-symbol message in Model.SymbolAsync through a new SymbolNotFoundException constructor, and update the public API baseline and related tests. - Test adapter requests and complete response rendering on all three protocols, capability refusals, unexpressible requests, inventory consistency, skip accounting, process exits, and report failures. - Add an IL-based guard against raw Connection.CallAsync or generated stub calls from the conformance runner. - Verify that each response mutation fails applicable scenarios on every protocol. - Raise the enforced .NET test minimum from 1333 to 1498 and expand Python gate self-tests from 37 to 56. - Update client documentation, the implementation plan, and changelog fragments. Leave the wire schema and RPC parity classifications unchanged. Validation: - Required-service make dotnet-test: passed 1498 tests, zero skips, including locked restore, zero-warning build, formatting, the sample, and all 56 Python gate tests. - make conformance-dotnet-check: passed; 303 results agree with the reference runner and 858 reviewed skips are excluded. - Process-level negative controls: missing values exit 2; invalid report destinations exit 1; removing all 858 JUnit skip markers fails the gate. - go build ./..., go vet ./..., gofmt -l ., changelog checks, documentation-label checks, and git diff --check: passed. - go test ./... is not green locally due to previously recorded macOS/environment-sensitive Go test failures; no Go source changed. - Hosted CI and Windows confirmation remain pending. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend the .NET client facade with action and state-machine execution, bounded schedule exploration, and behavior checking through the service. Execution and exploration: - Add ExecuteActionAsync and ExecuteStateAsync for single scheduled runs, plus ExploreActionAsync and ExploreStateAsync for bounded exploration. - Introduce RunOptions for scheduling, performers, state traces, simulated advance, random seeds, draw policies, and clock steps. - Add immutable ActionRun, StateRun, Exploration, Outcome, and ProbabilityRange results with structurally comparable collections. - Preserve outputs, performer attributes, final context, diagnostics, simulation time, order dependence, traces, and dropped-record counts. - Retain exploration budgets, completion status, failed linearizations, unenumerated constructs, witness choices, and probability bounds. - Enforce capability requirements before sending and reject incompatible run/explore schedules or trace requests. Behavior checking and failures: - Add CheckActionAsync and CheckStateAsync with CheckOptions for properties, divergence tracking, free inputs, assumptions, witnesses, search bounds, timeouts, engine selection, and performers. - Preserve search statistics, violations, divergent values, final outcomes, replay witnesses, symbolic claims, and engine standing. - Introduce shared Standing and Bound records for analysis results. - Keep failing properties as ordinary results rather than exceptions. - Add ExecutionException with failure diagnostics, final time, and trace data, and CheckException with the service's partial check result. - Reject check responses containing neither a verdict nor an error with TransportException and Internal status. - Preserve in-band errors and their partial results even when the service omits the verdict. Wire mapping and conformance: - Add immutable document-value variants and object, verdict, state, and event records for trace decoding and subsequent document-query support. - Reuse canonical quantity, big-integer, and rational decoding rules. - Reject unknown document-value arms and malformed element shapes without silently converting them into anonymous elements. - Validate that execution responses match the requested run or exploration shape. - Add typed conformance adapters for ExecuteAction, ExecuteState, and CheckBehavior, with public-constructor request-value conversion. - Render every exposed execution, exploration, check, and document field back into protocol messages for conformance comparisons. - Classify locally refused requests as unexpressible with their reason. - Update the public API baseline, parity inventory, and reviewed skips to reflect the three implemented RPCs. Tests and documentation: - Add 119 tests covering request construction, capability gates, immutable results, response decoding, malformed answers, failure payloads, rendering fidelity, and live-service behavior. - Exercise gRPC, Connect protobuf, and Connect JSON. - Add regression coverage for missing verdicts and preservation of verdict-less in-band failures through both public check methods. - Raise the minimum expected test count from 1498 to 1617. - Document the new APIs, error contracts, implementation roadmap, validation evidence, and downstream integration boundaries. - Add an unreleased changelog entry. Validation: - OPENSYSML_GRPC_BINARY="$PWD/bin/sysml-grpc" OPENSYSML_REQUIRE_SERVICE=1 make dotnet-test: passed, 1617 tests, zero failures or skips; zero-warning Release build, formatting, sample execution, and 56 gate self-tests passed. - go build ./...: passed. - go vet ./...: passed. - gofmt -l .: passed with no output. - python3 scripts/changelog.py check: passed. - python3 scripts/check-doc-ids.py: passed. - git diff --check: passed. - go test ./...: failed in eight untouched Go packages, including macOS temporary-path alias assertions and a ten-minute code-generation test timeout. No Go source or protocol schema changed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose the service's verification and analysis operations through the .NET client's asynchronous public API without introducing local solving or execution logic. Add verification and analysis operations: - Verify constraints and requirements with configurable questions, subjects, positional and named arguments, and engine selection. - Verify satisfaction assertions, provide a satisfaction convenience method, and validate instances with per-assertion and summary verdicts. - Evaluate calculations with positional arguments and preserve ordered output features. - Run and explore analysis cases with subject bindings, arguments, schedules, engine selection, and external-tool dry-run previews. - Run stepped or seeded sampled parameter sweeps, retaining each row's inputs, outputs, verdicts, evaluations, timing, and failure details. - List registered engines with readiness, provenance, supported questions, bounds, and optional probing. Preserve verification evidence and failure semantics: - Add immutable result records for verdicts, witness assignments, verification-case verdicts, calculations, analyses, sweeps, engine listings, and tool previews. - Carry engine standing through analysis explorations and use an empty standing for behavior explorations that report no engine. - Keep false and undecided verdicts as ordinary results rather than exceptions, and keep failed sweep runs as rows in the returned table. - Add verification exceptions with structured failure reasons and analysis exceptions retaining partial outputs, evaluations, verdicts, diagnostics, instances, and engine standing. - Preserve unknown numeric failure reasons and reject malformed or contradictory response shapes. - Validate option shapes, capability requirements, nested argument sendability, and run-versus-exploration selection before sending. Extend conformance coverage and regression gates: - Add public-API adapters and response rendering for all eight RPCs. - Add positional request-value decoding and lossless rendering of the new results, witnesses, partial runs, and exploration standing. - Update the parity inventory and reviewed skips, including three calculation requests the typed value API cannot express. - Exclude only sweep-row wall times from differential comparison while continuing to compare every other response field. - Add mapping, failure, capability-ordering, rendering, adapter, and live-service tests across all three client wires. - Raise the minimum expected .NET test count from 1617 to 1777. Update the public API inventory, client usage and conformance documentation, changelog fragment, and .NET implementation plan with delivery status, validation evidence, limitations, and follow-up work. Validation: - Release solution build with warnings as errors: passed with no warnings. - Focused .NET regression and live conformance tests: 335 passed, no skips. - Conformance gate self-tests: 59 passed. - Reference differential: 693 results agree; 468 reviewed skips excluded. - git diff --check: passed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose repeated execution, reflective model checking, and analysis-run recording through the typed .NET client without changing the service schema or Go implementation. Add repeated action and Monte Carlo execution: - Introduce RunActionRunsAsync and RunAnalysisRunsAsync with separate options for action inputs, performers, and observables versus analysis subjects and arguments. - Support run counts, optional seeds, draw policies, clock steps, and engine selection. - Return immutable run tables, observable distributions, percentiles, histogram bins, counted values, printed summaries, and case conclusions. - Keep failed runs as rows and preserve tables in RunsException when the service cannot complete the request. Add reflective self-checking: - Expose SelfCheckAsync with optional rule packages. - Return typed findings, application counts, aggregate status, diagnostics, and a convenience Holds property. - Keep constraint violations in the result and raise ModelException only when the check cannot start. Add analysis-run recording: - Support single runs, sweeps, and seeded Monte Carlo samples. - Return generated declarations, edited documents, skipped-run reasons, diagnostics, and exactly one run, sweep, or sample result. - Expose the recorded model as a new handle borrowing the connection, leaving the original model unchanged and writing nothing to disk. - Preserve partial execution results and refused declarations in RecordException, including whether execution itself reported the failure. Preserve service capability-gate ordering and reject malformed responses with explicit transport errors. Share sweep-row conversion and propagate nested field paths into conversion diagnostics. Extend public-API conformance adapters and rendering for RunRuns, SelfCheck, and RecordRun. Normalize row timings and generated recording timestamps during reference comparison, while checking recorded-model hashes for presence and distinction from the original model. Update the public API baseline, parity inventory, reviewed skips, client documentation, changelog fragment, and client implementation plan. Add 94 tests covering all three transports and raise the minimum test count from 1,777 to 1,871. Validation on macOS arm64 with .NET SDK 10.0.402: - Required-service make dotnet-test: 1,871 passed, zero failures or skips. - Release build: zero warnings or errors. - Formatting, sample execution, and all 63 gate self-tests passed. - make conformance-dotnet-check: 723 results agree with the reference runner; 438 reviewed skips excluded. - git diff --check passed. Linux and Windows validation was not run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose model conversion and SysML v1 migration through the typed .NET client, including complete result rendering and safe local file writes. Conversion API: - Add Connection.ConvertAsync for file, inline-content, and parsed-model sources, with SysML/KerML notation, Turtle, and API JSON output. - Add Model.ConvertAsync, ToNotationAsync, ToTurtleAsync, ToApiJsonAsync, and SaveAsync, including output-format inference from file extensions. - Support source formats, tolerated syntax errors, qualified or UUID ids, document selection, compact JSON, derived-property controls, and check diagnostics. - Preserve output formats, diagnostics, experimental status, and notices in Conversion results and ConversionException failures. - Check capability requirements before sending requests and distinguish missing files from evicted models. Migration API: - Add Connection.MigrateAsync for XMI, UML, and MDZIP file or byte sources. - Support full migration reports, stored results, layout paths or content, image base URLs, and strict migration. - Add immutable migration reports, entries, and byte-backed asset values, including total counts and verdict filtering. - Preserve in-band failures and format metadata in MigrationException. - Require valid, fully-qualified migration file paths, normalize them once, and use the same path for the service request and source protection. - Remove the client-working-directory assumption and the silent fallback that could discard source protection. Safe persistence: - Share a writer between conversion saving and migration publication. - Validate every destination before writing, stage files beside their targets, flush to disk, and publish assets before the model. - Refuse overwrites by default and never replace the migration source. - Reject traversal, absolute or drive-qualified asset names, symbolic links, duplicate destinations, and file/directory collisions. - Reject Windows-invalid characters, reserved device names, and trailing dots or spaces consistently across platforms. - Include Unicode normalization equivalence in macOS path comparisons while preserving Unicode distinctions on Linux and Windows. - Remove owned temporary files and newly created files/directories after failure or cancellation; document non-atomic multi-file overwrite behavior and the remaining concurrent directory-swap limitation. Conformance and documentation: - Add typed Convert and Migrate adapters and lossless response rendering. - Mark invalid, relative, or noncanonical migration paths unexpressible without silently rewriting conformance requests. - Update capability fixtures, parity coverage, reviewed skips, public API declarations, client documentation, changelog fragments, and the .NET implementation plan. - Add 136 test cases overall and raise the minimum-test gate from 1871 to 2007, including 17 path-safety regression cases. Validation on macOS arm64: - Required-service make dotnet-test: 2007 passed, zero skipped; formatting, warning-as-error build, sample, and 63 gate self-tests passed. - Focused conversion, safe-write, adapter, and live-service tests: 339 passed, zero skipped. - make conformance-dotnet-check: 795 results agree with the reference; 366 reviewed skips excluded. - Go build, vet, formatting, changelog, documentation-identifier, and whitespace checks passed. - Full Go tests failed in eight unchanged Go packages, including a ten-minute compiled-calculation timeout; runtime, corpus, and hygiene tests passed. - No Go source or protocol schema changes. - Linux and Windows execution remain unverified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose model queries, document queries, document rendering, and view rendering through immutable public APIs, with capability validation, lossless wire mappings, and conformance coverage across gRPC, Connect protobuf, and Connect JSON. Query API - Add Model.QueryAsync(Query) and Model.QueryOslcAsync(string), returning QueryResult elements with identity, metamodel type, and selected properties. - Add immutable Query records with scope, selection, optional filtering, Query.All, and content-based equality. - Add comparison constraints supporting equality, greater-than, less-than, and inversion, plus nested AND/OR composites. - Require valid operators and operand counts at construction, and keep structured and OSLC query forms mutually exclusive by API design. - Reuse the public query API for symbol lookup and suggestions, removing the superseded private wire-level query helper. Document queries and rendering - Add Model.RunDocumentQueryAsync with ordered, repeatable parameter bindings and typed columns, rows, and multivalued cells. - Add element and object reference factories and binding serialization for elements, held objects, strings, numbers, booleans, and quantities. - Allow answered element and object values to be rebound without losing their reported metadata. - Reject anonymous element bindings, invalid object references, infinity, and answer-only verdict, state, and event rows. - Enforce document-query, big-integer, and rational capability gates in order, converting exact-double rationals losslessly when rational support is unavailable. - Add Model.RenderDocumentAsync for Markdown and HTML, preserving rendered content and optional output file names. - Introduce QueryException as a ModelException for document/query FailedPrecondition refusals, preserving status, message, method, and underlying protocol exceptions. - Distinguish missing models from missing declarations or held objects, and reject document responses containing content in the wrong form. View rendering - Add Model.RenderViewAsync with typed port selection, optional notation, and positive depth overrides for declared views and pseudo-views. - Preserve every rendered node, port, edge, route, table row, canvas, geometry, style, note, notice, source span, and shown notation field. - Keep omitted geometry, styles, canvas, and origins null rather than fabricating zero-valued records. - Add root, child, and node navigation over parents-first node lists. - Reject duplicate node identifiers and parents not drawn before children. Conformance and parity tracking - Add typed adapters and response rendering for Query, RunDocumentQuery, RenderDocument, and RenderView. - Update reviewed skip accounting and verify the OSLC capability fallback executes when that capability is withheld. - Mark 110 request/response fields as typed and leave four RPCs uncovered. - Compact parity field classifications into shared groups while retaining all 175 messages and 995 fields. - Reject duplicate fields, repeated classifications, empty groups, duplicate members/messages, and unknown group members. Tests and documentation - Add wire-level, live-service, malformed-response, capability-gating, immutability, and complete-field round-trip tests across all three wires. - Exercise queries over every conformance fixture and render more than 100 views from the renderer's fixtures. - Add inventory-compaction validation and negative tests. - Raise the minimum expected .NET test count from 2007 to 2137. - Update the public API baseline, client documentation, changelog fragment, and implementation plan with delivered behavior and validation evidence. Validation on macOS arm64 with .NET SDK 10.0.402: - Full .NET solution tests with the service required: 2137 passed, 0 failed, 0 skipped. - Release solution build with warnings as errors: 0 warnings, 0 errors. - Formatting verification and git diff --check: passed. - Inventory comparison: only the intended 110 deferred-to-typed field classifications changed; no unrelated classification drift. No protobuf schema or Go implementation changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose the service's ApplyEdits through an immutable Edit hierarchy and a call-order Editor. A batch is checked against the capabilities it needs before anything is sent, multi-document models are edited as one, and the edited notation saves safely. Coverage spans gRPC, Connect protobuf, and Connect JSON. Editing API - Add Model.Edit(), which returns an Editor that collects edits in call order and applies them as one batch with ApplyAsync. Add Model.ApplyEditsAsync(IEnumerable<Edit>, EditOptions?). - Add Edit as an abstract record with an internal abstract arm, so no type outside the library can derive from it. It has one sealed nested record for each of the service's 17 kinds: SetValue, Rename, AddMember, Delete, Move, AddConnection, AddSatisfy, AddRequirementConstraint, AddTransition, AddImport, AddDocumentation, AddVerify, AddMetadata, AddSequence, AddMetadataPrefix, AddComment and AddNote. Each record carries every schema option. - Support recursive Body/ElseBody in AddSequence, with factories for each statement form and Editor.Body for nested bodies. A body's first statement is written without `then`. - Bound nesting at AddSequence.MaxDepth (128), the service's limit. An item nested deeper cannot be built. - Require non-null required strings, including through `with`. Leave unwritten optional parts null, and refuse optional parts set to empty text before sending. - Make the editor single-use after a successful apply. Refuse edits added while applying or after success, and allow a retry after a failure. - Add EditOptions (InDocument, AcceptDocuments = true) and MetadataFeatureValue. Results and failures - Add EditResult with Content, Documents, Diagnostics, HasSeveralDocuments and an AppliedEdit list (operation index, offset, length, old/new text and document). - Leave Content null for a model of several documents. EditResult.SaveAsync refuses to save one; save each document with EditedDocument.SaveAsync instead. - Add EditedDocument.SaveAsync, which writes through the safe writer. It never leaves a partial file and replaces an existing one only when SaveOptions.Overwrite is set. - Add EditException as a ModelException carrying the EditFailure kind (an unknown number is kept), diagnostics, Referrers and ReferringElements. - Map a missing model to ModelNotFoundException. Reject malformed answers (a refusal beside notation, an applied edit outside the batch, an unknown or duplicate document, content for a multi-document model) as TransportException with Internal. Capability gating - Check request shape first, then apply_edits, then the capabilities the whole batch needs in the service's order, then edit_documents when a document is named. - Read the gate order and each per-capability predicate from the service's source in tests rather than restating them. Conformance and parity tracking - Add EditingArea adapters and lossless EditResult rendering for results and refusals. - Remove ApplyEdits from the uncovered RPCs, leaving three. - Mark the ApplyEdits row and all 17 edit arms as implemented, and mark 129 more fields as typed. Tests and documentation - Add ModelEditingTests, EditInventoryTests, ConformanceEditingRenderingTests, ConformanceAdapterTests rows and live ServiceEditingTests across all three wires. They cover every arm and option, nested bodies, multi-document edits, refusal kinds, capability withholding, malformed answers and save round trips. - Raise the minimum expected .NET test count from 2137 to 2345. - Update the public API baseline, the client README and the changelog fragment. Validation on macOS arm64 with .NET SDK 10.0.402: - Full .NET solution tests with the service required: 2345 passed, 0 failed, 0 skipped. - Release build with warnings as errors: 0 warnings, 0 errors. - Conformance: 175/175 per protocol; conformance-dotnet-check reports 1050 results agree. - go build, go vet, gofmt -l, hygiene tests, docs-check and git diff --check: passed. No protobuf schema or Go implementation changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Complete typed coverage of all 31 service RPCs with graph export, ordered data import, and comparison of migrated SysML v1 results. Add graph export: - Expose Model.ExportGraphsAsync with immutable Graphs results. - Preserve canonical graph JSON exactly as returned, including escaping and the trailing newline, alongside its version and resolved subject. - Distinguish a missing model from an unknown subject and reject malformed responses without content, a positive version, or a subject. Add data import: - Expose Model.ImportDataAsync with DataImport and ImportOptions. - Support ordered CSV, TSV, JSON, and JSON Lines inputs, explicit formats, JSON mappings, dry runs, and multi-document acceptance. - Return per-file counts and assignments, diagnostics, edited notation, changed documents, and a new model handle borrowing the connection. - Preserve the original model and represent dry runs without a fabricated model or notation; surface refused imports as ModelException. - Validate response ordering, counts, document names, and model/content consistency; share document-name validation with editing. - Save single-document results through the existing atomic SafeWriter. Add result comparison: - Expose Model.CompareResultsAsync with configuration selection, runs, seed, draw policy, clock step, observable mappings, and engine options. - Decode configuration statuses, sweep rows, instances, distributions, statistic differences, declared case statistics, and engine standing. - Preserve absent distributions and seeds, explicit zero clock steps, non-finite numbers, unknown failure reasons, and partial failure data. - Add CompareException, status helpers, instance resolution, and rendering of the service's comparison lines. - Validate option shapes and enforce capability gates before sending. Integrate conformance coverage and regression tests: - Add graph/data adapters and lossless response rendering. - Mark the final three RPCs and their fields implemented in the parity inventory and remove the remaining uncovered-RPC skips. - Exclude comparison-row elapsed time from cross-run comparisons while continuing to compare the rest of each row. - Add fake-wire, rendering, malformed-response, and live-service tests across gRPC, Connect/protobuf, and Connect/JSON. - Raise the expected test floor from 2345 to 2525. - Update client documentation, add a changelog fragment, and record the .NET client implementation plan and validation evidence. Validation: - Release solution build: passed with 0 warnings and 0 errors. - Focused graph/data, editing, adapter, public API, and parity tests: 681 passed, 0 failed, 0 skipped, with service integration required. - Gate-script self-tests: 64 passed. - Formatting verification and git diff --check: passed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Coordinate private-service startup with the shared binary cache used by the Python, Java and Rust clients. Prefer verified, digest-named snapshots so subsequent cache replacements do not change the executable selected for a starting or running service. Implement cross-client cache locking: - Match the existing executable, metadata, lock and snapshot naming. - Serialize threads with an assembly-local semaphore and isolated load contexts with a persistent .NET guard file. - Use POSIX lockf on libc-opened O_CLOEXEC descriptors, avoiding .NET's implicit file locking and process-scoped descriptor lifetime hazards. - Use whole-file LockFileEx on Windows, with an unshared guard handle. - Add cancellable acquisition with exponential backoff, wait diagnostics, a two-minute timeout and idempotent reverse-order release. Add verified, crash-consistent cache transactions: - Stage executable bytes in the cache filesystem, flush them to disk, verify SHA-256 and atomically publish them before their metadata. - Check cancellation immediately before executable publication; once published, complete the metadata write despite caller cancellation. - Read bounded, Python-compatible metadata with duplicate-member and legacy-record handling, explicit failure reasons and digest validation. - Treat malformed UTF-8 and unpaired Unicode surrogates as unusable metadata rather than allowing decoding exceptions to escape. - Remove interrupted .NET staging files without deleting other clients' temporary files, and warn when an installed release cannot be recorded. Resolve cached binaries through stable snapshots: - Reuse snapshots only when their digest matches and they are not symbolic links; rebuild symbolic and dangling links with a warning. - Dereference symlinked executables before linking their underlying file. - Prefer native hard links, fall back to copying with a warning, and explicitly warn when the mutable cache executable must be used. - Recheck binary discovery if the cached executable disappears while waiting for its lock. - Preserve explicit binary and PATH resolution behavior and enforce caller-supplied digest requirements before execution. Expand tests and repository integration: - Add process and collectible-load-context probes for exclusion, cancellation, crash recovery, descriptor inheritance and transaction interruption at every publication stage. - Add Python, Java and dependency-pinned Rust lock holders to verify interoperability in both directions. - Stop and await foreign holders when acquisition fails, and establish disposal ownership before assertions in waiting-holder tests. - Add malformed-Unicode, symlink-stability and publication-cancellation regressions, bringing the enforced test count from 2525 to 2655. - Add an interoperability category and require promised toolchains rather than silently skipping tests when they are unavailable. - Provision Java 21 and Rust 1.83 in the Linux and native .NET CI jobs. - Wire the cache probe into the solution and test build, document native interop requirements, and update the client guide, changelog and implementation roadmap. Keep the public API and protobuf schema unchanged. Release downloading and signature verification remain outside this change. Validation on macOS arm64: - make dotnet-test: passed; 2655 tests, zero failures or skips, warning-free build, formatting, sample and supporting gates passed. - make dotnet-coverage: passed; 2655 tests, zero failures or skips. - go build ./... and go vet ./...: passed. - gofmt -l .: empty. - Changelog, documentation-ID and git diff --check validations: passed. - go test ./...: failed in nine Go packages; failures include macOS path-sensitive assertions, a code-generation timeout and Node's missing libllhttp.9.3.dylib dependency. No Go source files were changed. - Native Windows execution was not verified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Provision sysml-grpc automatically when no binary is named, integrating release selection, bounded downloads, and pins-only verification with the existing cross-client cache transaction and private-service lifecycle. Release selection and public API: - Add ConnectionOptions.DownloadVersion and GithubRepo, together with constants for release-version, repository, and unpinned-download environment settings. - Select the version from options, then OPENSYSML_GRPC_VERSION, then the release matching the client assembly's informational version. - Select the repository from options, then OPENSYSML_GITHUB_REPO, then Open-MBEE/OpenSysML. - Resolve "latest" through the GitHub releases API once per open. - Map the five published Linux, macOS, and Windows platform assets and report unsupported platforms explicitly. - Validate repository and tag path segments before issuing requests. - Reject incompatible private-service options and warn when environment- selected services or binaries make download options unused. - Add UnpinnedReleaseException and preserve download failures as the inner exception of BinaryNotFoundException. - Update the unshipped public API baseline. Trust and cache resolution: - Resolve named option and environment binaries first, then the shared cache and release download, with PATH reserved for implicit fallback. - Require a committed repository/tag/asset pin unless the existing same-origin opt-out explicitly permits an unpinned repository. - Require served checksums and downloaded bytes to agree with the pin, and enforce ExpectedBinarySha256 before fetching binary contents. - Refuse unpinned releases without fetching them; do not claim signature verification, which this client does not implement. - Check recorded cached releases against available committed pins before reuse, including digest shortcuts, offline fallback, unresolved latest, and unlocked-cache reads. - Fail on integrity contradictions without falling back to cache or PATH. - Restrict digest-only cache shortcuts to implicit version selection so explicit release tags and latest remain constraints. - Preserve hand-installed executables without metadata for implicit opens, while distinguishing absent metadata from invalid or torn records. - Warn before replacing stale releases and publish replacements only after verification through the existing cache transaction. - Retain permitted offline cache fallback, repository-aware latest fallback, and digest-named executable snapshots. HTTP transfer handling: - Fetch production releases over HTTPS and validate every redirect, refusing HTTPS-to-HTTP downgrades. - Permit plain HTTP only for injected loopback test sources. - Bound binary responses at 512 MiB and metadata at 8 MiB after decompression, rejecting excessive declared lengths before body reads. - Apply the 15-second idle timeout to individual plaintext transport reads so partial headers and compressed-body progress refresh the deadline. - Preserve correct timeout behavior across redirects, pooled connections, and subsequent requests after a timeout. - Keep local file writes outside the network idle deadline. - Preserve caller cancellation tokens and remove staged files on failure. - Normalize lazy JSON Unicode-decoding failures into ServiceStartException so malformed latest responses retain the intended cache fallback. - Send a versioned User-Agent and do not retry downloads. Tests, CI, and documentation: - Add a loopback release server covering malformed responses, redirects, stalls, trickled headers and bodies, compression, false lengths, persistent connections, and cleanup. - Cover release precedence, platform mapping, pins, same-origin opt-outs, explicit constraints, offline policy, concurrent opens, and cache reuse. - Exercise signed-release fixtures as unpinned refusals rather than successful signature verification. - Verify real-service download, startup, and cache reuse over all three supported wire configurations. - Add 30 follow-up regression cases and raise the minimum suite count from 2,655 to 2,866. - Route signed-release fixture changes to the .NET CI area. - Update the README, API documentation, changelog fragments, and client delivery plan with trust policy, behavior, limitations, and evidence. - Leave the RPC schema, parity inventory, and shared cache format unchanged. Validation: - make dotnet-test: passed on macOS arm64 with real-service and cross-client checks required; 2,866 passed, zero failures or skips. - Locked restore, warning-free Release build, formatting verification, runnable sample, 64 gate self-tests, and digest synchronization passed. - Focused affected tests: 212 passed with the real service required. - Documentation links, internal-label checks, changelog validation, and git diff --check passed. - go build ./... and go vet ./... passed; gofmt -l . produced no output. - go test ./... failed in unchanged Go packages, including macOS path and toolchain expectations, generated-C compilation, a compiled-step-budget timeout, and WASM tests blocked by the installed Node runtime's missing libllhttp dependency. - Native Windows/Linux and live GitHub downloads were not repeated for the follow-up fixes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The .NET client is published to no registry: its release is the checkout of the core v<version> tag. Make that release reproducible and gated. Release workflow - build-python-package now runs `check_version.py --dotnet`, so a tag whose version client/dotnet/Directory.Build.props does not declare fails before anything is built, as the Node, Java and Rust manifests already do. - A new step runs `dotnet-gates.py promote-api --check`, failing the release while the client's PublicAPI.Unshipped.txt still lists entries. A release rehearsal therefore catches a missed promotion before the tag. - tests/hygiene holds build-python-package to both checks, ahead of the distribution build. Public API promotion - `dotnet-gates.py promote-api` folds each library's PublicAPI.Unshipped.txt into PublicAPI.Shipped.txt at the release boundary: entries are added, `*REMOVED*` lines delete what they name, the shipped file is written in ordinal order, and the unshipped file keeps only its `#nullable enable` header. Every project is validated before any file is written; an entry listed twice or already shipped, a removal of something never shipped, a header mismatch and a misplaced directive are refused. With --check it changes nothing. Eight self-tests cover it, including promotion of the real baseline. The API is deliberately not promoted here: that happens on the release branch. Private service start on Linux - Linux refuses to exec a file any process holds open for writing (ETXTBSY). A child another thread is forking holds a copy of every open descriptor until it execs, so a binary this process has just written, such as a download into the shared cache, can be busy for a moment. The launcher now retries that refusal alone five times over about 1.5 s, logged at Debug, honoring cancellation, before failing with the kernel's reason. This was also the cause of an intermittent "Text file busy" failure of the FakeService lifecycle tests on Linux. - Three Linux-only tests prove that a binary held open for writing starts once it is closed, that one kept open fails after every retry with errno 26 and nothing run, and that cancelling during the wait starts nothing. The shared ListLogger gains a per-entry callback so the tests act deterministically on the Nth retry. Elsewhere they skip by name, since macOS does not refuse such a file. Coverage and documentation - The client README gains a Coverage table: every RPC, its status and the public methods that call it, in schema order. A test holds it to the parity inventory, so a schema change or renamed method cannot leave it stale. The README also describes the release model and the busy-binary retry. - docs/project/releasing.md gains "Releasing the .NET client as the tag's checkout" (version lockstep, API promotion, why the tag's own checkout does not pin its own release until the pin pull request lands, and what CI already proves). The release-branch checklist now covers Directory.Build.props and the API promotion. - CI routing tests now prove that a draft touching only the .NET client, its gates, the SDK pin or the signing fixtures runs the .NET job in the quick tier, and that a scenario change waits for the full tier. - DOTNET_MIN_TESTS rises to 2870. Validation (macOS arm64, SDK 10.0.402, with JAVA_HOME, OPENSYSML_GRPC_BINARY, OPENSYSML_REQUIRE_SERVICE=1 and OPENSYSML_REQUIRE_INTEROP=1): - make dotnet-test: 2870 tests, 3 Linux-only tests skipped by name, 72 gate self-tests. - make dotnet-coverage: 10180 of 10724 lines covered. - make conformance-dotnet: 188/188 per protocol by default and 187/187 withheld, 6 reviewed unexpressible skips. - make conformance-dotnet-check: 1128 results agree with the reference runner. - make proto-csharp produced no Wire drift. sync-release-digests --check, changelog check, check-doc-ids, check-doc-links, ci-changed-areas-test.sh, make docs-check, the strict MkDocs build, go build, go vet, gofmt and go test ./tests/hygiene/... all passed. - pin_release_checksums.py --from-manifest stamped a fixture release in a scratch checkout and synced every copy, the .NET one included. After the stamp, sync-release-digests --check passed and the scratch build's ReleaseDigestsTests passed (19/19). Validation (Linux arm64, pinned SDK container): the whole suite passes repeatedly (2870 tests, interop cases skipped by name because the image has no Python, JDK or Cargo). The baseline had failed 2 of 8 runs with ETXTBSY. Negative controls, each restored afterwards: - Retry disabled: 3 failures. - One README coverage row changed: 1 failure. - Either release check removed from the CircleCI config: the hygiene test fails, naming that check. - A shipped API entry dropped after promotion: RS0016. - A broken anchor in a new link: check-doc-links fails. - A drifted shared digest table: sync-release-digests --check names every copy that drifted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Owner
Author
|
@copilot resolve the merge conflicts in this pull request |
Document the asynchronous .NET client alongside the other language clients, with a runnable walkthrough and explicit distribution, transport, ownership, and release-trust contracts. Documentation and ecosystem integration: - Add a task-oriented guide and API reference covering connections, models, values, execution, verification, conversion, queries, documents, editing, file writes, capabilities, and exceptions. - Explain checkout-based ProjectReference consumption, the net10.0 target, gRPC and Connect encodings, private-service ownership, binary resolution, shared caching, and pinned-download trust. - State the unsupported surfaces explicitly: NuGet publication, synchronous APIs, Native AOT, trimming, browser hosts, generated model classes, and a standalone metamodel reader. - Add C# installation and evaluation tabs to the cross-client guide. - Update client listings, navigation, downloads, landing pages, architecture documentation, contribution guidance, and roadmap. - Add user-facing and repository-testing skills and a changelog fragment. - Model the .NET client, service channel, and codebase allocation in the architecture self-model, and regenerate the VS Code landing data. Runnable walkthrough and drift protection: - Align the Vehicle sample with the cross-client task: parse the model, report diagnostics, look up the sedan, and evaluate its redefined mass in the subject's context. - Separate assembly-identity checks from the published walkthrough and mark the walkthrough region for exact comparison with the guide. - Update the sample gate to require the sedan's evaluated mass. - Require the guide's complete service-enabled command on its own bash line, including the local service-binary assignment, rather than merely finding a dotnet-run substring. - Add seven command-validation cases covering the valid command, missing/empty/incorrect binary settings, comments, short-circuiting, and help-only invocation. - Confirm all six negative cases fail against the original substring check, and document the sample's identity-only behavior when no service or binary is configured. - Raise the executed-test floor to 2880 and route guide changes through the .NET CI area in both quick and full tiers. No service schema or client-library public API changes. Validation: - Documentation tests: 10 passed, no skips. - Vehicle gate: passed in identity-only, external-service, and private-service modes. - Sample-gate self-tests: 72 passed. - .NET formatting and CI-routing checks: passed. - Documentation checks, new-page link checks, and strict site build: passed. - Self-model and generated landing tests: passed. - go build ./..., go vet ./..., and git diff --check: passed. - gofmt -l .: no output. - Required-service/interop .NET suite: 2853 passed, 24 existing failures, and 3 Linux-only skips out of 2880 tests. - Full Go suite: failed in unrelated command, rendering, analysis/runtime, SMT, code-generation, and WASM tests, including a code-generation timeout. The existing .NET failures involve capability/query drift, constraint and view response handling, scalar-versus-sequence expectations, and embedded release-digest drift. They remain release blockers. Hosted platform CI, conformance comparisons, and coverage were not rerun. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a checkout-based generator that produces typed C# interfaces and classes from SysML model definitions, backed by the .NET client's immutable instance and value APIs. Generator and typed runtime: - Generate one interface per non-enumeration definition, extending every generated base interface in model-declared order. - Inherit the first generated base class and use explicit interface implementations to preserve multiple inheritance and feature identity. - Follow renamed and narrowing redefinitions when implementing inherited properties, deduplicating diamond ancestry. - Map scalar, quantity, enumeration and generated-object features to typed properties, falling back explicitly to Value where no sound mapping exists. - Provide required, nullable and immutable-list accessors, scalar decoders, typed-object factories and usage-to-definition registry aliases. - Resolve instance views to the most specific known generated class and report incompatible types, invalid feature values and missing values through dedicated exceptions. Deterministic generation and correctness: - Accept multiple files and directories, namespace and output options, explicit service selection, and a no-write --check drift gate. - Require the service's type_facts capability before parsing. - Stamp generated output with emission schema version 2 and a SHA-256 hash of sorted logical document names and length-delimited exact source bytes. - Preserve all package and namespace children across input documents through shared service symbol-fact enumeration, without merging document roots, non-namespace declarations or library/model homonyms. - Treat statically unknown upper multiplicity bounds as collections and unknown lower bounds with upper bound one as nullable. - Traverse inherited facts without an arbitrary depth cutoff, selecting the narrowest compatible type and intersecting multiplicity constraints. - Diagnose incompatible inherited types, disjoint ranges, cyclic redefinitions and ambiguous generated names. - Escape contextual and intrinsic C# keywords and normalize identifiers according to compiler equivalence before checking collisions. - Reject Unset values in required properties, including raw Value properties. - Report expected filesystem failures with diagnostics and exit code 2 while retaining atomic output replacement and temporary-file cleanup. Tests, tooling and documentation: - Add synthetic planner, naming, typing, inheritance, source-stamp and CLI tests, plus live generation and feature-read coverage over all three wires. - Compile committed goldens in a consumer project referencing only the client library, with warnings and missing documentation treated as errors. - Add generation and golden regeneration/check targets, manifest-driven gates, CI fixture routing and generated-file attributes. - Raise the test-count floor to 3,093 and document the generator, runtime, limitations and wire-level namespace enumeration behavior. Validation: - 213 focused .NET tests passed with no skips. - Locked restore, solution formatting and zero-warning build passed. - Golden checks, Vehicle sample, documentation checks, CI routing and 77 Python gate self-tests passed. - Targeted symbol-facts and gRPC Go tests passed. - go build ./..., go vet ./... and Go formatting checks passed. - Full .NET gate: 3,066 passed, 24 failed and 3 Linux-only skips; failures match the previously recorded drift outside this implementation. - Full Go suite remains non-green outside the changed packages, including path/tool assumptions, lifecycle timing and solver/runtime expectations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Owner
Author
|
@copilot resolve the merge conflicts in this pull request |
Add OpenMBEE.OpenSysML.Metamodel as a standalone net10.0 assembly generated from the same ontology table as the Python metamodel. Keep it independent of the service client, protobuf, gRPC, logging, and other runtime packages. Generate the complete metamodel type surface: - Emit 175 metaclass interfaces, 167 sealed concrete element classes, seven enums, and metadata for all 415 declared properties. - Preserve semantic ancestry through interface inheritance, supporting is checks and OfType<T>() selection across the hierarchy. - Expose read-only PascalCased properties, nullable single values, and IReadOnlyList<T> collections. - Implement inherited properties explicitly to avoid collisions between element class names and inherited property names. - Support conforming same-name redefinitions, with every ancestor interface reading the most specific declaration. - Record metamodel version, source tag, and source commit. Add the metamodel runtime and metadata registry: - Provide metaclass and enumeration lookup, conformance checks, C3 ancestry, effective properties, JSON-key and C#-name mappings, ranges, multiplicities, defaults, derivation, and association links. - Distinguish omitted properties from supplied null values through MetamodelException and NotSuppliedException without inventing defaults. - Add internal construction and property-supply seams for a future reader. - Make all public metadata collections immutable snapshots, defensively copying initialization arrays and preserving enumeration lookup consistency. Add deterministic generation and reject unsupported input: - Introduce the C# metamodel generator with -out and non-writing -check modes, plus regeneration and drift-check Make targets. - Reject ambiguous inherited declarations, nonconforming redefinitions, invalid identifiers, colliding names, and dangling association links. - Guard framework type names and inherited registry members against generated-name collisions. - Validate property kinds against primitive, enumeration, and metaclass ranges, rejecting unknown kinds explicitly. - Extract shared topological ordering and C3 linearization for the Python and C# generators while preserving Python output byte-for-byte. Integrate build, CI, documentation, and regression coverage: - Add solution projects, locked dependency graphs, and handwritten public API baselines with narrowly scoped generated-code exemptions. - Include generated metamodel code in coverage exclusions and generated file attributes, and strengthen the exemption boundary tests. - Run generation drift checks in CI and route ontology table and hierarchy changes to the .NET checks. - Raise the expected test-count floor to 3121. - Add 28 standalone metamodel tests covering hierarchy, properties, metadata, dependencies, immutable snapshots, and enum round trips. - Compile and exercise a synthetic generated fixture covering diamonds, narrowing redefinitions, and every supported range kind. - Update client documentation, API reference, roadmap, implementation plan, testing guidance, and the unreleased changelog fragment. Keep JSON reading and graph querying explicitly deferred; this change does not add a public graph reader or change the wire schema. Validation: - .NET solution build: passed with zero warnings and errors. - .NET formatting: passed. - Metamodel tests: 28 passed; API boundary tests: seven passed. - Root and tools Go builds and vet checks: passed. - Generator tests, Python/C# generation drift checks, formatting, documentation, changelog, and documentation-count checks: passed. - Full root Go suite: failed in unrelated CLI, rendering, runtime, SMT, code-generation, and WASM suites, including a code-generation timeout. - Full service-dependent .NET suite was not rerun for the final fixes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Integrate the remote feature branch's develop merge while preserving the standalone .NET metamodel implementation. Retain audit and metamodel Make targets, separate the Python and Java CI routing entries, and regenerate C# metamodel metadata against the incoming ontology release. Validated the .NET build and formatting, 28 metamodel tests, seven API boundary tests, CI routing, generation drift, generator tests, and Go build/vet checks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a standalone JSON reader to OpenMBEE.OpenSysML.Metamodel so exported models can be inspected through generated C# metamodel interfaces without the service, main client library, or transport dependencies. Build complete graphs while keeping malformed values and unresolved references local to their properties. Real exports omit library targets and derived properties, and sometimes supply derived references outside their declared ranges; these must not make unrelated elements unreadable. Graph reader and public API - Add ReadJson overloads for file paths, borrowed streams, JsonDocuments, and sequences of JsonElements, with explicit ReadOptions overloads. - Accept flat element objects and arrays, DataVersion envelopes, null payloads, and Commit change arrays. - Create elements before converting values and resolving references, preserving identity across forward, cyclic, and self references. - Expose document-ordered Elements, ID lookup, TryGet, Contains, interface-based All<T> selection, Roots, and reader-option metadata. - Normalize sysml-prefixed and versioned or unversioned SysML IRI types while retaining each element's original JsonType. - Resolve unknown types through normalized Supertypes mappings, falling back to Element, and reject conflicting mappings and used cycles. - Preserve caller ownership of streams and documents; returned graphs and immutable typed collections remain readable after source disposal. Property values and failures - Add GetValue(jsonKey), metadata property lookup, and typed document, value, unresolved-reference, and unknown-key exceptions. - Preserve the distinction between absent properties, explicit nulls, empty collections, malformed values, and unresolved references. - Report absent owned and derived properties as NotSuppliedException rather than inventing defaults or computing missing derived data. - Keep value failures and unresolved @id or @ref targets property-local. - Let CheckRanges=false retain out-of-range references through GetValue while typed reads still fail and all other validation remains active. Extension retention and input validation - Add opt-in KeepExtensions and immutable per-element Extensions copied independently of the source; explain the option when extensions were not retained instead of silently returning an empty dictionary. - Preserve opaque extension string escapes without decoding their values, while supporting caller-parsed comments and trailing commas. - Validate duplicate keys throughout every input, including ignored extensions, envelope metadata, and values skipped during conversion. - Reject invalid UTF-8 and undecodable Unicode property names or element identities with MalformedDocumentException. - Record undecodable Unicode property values and reference targets as property-local MalformedValueException failures. - Preserve ObjectDisposedException for disposed caller-owned documents. Generated runtime and integration - Generate internal sealed implementations for abstract metaclasses and provide factories for every metaclass without exposing abstract implementations as public element types. - Reserve the added runtime members and framework type names against generated-name collisions, and require Element and Namespace metadata. - Regenerate the metamodel and synthetic golden and update metadata, hierarchy, immutability, and public API expectations. - Add a standalone MetamodelReader sample and exact-output sample gate. - Wire the sample into the solution and test target, reference the metamodel from live export tests, and update the dependency lock. - Route shared Python metamodel fixture changes to .NET CI and raise the minimum expected test count from 3121 to 3242. - Update client guides, API reference, roadmap, skills, fixture notes, changelog fragments, and the client implementation plan. Tests and validation - Cover sources, envelopes, types, abstract fallbacks, references, ranges, cardinality, extensions, roots, identity, source disposal, and every metaclass property's value shape. - Add 36 validation regression cases spanning all source overloads and range-checking and extension-retention options. - Pass all 146 standalone metamodel tests and all three live export tests. - Verify the full standard-library export retains 112031 elements and, with extensions enabled, 138697 extension members. - Pass the warning-free Release solution build, formatting, generator drift and hierarchy tests, standalone sample, and 82 gate-script tests. - Pass Go build and vet checks, gofmt, and documentation/changelog checks. - Run the full Go suite; it remains failing outside the reader changes in engine, PDF, codegen, CI hygiene, and landing-snapshot checks. - The full .NET suite was not rerun after the final validation fixes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The committed C# stubs predated the schema's verdict notes, library references, Query.order_by, the four new PrimitiveConstraint operators, the query outcome detail, AsciiDoc documents, view compartments and inherited nodes and ports. The parity inventory read the descriptor compiled into those stubs, so it could not see the schema had moved. Regenerate them with the pinned buf and plugins; the plugins reproduce the previous stubs byte for byte from the schema they were made from, so the diff is the schema's alone. Classify every new field the RPCs reach as deferred in parity.json. CircleCI's .NET job now regenerates the stubs and fails on any difference, as the PR workflow's already did. WireSchemaTests builds the schema with buf ($BUF as the Makefile reads it, else buf on PATH) and names the first message, field, oneof, reserved number, enum value or RPC where it and the committed descriptor part; OPENSYSML_REQUIRE_BUF turns its skip into a failure, and both Linux CI jobs set it. InteropGate's PATH lookup moves to ToolSearch so the two gates share it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A private sysml-grpc inherited the whole parent environment, so a token set in OPENSYSML_GRPC_TOKEN for a remote service became one the child demanded, and every private service refused the client. The child is now started without the variable, compared under any case on Windows as the service reads it there, as the other clients do. ConnectionOptions.Token, else $OPENSYSML_GRPC_TOKEN (TokenVariable), is sent on every call as authorization: Bearer over gRPC and Connect. The headers are resolved once at open and handed to the transport. A token must be the RFC 6750 b64token the service accepts; an authorization entry in Headers takes the place of the variable and is refused beside Token. A token is never logged, and credentials sent over cleartext HTTP to another machine are logged as a warning. Like the peers, a connection sends its token to a private child too, which requires none and ignores it. A service-sent Unauthenticated is now an AuthenticationException, a ServiceException saying whether credentials were sent and where they came from, built by one factory both transports call. A proxy's HTTP 401 page stays a TransportException. Two tests asserted that every service status, Unauthenticated included, is exactly a ServiceException; they now expect the new subclass for that status alone. The orphan probe reports its service's address, so a test can show a private child started while the variable is set answers a call carrying no token; without the environment fix it fails on every wire. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ectory for posterity
The .NET client declared 0.10.1 while the core and every other client are at 0.11.0, and its embedded release-digest table lacked v0.11.0. The two are coupled: the version names the release a private service is downloaded from by default, so a bump without the digests would refuse that download as unpinned, and the digests without the bump leave the version lockstep check red. Both change here. The embedded table is resynced from client/release-digests.json (no other client's copy had drifted), and the three test projects' lock files record the project reference at 0.11.0; no package moved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…notes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…erdict notes and library references Implements the service features the .NET client lacked, each gated before sending in the service's own order and typed in the parity inventory, which now defers no field: - Capabilities: ConvertLibraryReferences, ConvertLibraryStubs, QueryOrderBy, RenderDocumentAsciidoc and VerdictNotes. - Query: Query.OrderBy (needs query_order_by), and the GreaterOrEqual, LessOrEqual, In and InstanceOf comparisons. And/Or now refuse fewer than two constraints, as the standard and the service do; InstanceOf compares @type alone. - Documents and views: DocumentForm.AsciiDoc (needs render_document_asciidoc); RenderViewOptions.Compartments; ViewNode.Compartment and Inherited, ViewPort.Inherited. A compartment row with no box parent is a malformed rendering. - Verdict.Notes, each a VerdictNote; a service-backed test asks a solver question behind a new solver gate (OPENSYSML_REQUIRE_SMT), and both Linux CI jobs install z3 and set it. - Conversion.LibraryReferences and ConvertOptions.IncludeLibraryStubs (needs convert_library_stubs). - The conformance adapters and renderer carry every new field, so the run agrees with the reference runner field for field. Tests changed on purpose: - A one-member composite is refused by the standard and, since 6000439, by the service, so the query integration test writes its inverse comparison on its own, and a unit test holds the factories to the refusal. The out-of-range operator probe moves from 4, now LessOrEqual, to 8. - A calc result or out parameter stating no multiplicity is [0..*], so since PR Open-MBEE#1308 (fix/calc-result-effective-multiplicity) the service answers one value as a one-element sequence, and the shared conformance scenarios pin that for the shared fixtures. The value round-trip test's own model now declares `return r[1] = x`, keeping it a scalar round trip; the tests over the shared fixtures assert the sequence the scenarios pin, with no cast left to throw. DOTNET_MIN_TESTS is 3383. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…notes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… stack snapshot Bring the .NET client jobs in line with the rework of the CI dependency lists merged from develop: - .circleci/config.yml: the .NET client tests job still referenced the removed scan-inputs anchor, so the config no longer parsed and every release-config hygiene test failed. It now requires client-inputs, as the other client jobs do; the job builds its own sysml-grpc, so the requirement only orders it. - .github/workflows/pr.yml: the .NET job's sysml-grpc build read the pull request number with no merge_group branch, leaving a queue build stamped "pr-". It now uses develop's expression and stamps "merge-queue". - editors/vscode/src/landing/stack.json: adding .NET to the stack model changed its content hash, which the hand edit left stale. Regenerated with -update-landing; only the hash moved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…baselines
At pin 2026-09 (0.63.0), repeated exports of the same checkout under
OpenJDK 27 give different values for InvocationExpression.featuringType
and OperatorExpression.featuringType. The pilot derives these values from
its transformation order, not from the model. Declare both rows
pilot-nondeterministic, with the evidence, as FeatureChainExpression
already is. They are then scored in the dedicated column, so the baseline
reproduces from run to run and the instability stays visible.
- tools/referee/apijson: add the two declarations and extend
TestDeclaredNondeterminismScoresTheWholeRow to cover every declared
metaclass.
- docs/project/api-json-differential{.md,-baseline.json}: record the new
instabilities and re-record the scorecard. The .NET client self-model
additions add 27 matched, 10 ours-only and 16 pilot-only elements in
the examples root. The files header now gives the actual count, 932.
- docs/project/pilot-differential-baseline.json: refresh the examples
root digest for the edited self-model files. Every verdict and count is
unchanged.
- changes/unreleased: add the changelog fragment.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve the conflicts with develop:
- Makefile, scripts/ci-changed-areas{,-test}.sh: keep both sides' targets,
paths and cases (develop's Java documentation and docs/project inputs,
this branch's .NET manifest and dotnet area).
- editors/vscode/src/landing/stack.json: regenerated with -update-landing
over the merged stack model.
- docs/project/pilot-differential-baseline.json: re-recorded; only the
examples digest moved, every verdict and count is unchanged.
- docs/project/api-json-differential{-baseline.json,.md}: re-recorded over
the merged tree (two runs reproduce it). Against develop's baseline the
examples root gains the .NET self-model's 27 matched, 10 ours-only and
16 pilot-only elements, and the declared featuring-type rows move into
the pilot-nondeterministic column; the record's figures follow.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Conflicts resolved:
- Makefile: .PHONY keeps the .NET targets and gains develop's
textmate-grammars-check and textmate-grammars-publish.
- docs/project/api-json-differential{.md,-baseline.json}: develop's record,
with this branch's featuring-type nondeterminism prose re-applied; the
baseline re-recorded on the merged tree (pilot 2026-09, OpenJDK 27) and the
scorecard, root table and launch-ready gap counts taken from it.
- docs/project/pilot-differential-baseline.json: re-recorded on the merged
tree; against develop only the examples digest and the date move.
Follow-ups the merge requires:
- client/dotnet Version 0.11.0 -> 0.12.0, matching develop's release, and the
release digest table synced (scripts/sync-release-digests.py).
- C# wire stubs regenerated (make proto-csharp) for develop's schema.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The C# stubs regenerated for develop's schema expose fields the client dropped; the parity inventory, the capability list and the complete-wire coverage tests all failed on them. The client now reads and sends each. - ExecuteActionAsync: RunOptions.Trace returns ActionRun.Trace and TraceDropped, gated on the new Capabilities.ActionTrace, and a failed traced run keeps its trace on ExecutionException. RunOptions.Events posts signals or items to the performer, as the REPL's %send does. A trace or events under an exploring schedule, events with no performer, and RunOptions.Events on a state run are refused before sending, as the service and the Go client refuse them. - DocumentEvent carries an action record's Token, Step, Feature and Value. - RenderedView.Frame (new ViewFrame), ViewNode.Arrow and ViewNode.Parallel. - LibraryReference.LibraryPath names an inherited unnamed library member; ToString falls back to it when there is no qualified name. - The conformance runner sends and renders every new field; parity.json classifies them, lists the action_trace gate, develop's two ParseFile scenarios and the Value carried by an event binding. - Integration tests follow develop's service: library references now list inherited members, the API-JSON export completes feature, definition and inheritedFeature, and the shared suite holds 196 scenarios. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pass Make's BUF command to the dotnet-test and dotnet-coverage test processes and require it, so their existing schema-to-descriptor comparison cannot silently skip when buf is absent. The default uses the pinned go run command; BUF remains overridable, and neither target rewrites the generated stubs. Add regression coverage for both Make recipes, including the default pinned command, a multi-argument override and an environment that allows skipping. Document the required check and its toolchain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Adds
OpenMBEE.OpenSysML, a typed, asynchronous C# client that lets .NET applications use OpenSysML without implementing its service protocols or managing service processes themselves.The branch includes:
The client targets .NET 10 and is consumed from a checkout through
ProjectReference; it is not published to NuGet. Its version follows OpenSysML releases in lockstep. Native AOT and trimming are not supported. Release verification uses pinned SHA-256 digests, not Sigstore signatures, and rejects unpinned releases by default.Specification basis
Implements the existing OpenSysML protobuf service contract and capability-gating rules over gRPC and Connect. The standalone metamodel types are generated from the repository’s pinned SysML v2 metamodel table and checked against its metaclass hierarchy.
This adds a client implementation, not new SysML language semantics; no specification-compliance status rows move. Schema, field, value-arm, edit-arm, capability, and scenario inventories guard against client/service drift.
How it was verified
Local verification used SDK 10.0.402 and a freshly rebuilt
sysml-grpc, with service, cross-client interop, and SMT prerequisites required.make build-grpc— passed.OPENSYSML_GRPC_BINARY="$PWD/bin/sysml-grpc" OPENSYSML_REQUIRE_SERVICE=1 OPENSYSML_REQUIRE_INTEROP=1 OPENSYSML_REQUIRE_SMT=1 make dotnet-test— locked restore, zero-warning Release build, and formatting passed. Test result: 3,377 passed, 3 failed, 3 skipped, 3,383 total. The skips are Linux-only busy-executable tests on macOS.make conformance-dotnet conformance-dotnet-check— passed across gRPC, Connect/protobuf, and Connect/JSON, including withheld-capability configurations; 1,128 results agree with the reference runner, with 33 reviewed skips excluded.make dotnet-generate-check— passed for all committed generated-model goldens.make dotnet-metamodel-check— passed.go test -C tools ./gen/csmetamodel ./gen/hierarchy— passed.python3 client/dotnet/scripts/dotnet-gates.py sample --expect 'OpenMBEE.OpenSysML 0.11.0 (.NETCoreApp,Version=v10.0)'— passed.python3 client/dotnet/scripts/dotnet-gates.py metamodel-sample --expect 'OpenMBEE.OpenSysML.Metamodel 0.11.0 (.NETCoreApp,Version=v10.0)'— passed.python3 client/dotnet/scripts/dotnet-gates-test.py— 82 tests passed.python3 scripts/check-doc-links.py && python3 scripts/check-doc-ids.py && python3 scripts/changelog.py check && python3 scripts/sync-release-digests.py --check— passed.Remaining blocker: the service renders
AbstractViews::familyMixedwith a repeated node ID under different parents. The client correctly rejects that malformed response, causing the same integration test to fail on all three protocols. Those tests remain enabled; the renderer needs an upstream fix before the client suite is green.The repository-wide
make testandmake lint, .NET coverage, documentation-site build, andmake docs-countswere not rerun for this verification.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelog