@fredericboyer/dev-team 0.1.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.
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * dev-team-task-loop.js
5
+ * Stop hook — implements iterative task loop with adversarial review gates.
6
+ *
7
+ * When a task loop is active (.claude/dev-team-task.json exists):
8
+ * - Intercepts session exit
9
+ * - Checks if completion criteria are met (no [DEFECT] challenges)
10
+ * - If not met, feeds the task back for another iteration
11
+ * - Respects max iteration limit
12
+ *
13
+ * State file: .claude/dev-team-task.json (created by /dev-team:task skill)
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+
21
+ const STATE_FILE = path.join(process.cwd(), '.claude', 'dev-team-task.json');
22
+
23
+ // No state file means no active task loop — allow normal exit
24
+ if (!fs.existsSync(STATE_FILE)) {
25
+ process.exit(0);
26
+ }
27
+
28
+ let state;
29
+ try {
30
+ state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
31
+ } catch {
32
+ // Corrupted state file — clean up and allow exit
33
+ try { fs.unlinkSync(STATE_FILE); } catch { /* ignore */ }
34
+ process.exit(0);
35
+ }
36
+
37
+ const { prompt, iteration = 1, maxIterations = 10, sessionId } = state;
38
+
39
+ // Check iteration limit
40
+ if (iteration >= maxIterations) {
41
+ console.log(
42
+ `[dev-team task-loop] Max iterations (${maxIterations}) reached. Exiting loop. Review remaining issues manually.`
43
+ );
44
+ try { fs.unlinkSync(STATE_FILE); } catch { /* ignore */ }
45
+ process.exit(0);
46
+ }
47
+
48
+ // Increment iteration and update state
49
+ state.iteration = iteration + 1;
50
+ try {
51
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
52
+ } catch {
53
+ // Can't write state — allow exit
54
+ process.exit(0);
55
+ }
56
+
57
+ // Block exit and re-inject the task prompt
58
+ const output = JSON.stringify({
59
+ decision: 'block',
60
+ reason: prompt,
61
+ 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
+ });
63
+
64
+ console.log(output);
65
+ process.exit(0);
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * dev-team-tdd-enforce.js
5
+ * PostToolUse hook on Edit/Write.
6
+ *
7
+ * Blocks implementation file changes unless:
8
+ * - A test file has been modified in the current session, OR
9
+ * - A corresponding test file already exists (allows refactoring)
10
+ *
11
+ * New implementation files with no existing tests are blocked.
12
+ * Exit 2 = block, exit 0 = allow.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const { execFileSync } = require('child_process');
18
+ const path = require('path');
19
+
20
+ const input = JSON.parse(process.argv[2] || '{}');
21
+ const filePath = (input.tool_input && (input.tool_input.file_path || input.tool_input.path)) || '';
22
+
23
+ if (!filePath) {
24
+ process.exit(0);
25
+ }
26
+
27
+ const basename = path.basename(filePath);
28
+ const ext = path.extname(filePath);
29
+
30
+ // Skip non-code files
31
+ const SKIP_EXTENSIONS = ['.md', '.json', '.yml', '.yaml', '.toml', '.txt', '.css', '.svg', '.png', '.jpg', '.gif', '.ico', '.lock'];
32
+ if (SKIP_EXTENSIONS.includes(ext)) {
33
+ process.exit(0);
34
+ }
35
+
36
+ // 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
+ ];
45
+
46
+ if (TEST_PATTERNS.some((p) => p.test(filePath))) {
47
+ process.exit(0);
48
+ }
49
+
50
+ // Skip config and non-implementation files
51
+ const SKIP_PATTERNS = [
52
+ /\/config\//,
53
+ /\.config\./,
54
+ /\.env/,
55
+ /Dockerfile/,
56
+ /docker-compose/,
57
+ /\.github\//,
58
+ /\.claude\//,
59
+ /node_modules\//,
60
+ ];
61
+
62
+ if (SKIP_PATTERNS.some((p) => p.test(filePath))) {
63
+ process.exit(0);
64
+ }
65
+
66
+ // Check if any test file has been modified in this session
67
+ let changedFiles = '';
68
+ try {
69
+ changedFiles = execFileSync('git', ['diff', '--name-only'], {
70
+ encoding: 'utf-8',
71
+ timeout: 5000,
72
+ });
73
+ } catch {
74
+ // If git is not available or fails, allow the change
75
+ process.exit(0);
76
+ }
77
+
78
+ const hasTestChanges = changedFiles
79
+ .split('\n')
80
+ .filter(Boolean)
81
+ .some((f) => TEST_PATTERNS.some((p) => p.test(f)));
82
+
83
+ if (hasTestChanges) {
84
+ // Tests were modified in this session — allow
85
+ process.exit(0);
86
+ }
87
+
88
+ // No test changes — check if a corresponding test file already exists.
89
+ // This allows refactoring (modifying existing tested code) without
90
+ // requiring the test file to also be modified.
91
+ const fs = require('fs');
92
+ const dir = path.dirname(filePath);
93
+ const name = path.basename(filePath, ext);
94
+
95
+ const CANDIDATE_PATTERNS = [
96
+ path.join(dir, `${name}.test${ext}`),
97
+ path.join(dir, `${name}.spec${ext}`),
98
+ path.join(dir, '__tests__', `${name}${ext}`),
99
+ path.join(dir, '__tests__', `${name}.test${ext}`),
100
+ ];
101
+
102
+ const hasExistingTests = CANDIDATE_PATTERNS.some((candidate) => {
103
+ try { return fs.statSync(candidate).isFile(); } catch { return false; }
104
+ });
105
+
106
+ if (hasExistingTests) {
107
+ // Existing tests cover this file — allow refactoring
108
+ process.exit(0);
109
+ }
110
+
111
+ // No test changes AND no existing test file — block
112
+ console.error(
113
+ `[dev-team tdd-enforce] TDD violation: "${basename}" modified but no corresponding test file exists. Write tests first.`
114
+ );
115
+ process.exit(2);
@@ -0,0 +1,50 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Edit|Write",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node .claude/hooks/dev-team-post-change-review.js"
10
+ },
11
+ {
12
+ "type": "command",
13
+ "command": "node .claude/hooks/dev-team-tdd-enforce.js"
14
+ }
15
+ ]
16
+ }
17
+ ],
18
+ "PreToolUse": [
19
+ {
20
+ "matcher": "Bash",
21
+ "hooks": [
22
+ {
23
+ "type": "command",
24
+ "command": "node .claude/hooks/dev-team-safety-guard.js"
25
+ }
26
+ ]
27
+ }
28
+ ],
29
+ "TaskCompleted": [
30
+ {
31
+ "hooks": [
32
+ {
33
+ "type": "command",
34
+ "command": "node .claude/hooks/dev-team-pre-commit-gate.js"
35
+ }
36
+ ]
37
+ }
38
+ ],
39
+ "Stop": [
40
+ {
41
+ "hooks": [
42
+ {
43
+ "type": "command",
44
+ "command": "node .claude/hooks/dev-team-task-loop.js"
45
+ }
46
+ ]
47
+ }
48
+ ]
49
+ }
50
+ }
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: dev-team:challenge
3
+ description: Challenge a proposed approach, implementation, or design decision. Use when the user says "challenge this", "what could go wrong", "play devil's advocate", or wants a critical review of an idea before committing to it.
4
+ ---
5
+
6
+ Critically examine the following proposal or implementation: $ARGUMENTS
7
+
8
+ Follow this structured review:
9
+
10
+ ## 1. Summarize the proposal
11
+ State what is being proposed in one paragraph. Confirm your understanding before proceeding.
12
+
13
+ ## 2. Identify assumptions
14
+ List every assumption the proposal relies on. For each assumption, state what would have to be true for it to hold.
15
+
16
+ ## 3. Find failure modes
17
+ For each assumption, construct a concrete scenario where it breaks. Be specific — name inputs, conditions, or sequences that cause failure.
18
+
19
+ ## 4. Classify findings
20
+ For each finding, classify it:
21
+ - `[DEFECT]`: Concretely wrong. Will produce incorrect behavior.
22
+ - `[RISK]`: Not wrong today, but creates a likely failure mode.
23
+ - `[QUESTION]`: Decision needs justification.
24
+ - `[SUGGESTION]`: Works, but here is a specific improvement.
25
+
26
+ ## 5. Verdict
27
+ State one of:
28
+ - **Proceed** — No blocking issues. Advisory findings noted.
29
+ - **Revise** — `[DEFECT]` or significant `[RISK]` found. Address before proceeding.
30
+ - **Reconsider** — Fundamental assumptions are flawed. Rethink the approach.
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: dev-team:task
3
+ description: Start an iterative task loop with adversarial review gates. Use when the user wants a task implemented with automatic quality convergence — the loop continues until no [DEFECT] challenges remain or max iterations are reached.
4
+ ---
5
+
6
+ Start a task loop for: $ARGUMENTS
7
+
8
+ ## Setup
9
+
10
+ 1. Parse the task description and any flags:
11
+ - `--max-iterations N` (default: 10)
12
+ - `--reviewers` (default: @dev-team-szabo, @dev-team-knuth)
13
+
14
+ 2. Create the state file `.claude/dev-team-task.json`:
15
+ ```json
16
+ {
17
+ "prompt": "<the original task description>",
18
+ "iteration": 1,
19
+ "maxIterations": <N>,
20
+ "reviewers": ["dev-team-szabo", "dev-team-knuth"]
21
+ }
22
+ ```
23
+
24
+ 3. Determine the right implementing agent based on the task:
25
+ - Backend/API/data work → @dev-team-voss
26
+ - Frontend/UI work → @dev-team-mori
27
+ - Test writing → @dev-team-beck
28
+ - Tooling/config → @dev-team-deming
29
+
30
+ ## Execution loop
31
+
32
+ Each iteration:
33
+ 1. The implementing agent works on the task.
34
+ 2. After implementation, spawn review agents in parallel as background tasks.
35
+ 3. Collect classified challenges from reviewers.
36
+ 4. If any `[DEFECT]` challenges exist, address them in the next iteration.
37
+ 5. If no `[DEFECT]` remains, output `<promise>DONE</promise>` to exit the loop.
38
+
39
+ The Stop hook (`dev-team-task-loop.js`) manages iteration counting and re-injection.
40
+
41
+ ## Completion
42
+
43
+ When the loop exits:
44
+ 1. Delete `.claude/dev-team-task.json`.
45
+ 2. Summarize what was accomplished across all iterations.
46
+ 3. Report any remaining `[RISK]` or `[SUGGESTION]` items for the human to review.
47
+ 4. Write key learnings to agent MEMORY.md files.