@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.
@@ -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 === "init") {
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dev-team.js","sourceRoot":"","sources":["../../src/bin/dev-team.ts"],"names":[],"mappings":";;AAAA,kCAA8B;AAC9B,sCAAmC;AACnC,kDAA8C;AAE9C,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,MAAM,EAAE,CAAC;IACvB,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,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,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"}
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"}
@@ -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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"}
@@ -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":";;;;;AAIA,wBA8EC;AAlFD,gDAAwB;AACxB,4CAAoB;AACpB,mCAAmE;AAEnE,SAAgB,MAAM,CAAC,SAAiB;IACtC,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAExD,MAAM,YAAY,GAAG,IAAA,gBAAQ,EAAC,SAAS,CAAC,CAAC;IACzC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,KAA8B,CAAC;IACnC,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAEnC,qBAAqB;IACrB,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7C,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,SAAS;IACT,MAAM,MAAM,GAAI,KAAK,CAAC,MAAmB,IAAI,EAAE,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAEnE,QAAQ;IACR,MAAM,KAAK,GAAI,KAAK,CAAC,KAAkB,IAAI,EAAE,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAEjE,2BAA2B;IAC3B,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAA,0BAAkB,EAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAEhG,WAAW;IACX,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,gBAAgB;IAChB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,YAAY,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3D,IAAI,IAAA,kBAAU,EAAC,OAAO,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAClC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,yBAAyB;gBAC7D,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC;YACzF,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,kBAAkB,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;IACpE,IAAI,IAAA,kBAAU,EAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAC5F,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fredericboyer/dev-team",
3
- "version": "0.4.1",
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",
@@ -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 | When touching module boundaries, dependencies, or ADRs |
46
- | Documentation | @dev-team-tufte | When APIs or public interfaces change |
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
- const { execFileSync } = require("child_process");
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 = execFileSync("git", ["diff", "--cached", "--name-only"], {
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 = execFileSync("git", ["diff", "--name-only"], {
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 = execFileSync("git", ["diff", "--name-only"], {
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: