Skip to content

fix(desktop): make agent definition authoritative for model/provider/prompt#1968

Open
wpfleger96 wants to merge 1 commit into
mainfrom
duncan/agent-config-resolver
Open

fix(desktop): make agent definition authoritative for model/provider/prompt#1968
wpfleger96 wants to merge 1 commit into
mainfrom
duncan/agent-config-resolver

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

Introduces a single effective-config resolver that makes agent definitions authoritative for model, provider, system prompt, and relay-mesh routing on linked instances. Stale materialized record bytes are never consulted at spawn, deploy, readiness, hash, card summary, or mesh preflight.

Resolution semantics (field-specific):

  • model/provider (linked): definition → global. None = inherit global default. Record value never consulted.
  • model/provider (definition-less): instance → global.
  • system_prompt (linked): strictly from definition; blank = no prompt. No global tier for prompt.
  • system_prompt (definition-less): from the instance.
  • relay-mesh preflight (both): driven by the same resolve_effective_config resolution spawn's mesh env consults — never the record's own provider/model/relay_mesh bytes.
  • Orphaned (linked record, definition missing): spawn, deploy, and mesh preflight blocked with actionable user-facing error.

Changes:

  • New effective_config resolver module with ConfigSource metadata (definition, global, instance_legacy)
  • All consumers routed through the single resolver: local spawn, deploy, readiness, spawn hash, card summary, relay-mesh preflight (interactive start and restore-on-launch)
  • apply_persona_snapshot no longer preserves stale record model/provider when definition is blank
  • Backend update_managed_agent blocks model/provider/prompt writes for linked records
  • Frontend omits model/provider/systemPrompt submission for linked instances; system prompt override hidden
  • model_source field added to ManagedAgentSummary so card labels distinguish inherited (Default model (X)) from explicit
  • Spawn hash now digests resolved model/provider (not raw record fields) so global default changes trip the restart badge even for runtimes without model_env_var
  • Orphan spawn/deploy/mesh-preflight blocked with jargon-free error ("This agent's configuration is missing — it may still be syncing or was deleted on another device")
  • EffectiveAgentConfig::relay_mesh_model_id() and resolve_effective_relay_mesh_model_id() added; both mesh preflights (start_local_agent_with_preflight, restore_managed_agents_on_launch) call this instead of the deleted relay_mesh_config/relay_mesh_model_id record-byte sniffs and legacy env-var fallback
  • Dead persona_field_with_record_fallback and wrapper persona_snapshot_with_agent_config_fallback deleted; callers use persona_snapshot directly
  • 20+ new resolver/deploy/hash/write-guard/mesh-preflight tests added, including switch-away and global-inheritance regressions for both mesh preflight call sites

@wpfleger96
wpfleger96 requested a review from a team as a code owner July 16, 2026 16:47

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: launch restore bypasses the new orphan guard. start_local_agent_with_preflight rejects a linked record whose definition is missing, but restore_managed_agents_on_launch still collects every local start_on_app_launch record, leaves a missing definition untouched at lines 177-182, and then calls spawn_agent_child in Phase B. That spawn path collapses the orphaned model/provider resolver result to (None, None) and continues, while effective_spawn_prompt can still read the materialized record prompt. An orphan configured to start on launch can therefore run despite the PR contract that orphaned linked instances cannot spawn. Please filter/persist an actionable error before Phase B (or put the guard at the shared spawn boundary) and add a restore-path regression test.

Also, the head is currently 13 commits behind main; please rebase and rerun CI before approval.

@wpfleger96
wpfleger96 force-pushed the duncan/agent-config-resolver branch 3 times, most recently from bd81f32 to 4e2ec85 Compare July 20, 2026 16:55

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: relay-mesh preflight still does not follow the new effective-config semantics. start_local_agent_with_preflight previews apply_persona_snapshot and passes that record to ensure_relay_mesh_for_record, but apply_persona_snapshot updates provider/model without clearing or recomputing the typed record.relay_mesh. relay_mesh_config falls back to that typed field whenever the current provider is not relay-mesh. Thus, after a linked definition changes from relay-mesh to another provider, the stale relay_mesh marker still triggers mesh bootstrap and can block an otherwise non-mesh start. The launch-restore preflight has the same issue after its re-snapshot.

Conversely, a definition/global resolution that inherits relay-mesh is not reliably represented by this record-only preview (especially a blank definition falling through to the global provider), so preflight can be skipped even though spawn resolves relay-mesh and emits its env.

Please drive preflight from resolve_effective_config (including global fallback), or construct a record/config whose provider, model, and typed mesh marker all match that resolution, and add switch-away plus global-inheritance regressions for interactive start and restore.

@wpfleger96
wpfleger96 force-pushed the duncan/agent-config-resolver branch from 4e2ec85 to 7da2ced Compare July 21, 2026 05:58
@wpfleger96
wpfleger96 requested a review from wesbillman July 21, 2026 07:12
@wpfleger96

Copy link
Copy Markdown
Member Author

hey @wesbillman this should be ready for another look — both directions from your last review are addressed now. The mesh preflights (interactive start and restore-on-launch) derive their decision from resolve_effective_config, the same resolution spawn uses, so the stale record.relay_mesh marker can't trip the preflight after switching a definition off relay-mesh, and a blank definition inheriting a relay-mesh global default now correctly triggers it. Deleted relay_mesh_config and the legacy env-var fallback entirely — record.relay_mesh has no code readers left. Spawn's mesh gate also routes through the same shared helper now so the two paths can't diverge on trim semantics. CI is green at 32c2eeddc.

…prompt

Linked agent instances now resolve effective model/provider/prompt through
a single resolver (effective_config.rs): definition -> global, never
consulting stale materialized record bytes. Editing the definition
reliably propagates on the next spawn/restart.

Previously three divergent resolution paths (record-first local spawn,
persona-first deploy, and persona_field_with_record_fallback snapshot)
could disagree. This unifies them at the shared spawn_agent_child boundary
so every caller (interactive start, launch restore,
start_managed_agent_process) inherits orphan refusal and correct resolution.

Key changes:
- resolve_effective_config() is the single source for model/provider/prompt
  at spawn, deploy, card-summary, and both relay-mesh preflights.
- Orphan guard: spawn, deploy, and mesh preflight block with a friendly
  error when the linked definition is missing/not synced.
- Backend rejects model/provider/prompt edits on linked records; frontend
  omits those fields for linked instances.
- spawn_config_hash digests the resolved model/provider so global default
  changes trip the restart badge for linked inherited agents.
- relay_mesh_model_id() unifies the mesh gate across spawn and preflight,
  eliminating the stale record.relay_mesh marker discrepancy.
- restart_eligible() predicate: orphaned instances never show "Restart
  required" since spawn refuses them.
- Deletes dead persona_field_with_record_fallback and spawn_orphan_refusal.
- Adds model_source to ManagedAgentSummary for card label (inherited vs
  explicit).

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 force-pushed the duncan/agent-config-resolver branch from 32c2eed to 6d0afda Compare July 23, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants