One pluggable check in the demo's inspect pipeline. Mirrors Fix: each inspection declares which issue codes it can emit and a single run function that walks the SceneModel and returns the issues it found. Plays the role of an eslint rule.

Granularity is "topical concern", not "one rule per code" — a single inspection often emits several related codes from one walk (e.g. geometryDataIntegrity covers eight GEOMETRY_* codes that all derive from one pass over sceneModel.geometries).

Inspections that are expensive or domain-specific (e.g. duplicateGeometries) declare optIn and are skipped by inspectSceneModel unless the caller explicitly asks for them via the matching InspectSceneModelParams flag.

interface Inspection {
    codes: string[];
    config?: ConfigSchema;
    description: string;
    descriptions?: Record<string, string>;
    labels?: Record<string, string>;
    optIn?: boolean;
    paramsKey?: string;
    run(
        sceneModel: SceneModel,
        params: InspectSceneModelParams,
        index?: SceneModelInspectionIndex,
    ): inspect.sceneModel.Issue[];
}

Properties

codes: string[]

Issue codes this inspection can emit. Used by the registry as the "what does this rule contribute?" map and surfaced to UI code that wants to enumerate every possible code even when no issues have fired yet. The codes a run actually produces on a given SceneModel are a subset of this list.

config?: ConfigSchema

Optional declarative configuration schema — the list of tunable knobs (opt-in toggle, numeric thresholds, enumerated choices) this inspection exposes. When present, run is expected to consume resolveConfig(this.config, params) instead of pulling individual fields off params.

Carries enough metadata (labels, units, min/max, descriptions) for a UI to auto-render a settings form per inspection — the SceneHealthPanel's Inspections section walks every registered inspection's schema and renders the form, with no per-inspection UI code. Plugins that declare a schema inherit that UI for free.

Optional — inspections without a schema read fields directly off params.

description: string

Short human-readable label describing what the inspection looks for. Equivalent to Fix.description.

descriptions?: Record<string, string>

Optional plain-English descriptions of what each code means — a sentence or two explaining why the issue matters and what's wrong, suitable for surfacing in a "What is this?" pane next to a list of issues sharing one code.

Keyed by code. Resolve via descriptionForCode, which walks the registry the same way labelForCode does. Plugin inspections that introduce new codes ship their own descriptions here; no central table to coordinate against.

labels?: Record<string, string>

Optional human-readable labels for the Inspection.codes this inspection emits. Keyed by code, so a UI rendering an inspection's codes can show "Duplicate geometry · GEOMETRY_DUPLICATE" rather than the raw constant.

The matching helper labelForCode walks DEFAULT_INSPECTION_REGISTRY (or any custom registry) to find a code's label, falling back to the code itself when no label is registered. Plugin authors who add a custom inspection with new codes just declare their labels here — no central table to coordinate against.

optIn?: boolean

true when this inspection should run only if the caller explicitly enables it through InspectSceneModelParams. Defaults to false — most inspections are cheap data-integrity checks that always run.

Opt-in inspections read their toggle from params themselves — the orchestrator doesn't know which key is which. Convention: use a check… boolean (checkDuplicateGeometries, checkDenseGeometries, …).

paramsKey?: string

For opt-in inspections — the InspectSceneModelParams boolean key that gates the inspection's runtime behaviour (e.g. "checkDuplicateGeometries"). The inspection's own run reads params[paramsKey] to decide whether to do work; the orchestrator never reads it.

Purely metadata — surfaced for UIs that want to render a checkbox per inspection without hardcoding the param mapping. Always-on inspections leave this undefined.

Methods