Skip to content

feat(profiles): two concurrent sessions in the same clone cannot hold different profiles — session-bound selection required #1240

Description

@daandradec

Before submitting

  • I searched open and closed issues and did not find a request for this feature. — Not applicable as written: a related request exists and I declare the relationship explicitly under "Additional context" below rather than claiming novelty.
  • I reviewed this request and removed credentials, tokens, private paths, hostnames, and other sensitive data.

Problem or opportunity

Two concurrent Pi sessions in the same clone cannot use different gentle profiles. Changing the active profile in one session rewrites the routing that the other session's later subagent launches will use, so parallel work has to be serialized: finish the work in session A, and only then switch profiles for session B.

The chain is reproducible and specific:

  1. The profile store is global and carries a single active marker.
  2. Applying a profile writes the routing authority (<config home>/models.json) and then materializes routing.
  3. Materialization targets Pi's agent home (<agent home>/subagents.json plus the agent frontmatter), which is a second, different home from the config home.
  4. Subagent launches re-resolve routing on every launch from the materialized stores, with no session-lifetime cache, so the other running session adopts the change mid-work — with the documented one-launch reconciliation lag.
  5. Review lens captures read the routing authority directly at capture time, so lens routing moves at the next capture.

The result: a second session's delegated agents silently change model, with no way for that session to hold its own choice. This is a per-session configuration boundary, not a host-specific concern.

Proposed outcome

An explicit, opt-in active-profile binding at the parent Pi session boundary, leaving today's global mechanism intact as the default. The invariants that matter for this report:

  • Concurrent parent sessions in the same clone can select different profiles without rewriting each other's routing.
  • A profile switch inside one session affects only that session's binding; running and already-queued children keep the routing resolved at launch.
  • New child launches inherit the parent session's current binding.
  • The binding survives session resume.
  • The effective profile, its scope, and its configuration source are visible in the UI.
  • Sessions without a binding behave exactly as today, and existing profile files need no migration.
  • The review lens read path is covered too, not only subagent launches: lens routing is read from the routing authority at capture time, so a session binding must govern that read as well.

Alternatives considered

Both existing mechanisms were audited against those invariants. Neither satisfies them.

Per-repository pin. This does solve parallel repositories, which is what the docs advertise it for. It does not solve parallel sessions:

  • The pin is a per-clone artifact with a single value, so two sessions in the same clone cannot hold different pins — the second selection overwrites the first.
  • It only governs subagent launches; the review lens capture path reads the routing authority directly and is unaffected by the pin.
  • It also does not isolate the global active marker or the materialized stores, so anything reading those still sees the shared state.

GENTLE_PI_CONFIG_HOME. This relocates the profile store and the routing authority, but not the materialization target, because the two homes are resolved independently:

  • config home = GENTLE_PI_CONFIG_HOME (profiles, routing authority, persona, guardrails, background policy, dev binary)
  • agent home = GENTLE_PI_AGENT_HOME / PI_CODING_AGENT_DIR (materialized subagents.json and agent frontmatter)

Relocating both would isolate the entire Pi agent home — agents, skills, authentication, and session history — which is a parallel installation rather than profile selection, and it is not discoverable as a profile feature. So even the most aggressive existing workaround leaves the invariant unmet.

Additional context

Relationship to an existing request. #1064 requests session-bound active profiles without global routing mutation and states the same central invariant. This report is not presented as independent novelty: it exists to supply what that request does not contain — a user-visible reproduction with the exact read and write paths, an audit showing that the two mechanisms currently offered do not meet the invariant (per-clone pin; config home without the agent home), and the same-clone concurrent-session case. Maintainers may prefer to fold this in as supporting evidence for #1064, and closing it as a duplicate is an acceptable outcome if that is the call.

Feasibility signal. Session-scoped machinery already ships in this codebase: the review-integration consent grants are bound to a live SessionManager, a non-empty session id, and the canonical Git common-directory identity, and the profile pin module already imports the session worktree registry. A session-bound profile binding is therefore consistent with the existing architecture rather than a new concept.

Environment. gentle-pi 3.3.0 (Pi client, macOS arm64), review contract v2, repository without a .pi/ directory, so only the global stores apply.

Note on the first checkbox. It cannot be answered affirmatively here: the search did find the related request above. It is reported rather than silently skipped.

No activity

Activity on this issue will appear here.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions