The C# home for the eventual full babel port. babel is HOLO-Q's agent-session
tracking daemon + terminal-session UX bus — today it lives in Rust at
~/holoq/repo-os/babel (the app) plus a cluster of babel-* crates
(babel-wire, babel-native, babel-store, babel-styling, …). This repo is
the seed of its migration into the repo-os3 C#/NativeAOT branch, alongside
bob.
This is not the full app port. As of the scaffold, the repo holds exactly
one project — Babel.Core — the C# port of the Rust babel-wire crate's
protocol/DTO surface. The app itself (the pump, the SQLite store, the feed
adapter, the daemon runtime, the pager) lands in a later wave, once we have
our bearings with C# dev and can scale the port.
Babel.Core is the interop contract. The Rust babel daemon stays the server for
now; a future C# babel client (and bob's future C# babel module, which will
reference Babel.Core as a sibling path-dep ../babel/Babel.Core/...) speaks
the same JSON line protocol over the daemon's Unix socket. Porting the wire types
first means the boundary is typed and verifiable before any app logic moves.
Faithful to the Rust wire shape (so a C# client interoperates with the Rust
daemon), but idiomatic C#: record/readonly record struct value types,
polymorphic record hierarchies for serde tagged-unions, real enums (never
string literals) with [JsonStringEnumMemberName] pinning the exact wire casing
(snake_case / kebab-case / PascalCase per the source crate), and serde-transparent
newtypes for domain ids.
| Area | Types | Rust source |
|---|---|---|
| HUD (the desktop snapshot) | HudSnapshot, PaneHud, SessionHud, ProjectHud, GitWorktreeState, HudPaneInput, SessionClaim (+Source/Strength) |
babel-wire/src/hud.rs |
| Paint stream | PaintEvent (Window/Workspace/Reset), WorkspacePaintEvent |
babel-wire/src/paint.rs |
| Indicators | IndicatorEvent (Set/Remove/Clear), IndicatorTexture (Stripes/CrossHatch), IndicatorRingStyle, IndicatorBatch |
babel-wire/src/indicator.rs |
| Daemon sub-protocols | PaintRequest, PaintResponse, PaneRequest, PaneResponse |
babel-wire/src/protocol.rs |
| Events | BabelEvent (25 variants), EventMessage, PulseTrigger |
babel-wire/src/events.rs |
| Model / identity | AgentKind (+slug/display/accent), ActivityState, HookState, HookType, MatchConfidence, NotifType/KnownNotifType, PulseEffect, ReadEffect, SessionId, PaneAddr, PaneSelector |
babel-wire/src/{agent_kind,activity_state,match_confidence,model/*}.rs |
- Entity replication — the
Replicate/Replicationarms ofPaintRequest/PaintResponseand the wholeReplicationSpec/ReplicationCursorsubtree (babel-wire/src/replication.rs). App-side machinery; not part of the paint/HUD path bob consumes. - Surface model —
SurfaceSelector/SurfaceAddr/AgentSessionKey/SurfaceServerId(babel-wire/src/model/surface_*.rs).PaneRequest.Focuscurrently targets the simplerPaneSelector(what bob-babel imports); widen to a portedSurfaceSelectorwhen the surface model lands. - Cairo rendering (
render.rs/render20.rs) — bob owns its own OpenGL renderer; the Cairo dot-drawing path does not port. - Codec — the actual JSON (de)serialization wiring (a reflection-free
JsonSerializerContextsource-gen for AOT, plus a custom converter to reproduce serde's#[serde(flatten)]onEventMessage). The types carry the shape and document the discriminants; the codec wave makes them speak.
cd ~/holoq/repo-os3/babel
rk build # net10.0, LangVersion 14, AOT-clean (IsAotCompatible)Babel.Core is a library — it does not set PublishAot (that is an
app-publish lever). IsAotCompatible runs the trim/AOT analyzers on every build
so the types stay AOT-clean for their NativeAOT consumer (bob).
MIT — mirrors the Rust babel-wire crate. (bob, the desktop renderer, is
GPL-2.0; the wire contract is a publishable protocol library and takes the
general MIT default.)