@fredericboyer/dev-team 0.1.2 → 0.2.0

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 (39) hide show
  1. package/README.md +128 -0
  2. package/bin/dev-team.js +1 -21
  3. package/dist/bin/dev-team.d.ts +1 -0
  4. package/dist/bin/dev-team.js +28 -0
  5. package/dist/bin/dev-team.js.map +1 -0
  6. package/dist/files.d.ts +51 -0
  7. package/dist/files.js +155 -0
  8. package/dist/files.js.map +1 -0
  9. package/dist/init.d.ts +4 -0
  10. package/dist/init.js +307 -0
  11. package/dist/init.js.map +1 -0
  12. package/dist/prompts.d.ts +25 -0
  13. package/dist/prompts.js +109 -0
  14. package/dist/prompts.js.map +1 -0
  15. package/dist/scan.d.ts +15 -0
  16. package/dist/scan.js +187 -0
  17. package/dist/scan.js.map +1 -0
  18. package/dist/update.d.ts +5 -0
  19. package/dist/update.js +229 -0
  20. package/dist/update.js.map +1 -0
  21. package/package.json +30 -9
  22. package/templates/CLAUDE.md +18 -0
  23. package/templates/agent-memory/dev-team-architect/MEMORY.md +12 -0
  24. package/templates/agent-memory/dev-team-docs/MEMORY.md +12 -0
  25. package/templates/agent-memory/dev-team-release/MEMORY.md +12 -0
  26. package/templates/agents/dev-team-architect.md +62 -0
  27. package/templates/agents/dev-team-deming.md +2 -1
  28. package/templates/agents/dev-team-docs.md +63 -0
  29. package/templates/agents/dev-team-release.md +65 -0
  30. package/templates/hooks/dev-team-post-change-review.js +63 -10
  31. package/templates/hooks/dev-team-pre-commit-gate.js +12 -14
  32. package/templates/hooks/dev-team-safety-guard.js +21 -11
  33. package/templates/hooks/dev-team-task-loop.js +17 -9
  34. package/templates/hooks/dev-team-tdd-enforce.js +42 -23
  35. package/templates/skills/dev-team-audit/SKILL.md +85 -0
  36. package/templates/skills/dev-team-review/SKILL.md +68 -0
  37. package/lib/files.js +0 -160
  38. package/lib/init.js +0 -206
  39. package/lib/prompts.js +0 -123
@@ -8,12 +8,20 @@
8
8
  * the file's domain. Advisory only — always exits 0.
9
9
  */
10
10
 
11
- 'use strict';
11
+ "use strict";
12
12
 
13
- const path = require('path');
13
+ const path = require("path");
14
14
 
15
- const input = JSON.parse(process.argv[2] || '{}');
16
- const filePath = (input.tool_input && (input.tool_input.file_path || input.tool_input.path)) || '';
15
+ let input = {};
16
+ try {
17
+ input = JSON.parse(process.argv[2] || "{}");
18
+ } catch (err) {
19
+ console.warn(
20
+ `[dev-team post-change-review] Warning: Failed to parse hook input, allowing operation. ${err.message}`,
21
+ );
22
+ process.exit(0);
23
+ }
24
+ const filePath = (input.tool_input && (input.tool_input.file_path || input.tool_input.path)) || "";
17
25
 
18
26
  if (!filePath) {
19
27
  process.exit(0);
@@ -47,7 +55,7 @@ const SECURITY_PATTERNS = [
47
55
  ];
48
56
 
49
57
  if (SECURITY_PATTERNS.some((p) => p.test(fullPath) || p.test(basename))) {
50
- flags.push('@dev-team-szabo (security surface changed)');
58
+ flags.push("@dev-team-szabo (security surface changed)");
51
59
  }
52
60
 
53
61
  // API/contract patterns → flag for Mori
@@ -63,7 +71,7 @@ const API_PATTERNS = [
63
71
  ];
64
72
 
65
73
  if (API_PATTERNS.some((p) => p.test(fullPath))) {
66
- flags.push('@dev-team-mori (API contract may affect UI)');
74
+ flags.push("@dev-team-mori (API contract may affect UI)");
67
75
  }
68
76
 
69
77
  // Config/infra patterns → flag for Voss
@@ -79,7 +87,7 @@ const INFRA_PATTERNS = [
79
87
  ];
80
88
 
81
89
  if (INFRA_PATTERNS.some((p) => p.test(fullPath))) {
82
- flags.push('@dev-team-voss (architectural/config change)');
90
+ flags.push("@dev-team-voss (architectural/config change)");
83
91
  }
84
92
 
85
93
  // Tooling patterns → flag for Deming
@@ -96,7 +104,52 @@ const TOOLING_PATTERNS = [
96
104
  ];
97
105
 
98
106
  if (TOOLING_PATTERNS.some((p) => p.test(fullPath))) {
99
- flags.push('@dev-team-deming (tooling change)');
107
+ flags.push("@dev-team-deming (tooling change)");
108
+ }
109
+
110
+ // Documentation patterns → flag for Docs
111
+ const DOC_PATTERNS = [
112
+ /readme/,
113
+ /changelog/,
114
+ /\.md$/,
115
+ /\.mdx$/,
116
+ /\/docs?\//,
117
+ /api-doc/,
118
+ /jsdoc/,
119
+ /typedoc/,
120
+ ];
121
+
122
+ if (DOC_PATTERNS.some((p) => p.test(fullPath))) {
123
+ flags.push("@dev-team-docs (documentation changed)");
124
+ }
125
+
126
+ // Architecture patterns → flag for Architect
127
+ const ARCH_PATTERNS = [
128
+ /\/adr\//,
129
+ /architecture/,
130
+ /\/modules?\//,
131
+ /\/layers?\//,
132
+ /\/core\//,
133
+ /\/domain\//,
134
+ /\/shared\//,
135
+ ];
136
+
137
+ if (ARCH_PATTERNS.some((p) => p.test(fullPath))) {
138
+ flags.push("@dev-team-architect (architectural boundary touched)");
139
+ }
140
+
141
+ // Release patterns → flag for Release
142
+ const RELEASE_PATTERNS = [
143
+ /package\.json$/,
144
+ /pyproject\.toml$/,
145
+ /cargo\.toml$/i,
146
+ /changelog/i,
147
+ /version/,
148
+ /\.github\/workflows\/.*release/,
149
+ ];
150
+
151
+ if (RELEASE_PATTERNS.some((p) => p.test(fullPath))) {
152
+ flags.push("@dev-team-release (version/release artifact changed)");
100
153
  }
101
154
 
102
155
  // Always flag Knuth for non-test implementation files
@@ -104,11 +157,11 @@ const isTestFile = /\.(test|spec)\.|__tests__|\/tests?\//.test(fullPath);
104
157
  const isCodeFile = /\.(js|ts|jsx|tsx|py|rb|go|java|rs|c|cpp|cs)$/.test(fullPath);
105
158
 
106
159
  if (isCodeFile && !isTestFile) {
107
- flags.push('@dev-team-knuth (new or changed code path to audit)');
160
+ flags.push("@dev-team-knuth (new or changed code path to audit)");
108
161
  }
109
162
 
110
163
  if (flags.length > 0) {
111
- console.log(`[dev-team review] Flag for review: ${flags.join(', ')}`);
164
+ console.log(`[dev-team review] Flag for review: ${flags.join(", ")}`);
112
165
  }
113
166
 
114
167
  process.exit(0);
@@ -8,14 +8,14 @@
8
8
  * review agents if they were not consulted. Advisory — always exits 0.
9
9
  */
10
10
 
11
- 'use strict';
11
+ "use strict";
12
12
 
13
- const { execFileSync } = require('child_process');
13
+ const { execFileSync } = require("child_process");
14
14
 
15
- let stagedFiles = '';
15
+ let stagedFiles = "";
16
16
  try {
17
- stagedFiles = execFileSync('git', ['diff', '--cached', '--name-only'], {
18
- encoding: 'utf-8',
17
+ stagedFiles = execFileSync("git", ["diff", "--cached", "--name-only"], {
18
+ encoding: "utf-8",
19
19
  timeout: 5000,
20
20
  });
21
21
  } catch {
@@ -23,7 +23,7 @@ try {
23
23
  process.exit(0);
24
24
  }
25
25
 
26
- const files = stagedFiles.split('\n').filter(Boolean);
26
+ const files = stagedFiles.split("\n").filter(Boolean);
27
27
 
28
28
  if (files.length === 0) {
29
29
  process.exit(0);
@@ -32,28 +32,26 @@ if (files.length === 0) {
32
32
  const reminders = [];
33
33
 
34
34
  const hasSecurityFiles = files.some((f) =>
35
- /auth|login|password|token|session|crypto|secret|permission/.test(f)
35
+ /auth|login|password|token|session|crypto|secret|permission/.test(f),
36
36
  );
37
37
  if (hasSecurityFiles) {
38
- reminders.push('@dev-team-szabo for security review');
38
+ reminders.push("@dev-team-szabo for security review");
39
39
  }
40
40
 
41
41
  const hasImplFiles = files.some(
42
- (f) => /\.(js|ts|jsx|tsx|py|rb|go|java|rs)$/.test(f) && !/\.(test|spec)\./.test(f)
42
+ (f) => /\.(js|ts|jsx|tsx|py|rb|go|java|rs)$/.test(f) && !/\.(test|spec)\./.test(f),
43
43
  );
44
44
  if (hasImplFiles) {
45
- reminders.push('@dev-team-knuth for quality audit');
45
+ reminders.push("@dev-team-knuth for quality audit");
46
46
  }
47
47
 
48
48
  const hasApiFiles = files.some((f) => /\/api\/|\/routes?\/|schema|\.graphql$/.test(f));
49
49
  if (hasApiFiles) {
50
- reminders.push('@dev-team-mori for UI impact review');
50
+ reminders.push("@dev-team-mori for UI impact review");
51
51
  }
52
52
 
53
53
  if (reminders.length > 0) {
54
- console.log(
55
- `[dev-team pre-commit] Before committing, consider running: ${reminders.join(', ')}`
56
- );
54
+ console.log(`[dev-team pre-commit] Before committing, consider running: ${reminders.join(", ")}`);
57
55
  }
58
56
 
59
57
  process.exit(0);
@@ -8,43 +8,53 @@
8
8
  * Exit 2 = block, exit 0 = allow.
9
9
  */
10
10
 
11
- 'use strict';
11
+ "use strict";
12
12
 
13
- const input = JSON.parse(process.argv[2] || '{}');
14
- const command = (input.tool_input && input.tool_input.command) || '';
13
+ let input = {};
14
+ try {
15
+ input = JSON.parse(process.argv[2] || "{}");
16
+ } catch (err) {
17
+ // SECURITY TRADEOFF: Failing open means parse errors bypass safety checks.
18
+ // We accept this because failing closed (exit 2) would block all Bash operations when input is malformed.
19
+ console.warn(
20
+ `[dev-team safety-guard] Warning: Failed to parse hook input, allowing operation. ${err.message}`,
21
+ );
22
+ process.exit(0);
23
+ }
24
+ const command = (input.tool_input && input.tool_input.command) || "";
15
25
 
16
26
  const BLOCKED_PATTERNS = [
17
27
  {
18
28
  pattern: /\brm\s+(-[^\s]*r[^\s]*|--recursive)\s+[^\s]*\s*\/\s*$/,
19
- reason: 'Recursive delete on root path is blocked.',
29
+ reason: "Recursive delete on root path is blocked.",
20
30
  },
21
31
  {
22
32
  pattern: /\brm\s+(-[^\s]*r[^\s]*|--recursive)\s+.*~\//,
23
- reason: 'Recursive delete on home directory is blocked.',
33
+ reason: "Recursive delete on home directory is blocked.",
24
34
  },
25
35
  {
26
36
  pattern: /\bgit\s+push\s+.*--force\b.*\b(main|master)\b/,
27
- reason: 'Force push to main/master is blocked. Use a PR instead.',
37
+ reason: "Force push to main/master is blocked. Use a PR instead.",
28
38
  },
29
39
  {
30
40
  pattern: /\bgit\s+push\s+.*\b(main|master)\b.*--force\b/,
31
- reason: 'Force push to main/master is blocked. Use a PR instead.',
41
+ reason: "Force push to main/master is blocked. Use a PR instead.",
32
42
  },
33
43
  {
34
44
  pattern: /\bDROP\s+(TABLE|DATABASE)\b/i,
35
- reason: 'DROP TABLE/DATABASE is blocked. Use a migration instead.',
45
+ reason: "DROP TABLE/DATABASE is blocked. Use a migration instead.",
36
46
  },
37
47
  {
38
48
  pattern: /\bchmod\s+777\b/,
39
- reason: 'chmod 777 is blocked. Use specific permissions instead.',
49
+ reason: "chmod 777 is blocked. Use specific permissions instead.",
40
50
  },
41
51
  {
42
52
  pattern: /\bcurl\b.*\|\s*(sh|bash|zsh)\b/,
43
- reason: 'Piping curl to a shell is blocked. Download and inspect scripts before executing.',
53
+ reason: "Piping curl to a shell is blocked. Download and inspect scripts before executing.",
44
54
  },
45
55
  {
46
56
  pattern: /\bwget\b.*\|\s*(sh|bash|zsh)\b/,
47
- reason: 'Piping wget to a shell is blocked. Download and inspect scripts before executing.',
57
+ reason: "Piping wget to a shell is blocked. Download and inspect scripts before executing.",
48
58
  },
49
59
  ];
50
60
 
@@ -13,12 +13,12 @@
13
13
  * State file: .claude/dev-team-task.json (created by /dev-team:task skill)
14
14
  */
15
15
 
16
- 'use strict';
16
+ "use strict";
17
17
 
18
- const fs = require('fs');
19
- const path = require('path');
18
+ const fs = require("fs");
19
+ const path = require("path");
20
20
 
21
- const STATE_FILE = path.join(process.cwd(), '.claude', 'dev-team-task.json');
21
+ const STATE_FILE = path.join(process.cwd(), ".claude", "dev-team-task.json");
22
22
 
23
23
  // No state file means no active task loop — allow normal exit
24
24
  if (!fs.existsSync(STATE_FILE)) {
@@ -27,10 +27,14 @@ if (!fs.existsSync(STATE_FILE)) {
27
27
 
28
28
  let state;
29
29
  try {
30
- state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
30
+ state = JSON.parse(fs.readFileSync(STATE_FILE, "utf-8"));
31
31
  } catch {
32
32
  // Corrupted state file — clean up and allow exit
33
- try { fs.unlinkSync(STATE_FILE); } catch { /* ignore */ }
33
+ try {
34
+ fs.unlinkSync(STATE_FILE);
35
+ } catch {
36
+ /* ignore */
37
+ }
34
38
  process.exit(0);
35
39
  }
36
40
 
@@ -39,9 +43,13 @@ const { prompt, iteration = 1, maxIterations = 10, sessionId } = state;
39
43
  // Check iteration limit
40
44
  if (iteration >= maxIterations) {
41
45
  console.log(
42
- `[dev-team task-loop] Max iterations (${maxIterations}) reached. Exiting loop. Review remaining issues manually.`
46
+ `[dev-team task-loop] Max iterations (${maxIterations}) reached. Exiting loop. Review remaining issues manually.`,
43
47
  );
44
- try { fs.unlinkSync(STATE_FILE); } catch { /* ignore */ }
48
+ try {
49
+ fs.unlinkSync(STATE_FILE);
50
+ } catch {
51
+ /* ignore */
52
+ }
45
53
  process.exit(0);
46
54
  }
47
55
 
@@ -56,7 +64,7 @@ try {
56
64
 
57
65
  // Block exit and re-inject the task prompt
58
66
  const output = JSON.stringify({
59
- decision: 'block',
67
+ decision: "block",
60
68
  reason: prompt,
61
69
  systemMessage: `[dev-team task-loop] Iteration ${iteration + 1}/${maxIterations}. Review findings and address any [DEFECT] challenges. When no [DEFECT] remains, output <promise>DONE</promise> to exit the loop. To cancel: delete .claude/dev-team-task.json`,
62
70
  });
@@ -12,13 +12,21 @@
12
12
  * Exit 2 = block, exit 0 = allow.
13
13
  */
14
14
 
15
- 'use strict';
15
+ "use strict";
16
16
 
17
- const { execFileSync } = require('child_process');
18
- const path = require('path');
17
+ const { execFileSync } = require("child_process");
18
+ const path = require("path");
19
19
 
20
- const input = JSON.parse(process.argv[2] || '{}');
21
- const filePath = (input.tool_input && (input.tool_input.file_path || input.tool_input.path)) || '';
20
+ let input = {};
21
+ try {
22
+ input = JSON.parse(process.argv[2] || "{}");
23
+ } catch (err) {
24
+ console.warn(
25
+ `[dev-team tdd-enforce] Warning: Failed to parse hook input, allowing operation. ${err.message}`,
26
+ );
27
+ process.exit(0);
28
+ }
29
+ const filePath = (input.tool_input && (input.tool_input.file_path || input.tool_input.path)) || "";
22
30
 
23
31
  if (!filePath) {
24
32
  process.exit(0);
@@ -28,20 +36,27 @@ const basename = path.basename(filePath);
28
36
  const ext = path.extname(filePath);
29
37
 
30
38
  // Skip non-code files
31
- const SKIP_EXTENSIONS = ['.md', '.json', '.yml', '.yaml', '.toml', '.txt', '.css', '.svg', '.png', '.jpg', '.gif', '.ico', '.lock'];
39
+ const SKIP_EXTENSIONS = [
40
+ ".md",
41
+ ".json",
42
+ ".yml",
43
+ ".yaml",
44
+ ".toml",
45
+ ".txt",
46
+ ".css",
47
+ ".svg",
48
+ ".png",
49
+ ".jpg",
50
+ ".gif",
51
+ ".ico",
52
+ ".lock",
53
+ ];
32
54
  if (SKIP_EXTENSIONS.includes(ext)) {
33
55
  process.exit(0);
34
56
  }
35
57
 
36
58
  // Skip if the file IS a test file
37
- const TEST_PATTERNS = [
38
- /\.test\./,
39
- /\.spec\./,
40
- /_test\./,
41
- /\/__tests__\//,
42
- /\/test\//,
43
- /\/tests\//,
44
- ];
59
+ const TEST_PATTERNS = [/\.test\./, /\.spec\./, /_test\./, /\/__tests__\//, /\/test\//, /\/tests\//];
45
60
 
46
61
  if (TEST_PATTERNS.some((p) => p.test(filePath))) {
47
62
  process.exit(0);
@@ -64,10 +79,10 @@ if (SKIP_PATTERNS.some((p) => p.test(filePath))) {
64
79
  }
65
80
 
66
81
  // Check if any test file has been modified in this session
67
- let changedFiles = '';
82
+ let changedFiles = "";
68
83
  try {
69
- changedFiles = execFileSync('git', ['diff', '--name-only'], {
70
- encoding: 'utf-8',
84
+ changedFiles = execFileSync("git", ["diff", "--name-only"], {
85
+ encoding: "utf-8",
71
86
  timeout: 5000,
72
87
  });
73
88
  } catch {
@@ -76,7 +91,7 @@ try {
76
91
  }
77
92
 
78
93
  const hasTestChanges = changedFiles
79
- .split('\n')
94
+ .split("\n")
80
95
  .filter(Boolean)
81
96
  .some((f) => TEST_PATTERNS.some((p) => p.test(f)));
82
97
 
@@ -88,19 +103,23 @@ if (hasTestChanges) {
88
103
  // No test changes — check if a corresponding test file already exists.
89
104
  // This allows refactoring (modifying existing tested code) without
90
105
  // requiring the test file to also be modified.
91
- const fs = require('fs');
106
+ const fs = require("fs");
92
107
  const dir = path.dirname(filePath);
93
108
  const name = path.basename(filePath, ext);
94
109
 
95
110
  const CANDIDATE_PATTERNS = [
96
111
  path.join(dir, `${name}.test${ext}`),
97
112
  path.join(dir, `${name}.spec${ext}`),
98
- path.join(dir, '__tests__', `${name}${ext}`),
99
- path.join(dir, '__tests__', `${name}.test${ext}`),
113
+ path.join(dir, "__tests__", `${name}${ext}`),
114
+ path.join(dir, "__tests__", `${name}.test${ext}`),
100
115
  ];
101
116
 
102
117
  const hasExistingTests = CANDIDATE_PATTERNS.some((candidate) => {
103
- try { return fs.statSync(candidate).isFile(); } catch { return false; }
118
+ try {
119
+ return fs.statSync(candidate).isFile();
120
+ } catch {
121
+ return false;
122
+ }
104
123
  });
105
124
 
106
125
  if (hasExistingTests) {
@@ -110,6 +129,6 @@ if (hasExistingTests) {
110
129
 
111
130
  // No test changes AND no existing test file — block
112
131
  console.error(
113
- `[dev-team tdd-enforce] TDD violation: "${basename}" modified but no corresponding test file exists. Write tests first.`
132
+ `[dev-team tdd-enforce] TDD violation: "${basename}" modified but no corresponding test file exists. Write tests first.`,
114
133
  );
115
134
  process.exit(2);
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: dev-team:audit
3
+ description: Full codebase audit combining security, quality, and tooling assessments. Use to run a comprehensive scan with Szabo (security), Knuth (quality), and Deming (tooling) in parallel. Can be scoped to specific directories or file patterns.
4
+ ---
5
+
6
+ Run a comprehensive audit of: $ARGUMENTS
7
+
8
+ ## Setup
9
+
10
+ 1. Determine the audit scope:
11
+ - If a directory or file pattern is given, scope the audit to those paths
12
+ - If no argument, audit the entire codebase
13
+ - Respect `.gitignore` — skip `node_modules/`, `dist/`, build artifacts
14
+
15
+ 2. The audit always spawns three specialist agents:
16
+ - **@dev-team-szabo** — Security audit
17
+ - **@dev-team-knuth** — Quality and correctness audit
18
+ - **@dev-team-deming** — Tooling and automation audit
19
+
20
+ ## Execution
21
+
22
+ 1. Spawn all three agents as **parallel background subagents** using the Agent tool with `subagent_type: "general-purpose"`.
23
+
24
+ 2. Each agent's prompt must include:
25
+ - The agent's full definition (read from `.claude/agents/<agent>.md`)
26
+ - The scope (directory/pattern or "full codebase")
27
+ - Instruction to produce classified findings: `[DEFECT]`, `[RISK]`, `[QUESTION]`, `[SUGGESTION]`
28
+ - Instruction to read the actual code and tests for full context
29
+
30
+ 3. Agent-specific instructions:
31
+
32
+ **Szabo (Security)**:
33
+ - Map all trust boundaries and entry points
34
+ - Check for OWASP Top 10 vulnerabilities
35
+ - Audit auth/authz flows end-to-end
36
+ - Review secret management and dependency vulnerabilities
37
+
38
+ **Knuth (Quality)**:
39
+ - Identify untested code paths and coverage gaps
40
+ - Find boundary conditions without tests
41
+ - Check assertion quality in existing tests
42
+ - Map test-to-requirement traceability
43
+
44
+ **Deming (Tooling)**:
45
+ - Inventory current tooling (linters, formatters, SAST, CI)
46
+ - Identify missing automation opportunities
47
+ - Check for stale dependencies and known vulnerabilities
48
+ - Evaluate CI pipeline efficiency
49
+
50
+ 4. Wait for all agents to complete.
51
+
52
+ ## Report
53
+
54
+ Produce a consolidated audit report:
55
+
56
+ ### Executive summary
57
+
58
+ One paragraph summarizing the overall health of the codebase across all three domains.
59
+
60
+ ### Security findings (@dev-team-szabo)
61
+
62
+ List all findings, grouped by classification:
63
+ - `[DEFECT]` — must fix
64
+ - `[RISK]` — should address
65
+ - `[QUESTION]` / `[SUGGESTION]` — consider
66
+
67
+ ### Quality findings (@dev-team-knuth)
68
+
69
+ Same grouping. Include specific files and line references.
70
+
71
+ ### Tooling findings (@dev-team-deming)
72
+
73
+ Same grouping. Include actionable recommendations.
74
+
75
+ ### Priority matrix
76
+
77
+ | Priority | Finding | Agent | Action |
78
+ |----------|---------|-------|--------|
79
+ | P0 (fix now) | `[DEFECT]` items | ... | ... |
80
+ | P1 (fix soon) | `[RISK]` items | ... | ... |
81
+ | P2 (improve) | `[SUGGESTION]` items | ... | ... |
82
+
83
+ ### Recommended next steps
84
+
85
+ Numbered list of concrete actions, ordered by priority. Each action should reference the specific finding it addresses.
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: dev-team:review
3
+ description: Orchestrated multi-agent parallel review. Use to review a PR, branch, or set of changes with multiple specialist agents simultaneously. Spawns agents based on changed file patterns and produces a unified review summary.
4
+ ---
5
+
6
+ Run a multi-agent parallel review of: $ARGUMENTS
7
+
8
+ ## Setup
9
+
10
+ 1. Determine what to review:
11
+ - If a PR number or branch is given, use `git diff` to get the changed files
12
+ - If a directory or file pattern is given, review those files
13
+ - If no argument, review all uncommitted changes (`git diff HEAD`)
14
+
15
+ 2. Categorize changed files by domain to determine which agents to spawn:
16
+
17
+ | File pattern | Agent | Reason |
18
+ |---|---|---|
19
+ | `auth`, `login`, `password`, `token`, `session`, `crypto`, `secret`, `permission`, `oauth`, `jwt`, `cors`, `csrf` | @dev-team-szabo | Security surface |
20
+ | `/api/`, `/routes/`, `schema`, `.graphql`, `.proto`, `openapi` | @dev-team-mori | API/UI contract |
21
+ | `docker`, `.env`, `config`, `migration`, `database`, `.sql`, `deploy` | @dev-team-voss | Infrastructure |
22
+ | `.github/workflows`, `.claude/`, `tsconfig`, `eslint`, `prettier`, `package.json` | @dev-team-deming | Tooling |
23
+ | `readme`, `changelog`, `.md`, `/docs/` | @dev-team-docs | Documentation |
24
+ | `/adr/`, `architecture`, `/core/`, `/domain/` | @dev-team-architect | Architecture |
25
+ | `package.json`, `version`, `changelog`, release workflows | @dev-team-release | Release artifacts |
26
+ | Any `.js`, `.ts`, `.py`, `.go`, `.java`, `.rs` (non-test) | @dev-team-knuth | Quality/coverage |
27
+
28
+ 3. Always include @dev-team-szabo and @dev-team-knuth — they review all code changes.
29
+
30
+ ## Execution
31
+
32
+ 1. Spawn each selected agent as a **parallel background subagent** using the Agent tool with `subagent_type: "general-purpose"`.
33
+
34
+ 2. Each agent's prompt must include:
35
+ - The agent's full definition (read from `.claude/agents/<agent>.md`)
36
+ - The list of changed files relevant to their domain
37
+ - Instruction to produce classified findings: `[DEFECT]`, `[RISK]`, `[QUESTION]`, `[SUGGESTION]`
38
+ - Instruction to read the actual code — not just the diff — for full context
39
+
40
+ 3. Wait for all agents to complete.
41
+
42
+ ## Report
43
+
44
+ Produce a unified review summary:
45
+
46
+ ### Blocking findings ([DEFECT])
47
+
48
+ List all `[DEFECT]` findings from all agents. These must be resolved before merge.
49
+
50
+ Format each as:
51
+ ```
52
+ **[DEFECT]** @agent-name — file:line
53
+ Description of the defect and why it blocks.
54
+ ```
55
+
56
+ ### Advisory findings
57
+
58
+ Group by severity:
59
+ - **[RISK]** — likely failure modes
60
+ - **[QUESTION]** — decisions needing justification
61
+ - **[SUGGESTION]** — specific improvements
62
+
63
+ ### Verdict
64
+
65
+ - **Approve** — No `[DEFECT]` findings. Advisory items noted.
66
+ - **Request changes** — `[DEFECT]` findings must be resolved.
67
+
68
+ State the verdict clearly. List what must be fixed for approval if requesting changes.