Commit Graph

5 Commits

Author SHA1 Message Date
enricobuehler 94f18e38b4 fix: the API emitted undefined optionals as null, and the UI couldn't decode them (v0.3.2)
CI / publish (push) Successful in 22s
CI / build (push) Successful in 34s
`Schema.optional(X)` means `X | undefined`, and the plain Schema encoder omits a
present-but-undefined key — but the HttpApi RESPONSE path serialises it as
`null`, which `X | undefined` then refuses when the client decodes it. Two
user-visible failures shipped in 0.3.1:

  - GET /api/status on a never-synced host returned `"lastSync":null`, so the
    Overview page could not decode its own status — i.e. every fresh install
    until the first successful sync.
  - POST /api/detect on a box with any emulator installed returned
    `"contested":null` / `"appId":null`, so the Emulators page's Detect button
    could not decode the result. It only looked fine because a value that has
    round-tripped through cache.json has those keys ABSENT rather than present
    -and-undefined, and absent keys encode correctly.

Nothing on this wire is `undefined` any more. EngineStatus.{lastSync,lastReport,
detectedAt} are `Schema.NullOr` and the engine sends explicit nulls. The
DetectedEmulator fields use `Schema.optional(Schema.NullOr(...))` instead —
tolerant of absent, undefined and null — because they also live in cache.json,
and requiring them would fail the whole cache decode on upgrade and silently
discard every art verdict.

plugin/test/wire.test.ts pins it: it drives the real makeApi handler stack
through toWebHandler and decodes the bytes with the shared contract schemas.
Against the old schema all five of its assertions fail; a unit test of either
side in isolation passes while the product is broken.

Also: the SSE feed now emits the current status on subscribe rather than only on
the next engine transition, so a freshly-opened console page is correct
immediately instead of stale until something happens.
2026-07-20 23:36:01 +02:00
enricobuehler d830b7133d fix: SSE keepalive via plugin-kit 0.1.4 (v0.3.1)
CI / publish (push) Failing after 28s
CI / build (push) Successful in 37s
Live-verified against a running host: status frames (including a syncing
transition) now stream through the plugin UI server. The previous keepalive
outlived Bun's default idle timeout, so an idle feed was closed before its
first ping.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 20:01:29 +02:00
enricobuehler 838cdc4339 fix(ui): inherit the theme collision fixes from plugin-kit 0.1.3
CI / publish (push) Failing after 22s
CI / build (push) Successful in 35s
The text-secondary re-point moved into the kit's theme.css (every plugin hits
it), joined there by the card-ring softening the console does in its own Card
wrapper. The SPA's stylesheet is back to imports only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 19:50:00 +02:00
enricobuehler 899028e20f feat: Effect services + HttpApi implementation + kit entry/CLI/dev server
- RomConfig/RomCache on the kit's ConfigService/CacheStore; RomSync wires the
  pure domain into the kit SyncEngine (poll/watch/coalesce/fingerprint) and
  ProviderClient; EngineStatus assembly shared by REST + SSE
- makeApi: HttpApiBuilder groups over live service values (handler runtime
  shares the plugin runtime's singletons) + sseRoute status feed
- index.ts: definePluginKit entry (async-main boundary); headless-first (UI
  serve failure logged, engine continues)
- cli.ts on the kit dispatcher: scan/detect/preview offline, sync/uninstall
  online; set-password is gone with the standalone server
- dev.ts: auth-free loopback API server (:5885) — the dev:live proxy target;
  never bundled
- verified live host-less: raw config round-trip on disk, status/platforms/
  preview endpoints, soft-fail reconcile without a host
- CI: workspace install, per-package typecheck, publish from plugin/

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 19:04:25 +02:00
enricobuehler d6cf5f3d36 refactor: workspace restructure — contract package + pure domain ported, tests green
- bun workspaces: contract/ (Schemas = source of truth: config raw↔resolved,
  domain DTOs, HttpApi contract, API errors) + plugin/ + ui/
- pure domain moved src/{engine,art}→plugin/src/{domain,art}, types now
  imported from @rom-manager/contract and @punktfunk/plugin-kit/wire (the
  hand-copied wire.ts dies), loggers injected instead of module-global
- ui.* and devEntry dropped from the config shape (standalone server is
  gone; stale keys tolerated on decode, dropped by the next save)
- all 48 domain tests ported and green BEFORE any Effect wiring

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 18:54:38 +02:00