diff --git a/.changeset/fix-3096-ai-integration-parallel-race.md b/.changeset/fix-3096-ai-integration-parallel-race.md
new file mode 100644
index 000000000..f1c87e1a8
--- /dev/null
+++ b/.changeset/fix-3096-ai-integration-parallel-race.md
@@ -0,0 +1,5 @@
+---
+type: Fixed
+pr: 3096
+---
+**`ai-integration-phase` Steps 7+8 now enforce sequential execution and Edit-only tool discipline** — when `gsd-ai-researcher` and `gsd-domain-researcher` were dispatched in parallel (an optimization an orchestrator could reasonably make since the sections appeared disjoint), `gsd-domain-researcher`'s `Write` call at finalization silently replaced the entire AI-SPEC.md with its pre-researcher copy, losing Sections 3/4. Confirmed at 40% incidence rate (2 of 5 agents on a real run). Fix adds an explicit sequential ordering note to Steps 7+8 ("MUST run sequentially — wait for Step 7 to complete before spawning Step 8") and injects Edit-only tool discipline into both agent prompts ("Use the Edit tool exclusively — NEVER use Write on this file"). Closes #3096.
diff --git a/get-shit-done/workflows/ai-integration-phase.md b/get-shit-done/workflows/ai-integration-phase.md
index e8dcdc222..6b19d00e8 100644
--- a/get-shit-done/workflows/ai-integration-phase.md
+++ b/get-shit-done/workflows/ai-integration-phase.md
@@ -139,6 +139,8 @@ Fill in header fields:
## 7. Spawn gsd-ai-researcher
+> **Ordering note (prevents tool-level last-writer-wins race):** Steps 7 and 8 write disjoint sections of AI-SPEC.md but MUST run sequentially — wait for Step 7 to complete before spawning Step 8. Both agents use the `Edit` tool exclusively (never `Write`) when modifying AI-SPEC.md. A `Write` on a shared file replaces the entire file, silently overwriting the other agent's work; `Edit` targets only the relevant lines. See #3096 for a confirmed 40%-incidence race on parallel dispatch.
+
Display:
```
◆ Step 2/4 — Researching {primary_framework} docs + AI systems best practices...
@@ -148,9 +150,12 @@ Spawn `gsd-ai-researcher` with:
```markdown
Read ~/.claude/agents/gsd-ai-researcher.md for instructions.
+**Tool discipline (mandatory):**
+Use the Edit tool exclusively when modifying AI-SPEC.md — NEVER use Write on this file.
+Write replaces the entire file and will overwrite work from parallel or sequential sibling agents.
+Before editing, verify the section you are about to write is still a template placeholder.
+
-Research {primary_framework} for Phase {phase_number}: {phase_name}
-Write Sections 3 and 4 of AI-SPEC.md
@@ -169,6 +174,8 @@ phase_context: Phase {phase_number}: {phase_name} — {phase_goal}
## 8. Spawn gsd-domain-researcher
+> **Wait for Step 7 to complete before spawning this step** (see ordering note in Step 7).
+
Display:
```
◆ Step 3/4 — Researching domain context and expert evaluation criteria...
@@ -178,9 +185,12 @@ Spawn `gsd-domain-researcher` with:
```markdown
Read ~/.claude/agents/gsd-domain-researcher.md for instructions.
+**Tool discipline (mandatory):**
+Use the Edit tool exclusively when modifying AI-SPEC.md — NEVER use Write on this file.
+Write replaces the entire file and will overwrite work from parallel or sequential sibling agents.
+Before editing, verify the section you are about to write is still a template placeholder.
+
-Research the business domain and expert evaluation criteria for Phase {phase_number}: {phase_name}
-Write Section 1b (Domain Context) of AI-SPEC.md
diff --git a/tests/bug-3096-ai-integration-phase-parallel-race.test.cjs b/tests/bug-3096-ai-integration-phase-parallel-race.test.cjs
new file mode 100644
index 000000000..4ae853f27
--- /dev/null
+++ b/tests/bug-3096-ai-integration-phase-parallel-race.test.cjs
@@ -0,0 +1,73 @@
+'use strict';
+// allow-test-rule: reads product workflow markdown (ai-integration-phase.md) to verify structural ordering contract — not a source-grep test
+
+// Regression guard for bug #3096.
+//
+// ai-integration-phase.md listed Steps 7+8 (gsd-ai-researcher +
+// gsd-domain-researcher) without an explicit sequential ordering constraint.
+// An orchestrator optimizing for speed could reasonably parallelize them
+// since the sections appeared disjoint. When parallelized, gsd-domain-researcher's
+// Write call at finalization replaced the whole AI-SPEC.md file with its
+// in-memory copy (pre-researcher state), silently overwriting Sections 3/4.
+//
+// Confirmed at 40% incidence rate on a real run (2 of 5 worktree agents hit it).
+// Recovery cost: one extra ai-researcher dispatch (~18 min wall).
+//
+// Fix:
+// 1. Explicit "MUST run sequentially" note on Steps 7 and 8
+// 2. Edit-only tool discipline injected into both agent prompts
+
+const { describe, test } = require('node:test');
+const assert = require('node:assert/strict');
+const fs = require('node:fs');
+const path = require('node:path');
+
+const ROOT = path.join(__dirname, '..');
+const src = fs.readFileSync(
+ path.join(ROOT, 'get-shit-done', 'workflows', 'ai-integration-phase.md'),
+ 'utf8',
+);
+
+describe('bug #3096: ai-integration-phase sequential ordering and Edit-only discipline', () => {
+ test('Step 7 documents sequential ordering requirement', () => {
+ assert.ok(
+ src.includes('sequentially') || src.includes('sequential'),
+ 'Steps 7+8 ordering note is missing — parallel dispatch race can recur',
+ );
+ });
+
+ test('Step 7 gsd-ai-researcher prompt includes Edit-only tool discipline', () => {
+ // The discipline block must appear before for gsd-ai-researcher
+ const step7Idx = src.indexOf('## 7. Spawn gsd-ai-researcher');
+ const step8Idx = src.indexOf('## 8. Spawn gsd-domain-researcher');
+ assert.ok(step7Idx !== -1, 'Step 7 not found');
+ assert.ok(step8Idx !== -1, 'Step 8 not found');
+ const step7Block = src.slice(step7Idx, step8Idx);
+ assert.ok(
+ step7Block.includes('Edit tool') && step7Block.includes('NEVER use Write'),
+ 'Step 7 agent prompt missing Edit-only tool discipline',
+ );
+ });
+
+ test('Step 8 gsd-domain-researcher prompt includes Edit-only tool discipline', () => {
+ const step8Idx = src.indexOf('## 8. Spawn gsd-domain-researcher');
+ const step9Idx = src.indexOf('## 9. Spawn gsd-eval-planner');
+ assert.ok(step8Idx !== -1, 'Step 8 not found');
+ assert.ok(step9Idx !== -1, 'Step 9 not found');
+ const step8Block = src.slice(step8Idx, step9Idx);
+ assert.ok(
+ step8Block.includes('Edit tool') && step8Block.includes('NEVER use Write'),
+ 'Step 8 agent prompt missing Edit-only tool discipline',
+ );
+ });
+
+ test('Step 8 references the wait instruction', () => {
+ const step8Idx = src.indexOf('## 8. Spawn gsd-domain-researcher');
+ const step9Idx = src.indexOf('## 9. Spawn gsd-eval-planner');
+ const step8Block = src.slice(step8Idx, step9Idx);
+ assert.ok(
+ step8Block.includes('Wait') || step8Block.includes('wait') || step8Block.includes('complete'),
+ 'Step 8 does not instruct orchestrator to wait for Step 7',
+ );
+ });
+});