Add a new adapter, persist it, and (if enabled) start it. Returns its new id.
enabled defaults to true.
Start an enabled entry WITHOUT persisting — the watchdog's attach when the device
appears. A disabled or already starting/running entry is left alone. Returns the
resulting status (error surfaces a failed bring-up to the caller's throttle).
The persisted half of one adapter, or absence — /adapter/{id}'s one read.
The PERSISTED half of every adapter, in config order — /adapter's one read.
Stop an entry WITHOUT persisting — the watchdog's clean detach when the device
vanishes. enabled stays true in the config, so the entry re-attaches when the
device is back.
The offer set as it stands — what the LAST sweep found present-but-unconfigured.
The store behind /surface/detected, and the reason there is only one: two things sweep
(the watchdog on its cadence, the /surface/autodetect operation on an operator's fire) and
before 2026-08-15 each published its own answer — the watchdog broadcast surface.detected,
the operation carried the set in its landing report. A client that fired the probe and one
that merely plugged a surface in learned the same fact two ways, with nothing making them
agree. Now both go through detectSurfaces, which writes HERE, and the row is the one
address either of them converges on.
Synchronous on purpose: a row read must not wait on hardware. [] before the first sweep is
the honest answer — nothing has been offered yet.
The NEW surfaces on the rig: every registered kind: 'surface' type that is physically
present but has NO config entry yet. Probes cold, against the schema's field defaults
(the same settings a fresh adapter.add with no overrides would produce).
Read-only and OFFER-ONLY: never mutates or persists anything, and never auto-adds — the
operator confirms via the ordinary add() call. A throwing probe (the probe contract
says never, but stay defensive) reads as absent, not an error.
A type the operator has ALREADY configured is skipped: the watchdog owns presence for configured entries, and re-offering a surface that is merely unplugged would be noise where the missing-hardware alarm is the honest signal. This per-type rule replaces the old first-run gate (hasConfiguredSurface), which silenced detection entirely once any one surface existed — so an X-Touch plugged in on a rig that already had some other surface configured was never noticed at all.
True once at least one kind: 'surface' entry is configured — the first-run gate
for detectSurfaces. Autodetect only makes sense before the operator has
configured any surface at all; once one exists, the watchdog (not a fresh scan)
owns presence.
The current adapters + their live status. Async: a type's AdapterInstance.detail
(e.g. the reac adapter's honest link state, issue #217) is read FRESH per entry, never
cached, so every adapter.list reply reflects the current live state, not the state at
start().
Read the config file and instantiate + start every enabled adapter. A missing
file is treated as an empty set (first run). Returns the current status list.
Ids of entries whose registered type carries a presence probe.
Run the type's presence probe against entry id's settings. undefined when the
type has no probe. Never throws for a probeable type (the probe contract).
Re-read every instance's AdapterInstance.detail and record it. Returns the ids
whose detail CHANGED — the caller re-projects exactly those /adapter/{id}/status rows,
the same changed-flag contract setPresence has.
Register (or replace) an adapter type's factory + settings schema.
Stop, remove, and persist the removal of adapter id.
Record a probed presence. Returns whether the value changed (drives broadcasts).
The LIVE half of one adapter, synchronously — /adapter/{id}/status's one read. detail
is the last observed value (see Entry.detail); everything else is current.
Stop every running adapter (e.g. on server shutdown). Does not persist.
The configured CONTROL SURFACES (a kind: 'surface' adapter — an X-Touch etc.) with
their live presence, for the session hardware manifest (issue #154): the manifest records
these as expected, and the restore diff flags one whose present is not true.
The settings schema for each registered type — drives adapter.types.
Update an existing adapter's settings (and optionally its enabled flag),
persist, and restart it to apply. Returns the new status report.
Optionalenabled: boolean
Owns the adapter registry, the live instances, and the config file.