Files
orca/src
m4air 52b0d1295e fix(source-control-ai): an absent legacy customAgentCommand no longer crashes the settings pane
A settings.json whose legacy `commitMessageAi` block has no `customAgentCommand`
key made the reconciliation copy `undefined` in as an OWN property, which then
clobbered the `customAgentCommand: ''` default in the normalizer's
`{ ...defaults, ...base }` merge. Main loads that on every start and hands it to
the renderer over structured clone (which, unlike JSON, preserves an own
undefined key), so the state was sticky and self-perpetuating and the settings
pane threw "Cannot read properties of undefined (reading 'trim')" at the
page.settings boundary (crash report 21699b66, v1.4.199).

Fixed at the normalizer contract rather than the one call site: the normalizer
now reads an own key holding undefined as absent - on input, on the nested
per-operation instruction strings, and on its own output - so no consumer of
SourceControlAiSettings sees an off-type value. That also unblocks remote work:
the `SourceControlAiSettings` wire schema in `rpc-contract/git-params.ts` types
`customAgentCommand` as a required string, so the same profile failed param
validation for remote/SSH commit-message generation, not only the settings pane.

Behavior change, deliberate: a legacy core field (`enabled`, `agentId`,
`customPrompt`, `customAgentCommand`) that is *absent* from the legacy block now
reads as absence rather than as a rollback-build edit. Previously an absent field
compared unequal to the projected value, so it counted as "changed" and was
written back - which, once the normalizer stops adopting undefined, would reset
the field to its default. A saved `customAgentCommand` is now preserved and
`enabled: false` stays off instead of flipping on. All four fields are required
in `CommitMessageAiSettings`, so a well-formed legacy block written by any
rollback build is unaffected; a differential probe over 288 well-formed profiles
produces byte-identical output against the previous code.

Tests cover the pure normalizer contract, the reconciliation, and the real
Store load path that made the state sticky.
2026-09-10 22:54:40 -07:00
..