Skip to content

fix(config-bridge): add harness-definition env tier and fix equal-value model override - #3580

Merged
wpfleger96 merged 6 commits into
mainfrom
duncan/effort-global-persona-display
Aug 3, 2026
Merged

fix(config-bridge): add harness-definition env tier and fix equal-value model override#3580
wpfleger96 merged 6 commits into
mainfrom
duncan/effort-global-persona-display

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Jul 29, 2026

Copy link
Copy Markdown
Member

All seven normalized config fields resolve through sanitized InheritedConfigTiers passed wholesale to read_config_surface. The reader's precedence tiers now match spawn's Layer 2b exactly — including harness-definition env — and the equal-value model-override regression is fixed.

Changes

config_bridge/types.rs — add InheritedConfigTiers: persona env, global env, harness definition env, structured model/provider/prompt for both tiers. Add HarnessDefault ConfigOrigin variant for harness-definition env values.

commands/agent_config.rsbuild_inherited_tiers now resolves the harness definition env using the same lookup path as spawn (record.runtimepersona.runtime → empty string) and applies sanitize_inherited_env to it. resolve_config_surface is unchanged in shape — tiers passed to the reader now include definition_env.

config_bridge/reader.rsenv_candidates extended to 4-element return (record, persona, global, definition). All five field builders that use env candidates now include the definition-env slot below global env and above the structured block, matching spawn Layer 2b. Magic configured[..6] slice replaced with configured[..configured.len()-1] (named split: all non-file candidates). Equal-value model-override arm falls through to the normal resolve path instead of early-returning RuntimeOverride, so the panel shows the baseline origin (e.g. BuzzExplicit) rather than a spurious "Live override" label for a no-op switch.

config_bridge/reader_tests_ext.rs — three new Layer 2b tests: definition env beats structured persona model, global env beats definition env, reserved-key-absent fallthrough.

commands/agent_config_tests.rsgenuine_explicit_live_switch_to_same_model_yields_clean_field updated to assert origin == BuzzExplicit (not RuntimeOverride); wrapped in with_no_goose_config for hermeticity. New reserved_key_in_definition_env_shaped_map_is_stripped_by_sanitize test pins the shared sanitization contract.

AgentConfigPanel.tsx / types.tsHarnessDefault origin variant wired end-to-end: TS union type and provenance sentence ("Inherited from harness definition").

@wpfleger96
wpfleger96 requested a review from a team as a code owner July 29, 2026 16:50
@wpfleger96
wpfleger96 force-pushed the duncan/effort-global-persona-display branch from f9f6646 to 40c7207 Compare July 29, 2026 17:29
@wpfleger96 wpfleger96 changed the title fix(agent-config): surface inherited thinking effort in profile panel fix(agent-config): surface inherited thinking effort via reader tiers Jul 29, 2026
@wpfleger96 wpfleger96 changed the title fix(agent-config): surface inherited thinking effort via reader tiers refactor(config-bridge): genericize read-side tier resolution Jul 29, 2026
@wpfleger96
wpfleger96 marked this pull request as draft July 29, 2026 22:01
@wpfleger96
wpfleger96 marked this pull request as ready for review July 31, 2026 17:09
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 and others added 5 commits July 31, 2026 13:19
build_thinking_field reads only the per-record env var, but the spawn
path also layers persona env (Layer 3b) and global env (Layer 3a) below
the record. Any agent inheriting effort from either inherited tier shows
no row in the Runtime panel even though the agent actually runs with
that effort level.

Apply the same inject + re-tag pattern resolve_config_surface already
uses for model/provider/prompt: detect whether the record had its own
effort (had_effort), try persona env first, fall back to global env,
inject whichever wins into the record before read_config_surface, then
re-tag the resulting BuzzExplicit field to PersonaDefault or GlobalDefault
to match its true provenance.

Precedence is unchanged: record > persona > global > absent.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…r findings

Restructure build_thinking_field to accept persona_effort and global_effort
as explicit tier parameters, resolving via the existing resolve_with_override
machinery at the correct precedence:

  record env (BuzzExplicit) > ACP configOption > persona > global > config file

The previous inject+retag approach planted persona/global values in the
record-env tier, which outranks ACP; a live ACP effort (e.g. Goose effort=low
set post-spawn) would be shadowed by the spawn baseline. The tiered reader
approach fixes this: ACP wins as primary with the inherited value as the
overridden secondary, exactly as resolve_with_override produces.

Remove all effort injection from resolve_config_surface and the five duplicate
inline tests, reducing agent_config.rs from 1365 to 1109 lines (gate: ≤1112).
Move the five acceptance-criteria tests to reader_tests.rs and add the
conflicting-ACP test Thufir required. Rebase onto origin/main to pick up
AgentDefinition.shared/catalog_source fields added in #3569.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
…elper

Add #[allow(clippy::too_many_arguments)] to build_thinking_field —
matching the identical allow already on build_model_field in the same file.

Delete persona_with_effort() from reader_tests.rs — it was no longer
called after the reader-tier rework landed its tests as direct
read_config_surface calls.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Replace inject+retag with sanitized InheritedConfigTiers passed wholesale
to read_config_surface. All seven normalized fields resolve through
field-specific candidate lists via resolve_with_override; no per-field
value params remain on the reader entry point.

Key changes:

- types.rs: add InheritedConfigTiers (persona_env, global_env, structured
  model/provider/prompt fields for both tiers).

- agent_config.rs: add sanitize_inherited_env(), non_blank(),
  build_inherited_tiers() at the command boundary — spawn-equivalent
  sanitization (reserved keys, malformed keys, NUL values, oversize values
  stripped). resolve_config_surface() shrinks to: clear definition-
  authoritative structured fields on persona-linked records, assemble
  sanitized tiers, call reader. Orphaned persona links yield empty persona
  tier; panel still renders from record/global.

- reader.rs: read_config_surface() takes &InheritedConfigTiers instead of
  per-field effort params. All builders use env_candidates() for spawn-
  order env tiers (record > persona > global). Env block sits wholly above
  structured block, matching spawn's descriptor.env-written-last contract.
  build_model_field() uses conditional candidate construction gated on
  model_overridden (excludes ACP when any configured candidate exists;
  equal-value switch yields clean field). build_system_prompt_field()
  includes global env BUZZ_ACP_SYSTEM_PROMPT as a real tier despite no
  structured GlobalAgentConfig.system_prompt. build_provider_field()
  restores structured persona/global baseline after env candidates.
  Deleted: apply_runtime_override(), retag_persona_default(),
  retag_global_default(), model_baseline param, persona_effort/global_effort
  params, resolve_effective_prompt_model_provider from metadata.rs.

- reader_tests.rs + reader_tests_ext.rs: all 33 original tests updated to
  new 4-param signature; new tests added for model matrix (8 cases),
  numerics inheritance, env-vs-structured collision (3 cases), invalid
  normalized-value sanitization, pass-3 prompt collision (record env beats
  record struct).

- agent_config_tests.rs (new): tests split out from agent_config.rs to keep
  both files under the 1000-line ratchet. Adds orphaned-link, reserved-key,
  and malformed-key sanitization tests for build_inherited_tiers.

Gates: just desktop-tauri-clippy, just desktop-tauri-fmt-check,
just desktop-tauri-test (1870 passed), just desktop-check all clean.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The test starts from an already-sanitized (absent) global env tier, so it
verifies post-sanitization fallthrough, not NUL stripping itself — that is
pinned at the command boundary in commands/agent_config_tests.rs.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 force-pushed the duncan/effort-global-persona-display branch from 83f21b7 to c07c2e3 Compare July 31, 2026 17:19
…ue model override

Task 1 — add harness-definition env tier (Layer 2b) to the reader.

Spawn layers harness_def.env between runtime metadata and global env
(readiness.rs Layer 2b). The reader's InheritedConfigTiers had no slot
for it, so a custom harness definition env value (e.g. GOOSE_MODEL=X)
would win at runtime while the panel showed a lower-tier value.

- Add definition_env: BTreeMap<String, String> to InheritedConfigTiers
  (populated by build_inherited_tiers using the same lookup path as spawn:
  record.runtime → persona.runtime → empty; sanitized with the same
  sanitize_inherited_env rules applied to persona/global env)
- Slot it below global_env and above the structured block in every field
  builder's candidate list, matching spawn's Layer 2b precedence
- Add HarnessDefault ConfigOrigin variant with UI label "Inherited from
  harness definition" in AgentConfigPanel.tsx and types.ts
- Replace the magic configured[..6] slice in build_model_field with
  configured[..configured.len()-1] (named split: all non-file candidates)
- Pin with 3 reader tests: definition_env_beats_structured_persona_model,
  global_env_beats_definition_env, reserved_key_absent_from_definition_env_falls_through
- Pin sanitization contract with reserved_key_in_definition_env_shaped_map_is_stripped_by_sanitize

Task 2 — fix equal-value model-override regression.

PR head stamped RuntimeOverride on the equal-value model_overridden arm
(ACP == baseline), which main preserved as the baseline origin.

Fix: in the equal-value arm, fall through to the normal resolve path
instead of returning a RuntimeOverride field. The normal path returns the
correct value/origin (e.g. BuzzExplicit) with no secondary row.

- Update genuine_explicit_live_switch_to_same_model_yields_clean_field to
  assert origin == BuzzExplicit (not RuntimeOverride) in addition to
  overridden_value == None / overridden_origin == None
- Add with_no_goose_config guard to that test so the fall-through to
  normal resolution cannot pick up ~/.config/goose/config.yaml as a
  spurious secondary (hermetic regardless of dev machine state)

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96 wpfleger96 changed the title refactor(config-bridge): genericize read-side tier resolution fix(config-bridge): add harness-definition env tier and fix equal-value model override Aug 1, 2026
@wpfleger96
wpfleger96 merged commit be95a8a into main Aug 3, 2026
27 checks passed
@wpfleger96
wpfleger96 deleted the duncan/effort-global-persona-display branch August 3, 2026 15:04
tlongwell-block pushed a commit that referenced this pull request Aug 3, 2026
The pre-push branch-skew hook correctly refused a tree CI will never test:
origin/main advanced over desktop/src/testing/e2eBridge.ts, which this
branch also carries via its base. Merging the PR's own base rather than
origin/main directly: 4c257c8 already contains current main (5e0efb0)
AND Max's resolution of that exact e2eBridge.ts overlap, certified with
Desktop Smoke E2E (1) green. Re-resolving main's conflict here would
duplicate that work and risk diverging from it.

Merge-only, no rebase, no force. merge-tree reported 0 conflicts.

Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz>
Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@buzz.block.builderlab.xyz>

* origin/max/tui-renderer:
  fix(desktop): disambiguate provider API key labels and annotate mint key (#4406)
  fix(desktop): make OpenAI key re-enterable after first save in card mint dialog (#4140)
  fix(config-bridge): add harness-definition env tier and fix equal-value model override (#3580)
  test(desktop): prove channel repair boundary
  Polish mobile composer and messaging UI (#3918)
  ci(linux): enable mesh-llm feature in Linux release and canary builds (#4524)
  test(desktop): arm validation error before read
  test(desktop): atomically start channel validation
  fix(desktop): retain terminal focus on viewport click
  test(desktop): isolate deferred channel read
  fix(desktop): stop the terminal fade clobbering the app surface's compositor hint
  Revert "Merge PR #4523: close channel validation latch race"
  test(desktop): close channel validation latch race
wpfleger96 pushed a commit that referenced this pull request Aug 3, 2026
…ed-unread

* origin/main: (44 commits)
  chore(release): release Buzz Desktop version 0.5.4 (#4562)
  test(mobile): assert follow boundary semantics (#4559)
  docs(release): align desktop handoff instructions (#3988)
  fix: report agent usage per provider round, not once per turn (#4545)
  fix(desktop): harden Windows installs against Defender block and orphaned Node (#4382)
  feat(desktop): improve channel template discovery (#4549)
  fix(desktop): save key backups to authorized path (#4022)
  Add channel activity hover menu (#3935)
  feat(desktop): show saved Run on settings when editing an agent (#4539)
  fix(desktop): disambiguate provider API key labels and annotate mint key (#4406)
  fix(desktop): make OpenAI key re-enterable after first save in card mint dialog (#4140)
  fix(config-bridge): add harness-definition env tier and fix equal-value model override (#3580)
  Polish mobile composer and messaging UI (#3918)
  ci(linux): enable mesh-llm feature in Linux release and canary builds (#4524)
  fix(desktop): stop the create-agent provider config probe from erasing keystrokes (#4411)
  fix(mobile): recover and pace live subscriptions (#3053)
  feat(acp): deliver system prompt via _meta.systemPrompt for claude-agent-acp (#4395)
  fix(security): bump nostr crates for RUSTSEC-2026-0225..0232 + default sprig image to published digest (#4392)
  fix(desktop): back/forward via keyboard chords, mouse X1/X2 buttons, and swipe gestures (#3778)
  feat(k8s): Kubernetes backend plugin + desktop deploy path (#4289)
  ...

Signed-off-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
wpfleger96 added a commit that referenced this pull request Aug 3, 2026
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>

* origin/main: (40 commits)
  fix(mobile): recover stale relay sessions (#4372)
  chore(release): release Buzz Desktop version 0.5.4 (#4562)
  test(mobile): assert follow boundary semantics (#4559)
  docs(release): align desktop handoff instructions (#3988)
  fix: report agent usage per provider round, not once per turn (#4545)
  fix(desktop): harden Windows installs against Defender block and orphaned Node (#4382)
  feat(desktop): improve channel template discovery (#4549)
  fix(desktop): save key backups to authorized path (#4022)
  Add channel activity hover menu (#3935)
  feat(desktop): show saved Run on settings when editing an agent (#4539)
  fix(desktop): disambiguate provider API key labels and annotate mint key (#4406)
  fix(desktop): make OpenAI key re-enterable after first save in card mint dialog (#4140)
  fix(config-bridge): add harness-definition env tier and fix equal-value model override (#3580)
  Polish mobile composer and messaging UI (#3918)
  ci(linux): enable mesh-llm feature in Linux release and canary builds (#4524)
  fix(desktop): stop the create-agent provider config probe from erasing keystrokes (#4411)
  fix(mobile): recover and pace live subscriptions (#3053)
  feat(acp): deliver system prompt via _meta.systemPrompt for claude-agent-acp (#4395)
  fix(security): bump nostr crates for RUSTSEC-2026-0225..0232 + default sprig image to published digest (#4392)
  fix(desktop): back/forward via keyboard chords, mouse X1/X2 buttons, and swipe gestures (#3778)
  ...
wpfleger96 added a commit that referenced this pull request Aug 3, 2026
Syncs Cargo.lock and ci.yml updates from origin/main via the umbrella, which
resolves the RUSTSEC-2026-0225..0229 nostr advisory failures in the Security gate.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>

* commit 'ad9ae1dbb0c2d9b6839c1e18d6fd6a78238b61fb': (40 commits)
  fix(mobile): recover stale relay sessions (#4372)
  chore(release): release Buzz Desktop version 0.5.4 (#4562)
  test(mobile): assert follow boundary semantics (#4559)
  docs(release): align desktop handoff instructions (#3988)
  fix: report agent usage per provider round, not once per turn (#4545)
  fix(desktop): harden Windows installs against Defender block and orphaned Node (#4382)
  feat(desktop): improve channel template discovery (#4549)
  fix(desktop): save key backups to authorized path (#4022)
  Add channel activity hover menu (#3935)
  feat(desktop): show saved Run on settings when editing an agent (#4539)
  fix(desktop): disambiguate provider API key labels and annotate mint key (#4406)
  fix(desktop): make OpenAI key re-enterable after first save in card mint dialog (#4140)
  fix(config-bridge): add harness-definition env tier and fix equal-value model override (#3580)
  Polish mobile composer and messaging UI (#3918)
  ci(linux): enable mesh-llm feature in Linux release and canary builds (#4524)
  fix(desktop): stop the create-agent provider config probe from erasing keystrokes (#4411)
  fix(mobile): recover and pace live subscriptions (#3053)
  feat(acp): deliver system prompt via _meta.systemPrompt for claude-agent-acp (#4395)
  fix(security): bump nostr crates for RUSTSEC-2026-0225..0232 + default sprig image to published digest (#4392)
  fix(desktop): back/forward via keyboard chords, mouse X1/X2 buttons, and swipe gestures (#3778)
  ...
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