Skip to content

fix(agents): canonicalize stale persona harness pins - #4631

Open
wpfleger96 wants to merge 1 commit into
mainfrom
hayt/stale-pin-carveout
Open

fix(agents): canonicalize stale persona harness pins#4631
wpfleger96 wants to merge 1 commit into
mainfrom
hayt/stale-pin-carveout

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Aug 3, 2026

Copy link
Copy Markdown
Member

Replace the stale agent_command_override drop logic in apply_persona_snapshot with a three-tier canonical command resolver.

What this fixes

The old code dropped a create-time harness pin when the persona switched to a different runtime, but it had two failure modes:

  1. Preset harnesses invisible. known_acp_runtime_exact() only searches KNOWN_ACP_RUNTIMES (builtins). Preset harnesses such as OpenClaw live in PRESET_HARNESSES, so the destination lookup returned None and the outer if let branch never executed — a Goose→OpenClaw persona switch left the stale Goose override in place, keeping the agent running Goose instead of OpenClaw.

  2. Pin-side canonical resolution incomplete. The pin was resolved by known_acp_runtime(), which searches by id/command/alias and returns a &KnownAcpRuntime entry correctly. However, if the pin named an alias (e.g. claude-code-acp) and the destination was a preset harness absent from builtins, the outer guard still failed for the same reason as (1). The alias regression test pins the requirement that the canonical resolver must handle both sides: alias pins must be recognised and drops must fire when the destination is a known preset.

How it works now

canonical_harness_command(input) accepts any form a stored override can take — bare command, alias, path prefix, or runtime id — and resolves it to the harness primary command through three tiers:

  1. BuiltinsKNOWN_ACP_RUNTIMES, matched by id/command/alias.
  2. Static presetsPRESET_HARNESSES, matched by id or normalised command.
  3. Loaded registry — custom/preset definitions loaded at runtime.

command_for_runtime_id (id-only input, same three tiers) replaces the two-step known_acp_runtime_exact/lookup_loaded_harness_by_id pattern in record_agent_command, effective_agent_command, and try_record_agent_command, adding the static preset tier so preset harnesses resolve correctly even without a warm registry.

Changed files

  • discovery/presets.rspreset_command_for_id, command_for_runtime_id, canonical_harness_command
  • discovery.rs — re-export new functions; make normalize_command_identity pub(crate); refactor three command-resolution functions to use command_for_runtime_id
  • custom_harnesses.rsloaded_harness_registry visibility fnpub(super) (needed by canonical_harness_command)
  • persona_events.rs — replace two-step known_acp_runtime_exact/known_acp_runtime + pointer comparison with canonical-command comparison
  • persona_events/stale_pin_tests.rs (new) — four regression tests: Goose→OpenClaw drop, OpenClaw→Goose drop, claude-code-acp alias→OpenClaw drop, same-harness path keep
  • persona_events/tests.rssample_record/sample_persona exposed as pub(super) for the new test module

… command resolver

The previous apply_persona_snapshot stale-pin check used known_acp_runtime_exact
+ known_acp_runtime with a pointer comparison to decide whether to drop a
create-time agent_command_override. This had two failure modes:

1. Aliases (e.g. "claude-code-acp") are not the primary command and
   known_acp_runtime returns a different static slot — the pointer comparison
   treats them as different harnesses and drops the pin even when the persona
   stays on Claude.
2. Preset harnesses (e.g. openclaw) are not in KNOWN_ACP_RUNTIMES so
   known_acp_runtime_exact returns None and the pin is silently kept, meaning
   a Goose→OpenClaw persona switch leaves a stale Goose override running.

Replace with canonical_harness_command, a three-tier resolver (builtins →
static presets → loaded registry) that accepts either a runtime id or any
command form (alias, path prefix, bare name). Comparison is on canonical
primary commands so switching harnesses always drops the stale pin, while
same-harness path overrides (e.g. /usr/local/bin/goose) are kept.

Also consolidate the two-step known_acp_runtime_exact/lookup_loaded_harness_by_id
pattern in record_agent_command, effective_agent_command, and
try_record_agent_command into command_for_runtime_id — a shared three-tier
lookup that adds the static preset tier so preset harnesses resolve correctly
even with a cold registry.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 requested a review from a team as a code owner August 3, 2026 22:31
@wpfleger96 wpfleger96 changed the title fix(agents): replace pointer-comparison stale-pin drop with canonical command resolver fix(agents): canonicalize stale persona harness pins Aug 3, 2026
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.

1 participant