LabKit MATLAB Workbench

history

Explicit layout action contract

id: LK-20260717-explicit-layout-action-contract
date: 2026-07-17
sequence: 123
type: refactor
compatibility: compatible
component: `labkit_DICPostprocess_app` | `1.4.5 -> 1.4.6`
component: `labkit_DICPreprocess_app` | `1.5.6 -> 1.5.7`
component: `labkit_ChronoOverlay_app` | `1.4.6 -> 1.4.7`
component: `labkit_CIC_app` | `1.4.6 -> 1.4.7`
component: `labkit_CSC_app` | `1.4.6 -> 1.4.7`
component: `labkit_EIS_app` | `1.4.6 -> 1.4.7`
component: `labkit_VTResistance_app` | `1.4.6 -> 1.4.7`
component: `labkit_GaitAnalysis_app` | `2.0.6 -> 2.0.7`
component: `labkit_BatchImageCrop_app` | `1.7.5 -> 1.7.6`
component: `labkit_CurvatureMeasurement_app` | `1.4.5 -> 1.4.6`
component: `labkit_FLIRThermal_app` | `1.4.5 -> 1.4.6`
component: `labkit_FocusStack_app` | `1.5.4 -> 1.5.5`
component: `labkit_ImageEnhance_app` | `1.6.5 -> 1.6.6`
component: `labkit_ImageMatch_app` | `1.6.5 -> 1.6.6`
component: `labkit_VideoMarker_app` | `1.5.5 -> 1.5.6`
component: `labkit_FigureStudio_app` | `0.2.7 -> 0.2.8`
component: `labkit_NerveResponseAnalysis_app` | `1.4.5 -> 1.4.6`
component: `labkit_ResponseReviewStats_app` | `1.4.5 -> 1.4.6`
component: `labkit_RHSPreview_app` | `1.4.5 -> 1.4.6`
component: `labkit_ECGPrint_app` | `1.4.5 -> 1.4.6`
scope: Runtime V2 layout callback resolution
scope: public App maintenance cost

Context

Every public App layout carried the same local callbackValue helper. The helper returned an empty value when a callback field was absent, so a misspelled or unregistered action could survive startup as a control that silently did nothing. Twenty copies also obscured that Runtime already creates the complete callback table from each App definition.

Decision and rationale

Layouts reference Runtime-generated callbacks directly. MATLAB field access therefore validates the action ID while the data-only layout is built. Runtime remains the single callback-adapter owner; Apps own only their semantic action registries and layout references.

Changes

User and data impact

Correctly registered controls behave as before. A broken App definition now fails during layout construction instead of presenting an inert control. No scientific calculation, project payload, saved file, or interaction semantics changed.

Compatibility and migration

No project migration is required. This is an App-development contract tightening: custom layouts must register every referenced semantic action.

Validation

The focused fleet contract builds every public App layout and catches missing or misspelled callback fields. The App package guardrail rejects reintroduced silent callback fallbacks, and focused workflow-layout tests cover direct construction outside a running figure.

Evidence

Known limitations and follow-up

This change deliberately does not merge short semantic actions or dynamic control helpers merely to reduce line count. Those remain candidates only when a repeated behavior has one stable, domain-neutral owner.