fix(namepool): only persist runtime state, not config in state file

The pool state file was saving CustomNames even though Load() ignored
them (CustomNames come from settings/config.json). This caused the
state file to have stale/incorrect custom names data.

Changes:
- Create namePoolState struct for persisting only OverflowNext/MaxSize
- Save() now only writes runtime state, not configuration
- Load() uses the same struct for consistency
- Removed redundant runtime pool update from runNamepoolAdd since
  the settings file is the source of truth for custom names

Fixes: gt-ofqzwv

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gastown/crew/dennis
2026-01-17 01:11:14 -08:00
committed by Steve Yegge
parent 5823c9fb36
commit bda1dc97c5
2 changed files with 25 additions and 17 deletions

View File

@@ -247,15 +247,9 @@ func runNamepoolAdd(cmd *cobra.Command, args []string) error {
return fmt.Errorf("saving settings: %w", err)
}
// Also update runtime pool for immediate use
pool := polecat.NewNamePool(rigPath, rigName)
if err := pool.Load(); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("loading pool: %w", err)
}
pool.AddCustomName(name)
if err := pool.Save(); err != nil {
return fmt.Errorf("saving pool: %w", err)
}
// Note: No need to update runtime pool state - the settings file is the source
// of truth for custom names. The pool state file only persists OverflowNext/MaxSize.
// New managers will load custom names from settings/config.json.
fmt.Printf("Added '%s' to the name pool\n", name)
return nil

View File

@@ -163,17 +163,14 @@ func (p *NamePool) Load() error {
return err
}
var loaded NamePool
// Load only runtime state - Theme and CustomNames come from settings/config.json.
// ZFC: InUse is NEVER loaded from disk - it's transient state derived
// from filesystem via Reconcile(). Always start with empty map.
var loaded namePoolState
if err := json.Unmarshal(data, &loaded); err != nil {
return err
}
// Note: Theme and CustomNames are NOT loaded from state file.
// They are configuration (from settings/config.json), not runtime state.
// The state file only persists OverflowNext and MaxSize.
//
// ZFC: InUse is NEVER loaded from disk - it's transient state derived
// from filesystem via Reconcile(). Always start with empty map.
p.InUse = make(map[string]bool)
p.OverflowNext = loaded.OverflowNext
@@ -187,7 +184,17 @@ func (p *NamePool) Load() error {
return nil
}
// namePoolState is the subset of NamePool that is persisted to the state file.
// Only runtime state is saved, not configuration (Theme, CustomNames come from settings).
type namePoolState struct {
RigName string `json:"rig_name"`
OverflowNext int `json:"overflow_next"`
MaxSize int `json:"max_size"`
}
// Save persists the pool state to disk using atomic write.
// Only runtime state (OverflowNext, MaxSize) is saved - configuration like
// Theme and CustomNames come from settings/config.json and are not persisted here.
func (p *NamePool) Save() error {
p.mu.RLock()
defer p.mu.RUnlock()
@@ -197,7 +204,14 @@ func (p *NamePool) Save() error {
return err
}
return util.AtomicWriteJSON(p.stateFile, p)
// Only save runtime state, not configuration
state := namePoolState{
RigName: p.RigName,
OverflowNext: p.OverflowNext,
MaxSize: p.MaxSize,
}
return util.AtomicWriteJSON(p.stateFile, state)
}
// Allocate returns a name from the pool.