github / github/copilot-cli

/spawn command template instructs the agent to reuse an existing session, contradicting its own singular-spawn contract - and no approval gate on the resulting cross-session write

Open
#4,491 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:agents area:sessions
Dominant language
Shell
Stars
11.2k
Forks
1.9k
Avg merge
14h 16m
Merged PRs (30d)
6

Description

Describe the bug

The /spawn command's expanded prompt template contradicts itself, and the contradiction resolves in the destructive direction: it can silently turn "create a child session" into "inject context into an unrelated running session."

The template opens with a singular-spawn contract:

Spawn exactly ONE child session — this is the singular gesture, not a fan-out.

Step 3 then instructs create_session with a complete standalone kickoff.prompt. But step 2 says:

Check list_sessions_and_chats so you reuse an existing session instead of creating a duplicate for work already in flight.

Step 2 contradicts both. When it wins, the result is a send_session_message into a different session — a fundamentally different action from the one /spawn promises, with a different blast radius, executed with no confirmation.

What happened

I invoked /spawn explicitly with this appended instruction:

a session to focus on addressing this narrowness. What guidance files need to be updated to ensure next times it happens correctly? The session will be interactive and not change anything until the user is happy.

Nothing there names or implies an existing session. The agent replied:

Reused the existing "Interactive ingestion rules" session in the 2ndBrain repository rather than creating a duplicate. It will inspect the relevant guidance files and propose precise updates—without modifying anything until you approve them.

That is step 2's language, near-verbatim. The agent followed the spec. The target it selected was a sibling session created seven minutes earlier on an adjacent topic — plausible under a loose reading of "work already in flight," and actively wrong: that session had its own task, and the injection redirected it.

Expected behavior

/spawn creates a new session. If the agent believes an existing session is a better target, it surfaces the candidate and asks — it does not substitute silently.

What's defective in step 2
  1. It contradicts the command's own stated contract. The template says "singular gesture" and "call create_session", then instructs reuse.
  2. "Work already in flight" is unbounded. No similarity threshold, no recency bound, no repo/task scoping. Topical adjacency is enough to trigger it.
  3. Reuse is silent. No confirmation before the write; the user finds out after it has landed.
  4. The two branches have asymmetric blast radii. Spawning a superfluous session is additive and trivially discarded. Reuse mutates a running session's conversation — it corrupts work in progress, and the damage isn't visible until that session produces a wrong result. Deduplication logic should never silently pick the destructive branch.

Point 4 is the core of it: this is framed as a deduplication nicety, but the "duplicate" it avoids is cheap while the mutation it performs is not.

Suggested fix

Either:

  • Remove step 2. /spawn means spawn. Deduplication across existing work belongs in /orchestrate or /fleet, where multi-session coordination is the explicit contract; or
  • Make detection advisory. Keep the list_sessions_and_chats check, but require explicit user confirmation — showing target session name/ID and a preview of the message — before messaging instead of creating.
Related: no permission surface for cross-session writes

This is what let a template ambiguity become a silent mutation, and it stands independently of the /spawn fix.

permissions-config.json supports write, shell, and mcp approvals, but has no concept of "this agent may inject context into another session." Cross-session messaging appears to be the only side-effecting capability with no permission surface at all. Worth adding a permission kind for it, and/or a policy such as alwaysAskBeforeCrossSessionMessage, defaulting to on.

Workaround

I added rules to ~/.copilot/copilot-instructions.md requiring ask_user approval before any send_session_message, and forbidding substitution of an existing session for a spawn request. This helps, but it's instruction-level guidance competing with the command template's own step 2 — it degrades under context pressure and doesn't protect users who don't know to write it.

Related issues
  • #2436 (Cross-Session Context Querying) proposes expanding cross-session reach, including a "session-as-agent" model — roughly the capability that misfired here. It doesn't discuss consent or approval. The more this capability grows, the more it needs a boundary; the two issues are complementary, not competing.
  • #4153 (closed) — create_session dropped kickoff prompts. A different spawn-path bug, but adjacent.
Versions

Copilot CLI / App version: 1.0.79-9
OS: Windows

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Inspect the /spawn expanded prompt, especially step 2, alongside permissions-config.json and the create_session and send_session_message entry points. Determine how spawning and cross-session writes are currently handled; done means /spawn creates a child session or asks for confirmation before reusing one, with cross-session messaging covered by an approval policy.

Written by the indexing model from the issue text.

Assessment

Tech stack
shell
Domain
authorization, cli, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.