Skip to content

Reorganize source and tests around domain-aligned namespaces - #103

Merged
kelchm merged 8 commits into
mainfrom
reorg/domains
Aug 9, 2026
Merged

Reorganize source and tests around domain-aligned namespaces#103
kelchm merged 8 commits into
mainfrom
reorg/domains

Conversation

@kelchm

@kelchm kelchm commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Closes #102.

Mechanical reorganization of the codebase into domain folders with a literal path == namespace rule, per the issue and its ratified amendments.

What changed

  • Core (8cb7d74): the Protocol/ grab-bag dissolved into Display/{Protocol,Session,Catalog}, Leds/, Devices/{Identity,Profiles} (absorbing the former Profiles/ root), Tuning/; connection/identity types moved out of Transport/; Core-subject tests re-homed under tests/.../Core/<domain>/.
  • Plugin (df27a88): Adapters/ dissolved into Display/, Leds/, Devices/, Settings/, ControlMapper/, UI/; stale namespace declarations corrected; plugin-subject tests re-homed; one mixed test suite split by true subject.
  • Friend access closed (cb29e3a, isolated as required): ConverterCaptureProbe is SimHub-free and moved into Core, removing the production InternalsVisibleTo grant — the merged build now proves the plugin needs no Core internals.
  • Namespace scheme + enforcement (1f58560): every declaration equals its project directory root plus relative folder path (FanaBridge.Core.* / FanaBridge.* / FanaBridge.Updater.* / FanaBridge.Tests.*), with truthful RootNamespace in every project. Enforcement is compiler-native — IDE0130 at error severity with EnforceCodeStyleInBuild — plus a small contract test for XAML x:Class (outside the analyzer's reach). Exceptions are two pragma'd files with in-file reasons (root-namespace Log, the ModuleInitializer polyfill) and the SimHub reflection shim in tests. UI/ is subdivided by feature (Settings/, Wizard/, Devices/) ahead of upcoming display work. Rules and frozen names are documented in docs/architecture.md.
  • Polish (a9f2cd2): review fixes — vacuous-pass guard in the XAML contract test, frozen-names completeness, using order.

Not changed

No behavior, member-signature, visibility, or type-short-name changes; fully-qualified names change by design (namespaces are the point of this PR — no external consumers exist, as this is a plugin, not a library). No serialization or SimHub-facing string changes — all AttachDelegate/AddEvent keys, settings filenames, and the persisted FanaBridge.FanatecPlugin type name are byte-identical. Project graph and single-DLL ILRepack packaging unchanged.

Verification

  • 749/749 tests green (748 at base + the new XAML contract test; full test-method inventory compared base vs head — none lost).
  • Merged ILRepack build clean; FanaBridge.FanatecPlugin export confirmed in the merged DLL; embedded wheel profiles verified loading under the new manifest names.
  • IDE0130 verified to fail the build on planted violations in all four projects; the XAML contract test verified to catch a planted misplaced x:Class.
  • Mid-branch commit built and tested green (bisect-safe).

Remaining before merge

  • Manual smoke in SimHub with the merged DLL: FanaBridge tab, device screen/tuning panels, wheel-profile wizard (the UI/ subdivision changed internal BAML resource URIs; regeneration verified, rendering has no automated coverage).

kelchm added 5 commits August 8, 2026 18:30
Mechanical move of the Core Protocol/ grab-bag and Transport strays into
domain homes: Display/{Protocol,Session,Catalog}, Leds/, Devices/
(+Identity/, +Profiles/ absorbing the former Profiles/ root), Tuning/,
with ReportElicit joining Transport/. Namespaces follow folders under
the unchanged FanaBridge root namespace; Col03FrameClassifier's stale
FanaBridge.Protocol declaration corrected to FanaBridge.Transport.

Core-subject tests move to tests/FanaBridge.Tests/Core/<domain>/
mirroring their subjects (per-project-root convention: Core/, Plugin/,
Updater/).

One reference-form change rides along: IFanatecLedModuleHost's
Profiles.WheelCapabilities parameter is now unqualified under
using FanaBridge.Devices.Profiles (the old prefix resolved via an
ancestor namespace that no longer exists).

No behavior, API, visibility, or resource changes; RootNamespace,
Resources/, and root-namespace Log are untouched. 748/748 tests green;
ILRepack merged build clean.
…gin.* (issue #102)

The plugin's Adapters/ grab-bag is gone: Display/{Drivers,DisplaySettings},
Leds/, Devices/, Settings/ (absorbing root FanatecPluginSettings),
ControlMapper/, and UI/ (IDevicePanelFactory). DiagnosticsReport's stale
FanaBridge.Protocol declaration corrected to its Diagnostics home.

Plugin production namespaces now carry the per-project root
FanaBridge.Plugin.<path> (ratified on #102): the shipped DLL merges all
assemblies, so the Core/plugin boundary must survive in type names.
Core keeps clean FanaBridge.* namespaces. Documented exceptions:
FanatecPlugin and the root logging types stay in namespace FanaBridge
(the plugin FQN is persisted user state in SimHub); ConverterCaptureProbe
is deferred to the friend-access commit.

Domain taxonomies are project-local (also ratified): plugin nouns match
Core where the capability genuinely spans both sides; the one-type
Display/Host segment was flattened into Display/.

Plugin-subject tests move to tests/FanaBridge.Tests/Plugin/<domain>/,
and ItmTelemetryTests split by true subject: 30 mapper tests now in
Plugin/Display/Drivers/ItmTelemetryMapperTests, 11 protocol tests
remain in Core.

Mechanical throughout: no behavior, API, visibility, or literal changes;
all AttachDelegate keys and settings strings byte-identical.
748/748 tests green; ILRepack merged build clean.
…end access (issue #102)

The probe is SimHub-free and used Core internals (Col03FrameClassifier,
WheelEngage) — the sole reason FanaBridge.Core granted
InternalsVisibleTo("FanaBridge"). It now lives in Core/Diagnostics
beside FanatecSoftwareMonitor, and the production friend grant is gone;
the merged build proves the plugin needs no Core internals. Tests keep
their own grant and move to Core/Diagnostics.

748/748 tests green; ILRepack merged build clean.
…ent (issue #102)

Namespaces now spell their location, ratified on #102 after review:
Core declares FanaBridge.Core.<folder> (RootNamespace made truthful;
embedded profile resources verified loading — the loader matches a
'.Profiles.' manifest segment, not the root). The plugin declares
FanaBridge.<folder>; the shipped FanaBridge.dll therefore exports
FanaBridge.* from the shell and FanaBridge.Core.* from the merged
library, so ownership stays readable in stack traces while every
directory spells its namespace.

Riding on the same surface:
- SimHubLogSink joins its mapped FanaBridge.Logging home; the net48
  ModuleInitializer polyfill splits into Properties/ (pragma'd).
- UI/ subdivides by feature (Settings/, Wizard/, Devices/) ahead of the
  display editor; BAML resource URIs regenerate internally (verified).
- Layout enforcement is compiler-native — IDE0130 at error severity
  with EnforceCodeStyleInBuild — rather than a bespoke guard test.
  Exceptions are two in-file pragmas (root-namespace Log, the polyfill)
  plus the SimHub reflection shim in tests, each with its reason at
  the site.
- tests/Contracts/ hosts repo/external-contract tests: the XAML x:Class
  layout check (markup is outside the analyzer's reach) and the SimHub
  enum snapshot.
- docs/architecture.md records the layers, the namespace rule, and the
  frozen names invisible to the compiler.

Mechanical throughout; all SimHub-facing strings byte-identical; the
persisted FanaBridge.FanatecPlugin type name is untouched and now
path-conformant. 749/749 tests green; merged build exports verified;
IDE0130 fail-on-violation verified with a planted file.
…test, frozen-names completeness, using order

From the whole-branch review: the XAML layout test now fails loudly if
it scans zero files; docs/architecture.md gains the Control Mapper
variant-id row, a note that SimHub's resolve cache is hash-invalidated
(cache state, not durable state), and a pointer to the tests README for
the shim exception; one using block re-sorted.
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 135 files, which is 35 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 23f59d24-40ee-4341-93f0-2b322c6ae281

📥 Commits

Reviewing files that changed from the base of the PR and between fd6a765 and 23a1ee3.

📒 Files selected for processing (135)
  • .editorconfig
  • Directory.Build.props
  • docs/README.md
  • docs/architecture.md
  • src/FanaBridge.Core/Devices/ConnectionMonitor.cs
  • src/FanaBridge.Core/Devices/FanatecWheelbase.cs
  • src/FanaBridge.Core/Devices/IWheelbaseConnection.cs
  • src/FanaBridge.Core/Devices/Identity/FanatecDeviceTables.cs
  • src/FanaBridge.Core/Devices/Identity/FanatecIdentity.cs
  • src/FanaBridge.Core/Devices/Identity/IdentitySettler.cs
  • src/FanaBridge.Core/Devices/Identity/SrmConverterIdentity.cs
  • src/FanaBridge.Core/Devices/Identity/SystemReportReader.cs
  • src/FanaBridge.Core/Devices/Identity/WheelEngage.cs
  • src/FanaBridge.Core/Devices/Profiles/ColorFormat.cs
  • src/FanaBridge.Core/Devices/Profiles/DeviceConfig.cs
  • src/FanaBridge.Core/Devices/Profiles/DisplayType.cs
  • src/FanaBridge.Core/Devices/Profiles/InputMapping.cs
  • src/FanaBridge.Core/Devices/Profiles/LedChannelConverter.cs
  • src/FanaBridge.Core/Devices/Profiles/LedColorLimitation.cs
  • src/FanaBridge.Core/Devices/Profiles/LedDefinition.cs
  • src/FanaBridge.Core/Devices/Profiles/LedEnums.cs
  • src/FanaBridge.Core/Devices/Profiles/ProfileMatch.cs
  • src/FanaBridge.Core/Devices/Profiles/ProfileSource.cs
  • src/FanaBridge.Core/Devices/Profiles/WheelCapabilities.cs
  • src/FanaBridge.Core/Devices/Profiles/WheelProfile.cs
  • src/FanaBridge.Core/Devices/Profiles/WheelProfileStore.cs
  • src/FanaBridge.Core/Diagnostics/ConverterCaptureProbe.cs
  • src/FanaBridge.Core/Diagnostics/FanatecSoftwareMonitor.cs
  • src/FanaBridge.Core/Display/Catalog/ItmDeviceCatalog.cs
  • src/FanaBridge.Core/Display/Protocol/DisplayEncoder.cs
  • src/FanaBridge.Core/Display/Protocol/ItmEncoder.cs
  • src/FanaBridge.Core/Display/Protocol/ItmTelemetry.cs
  • src/FanaBridge.Core/Display/Protocol/SevenSegment.cs
  • src/FanaBridge.Core/Display/Session/ItmLifecycleController.cs
  • src/FanaBridge.Core/FanaBridge.Core.csproj
  • src/FanaBridge.Core/Leds/ColorHelper.cs
  • src/FanaBridge.Core/Leds/LedEncoder.cs
  • src/FanaBridge.Core/Leds/LegacyLedEncoder.cs
  • src/FanaBridge.Core/Logging/ILogSink.cs
  • src/FanaBridge.Core/Logging/Log.cs
  • src/FanaBridge.Core/Transport/Col03Family.cs
  • src/FanaBridge.Core/Transport/Col03FrameClassifier.cs
  • src/FanaBridge.Core/Transport/Col03QueueSet.cs
  • src/FanaBridge.Core/Transport/FanatecTransport.cs
  • src/FanaBridge.Core/Transport/HidReportQueue.cs
  • src/FanaBridge.Core/Transport/IConnectableTransport.cs
  • src/FanaBridge.Core/Transport/IDeviceTransport.cs
  • src/FanaBridge.Core/Transport/IHidBusEnumerator.cs
  • src/FanaBridge.Core/Transport/IReportStream.cs
  • src/FanaBridge.Core/Transport/ReportElicit.cs
  • src/FanaBridge.Core/Tuning/EncoderMode.cs
  • src/FanaBridge.Core/Tuning/FanatecTuningController.cs
  • src/FanaBridge/ControlMapper/ControlMapperBridge.cs
  • src/FanaBridge/ControlMapper/FanaBridgeVariantProvider.cs
  • src/FanaBridge/Devices/FanatecDevicesRegistry.cs
  • src/FanaBridge/Devices/FanatecWheelDeviceInstance.cs
  • src/FanaBridge/Devices/SimHubDevicesGateway.cs
  • src/FanaBridge/Diagnostics/DiagnosticsReport.cs
  • src/FanaBridge/Display/DisplaySettings.cs
  • src/FanaBridge/Display/Drivers/FanatecDisplayDriver.cs
  • src/FanaBridge/Display/Drivers/ItmDisplayDriver.cs
  • src/FanaBridge/Display/Drivers/ItmTelemetryMapper.cs
  • src/FanaBridge/FanatecPlugin.cs
  • src/FanaBridge/Leds/FanatecLedDriver.cs
  • src/FanaBridge/Leds/FanatecLedManager.cs
  • src/FanaBridge/Leds/FanatecLedModuleHost.cs
  • src/FanaBridge/Leds/IFanatecLedModuleHost.cs
  • src/FanaBridge/Leds/NoLedModuleHost.cs
  • src/FanaBridge/Logging/SimHubLogSink.cs
  • src/FanaBridge/Properties/ModuleInitializerAttribute.cs
  • src/FanaBridge/Settings/FanatecDeviceSettings.cs
  • src/FanaBridge/Settings/FanatecPluginSettings.cs
  • src/FanaBridge/Settings/FanatecSettingsSnapshot.cs
  • src/FanaBridge/Settings/PersistedPluginSettings.cs
  • src/FanaBridge/UI/Devices/DevicePanelFactory.cs
  • src/FanaBridge/UI/Devices/IDevicePanelFactory.cs
  • src/FanaBridge/UI/Devices/LedColorLimitationNotice.xaml
  • src/FanaBridge/UI/Devices/LedColorLimitationNotice.xaml.cs
  • src/FanaBridge/UI/Settings/ScreenSettingsPanel.xaml
  • src/FanaBridge/UI/Settings/ScreenSettingsPanel.xaml.cs
  • src/FanaBridge/UI/Settings/SettingsControl.xaml
  • src/FanaBridge/UI/Settings/SettingsControl.xaml.cs
  • src/FanaBridge/UI/Settings/TuningSettingsPanel.xaml
  • src/FanaBridge/UI/Settings/TuningSettingsPanel.xaml.cs
  • src/FanaBridge/UI/Wizard/WheelProfileWizardDialog.xaml
  • src/FanaBridge/UI/Wizard/WheelProfileWizardDialog.xaml.cs
  • src/FanaBridge/UI/Wizard/WizardState.cs
  • tests/FanaBridge.Tests/Contracts/NamespaceEnforcementContractTests.cs
  • tests/FanaBridge.Tests/Contracts/SimHubEnumSnapshotTests.cs
  • tests/FanaBridge.Tests/Contracts/XamlClassLayoutTests.cs
  • tests/FanaBridge.Tests/Core/Devices/ConnectFailureMessageTests.cs
  • tests/FanaBridge.Tests/Core/Devices/ConnectionMonitorTests.cs
  • tests/FanaBridge.Tests/Core/Devices/FanatecWheelbaseTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Identity/FanatecDeviceTablesTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Identity/IdentitySettlerTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Identity/SrmConverterIdentityTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Profiles/LedChannelConverterTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Profiles/LedColorLimitationTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Profiles/WheelProfileItmDeviceTests.cs
  • tests/FanaBridge.Tests/Core/Devices/Profiles/WheelProfileStoreTests.cs
  • tests/FanaBridge.Tests/Core/Diagnostics/ConverterCaptureProbeTests.cs
  • tests/FanaBridge.Tests/Core/Diagnostics/FanatecSoftwareMonitorTests.cs
  • tests/FanaBridge.Tests/Core/Display/Catalog/ItmDeviceCatalogTests.cs
  • tests/FanaBridge.Tests/Core/Display/Protocol/ItmEncoderTests.cs
  • tests/FanaBridge.Tests/Core/Display/Protocol/ItmTelemetryTests.cs
  • tests/FanaBridge.Tests/Core/Display/Protocol/SevenSegmentTests.cs
  • tests/FanaBridge.Tests/Core/Display/Session/ItmLifecycleControllerTests.cs
  • tests/FanaBridge.Tests/Core/Leds/ColorHelperTests.cs
  • tests/FanaBridge.Tests/Core/Leds/LedEncoderTests.cs
  • tests/FanaBridge.Tests/Core/Leds/LegacyLedEncoderTests.cs
  • tests/FanaBridge.Tests/Core/Transport/Col03FrameClassifierTests.cs
  • tests/FanaBridge.Tests/Core/Transport/Col03QueueSetTests.cs
  • tests/FanaBridge.Tests/Core/Transport/FanatecTransportReaderTests.cs
  • tests/FanaBridge.Tests/Core/Transport/HidReportQueueTests.cs
  • tests/FanaBridge.Tests/Core/Transport/ReportElicitTests.cs
  • tests/FanaBridge.Tests/Core/Tuning/FanatecTuningControllerTests.cs
  • tests/FanaBridge.Tests/Plugin/ControlMapper/ControlMapperBridgeTests.cs
  • tests/FanaBridge.Tests/Plugin/ControlMapper/ControlMapperFakes.cs
  • tests/FanaBridge.Tests/Plugin/ControlMapper/FanaBridgeVariantProviderTests.cs
  • tests/FanaBridge.Tests/Plugin/Devices/DeviceRegistryOverrideTests.cs
  • tests/FanaBridge.Tests/Plugin/Devices/EnabledHidingProbeTests.cs
  • tests/FanaBridge.Tests/Plugin/Devices/EnabledNotificationProbeTests.cs
  • tests/FanaBridge.Tests/Plugin/Devices/FanatecWheelDeviceInstanceTests.cs
  • tests/FanaBridge.Tests/Plugin/Devices/SimHubDevicesGatewayTests.cs
  • tests/FanaBridge.Tests/Plugin/Diagnostics/FirmwareDecodeTests.cs
  • tests/FanaBridge.Tests/Plugin/Diagnostics/HidUsageTests.cs
  • tests/FanaBridge.Tests/Plugin/Display/Drivers/FanatecDisplayDriverTests.cs
  • tests/FanaBridge.Tests/Plugin/Display/Drivers/ItmDisplayDriverTests.cs
  • tests/FanaBridge.Tests/Plugin/Display/Drivers/ItmTelemetryMapperTests.cs
  • tests/FanaBridge.Tests/Plugin/Leds/FanatecLedDriverTests.cs
  • tests/FanaBridge.Tests/Plugin/Settings/FanatecDeviceSettingsTests.cs
  • tests/FanaBridge.Tests/Plugin/UI/Wizard/WizardStateTests.cs
  • tests/FanaBridge.Tests/README.md
  • tests/FanaBridge.Tests/TestDoubles/FakeLedModuleHost.cs
  • tests/FanaBridge.Tests/TestDoubles/FakeReportStream.cs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

kelchm added 3 commits August 8, 2026 23:01
…conformance, taxonomy clarification

Four XML doc crefs broken by the namespace moves are fully qualified
(doc generation is off, so no build warning fired). ILogSink splits out
of Log.cs into its conformant FanaBridge.Core.Logging home, shrinking
the root-namespace exception to exactly the physics-required Log type.
docs/architecture.md now states explicitly that domain folders are
navigational taxonomy, not directional boundaries — assembly references
are the only compiler-enforced direction.
…pragma allowlist

Two contract facts close the governance gaps in compiler-native layout
enforcement: IDE0130 trusts the mutable RootNamespace and compares
case-insensitively, so the four RootNamespace values are now pinned
ordinally; and pragma exceptions were self-service, so IDE0130 pragma
mentions are now a closed three-file allowlist with a dormancy check.
The XAML layout contract also gains the (WPF-capable) test project.
Both facts plant-verified. 751/751 green.
The IDE0130 allowlist scan now matches actual #pragma directives instead
of raw mentions, eliminating the Contracts/ directory exemption that let
new files there suppress the analyzer unchecked. The RootNamespace pin
now requires exactly one declaration per csproj — MSBuild evaluation is
last-one-wins, so a duplicate element could silently redefine the
effective value while the first-element check passed. Both fixes
plant-verified.
@kelchm
kelchm marked this pull request as ready for review August 9, 2026 12:55
@kelchm
kelchm merged commit 055aa45 into main Aug 9, 2026
2 checks passed
@kelchm
kelchm deleted the reorg/domains branch August 9, 2026 14:26
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.

Reorganize source and tests around domain-aligned namespaces

1 participant