claude-raid 0.1.7 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/bin/cli.js +13 -1
  2. package/package.json +1 -1
  3. package/src/descriptions.js +26 -24
  4. package/src/init.js +6 -10
  5. package/src/merge-settings.js +0 -15
  6. package/src/remove.js +18 -16
  7. package/src/ui.js +1 -1
  8. package/src/update.js +28 -13
  9. package/template/.claude/agents/archer.md +10 -20
  10. package/template/.claude/agents/rogue.md +11 -21
  11. package/template/.claude/agents/warrior.md +8 -19
  12. package/template/.claude/agents/wizard.md +14 -247
  13. package/template/.claude/dungeon-master-rules.md +210 -0
  14. package/template/.claude/hooks/raid-lib.sh +29 -2
  15. package/template/.claude/hooks/raid-pre-compact.sh +12 -1
  16. package/template/.claude/hooks/raid-session-end.sh +23 -13
  17. package/template/.claude/hooks/raid-session-start.sh +21 -3
  18. package/template/.claude/hooks/validate-commit.sh +7 -74
  19. package/template/.claude/hooks/validate-dungeon.sh +30 -11
  20. package/template/.claude/hooks/validate-no-placeholders.sh +3 -3
  21. package/template/.claude/hooks/validate-write-gate.sh +45 -63
  22. package/template/.claude/{raid-rules.md → party-rules.md} +38 -13
  23. package/template/.claude/skills/raid-browser-chrome/SKILL.md +1 -1
  24. package/template/.claude/skills/{raid-design → raid-canonical-design}/SKILL.md +52 -16
  25. package/template/.claude/skills/{raid-implementation → raid-canonical-implementation}/SKILL.md +41 -14
  26. package/template/.claude/skills/{raid-implementation-plan → raid-canonical-implementation-plan}/SKILL.md +49 -17
  27. package/template/.claude/skills/raid-canonical-prd/SKILL.md +133 -0
  28. package/template/.claude/skills/raid-canonical-protocol/SKILL.md +211 -0
  29. package/template/.claude/skills/{raid-review → raid-canonical-review}/SKILL.md +78 -17
  30. package/template/.claude/skills/raid-debugging/SKILL.md +30 -5
  31. package/template/.claude/skills/raid-init/SKILL.md +130 -0
  32. package/template/.claude/skills/raid-tdd/SKILL.md +1 -1
  33. package/template/.claude/skills/raid-wrap-up/SKILL.md +184 -0
  34. package/template/.claude/hooks/raid-stop.sh +0 -20
  35. package/template/.claude/hooks/raid-task-completed.sh +0 -42
  36. package/template/.claude/hooks/validate-bash-writes.sh +0 -157
  37. package/template/.claude/skills/raid-browser-playwright/SKILL.md +0 -163
  38. package/template/.claude/skills/raid-finishing/SKILL.md +0 -140
  39. package/template/.claude/skills/raid-git-worktrees/SKILL.md +0 -96
  40. package/template/.claude/skills/raid-protocol/SKILL.md +0 -337
@@ -0,0 +1,184 @@
1
+ ---
2
+ name: raid-wrap-up
3
+ description: "Phase 6 of Canonical Quest. Generates quest storyboard report, creates PR, archives dungeon to vault, dismisses party. No new code."
4
+ ---
5
+
6
+ # Raid Wrap Up — Phase 6
7
+
8
+ The quest ends. The bard sings the tale. The treasure is committed. The party rests.
9
+
10
+ <HARD-GATE>
11
+ Do NOT write new code. This phase is about reporting, cleanup, PR creation, and archival. Agents are dismissed, not dispatched.
12
+ </HARD-GATE>
13
+
14
+ ## Mode Behavior
15
+
16
+ - **Full Raid**: Wizard writes full storyboard from all phase files. Full PR with narrative.
17
+ - **Skirmish**: Wizard writes condensed storyboard. Standard PR.
18
+ - **Scout**: Wizard writes brief summary. Quick PR.
19
+
20
+ ## Process Flow
21
+
22
+ ```dot
23
+ digraph wrapup {
24
+ "Wizard updates phase to wrap-up" -> "Create phase-6-wrap-up.md";
25
+ "Create phase-6-wrap-up.md" -> "Write phase-by-phase storyboard";
26
+ "Write phase-by-phase storyboard" -> "Cleanup temp files";
27
+ "Cleanup temp files" -> "Verify all tests pass (fresh run)";
28
+ "Verify all tests pass (fresh run)" -> "Tests pass?" [shape=diamond];
29
+ "Tests pass?" -> "Fix first. Do not proceed." [label="no"];
30
+ "Fix first. Do not proceed." -> "Verify all tests pass (fresh run)";
31
+ "Tests pass?" -> "Present merge options" [label="yes"];
32
+ "Present merge options" -> "Human chooses";
33
+ "Human chooses" -> "Execute choice";
34
+ "Execute choice" -> "Dismiss party";
35
+ "Dismiss party" -> "Archive to vault";
36
+ "Archive to vault" -> "Final commit + cleanup" [shape=doublecircle];
37
+ }
38
+ ```
39
+
40
+ ## Wizard Checklist
41
+
42
+ 1. **Update raid-session** — set phase to `"wrap-up"`
43
+ 2. **Create storyboard** — `{questDir}/phase-6-wrap-up.md`
44
+ 3. **Write narrative** — phase-by-phase story from quest files
45
+ 4. **Cleanup** — remove temp configs, debug files, stale artifacts
46
+ 5. **Verify tests** — fresh full run, must pass
47
+ 6. **Present options** — 4 merge choices
48
+ 7. **Execute choice** — merge, PR, keep, or discard
49
+ 8. **Dismiss party** — RPG flavor shutdown
50
+ 9. **Archive** — move dungeon to vault
51
+ 10. **Final commit** — `docs(quest-{slug}): phase 6 wrap-up — quest complete`
52
+ 11. **Session cleanup** — remove `.claude/raid-session`
53
+
54
+ ## Step 1: The Quest Storyboard
55
+
56
+ Create `{questDir}/phase-6-wrap-up.md` and write a phase-by-phase narrative:
57
+
58
+ ```markdown
59
+ # Phase 6: Wrap Up — Quest Storyboard
60
+ ## Quest: <quest name>
61
+ ## Mode: <mode>
62
+
63
+ ### Phase 1: PRD — Forging the Scroll
64
+ (if phase-1-prd.md exists)
65
+ - What requirements were established
66
+ - Key decisions from research
67
+
68
+ ### Phase 2: Design — Charting the Map
69
+ - Architecture chosen and why
70
+ - Key trade-offs resolved
71
+ - Alternatives considered and rejected
72
+
73
+ ### Phase 3: Implementation Plan — Marshaling the Forces
74
+ - Number of tasks, dependency structure
75
+ - Risk areas identified
76
+
77
+ ### Phase 4: Implementation — Into the Fray
78
+ - What was built
79
+ - Challenges overcome
80
+ - Test coverage highlights
81
+
82
+ ### Phase 5: Review — Inspecting the Treasure
83
+ (if phase-5-review.md exists)
84
+ - Findings pinned and resolved
85
+ - Black cards (if any)
86
+ - Fixes applied
87
+
88
+ ### Summary
89
+ - Total phases completed
90
+ - Key achievements
91
+ - Known limitations
92
+ ```
93
+
94
+ Read all prior phase files from the quest directory to build this narrative.
95
+
96
+ ## Step 2: Cleanup
97
+
98
+ Remove temporary artifacts:
99
+ - Debug files
100
+ - Temp configs
101
+ - Stale backups in the quest directory
102
+
103
+ ## Step 3: Final Verification
104
+
105
+ ```
106
+ 1. IDENTIFY: test command from .claude/raid.json
107
+ 2. RUN: Execute the FULL test suite (fresh, complete)
108
+ 3. READ: Full output, check exit code, count failures
109
+ 4. VERIFY: Zero failures?
110
+ If NO → STOP. Fix first. Do not present options.
111
+ If YES → Proceed with evidence.
112
+ ```
113
+
114
+ ## Step 4: Present Options
115
+
116
+ ```
117
+ RULING: The quest is complete and verified.
118
+
119
+ Tests: [N] passing, 0 failures (evidence: [command output])
120
+
121
+ Options:
122
+ 1. Merge back to [base-branch] locally
123
+ 2. Push and create a Pull Request
124
+ 3. Keep the branch as-is (handle later)
125
+ 4. Discard this work
126
+
127
+ Which option?
128
+ ```
129
+
130
+ **For option 2 (PR):** Create the PR with:
131
+ - **Title**: Descriptive, includes quest name
132
+ - **Body**: The phase-by-phase storyboard from the wrap-up doc
133
+
134
+ ## Step 5: Execute
135
+
136
+ | Option | Actions |
137
+ |--------|---------|
138
+ | **1. Merge** | Checkout base -> pull -> merge -> run tests on merged result -> delete branch -> clean up |
139
+ | **2. PR** | Push with -u -> create PR via gh with storyboard body -> clean up |
140
+ | **3. Keep** | Report branch location. Done. |
141
+ | **4. Discard** | Require typed "discard" confirmation -> delete branch (force) -> clean up |
142
+
143
+ ## Step 6: Dismiss the Party
144
+
145
+ Send shutdown to all teammates with RPG flavor:
146
+
147
+ > "The quest is done, brave engineers. The bards will sing of **{quest-name}**. Sheathe your tools — until the next adventure."
148
+
149
+ ```
150
+ SendMessage(to="warrior", message={"type": "shutdown_request"})
151
+ SendMessage(to="archer", message={"type": "shutdown_request"})
152
+ SendMessage(to="rogue", message={"type": "shutdown_request"})
153
+ ```
154
+
155
+ ## Step 7: Archive to Vault
156
+
157
+ 1. Move quest directory to vault:
158
+ ```
159
+ mv .claude/dungeon/{quest-slug}/ .claude/vault/{quest-slug}/
160
+ ```
161
+ 2. Update vault index at `.claude/vault/index.md`:
162
+ ```
163
+ | {date} | [{quest-name}]({quest-slug}/quest.md) | {mode} | {tags} |
164
+ ```
165
+
166
+ ## Step 8: Final Commit & Cleanup
167
+
168
+ 1. **Commit**: `docs(quest-{slug}): phase 6 wrap-up — quest complete`
169
+ 2. **Remove**: `.claude/raid-session`
170
+ 3. **Session is over. No further skills to load.**
171
+
172
+ ## Red Flags
173
+
174
+ | Thought | Reality |
175
+ |---------|---------|
176
+ | "Tests passed earlier, no need to re-run" | Fresh run or no claim. Always. |
177
+ | "Skip the storyboard, just make the PR" | The storyboard IS the PR body. It documents the journey. |
178
+ | "Leave the dungeon files, they might be useful" | Archive to vault. Session artifacts don't belong in the repo. |
179
+ | "Merge without testing the merged result" | Merges introduce conflicts. Test after merge. |
180
+ | "I'll write the code fix myself" | You are the Wizard. Dispatch the fix to an agent. |
181
+
182
+ ## Phase Spoils
183
+
184
+ **Output**: `{questDir}/phase-6-wrap-up.md` — The complete quest narrative, phase by phase.
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Raid lifecycle hook: Stop
3
- # Detects phase transitions and injects human confirmation gate.
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- source "$SCRIPT_DIR/raid-lib.sh"
8
-
9
- if [ "$RAID_ACTIVE" != "true" ]; then
10
- exit 0
11
- fi
12
-
13
- if [ "$RAID_LIFECYCLE_PHASE_CONFIRM" != "true" ]; then
14
- exit 0
15
- fi
16
-
17
- # Phase transitions are managed by the Wizard via raid_session_set().
18
- # No automatic detection needed — the Wizard explicitly updates the session.
19
-
20
- exit 0
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Raid lifecycle hook: TaskCompleted
3
- # Blocks task completion if tests haven't run recently.
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- source "$SCRIPT_DIR/raid-lib.sh"
8
-
9
- if [ "$RAID_ACTIVE" != "true" ]; then
10
- exit 0
11
- fi
12
-
13
- if [ "$RAID_LIFECYCLE_COMPLETION_GATE" != "true" ]; then
14
- exit 0
15
- fi
16
-
17
- # Design and plan phases have no code to test — skip test-run requirement
18
- case "${RAID_PHASE:-}" in
19
- design|plan) exit 0 ;;
20
- esac
21
-
22
- TEST_RUN_FILE=".claude/raid-last-test-run"
23
-
24
- if [ ! -f "$TEST_RUN_FILE" ]; then
25
- raid_block "Tests must pass before marking a task complete. No test run recorded — run your test command first."
26
- fi
27
-
28
- LAST_RUN=$(cat "$TEST_RUN_FILE" 2>/dev/null | tr -d '[:space:]')
29
- NOW=$(date +%s)
30
- WINDOW=$((RAID_LIFECYCLE_TEST_WINDOW * 60))
31
- # Guard against corrupted/non-numeric timestamp
32
- case "$LAST_RUN" in
33
- ''|*[!0-9]*) raid_block "Tests must pass before marking a task complete. Test run timestamp is invalid — run your test command first." ;;
34
- esac
35
- AGE=$((NOW - LAST_RUN))
36
-
37
- if [ "$AGE" -gt "$WINDOW" ]; then
38
- MINS_AGO=$((AGE / 60))
39
- raid_block "Tests last ran $MINS_AGO minutes ago (window is $RAID_LIFECYCLE_TEST_WINDOW min). Run tests again before marking this task complete."
40
- fi
41
-
42
- exit 0
@@ -1,157 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Raid Bash write-gate: intercepts file-writing Bash commands
3
- # PreToolUse hook for Bash operations — defense-in-depth layer.
4
- # Detects: redirects (> >>), tee, sed -i, cp, mv, curl -o,
5
- # and scripting language writes (python3/node/ruby/perl).
6
- # Protects .claude/raid-session and .claude/raid-last-test-run from all Bash writes.
7
- set -euo pipefail
8
-
9
- HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
10
- source "$HOOK_DIR/raid-lib.sh"
11
-
12
- raid_read_input
13
-
14
- # No command — nothing to gate
15
- if [ -z "${RAID_COMMAND:-}" ]; then
16
- exit 0
17
- fi
18
-
19
- # No active session — allow everything
20
- if [ "$RAID_ACTIVE" = "false" ]; then
21
- exit 0
22
- fi
23
-
24
- # --- Extract target file paths from known write patterns ---
25
-
26
- # Collects candidate target paths from the command string.
27
- # This is regex heuristics on a Bash command — it catches the 90% case,
28
- # not arbitrary scripting. Defense in depth, not a security boundary.
29
- _targets=()
30
-
31
- _cmd="$RAID_COMMAND"
32
-
33
- # Pattern 1: Redirects — command > file, command >> file
34
- # Matches: > path, >> path (with optional whitespace)
35
- while IFS= read -r _match; do
36
- [ -n "$_match" ] && _targets+=("$_match")
37
- done < <(echo "$_cmd" | grep -oE '>{1,2}\s*[^ |;&)]+' | sed 's/^>*[[:space:]]*//')
38
-
39
- # Pattern 2: tee [-a] file [file...]
40
- while IFS= read -r _match; do
41
- [ -n "$_match" ] && _targets+=("$_match")
42
- done < <(echo "$_cmd" | grep -oE 'tee\s+(-a\s+)?[^ |;&)]+' | sed 's/^tee\s\+\(-a\s\+\)\?//' | sed 's/^tee[[:space:]]*\(-a[[:space:]]*\)\{0,1\}//')
43
-
44
- # Pattern 3: sed -i[suffix] 's/.../.../g' file
45
- while IFS= read -r _match; do
46
- [ -n "$_match" ] && _targets+=("$_match")
47
- done < <(echo "$_cmd" | grep -oE "sed\s+-i[^ ]*\s+'[^']*'\s+[^ |;&)]+" | rev | cut -d' ' -f1 | rev)
48
-
49
- # Pattern 4: cp source target (last arg is target)
50
- while IFS= read -r _match; do
51
- [ -n "$_match" ] && _targets+=("$_match")
52
- done < <(echo "$_cmd" | grep -oE 'cp\s+(-[a-zA-Z]+\s+)*[^ |;&)]+\s+[^ |;&)]+' | rev | cut -d' ' -f1 | rev)
53
-
54
- # Pattern 5: mv source target (last arg is target)
55
- while IFS= read -r _match; do
56
- [ -n "$_match" ] && _targets+=("$_match")
57
- done < <(echo "$_cmd" | grep -oE 'mv\s+(-[a-zA-Z]+\s+)*[^ |;&)]+\s+[^ |;&)]+' | rev | cut -d' ' -f1 | rev)
58
-
59
- # Pattern 6: curl -o file / curl --output file
60
- while IFS= read -r _match; do
61
- [ -n "$_match" ] && _targets+=("$_match")
62
- done < <(echo "$_cmd" | grep -oE 'curl\s+.*-o\s+[^ |;&)]+' | grep -oE '\-o\s+[^ |;&)]+' | sed 's/^-o[[:space:]]*//')
63
-
64
- # Pattern 7: Scripting language inline writes — extract quoted paths
65
- # python3 -c "open('path', 'w')..."
66
- while IFS= read -r _match; do
67
- [ -n "$_match" ] && _targets+=("$_match")
68
- done < <(echo "$_cmd" | grep -oE "python3?\s+-c\s+['\"].*['\"]" | grep -oE "open\(['\"][^'\"]+['\"]" | sed "s/^open(['\"]//;s/['\"]$//")
69
-
70
- # node -e "fs.writeFileSync('path', ...)"
71
- while IFS= read -r _match; do
72
- [ -n "$_match" ] && _targets+=("$_match")
73
- done < <(echo "$_cmd" | grep -oE "node\s+-e\s+['\"].*['\"]" | grep -oE "writeFileSync\(['\"][^'\"]+['\"]" | sed "s/^writeFileSync(['\"]//;s/['\"]$//")
74
-
75
- # ruby -e "File.write('path', ...)"
76
- while IFS= read -r _match; do
77
- [ -n "$_match" ] && _targets+=("$_match")
78
- done < <(echo "$_cmd" | grep -oE "ruby\s+-e\s+['\"].*['\"]" | grep -oE "File\.write\(['\"][^'\"]+['\"]" | sed "s/^File\.write(['\"]//;s/['\"]$//")
79
-
80
- # perl -e 'open(F,">path")...'
81
- while IFS= read -r _match; do
82
- [ -n "$_match" ] && _targets+=("$_match")
83
- done < <(echo "$_cmd" | grep -oE "perl\s+-e\s+['\"].*['\"]" | grep -oE '>[^"'\'']+['\''"]' | sed "s/^>//;s/['\"]$//")
84
-
85
- # No write targets detected — allow
86
- if [ ${#_targets[@]} -eq 0 ]; then
87
- exit 0
88
- fi
89
-
90
- # --- Check each target ---
91
-
92
- for _target in "${_targets[@]}"; do
93
- # Normalize path: resolve .., //, and strip absolute prefix
94
- _norm="$_target"
95
- # Convert to absolute for uniform handling
96
- if [[ "$_norm" != /* ]]; then
97
- _norm="$PWD/$_norm"
98
- fi
99
- # Collapse // and resolve /dir/../ components (portable — no GNU sed labels)
100
- _norm=$(echo "$_norm" | sed 's|//\{1,\}|/|g' | while read -r _p; do
101
- # Iteratively resolve ../ until none remain
102
- while echo "$_p" | grep -q '/[^/][^/]*/\.\./'; do
103
- _p=$(echo "$_p" | sed 's|/[^/][^/]*/\.\./|/|')
104
- done
105
- echo "$_p"
106
- done)
107
- # Strip PWD prefix to get relative path
108
- _norm="${_norm#"$PWD"/}"
109
-
110
- # Check 1: Protected files — always blocked during active session
111
- case "$_norm" in
112
- .claude/raid-session|.claude/raid-last-test-run)
113
- raid_block "File '${_norm}' is protected. It is managed by hooks and the Wizard."
114
- ;;
115
- esac
116
-
117
- # Check 2: Non-production files — always allowed
118
- if ! raid_is_production_file "$_norm"; then
119
- continue
120
- fi
121
-
122
- # Check 3: Phase-based enforcement on production files
123
- case "${RAID_PHASE:-}" in
124
- design)
125
- raid_block "Bash write to production file '${_norm}' blocked. Read-only phase (design)."
126
- ;;
127
- plan)
128
- raid_block "Bash write to production file '${_norm}' blocked. Read-only phase (plan)."
129
- ;;
130
- implementation)
131
- # Scout mode: skip implementer check
132
- if [ "$RAID_MODE" = "scout" ]; then
133
- continue
134
- fi
135
- # Only the designated implementer may write production code via Bash
136
- if [ -n "$RAID_IMPLEMENTER" ] && [ "$RAID_CURRENT_AGENT" != "$RAID_IMPLEMENTER" ]; then
137
- raid_block "Bash write to production file '${_norm}' blocked. Only ${RAID_IMPLEMENTER} writes production code this task."
138
- fi
139
- continue
140
- ;;
141
- review)
142
- raid_block "Bash write to production file '${_norm}' blocked. Read-only phase (review)."
143
- ;;
144
- finishing)
145
- raid_block "Bash write to production file '${_norm}' blocked. Finishing phase."
146
- ;;
147
- "")
148
- # Bootstrap — allow with warning (consistent with write-gate)
149
- raid_warn "Session active but phase is empty — allowing Bash writes during bootstrap."
150
- ;;
151
- *)
152
- raid_block "Bash write to production file '${_norm}' blocked. Unknown phase '${RAID_PHASE}'."
153
- ;;
154
- esac
155
- done
156
-
157
- exit 0
@@ -1,163 +0,0 @@
1
- ---
2
- name: raid-browser-playwright
3
- description: "Playwright MCP automated browser test authoring. Extends TDD RED-GREEN-REFACTOR with .spec.ts files. Console + network assertions mandatory. Invoked from raid-tdd and raid-implementation during Phase 3."
4
- ---
5
-
6
- # Raid Browser Playwright — Automated Test Authoring
7
-
8
- Write browser tests as part of TDD. Use Playwright MCP to explore, then encode verified interactions into durable `.spec.ts` files.
9
-
10
- <HARD-GATE>
11
- Do NOT write browser tests without invoking `raid-browser` pre-flight first. Do NOT skip console/network assertions. Do NOT write tests without watching them fail first (TDD RED step). No subagents.
12
- </HARD-GATE>
13
-
14
- ## When to Write Browser Tests vs Unit Tests
15
-
16
- Not every task needs a browser test. The implementer decides and states reasoning. Challengers attack this decision.
17
-
18
- | Write Browser Test | Write Unit Test Only |
19
- |---|---|
20
- | New user-facing flow (signup, checkout) | Pure utility function |
21
- | UI interaction (drag-drop, modal, form) | API endpoint logic |
22
- | Client-side routing / navigation | Data transformation |
23
- | Visual state changes (loading, error, empty) | Business rule validation |
24
- | Integration between frontend and API | Database queries |
25
-
26
- **If unsure:** Write the browser test. It's easier to remove an unnecessary test than to find a bug in production.
27
-
28
- ## Browser TDD Cycle
29
-
30
- ### RED (browser)
31
-
32
- 1. Write Playwright test file: `tests/e2e/<feature>.spec.ts`
33
- 2. Test describes **user behavior**, not implementation:
34
- - Navigate to page
35
- - Interact (click, type, select, drag)
36
- - Assert visible outcome (text appears, redirect happens, element state changes)
37
- 3. Include mandatory infrastructure assertions (see below)
38
- 4. Run test → **MUST fail**
39
- 5. Verify it fails for the **RIGHT reason** (page/element missing — not test syntax error)
40
-
41
- ### GREEN (browser)
42
-
43
- 1. Implement the feature code
44
- 2. Run Playwright test → **MUST pass**
45
- 3. Run full test suite (unit + browser) → all green
46
-
47
- ### REFACTOR
48
-
49
- 1. Clean up implementation and test code
50
- 2. Re-run all tests → still green
51
-
52
- ## Using Playwright MCP During Test Authoring
53
-
54
- While writing the test, the implementer explores interactively to understand the current state and find correct selectors:
55
-
56
- | Tool | Purpose |
57
- |---|---|
58
- | `browser_navigate` | Load the page, see what's there |
59
- | `browser_snapshot` | Get DOM state, find correct selectors |
60
- | `browser_click` / `browser_fill_form` | Test interactions manually first |
61
- | `browser_console_messages` | Check for errors during interaction |
62
- | `browser_network_requests` | Verify API calls, check payloads |
63
- | `browser_take_screenshot` | Capture visual state for evidence |
64
-
65
- **The MCP tools are the exploratory scratchpad. The `.spec.ts` file is the durable artifact.**
66
-
67
- Encode what you verified interactively into the test file. The test must run headlessly in CI without MCP tools.
68
-
69
- ## Mandatory Assertions
70
-
71
- Every browser test file MUST include at least:
72
-
73
- ### 1. Console-Clean Assertion
74
-
75
- ```typescript
76
- test('no console errors during <feature> flow', async ({ page }) => {
77
- const errors: string[] = [];
78
- page.on('console', msg => {
79
- if (msg.type() === 'error') errors.push(msg.text());
80
- });
81
-
82
- // ... perform the feature flow ...
83
-
84
- expect(errors).toEqual([]);
85
- });
86
- ```
87
-
88
- ### 2. Network-Health Assertion
89
-
90
- ```typescript
91
- test('API calls succeed during <feature> flow', async ({ page }) => {
92
- const failures: string[] = [];
93
- page.on('response', response => {
94
- if (response.status() >= 400) {
95
- failures.push(`${response.status()} ${response.url()}`);
96
- }
97
- });
98
-
99
- // ... perform the feature flow ...
100
-
101
- expect(failures).toEqual([]);
102
- });
103
- ```
104
-
105
- **Missing either of these is an automatic challenge from any reviewer.**
106
-
107
- ## Selector Best Practices
108
-
109
- | Prefer | Avoid | Why |
110
- |---|---|---|
111
- | `data-testid="submit-btn"` | `button.btn-primary` | CSS classes change for styling reasons |
112
- | `getByRole('button', { name: 'Submit' })` | `#submit` | Accessible and resilient |
113
- | `getByText('Welcome back')` | `.header > div:nth-child(2)` | Structural selectors break on layout changes |
114
-
115
- ## Challenger Attacks on Browser Tests (Phase 3)
116
-
117
- **Warrior attacks:**
118
- - "You only tested the happy path — what happens with network failure?"
119
- - "No test for rapid double-submit on the form"
120
- - "What about a 10,000-character input in the name field?"
121
- - "You didn't test with JavaScript disabled / slow network"
122
-
123
- **Archer attacks:**
124
- - "Your selector `button[type=submit]` is fragile — use `data-testid`"
125
- - "No assertion on console errors — the feature works but throws warnings"
126
- - "Missing network assertion — you don't verify the POST payload"
127
- - "Tested at desktop width only — what about mobile viewport?"
128
-
129
- **Rogue attacks:**
130
- - "What happens if the user is already logged in and hits /register?"
131
- - "No test for XSS in the input fields"
132
- - "What if the API returns 200 but with an error body?"
133
- - "Race condition: what if the user navigates away during submission?"
134
-
135
- **Each challenger BOOTS their own app instance** (on their own port via `raid-browser`), runs the tests independently, and verifies they pass without flakiness.
136
-
137
- ## Running Browser Tests
138
-
139
- Use the test command from `.claude/raid.json`:
140
- - Read `project.execCommand` (e.g., `pnpm dlx`, `npx`, `bunx`)
141
- - Run: `{execCommand} playwright test`
142
- - For a specific test: `{execCommand} playwright test tests/e2e/<feature>.spec.ts`
143
-
144
- ## Test File Organization
145
-
146
- ```
147
- tests/
148
- e2e/
149
- <feature-name>.spec.ts # One file per feature/flow
150
- auth/
151
- login.spec.ts # Group related flows in directories
152
- registration.spec.ts
153
- ```
154
-
155
- ## Red Flags
156
-
157
- | Thought | Reality |
158
- |---------|---------|
159
- | "The feature is too simple for a browser test" | Simple features break in the browser. If it's user-facing, test it. |
160
- | "I'll add console assertions later" | Later never comes. Add them now. |
161
- | "The unit tests cover this" | Unit tests don't catch hydration mismatches, missing CSS, broken routing. |
162
- | "I tested it manually with MCP tools" | Manual verification isn't reproducible. Write the `.spec.ts`. |
163
- | "Selectors are fine, they work" | They work today. Will they work after a CSS refactor? Use `data-testid`. |