Files
buzz/desktop
SamiandTyler Longwell aa39d72aac fix(agents): stop boot reconcile republishing stale config over a newer head
Boot reconcile is a fourth stale-disk republish site, in the same class as
the three write sites fixed in the previous commit but worse: it fires at
launch, unprompted, for every agent on a device that follows another
device's config.

`reconcile_agents_in_dir_at` reads `managed-agents.json` raw and cannot
resolve the private-config overlay -- `hydrate_private_config_overlay` runs
after this leg (`event_sync.rs:19-20`) and reads the rows this leg writes.
Inbound kind:30179 updates the overlay and retention but never the JSON, so
on a follower disk is stale by construction. Rebuilding the 30179 projection
from disk then republishes every stale field over device A's newer head as a
validly chained gen+1 successor, and `monotonic_created_at` floors it at
head+1 so it wins LWW. Measured: gen 5 -> 6, `prev` = the clobbered head,
`created_at` = head+1 against a head 10,000s in the future, `pending_sync`
set, and every field (name, system_prompt, parallelism, env_vars) taken from
stale disk.

It also does not self-heal. A second boot is a clean no-op because disk now
matches the head it wrote, but each new head device A publishes re-arms it:
measured 16 -> 1, no-op, then 24 -> 1. The follower's disk wins every round
and the user on A sees their edit silently revert.

The previous commit's keyring hydration is what makes this reachable. Before
it, `retain_private_agent_record`'s empty-nsec skip returned early for every
keyring-resident record, so boot never built a 30179 at all -- the skip was
incidentally protecting this path. Hydrating keys is still correct (an
untouched agent must publish its first 30179 on a default build), but it
exposed everything downstream of the guard it removed. A control arm with an
absent nsec confirms the head survives, pinning the causal line.

Fix: `retain_agent_record_at_boot` publishes the 30179 only when no retained
head exists, and is used by boot reconcile alone. That keeps the requirement
boot exists to serve -- an agent whose nsec lives in the keyring gets its
FIRST private config published -- while leaving an existing head to the
interactive edit paths, which resolve the overlay before retaining and so
author from relay-fresh state. The kind:30177 identity leg is untouched, so
the upgrade republish waves keep working.

Resolving the overlay at boot instead was rejected and is pinned by a
permanent wrong-fix probe: an offline local edit lives on disk and in an
unflushed `pending_sync` 30179, so resolving disk through an overlay
hydrated from the older head would discard it -- the centralized-resolve
failure from the previous commit, with boot's blast radius.

Tests (4): the fix verification asserts the head is byte-identical after
boot and nothing is enqueued; two requirement-preservation arms (first 30179
still published when no head exists; 30177 still republishes when a private
head is present) so the fix cannot be satisfied by never publishing at boot
or by gating at the wrong level; and the wrong-fix probe. Three mutants,
each killed by a different arm: gate deleted, gate inverted, gate applied to
the whole record instead of the private leg. Mutants re-run after cargo fmt.

Desktop lib suite 2360 passed / 0 failed / 15 ignored (--all-features);
cargo fmt --check, cargo clippy --workspace --all-targets --all-features
-D warnings, and the desktop file-size ratchet (against the CI base) all
clean -- the ratchet verified live with a padding control that fails it.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
2026-08-06 13:19:49 -04:00
..
2026-08-03 21:51:17 -04:00
…

Buzz

Desktop chat shell with:

  • Tauri + React + TypeScript + Vite
  • Tailwind CSS
  • shadcn/ui-ready shared components
  • Biome (lint/format/check)
  • Feature-driven frontend structure

Scripts

  • pnpm dev - run the web frontend
  • pnpm tauri dev - run the desktop app
  • pnpm build - typecheck and build frontend
  • pnpm typecheck - TypeScript checks
  • pnpm lint - Biome lint
  • pnpm format - Biome format (write)
  • pnpm check - Biome check

Structure

  • src/shared - reusable app-wide code (ui, lib, styles)
  • src/features - feature modules (vertical slices)
  • src/app - top-level app composition