Skip to content

[macos][release] Add Sparkle update channel for native app #134

Description

@100yenadmin

Summary

Add a Sparkle-backed update channel for the native ClawDnD macOS app after the
OpenWorlds shell, native bridge, local .app bundle, and signing identity are
stable.

The goal is to reduce repeated manual rebuild/download cycles for owners and
testers while preserving ClawDnD's state-authority boundary: app updates may
replace the app bundle, but must not mutate campaign state, QA state, private
world seeds, transcripts, or engine-owned game data.

Why this matters

Right now every meaningful app change requires a local rebuild, manual relaunch,
or a fresh artifact handoff. As the OpenWorlds macOS app becomes the primary
play surface, that creates avoidable friction and makes rapid UI/supervisor
iteration more expensive.

Sparkle should become the app update lane once local packaging is stable:

  • designers/testers can stay on a known release channel;
  • owner machines can pick up app fixes without manual rebuilds;
  • rollback and release notes become explicit;
  • engine/viewer state remains outside the replaceable app bundle.

Architecture plan

Add Sparkle only after the correction and bridge PRs establish the final app
shape:

  1. Bundle identity and signing

    • Decide the stable bundle identifier for ClawDnD.app.
    • Decide dev, nightly, and later beta signing identities.
    • Keep unsigned local dev builds working through ./script/build_and_run.sh --verify.
  2. Sparkle integration

    • Add Sparkle to the SwiftPM macOS package or an Xcode packaging layer, based
      on whichever release path the app settles on.
    • Keep Sparkle ownership in the native supervisor layer, not in viewer Python
      or OpenWorlds browser code.
    • Expose a narrow native bridge surface to OpenWorlds Settings:
      • update status;
      • current app version/build;
      • channel;
      • check for updates;
      • last update error;
      • release notes URL when available.
  3. Appcast and release channels

    • Define dev/nightly and beta appcast URLs.
    • Document who can publish appcasts and where signing keys live.
    • Do not ship private world seeds, play-state, qa/state, transcripts, or
      local provider config inside the update payload.
  4. Rollback and diagnostics

    • Add release notes and rollback notes to the packaging checklist.
    • Include update diagnostics in the OpenWorlds Settings diagnostics export.
    • Make update failures visible without falling back to the old SwiftUI shell.

Acceptance criteria

  • ClawDnD.app can check for updates from a configured appcast channel.
  • Update status and manual check controls are visible in OpenWorlds Settings.
  • Local dev builds still work without Sparkle/appcast configuration.
  • The update payload only replaces app-bundle code/assets and never mutates
    campaign/runtime state directories.
  • Release documentation explains signing, appcast publishing, rollback, and
    non-notarized/dev-channel constraints.

Validation sketch

From a Lexar-backed checkout:

swift build --package-path macos/ClawDnDApp
./script/build_and_run.sh --verify
codesign --verify --deep --strict dist/ClawDnD.app
plutil -lint dist/ClawDnD.app/Contents/Info.plist
python3 scripts/license_check.py

Manual smoke:

  • launch the app;
  • open OpenWorlds Settings;
  • verify update channel/status is visible;
  • run a manual update check against a test appcast;
  • confirm campaign state and provider config survive the app update.

Original-agent handoff

Start with:

  • macos/ClawDnDApp/Package.swift
  • macos/ClawDnDApp/Sources/ClawDnDApp/App/ClawDnDApp.swift
  • macos/ClawDnDApp/Sources/ClawDnDApp/Views/RootView.swift
  • macos/ClawDnDApp/Sources/ClawDnDApp/Views/WebView.swift
  • script/build_and_run.sh
  • docs/OPENWORLDS_NATIVE_APP_ROADMAP.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestseverity:minorPolish gap — release-quality wouldn't ship with ittier-2Tier 2: OpenClaw integration

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions