Skip to content
Agent Workspaces
Agent

state-ownership

Emdash has two durable state authorities:

From plugin
emdash
6.2k33 skills33 agents

Agent definition

state-ownership.md

State Ownership

Emdash has two durable state authorities:

  • Desktop SQLite owns desktop entities such as projects, tasks, automations, conversations,

and the bindings from those entities to host resources.

  • Each workspace host owns the resources on its machine: repositories, worktrees,

branches, process state, and the per-record outcome annotations its registry writes.

Do not treat a desktop workspace row as the workspace itself. For host-owned resources, desktop rows are a materialized cache plus desktop-owned metadata and links. The host's registry and its observations are the observed truth (ADR 0001, ADR 0005).

Ownership Classes

| Class | Examples | Authority | Desktop row meaning | | --- | --- | --- | --- | | Desktop entities | project, task, automation, conversation | Desktop SQLite | The entity itself; tombstones are authoritative. | | Host resources | repository, worktree, branch, path | Workspace host | Cached observation and optional desktop metadata. | | Bindings | task to workspace, project to host | Desktop SQLite | A desktop-owned reference to a host resource. |

This means `deletedAt` on a desktop entity means the entity is deleted. A deletion tombstone on a mirror row for a host resource means the desktop intends removal; the resource exists until the host executes the delete verb or observes it gone.

Mutation Model

Host mutations are plain fail-fast RPCs against the host's registry verbs — no durable command queue, no operation log, no desktop-held claims (ADR 0005). Deletion is the one host mutation that must survive host unreachability, and it does so through data, not machinery (ADR 0006):

  • Deleting a host-resident entity writes a durable **tombstone** on its mirror row,

freezing the deletion options and the target record's UUID. The tombstoned row is the visible pending state and the queue; nothing else is enqueued anywhere.

  • An entity-generic **reconcile sweep** runs whenever a host is reachable (boot,

reconnect, tombstoned-while-reachable, 10-minute backstop) and calls each kind's idempotent delete verb for that host's tombstones, purging a tombstone only when the mirror confirms the host record gone.

  • Verb outcomes live on host records (stage, class, message, timestamp) and sync to the

mirror, which is the only thing the UI reads. RPC returns are loop control, never UI truth.

Placement follows the same line: entity knowledge, cascading intent, and user confirmation live in desktop delete flows; disk/process facts and verb serialization (a keyed mutex, per-repo for worktree create/delete, per-workspace for activate/deactivate/delete) live on the host.

Decisions

  • Use one writer per resource. Convergence happens through live models and snapshot

sync, not by merging concurrently-written state.

  • Creation and lifecycle verbs fail fast against unreachable hosts; interrupted creates

recover via the host's durable record plus idempotent client replay (same UUID, identical spec).

  • Deletion intent is durable client data (the tombstone), converged by the reconcile

sweep. Every tombstone has user-operable release paths: Retry and Untrack-anyway.

  • Status machines are per authority, but each status set should have an explicit

transition table and a pure severity fold for UI rollups.

  • Contribute behavior through manifests and definitions. Keep shared vocabulary, such

as statuses and outcome classes, centrally owned and mechanically reviewable.

Archive Script Cleanup

Task archive requests host workspace deactivation using the task's persisted workspace identity, including when the task is not mounted. It preserves the worktree. Script failures and timeouts are notices; an unreachable host is skipped without queued cleanup. The host runs `scripts.teardown` unless its existing lifecycle step is `succeeded` or `failed` (including timeout). The settled script observation is persisted before deactivation returns, so a later delete does not repeat it, even after restart. Reactivation resets script steps and stores the superseded run IDs in the lifecycle record, so retained script results cannot revive a previous cycle after a registry-worker restart. Absent or cancelled teardown steps remain eligible for the next explicit deactivation or deletion. `archivedAt` and `lastActivatedAt` are not cleanup receipts. A teardown failure during deletion still stops that worktree removal attempt; a subsequent removal proceeds past the settled script attempt.

Desktop activation and cleanup are serialized per Workspace, including participant acquisition and task registration. Archive's timeout bounds the caller's wait, not the cleanup lifetime: already-running cleanup retains ownership until it actually settles, and a later activation waits behind it. Waiting operations can be cancelled; cleanup whose deadline expires before it starts is skipped. This coordination is in memory, not a durable retry queue.

See ADR 0005 (`docs/adr/0005-host-workspace-registry-plain-rpc-verbs.md`) and ADR 0006 (`docs/adr/0006-tombstone-and-reconcile-deletion.md`) for the full model, and the glossary in `CONTEXT.md` for the vocabulary.

Read more
@generalaction
Ships withemdash

Emdash is the Open-Source Agentic Development Environment (🧡 YC W26). Run multiple coding agents in parallel. Use any provider.

Stars on GitHub

Momentum

stars in total
6.2k
Star history of generalaction/emdash on GitHub, a chart by star-history.com

Other agents on emdash.

acp-runtime

acp-runtime

Agent

The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run…

core-modules

core-modules

Agent

This page defines the target organization of `packages/core/src/`. Core is organized by module type so that shared domain APIs…

git-runtime

git-runtime

Agent

Git is split into a transport contract and a host-scoped runtime. Renderer, desktop, and workspace-server code share the Wire…

main-process

main-process

Agent

The main process is organized into domain modules under `src/main/core/`. Each domain typically has a `controller.ts` (RPC…

path-system

path-system

Agent

`@emdash/core/primitives/path/api` is the source of truth for portable file identity and lexical path operations. The detailed…

More agents from other plugins.

api-builder

api-builder

Agent

Deprecated placeholder. Do not use; follow root AGENTS.md and package instructions instead.

happier3d2.2k
@happier-dev@happier-devInstall Agent

Questions about state-ownership.

Which coding agents can use state-ownership?
state-ownership installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.