Skip to content

bug(profiles): applying a newly created empty profile wipes models.json and clears every agent's routing #1349

Description

@jonathanludena

Before submitting

  • I searched open and closed issues and did not find a report of this problem.
  • I reviewed this report and removed credentials, tokens, private paths, hostnames, and other sensitive data.

Problem

A profile created with c starts empty by design ("Create a new, empty profile"), and /gentle:models never writes into it. Its u action targets the current profile, resolved by resolveCurrentProfileTarget as the repository pin, else the globally active profile. So the natural operator flow — create a profile, configure the models, then select that profile — cannot populate the new profile: every configuration write lands in the previously active profile. The final enter (apply) on the still-empty profile then writes {} to ~/.pi/gentle-ai/models.json and replaces the materialized routing of every discoverable agent with clear entries, so all agents return to inherit. The whole model configuration is destroyed with no confirmation, no warning, and no recovery.

The panel already computes the exact signal for this state and renders it in the detail pane's "Profile routing" section ("No routing entries — every agent inherits its default model"), but enter acts on that state destructively instead of guarding it.

Because writing {} is a successful write, the compensation path already present in runProfilesPanelAction (revertClaim, which restores the previous active marker and the previously active profile's routing) never fires.

Steps to reproduce

  1. /gentle:profiles → press c → name the profile (for example hybrid). The store now holds "hybrid": {}.
  2. /gentle:models → assign model and effort to the agents → save with ctrl+s, or with u.
  3. /gentle:profiles → select hybrid → press enter to apply.

Observed after step 3: ~/.pi/gentle-ai/models.json is {}, ~/.pi/agent/subagents.json holds clear entries for every agent, and no confirmation was shown.

Step 2 is the decisive detail. Whichever save key is used, the just-created profile stays {}; u writes to the pinned profile or the globally active one, never to the new profile. An operator who expects "configure the models into the profile I just created" gets no error and no hint, because the global save succeeds and the panel reports success.

Expected and actual behavior

Expected: applying a profile that has zero routing entries either refuses with an actionable message, or asks for explicit confirmation that names the destructive effect (global routing replaced with {}, every omitted agent returned to inherit). The previous routing and active marker should remain recoverable.

Actual: enter silently replaces the global routing with {} and clears every agent's materialized route. Nothing is restored, reported, or reversible from the UI.

A second, independent behavior amplifies it: c creates the profile without any seed from the current routing, so the empty state is the default first touch of a new profile rather than an exceptional one. Seeding the new profile from the effective routing (the same snapshot s takes) would make the documented create-then-configure flow work.

Two independent occurrences on the same machine left the same artifact signature:

# profiles store backup: an empty profile became active
active: "<profile>", "<profile>": {}

# models.json backup: global routing wiped
{}

# subagents.json backup: materialized routing wiped
{}

This is not fixed as of 3.5.1. The case "apply" and case "create" blocks in extensions/gentle-ai.ts and lib/agent-profiles.ts are byte-identical between the installed 3.3.0 and the 3.5.1 tarball, so upgrading does not change the behavior.

Relevant code paths: runProfilesPanelAction (cases apply and create), resolveCurrentProfileTarget, updateCurrentProfileFromSavedRouting, withOmittedAgentsClearedAsync, writeModelConfigAsync, applyModelConfigAsync; createProfile, setActiveProfile, normalizeProfilesFile in lib/agent-profiles.ts.

Documented keys that feed the trap, from docs/readme-reference.md (Agent-model profiles): enter applies live and "replaces the routing of every agent"; c creates "a new, empty profile"; s snapshots the current routing into the selected profile. The safe sequence exists, but nothing in the UI steers a new profile toward s before enter is ever pressed.

gentle-pi version

3.3.0 (installed from npm; 3.5.1 verified to be identical in the affected code paths)

Pi version

0.86.1

Operating system

macOS

Relevant logs or error output (optional)

# after step 1 — the new profile is empty, active is still the previous profile
~/.pi/gentle-ai/profiles.json
  openai: 23 roles | hybrid: {} | active: "openai"

# after step 3 — the global routing is gone
~/.pi/gentle-ai/models.json
  {}                                  # held 23 routing entries immediately before `enter`

# same signature from an earlier occurrence in the same store
profiles.json.bak-<epoch>  -> active: "nan", "nan": {}
models.json.bak-<epoch>    -> {}
subagents.json.bak-<epoch> -> {}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions