Skip to content

feat(desktop): conflict resolution surface for parked agent config coordinates (Step 6 / V3.6) #3819

Description

@wpfleger96

Background

The boot barrier added in #3752 closes the stale-store revert vector: a coordinate whose local store has no publish history but whose relay head is present gets its pending row withheld (publish_blocked = 1). This is the correct polarity for dev-build collisions.

The parked state is a stable fixed point: retain_event's upsert never touches publish_blocked, and each subsequent boot re-parks the same coordinate so long as no baseline exists. A user who edits an agent on a second legitimate install (no prior publish history on that machine) gets a save that never syncs, with no UI explaining why.

This issue tracks the Step 6 / V3.6 resolution surface that unblocks parked coordinates.

Required surface

Backend (Rust / Tauri)

  • get_blocked_coordinates — query the retention DB for all rows where publish_blocked = 1 and pending_sync = 1, return coordinate + local projection + reason (ParkReason)
  • force_publish_local — clear publish_blocked = 0 for the coordinate, then stamp the baseline from the local row's event_id/content atomically; the next flush loop tick picks it up as a normal pending publish
  • accept_remote_head — write the relay head's content to the local disk record (same path as ApplyHead), clear publish_blocked, stamp baseline from the head
  • Both operations must be atomic per coordinate — clear gate + stamp baseline in one transaction; no partial state where the row is unblocked but has no baseline (which would cause the next boot to re-park it again)

Frontend

  • Surface the blocked-coordinate list in agent settings or a dedicated conflict indicator
  • For each parked coordinate: show local vs. relay content diff (or at minimum local content + "relay has a different version"), and offer Keep mine / Use relay's actions
  • Parked state is transient relative to the user's intent — surface it promptly, not buried under a deep settings link

Schema notes

The resolution path is reachable today without schema changes:

  • set_publish_blocked(conn, kind, pubkey, d_tag, false) already exists (retention.rs)
  • stamp_baseline already exists (config_sync.rs)
  • The atomicity requirement means these two calls must be wrapped in a single SQLite transaction per coordinate

Diagnosing parked rows today

is_publish_blocked is #[cfg(test)] and not available in production. The barrier's per-decision tracing line (buzz::config_sync) logs every Park decision with coordinate, kind, and reason — that trace line and direct SQL against the retention DB are the current support path.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions