Closes the non-hardware gap surfaced in the #220 audit: FOCAS had full Tier-C
architecture (Driver.FOCAS + Driver.FOCAS.Host + Driver.FOCAS.Shared, supervisor,
post-mortem MMF, NSSM scripts, 239 tests) but no factory registration, so config-DB
DriverInstance rows of type "FOCAS" would fail at bootstrap with "unknown driver
type". Hardware-gated FwlibHostedBackend (real Fwlib32 P/Invoke inside the Host
process) stays deferred under #222 lab-rig.
Ships:
- FocasDriverFactoryExtensions.Register(registry) mirroring the Galaxy pattern.
JSON schema selects backend via "Backend" field:
"ipc" (default) — IpcFocasClientFactory → named-pipe FocasIpcClient →
Driver.FOCAS.Host process (Tier-C isolation)
"fwlib" — direct in-process FwlibFocasClientFactory (P/Invoke)
"unimplemented" — UnimplementedFocasClientFactory (fail-fast on use —
useful for staging DriverInstance rows pre-Host-deploy)
- Devices / Tags / Probe / Timeout / Series feed into FocasDriverOptions.
Series validated eagerly at top-level so typos fail at bootstrap, not first
read. Tag DataType + Series enum values surface clear errors listing valid
options.
- Program.cs adds FocasDriverFactoryExtensions.Register alongside Galaxy.
- Driver.FOCAS.csproj references Core (for DriverFactoryRegistry).
- Server.csproj adds Driver.FOCAS ProjectReference so the factory type is
reachable from Program.cs.
Tests: 13 new FocasDriverFactoryExtensionsTests covering: registry entry,
case-insensitive lookup, ipc backend with full config, ipc defaults, missing
PipeName/SharedSecret errors, fwlib backend short-path, unimplemented backend,
unknown-backend error, unknown-Series error, tag missing DataType, null/ws args,
duplicate-register throws.
Regression: 202 FOCAS + 13 FOCAS.Host + 24 FOCAS.Shared + 239 Server all pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>