@@ -172,9 +172,6 @@ func (s *ConfigStore) atomicWrite(scope Scope, fn func(current []byte) ([]byte,
172 return err
172 return err
175− if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
176− return fmt.Errorf("create config directory: %w", err)
178 return atomicWriteFile(path, newData, 0o600)
175 return atomicWriteFile(path, newData, 0o600)
@@ -221,11 +218,20 @@ func (s *ConfigStore) SetConfigField(scope Scope, key string, value any) error {
221// The write is protected by an in-process mutex and a cross-process flock
218// The write is protected by an in-process mutex and a cross-process flock
222// to prevent races between concurrent writers in different processes.
219// to prevent races between concurrent writers in different processes.
223func (s *ConfigStore) SetConfigFields(scope Scope, kv map[string]any) error {
220func (s *ConfigStore) SetConfigFields(scope Scope, kv map[string]any) error {
221+ // Sort keys for deterministic output regardless of map iteration
222+ // order. This also ensures consistent results when callers pass
223+ // overlapping JSONPath keys (e.g. "a" and "a.b").
224+ keys := make([]string, 0, len(kv))
226+ keys = append(keys, k)
224 err := s.atomicWrite(scope, func(data []byte) ([]byte, error) {
230 err := s.atomicWrite(scope, func(data []byte) ([]byte, error) {
225 v := string(data)
231 v := string(data)
226− for key, value := range kv {
232+ for _, key := range keys {
227 var sErr error
233 var sErr error
228− v, sErr = sjson.Set(v, key, value)
234+ v, sErr = sjson.Set(v, key, kv[key])
229 if sErr != nil {
235 if sErr != nil {
230 return nil, fmt.Errorf("failed to set config field %s: %w", key, sErr)
236 return nil, fmt.Errorf("failed to set config field %s: %w", key, sErr)