Summary
The subagent tool spawns child subagent sessions in the pi session cwd, not the dispatch target's cwd. The "Work from: …" prose in the dispatch task text is not enforced. A child can therefore read (and potentially write) any repo reachable from the session cwd, including unrelated sibling projects. Additionally, because the child can see other sessions' on-disk artifacts (e.g. another project's .superpowers/sdd/ ledger), it can confabulate ownership of pre-existing work it merely read.
Evidence (surfaced while dogfooding armory-fleet on itself for SPEC-6-3)
- A pi session was started in
~/local-dev/getpipher/keystone (a separate, active SDD run in another pane). armory-fleet work was driven from that session by pasting an armory-fleet handoff.
- Tasks 1–7 subagents honored the "Work from: ~/local-dev/getpipher/armory-fleet" prose and
cd'd there correctly.
- The Task 8 subagent, spawned in the keystone cwd, read keystone's
.superpowers/sdd/ ledger (a parallel SDD run) and falsely claimed credit for "keystone Task 7" (commit 1ec048e) in its response text — even though that commit was made by the separate keystone session ~2 min before the armory-fleet subagent ran. The subagent's actual report file was armory-fleet-only (0 keystone mentions) and its real commit (6e0be06) was clean armory-fleet. No cross-repo write occurred — the fault was a confabulation, not a real leak.
Impact
- Low in practice (this instance): zero cross-session writes; the armory-fleet commit was clean and the sibling session's work was intact. The only artifact was a misleading response text, caught by verifying the report file + git.
- Higher in principle: a subagent scoped to project X can read/write sibling repos reachable from the session cwd. If a future subagent goes rogue (or just gets confused), it could make real commits in the wrong repo. The normal usage pattern (start pi in the project you're working on → session cwd == dispatch target) doesn't trigger it; the edge case is driving project X from a session whose cwd is project Y.
Proposed fix
Add a cwd concept the child subagent cannot escape:
- The
subagent tool accepts an explicit cwd (default = the dispatching project's cwd, NOT the session cwd).
- The child's working directory is pinned to
cwd; operations (read/write/bash/git) outside it are rejected or sandboxed.
- Equivalently: pin the child session's
ResourceLoader + cwd to the dispatch target so it cannot even see sibling repos — which also prevents the confabulation at the source (can't claim credit for what it can't see).
This deserves its own brainstorm → spec → plan (default-cwd semantics, panel Run-action interaction, relative-skill-path implications), not a hot-patch.
Repro
- Start pi in repo A (
~/local-dev/<org>/A).
- From that session, dispatch
subagent({ task: "<work for repo B at ~/local-dev/<org>/B>" }) where the task text says "Work from: ~/local-dev//B".
- Observe the child spawns in A's cwd (the session cwd); it can
ls/read A's files (and any sibling) despite the task targeting B.
- If A has SDD/agent artifacts on disk, the child may read + reference them in its response (confabulation risk).
Mitigation in the meantime
Dispatch prompts explicitly instruct: "cd to FIRST; do not read/write/commit in any other directory; ignore any .superpowers/sdd/ or repo artifacts not in ; claim only work you actually performed." Sufficient for trusted single-session use; not a substitute for the cwd-isolation fix.
Proposed disposition
Tracked enhancement — candidate for a dedicated fix(subagent): patch or a SPEC-6-4 item, not a v0.12.0 blocker (zero actual harm; normal usage doesn't trigger it).
Summary
The
subagenttool spawns child subagent sessions in the pi session cwd, not the dispatch target's cwd. The "Work from: …" prose in the dispatch task text is not enforced. A child can therefore read (and potentially write) any repo reachable from the session cwd, including unrelated sibling projects. Additionally, because the child can see other sessions' on-disk artifacts (e.g. another project's.superpowers/sdd/ledger), it can confabulate ownership of pre-existing work it merely read.Evidence (surfaced while dogfooding armory-fleet on itself for SPEC-6-3)
~/local-dev/getpipher/keystone(a separate, active SDD run in another pane). armory-fleet work was driven from that session by pasting an armory-fleet handoff.cd'd there correctly..superpowers/sdd/ledger (a parallel SDD run) and falsely claimed credit for "keystone Task 7" (commit1ec048e) in its response text — even though that commit was made by the separate keystone session ~2 min before the armory-fleet subagent ran. The subagent's actual report file was armory-fleet-only (0 keystone mentions) and its real commit (6e0be06) was clean armory-fleet. No cross-repo write occurred — the fault was a confabulation, not a real leak.Impact
Proposed fix
Add a
cwdconcept the child subagent cannot escape:subagenttool accepts an explicitcwd(default = the dispatching project's cwd, NOT the session cwd).cwd; operations (read/write/bash/git) outside it are rejected or sandboxed.ResourceLoader+ cwd to the dispatch target so it cannot even see sibling repos — which also prevents the confabulation at the source (can't claim credit for what it can't see).This deserves its own brainstorm → spec → plan (default-cwd semantics, panel Run-action interaction, relative-skill-path implications), not a hot-patch.
Repro
~/local-dev/<org>/A).subagent({ task: "<work for repo B at ~/local-dev/<org>/B>" })where the task text says "Work from: ~/local-dev//B".ls/read A's files (and any sibling) despite the task targeting B.Mitigation in the meantime
Dispatch prompts explicitly instruct: "cd to FIRST; do not read/write/commit in any other directory; ignore any
.superpowers/sdd/or repo artifacts not in ; claim only work you actually performed." Sufficient for trusted single-session use; not a substitute for the cwd-isolation fix.Proposed disposition
Tracked enhancement — candidate for a dedicated
fix(subagent):patch or a SPEC-6-4 item, not a v0.12.0 blocker (zero actual harm; normal usage doesn't trigger it).