Back to list
Jul 27 2026

Development Update — July 27

The skychat convergence hit full stride today — eighteen PRs, most of them landing the payoff of yesterday’s seams. The centerpiece is a single shared DM controller that both the native app and the browser wasm visor now run on, deleting hundreds of lines of duplicated connection, read-loop, and send logic that had drifted between the two. With one core in place, the DM feature set that used to be implemented twice (or not at all on one surface) landed uniformly: delete-for-everyone, WhatsApp-style delivery ticks, and the quoted-reply UI reached both visors and both chat UIs at once. The day also brought a large browser-skychat feature merge, a config-regen fix that had been quietly making newly-shipped apps unreachable, and an RFC on serving SkyDEX as a plain website over dmsg.

Skywire: One Shared DM Controller

3608 feat(skychat): shared DM controller in pkg/skychat/dm extracts the 1:1 direct-message core both visors duplicate — per-peer framed connections, the listen/accept and per-conn read loops, chat-msg/chat-ack/quoted-reply envelope handling, and the outbound send path including peer-receipt ack-wait, cross-network fallback, and stale-conn redial-retry — into one dm.Controller. It imports no pkg/app, net/http, or bbolt, so it compiles under GOOS=js, and it decouples via seams (Client, history.Store, OnEvent, PreHandleFrame, DialRetry) satisfied structurally on both visors. 3609 feat(wasm-visor): run 1:1 skychat on the shared pkg/skychat/dm controller migrates the browser visor onto it first, deleting chatConns/acceptChatLoop/readChatConn/decodeChatPayload and the send-core body (~100 lines of duplication); its OnEvent maps every surfaced message to appendChat, keeping the MemStore the single history writer. 3610 feat(skychat/dm): Serve (inject conns), Stats counters, nil-transport safety adds the capabilities the native app additionally needs — Serve(conn) to run an already-established TCP-direct conn through the same cache and read loop, Stats() for the /status counters, and nil-Client safety so a --standalone visor with no transport errors cleanly instead of panicking. 3611 feat(skychat): migrate the native app onto the shared pkg/skychat/dm controller closes the loop: the native app’s ~250-line send-core collapses to chatCtrl.Send(), TCP-direct injects via Serve, pairing sends via SendRaw, and the whole conns/dialAndCache/handleConn/listenLoop apparatus is gone — one shared controller, both visors on it.

Skywire: Delete, Ticks, Replies, and Backfill — on Both Surfaces

With the shared controller in place, three DM features landed across every surface. Delete-for-everyone came in as a stack: 3612 feat(skychat/dm): delete-for-everyone wire type + controller support adds the chat-delete envelope type plus SendDelete/OnDelete; 3613 feat(skychat): delete-for-everyone in the native app + wasm visor wires it into both visors’ backends (native POST /delete, wasm skychatDelete), tombstoning the deleter’s own bubble and the peer’s copy via the dm-status channel; 3614 feat(skychat): DM delete-for-everyone UI (native SPA + HV Angular) and 3615 feat(skychat): handle dm-status delete in the HV Angular UI native path add the delete affordance and tombstone rendering to both UIs; and 3616 fix(skychat): eslint errors in the Angular skychat component (unblock ui CI) unbreaks the ui lint lane the delete follow-ups had reddened. Delivery ticks followed the same both-paths pattern: 3617 feat(skychat): delivery-status ticks in the HV Angular UI (native path) renders the ✓✓✓✓ (blue) lifecycle on the native-proxy path, and 3618 feat(skychat): delivery-status ticks on the wasm-visor path (HV Angular UI) gives the wasm path its missing per-message receipt surface via a new controller SendRead and a skychatReadReceipt hook. The quoted-reply UI, whose wire format landed yesterday, reached the surfaces too: 3604 feat(skychat): persist + surface message id and reply_to on native read paths fixes the native read paths to key inbound events by the envelope id and persist ReplyTo; 3606 feat(skychat): quoted-reply threading in the native SPA and 3607 feat(skychat): quoted-reply threading in the HV Angular UI add the quoted-parent snippet, the hover ↩ affordance, and the compose banner to both UIs. Finally 3602 feat(wasm-visor): backfill group chat history via Manager.ReplayHistory exports ReplayHistory and re-pumps a joined group’s CXO feed on a short backoff, so history that syncs after the subscribe returns still appears in the browser visor’s empty-after-reload store — deduped so repeated replays stay idempotent.

3592 Improve Skychat lands a large feature set on the embedded browser skychat app, turning it from a text-only client into a full chat app: inline images with a lightbox, native video/audio players and download cards, 📎 file send with optimistic previews and on-demand backfill, groups proxied to the visor’s GroupX RPC, Telegram-style press-and-hold voice and video messages streamed through OPFS temp files so memory stays flat, 1:1 voice calls with an in-call spectrogram, browser and host-OS desktop notifications (the new dependency-free pkg/osnotify), and a local contacts book with dmsg-ping presence dots. It also carried three fixes found in live testing — a RouteGroup.read EOF that reported delivered files as failed, a file-transfer deadline that was a hidden size limit (now a 60s idle timeout), and a delivery tick stuck on “sent” when a receipt arrived before its message id.

Skywire: Beyond Chat — Config Regen and the SkyDEX RFC

3603 fix(config): regen preserves custom apps + operator toggles, adds new defaults fixes a genuinely damaging bug: config gen -r rebuilt launcher.apps from defaults, which added new apps but silently dropped any app the operator had added by hand and reset per-app toggles — so a customized config had no non-destructive way to pick up a freshly-shipped app, and in practice a new app stayed unreachable (the “site can’t be reached” people hit when told to start skydex-client) until a manual JSON edit. A regen of a real pre-skydex config went 11 apps → 8. The new mergeExistingApps reconciles the default list against the previous config — restoring operator-toggled fields (AutoStart, Args, LauncherMode, RestartPolicy) on apps in both, carrying over custom-only apps verbatim, and still adding brand-new defaults — so the same regen now keeps all 11 and adds the 3 new ones. 3605 docs(skydex): RFC — SkyDEX as a website over dmsg is a discussion draft asking whether SkyDEX needs its dedicated skydex-client app and custom market protocol, or whether the exchange could just be a website served over dmsg. Its key subtlety is identity: the market derives each trader’s PK from the dmsg-authenticated transport, so a website design preserves per-trader identity only because each user reaches it through their own visor gateway — a shared public proxy would collapse it.