feat(desktop): restart-required badge from spawn-time config hash#1602
Conversation
Stamp a digest of the effective spawn config (live-persona-resolved harness command + derived args/mcp, layered effective env, and the record fields the spawn env writes read) on ManagedAgentProcess at launch. build_managed_agent_summary recomputes the hash from current disk state and flags needs_restart on mismatch, surfaced as a "Restart required" badge on the agent row. Semantics: the badge means "a restart would change what runs"; persona_out_of_date keeps meaning "a respawn would." Persona prompt/model/provider edits are snapshot-pinned at spawn and so are excluded; persona runtime edits resolve live and are included. Channel membership is not an input — agents pick up channel changes live (#1468). The hash is runtime-only state, never persisted; agents adopted via a persisted runtime_pid have no stamped hash and stay unbadged. Also starts the queued tauri.ts split (start/stopManagedAgent → tauriManagedAgents.ts) and ratchets its file-size limit 1388 → 1380. Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
wpfleger96
left a comment
There was a problem hiding this comment.
Dedicated review of the restart-required badge, re-verified at source before posting. The UI/API plumbing is coherent, Unix and Windows stamp the same computed spawn_config_hash, stopped/adopted-via-runtime_pid agents correctly stay badge-off, and the tauri.ts split is real (1375 lines against the ratcheted 1380 override, not a bump in disguise).
Requesting changes on two correctness gaps where the badge stays OFF even though a plain restart would change what runs — the dangerous false-negative direction for this feature. Both verified against the actual start/spawn paths. Inline comments below; the 🟢 is optional.
| //! command (persona runtime edits DO propagate on restart), its derived | ||
| //! args/mcp command, the effective env layering, and the record fields the | ||
| //! spawn env writes read. | ||
| //! - Persona prompt/model/provider edits are EXCLUDED: spawn reads the pinned |
There was a problem hiding this comment.
False-negative: persona prompt/model/provider edits are excluded, but the restart path DOES apply them. This scope rule assumes spawn reads the pinned record snapshot, so a persona prompt/model/provider edit wouldn't survive a restart. That's not what the start path does anymore: start_local_agent_with_preflight re-snapshots the linked persona's system_prompt/model/provider/env_vars onto the record immediately before spawning (desktop/src-tauri/src/commands/agents.rs:263–:284), and restore does the same on launch. So a running persona-backed agent can have its persona prompt edited, this hash stays unchanged (it digests the stored record fields, not the prospective re-snapshot), the badge stays off — and then a stop/start changes what runs.
Fix: compute the comparison hash from the same prospective re-snapshotted record that start/restore will actually spawn (resolve the persona into a scratch record before hashing), OR drop the pre-spawn re-snapshot if pinned-until-delete is the intended product behavior. Whichever way it lands, persona_prompt_edit_does_not_change_hash (spawn_hash/tests.rs:112) needs to flip to assert_ne! if the re-snapshot stays.
There was a problem hiding this comment.
Confirmed at source and fixed in dcd5cee — you're right, start_local_agent_with_preflight and restore_managed_agents_on_launch both re-snapshot the persona onto the record before spawning, so those edits DO apply on restart. spawn_config_hash now applies the same prospective re-snapshot (persona_snapshot_with_agent_config_fallback with the record's model/provider fallbacks) to a scratch record before hashing prompt/model/provider/env, so the hash covers exactly what a restart would run. The re-snapshot is idempotent, so the spawn-time stamp and later recomputes agree when nothing changed. Flipped persona_prompt_edit_does_not_change_hash to persona_prompt_edit_changes_hash (assert_ne).
| effective.env.hash(&mut hasher); | ||
|
|
||
| // Record fields the spawn env writes read directly. | ||
| record.relay_url.hash(&mut hasher); |
There was a problem hiding this comment.
False-negative: blank record relay hashes the raw empty string, but spawn resolves the workspace relay. spawn_agent_child sets BUZZ_RELAY_URL from effective_agent_relay_url(&record.relay_url, relay_ws_url_with_override(state)) (runtime.rs:1553–1560), which falls back to the active workspace relay when record.relay_url is empty (relay.rs:65–72). Create intentionally stores relay_url: "" when the user leaves it unset (agents.rs:582–587). So if the workspace relay changes while a blank-relay agent is running, a restart would change both BUZZ_RELAY_URL and the relay-scoped git credential-helper URL — but this hashes "" vs "" and keeps the badge off.
Fix: hash the resolved effective relay URL (pass the workspace/effective relay into the helper) rather than the raw record field. Add a regression test for blank record relay + changed workspace relay.
There was a problem hiding this comment.
Fixed in dcd5cee: the relay is now hashed in resolved form — spawn_config_hash takes a workspace_relay param (keeping it pure, no AppHandle) and hashes effective_agent_relay_url(&record.relay_url, workspace_relay). The summary builder passes relay_ws_url_with_override; the spawn stamp reuses the already-resolved effective_relay_url (resolution is idempotent). Added regression tests: blank record relay + workspace change trips the hash; pinned record relay + workspace change does not.
| effective.env.hash(&mut hasher); | ||
|
|
||
| // Record fields the spawn env writes read directly. | ||
| record.relay_url.hash(&mut hasher); |
There was a problem hiding this comment.
Nit (optional, opposite direction — false positive): a few record fields are hashed in raw shape where spawn normalizes or drops them, which can trip the badge when a restart would change nothing — respond_to_allowlist when mode isn't allowlist, mcp_toolsets: None vs the default toolset string, max_turn_duration_seconds: None vs an explicit default. Not blocking, but worth tightening once the false-negatives above are fixed if the contract is strictly "badge only when a restart changes behavior."
There was a problem hiding this comment.
Agreed these are real but benign (worst case a spurious badge that a restart clears, and each requires an unusual edit sequence). Deferring to keep this fix focused on the two false-negatives — happy to normalize respond_to_allowlist/mcp_toolsets/max_turn_duration in a follow-up if you'd like it tracked.
…lves it Review feedback on #1602: the restart badge hash had two false-negatives. 1. Persona prompt/model/provider/env edits were excluded, but start/restore re-snapshot the linked persona onto the record right before spawning, so those edits DO apply on a plain restart. spawn_config_hash now applies the same prospective re-snapshot (persona_snapshot_with_agent_config_fallback) before hashing, so the badge trips when a restart would pick up the edit. 2. A blank record relay_url resolves to the active workspace relay at spawn, but the raw "" was hashed — a workspace relay change never badged. The relay is now hashed in resolved form (effective_agent_relay_url) with the workspace relay threaded from both call sites, keeping the hash pure. Flipped persona_prompt_edit test to assert_ne and added blank-relay / pinned-relay workspace-change regression tests. Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
…ivity * origin/main: feat(desktop): restart-required badge from spawn-time config hash (#1602) feat(desktop): boot-time reconcile of managed agents to relay events (#1601) feat(desktop): canonical <PubKey> component — hover to view/copy full keys, owner "you" labels (#1589) Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
* origin/main: docs(readme): add Getting started section routing install paths (#1606) fix(desktop): restrict shared-agent sync to dev data dirs (#1597) feat(desktop): restart-required badge from spawn-time config hash (#1602) feat(desktop): boot-time reconcile of managed agents to relay events (#1601) feat(desktop): canonical <PubKey> component — hover to view/copy full keys, owner "you" labels (#1589) fix(desktop): hydrate reactions for Inbox context messages (#1596) fix: cleanup old screenshots that my agents committed (#1598) chore(release): release Buzz Desktop version 0.3.46 (#1585) fix(desktop): preserve agent model/provider when persona snapshot fields are blank (#1583) feat(acp,desktop): identify and reap stale agent harness processes (#1582) feat(desktop): active-draft badge, send-from-drafts confirm dialog, thread-deleted state (#1581) fix(desktop): treat baked build env vars as satisfying required agent config (#1580) feat(desktop): add "Copy image" to image right-click context menu (#1579) fix(nest): use buzz-dev symlink name for dev builds (#1587) fix(composer): address image-editor follow-up nits on #1491 (#1565) fix(desktop): render black static boot screen (#1570) feat(agents): group activity tool bursts (#1571) feat(desktop): aggregated overview rail, commit detail page, and full breadcrumbs (#1573) fix(desktop): fetch profiles for reaction actors and thread-reply authors (#1550)
Summary
Adds a "Restart required" badge for running managed agents whose effective spawn configuration has drifted since they were started — the detection layer for the upcoming auto-restart policy (Chunk F).
spawn_config_hash(record, personas) -> u64(managed_agents/spawn_hash.rs): hashes exactly what spawn consumes —effective_agent_command(live-persona-resolved), normalized args, effective MCP config,resolve_effective_agent_envoutput, and the record fields the env writes read.DefaultHasheroverBTreeMaps; the hash never crosses a process/persistence boundary.personaOutOfDate= "a respawn would." Persona prompt/model/provider edits do NOT trip the badge (spawn reads the pinned record snapshot — restart wouldn't apply them); persona runtime/harness edits DO (resolved live at spawn). Record-level prompt edits trip it (spawn input viaBUZZ_ACP_SYSTEM_PROMPT).ManagedAgentProcess(Unix struct literal + Windowsfinish_spawn);build_managed_agent_summaryrecomputes vs the current record+personas →needs_restart→needsRestartbadge + hint inManagedAgentRow. Stopped/adopted-via-runtime_pidagents have no runtimes entry, so they stay honestly badge-off.tauri.tscrossed its limit, so this does the queued split (start/stopManagedAgent→tauriManagedAgents.ts) and ratchets the guard 1388 → 1380 rather than bumping it.Testing
persona_runtime_edit_changes_hash/persona_prompt_edit_does_not_change_hash) andnon_spawn_bookkeeping_fields_do_not_change_hash.just desktop-tauri-test1016 passed / 0 failed;just desktop-check,just desktop-test(2029 passed),just desktop-typecheck, both fmt-checks, workspacejust clippyall green.