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>
This commit is contained in:
2026-07-20 19:04:25 +02:00
parent d6cf5f3d36
commit 899028e20f
43 changed files with 811 additions and 1558 deletions
+4 -4
View File
@@ -5,14 +5,14 @@
// `enumerateTitles` is factored out so the orchestrator can learn which titles need art (and warm the
// cache) BEFORE the final `computeDesired`, without re-implementing the exclude/dedupe rules.
import type { Artwork, ProviderEntry } from "@punktfunk/plugin-kit/wire";
import type { Config, GameOverride } from "@rom-manager/contract";
import type { ArtVerdict } from "../art/provider.js";
import { killPrep } from "./close.js";
import { type DetectedEmulator, resolveEmulators } from "./emulators.js";
import { type EffectiveLaunch, resolveLaunch } from "./launch.js";
import { type Platform, resolvePlatforms } from "./platforms.js";
import type { Os } from "./quote.js";
import type { ArtVerdict } from "../art/provider.js";
import type { Artwork, ProviderEntry } from "@punktfunk/plugin-kit/wire";
import { killPrep } from "./close.js";
import { type EffectiveLaunch, resolveLaunch } from "./launch.js";
import type { RomCandidate } from "./scanner.js";
import {
dedupeKey,