Expand description
engate-types — typed phase markers + traits for the engate attach
primitive. The actual attach machinery lives in engate-attach;
this crate is the small dependency-free contract so consumers can
depend on shapes without pulling in statig / typed-builder.
§Why
The bug class engate kills: a producer (PTY, WS, MQ, network) emits data BEFORE a consumer subscribes; subscribe returns only NEW data; the consumer’s local model stays empty even though the producer’s state is full. Today’s hand-wired attach paths in the pleme-io fleet (mado↔tear, kenshi↔testpod, hiroba clients, ayatsuri↔mado, namimado↔CDP) all suffer this class.
The fix: model attach as a 4-state typestate
(Spawned → Subscribed → Synced → Live) where the consumer can
only render from a Live value, Live can only be reached via
Synced.start_live(), Synced can only be reached via
Subscribed.replay(history), and history is a #[must_use]
linear-ish handle that cannot be dropped without being consumed.
Reaching the render path WITHOUT history is unrepresentable in
the type system.
See pleme-io/CLAUDE.md task tracker (#123-#129) for the full
M0-M6 roadmap.
Structs§
- Engate
Spec - Declarative spec for one engate attach point. Authored either by
hand in Rust (
EngateSpec { ... }) or via tatara-lisp’s(defengate ...)form (M5.1 —#[derive(TataraDomain)]lands when tatara-lisp’s macro story is mature enough to consume this without a manualregister()boilerplate dance). - Live
- Live items from the producer are flowing into the consumer. This
is the only phase from which
render()is reachable. Construction gated onSynced.start_live()— reachingLivewithout going throughSyncedis impossible in the type system. - Spawned
- Initial phase: producer has been identified (e.g. a pane id, a channel name) but no connection has been opened yet.
- Subscribed
- The consumer has registered with the producer’s live emission stream. No history has been replayed yet — calling render here would show an empty model even if the producer’s state is full.
- Synced
- Historical snapshot has been replayed into the consumer. The consumer’s local model now matches the producer’s state as of the snapshot. Live stream may have items queued but not yet forwarded.
- Type
Path - A crate + dotted type path. Two strings instead of one because the Nix side needs the crate name for the closure graph and the type path for the Rust import.
Enums§
- Attach
Error - Errors that can occur during an attach lifecycle.
Traits§
- Phase
- Phase of an attach lifecycle. Marker only — carries no data.
- Snapshot
- Producer-side snapshot of current state. Whatever the consumer
needs to bootstrap its local model to match the producer at attach
time. For tear: a
PaneSnapshot(grid + cursor + flags). For a WebSocket: the last N messages. For a Kubernetes log stream: the tail of stdout up to attach time.