@fredericboyer/dev-team 0.4.1 → 0.5.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/dist/bin/dev-team.js +17 -1
- package/dist/bin/dev-team.js.map +1 -1
- package/dist/doctor.d.ts +1 -0
- package/dist/doctor.js +105 -0
- package/dist/doctor.js.map +1 -0
- package/dist/status.d.ts +1 -0
- package/dist/status.js +82 -0
- package/dist/status.js.map +1 -0
- package/package.json +2 -2
- package/templates/CLAUDE.md +21 -1
- package/templates/agents/dev-team-drucker.md +21 -3
- package/templates/hooks/dev-team-post-change-review.js +16 -0
- package/templates/hooks/dev-team-pre-commit-gate.js +31 -9
- package/templates/hooks/dev-team-tdd-enforce.js +30 -5
- package/templates/skills/dev-team-audit/SKILL.md +6 -0
- package/templates/skills/dev-team-review/SKILL.md +6 -0
- package/templates/skills/dev-team-task/SKILL.md +42 -0
package/dist/bin/dev-team.js
CHANGED
|
@@ -3,9 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const init_1 = require("../init");
|
|
4
4
|
const update_1 = require("../update");
|
|
5
5
|
const create_agent_1 = require("../create-agent");
|
|
6
|
+
const doctor_1 = require("../doctor");
|
|
7
|
+
const status_1 = require("../status");
|
|
8
|
+
const files_1 = require("../files");
|
|
6
9
|
const args = process.argv.slice(2);
|
|
7
10
|
const command = args[0];
|
|
8
|
-
if (command === "
|
|
11
|
+
if (command === "--version" || command === "-v") {
|
|
12
|
+
console.log((0, files_1.getPackageVersion)());
|
|
13
|
+
process.exit(0);
|
|
14
|
+
}
|
|
15
|
+
else if (command === "init") {
|
|
9
16
|
(0, init_1.run)(process.cwd(), args.slice(1)).catch((err) => {
|
|
10
17
|
console.error(`Error: ${err.message}`);
|
|
11
18
|
process.exit(1);
|
|
@@ -20,6 +27,12 @@ else if (command === "update") {
|
|
|
20
27
|
else if (command === "create-agent") {
|
|
21
28
|
(0, create_agent_1.createAgent)(process.cwd(), args[1]);
|
|
22
29
|
}
|
|
30
|
+
else if (command === "doctor") {
|
|
31
|
+
(0, doctor_1.doctor)(process.cwd());
|
|
32
|
+
}
|
|
33
|
+
else if (command === "status") {
|
|
34
|
+
(0, status_1.status)(process.cwd());
|
|
35
|
+
}
|
|
23
36
|
else {
|
|
24
37
|
console.log("dev-team — Adversarial AI agent team for any project\n");
|
|
25
38
|
console.log("Usage:");
|
|
@@ -30,6 +43,9 @@ else {
|
|
|
30
43
|
console.log(" npx dev-team init --preset data Data pipeline (backend, quality, tooling)");
|
|
31
44
|
console.log(" npx dev-team update Update agents, hooks, and skills to latest");
|
|
32
45
|
console.log(" npx dev-team create-agent <name> Scaffold a new custom agent");
|
|
46
|
+
console.log(" npx dev-team doctor Check installation health");
|
|
47
|
+
console.log(" npx dev-team status Show installed agents, hooks, and memory");
|
|
48
|
+
console.log(" npx dev-team --version Print version");
|
|
33
49
|
console.log("");
|
|
34
50
|
process.exit(command === "--help" || command === "-h" ? 0 : 1);
|
|
35
51
|
}
|
package/dist/bin/dev-team.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-team.js","sourceRoot":"","sources":["../../src/bin/dev-team.ts"],"names":[],"mappings":";;AAAA,kCAA8B;AAC9B,sCAAmC;AACnC,kDAA8C;
|
|
1
|
+
{"version":3,"file":"dev-team.js","sourceRoot":"","sources":["../../src/bin/dev-team.ts"],"names":[],"mappings":";;AAAA,kCAA8B;AAC9B,sCAAmC;AACnC,kDAA8C;AAC9C,sCAAmC;AACnC,sCAAmC;AACnC,oCAA6C;AAE7C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAExB,IAAI,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,IAAA,yBAAiB,GAAE,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IAC9B,IAAA,UAAG,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;QACrD,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;IAChC,IAAA,eAAM,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;QACzC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;IACtC,IAAA,0BAAW,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;KAAM,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;IAChC,IAAA,eAAM,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AACxB,CAAC;KAAM,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;IAChC,IAAA,eAAM,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AACxB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,oFAAoF,CAAC,CAAC;IAClG,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CAAC,mFAAmF,CAAC,CAAC;IACjG,OAAO,CAAC,GAAG,CAAC,mFAAmF,CAAC,CAAC;IACjG,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;IAC/F,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC"}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function doctor(targetDir: string): void;
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.doctor = doctor;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const files_1 = require("./files");
|
|
9
|
+
function doctor(targetDir) {
|
|
10
|
+
console.log("\ndev-team doctor — Installation health check\n");
|
|
11
|
+
const claudeDir = path_1.default.join(targetDir, ".claude");
|
|
12
|
+
const results = [];
|
|
13
|
+
// 1. dev-team.json exists and is valid
|
|
14
|
+
const prefsPath = path_1.default.join(claudeDir, "dev-team.json");
|
|
15
|
+
const prefsContent = (0, files_1.readFile)(prefsPath);
|
|
16
|
+
let prefs = null;
|
|
17
|
+
if (!prefsContent) {
|
|
18
|
+
results.push({ name: "dev-team.json", pass: false, detail: "Not found" });
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
try {
|
|
22
|
+
prefs = JSON.parse(prefsContent);
|
|
23
|
+
results.push({ name: "dev-team.json", pass: true, detail: `v${prefs.version}` });
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
results.push({ name: "dev-team.json", pass: false, detail: "Invalid JSON" });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// 2. Agent files exist
|
|
30
|
+
if (prefs?.agents) {
|
|
31
|
+
const agentsDir = path_1.default.join(claudeDir, "agents");
|
|
32
|
+
for (const label of prefs.agents) {
|
|
33
|
+
// Convert label to filename pattern
|
|
34
|
+
const fileName = `dev-team-${label.toLowerCase()}.md`;
|
|
35
|
+
const exists = (0, files_1.fileExists)(path_1.default.join(agentsDir, fileName));
|
|
36
|
+
results.push({
|
|
37
|
+
name: `Agent: ${label}`,
|
|
38
|
+
pass: exists,
|
|
39
|
+
detail: exists ? fileName : `${fileName} missing`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// 3. Hook files exist
|
|
44
|
+
if (prefs?.hooks) {
|
|
45
|
+
const hooksDir = path_1.default.join(claudeDir, "hooks");
|
|
46
|
+
const hookFileMap = {
|
|
47
|
+
"TDD enforcement": "dev-team-tdd-enforce.js",
|
|
48
|
+
"Safety guard": "dev-team-safety-guard.js",
|
|
49
|
+
"Post-change review": "dev-team-post-change-review.js",
|
|
50
|
+
"Pre-commit gate": "dev-team-pre-commit-gate.js",
|
|
51
|
+
"Task loop": "dev-team-task-loop.js",
|
|
52
|
+
"Watch list": "dev-team-watch-list.js",
|
|
53
|
+
"Pre-commit lint": "dev-team-pre-commit-lint.js",
|
|
54
|
+
};
|
|
55
|
+
for (const label of prefs.hooks) {
|
|
56
|
+
const fileName = hookFileMap[label];
|
|
57
|
+
if (!fileName) {
|
|
58
|
+
results.push({ name: `Hook: ${label}`, pass: false, detail: "Unknown hook" });
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const exists = (0, files_1.fileExists)(path_1.default.join(hooksDir, fileName));
|
|
62
|
+
results.push({
|
|
63
|
+
name: `Hook: ${label}`,
|
|
64
|
+
pass: exists,
|
|
65
|
+
detail: exists ? fileName : `${fileName} missing`,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// 4. CLAUDE.md has dev-team markers
|
|
70
|
+
const claudeMdPath = path_1.default.join(targetDir, "CLAUDE.md");
|
|
71
|
+
const claudeMd = (0, files_1.readFile)(claudeMdPath);
|
|
72
|
+
if (!claudeMd) {
|
|
73
|
+
results.push({ name: "CLAUDE.md", pass: false, detail: "Not found" });
|
|
74
|
+
}
|
|
75
|
+
else if (!claudeMd.includes("<!-- dev-team:begin -->")) {
|
|
76
|
+
results.push({ name: "CLAUDE.md", pass: false, detail: "Missing dev-team markers" });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
results.push({ name: "CLAUDE.md", pass: true, detail: "Markers present" });
|
|
80
|
+
}
|
|
81
|
+
// 5. Agent memory directories
|
|
82
|
+
if (prefs?.agents) {
|
|
83
|
+
const memoryDir = path_1.default.join(claudeDir, "agent-memory");
|
|
84
|
+
for (const label of prefs.agents) {
|
|
85
|
+
const dirName = `dev-team-${label.toLowerCase()}`;
|
|
86
|
+
const memPath = path_1.default.join(memoryDir, dirName, "MEMORY.md");
|
|
87
|
+
const exists = (0, files_1.fileExists)(memPath);
|
|
88
|
+
results.push({
|
|
89
|
+
name: `Memory: ${label}`,
|
|
90
|
+
pass: exists,
|
|
91
|
+
detail: exists ? "MEMORY.md present" : "MEMORY.md missing",
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Print results
|
|
96
|
+
const passed = results.filter((r) => r.pass).length;
|
|
97
|
+
const failed = results.filter((r) => !r.pass).length;
|
|
98
|
+
for (const r of results) {
|
|
99
|
+
const icon = r.pass ? " OK" : " FAIL";
|
|
100
|
+
console.log(`${icon} ${r.name} — ${r.detail}`);
|
|
101
|
+
}
|
|
102
|
+
console.log(`\n${passed} passed, ${failed} failed\n`);
|
|
103
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/status.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function status(targetDir: string): void;
|
package/dist/status.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.status = status;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const files_1 = require("./files");
|
|
10
|
+
function status(targetDir) {
|
|
11
|
+
const claudeDir = path_1.default.join(targetDir, ".claude");
|
|
12
|
+
const prefsPath = path_1.default.join(claudeDir, "dev-team.json");
|
|
13
|
+
const prefsContent = (0, files_1.readFile)(prefsPath);
|
|
14
|
+
if (!prefsContent) {
|
|
15
|
+
console.error("Not a dev-team project. Run `npx dev-team init` first.");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
let prefs;
|
|
19
|
+
try {
|
|
20
|
+
prefs = JSON.parse(prefsContent);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
console.error("dev-team.json is corrupted.");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
console.log("\ndev-team status\n");
|
|
27
|
+
// Version and preset
|
|
28
|
+
console.log(` Version: v${prefs.version}`);
|
|
29
|
+
if (prefs.preset) {
|
|
30
|
+
console.log(` Preset: ${prefs.preset}`);
|
|
31
|
+
}
|
|
32
|
+
// Agents
|
|
33
|
+
const agents = prefs.agents || [];
|
|
34
|
+
console.log(` Agents: ${agents.join(", ")} (${agents.length})`);
|
|
35
|
+
// Hooks
|
|
36
|
+
const hooks = prefs.hooks || [];
|
|
37
|
+
console.log(` Hooks: ${hooks.join(", ")} (${hooks.length})`);
|
|
38
|
+
// Skills (auto-discovered)
|
|
39
|
+
const skillsDir = path_1.default.join(claudeDir, "skills");
|
|
40
|
+
const skills = (0, files_1.listSubdirectories)(skillsDir).map((s) => s.replace("dev-team-", ""));
|
|
41
|
+
console.log(` Skills: ${skills.length > 0 ? skills.join(", ") : "none"} (${skills.length})`);
|
|
42
|
+
// Workflow
|
|
43
|
+
if (prefs.issueTracker) {
|
|
44
|
+
console.log(` Tracker: ${prefs.issueTracker}`);
|
|
45
|
+
}
|
|
46
|
+
if (prefs.branchConvention && prefs.branchConvention !== "None") {
|
|
47
|
+
console.log(` Branches: ${prefs.branchConvention}`);
|
|
48
|
+
}
|
|
49
|
+
// Memory status
|
|
50
|
+
console.log("\n Memory:");
|
|
51
|
+
const memoryDir = path_1.default.join(claudeDir, "agent-memory");
|
|
52
|
+
for (const label of agents) {
|
|
53
|
+
const dirName = `dev-team-${label.toLowerCase()}`;
|
|
54
|
+
const memPath = path_1.default.join(memoryDir, dirName, "MEMORY.md");
|
|
55
|
+
if ((0, files_1.fileExists)(memPath)) {
|
|
56
|
+
try {
|
|
57
|
+
const stat = fs_1.default.statSync(memPath);
|
|
58
|
+
const hasContent = stat.size > 200; // Template is ~200 bytes
|
|
59
|
+
console.log(` ${label}: ${hasContent ? "has learnings" : "empty (template only)"}`);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
console.log(` ${label}: unknown`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log(` ${label}: no memory file`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Shared learnings
|
|
70
|
+
const learningsPath = path_1.default.join(claudeDir, "dev-team-learnings.md");
|
|
71
|
+
if ((0, files_1.fileExists)(learningsPath)) {
|
|
72
|
+
try {
|
|
73
|
+
const stat = fs_1.default.statSync(learningsPath);
|
|
74
|
+
console.log(` Shared learnings: ${stat.size > 300 ? "has content" : "template only"}`);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
console.log(` Shared learnings: unknown`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
console.log("");
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fredericboyer/dev-team",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Adversarial AI agent team for any project — installs Claude Code agents, hooks, and skills that enforce quality through productive friction",
|
|
5
5
|
"main": "dist/init.js",
|
|
6
6
|
"types": "dist/init.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsc",
|
|
17
17
|
"pretest": "npm run build",
|
|
18
|
-
"test": "node --test tests/unit/files.test.js tests/unit/hooks.test.js tests/unit/scan.test.js tests/unit/create-agent.test.js tests/integration/fresh-project.test.js tests/integration/idempotency.test.js tests/integration/update.test.js tests/scenarios/node-project.test.js tests/scenarios/python-project.test.js tests/scenarios/upgrade-path.test.js",
|
|
18
|
+
"test": "node --test tests/unit/files.test.js tests/unit/hooks.test.js tests/unit/scan.test.js tests/unit/create-agent.test.js tests/unit/cli.test.js tests/integration/fresh-project.test.js tests/integration/idempotency.test.js tests/integration/update.test.js tests/scenarios/node-project.test.js tests/scenarios/python-project.test.js tests/scenarios/upgrade-path.test.js",
|
|
19
19
|
"test:unit": "node --test tests/unit/files.test.js tests/unit/hooks.test.js",
|
|
20
20
|
"test:integration": "node --test tests/integration/fresh-project.test.js tests/integration/idempotency.test.js",
|
|
21
21
|
"test:scenarios": "node --test tests/scenarios/node-project.test.js tests/scenarios/python-project.test.js tests/scenarios/upgrade-path.test.js",
|
package/templates/CLAUDE.md
CHANGED
|
@@ -18,7 +18,7 @@ This project uses [dev-team](https://github.com/dev-team) — adversarial AI age
|
|
|
18
18
|
| `@dev-team-brooks` | Architect | Architectural review, coupling, dependency direction, ADR compliance |
|
|
19
19
|
| `@dev-team-conway` | Release Manager | Versioning, changelog, release readiness, semver validation |
|
|
20
20
|
| `@dev-team-drucker` | Team Lead / Orchestrator | Auto-delegates to specialists, manages review loops, resolves conflicts |
|
|
21
|
-
| `@dev-team-borges` | Librarian | End-of-task memory review, cross-agent coherence, system improvement |
|
|
21
|
+
| `@dev-team-borges` | Librarian | End-of-task/review/audit memory review, cross-agent coherence, system improvement |
|
|
22
22
|
|
|
23
23
|
### Workflow
|
|
24
24
|
|
|
@@ -26,10 +26,30 @@ For automatic delegation, use `@dev-team-drucker` — it analyzes the task and r
|
|
|
26
26
|
|
|
27
27
|
For non-trivial work: explore the area first, then implement, then review.
|
|
28
28
|
|
|
29
|
+
**Automatic invocation (hooks):**
|
|
30
|
+
- **Szabo** — auto-flagged when security-sensitive files change (auth, token, session, crypto, etc.)
|
|
31
|
+
- **Knuth** — auto-flagged when any non-test implementation code changes
|
|
32
|
+
- **Mori** — auto-flagged when API contract files change (/api/, /routes/, schema, etc.)
|
|
33
|
+
- **Voss** — auto-flagged when infrastructure/config files change (docker, .env, migrations, etc.)
|
|
34
|
+
- **Deming** — auto-flagged when tooling files change (eslint, CI workflows, package.json, etc.)
|
|
35
|
+
- **Tufte** — auto-flagged when documentation files change (.md, /docs/, README, etc.)
|
|
36
|
+
- **Brooks** — auto-flagged when architectural boundaries are touched (/adr/, /core/, /domain/, /lib/, build config, etc.)
|
|
37
|
+
- **Conway** — auto-flagged when release artifacts change (package.json, changelog, version files, release/publish/deploy workflows, etc.)
|
|
38
|
+
|
|
39
|
+
**End-of-workflow agents:**
|
|
40
|
+
- **Borges** — mandatory at end of every `/dev-team:task`, `/dev-team:review`, and `/dev-team:audit`. Reviews memory freshness, cross-agent coherence, and system improvement opportunities.
|
|
41
|
+
|
|
42
|
+
**Orchestration:**
|
|
43
|
+
- **Drucker** — delegates tasks to the right implementing agent and spawns reviewers. Brooks reviews ALL structural changes (not just explicit architecture files). Szabo and Knuth review all code changes.
|
|
44
|
+
|
|
29
45
|
Agents challenge each other using classified findings:
|
|
30
46
|
- `[DEFECT]` blocks progress. `[RISK]`, `[QUESTION]`, `[SUGGESTION]` are advisory.
|
|
31
47
|
- When agents disagree, they escalate to the human after one exchange each. Human decides.
|
|
32
48
|
|
|
49
|
+
### Parallel execution
|
|
50
|
+
|
|
51
|
+
When working on multiple independent issues, use parallel agents on separate branches. Drucker coordinates the review wave after all implementations complete. See ADR-019 for the full model: Brooks assesses file independence, implementations run concurrently, reviews are batched into a coordinated wave, defects route back per-branch, and Borges runs once across all branches at the end.
|
|
52
|
+
|
|
33
53
|
### Hook directives are MANDATORY
|
|
34
54
|
|
|
35
55
|
When a dev-team hook outputs `ACTION REQUIRED — spawn these agents`, you MUST:
|
|
@@ -42,9 +42,9 @@ Based on the classification, select:
|
|
|
42
42
|
|---------|-------|--------------------|
|
|
43
43
|
| Security | @dev-team-szabo | Always for code changes |
|
|
44
44
|
| Quality/correctness | @dev-team-knuth | Always for code changes |
|
|
45
|
-
| Architecture | @dev-team-brooks |
|
|
46
|
-
| Documentation | @dev-team-tufte | When APIs
|
|
47
|
-
| Release | @dev-team-conway | When version-related files change |
|
|
45
|
+
| Architecture | @dev-team-brooks | Always for structural changes (new files, moved files, changed exports, new dependencies, config changes). Skip only for content-only edits to existing files. |
|
|
46
|
+
| Documentation | @dev-team-tufte | When APIs, public interfaces, or documentation files change |
|
|
47
|
+
| Release | @dev-team-conway | When version-related files change (package.json, changelog, version bumps, release workflows) |
|
|
48
48
|
|
|
49
49
|
### 3. Architect pre-assessment
|
|
50
50
|
|
|
@@ -94,6 +94,24 @@ When no `[DEFECT]` findings remain:
|
|
|
94
94
|
4. List which agents reviewed and their verdicts.
|
|
95
95
|
5. Write learnings to agent memory files.
|
|
96
96
|
|
|
97
|
+
### Parallel orchestration
|
|
98
|
+
|
|
99
|
+
When working on multiple issues simultaneously (see ADR-019):
|
|
100
|
+
|
|
101
|
+
1. **Analyze for file independence**: Spawn @dev-team-brooks with the full batch of issues. Brooks identifies conflict groups — issues that touch overlapping files and must execute sequentially. Independent issues can proceed in parallel.
|
|
102
|
+
|
|
103
|
+
2. **Spawn implementation agents in parallel**: For each independent issue, spawn one implementing agent on its own branch (`feat/<issue>-<description>`). Each agent works without awareness of other parallel agents. Track state in `.claude/dev-team-parallel.json`.
|
|
104
|
+
|
|
105
|
+
3. **Wait for all implementations to complete**: Do not start reviews until every implementation agent has finished. This is the synchronization barrier.
|
|
106
|
+
|
|
107
|
+
4. **Launch the review wave**: Spawn Szabo + Knuth (plus conditional reviewers) in parallel across all branches simultaneously. Each reviewer receives the diff for one specific branch and produces classified findings scoped to that branch.
|
|
108
|
+
|
|
109
|
+
5. **Route defects back per-branch**: Collect all findings. Route `[DEFECT]` items back to the original implementing agent for each branch. After fixes, run another review wave. Repeat until convergence or the per-branch iteration limit is reached.
|
|
110
|
+
|
|
111
|
+
6. **Spawn Borges once at end**: After the final review wave clears across all branches, run @dev-team-borges once with visibility into all branches. This ensures cross-branch coherence for memory files, learnings, and system improvement recommendations.
|
|
112
|
+
|
|
113
|
+
Conflict groups (issues with file overlaps) execute sequentially within the group but in parallel with other groups and independent issues.
|
|
114
|
+
|
|
97
115
|
## Focus areas
|
|
98
116
|
|
|
99
117
|
You always check for:
|
|
@@ -132,6 +132,11 @@ const ARCH_PATTERNS = [
|
|
|
132
132
|
/\/core\//,
|
|
133
133
|
/\/domain\//,
|
|
134
134
|
/\/shared\//,
|
|
135
|
+
/\/lib\//,
|
|
136
|
+
/\/plugins?\//,
|
|
137
|
+
/\/middleware\//,
|
|
138
|
+
/tsconfig/,
|
|
139
|
+
/webpack|vite|rollup|esbuild/,
|
|
135
140
|
];
|
|
136
141
|
|
|
137
142
|
if (ARCH_PATTERNS.some((p) => p.test(fullPath))) {
|
|
@@ -146,6 +151,12 @@ const RELEASE_PATTERNS = [
|
|
|
146
151
|
/changelog/i,
|
|
147
152
|
/version/,
|
|
148
153
|
/\.github\/workflows\/.*release/,
|
|
154
|
+
/\.github\/workflows\/.*publish/,
|
|
155
|
+
/\.github\/workflows\/.*deploy/,
|
|
156
|
+
/\.npmrc$/,
|
|
157
|
+
/\.npmignore$/,
|
|
158
|
+
/release\.config/,
|
|
159
|
+
/lerna\.json$/,
|
|
149
160
|
];
|
|
150
161
|
|
|
151
162
|
if (RELEASE_PATTERNS.some((p) => p.test(fullPath))) {
|
|
@@ -160,6 +171,11 @@ if (isCodeFile && !isTestFile) {
|
|
|
160
171
|
flags.push("@dev-team-knuth (new or changed code path to audit)");
|
|
161
172
|
}
|
|
162
173
|
|
|
174
|
+
// Flag Beck for test file changes (test quality review)
|
|
175
|
+
if (isTestFile && isCodeFile) {
|
|
176
|
+
flags.push("@dev-team-beck (test file changed — review test quality)");
|
|
177
|
+
}
|
|
178
|
+
|
|
163
179
|
if (flags.length === 0) {
|
|
164
180
|
process.exit(0);
|
|
165
181
|
}
|
|
@@ -14,16 +14,41 @@
|
|
|
14
14
|
|
|
15
15
|
"use strict";
|
|
16
16
|
|
|
17
|
+
const { createHash } = require("crypto");
|
|
18
|
+
const { execFileSync } = require("child_process");
|
|
17
19
|
const fs = require("fs");
|
|
20
|
+
const os = require("os");
|
|
18
21
|
const path = require("path");
|
|
19
|
-
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Cached git diff — reads from a temp file if it was written < 5 seconds ago,
|
|
25
|
+
* otherwise shells out to git and writes the result for subsequent hooks.
|
|
26
|
+
* Cache key includes cwd hash so different repos don't share cache.
|
|
27
|
+
*/
|
|
28
|
+
function cachedGitDiff(args, timeoutMs) {
|
|
29
|
+
const cwdHash = createHash("md5").update(process.cwd()).digest("hex").slice(0, 8);
|
|
30
|
+
const argsKey = args.join("-").replace(/[^a-zA-Z0-9-]/g, "");
|
|
31
|
+
const cacheFile = path.join(os.tmpdir(), `dev-team-git-cache-${cwdHash}-${argsKey}.txt`);
|
|
32
|
+
try {
|
|
33
|
+
const stat = fs.statSync(cacheFile);
|
|
34
|
+
if (Date.now() - stat.mtimeMs < 5000) {
|
|
35
|
+
return fs.readFileSync(cacheFile, "utf-8");
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
// No cache or stale — fall through to git call
|
|
39
|
+
}
|
|
40
|
+
const result = execFileSync("git", args, { encoding: "utf-8", timeout: timeoutMs });
|
|
41
|
+
try {
|
|
42
|
+
fs.writeFileSync(cacheFile, result);
|
|
43
|
+
} catch {
|
|
44
|
+
// Best effort — don't fail the hook over caching
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
20
48
|
|
|
21
49
|
let stagedFiles = "";
|
|
22
50
|
try {
|
|
23
|
-
stagedFiles =
|
|
24
|
-
encoding: "utf-8",
|
|
25
|
-
timeout: 5000,
|
|
26
|
-
});
|
|
51
|
+
stagedFiles = cachedGitDiff(["diff", "--cached", "--name-only"], 2000);
|
|
27
52
|
} catch {
|
|
28
53
|
// Not in a git repo or git not available
|
|
29
54
|
process.exit(0);
|
|
@@ -79,10 +104,7 @@ const hasMemoryUpdates = files.some(
|
|
|
79
104
|
if (hasImplFiles && !hasMemoryUpdates) {
|
|
80
105
|
let unstagedMemory = false;
|
|
81
106
|
try {
|
|
82
|
-
const unstaged =
|
|
83
|
-
encoding: "utf-8",
|
|
84
|
-
timeout: 5000,
|
|
85
|
-
});
|
|
107
|
+
const unstaged = cachedGitDiff(["diff", "--name-only"], 2000);
|
|
86
108
|
unstagedMemory = unstaged
|
|
87
109
|
.split("\n")
|
|
88
110
|
.map((f) => f.split("\\").join("/"))
|
|
@@ -14,9 +14,38 @@
|
|
|
14
14
|
|
|
15
15
|
"use strict";
|
|
16
16
|
|
|
17
|
+
const { createHash } = require("crypto");
|
|
17
18
|
const { execFileSync } = require("child_process");
|
|
19
|
+
const fs = require("fs");
|
|
20
|
+
const os = require("os");
|
|
18
21
|
const path = require("path");
|
|
19
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Cached git diff — reads from a temp file if it was written < 5 seconds ago,
|
|
25
|
+
* otherwise shells out to git and writes the result for subsequent hooks.
|
|
26
|
+
* Cache key includes cwd hash so different repos don't share cache.
|
|
27
|
+
*/
|
|
28
|
+
function cachedGitDiff(args, timeoutMs) {
|
|
29
|
+
const cwdHash = createHash("md5").update(process.cwd()).digest("hex").slice(0, 8);
|
|
30
|
+
const argsKey = args.join("-").replace(/[^a-zA-Z0-9-]/g, "");
|
|
31
|
+
const cacheFile = path.join(os.tmpdir(), `dev-team-git-cache-${cwdHash}-${argsKey}.txt`);
|
|
32
|
+
try {
|
|
33
|
+
const stat = fs.statSync(cacheFile);
|
|
34
|
+
if (Date.now() - stat.mtimeMs < 5000) {
|
|
35
|
+
return fs.readFileSync(cacheFile, "utf-8");
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
// No cache or stale — fall through to git call
|
|
39
|
+
}
|
|
40
|
+
const result = execFileSync("git", args, { encoding: "utf-8", timeout: timeoutMs });
|
|
41
|
+
try {
|
|
42
|
+
fs.writeFileSync(cacheFile, result);
|
|
43
|
+
} catch {
|
|
44
|
+
// Best effort — don't fail the hook over caching
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
20
49
|
let input = {};
|
|
21
50
|
try {
|
|
22
51
|
input = JSON.parse(process.argv[2] || "{}");
|
|
@@ -82,10 +111,7 @@ if (SKIP_PATTERNS.some((p) => p.test(filePath))) {
|
|
|
82
111
|
// Check if any test file has been modified in this session
|
|
83
112
|
let changedFiles = "";
|
|
84
113
|
try {
|
|
85
|
-
changedFiles =
|
|
86
|
-
encoding: "utf-8",
|
|
87
|
-
timeout: 5000,
|
|
88
|
-
});
|
|
114
|
+
changedFiles = cachedGitDiff(["diff", "--name-only"], 2000);
|
|
89
115
|
} catch {
|
|
90
116
|
// If git is not available or fails, allow the change
|
|
91
117
|
process.exit(0);
|
|
@@ -105,7 +131,6 @@ if (hasTestChanges) {
|
|
|
105
131
|
// No test changes — check if a corresponding test file already exists.
|
|
106
132
|
// This allows refactoring (modifying existing tested code) without
|
|
107
133
|
// requiring the test file to also be modified.
|
|
108
|
-
const fs = require("fs");
|
|
109
134
|
const dir = path.dirname(filePath);
|
|
110
135
|
const name = path.basename(filePath, ext);
|
|
111
136
|
|
|
@@ -83,3 +83,9 @@ Same grouping. Include actionable recommendations.
|
|
|
83
83
|
### Recommended next steps
|
|
84
84
|
|
|
85
85
|
Numbered list of concrete actions, ordered by priority. Each action should reference the specific finding it addresses.
|
|
86
|
+
|
|
87
|
+
### Completion
|
|
88
|
+
|
|
89
|
+
After the audit report is delivered:
|
|
90
|
+
1. Spawn **@dev-team-borges** (Librarian) to review memory freshness and capture learnings from the audit findings. This is mandatory.
|
|
91
|
+
2. Include Borges's recommendations in the final report.
|
|
@@ -66,3 +66,9 @@ Group by severity:
|
|
|
66
66
|
- **Request changes** — `[DEFECT]` findings must be resolved.
|
|
67
67
|
|
|
68
68
|
State the verdict clearly. List what must be fixed for approval if requesting changes.
|
|
69
|
+
|
|
70
|
+
### Completion
|
|
71
|
+
|
|
72
|
+
After the review report is delivered:
|
|
73
|
+
1. Spawn **@dev-team-borges** (Librarian) to review memory freshness and capture any learnings from the review findings. This is mandatory.
|
|
74
|
+
2. Include Borges's recommendations in the final report.
|
|
@@ -50,6 +50,48 @@ Each iteration:
|
|
|
50
50
|
|
|
51
51
|
The Stop hook (`dev-team-task-loop.js`) manages iteration counting and re-injection.
|
|
52
52
|
|
|
53
|
+
## Parallel mode
|
|
54
|
+
|
|
55
|
+
When multiple issues are being addressed in a single session, the task loop switches to parallel orchestration (see ADR-019). Drucker coordinates all phases.
|
|
56
|
+
|
|
57
|
+
### Phase 0: Brooks pre-assessment (batch)
|
|
58
|
+
Spawn @dev-team-brooks once with all issues. Brooks identifies:
|
|
59
|
+
- **File independence**: which issues touch overlapping files (conflict groups that must run sequentially)
|
|
60
|
+
- **ADR needs** across the batch
|
|
61
|
+
- **Architectural interactions** between issues
|
|
62
|
+
|
|
63
|
+
Issues in the same conflict group execute sequentially. Independent issues proceed in parallel.
|
|
64
|
+
|
|
65
|
+
### Phase 1: Parallel implementation
|
|
66
|
+
Drucker spawns one implementing agent per independent issue, each on its own branch (`feat/<issue>-<description>`). Agents work concurrently without awareness of each other. Track state in `.claude/dev-team-parallel.json`:
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mode": "parallel",
|
|
70
|
+
"issues": [
|
|
71
|
+
{ "issue": 42, "branch": "feat/42-add-auth", "agent": "dev-team-voss", "status": "implementing" },
|
|
72
|
+
{ "issue": 43, "branch": "feat/43-fix-nav", "agent": "dev-team-mori", "status": "implementing" }
|
|
73
|
+
],
|
|
74
|
+
"phase": "implementation",
|
|
75
|
+
"conflictGroups": [[42, 55]],
|
|
76
|
+
"reviewWave": null
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Phase 2: Review wave
|
|
81
|
+
Reviews do **not** start until **all** implementation agents have completed. Once all are done, spawn review agents (Szabo + Knuth, plus conditional reviewers) in parallel across all branches simultaneously. Each reviewer receives the diff for one specific branch and produces classified findings scoped to that branch.
|
|
82
|
+
|
|
83
|
+
### Phase 3: Defect routing
|
|
84
|
+
Collect all findings. Route `[DEFECT]` items back to the original implementing agent for each branch. Agents fix defects on their own branch. After fixes, another review wave runs. Continue until no `[DEFECT]` findings remain or the per-branch iteration limit is reached.
|
|
85
|
+
|
|
86
|
+
### Phase 4: Borges completion
|
|
87
|
+
Borges runs **once** across all branches after the final review wave clears. This ensures cross-branch coherence: memory files are consistent, learnings are not duplicated, and system improvement recommendations consider the full batch.
|
|
88
|
+
|
|
89
|
+
### Convergence criteria
|
|
90
|
+
Parallel mode is complete when:
|
|
91
|
+
1. All branches have zero `[DEFECT]` findings, OR the per-branch iteration limit (default: 10) is reached
|
|
92
|
+
2. Borges has run across all branches
|
|
93
|
+
3. `.claude/dev-team-parallel.json` is deleted
|
|
94
|
+
|
|
53
95
|
## Completion
|
|
54
96
|
|
|
55
97
|
When the loop exits:
|