diff --git a/agents/gsd-debugger.md b/agents/gsd-debugger.md
index 8c7109032..3ed354166 100644
--- a/agents/gsd-debugger.md
+++ b/agents/gsd-debugger.md
@@ -2,6 +2,7 @@
name: gsd-debugger
description: Investigates bugs using scientific method, manages debug sessions, handles checkpoints. Spawned by /gsd:debug orchestrator.
tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch
+permissionMode: acceptEdits
color: orange
# hooks:
# PostToolUse:
diff --git a/agents/gsd-executor.md b/agents/gsd-executor.md
index a7673e6f0..03cbf9b3e 100644
--- a/agents/gsd-executor.md
+++ b/agents/gsd-executor.md
@@ -2,6 +2,7 @@
name: gsd-executor
description: Executes GSD plans with atomic commits, deviation handling, checkpoint protocols, and state management. Spawned by execute-phase orchestrator or execute-plan command.
tools: Read, Write, Edit, Bash, Grep, Glob
+permissionMode: acceptEdits
color: yellow
# hooks:
# PostToolUse:
diff --git a/get-shit-done/workflows/map-codebase.md b/get-shit-done/workflows/map-codebase.md
index 7c0e44bf2..ed061f504 100644
--- a/get-shit-done/workflows/map-codebase.md
+++ b/get-shit-done/workflows/map-codebase.md
@@ -85,10 +85,7 @@ Continue to spawn_agents.
Before spawning agents, detect whether the current runtime supports the `Task` tool for subagent delegation.
-**Runtimes with Task tool:** Claude Code, Cursor, OpenCode (native subagent support via `Task` or `task`)
-**Runtimes WITHOUT Task tool:** Antigravity, Gemini CLI, Codex, and others
-
-**How to detect:** Check if you have access to a `Task` or `task` tool (either casing counts). If you do NOT have a Task/task tool (or only have tools like `browser_subagent` which is for web browsing, NOT code analysis):
+**How to detect:** Check if you have access to a `Task` tool (may be capitalized as `Task` or lowercase as `task` depending on runtime). If you do NOT have a `Task`/`task` tool (or only have tools like `browser_subagent` which is for web browsing, NOT code analysis):
→ **Skip `spawn_agents` and `collect_confirmations`** — go directly to `sequential_mapping` instead.
@@ -218,7 +215,7 @@ If any agent failed, note the failure and continue with successful documents.
Continue to verify_output.
-
+
When the `Task` tool is unavailable, perform codebase mapping sequentially in the current context. This replaces `spawn_agents` and `collect_confirmations`.
**IMPORTANT:** Do NOT use `browser_subagent`, `Explore`, or any browser-based tool. Use only file system tools (Read, Bash, Write, Grep, Glob, list_dir, view_file, grep_search, or equivalent tools available in your runtime).
diff --git a/tests/agent-frontmatter.test.cjs b/tests/agent-frontmatter.test.cjs
index f9977c338..19b5a956f 100644
--- a/tests/agent-frontmatter.test.cjs
+++ b/tests/agent-frontmatter.test.cjs
@@ -339,3 +339,56 @@ describe('DISCUSS: discussion log generation', () => {
);
});
});
+
+// ─── Worktree Permission Mode (#1334) ───────────────────────────────────────
+
+describe('PERM: worktree agents have permissionMode: acceptEdits', () => {
+ // Agents spawned with isolation="worktree" need permissionMode: acceptEdits
+ // to avoid per-directory edit permission prompts in the worktree path.
+ // See: anthropics/claude-code#29110, anthropics/claude-code#28041
+ const WORKTREE_AGENTS = ['gsd-executor', 'gsd-debugger'];
+
+ for (const agent of WORKTREE_AGENTS) {
+ test(`${agent} has permissionMode: acceptEdits`, () => {
+ const content = fs.readFileSync(path.join(AGENTS_DIR, agent + '.md'), 'utf-8');
+ const frontmatter = content.split('---')[1] || '';
+ assert.ok(
+ frontmatter.includes('permissionMode: acceptEdits'),
+ `${agent} must have permissionMode: acceptEdits — worktree agents need this to avoid ` +
+ `per-directory edit permission prompts (see #1334)`
+ );
+ });
+ }
+
+ test('worktree-spawned agents are covered', () => {
+ // Verify that agents referenced with isolation="worktree" in workflows
+ // are included in the WORKTREE_AGENTS list above
+ const dirs = [WORKFLOWS_DIR, COMMANDS_DIR];
+ const worktreeAgentTypes = new Set();
+
+ for (const dir of dirs) {
+ if (!fs.existsSync(dir)) continue;
+ const files = fs.readdirSync(dir).filter(f => f.endsWith('.md'));
+ for (const file of files) {
+ const content = fs.readFileSync(path.join(dir, file), 'utf-8');
+ // Find patterns like: subagent_type="gsd-executor" ... isolation="worktree"
+ // These can span multiple lines in Task() calls
+ const taskBlocks = content.match(/Task\([^)]*isolation="worktree"[^)]*\)/gs) || [];
+ for (const block of taskBlocks) {
+ const typeMatch = block.match(/subagent_type="([^"]+)"/);
+ if (typeMatch) {
+ worktreeAgentTypes.add(typeMatch[1]);
+ }
+ }
+ }
+ }
+
+ for (const agentType of worktreeAgentTypes) {
+ assert.ok(
+ WORKTREE_AGENTS.includes(agentType),
+ `${agentType} is spawned with isolation="worktree" but not in WORKTREE_AGENTS list — ` +
+ `add permissionMode: acceptEdits to its frontmatter and update this test`
+ );
+ }
+ });
+});