@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.
- package/LICENSE +21 -0
- package/bin/dev-team.js +22 -0
- package/lib/files.js +160 -0
- package/lib/init.js +206 -0
- package/lib/prompts.js +123 -0
- package/package.json +35 -0
- package/templates/CLAUDE.md +31 -0
- package/templates/agent-memory/dev-team-beck/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-deming/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-knuth/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-mori/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-szabo/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-voss/MEMORY.md +12 -0
- package/templates/agents/dev-team-beck.md +66 -0
- package/templates/agents/dev-team-deming.md +82 -0
- package/templates/agents/dev-team-knuth.md +64 -0
- package/templates/agents/dev-team-mori.md +64 -0
- package/templates/agents/dev-team-szabo.md +64 -0
- package/templates/agents/dev-team-voss.md +64 -0
- package/templates/dev-team-learnings.md +16 -0
- package/templates/hooks/dev-team-post-change-review.js +114 -0
- package/templates/hooks/dev-team-pre-commit-gate.js +59 -0
- package/templates/hooks/dev-team-safety-guard.js +58 -0
- package/templates/hooks/dev-team-task-loop.js +65 -0
- package/templates/hooks/dev-team-tdd-enforce.js +115 -0
- package/templates/settings.json +50 -0
- package/templates/skills/dev-team-challenge/SKILL.md +30 -0
- package/templates/skills/dev-team-task/SKILL.md +47 -0
|
@@ -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.
|