summaryrefslogtreecommitdiffhomepage
path: root/.dispatch/ui-contract.reference.md
diff options
context:
space:
mode:
Diffstat (limited to '.dispatch/ui-contract.reference.md')
-rw-r--r--.dispatch/ui-contract.reference.md169
1 files changed, 169 insertions, 0 deletions
diff --git a/.dispatch/ui-contract.reference.md b/.dispatch/ui-contract.reference.md
new file mode 100644
index 0000000..3962fc1
--- /dev/null
+++ b/.dispatch/ui-contract.reference.md
@@ -0,0 +1,169 @@
+# `@dispatch/ui-contract` — in-repo reference (read THIS, not node_modules)
+
+> This MIRRORS the backend's `@dispatch/ui-contract` package source so headless FE agents can
+> read the surface contract WITHOUT following the `file:` dep symlink out of this repo (which
+> hangs on a permission prompt). Your CODE still imports `@dispatch/ui-contract` normally — this
+> file is for READING only.
+>
+> **Orchestrator:** this is a SNAPSHOT — regenerate it whenever `ui-contract` changes.
+
+```ts
+/**
+ * UI contract — the frontend-agnostic vocabulary for backend-declared "surfaces".
+ *
+ * A SURFACE is a "data transportation surface": a typed description of what data an
+ * extension exposes, its semantics, and the actions that can act on it — NOT UI.
+ * Any client renders a surface in its own idiom (web/Svelte, CLI, future TUI/mobile).
+ * Types-only, zero runtime, zero `@dispatch/*` deps.
+ */
+
+/** Where a surface mounts — a coarse, semantic placement hint, NOT layout/CSS. Open string. */
+export type Region = string;
+
+/** A typed reference to a backend action a field can invoke (client posts payload back). */
+export interface ActionRef {
+ readonly actionId: string;
+}
+
+/** One selectable option in a `selector` field. */
+export interface SurfaceOption {
+ readonly value: string;
+ readonly label: string;
+}
+
+/** A field within a surface — a SEMANTIC value, not a widget. `kind` is the discriminant. */
+export type SurfaceField =
+ | ToggleField
+ | ProgressField
+ | SelectorField
+ | StatField
+ | ButtonField
+ | CustomField;
+
+/** A boolean setting plus the action that flips it. */
+export interface ToggleField {
+ readonly kind: "toggle";
+ readonly label: string;
+ readonly value: boolean;
+ readonly action: ActionRef;
+}
+
+/** A bounded ratio in [0, 1] with a label. Read-only. */
+export interface ProgressField {
+ readonly kind: "progress";
+ readonly label: string;
+ readonly value: number;
+}
+
+/** An enum choice: the current value, the options, and the action that sets it. */
+export interface SelectorField {
+ readonly kind: "selector";
+ readonly label: string;
+ readonly value: string;
+ readonly options: readonly SurfaceOption[];
+ readonly action: ActionRef;
+}
+
+/** A read-only labelled scalar readout. */
+export interface StatField {
+ readonly kind: "stat";
+ readonly label: string;
+ readonly value: string;
+}
+
+/** A labelled action trigger. */
+export interface ButtonField {
+ readonly kind: "button";
+ readonly label: string;
+ readonly action: ActionRef;
+}
+
+/**
+ * The escape hatch: data that fits no semantic field kind. Opaque `payload` + a
+ * `rendererId`; clients WITH a renderer for that id show it, others GRACEFULLY SKIP.
+ */
+export interface CustomField {
+ readonly kind: "custom";
+ readonly rendererId: string;
+ readonly payload: unknown;
+}
+
+/** A surface: an ordered set of fields mounted in a region, with a title. */
+export interface SurfaceSpec {
+ readonly id: string;
+ readonly region: Region;
+ readonly title: string;
+ readonly fields: readonly SurfaceField[];
+}
+
+/** A surface-catalog entry — discovery metadata only (no field data). */
+export interface SurfaceCatalogEntry {
+ readonly id: string;
+ readonly region: Region;
+ readonly title: string;
+}
+
+/** The surface catalog: the list of available surfaces a client can choose to show. */
+export type SurfaceCatalog = readonly SurfaceCatalogEntry[];
+
+/** A live update for a subscribed surface. v1 carries the full new spec. */
+export interface SurfaceUpdate {
+ readonly surfaceId: string;
+ readonly spec: SurfaceSpec;
+}
+
+// ── Surface WebSocket protocol (slice 1: surfaces only) ──────────────────────
+
+/** A client → server message on the surface channel. */
+export type SurfaceClientMessage = SubscribeMessage | UnsubscribeMessage | InvokeMessage;
+
+export interface SubscribeMessage {
+ readonly type: "subscribe";
+ readonly surfaceId: string;
+}
+
+export interface UnsubscribeMessage {
+ readonly type: "unsubscribe";
+ readonly surfaceId: string;
+}
+
+/** Invoke a field's action; `payload` is the new value (e.g. a toggle's boolean). */
+export interface InvokeMessage {
+ readonly type: "invoke";
+ readonly surfaceId: string;
+ readonly actionId: string;
+ readonly payload?: unknown;
+}
+
+/** A server → client message on the surface channel. */
+export type SurfaceServerMessage =
+ | CatalogMessage
+ | SurfaceMessage
+ | SurfaceUpdateMessage
+ | SurfaceErrorMessage;
+
+/** The current surface catalog (sent on connect and whenever it changes). */
+export interface CatalogMessage {
+ readonly type: "catalog";
+ readonly catalog: SurfaceCatalog;
+}
+
+/** The full current spec for a surface the client just subscribed to. */
+export interface SurfaceMessage {
+ readonly type: "surface";
+ readonly spec: SurfaceSpec;
+}
+
+/** A live update for a subscribed surface. */
+export interface SurfaceUpdateMessage {
+ readonly type: "update";
+ readonly update: SurfaceUpdate;
+}
+
+/** A surface-scoped error. */
+export interface SurfaceErrorMessage {
+ readonly type: "error";
+ readonly surfaceId?: string;
+ readonly message: string;
+}
+```