Logo FS-Skia-UI

Compatibility Package Analysis

This report expands phase 5 from the refactoring analysis: decide what to do with the FS.Skia.UI compatibility package after the lower-risk cleanup phases are complete. The package is a meaningful design problem because it is both a public surface and a historical container for capabilities that now have more focused packages.

The recommendation is not to restructure the package during the first behavior-preserving refactor. Treat compatibility package direction as its own design feature with explicit consumer inventory, migration policy, package surface evidence, and release notes.

Executive Position

FS.Skia.UI should remain stable until the repository can answer three questions with evidence:

  1. Which current consumers still open FS.Skia.UI directly?
  2. Which public types in FS.Skia.UI are compatibility aliases, and which are still the only available public contract for a capability?
  3. Is the intended future of FS.Skia.UI to be a permanent broad package, a facade over split packages, or a deprecated migration bridge?

The safest near-term decision is to keep the package as a compatibility surface, stop adding new primary concepts to it unless compatibility requires them, and move new authoring guidance toward the focused packages. That preserves existing consumers while preventing the compatibility package from becoming the default home for new framework work.

Current Package Shape

The package project is src/Lib/Lib.fsproj. It produces the package identity FS.Skia.UI and assembly name FS.Skia.UI.

The current compile set is:

File

Role

InternalsVisibleTo.fs

Test and internal access policy.

VulkanResources.fsi and VulkanResources.fs

Vulkan resource contracts and implementation.

VulkanStartup.fsi and VulkanStartup.fs

Vulkan startup contracts and implementation.

Library.fsi and Library.fs

Broad public UI, scene, viewer, diagnostics, parity, and runtime surface.

KeyboardInput.fsi and KeyboardInput.fs

Compatibility keyboard input surface and implementation.

The package references Fable.Elmish, Silk.NET window/input/Vulkan packages, SkiaSharp native assets, and YamlDotNet. That dependency set is much broader than the newer focused authoring packages need.

The focused packages already separate major responsibilities elsewhere:

Focused package

Current role

FS.Skia.UI.Scene

Immutable scene primitives and deterministic evidence.

FS.Skia.UI.SkiaViewer

Viewer host, persistent window behavior, screenshot and visual evidence.

FS.Skia.UI.Elmish

Elmish integration for viewer programs.

FS.Skia.UI.KeyboardInput

Keyboard runtime, command configuration, diagnostics, and state display.

FS.Skia.UI.Layout

Layout evaluation and graph layout support.

FS.Skia.UI.Controls

Controls, charts, graph views, DataGrid, and rich rendering.

FS.Skia.UI.Controls.Elmish

Controls-specific Elmish adapter.

FS.Skia.UI.Testing

Generated product validation and evidence helpers.

This means FS.Skia.UI is no longer the only logical package boundary for most capabilities, but it may still be the easiest package for older samples, consumers, or compatibility smoke tests.

Why Phase 5 Must Be Separate

Compatibility work carries a different risk profile from file extraction. Moving internals behind unchanged signatures is mostly a maintainability exercise. Changing what FS.Skia.UI means is a product and ecosystem decision.

Phase 5 affects:

Those concerns need explicit acceptance criteria. They should not ride along with template cleanup, build script decomposition, or viewer internal module splits.

Consumer Inventory Needed

Before choosing a direction, collect a concrete inventory of current usage.

Repository Consumers

Known repository references include:

Consumer

Current signal

samples/BasicViewer

References src/Lib/Lib.fsproj locally and package FS.Skia.UI for packaged mode, then opens FS.Skia.UI.

samples/ScreenshotGallery

References src/Lib/Lib.fsproj locally and package FS.Skia.UI for packaged mode.

Documentation

Architecture and subsystem docs describe src/Lib as the compatibility core package.

Older design docs

V3 design material frames split packages as the preferred long-term structure.

The next pass should produce a table of every repository ProjectReference, PackageReference, namespace open, sample, template fragment, and docs page that still depends on FS.Skia.UI.

External Consumers

External usage is harder to prove from the repository. The design decision should still define a migration posture for unknown consumers:

Public Surface Classification

The compatibility package should be classified member-by-member before any migration plan is accepted. A useful classification is:

Classification

Meaning

Default action

Primary-only compatibility member

Public member exists only in FS.Skia.UI.

Keep until a focused replacement exists and is documented.

Duplicate of focused package concept

Public member has an equivalent in a focused package.

Prefer focused package for new docs; keep compatibility member stable.

Facade candidate

Compatibility member can delegate to a focused package without behavior change.

Consider internal delegation after tests prove parity.

Deprecated candidate

Member has a better replacement and low active usage.

Deprecate only with migration guidance and surface evidence.

Permanent compatibility surface

Member is intentionally retained for old consumers.

Document as compatibility-owned and freeze semantics.

This inventory matters because the file size in Library.fs is not enough evidence to remove or migrate public members. Large public files can still represent valid compatibility commitments.

Strategic Options

Option A: Keep FS.Skia.UI As A Permanent Broad Package

Under this option, FS.Skia.UI remains a fully supported package that exposes a large integrated surface. Focused packages still exist for lighter consumers, but the broad package is not deprecated.

Advantages:

Costs:

This option is reasonable if external compatibility matters more than package minimalism. It still needs a rule that new primary concepts start in focused packages unless the broad package intentionally re-exports them.

Option B: Make FS.Skia.UI A Facade Over Focused Packages

Under this option, FS.Skia.UI remains the public package identity but its implementation delegates to or re-exports focused package concepts where possible.

Advantages:

Costs:

This is likely the best long-term direction if type identity and dependency direction can be handled cleanly. It should start with low-risk delegation behind unchanged signatures, not with public type substitution.

Option C: Deprecate FS.Skia.UI In Favor Of Focused Packages

Under this option, FS.Skia.UI becomes a migration bridge and new users are directed to focused packages only.

Advantages:

Costs:

This option should not be chosen until replacement docs, samples, and package surface baselines prove that focused packages cover the current compatibility scenarios.

Option D: Freeze FS.Skia.UI And Move Only New Work Elsewhere

Under this option, the compatibility package remains supported but receives no new primary capabilities unless needed to preserve existing behavior. Focused packages become the home for new authoring.

Advantages:

Costs:

This is the recommended next posture before a full phase 5 design project. It does not solve the compatibility package, but it stops making the problem worse.

Recommended Decision Path

Use a staged decision, not a one-step migration.

Stage 1: Freeze And Inventory

Keep FS.Skia.UI behavior stable. Add no new primary feature surface to the compatibility package unless a compatibility scenario requires it.

Produce:

Acceptance:

Stage 2: Replacement Coverage

For each compatibility capability, identify whether a focused package already covers it.

Produce:

Acceptance:

Stage 3: Facade Feasibility

Try internal delegation for low-risk areas where public signatures can remain unchanged.

Acceptance:

Stage 4: Deprecation Decision

Only after replacement coverage and facade feasibility are known, decide whether to keep, facade, or deprecate FS.Skia.UI.

Acceptance:

Technical Risk Areas

Type Identity

F# records and discriminated unions with the same fields are still different types when they come from different assemblies or namespaces. A migration from FS.Skia.UI.Rect to FS.Skia.UI.Scene.Rect is not just a namespace edit unless the public contract is designed around aliases or conversion helpers.

Risk response:

Dependency Direction

The broad package currently owns a wide dependency set. A facade strategy could make FS.Skia.UI depend on focused packages, but focused packages must not depend back on FS.Skia.UI in a way that creates cycles or makes the split meaningless.

Risk response:

Runtime Behavior

The compatibility package includes Vulkan startup, viewer behavior, diagnostics, and keyboard input. Even if focused packages offer equivalent capabilities, old runtime behavior may have exact diagnostic text, unsupported-host behavior, or startup failure semantics that tests and users rely on.

Risk response:

Documentation Drift

If docs call FS.Skia.UI both "core" and "compatibility", users will receive conflicting guidance.

Risk response:

Evidence Required For A Phase 5 Feature

A future phase 5 implementation plan should require these readiness artifacts:

Evidence file

Purpose

readiness/compatibility-consumer-inventory.md

Lists repository consumers and package/reference usage.

readiness/compatibility-public-surface-map.md

Classifies public members and replacement coverage.

readiness/compatibility-dependency-report.md

Shows dependency closure before and after any change.

readiness/compatibility-sample-migration.md

Demonstrates representative sample migration paths.

readiness/compatibility-surface-baseline.md

Records package surface baseline status and intentional differences.

readiness/compatibility-release-policy.md

States whether the package is kept, facaded, frozen, or deprecated.

These artifacts should be real review inputs. A phase 5 plan should not rely on "file got smaller" as proof of a correct compatibility decision.

Acceptance Criteria For Compatibility Work

Compatibility package work is acceptable only when:

Anti-Goals

Do not use compatibility package review to:

Final Recommendation

For the current refactoring feature, phase 5 should remain deferred. The next responsible action is to freeze the compatibility package as a compatibility surface, inventory its consumers and public members, and direct new authoring guidance toward focused packages.

After generated evidence cleanup, template splitting, build decomposition, and viewer internal boundaries are stable, open a dedicated compatibility package feature. That feature should decide between permanent broad package, facade, freeze, or deprecation based on consumer inventory and replacement coverage, not on file size alone.

Type something to start searching.