acp-runtime
AgentThe ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run…
- `src/main/host/updates/update-service.ts` - `src/core/features/updates/node/wire-controller.ts` - `src/core/features/updates/browser/update-store.tsx` - `src/core/features/settings/browser/components/UpdateCard.tsx` - `packages/ui/src/react/components/update-card/`
The main-process update service owns the transfer. `downloadUpdate()` accepts a start request synchronously and retains the background promise; Wire returns the current state without waiting for the archive. Duplicate requests during downloading, downloaded, or installing are successful no-ops. Checks must not overwrite those states. Electron's progress, completion, and error events drive the renderer; a request timeout alone does not mean the transfer failed.
The shared update card receives explicit downloading/installing states and progress. Component-local pending state covers only request acknowledgement. Do not derive transfer progress from the lifetime of a button callback: downloads can start from the sidebar, toast, or recovery window, and continue while Settings is unmounted. State snapshots must not replace newer events received while awaiting the response.
Error summaries wrap below the card description. Full sanitized diagnostics are preserved separately for the Details disclosure and Copy details action; summaries and updater log messages remain bounded.
Regression coverage lives in `src/main/host/updates/update-service.test.ts`, `src/main/host/updates/utils.test.ts`, `src/renderer/tests/update-flow.test.ts`, and the shared card's tests and Storybook states.
The stable release pipeline publishes to **GitHub Releases** (primary feed) and **Cloudflare R2** (legacy/migration feed). Both feeds are served from the same platform builds and are promoted by a single finalizer only after the complete supported architecture set builds and verifies.
electron-builder emits channel manifests named by the **first** publish provider's `channel`:
The R2 feed uses different channel names (`v1-stable`, `v1-canary`) that pre-date the GitHub migration. Rather than running a second packaging pass, `scripts/release/build.ts` calls `duplicateChannelManifests()` after the electron-builder step to copy `latest*.yml → v1-stable*.yml` (or `canary*.yml → v1-canary*.yml`). The duplicated manifests are kept local until platform verification finishes. `upload-github-assets.ts` then hashes the final files, refreshes manifest checksums and sizes, and uploads the artifacts and both manifest variants to the exact owned GitHub draft. On macOS this happens only after notarization and stapling.
Platform jobs never write the live R2 channel. `scripts/release/finalize-release.ts` first validates the exact owned GitHub release, the complete architecture inventory, and every update manifest entry. It downloads every referenced GitHub asset, verifies its SHA-512 against the manifest, uploads installer assets under an immutable `releases/<tag>/<run>-<attempt>/` prefix, and rewrites the R2 manifests to those keys. Before replacing any root `v1-stable*.yml` or `v1-canary*.yml` object, it snapshots the complete previous manifest set. Promotion or a confirmed GitHub publication failure restores that set. The original snapshot is journaled in R2 by tag, run, and commit before any root changes, so it survives retries and runner termination. If GitHub's response is ambiguous, the complete new R2 set is retained; a retry restores the journaled public roots when the release is still a draft or reconciles every root when publication actually succeeded.
The app does **not** override `autoUpdater.channel`; the GitHub provider resolves the channel naturally:
The `UPDATE_CHANNEL` / `v1-stable` / `v1-canary` naming applies **only** to the flat R2 bucket (via the `generic` publish block's `channel`). It is kept as a log label in `update-service.ts` for diagnostics but is not passed to `autoUpdater.channel`.
R2 uploads continue until telemetry confirms all clients have migrated to the GitHub-backed feed. At that point:
1. Remove the `provider: generic` block from `electron-builder.config.ts` and `electron-builder.canary.config.ts`. 2. Remove R2 staging/promotion from `finalize-release.ts` and `duplicateChannelManifests` from `build.ts`. 3. Decommission the R2 bucket.
Emdash is the Open-Source Agentic Development Environment (🧡 YC W26). Run multiple coding agents in parallel. Use any provider.
The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run…
This page defines the target organization of `packages/core/src/`. Core is organized by module type so that shared domain APIs…
Git is split into a transport contract and a host-scoped runtime. Renderer, desktop, and workspace-server code share the Wire…
The main process is organized into domain modules under `src/main/core/`. Each domain typically has a `controller.ts` (RPC…
`@emdash/core/primitives/path/api` is the source of truth for portable file identity and lexical path operations. The detailed…
Validates project structure against co-location and architecture patterns defined in AGENTS.md
Deprecated placeholder. Do not use; follow root AGENTS.md and package instructions instead.
Use this agent when you need to create or update technical documentation that helps developers understand the deep patterns,…
Orchestration patterns learned from experience. Review at startup and before heartbeat responses.