claude-raid 0.1.2 → 0.1.3

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.
package/bin/cli.js CHANGED
@@ -11,12 +11,26 @@ const showUpdateNotice = versionCheck.start();
11
11
 
12
12
  const COMMANDS = {
13
13
  // Primary commands
14
- summon: () => require('../src/init').run(),
14
+ summon: () => {
15
+ if (process.argv.includes('--dry-run')) {
16
+ console.log('\n' + banner());
17
+ console.log(require('../src/init').dryRun(process.cwd()));
18
+ return;
19
+ }
20
+ return require('../src/init').run();
21
+ },
15
22
  update: () => require('../src/update').run(),
16
23
  dismantle: () => require('../src/remove').run(),
17
24
  heal: () => require('../src/doctor').run(),
18
25
  // Aliases (backward compat)
19
- init: () => require('../src/init').run(),
26
+ init: () => {
27
+ if (process.argv.includes('--dry-run')) {
28
+ console.log('\n' + banner());
29
+ console.log(require('../src/init').dryRun(process.cwd()));
30
+ return;
31
+ }
32
+ return require('../src/init').run();
33
+ },
20
34
  remove: () => require('../src/remove').run(),
21
35
  doctor: () => require('../src/doctor').run(),
22
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-raid",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "commonjs",
5
5
  "description": "Adversarial multi-agent development system for Claude Code",
6
6
  "author": "Pedro Picardi",
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ // Single source of truth for file descriptions used by dry-run and install output.
4
+ // Keep descriptions under 80 chars — they appear in terminal columns.
5
+
6
+ const AGENTS = {
7
+ 'wizard.md': 'Dungeon master — opens phases, dispatches team, closes with rulings',
8
+ 'warrior.md': 'Stress-tester — breaks things under load, edge cases, pressure',
9
+ 'archer.md': 'Pattern-seeker — traces ripple effects, naming drift, contract violations',
10
+ 'rogue.md': 'Assumption-destroyer — thinks like a failing system, malicious input',
11
+ };
12
+
13
+ const HOOKS = {
14
+ lifecycle: [
15
+ { name: 'raid-lib.sh', desc: 'Shared config — reads raid.json, exports session state' },
16
+ { name: 'raid-session-start.sh', desc: 'Activates Raid workflow when session begins' },
17
+ { name: 'raid-session-end.sh', desc: 'Archives Dungeon, cleans up when session ends' },
18
+ { name: 'raid-stop.sh', desc: 'Backs up Dungeon on phase transitions' },
19
+ { name: 'raid-pre-compact.sh', desc: 'Backs up Dungeon before message compaction' },
20
+ { name: 'raid-task-created.sh', desc: 'Validates task subjects are meaningful' },
21
+ { name: 'raid-task-completed.sh', desc: 'Blocks task completion without test evidence' },
22
+ { name: 'raid-teammate-idle.sh', desc: 'Nudges idle agents to participate' },
23
+ ],
24
+ gates: [
25
+ { name: 'validate-commit.sh', desc: 'Enforces conventional commits + test gate' },
26
+ { name: 'validate-write-gate.sh', desc: 'Blocks implementation before design doc exists' },
27
+ { name: 'validate-file-naming.sh', desc: 'Enforces naming convention (kebab-case, etc.)' },
28
+ { name: 'validate-no-placeholders.sh', desc: 'Blocks TBD/TODO in specs and plans' },
29
+ { name: 'validate-dungeon.sh', desc: 'Requires multi-agent verification on pins' },
30
+ { name: 'validate-browser-tests-exist.sh', desc: 'Checks Playwright tests exist before commits' },
31
+ { name: 'validate-browser-cleanup.sh', desc: 'Verifies browser processes cleaned up properly' },
32
+ ],
33
+ };
34
+
35
+ const SKILLS = {
36
+ 'raid-protocol': 'Session lifecycle and team rules',
37
+ 'raid-design': 'Phase 1: adversarial exploration',
38
+ 'raid-implementation-plan': 'Phase 2: task decomposition',
39
+ 'raid-implementation': 'Phase 3: TDD with direct challenge',
40
+ 'raid-review': 'Phase 4: independent review + fighting',
41
+ 'raid-finishing': 'Completeness debate + merge options',
42
+ 'raid-tdd': 'RED-GREEN-REFACTOR enforcement',
43
+ 'raid-debugging': 'Root-cause investigation',
44
+ 'raid-verification': 'Evidence-before-claims gate',
45
+ 'raid-git-worktrees': 'Isolated workspace creation',
46
+ 'raid-browser': 'Browser startup discovery',
47
+ 'raid-browser-playwright': 'Playwright test authoring',
48
+ 'raid-browser-chrome': 'Live browser inspection',
49
+ };
50
+
51
+ const CONFIG = {
52
+ 'raid.json': 'Project settings (editable)',
53
+ 'raid-rules.md': '17 team rules (editable)',
54
+ 'settings.json': 'Hooks merged into existing (backup created)',
55
+ };
56
+
57
+ module.exports = { AGENTS, HOOKS, SKILLS, CONFIG };
package/src/doctor.js CHANGED
@@ -1,13 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  const { runChecks, runSetup } = require('./setup');
4
- const { banner, box, header, colors } = require('./ui');
4
+ const { banner, header } = require('./ui');
5
5
 
6
6
  function diagnose(opts) {
7
7
  return runChecks(opts);
8
8
  }
9
9
 
10
10
  async function run() {
11
+ const { referenceCard } = require('./ui');
12
+
11
13
  console.log('\n' + banner());
12
14
  console.log(header('Diagnosing Wounds...') + '\n');
13
15
 
@@ -17,34 +19,7 @@ async function run() {
17
19
  process.exitCode = 1;
18
20
  }
19
21
 
20
- const quickStart = box('Quick Start', [
21
- ' In-process mode (any terminal):',
22
- ' ' + colors.bold('claude --agent wizard'),
23
- '',
24
- ' Split-pane mode (tmux):',
25
- ' ' + colors.bold('tmux new-session -s raid'),
26
- ' ' + colors.bold('claude --agent wizard --teammate-mode tmux'),
27
- ]);
28
- console.log('\n' + quickStart);
29
-
30
- const controls = box('Controls', [
31
- ' ' + colors.bold('Shift+Down') + ' Cycle through teammates',
32
- ' ' + colors.bold('Enter') + ' View a teammate\'s session',
33
- ' ' + colors.bold('Escape') + ' Interrupt a teammate\'s turn',
34
- ' ' + colors.bold('Ctrl+T') + ' Toggle the shared task list',
35
- ' ' + colors.bold('Click pane') + ' Interact directly (split-pane)',
36
- ]);
37
- console.log('\n' + controls);
38
-
39
- const modes = box('Raid Modes', [
40
- ' ' + colors.bold('Full Raid') + ' Warrior + Archer + Rogue (3 agents)',
41
- ' ' + colors.bold('Skirmish') + ' 2 agents, lightweight',
42
- ' ' + colors.bold('Scout') + ' Wizard solo review',
43
- '',
44
- ' The Wizard recommends a mode based on task',
45
- ' complexity. You confirm before agents spawn.',
46
- ]);
47
- console.log('\n' + modes + '\n');
22
+ console.log('\n' + referenceCard() + '\n');
48
23
  }
49
24
 
50
25
  module.exports = { diagnose, run };
package/src/init.js CHANGED
@@ -6,6 +6,7 @@ const { detectProject } = require('./detect-project');
6
6
  const { mergeSettings } = require('./merge-settings');
7
7
  const { runSetup } = require('./setup');
8
8
  const { banner, header, colors } = require('./ui');
9
+ const { AGENTS, HOOKS, SKILLS, CONFIG } = require('./descriptions');
9
10
 
10
11
  const TEMPLATE_DIR = path.join(__dirname, '..', 'template', '.claude');
11
12
 
@@ -60,6 +61,16 @@ function install(cwd) {
60
61
  }
61
62
  }
62
63
 
64
+ // Count copied files by category
65
+ const agentsDir = path.join(claudeDir, 'agents');
66
+ const hooksDir2 = path.join(claudeDir, 'hooks');
67
+ const skillsDir = path.join(claudeDir, 'skills');
68
+ result.counts = {
69
+ agents: fs.existsSync(agentsDir) ? fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).length : 0,
70
+ hooks: fs.existsSync(hooksDir2) ? fs.readdirSync(hooksDir2).filter(f => f.endsWith('.sh')).length : 0,
71
+ skills: fs.existsSync(skillsDir) ? fs.readdirSync(skillsDir).filter(f => !f.startsWith('.')).length : 0,
72
+ };
73
+
63
74
  // Generate raid.json (skip if it already exists to preserve user config)
64
75
  const raidConfigPath = path.join(claudeDir, 'raid.json');
65
76
  if (!fs.existsSync(raidConfigPath)) {
@@ -139,7 +150,8 @@ function install(cwd) {
139
150
  ];
140
151
  if (fs.existsSync(gitignorePath)) {
141
152
  let content = fs.readFileSync(gitignorePath, 'utf8');
142
- const toAdd = ignoreEntries.filter(e => !content.includes(e));
153
+ const lines = content.split('\n').map(l => l.trim());
154
+ const toAdd = ignoreEntries.filter(e => !lines.includes(e.trim()));
143
155
  if (toAdd.length > 0) {
144
156
  const sep = content.endsWith('\n') ? '' : '\n';
145
157
  fs.appendFileSync(gitignorePath, sep + toAdd.join('\n') + '\n');
@@ -153,26 +165,149 @@ function install(cwd) {
153
165
 
154
166
  async function run() {
155
167
  const cwd = process.cwd();
168
+ const { bold, dim } = colors;
169
+
156
170
  console.log('\n' + banner());
157
171
  console.log(header('Summoning the Party...') + '\n');
158
172
 
159
173
  const result = install(cwd);
160
174
 
161
175
  if (result.alreadyInstalled) {
162
- console.log(' The party is already here. Use ' + colors.bold('claude-raid update') + ' to reforge.');
176
+ console.log(' The party is already here. Use ' + bold('claude-raid update') + ' to reforge.');
163
177
  console.log(' Proceeding with re-summon...\n');
164
178
  }
165
179
 
166
- console.log(' Realm detected: ' + colors.bold(result.detected.language));
180
+ // Detection summary
181
+ console.log(' Realm detected: ' + bold(result.detected.language));
167
182
  if (result.detected.testCommand) {
168
- console.log(' Battle cry: ' + colors.bold(result.detected.testCommand));
183
+ console.log(' Test command: ' + bold(result.detected.testCommand));
184
+ }
185
+ if (result.detected.lintCommand) {
186
+ console.log(' Lint command: ' + bold(result.detected.lintCommand));
169
187
  }
188
+
189
+ // Agents
190
+ console.log('');
191
+ console.log(' ' + header('Agents') + dim(` ${result.counts.agents} files`));
192
+ console.log(' Copied wizard.md, warrior.md, archer.md, rogue.md');
193
+ console.log(dim(' AI teammates that challenge each other\'s work from'));
194
+ console.log(dim(' competing angles. Start a session with: claude --agent wizard'));
195
+
196
+ // Hooks
197
+ console.log('');
198
+ console.log(' ' + header('Hooks') + dim(` ${result.counts.hooks} files`));
199
+ console.log(' Copied ' + bold(`${HOOKS.lifecycle.length} lifecycle hooks`) + ' + ' + bold(`${HOOKS.gates.length} quality gates`));
200
+ console.log(dim(' Lifecycle hooks manage session state automatically.'));
201
+ console.log(dim(' Quality gates block bad commits, missing tests, and'));
202
+ console.log(dim(' placeholder text \u2014 only active during Raid sessions.'));
203
+
204
+ // Skills
205
+ console.log('');
206
+ console.log(' ' + header('Skills') + dim(` ${result.counts.skills} folders`));
207
+ const skillNames = Object.keys(SKILLS).join(', ');
208
+ console.log(' ' + dim(skillNames));
209
+ console.log(dim(' Phase-specific workflows that guide agent behavior.'));
210
+
211
+ // Config
212
+ console.log('');
213
+ console.log(' ' + header('Config'));
214
+ console.log(' Generated ' + bold('raid.json') + ' ' + dim('Project settings (editable)'));
215
+ console.log(' Copied ' + bold('raid-rules.md') + ' ' + dim('17 team rules (editable)'));
216
+ console.log(' Merged ' + bold('settings.json') + ' ' + dim('Backup at .pre-raid-backup'));
217
+
218
+ // Skipped files
170
219
  if (result.skipped.length > 0) {
171
- console.log('\n ' + colors.dim('Preserved existing scrolls:'));
172
- result.skipped.forEach(f => console.log(' ' + colors.dim(' ' + path.relative(cwd, f))));
220
+ console.log('');
221
+ console.log(' ' + dim('Preserved existing scrolls:'));
222
+ result.skipped.forEach(f => console.log(' ' + dim('\u2192 ' + path.relative(cwd, f))));
173
223
  }
174
224
 
225
+ // Setup wizard
175
226
  await runSetup();
227
+
228
+ // Reference card
229
+ const { referenceCard } = require('./ui');
230
+ console.log('\n' + referenceCard() + '\n');
231
+ }
232
+
233
+ function dryRun(cwd) {
234
+ const detected = detectProject(cwd);
235
+ const lines = [];
236
+
237
+ lines.push(header('Dry Run — nothing will be written') + '\n');
238
+
239
+ // Realm
240
+ lines.push(' Realm detected: ' + colors.bold(detected.language));
241
+ if (detected.testCommand) {
242
+ lines.push(' Test command: ' + colors.bold(detected.testCommand));
243
+ }
244
+ if (detected.lintCommand) {
245
+ lines.push(' Lint command: ' + colors.bold(detected.lintCommand));
246
+ }
247
+ lines.push('');
248
+
249
+ // Helper: check if a file already exists
250
+ const claudeDir = path.join(cwd, '.claude');
251
+ function tag(relPath) {
252
+ const full = path.join(claudeDir, relPath);
253
+ return fs.existsSync(full) ? ' ' + colors.dim('(preserved)') : '';
254
+ }
255
+
256
+ // Agents
257
+ lines.push(header('Agents') + '\n');
258
+ for (const [file, desc] of Object.entries(AGENTS)) {
259
+ lines.push(' ' + colors.bold(file.padEnd(14)) + desc + tag('agents/' + file));
260
+ }
261
+ lines.push('');
262
+
263
+ // Hooks — Lifecycle
264
+ lines.push(header('Hooks — Lifecycle') + '\n');
265
+ for (const h of HOOKS.lifecycle) {
266
+ lines.push(' ' + colors.bold(h.name.padEnd(28)) + h.desc + tag('hooks/' + h.name));
267
+ }
268
+ lines.push('');
269
+
270
+ // Hooks — Quality Gates
271
+ lines.push(header('Hooks — Quality Gates') + '\n');
272
+ for (const h of HOOKS.gates) {
273
+ lines.push(' ' + colors.bold(h.name.padEnd(36)) + h.desc + tag('hooks/' + h.name));
274
+ }
275
+ lines.push('');
276
+
277
+ // Skills
278
+ lines.push(header('Skills') + '\n');
279
+ for (const [folder, desc] of Object.entries(SKILLS)) {
280
+ lines.push(' ' + colors.bold(folder.padEnd(28)) + desc + tag('skills/' + folder));
281
+ }
282
+ lines.push('');
283
+
284
+ // Config
285
+ lines.push(header('Config') + '\n');
286
+ for (const [file, desc] of Object.entries(CONFIG)) {
287
+ lines.push(' ' + colors.bold(file.padEnd(20)) + desc + tag(file));
288
+ }
289
+ lines.push('');
290
+
291
+ // .gitignore
292
+ lines.push(header('.gitignore entries') + '\n');
293
+ const ignoreEntries = [
294
+ '.claude/raid-last-test-run',
295
+ '.claude/raid-session',
296
+ '.claude/raid-dungeon.md',
297
+ '.claude/raid-dungeon-phase-*',
298
+ '.claude/raid-dungeon-backup.md',
299
+ '.claude/raid-dungeon-phase-*-backup.md',
300
+ '.claude/vault/.draft/',
301
+ '.env.raid',
302
+ ];
303
+ for (const entry of ignoreEntries) {
304
+ lines.push(' ' + colors.dim(entry));
305
+ }
306
+ lines.push('');
307
+
308
+ lines.push(' Run without --dry-run to install.');
309
+
310
+ return lines.join('\n');
176
311
  }
177
312
 
178
- module.exports = { install, run };
313
+ module.exports = { install, run, dryRun };
@@ -126,7 +126,7 @@ function mergeSettings(cwd) {
126
126
  if (!existing.hooks) existing.hooks = {};
127
127
 
128
128
  for (const [event, raidEntries] of Object.entries(RAID_HOOKS)) {
129
- if (!existing.hooks[event]) {
129
+ if (!Array.isArray(existing.hooks[event])) {
130
130
  existing.hooks[event] = [];
131
131
  }
132
132
  existing.hooks[event] = existing.hooks[event].filter(entry => !isRaidHookEntry(entry));
package/src/setup.js CHANGED
@@ -34,7 +34,7 @@ function versionGte(v, min) {
34
34
  const MIN_NODE = { major: 18, minor: 0, patch: 0 };
35
35
  const MIN_CLAUDE = { major: 2, minor: 1, patch: 32 };
36
36
  const VALID_TEAMMATE_MODES = ['tmux', 'in-process', 'auto'];
37
- const REQUIRED_IDS = ['node', 'claude'];
37
+ const REQUIRED_IDS = ['node', 'claude', 'jq'];
38
38
 
39
39
  // --- Check functions (private) ---
40
40
 
@@ -166,11 +166,10 @@ function checkPlaywright(exec, cwd) {
166
166
  }
167
167
 
168
168
  // Determine exec command prefix (e.g. "npx" or "pnpm dlx")
169
- const execCommand = raidConfig.execCommand || 'npx';
169
+ const execCommand = (raidConfig.project && raidConfig.project.execCommand) || 'npx';
170
170
 
171
171
  // Check if playwright config file exists
172
172
  const configFile = (raidConfig.browser && raidConfig.browser.playwrightConfig) || 'playwright.config.ts';
173
- const configExists = cwd && fs.existsSync(path.join(cwd, configFile));
174
173
 
175
174
  // Check playwright version
176
175
  const raw = exec(`${execCommand} playwright --version`);
@@ -197,6 +196,45 @@ function checkPlaywright(exec, cwd) {
197
196
  };
198
197
  }
199
198
 
199
+ function checkJq(exec) {
200
+ const found = exec('command -v jq');
201
+ if (found) {
202
+ return {
203
+ id: 'jq',
204
+ ok: true,
205
+ label: 'jq',
206
+ detail: 'installed',
207
+ };
208
+ }
209
+ return {
210
+ id: 'jq',
211
+ ok: false,
212
+ label: 'jq',
213
+ detail: 'not found',
214
+ hint: process.platform === 'darwin'
215
+ ? 'Install: brew install jq'
216
+ : 'Install jq via your package manager (apt, dnf, brew, etc.)',
217
+ };
218
+ }
219
+
220
+ function checkPlatform(platform) {
221
+ if (platform === 'win32') {
222
+ return {
223
+ id: 'platform',
224
+ ok: false,
225
+ label: 'Platform',
226
+ detail: 'Windows is not supported — hooks require POSIX bash',
227
+ hint: 'Use WSL2 (Windows Subsystem for Linux) for full compatibility',
228
+ };
229
+ }
230
+ return {
231
+ id: 'platform',
232
+ ok: true,
233
+ label: 'Platform',
234
+ detail: platform,
235
+ };
236
+ }
237
+
200
238
  function checkSplitPane(exec) {
201
239
  const tmux = exec('command -v tmux');
202
240
  const it2 = exec('command -v it2');
@@ -273,9 +311,13 @@ function runChecks(opts = {}) {
273
311
 
274
312
  const nodeVersion = opts.nodeVersion || undefined;
275
313
 
314
+ const platform = opts.platform || process.platform;
315
+
276
316
  const checks = [
317
+ checkPlatform(platform),
277
318
  checkNode(nodeVersion),
278
319
  checkClaude(exec),
320
+ checkJq(exec),
279
321
  checkTeammateMode(homedir),
280
322
  checkSplitPane(exec),
281
323
  checkPlaywright(exec, cwd),
package/src/ui.js CHANGED
@@ -16,6 +16,7 @@ const colors = {
16
16
  bold: wrap('1'),
17
17
  boldAmber: wrap('1;33'),
18
18
  boldRed: wrap('1;31'),
19
+ dimRed: wrap('2;31'),
19
20
  };
20
21
 
21
22
  function stripAnsi(str) {
@@ -23,7 +24,7 @@ function stripAnsi(str) {
23
24
  }
24
25
 
25
26
  function banner() {
26
- const { amber, boldAmber, boldRed, dim } = colors;
27
+ const { amber, boldAmber, boldRed, red, dimRed, dim } = colors;
27
28
  const rule = amber(' ⚔ ═══════════════════════════════════════════════════════ ⚔');
28
29
 
29
30
  const claudeArt = [
@@ -44,14 +45,30 @@ function banner() {
44
45
  ' ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═════╝ ',
45
46
  ];
46
47
 
47
- const tagline = ' Adversarial multi-agent warfare for Claude Code';
48
+ // 5-tone vertical gradient: boldAmber -> amber -> boldRed -> red -> dimRed
49
+ // Lines 1-2 (CLAUDE top): boldAmber
50
+ // Lines 3-5 (CLAUDE bottom + transition): amber
51
+ // Line 6 (CLAUDE/RAID boundary): boldRed
52
+ // Lines 7-8 (RAID top): boldRed
53
+ // Lines 9-11 (RAID middle): red
54
+ // Line 12 (RAID bottom): dimRed
55
+ const gradientColors = [
56
+ boldAmber, boldAmber, // claudeArt[0-1]
57
+ amber, amber, amber, // claudeArt[2-4]
58
+ boldRed, // claudeArt[5]
59
+ boldRed, boldRed, // raidArt[0-1]
60
+ red, red, red, // raidArt[2-4]
61
+ dimRed, // raidArt[5]
62
+ ];
63
+
64
+ const allArt = [...claudeArt, ...raidArt];
65
+ const tagline = ' Adversarial multi-agent development for Claude Code';
48
66
 
49
67
  const lines = [
50
68
  '',
51
69
  rule,
52
70
  '',
53
- ...claudeArt.map(l => boldAmber(l)),
54
- ...raidArt.map(l => boldRed(l)),
71
+ ...allArt.map((l, i) => gradientColors[i](l)),
55
72
  '',
56
73
  dim(tagline),
57
74
  '',
@@ -100,4 +117,52 @@ function header(text) {
100
117
  return ` ${amber(bold(`\u2694 ${text}`))}`;
101
118
  }
102
119
 
103
- module.exports = { colors, banner, box, header, stripAnsi };
120
+ function referenceCard() {
121
+ const howItWorks = box('How It Works', [
122
+ ' You describe a task. The Wizard assesses complexity and',
123
+ ' recommends a mode:',
124
+ '',
125
+ ' ' + colors.bold('Full Raid') + ' 3 agents attack from competing angles',
126
+ ' ' + colors.bold('Skirmish') + ' 2 agents, lighter process',
127
+ ' ' + colors.bold('Scout') + ' 1 agent + Wizard review',
128
+ '',
129
+ ' Every task flows through 4 phases:',
130
+ '',
131
+ ' 1. ' + colors.bold('Design') + ' Agents explore and challenge the approach',
132
+ ' 2. ' + colors.bold('Plan') + ' Agents decompose into testable tasks',
133
+ ' 3. ' + colors.bold('Implement') + ' One builds (TDD), others attack',
134
+ ' 4. ' + colors.bold('Review') + ' Independent reviews, fight over findings',
135
+ '',
136
+ ' Hooks enforce discipline automatically:',
137
+ ' ' + colors.dim('\u2022') + ' No implementation without a design doc',
138
+ ' ' + colors.dim('\u2022') + ' No commits without passing tests',
139
+ ' ' + colors.dim('\u2022') + ' No completion claims without fresh test evidence',
140
+ ' ' + colors.dim('\u2022') + ' Conventional commit messages required',
141
+ '',
142
+ ' ' + colors.dim('Hooks only activate during Raid sessions \u2014 they won\'t'),
143
+ ' ' + colors.dim('interfere with normal coding outside of a Raid.'),
144
+ '',
145
+ ' Config: ' + colors.bold('.claude/raid.json') + ' ' + colors.dim('project settings'),
146
+ ' Rules: ' + colors.bold('.claude/raid-rules.md') + ' ' + colors.dim('editable team rules'),
147
+ ]);
148
+
149
+ const nextStep = box('Next Step', [
150
+ ' ' + colors.bold('claude --agent wizard'),
151
+ '',
152
+ ' Describe your task and the Wizard takes over.',
153
+ ' ' + colors.dim('Tip: start with a small task (bugfix, config change) to'),
154
+ ' ' + colors.dim('see the workflow before tackling something complex.'),
155
+ '',
156
+ ' ' + colors.bold('Controls'),
157
+ ' ' + colors.bold('Shift+Down') + ' Cycle through teammates',
158
+ ' ' + colors.bold('Enter') + ' View a teammate\'s session',
159
+ ' ' + colors.bold('Escape') + ' Interrupt a teammate\'s turn',
160
+ ' ' + colors.bold('Ctrl+T') + ' Toggle the shared task list',
161
+ '',
162
+ ' Review this anytime: ' + colors.bold('claude-raid heal'),
163
+ ]);
164
+
165
+ return howItWorks + '\n' + nextStep;
166
+ }
167
+
168
+ module.exports = { colors, banner, box, header, stripAnsi, referenceCard };
@@ -64,9 +64,9 @@ Read `.claude/raid.json` at session start for project-specific settings (test co
64
64
 
65
65
  ## How You Lead
66
66
 
67
- ### Phase 1 — Comprehension (you alone)
67
+ ### Pre-Phase — Comprehension (you alone)
68
68
 
69
- When a task arrives, you do NOT immediately delegate. You:
69
+ When a task arrives, you do NOT immediately delegate. Before opening any phase, you:
70
70
  1. Read the full prompt. Read it again. Read it a third time.
71
71
  2. Identify the real problem beneath the stated problem.
72
72
  3. Map the blast radius — what does this touch? What could break?
@@ -75,7 +75,9 @@ When a task arrives, you do NOT immediately delegate. You:
75
75
  6. Understand the big picture — the project architecture, its patterns, its conventions.
76
76
  7. Assess complexity and recommend a mode: **Full Raid** (3 agents), **Skirmish** (2 agents), or **Scout** (1 agent). Present recommendation. Proceed only after human confirms.
77
77
 
78
- ### Phase 2Open the Dungeon
78
+ Then proceed to **Phase 1Design** (multi-agent exploration via `raid-design`).
79
+
80
+ ### Phase 1 — Open the Dungeon
79
81
 
80
82
  You set the stage. You give each agent:
81
83
  - The core objective