FOCAS version-matrix stabilization (PR 1 of #220 split) #168

Merged
dohertj2 merged 1 commits from focas-version-matrix-stabilization into v2 2026-04-20 13:46:55 -04:00
Owner

Ships the cheap half of the hardware-free FOCAS stability gap ahead of Tier-C isolation. No CNC or simulator on the bench, so the highest-leverage move is to catch operator config errors at init time instead of at per-read steady-state.

What this PR lands

  • FocasCncSeries enum (Unknown / 16i / 0i-D / 0i-F family / 30i family / PowerMotion-i)
  • FocasCapabilityMatrix encoding per-series documented ranges for cnc_rdmacro/wrmacro, cnc_rdparam/wrparam, pmc_rdpmcrng/wrpmcrng
  • FocasDeviceOptions.Series knob (defaults Unknown = permissive so pre-matrix configs don't break on upgrade)
  • FocasDriver.InitializeAsync now parses every tag address + validates against the owning device's declared series
  • InvalidOperationException on mismatch with reason naming both the series + the documented limit (Parameter #30000 is outside the documented range [0, 29999] for Thirty_i)

Tests

  • 46 new theory cases in FocasCapabilityMatrixTests.cs covering macro / parameter / PMC-letter / PMC-number boundaries + permissive Unknown + rejection-message content + case-insensitive PMC-letter matching
  • Full FOCAS suite: 165/165 passing (119 existing + 46 new)
  • Every InlineData cites the matrix row it reflects — widening a range without updating docs/v2/focas-version-matrix.md fails a test

Docs

  • docs/v2/focas-version-matrix.md — authoritative matrix with per-function citations + CNC-series era context + error-surface shape
  • docs/v2/implementation/focas-isolation-plan.md — multi-PR plan for #220 Tier-C isolation (Shared contracts → Host skeleton → Fwlib32 move → Supervisor+respawn → MMF+ops glue; ~2200-3200 LOC mirroring Galaxy Tier-C)
  • docs/drivers/FOCAS-Test-Fixture.md — promoted from 'no version-matrix coverage' to explicit coverage + cross-links

Why ship now, before #220

Two independent wins: matrix catches operator typos today (per-read BadOutOfRange → per-config init-time failure with an actionable message); isolation closes the native-crash blast radius next. Shipping in one PR would bloat diff + delay the config-error feedback loop unnecessarily.

Scope NOT in this PR

  • Tier-C out-of-process Host (task #220 stays open; the plan doc is the bounded next step)
  • Integration fixture (no public FOCAS simulator; still blocked on lab rig per FOCAS-Test-Fixture.md §Follow-up)
  • New capability surfaces (tool management, alarm history) — matrix currently covers only macro/parameter/PMC as the driver exposes
Ships the cheap half of the hardware-free FOCAS stability gap ahead of Tier-C isolation. No CNC or simulator on the bench, so the highest-leverage move is to catch operator config errors at init time instead of at per-read steady-state. ## What this PR lands - `FocasCncSeries` enum (Unknown / 16i / 0i-D / 0i-F family / 30i family / PowerMotion-i) - `FocasCapabilityMatrix` encoding per-series documented ranges for `cnc_rdmacro`/`wrmacro`, `cnc_rdparam`/`wrparam`, `pmc_rdpmcrng`/`wrpmcrng` - `FocasDeviceOptions.Series` knob (defaults `Unknown` = permissive so pre-matrix configs don't break on upgrade) - `FocasDriver.InitializeAsync` now parses every tag address + validates against the owning device's declared series - `InvalidOperationException` on mismatch with reason naming both the series + the documented limit (`Parameter #30000 is outside the documented range [0, 29999] for Thirty_i`) ## Tests - 46 new theory cases in `FocasCapabilityMatrixTests.cs` covering macro / parameter / PMC-letter / PMC-number boundaries + permissive Unknown + rejection-message content + case-insensitive PMC-letter matching - Full FOCAS suite: **165/165 passing** (119 existing + 46 new) - Every `InlineData` cites the matrix row it reflects — widening a range without updating `docs/v2/focas-version-matrix.md` fails a test ## Docs - `docs/v2/focas-version-matrix.md` — authoritative matrix with per-function citations + CNC-series era context + error-surface shape - `docs/v2/implementation/focas-isolation-plan.md` — multi-PR plan for #220 Tier-C isolation (Shared contracts → Host skeleton → Fwlib32 move → Supervisor+respawn → MMF+ops glue; ~2200-3200 LOC mirroring Galaxy Tier-C) - `docs/drivers/FOCAS-Test-Fixture.md` — promoted from 'no version-matrix coverage' to explicit coverage + cross-links ## Why ship now, before #220 Two independent wins: matrix catches operator typos today (per-read `BadOutOfRange` → per-config init-time failure with an actionable message); isolation closes the native-crash blast radius next. Shipping in one PR would bloat diff + delay the config-error feedback loop unnecessarily. ## Scope NOT in this PR - Tier-C out-of-process Host (task #220 stays open; the plan doc is the bounded next step) - Integration fixture (no public FOCAS simulator; still blocked on lab rig per `FOCAS-Test-Fixture.md` §Follow-up) - New capability surfaces (tool management, alarm history) — matrix currently covers only macro/parameter/PMC as the driver exposes
dohertj2 added 1 commit 2026-04-20 13:46:41 -04:00
FOCAS version-matrix stabilization (PR 1 of #220 split) — ship the cheap half of the hardware-free stability gap ahead of the Tier-C out-of-process split. Without any CNC or simulator on the bench, the highest-leverage move is to catch operator config errors at init time instead of at steady-state per-read. Adds FocasCncSeries enum (Unknown/16i/0i-D/0i-F family/30i family/PowerMotion-i) + FocasCapabilityMatrix static class that encodes the per-series documented ranges for macro variables (cnc_rdmacro/wrmacro), parameters (cnc_rdparam/wrparam), and PMC letters + byte ceilings (pmc_rdpmcrng/wrpmcrng) straight from the Fanuc FOCAS Developer Kit. FocasDeviceOptions gains a Series knob (defaults Unknown = permissive so pre-matrix configs don't break on upgrade). FocasDriver.InitializeAsync now calls FocasAddress.TryParse on every tag + runs FocasCapabilityMatrix.Validate against the owning device's declared series, throwing InvalidOperationException with a reason string that names both the series and the documented limit ("Parameter #30000 is outside the documented range [0, 29999] for Thirty_i") so an operator can tell whether the mismatch is in the config or in their declared CNC model. Unknown series skips validation entirely. Ships 46 new theory cases in FocasCapabilityMatrixTests.cs — covering every boundary in the matrix (widen 16i->0i-F: macro ceiling 999->9999, param 9999->14999; widen 0i-F->30i: PMC letters +K+T; PMC-number 16i=999/0i-D=1999/0i-F=9999/30i=59999), permissive Unknown-series behavior, rejection-message content, and case-insensitive PMC-letter matching. Widening a range without updating docs/v2/focas-version-matrix.md fails a test because every InlineData cites the row it reflects. Full FOCAS test suite stays at 165/165 passing (119 existing + 46 new). Also authors docs/v2/focas-version-matrix.md as the authoritative range reference with per-function citations, CNC-series era context, error-surface shape, and the link back to the matrix code; docs/v2/implementation/focas-isolation-plan.md as the multi-PR plan for #220 Tier-C isolation (Shared contracts -> Host skeleton -> move Fwlib32 calls -> Supervisor+respawn -> MMF+ops glue, 2200-3200 LOC across 5 PRs mirroring the Galaxy Tier-C topology); and promotes docs/drivers/FOCAS-Test-Fixture.md from "version-matrix coverage = no" to explicit coverage via the new test file + cross-links to the matrix and isolation-plan docs. Leaves task #220 open since isolation itself (the expensive half) is still ahead. a6be2f77b5
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit 4a6fe7fa7e into v2 2026-04-20 13:46:55 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#168