# Selkie 1.0 API Surface Audit

Last updated: 2026-06-25.

This document classifies the currently shipped modules before the 1.0 API
freeze. The default policy is minimum breakage: keep existing public-looking
modules unless they are unsafe or misleading, add compatibility aliases for
unavoidable renames when feasible, and migrate first-party consumers in the
same branch as any intentional break.

## Stable 1.0 Candidates

These are expected to remain public, with only compatibility-preserving changes
unless a concrete production issue is found.

- `Selkie`
- `Selkie::App`
- `Selkie::Container`
- `Selkie::Event`
- `Selkie::ScreenManager`
- `Selkie::Sizing`
- `Selkie::Store`
- `Selkie::Style`
- `Selkie::Theme`
- `Selkie::Widget`
- `Selkie::Layout::HBox`
- `Selkie::Layout::Split`
- `Selkie::Layout::VBox`
- `Selkie::Widget::Border`
- `Selkie::Widget::Button`
- `Selkie::Widget::CardList`
- `Selkie::Widget::Checkbox`
- `Selkie::Widget::CommandPalette`
- `Selkie::Widget::ConfirmModal`
- `Selkie::Widget::FileBrowser`
- `Selkie::Widget::HelpOverlay`
- `Selkie::Widget::Image`
- `Selkie::Widget::ListView`
- `Selkie::Widget::Modal`
- `Selkie::Widget::MultiLineInput`
- `Selkie::Widget::ProgressBar`
- `Selkie::Widget::RadioGroup`
- `Selkie::Widget::RichText`
- `Selkie::Widget::RichText::Span`
- `Selkie::Widget::ScrollView`
- `Selkie::Widget::Select`
- `Selkie::Widget::Spinner`
- `Selkie::Widget::TabBar`
- `Selkie::Widget::Table`
- `Selkie::Widget::Text`
- `Selkie::Widget::TextInput`
- `Selkie::Widget::TextStream`
- `Selkie::Widget::Toast`
- `Selkie::Widget::ViewportedCardList`

## Selkie::App Facade

`Selkie::App` is now the stable entry point over internal helpers under
`Selkie::App::Internal::*`. Before 1.0, review these public methods and
attribute accessors as the intended facade surface:

- Lifecycle and loop: `run`, `quit`, `shutdown`
- Terminal: `stdplane`, `set-title`, `build-title-osc`,
  `build-terminal-cleanup-sequence`, `set-error-log`, `error-log`
- Screens and theme: `theme`, `store`, `screen-manager`, `root`,
  `set-theme`, `add-screen`, `switch-screen`
- Focus and events: `focused`, `event-supply`, `focus`, `focus-next`,
  `focus-prev`, `widget-attached`, `check-focus-invariant`, `on-key`,
  `on-frame`, `on-resize`
- Overlays: `toast`, `show-modal`, `close-modal`, `has-modal`
- Input/render helpers: `widget-at-in`, `detect-sprixel-bug-prone-terminal`,
  `force-refresh-sprixels`, `hot-hz`, `sprixel-refresh-idle-threshold`
- Package helper: `Selkie::App::pick-frame-budget`

## Contract Sweep Decisions

Reviewed on 2026-06-25 without doing the full method/export inventory.
The following names are deliberate enough to keep unless the final 1.0
inventory finds a concrete production issue:

- Keep `Selkie::Store.register-handler` for event handlers and
  `register-fx` for effect handlers. The `fx` abbreviation matches the
  store's re-frame vocabulary and has broad first-party/downstream usage.
- Keep all four subscription entry points:
  `subscribe`, `subscribe-path-callback`, `subscribe-computed`, and
  `subscribe-with-callback`. The path forms are push-indexed; the computed
  forms are pull-checked. The callback suffix names the side-effecting forms.
- Keep `mark-dirty`, `mark-dirty-tree`, and `mark-screen-dirty`.
  `mark-screen-dirty` is documented as the root-walk + descendant-cascade path,
  not just another spelling of `mark-dirty`.
- Keep the layout vocabulary split: `reposition` moves the local plane,
  `set-viewport` updates absolute/visible viewport metadata from parent
  layouts, and `handle-resize` is the terminal/layout resize cascade.
- Keep current reviewed defaults: subscription change detection remains
  structural by default with `:identity-check-only` as an opt-out; modal and
  border `set-content` destroy old content by default; App title tmux wrapping
  is opt-in; toast duration defaults to 2 seconds; async drain timeout defaults
  to 5 seconds; mouse button handlers default to primary button 1.

## Stable But Opt-In

These are shipped and documented, but are not imported by the umbrella
`use Selkie;` path. Keep them public unless the chart API gets a deliberate
pre-1.0 redesign.

- `Selkie::Plot::Palette`
- `Selkie::Plot::Scaler`
- `Selkie::Plot::Ticks`
- `Selkie::Widget::Axis`
- `Selkie::Widget::BarChart`
- `Selkie::Widget::Heatmap`
- `Selkie::Widget::Histogram`
- `Selkie::Widget::Legend`
- `Selkie::Widget::LineChart`
- `Selkie::Widget::Plot`
- `Selkie::Widget::ScatterPlot`
- `Selkie::Widget::Sparkline`

## Experimental Or Support Surface

These modules are useful, but should not be treated as frozen until they have
explicit narrative docs and downstream usage checks.

- `Selkie::EffectiveBounds`
- `Selkie::Layout::Allocate`
- `Selkie::Trace`
- `Selkie::Tree`
- `Selkie::Widget::FocusableByDefault`
- `Selkie::Widget::PasswordStrength`
- `Selkie::Test::Focus`
- `Selkie::Test::Keys`
- `Selkie::Test::Snapshot`
- `Selkie::Test::Snapshot::Harness`
- `Selkie::Test::Store`
- `Selkie::Test::Supply`
- `Selkie::Test::Tree`

## Internal Implementation Surface

These modules are installed so `Selkie::App` resolves correctly from a packaged
distribution, but they are explicitly not part of the 1.0 compatibility
contract. Consumers should use `Selkie::App`.

- `Selkie::App::Internal::ErrorLog`
- `Selkie::App::Internal::Dispatch`
- `Selkie::App::Internal::FocusTree`
- `Selkie::App::Internal::HitTest`
- `Selkie::App::Internal::IdleBudget`
- `Selkie::App::Internal::OverlayTree`
- `Selkie::App::Internal::RenderLoop`
- `Selkie::App::Internal::ScreenModalLifecycle`
- `Selkie::App::Internal::Terminal`
- `Selkie::App::Internal::TerminalSequences`

## Theme Surface

Required core slots:

- `base`
- `border`
- `border-focused`
- `text`
- `text-dim`
- `text-highlight`
- `input`
- `input-focused`
- `input-placeholder`
- `scrollbar-track`
- `scrollbar-thumb`
- `divider`
- `tab-active`
- `tab-inactive`

Defaulted UI slots added for the production-readiness cleanup:

- `control-focused`
- `selection`
- `dropdown`
- `dropdown-highlight`
- `overlay-title`
- `overlay-key`
- `modal-backdrop`
- `toast`
- `password-empty`
- `password-weak`
- `password-fair`
- `password-good`
- `password-strong`
- `password-very-strong`

Defaulted chart slots:

- `graph-axis`
- `graph-axis-label`
- `graph-grid`
- `graph-line`
- `graph-fill`
- `graph-legend-bg`

`Selkie::Widget::PasswordStrength` uses the password band slots above and
`text-dim` for the unfilled bar. `level-for` reports the current band as a
theme slot name so consumers can reuse the framework palette without depending
on raw RGB constants.

## Event And Effect Names

Public event/effect names are part of the 1.0 compatibility contract once
documented. The core Store payload shapes are documented in
`Selkie::Store` Pod as of 2026-06-25:

- Focus events: `ui/focus`, `ui/focus-next`, `ui/focus-prev`
- Built-in Store effects: `db`, `db-replace`, `db-delete`, `dispatch`, `async`
- Error isolation event: `__effect-error`
- Store effect names still to audit if/when they ship: `batch`, `tick`, `timer`

Avoid renames unless the current name is unsafe or materially misleading. If a
rename is unavoidable, keep a compatibility alias through the final 0.x series
where feasible.

## Removal Notes

No public module is approved for removal by this audit pass. Confirmed private
dead code removed on 2026-06-19:

- `Selkie::Store.!debug-log-enabled`
- `Selkie::Widget::MultiLineInput.!move-left`
- `Selkie::Widget::MultiLineInput.!move-right`
- `Selkie::Widget::MultiLineInput.!move-word-left`
- `Selkie::Widget::MultiLineInput.!move-word-right`
- `Selkie::Widget::ViewportedCardList.!update-content-height`
