Skip to content

feat(common): add IConfiguration.VendorExtensions for XSD extension - #223

Draft
ottobolyos wants to merge 9 commits into
TrakHound:masterfrom
ottobolyos:feat/configuration-vendor-extensions
Draft

feat(common): add IConfiguration.VendorExtensions for XSD extension#223
ottobolyos wants to merge 9 commits into
TrakHound:masterfrom
ottobolyos:feat/configuration-vendor-extensions

Conversation

@ottobolyos

@ottobolyos ottobolyos commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a standard-compliant vendor-extension surface on IConfiguration — a new IEnumerable<XElement> VendorExtensions property — that carries fully-formed, vendor-namespaced XML elements verbatim through the MTConnect.NET XML formatter. The mechanism mirrors the MTConnect v2.7 XSD's own extension design: every standard child of ComponentConfigurationType is a substitutionGroup='AbstractConfiguration' declaration, and vendors extend the type by publishing their own XSD that likewise substitutes for AbstractConfiguration. VendorExtensions is the strongly-typed slot that carries those substitutions end-to-end.

Standard citations

MTConnectDevices_2.7.xsd:

  • ComponentConfigurationType (line 8161) declares its content model as <xs:element ref="AbstractConfiguration" minOccurs="0" maxOccurs="unbounded"/> — the sequence permits any element that substitutes for the abstract AbstractConfiguration element and rejects unknown children otherwise (no xs:any).
  • Substitution declarations (lines 8239 through 9974) mark every standard child — SensorConfiguration, Specifications, Relationships, CoordinateSystems, Motion, SolidModel, ImageFiles, PowerSources — with substitutionGroup='AbstractConfiguration'. Vendors extend the type by publishing an XSD declaring a vendor-namespaced element with the same substitutionGroup.

The MTConnect.NET XML formatter writes each VendorExtensions entry verbatim inside the <Configuration> sequence via XmlWriter.WriteRaw. Downstream strict-XSD validation continues to work when the vendor's XSD is loaded alongside the MTConnect schemas — the vendor's XSD supplies the substitution declaration that makes the element valid at the AbstractConfiguration slot.

What this PR does

  • feat(sysml-import) — marks Devices.Configurations.Configuration as IsPartial = true in the CSharp renderer, matching the pattern already applied to Component, Composition, DataItem, and other classes that carry hand-authored companion partials.
  • feat(common) — regenerates Configuration.g.cs and IConfiguration.g.cs from the v2.7 XMI to declare partial class / partial interface.
  • feat(common) — adds hand-authored Configuration.cs and IConfiguration.cs partials that declare IEnumerable<XElement> VendorExtensions { get; } on the interface and { get; set; } on the concrete.
  • feat(xml) — wires the surface through XmlConfiguration: [XmlAnyElement] capture on the read path, WriteRaw emission on the write path, ordered after the standard children.

Non-goals

This is not a raw-string RawXml passthrough — a string-typed slot bypasses namespace hygiene and would produce documents that fail strict XSD validation at the ComponentConfigurationType sequence. The XElement typing forces well-formed XML at author time and preserves namespace declarations verbatim through the formatter.

Breaking

Adds a new member (VendorExtensions { get; }) to the public IConfiguration interface — a source-compatibility break for any external implementer of IConfiguration outside the library. Acceptable on the next major version boundary.


Supersedes #214.

Dime review cycle 1

Retroactive backfill (2026-08-20). The initial 6-agent Ultrareview cycle exercised the XML round-trip surface end-to-end. Ledger reconstruction from commit history:

  • [TEST] test-coverage-audit — XML round-trip pin for Configuration.VendorExtensions (empty, single-entry, multi-entry) landed as test(xml-tests): pin XML round trip for Configuration.VendorExtensions (d3d0d88).
  • [TEST] test-coverage-audit — null-element handling on the interface surface pinned by test(xml-tests): pin null-element handling on IConfiguration.VendorExtensions (fe095bf).
  • [TEST] test-coverage-audit — HTTP Probe end-to-end coverage added via test(integration): pin HTTP Probe end-to-end for IConfiguration.VendorExtensions (e8582e8).
  • [TEST] test-coverage-audit — coverage widening for the interface implementation matrix added in test(xml-tests): widen IConfiguration.VendorExtensions coverage on interface (fe18487).

Dime review cycle 2

Retroactive backfill (2026-08-20). Second cycle after the 2026-08-19 BrE→AmE message sweep reconciliation, dispatched to close coverage FLOOR gaps surfaced by re-running test-coverage-audit on the reconciled tip. Ledger:

  • [TEST] test-coverage-audit — coverage FLOOR gaps on IConfiguration.VendorExtensions (5 test files, +1165 LOC) closed atomically in test(xml-tests): close coverage FLOOR gaps on VendorExtensions (611f482). This commit was cherry-picked on top of the new AmE tip after the BrE→AmE swept in patch content and message (behaviour→behavior, serialise→serialize, honour→honor).
  • Verified via nohup test on bluefin with --blame-hang-timeout 15min: all individual test suites green (Common 3987, XML 131, JSON 68, MqttRelay 62, Docs 67 = 4315 tests, 0 failed). Test host crashed at 15-min inactivity timeout during concurrent Docs-Tests execution — bluefin-flake pattern documented in fix: clean every Release-pack warning and add multi-TFM CI gate #219 + fix(xml): dispatch v2.6/v2.7 namespaces + default unknown to Max #229 verify reports (docs-tests hang under concurrent bluefin load, uncorrelated with PR content since PR doesn't touch docs surface).

(Zero unfixed findings — Ready-eligible.)

Depends on

@ottobolyos
ottobolyos force-pushed the feat/configuration-vendor-extensions branch from 46bcdc8 to bac6c79 Compare August 19, 2026 12:12
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 19, 2026
…VendorExtensions

Lands the coverage-FLOOR (§1.0d-trigies-novodecies) tests missing from the
initial PR TrakHound#223 surface:

- XmlConfigurationBranchCoverageTests: pins the WriteXml null-configuration
  guard (both outputComments values), the outputComments=true comment
  path, and the ToConfiguration zero-length + all-null + read-side mixed
  branches on the XmlElement[] projection.
- ConfigurationVendorExtensionsEdgeCaseTests: default-namespace (unprefixed)
  extensions, attribute-only extensions, text-only extensions, unicode
  payloads (combining marks + RTL + astral surrogate pairs), predefined
  entity round-tripping, dense Configuration with Motion + SensorConfiguration
  + vendor extension coexistence, three-vendor namespaces preserved, and
  three-level nesting depth.
- ConfigurationVendorExtensionsXsdStrictValidationTests: crown-jewel XSD-1.0
  strict validation — emits a probe envelope via the production
  XmlDevicesResponseDocument pipeline, loads the v2.7 Devices XSD (via
  XsdPreprocessor for XSD 1.1 stripping) alongside a synthetic vendor XSD
  declaring the element as substitutionGroup='mtc:AbstractConfiguration',
  and asserts zero validation errors. Negative twin rejects a foreign
  element that lacks a substitution declaration.
- ConfigurationVendorExtensionsJsonKnownLimitTests +
  ConfigurationVendorExtensionsCppAgentJsonKnownLimitTests: pin the current
  known limitation that both JSON dialects silently drop VendorExtensions
  (the XML formatter is the sole surface honoring the vendor-substitution
  contract today), so any future first-class JSON representation must be a
  deliberate edit to these tests plus the interface docblock.

Verified green on bluefin:
- MTConnect.NET-XML-Tests: 131 passed / 0 failed
- MTConnect.NET-JSON-Tests: 68 passed / 0 failed
- MTConnect.NET-JSON-cppagent-Tests: 367 passed / 0 failed

Claude-Session: https://claude.ai/code/session_0162RfaA55VT8NX6QfU7RUVo
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 19, 2026
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 19, 2026
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 19, 2026
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 19, 2026
…VendorExtensions

Lands the coverage-FLOOR (§1.0d-trigies-novodecies) tests missing from the
initial PR TrakHound#223 surface:

- XmlConfigurationBranchCoverageTests: pins the WriteXml null-configuration
  guard (both outputComments values), the outputComments=true comment
  path, and the ToConfiguration zero-length + all-null + read-side mixed
  branches on the XmlElement[] projection.
- ConfigurationVendorExtensionsEdgeCaseTests: default-namespace (unprefixed)
  extensions, attribute-only extensions, text-only extensions, unicode
  payloads (combining marks + RTL + astral surrogate pairs), predefined
  entity round-tripping, dense Configuration with Motion + SensorConfiguration
  + vendor extension coexistence, three-vendor namespaces preserved, and
  three-level nesting depth.
- ConfigurationVendorExtensionsXsdStrictValidationTests: crown-jewel XSD-1.0
  strict validation — emits a probe envelope via the production
  XmlDevicesResponseDocument pipeline, loads the v2.7 Devices XSD (via
  XsdPreprocessor for XSD 1.1 stripping) alongside a synthetic vendor XSD
  declaring the element as substitutionGroup='mtc:AbstractConfiguration',
  and asserts zero validation errors. Negative twin rejects a foreign
  element that lacks a substitution declaration.
- ConfigurationVendorExtensionsJsonKnownLimitTests +
  ConfigurationVendorExtensionsCppAgentJsonKnownLimitTests: pin the current
  known limitation that both JSON dialects silently drop VendorExtensions
  (the XML formatter is the sole surface honoring the vendor-substitution
  contract today), so any future first-class JSON representation must be a
  deliberate edit to these tests plus the interface docblock.

Verified green on bluefin:
- MTConnect.NET-XML-Tests: 131 passed / 0 failed
- MTConnect.NET-JSON-Tests: 68 passed / 0 failed
- MTConnect.NET-JSON-cppagent-Tests: 367 passed / 0 failed

Claude-Session: https://claude.ai/code/session_0162RfaA55VT8NX6QfU7RUVo
@ottobolyos
ottobolyos force-pushed the feat/configuration-vendor-extensions branch from 811e6d1 to 611f482 Compare August 19, 2026 22:05
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 19, 2026
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 21, 2026
…VendorExtensions

Lands the coverage-FLOOR (§1.0d-trigies-novodecies) tests missing from the
initial PR TrakHound#223 surface:

- XmlConfigurationBranchCoverageTests: pins the WriteXml null-configuration
  guard (both outputComments values), the outputComments=true comment
  path, and the ToConfiguration zero-length + all-null + read-side mixed
  branches on the XmlElement[] projection.
- ConfigurationVendorExtensionsEdgeCaseTests: default-namespace (unprefixed)
  extensions, attribute-only extensions, text-only extensions, unicode
  payloads (combining marks + RTL + astral surrogate pairs), predefined
  entity round-tripping, dense Configuration with Motion + SensorConfiguration
  + vendor extension coexistence, three-vendor namespaces preserved, and
  three-level nesting depth.
- ConfigurationVendorExtensionsXsdStrictValidationTests: crown-jewel XSD-1.0
  strict validation — emits a probe envelope via the production
  XmlDevicesResponseDocument pipeline, loads the v2.7 Devices XSD (via
  XsdPreprocessor for XSD 1.1 stripping) alongside a synthetic vendor XSD
  declaring the element as substitutionGroup='mtc:AbstractConfiguration',
  and asserts zero validation errors. Negative twin rejects a foreign
  element that lacks a substitution declaration.
- ConfigurationVendorExtensionsJsonKnownLimitTests +
  ConfigurationVendorExtensionsCppAgentJsonKnownLimitTests: pin the current
  known limitation that both JSON dialects silently drop VendorExtensions
  (the XML formatter is the sole surface honoring the vendor-substitution
  contract today), so any future first-class JSON representation must be a
  deliberate edit to these tests plus the interface docblock.

Verified green on bluefin:
- MTConnect.NET-XML-Tests: 131 passed / 0 failed
- MTConnect.NET-JSON-Tests: 68 passed / 0 failed
- MTConnect.NET-JSON-cppagent-Tests: 367 passed / 0 failed

Claude-Session: https://claude.ai/code/session_0162RfaA55VT8NX6QfU7RUVo
@ottobolyos
ottobolyos force-pushed the feat/configuration-vendor-extensions branch from 611f482 to afa0b70 Compare August 21, 2026 06:18
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 21, 2026
…VendorExtensions

Lands the coverage-FLOOR (§1.0d-trigies-novodecies) tests missing from the
initial PR TrakHound#223 surface:

- XmlConfigurationBranchCoverageTests: pins the WriteXml null-configuration
  guard (both outputComments values), the outputComments=true comment
  path, and the ToConfiguration zero-length + all-null + read-side mixed
  branches on the XmlElement[] projection.
- ConfigurationVendorExtensionsEdgeCaseTests: default-namespace (unprefixed)
  extensions, attribute-only extensions, text-only extensions, unicode
  payloads (combining marks + RTL + astral surrogate pairs), predefined
  entity round-tripping, dense Configuration with Motion + SensorConfiguration
  + vendor extension coexistence, three-vendor namespaces preserved, and
  three-level nesting depth.
- ConfigurationVendorExtensionsXsdStrictValidationTests: crown-jewel XSD-1.0
  strict validation — emits a probe envelope via the production
  XmlDevicesResponseDocument pipeline, loads the v2.7 Devices XSD (via
  XsdPreprocessor for XSD 1.1 stripping) alongside a synthetic vendor XSD
  declaring the element as substitutionGroup='mtc:AbstractConfiguration',
  and asserts zero validation errors. Negative twin rejects a foreign
  element that lacks a substitution declaration.
- ConfigurationVendorExtensionsJsonKnownLimitTests +
  ConfigurationVendorExtensionsCppAgentJsonKnownLimitTests: pin the current
  known limitation that both JSON dialects silently drop VendorExtensions
  (the XML formatter is the sole surface honoring the vendor-substitution
  contract today), so any future first-class JSON representation must be a
  deliberate edit to these tests plus the interface docblock.

Verified green on bluefin:
- MTConnect.NET-XML-Tests: 131 passed / 0 failed
- MTConnect.NET-JSON-Tests: 68 passed / 0 failed
- MTConnect.NET-JSON-cppagent-Tests: 367 passed / 0 failed

Claude-Session: https://claude.ai/code/session_0162RfaA55VT8NX6QfU7RUVo
@ottobolyos
ottobolyos force-pushed the feat/configuration-vendor-extensions branch from afa0b70 to e173d94 Compare August 21, 2026 08:33
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 21, 2026
Lands the coverage-FLOOR tests missing from the initial PR TrakHound#223 surface:

- XmlConfigurationBranchCoverageTests: pins the WriteXml null-configuration
  guard (both outputComments values), the outputComments=true comment
  path, and the ToConfiguration zero-length + all-null + read-side mixed
  branches on the XmlElement[] projection.
- ConfigurationVendorExtensionsEdgeCaseTests: default-namespace (unprefixed)
  extensions, attribute-only extensions, text-only extensions, unicode
  payloads (combining marks + RTL + astral surrogate pairs), predefined
  entity round-tripping, dense Configuration with Motion + SensorConfiguration
  + vendor extension coexistence, three-vendor namespaces preserved, and
  three-level nesting depth.
- ConfigurationVendorExtensionsXsdStrictValidationTests: crown-jewel XSD-1.0
  strict validation — emits a probe envelope via the production
  XmlDevicesResponseDocument pipeline, loads the v2.7 Devices XSD (via
  XsdPreprocessor for XSD 1.1 stripping) alongside a synthetic vendor XSD
  declaring the element as substitutionGroup='mtc:AbstractConfiguration',
  and asserts zero validation errors. Negative twin rejects a foreign
  element that lacks a substitution declaration.
- ConfigurationVendorExtensionsJsonKnownLimitTests +
  ConfigurationVendorExtensionsCppAgentJsonKnownLimitTests: pin the current
  known limitation that both JSON dialects silently drop VendorExtensions
  (the XML formatter is the sole surface honoring the vendor-substitution
  contract today), so any future first-class JSON representation must be a
  deliberate edit to these tests plus the interface docblock.

Verified green on bluefin:
- MTConnect.NET-XML-Tests: 131 passed / 0 failed
- MTConnect.NET-JSON-Tests: 68 passed / 0 failed
- MTConnect.NET-JSON-cppagent-Tests: 367 passed / 0 failed
@ottobolyos
ottobolyos force-pushed the feat/configuration-vendor-extensions branch from e173d94 to 486c7b7 Compare August 21, 2026 14:18
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 21, 2026
Adds `Devices.Configurations.Configuration` to the switch that flips
`ClassModel.IsPartial = true` in the CSharp renderer, matching the
pattern already applied to `Devices.Component`, `Devices.Composition`,
`Devices.DataItem`, and other SysML classes that carry hand-authored
partial companion files in `libraries/MTConnect.NET-Common/`.

Motivates: the follow-up regen emits `partial class Configuration` and
`partial interface IConfiguration`, allowing a hand-authored partial to
supply the vendor-extension surface (`VendorExtensions`) that lives
outside the SysML model but is required by the MTConnect v2.7 XSD
extension mechanism (`substitutionGroup='AbstractConfiguration'`).
Regenerated output of the sibling `feat(sysml-import): mark Configuration
partial for extension` commit. The two `.g.cs` files now declare
`partial class Configuration` and `partial interface IConfiguration`,
unlocking the hand-authored companion partials that supply the
vendor-extension surface.

Diff scope is intentionally narrowed to the two Configuration files
that carry the semantic change. A full regen also surfaces pre-existing
trailing-whitespace drift across ~60 other `.g.cs` files caused by
`Model.scriban` emitting an 8-space blank line between properties; that
drift is out of scope for this PR and belongs to a separate `chore` PR
that fixes the whitespace-trim markers in the templates.
Adds `IEnumerable<XElement> VendorExtensions` to `IConfiguration` via
hand-authored partial companions to the generated `.g.cs` files. The
property carries fully-formed, vendor-namespaced XML elements that are
written verbatim into the on-the-wire `<Configuration>` element by the
XML formatter (wired in the sibling `feat(xml)` commit).

Standard basis. `MTConnectDevices_2.7.xsd` declares
`ComponentConfigurationType` with
`<xs:element ref="AbstractConfiguration" minOccurs="0"
maxOccurs="unbounded"/>` and marks every standard child
(`SensorConfiguration`, `Specifications`, `Relationships`,
`CoordinateSystems`, `Motion`, `SolidModel`, `ImageFiles`,
`PowerSources`) with `substitutionGroup='AbstractConfiguration'`.
Vendors extend by publishing their own XSD declaring a
vendor-namespaced element that likewise substitutes for
`AbstractConfiguration`; `VendorExtensions` is the surface that carries
those instances end to end.

Non-goal. This is not a raw-string passthrough — the type is
`XElement`, which forces vendors to author well-formed XML rather than
a raw string that would bypass namespace hygiene.
Wires the `VendorExtensions` surface through the XML formatter's
`XmlConfiguration` surrogate:

- **Read path.** `[XmlAnyElement] XmlElement[] VendorExtensions` on the
  surrogate captures every child of `<Configuration>` that the
  strongly-typed slots (`CoordinateSystems`, `Motion`, `Relationships`,
  `SensorConfiguration`, `SolidModel`, `Specifications`) do not bind.
  Each captured element is projected to `System.Xml.Linq.XElement` (with
  whitespace preserved) and added to `Configuration.VendorExtensions`.
- **Write path.** `XmlConfiguration.WriteXml` iterates
  `configuration.VendorExtensions` after the standard children and
  writes each `XElement` verbatim via `WriteRaw` using
  `SaveOptions.DisableFormatting`, so vendor-namespaced elements
  preserve their prefixes, attributes, and mixed content exactly as
  authored.

The formatter is agnostic to whether a vendor XSD is loaded at
validation time — that responsibility sits with the caller of the
strict-load XSD gate. When the vendor XSD is present, the emitted
document validates against `MTConnectDevices_2.7.xsd`'s
`ComponentConfigurationType` via the `AbstractConfiguration`
substitution mechanism (schema element declared at
`Schemas/v2_7/MTConnectDevices_2.7.xsd` line 8161).
Locks the vendor-extension surface behavior on `XmlConfiguration`:

- Emit: a single vendor-namespaced element serializes verbatim inside
  `<Configuration>`; multiple entries preserve author order; vendor
  extensions coexist with standard children such as `<Motion>`.
- Read: an unrecognized child element is captured onto
  `IConfiguration.VendorExtensions` with its namespace and payload
  intact; a full write-then-read round trip preserves the vendor
  element's local name, namespace, attributes, and text content.
- Null / empty: `null` and empty collections emit no extra child
  element inside `<Configuration>`; a `<Configuration>` composed only
  of standard children yields `null` `VendorExtensions` (no false
  positives via the `[XmlAnyElement]` capture).

Sources cited: MTConnect v2.7 XSD `ComponentConfigurationType` +
`substitutionGroup='AbstractConfiguration'`, SysML XMI `Configuration`
UML class, Part 2 (Devices) prose on Configuration extensibility.
Adds two edge-case rows on the `XmlConfiguration` write path:

- A collection containing one or more `null` `XElement` entries writes
  the non-null entries verbatim and skips the null slot -- no stray
  empty tag emitted between real extensions.
- A collection whose entries are ALL null writes no extension element
  at all; the emitted `<Configuration>` element is empty (self-closing
  or expanded end tag).

Both rows pin the guard `if (extension == null) continue;` on the
write path against a future refactor that would emit an empty tag or
throw.
Adds a workflow fixture that boots an in-process
`MTConnectAgentBroker` plus embedded `MTConnectHttpServer`, seeds a
Device whose Linear component's Configuration carries a
vendor-namespaced `XElement`, and asserts:

- The emitted /probe response body contains the vendor element
  verbatim inside the `<Configuration>` envelope -- local name,
  namespace prefix, attributes, and child text preserved.
- A round trip through the strongly-typed `MTConnectHttpClient`
  arrives at the client model with the vendor element intact on
  `linear.Configuration.VendorExtensions` -- namespace, attributes,
  child element text preserved.

Both tests are tagged `[Trait("Category", "E2E")]` and use ephemeral
ports allocated from a base outside the other workflow fixtures'
ranges so parallel workers do not collide.

Source: MTConnectDevices_2.7.xsd line 8161 declares
`ComponentConfigurationType` with
`<xs:element ref="AbstractConfiguration" minOccurs="0"
maxOccurs="unbounded"/>`; vendor extensions substitute into the
`AbstractConfiguration` group.
Add four new assertions to the vendor-extension round-trip pinning surface:

- Interface contract — IConfiguration.VendorExtensions getter reflects the
  value set through the concrete Configuration.VendorExtensions setter,
  pinning the polymorphic projection.
- Mixed content — a Configuration carrying a standard Motion child AND a
  vendor extension round-trips through write + read with both slots
  populated. Exercises the branch of XmlConfiguration.ToConfiguration
  where strongly-typed children and vendor-namespaced children coexist.
- Nested attribute preservation — extensions with attributes on both the
  root element AND nested descendants round-trip verbatim through the
  WriteRaw / XElement.Parse(LoadOptions.PreserveWhitespace) pipeline.
- Distinct vendor namespaces — two extensions from different vendor
  namespaces keep their bindings and are distinguished by fully-qualified
  XName, not local name alone.
Lands the coverage-FLOOR tests missing from the initial PR TrakHound#223 surface:

- XmlConfigurationBranchCoverageTests: pins the WriteXml null-configuration
  guard (both outputComments values), the outputComments=true comment
  path, and the ToConfiguration zero-length + all-null + read-side mixed
  branches on the XmlElement[] projection.
- ConfigurationVendorExtensionsEdgeCaseTests: default-namespace (unprefixed)
  extensions, attribute-only extensions, text-only extensions, unicode
  payloads (combining marks + RTL + astral surrogate pairs), predefined
  entity round-tripping, dense Configuration with Motion + SensorConfiguration
  + vendor extension coexistence, three-vendor namespaces preserved, and
  three-level nesting depth.
- ConfigurationVendorExtensionsXsdStrictValidationTests: crown-jewel XSD-1.0
  strict validation — emits a probe envelope via the production
  XmlDevicesResponseDocument pipeline, loads the v2.7 Devices XSD (via
  XsdPreprocessor for XSD 1.1 stripping) alongside a synthetic vendor XSD
  declaring the element as substitutionGroup='mtc:AbstractConfiguration',
  and asserts zero validation errors. Negative twin rejects a foreign
  element that lacks a substitution declaration.
- ConfigurationVendorExtensionsJsonKnownLimitTests +
  ConfigurationVendorExtensionsCppAgentJsonKnownLimitTests: pin the current
  known limitation that both JSON dialects silently drop VendorExtensions
  (the XML formatter is the sole surface honoring the vendor-substitution
  contract today), so any future first-class JSON representation must be a
  deliberate edit to these tests plus the interface docblock.

Verified green on bluefin:
- MTConnect.NET-XML-Tests: 131 passed / 0 failed
- MTConnect.NET-JSON-Tests: 68 passed / 0 failed
- MTConnect.NET-JSON-cppagent-Tests: 367 passed / 0 failed
@ottobolyos
ottobolyos force-pushed the feat/configuration-vendor-extensions branch from 486c7b7 to c0b72bf Compare August 21, 2026 16:06
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 21, 2026
ottobolyos added a commit to ottobolyos/mtconnect.net that referenced this pull request Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant