ワンクリックで
workspace-isolation
Workspace isolation boundaries.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Workspace isolation boundaries.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Iterative multi-round codebase audit with diminishing-returns detection. Run 5-20+ rounds, each focusing on one specific area. Built from 19 rounds of dogfooding pi-crew on itself.
Pi TUI crew widget data sources, display priority, and rendering performance.
Multi-phase orchestration for planners and executors.
Spawn 3 adversarial subagents (Skeptic, Pragmatist, Critic) to evaluate a decision, architecture choice, or plan. Anti-anchoring: each role receives ONLY the question, not conversation history. Aggregates votes into consensus recommendation with dissent tracking. Use when facing critical decisions, architecture choices, security tradeoffs, or plan reviews where single-perspective analysis is insufficient.
Background worker, heartbeat, stale-run, crash-recovery, and deadletter workflow. Use when debugging stuck/dead workers or changing async run reliability.
Child Pi worker spawning, lifecycle callbacks, and failure modes.
| name | workspace-isolation |
| description | Workspace isolation boundaries. |
| origin | pi-crew |
| triggers | ["workspace isolation","cross-workspace access","escape boundary","worktree safety","agent isolation"] |
pi-crew enforces workspace isolation so that agents, runs, and live sessions from one project folder cannot be accessed from another. The workspace boundary is manifest.cwd — the directory where a run was initiated.
manifest.cwd is the canonical workspace root. Every run record carries the directory where it was created.
Why it matters: Pi can have multiple workspace folders open simultaneously. Without isolation, an agent from workspace A could be steered/controlled from workspace B.
Rules:
manifest.cwd is set at creation timeworkspaceId = manifest.cwdmanifest.cwdLiveAgentHandle.workspaceId field (added to prevent cross-workspace access):
interface LiveAgentHandle {
// ... other fields
/** Workspace where this agent was spawned — used for session-scoped visibility. */
workspaceId: string;
}
Enforcement in api.ts (team-tool operations):
// list-active-live-agents: filter by workspace
listActiveLiveAgentsByWorkspace(manifest.cwd);
// steer-agent, follow-up-agent, stop-agent, resume-agent:
const live = getLiveAgent(agentId);
if (live && live.workspaceId !== manifest.cwd)
return result(`Live agent '${agentId}' does not belong to workspace ${manifest.cwd}.`, { status: "error" }, true);
Enforcement in live-agent-manager.ts:
// listLiveAgentsByWorkspace(workspaceId): filter by workspaceId
export function listLiveAgentsByWorkspace(workspaceId: string): LiveAgentHandle[] {
return listLiveAgents().filter((a) => a.workspaceId === workspaceId);
}
single (default)manifest.cwd)worktree (parallel isolation)<repo-root>/.worktrees/<runId>/<taskId>/crew/<runId>-<taskId> (sanitized)Entry point in team-runner.ts:
const worktree = workspaceMode === "worktree" && task.worktree !== undefined
? { path: task.worktree.path, branch: task.worktree.branch, reused: task.worktree.reused }
: undefined;
Worktree lifecycle:
Creation (prepareTaskWorkspace in worktree-manager.ts):
assertCleanLeader)git worktree add <path> <branch>node_modules if presentNaming convention:
Branch: crew/<sanitized-runId>-<sanitized-taskId>
Path: .worktrees/<runId>/<taskId>/
Cleanup (on task/run completion):
git worktree remove <path> --force (only if force=true)Safety rules:
In api.ts (handleTeamToolCall):
if (operation === "list-live-agents") {
return result(JSON.stringify(
listActiveLiveAgentsByWorkspace(loaded.manifest.cwd), // ← filtered by workspace
null, 2
), { action: "api", status: "ok", runId: loaded.manifest.runId });
}
In cancel.ts:
In respond.ts:
In crash-recovery.ts:
purgeStaleActiveRunIndex only affects runs in the current workspace (cwd)reconcileAllStaleRuns only scans the current workspace's .crew/state/runs/LiveSessionConfig carries workspaceId:
interface LiveSessionConfig {
// ... other fields
/** Workspace directory — used for path containment and isolation. */
workspaceId: string;
}
Propagation chain:
team-tool.ts (handleTeamToolCall)
→ TeamContext { workspaceId: cwd }
→ LiveSessionConfig { workspaceId }
→ registerLiveAgent({ workspaceId })
→ LiveAgentHandle { workspaceId }
defaults.ts isolation settings:
const DEFAULT_PATHS = {
crewRoot: ".crew", // under project root
stateRoot: ".crew/state", // under project root
};
All paths are resolved relative to manifest.cwd, ensuring state stays under the project root.
Before performing cross-workspace operations, verify:
If ANY answer is NO → Stop. Verify workspace isolation before proceeding.
resolveContainedPath to ensure paths stay under workspace root.ownerSessionId.resolveRealContainedPath to resolve symlinks and detect escape attempts.src/extension/team-tool/api.ts — workspaceId filter in list-live-agents, steer-agent, follow-up-agent, stop-agent, resume-agentsrc/runtime/live-agent-manager.ts — workspaceId in LiveAgentHandle, listLiveAgentsByWorkspace, listActiveLiveAgentsByWorkspacesrc/runtime/live-session-runtime.ts — LiveSessionConfig, workspaceId in session creationsrc/runtime/team-runner.ts — workspaceId passed through executeTeamRunsrc/state/state-store.ts — initRunManifest with cwd, manifest.cwdsrc/worktree/worktree-manager.ts — prepareTaskWorkspace, assertCleanLeader, linkNodeModulesIfPresentsrc/config/defaults.ts — DEFAULT_PATHS (state under project root)cd pi-crew
# Verify workspace filter in list-live-agents
node --experimental-strip-types -e "
import { listLiveAgentsByWorkspace, listActiveLiveAgentsByWorkspace } from './src/runtime/live-agent-manager.ts';
console.log('By workspace:', listLiveAgentsByWorkspace(process.cwd()).length);
console.log('Active by workspace:', listActiveLiveAgentsByWorkspace(process.cwd()).length);
"
# Verify worktree creation
node --experimental-strip-types -e "
import { prepareTaskWorkspace } from './src/worktree/worktree-manager.ts';
// Requires a clean git repo and workspaceMode='worktree'
"
npx tsc --noEmit
node --experimental-strip-types --test test/unit/worktree-manager.test.ts test/unit/isolation-policy.test.ts
npm test