@fredericboyer/dev-team 0.1.1 → 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.
- package/README.md +128 -0
- package/bin/dev-team.js +1 -21
- package/dist/bin/dev-team.d.ts +1 -0
- package/dist/bin/dev-team.js +28 -0
- package/dist/bin/dev-team.js.map +1 -0
- package/dist/files.d.ts +51 -0
- package/dist/files.js +155 -0
- package/dist/files.js.map +1 -0
- package/dist/init.d.ts +4 -0
- package/dist/init.js +307 -0
- package/dist/init.js.map +1 -0
- package/dist/prompts.d.ts +25 -0
- package/dist/prompts.js +109 -0
- package/dist/prompts.js.map +1 -0
- package/dist/scan.d.ts +15 -0
- package/dist/scan.js +187 -0
- package/dist/scan.js.map +1 -0
- package/dist/update.d.ts +5 -0
- package/dist/update.js +229 -0
- package/dist/update.js.map +1 -0
- package/package.json +30 -9
- package/templates/CLAUDE.md +18 -0
- package/templates/agent-memory/dev-team-architect/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-docs/MEMORY.md +12 -0
- package/templates/agent-memory/dev-team-release/MEMORY.md +12 -0
- package/templates/agents/dev-team-architect.md +62 -0
- package/templates/agents/dev-team-deming.md +2 -1
- package/templates/agents/dev-team-docs.md +63 -0
- package/templates/agents/dev-team-release.md +65 -0
- package/templates/hooks/dev-team-post-change-review.js +63 -10
- package/templates/hooks/dev-team-pre-commit-gate.js +12 -14
- package/templates/hooks/dev-team-safety-guard.js +21 -11
- package/templates/hooks/dev-team-task-loop.js +17 -9
- package/templates/hooks/dev-team-tdd-enforce.js +42 -23
- package/templates/skills/dev-team-audit/SKILL.md +85 -0
- package/templates/skills/dev-team-review/SKILL.md +68 -0
- package/lib/files.js +0 -160
- package/lib/init.js +0 -206
- package/lib/prompts.js +0 -123
package/dist/init.js
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.run = run;
|
|
40
|
+
const path_1 = __importDefault(require("path"));
|
|
41
|
+
const files_1 = require("./files");
|
|
42
|
+
const prompts = __importStar(require("./prompts"));
|
|
43
|
+
const scan_1 = require("./scan");
|
|
44
|
+
const ALL_AGENTS = [
|
|
45
|
+
{ label: "Voss", file: "dev-team-voss.md", description: "Backend Engineer" },
|
|
46
|
+
{
|
|
47
|
+
label: "Mori",
|
|
48
|
+
file: "dev-team-mori.md",
|
|
49
|
+
description: "Frontend/UI Engineer",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
label: "Szabo",
|
|
53
|
+
file: "dev-team-szabo.md",
|
|
54
|
+
description: "Security Auditor",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
label: "Knuth",
|
|
58
|
+
file: "dev-team-knuth.md",
|
|
59
|
+
description: "Quality Auditor",
|
|
60
|
+
},
|
|
61
|
+
{ label: "Beck", file: "dev-team-beck.md", description: "Test Implementer" },
|
|
62
|
+
{
|
|
63
|
+
label: "Deming",
|
|
64
|
+
file: "dev-team-deming.md",
|
|
65
|
+
description: "Tooling & DX Optimizer",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: "Docs",
|
|
69
|
+
file: "dev-team-docs.md",
|
|
70
|
+
description: "Documentation Engineer",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
label: "Architect",
|
|
74
|
+
file: "dev-team-architect.md",
|
|
75
|
+
description: "Architect",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
label: "Release",
|
|
79
|
+
file: "dev-team-release.md",
|
|
80
|
+
description: "Release Manager",
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
const QUALITY_HOOKS = [
|
|
84
|
+
{
|
|
85
|
+
label: "TDD enforcement",
|
|
86
|
+
file: "dev-team-tdd-enforce.js",
|
|
87
|
+
description: "Block implementation changes without tests",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: "Safety guard",
|
|
91
|
+
file: "dev-team-safety-guard.js",
|
|
92
|
+
description: "Block dangerous commands (rm -rf, force push)",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: "Post-change review",
|
|
96
|
+
file: "dev-team-post-change-review.js",
|
|
97
|
+
description: "Flag which agents should review after edits",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: "Pre-commit gate",
|
|
101
|
+
file: "dev-team-pre-commit-gate.js",
|
|
102
|
+
description: "Remind about reviews before committing",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: "Task loop",
|
|
106
|
+
file: "dev-team-task-loop.js",
|
|
107
|
+
description: "Iterative task loop with adversarial review gates",
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
/**
|
|
111
|
+
* Main init flow.
|
|
112
|
+
*/
|
|
113
|
+
async function run(targetDir, flags = []) {
|
|
114
|
+
const isAll = flags.includes("--all");
|
|
115
|
+
console.log("\ndev-team — Adversarial AI agent team\n");
|
|
116
|
+
// Step 1: Detect existing state
|
|
117
|
+
const claudeDir = path_1.default.join(targetDir, ".claude");
|
|
118
|
+
const agentsDir = path_1.default.join(claudeDir, "agents");
|
|
119
|
+
const hooksDir = path_1.default.join(claudeDir, "hooks");
|
|
120
|
+
const skillsDir = path_1.default.join(claudeDir, "skills");
|
|
121
|
+
const memoryDir = path_1.default.join(claudeDir, "agent-memory");
|
|
122
|
+
const settingsPath = path_1.default.join(claudeDir, "settings.json");
|
|
123
|
+
const claudeMdPath = path_1.default.join(targetDir, "CLAUDE.md");
|
|
124
|
+
const prefsPath = path_1.default.join(claudeDir, "dev-team.json");
|
|
125
|
+
console.log("Detected:");
|
|
126
|
+
console.log(` .claude/ directory: ${(0, files_1.dirExists)(claudeDir) ? "exists" : "will be created"}`);
|
|
127
|
+
console.log(` CLAUDE.md: ${(0, files_1.fileExists)(claudeMdPath) ? "exists (will merge)" : "will be created"}`);
|
|
128
|
+
console.log("");
|
|
129
|
+
// Step 2: Agent selection
|
|
130
|
+
let selectedAgents;
|
|
131
|
+
if (isAll) {
|
|
132
|
+
selectedAgents = ALL_AGENTS.map((a) => a.label);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
selectedAgents = await prompts.checkbox("Which agents would you like to install?", ALL_AGENTS.map((a) => ({
|
|
136
|
+
label: a.label,
|
|
137
|
+
description: `${a.description}`,
|
|
138
|
+
defaultSelected: true,
|
|
139
|
+
})));
|
|
140
|
+
}
|
|
141
|
+
// Step 3: Hook selection
|
|
142
|
+
let selectedHooks;
|
|
143
|
+
if (isAll) {
|
|
144
|
+
selectedHooks = QUALITY_HOOKS.map((h) => h.label);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
selectedHooks = await prompts.checkbox("Which quality hooks do you want to enforce?", QUALITY_HOOKS.map((h) => ({
|
|
148
|
+
label: h.label,
|
|
149
|
+
description: h.description,
|
|
150
|
+
defaultSelected: true,
|
|
151
|
+
})));
|
|
152
|
+
}
|
|
153
|
+
// Step 4: Issue tracker preference
|
|
154
|
+
let issueTracker;
|
|
155
|
+
if (isAll) {
|
|
156
|
+
issueTracker = "GitHub Issues";
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
issueTracker = await prompts.select("Which issue tracker do you use?", [
|
|
160
|
+
{ label: "GitHub Issues", description: "Track work with GitHub Issues" },
|
|
161
|
+
{ label: "Jira", description: "Atlassian Jira" },
|
|
162
|
+
{ label: "Linear", description: "Linear issue tracker" },
|
|
163
|
+
{ label: "Other", description: "Another issue tracker" },
|
|
164
|
+
{ label: "None", description: "No issue tracking enforcement" },
|
|
165
|
+
]);
|
|
166
|
+
}
|
|
167
|
+
// Step 5: Branch naming convention
|
|
168
|
+
let branchConvention;
|
|
169
|
+
if (isAll) {
|
|
170
|
+
branchConvention = "feat/123-description";
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
branchConvention = await prompts.select("Branch naming convention?", [
|
|
174
|
+
{
|
|
175
|
+
label: "feat/123-description",
|
|
176
|
+
description: "Type/issue-number-description (e.g., feat/42-add-auth)",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
label: "type/description",
|
|
180
|
+
description: "Type/description without issue number (e.g., feat/add-auth)",
|
|
181
|
+
},
|
|
182
|
+
{ label: "None", description: "No branch naming enforcement" },
|
|
183
|
+
]);
|
|
184
|
+
}
|
|
185
|
+
// Step 6: Copy agents (renumbered after adding workflow prompts)
|
|
186
|
+
const templates = (0, files_1.templateDir)();
|
|
187
|
+
let agentCount = 0;
|
|
188
|
+
for (const agent of ALL_AGENTS) {
|
|
189
|
+
if (!selectedAgents.includes(agent.label))
|
|
190
|
+
continue;
|
|
191
|
+
const src = path_1.default.join(templates, "agents", agent.file);
|
|
192
|
+
const dest = path_1.default.join(agentsDir, agent.file);
|
|
193
|
+
if ((0, files_1.fileExists)(dest) && !isAll) {
|
|
194
|
+
const overwrite = await prompts.confirm(` ${agent.file} already exists. Overwrite?`, false);
|
|
195
|
+
if (!overwrite)
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
(0, files_1.copyFile)(src, dest);
|
|
199
|
+
agentCount++;
|
|
200
|
+
}
|
|
201
|
+
// Step 7: Create agent memory directories
|
|
202
|
+
for (const agent of ALL_AGENTS) {
|
|
203
|
+
if (!selectedAgents.includes(agent.label))
|
|
204
|
+
continue;
|
|
205
|
+
const agentName = agent.file.replace(".md", "");
|
|
206
|
+
const memorySrc = path_1.default.join(templates, "agent-memory", agentName, "MEMORY.md");
|
|
207
|
+
const memoryDest = path_1.default.join(memoryDir, agentName, "MEMORY.md");
|
|
208
|
+
if (!(0, files_1.fileExists)(memoryDest)) {
|
|
209
|
+
(0, files_1.copyFile)(memorySrc, memoryDest);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Step 8: Create shared team learnings
|
|
213
|
+
const learningsSrc = path_1.default.join(templates, "dev-team-learnings.md");
|
|
214
|
+
const learningsDest = path_1.default.join(claudeDir, "dev-team-learnings.md");
|
|
215
|
+
if (!(0, files_1.fileExists)(learningsDest)) {
|
|
216
|
+
(0, files_1.copyFile)(learningsSrc, learningsDest);
|
|
217
|
+
}
|
|
218
|
+
// Step 7: Copy hooks
|
|
219
|
+
let hookCount = 0;
|
|
220
|
+
for (const hook of QUALITY_HOOKS) {
|
|
221
|
+
if (!selectedHooks.includes(hook.label))
|
|
222
|
+
continue;
|
|
223
|
+
const src = path_1.default.join(templates, "hooks", hook.file);
|
|
224
|
+
const dest = path_1.default.join(hooksDir, hook.file);
|
|
225
|
+
if ((0, files_1.fileExists)(dest) && !isAll) {
|
|
226
|
+
const overwrite = await prompts.confirm(` ${hook.file} already exists. Overwrite?`, false);
|
|
227
|
+
if (!overwrite)
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
(0, files_1.copyFile)(src, dest);
|
|
231
|
+
hookCount++;
|
|
232
|
+
}
|
|
233
|
+
// Step 8: Merge hook settings
|
|
234
|
+
const settingsContent = (0, files_1.readFile)(path_1.default.join(templates, "settings.json"));
|
|
235
|
+
if (!settingsContent) {
|
|
236
|
+
throw new Error("Missing templates/settings.json");
|
|
237
|
+
}
|
|
238
|
+
const settingsTemplate = JSON.parse(settingsContent);
|
|
239
|
+
// Filter settings to only include selected hooks
|
|
240
|
+
const filteredSettings = { hooks: {} };
|
|
241
|
+
const selectedHookFiles = QUALITY_HOOKS.filter((h) => selectedHooks.includes(h.label)).map((h) => h.file);
|
|
242
|
+
for (const [event, entries] of Object.entries(settingsTemplate.hooks)) {
|
|
243
|
+
const filteredEntries = entries
|
|
244
|
+
.map((entry) => ({
|
|
245
|
+
...entry,
|
|
246
|
+
hooks: (entry.hooks || []).filter((h) => selectedHookFiles.some((f) => h.command && h.command.includes(f))),
|
|
247
|
+
}))
|
|
248
|
+
.filter((entry) => entry.hooks.length > 0);
|
|
249
|
+
if (filteredEntries.length > 0) {
|
|
250
|
+
filteredSettings.hooks[event] = filteredEntries;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
(0, files_1.mergeSettings)(settingsPath, filteredSettings);
|
|
254
|
+
// Step 9: Copy skills
|
|
255
|
+
const skillsSrcDir = path_1.default.join(templates, "skills");
|
|
256
|
+
const skillDirs = ["dev-team-challenge", "dev-team-task", "dev-team-review", "dev-team-audit"];
|
|
257
|
+
for (const skillDir of skillDirs) {
|
|
258
|
+
const src = path_1.default.join(skillsSrcDir, skillDir, "SKILL.md");
|
|
259
|
+
const dest = path_1.default.join(skillsDir, skillDir, "SKILL.md");
|
|
260
|
+
if (!(0, files_1.fileExists)(dest) || isAll) {
|
|
261
|
+
(0, files_1.copyFile)(src, dest);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Step 10: Merge CLAUDE.md
|
|
265
|
+
const claudeMdTemplate = (0, files_1.readFile)(path_1.default.join(templates, "CLAUDE.md"));
|
|
266
|
+
if (!claudeMdTemplate) {
|
|
267
|
+
throw new Error("Missing templates/CLAUDE.md");
|
|
268
|
+
}
|
|
269
|
+
const claudeResult = (0, files_1.mergeClaudeMd)(claudeMdPath, claudeMdTemplate);
|
|
270
|
+
// Save preferences
|
|
271
|
+
const prefs = {
|
|
272
|
+
version: "0.2.0",
|
|
273
|
+
agents: selectedAgents,
|
|
274
|
+
hooks: selectedHooks,
|
|
275
|
+
issueTracker,
|
|
276
|
+
branchConvention,
|
|
277
|
+
};
|
|
278
|
+
(0, files_1.writeFile)(prefsPath, JSON.stringify(prefs, null, 2) + "\n");
|
|
279
|
+
// Step 11: Print summary
|
|
280
|
+
console.log("\nDone! Installed:\n");
|
|
281
|
+
console.log(` Agents: ${selectedAgents.join(", ")} (${agentCount} files)`);
|
|
282
|
+
console.log(` Hooks: ${selectedHooks.join(", ")} (${hookCount} files)`);
|
|
283
|
+
console.log(" Skills: challenge, task, review, audit");
|
|
284
|
+
console.log(` Memory: ${selectedAgents.length} agent memories + shared learnings`);
|
|
285
|
+
console.log(` CLAUDE.md: ${claudeResult}`);
|
|
286
|
+
console.log(` Settings: ${settingsPath}`);
|
|
287
|
+
console.log(` Workflow: ${issueTracker}${branchConvention !== "None" ? `, branches: ${branchConvention}` : ""}`);
|
|
288
|
+
console.log("");
|
|
289
|
+
// Step 12: Optional Deming tooling scan
|
|
290
|
+
let runScan = isAll;
|
|
291
|
+
if (!isAll) {
|
|
292
|
+
runScan = await prompts.confirm("Run Deming tooling scan to check for linters, SAST, and CI gaps?", true);
|
|
293
|
+
}
|
|
294
|
+
if (runScan) {
|
|
295
|
+
const findings = (0, scan_1.scanProject)(targetDir);
|
|
296
|
+
console.log((0, scan_1.formatScanReport)(findings));
|
|
297
|
+
console.log("");
|
|
298
|
+
}
|
|
299
|
+
console.log("Next steps:");
|
|
300
|
+
console.log(" 1. Review installed agents in .claude/agents/");
|
|
301
|
+
console.log(" 2. Customize agent personas and focus areas to fit your project");
|
|
302
|
+
if (!runScan) {
|
|
303
|
+
console.log(" 3. Run @dev-team-deming to scan for additional tooling recommendations");
|
|
304
|
+
}
|
|
305
|
+
console.log("");
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface CheckboxItem {
|
|
2
|
+
label: string;
|
|
3
|
+
description: string;
|
|
4
|
+
defaultSelected: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface SelectOption {
|
|
7
|
+
label: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Asks a yes/no question. Returns true for yes.
|
|
12
|
+
*/
|
|
13
|
+
export declare function confirm(question: string, defaultYes?: boolean): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Asks a checkbox-style question. Returns array of selected labels.
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkbox(question: string, items: CheckboxItem[]): Promise<string[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Asks a single-choice question. Returns the selected label.
|
|
20
|
+
*/
|
|
21
|
+
export declare function select(question: string, options: SelectOption[]): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Asks for free-text input.
|
|
24
|
+
*/
|
|
25
|
+
export declare function input(question: string, defaultValue?: string): Promise<string>;
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
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.confirm = confirm;
|
|
7
|
+
exports.checkbox = checkbox;
|
|
8
|
+
exports.select = select;
|
|
9
|
+
exports.input = input;
|
|
10
|
+
const readline_1 = __importDefault(require("readline"));
|
|
11
|
+
function createInterface() {
|
|
12
|
+
return readline_1.default.createInterface({
|
|
13
|
+
input: process.stdin,
|
|
14
|
+
output: process.stdout,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Asks a yes/no question. Returns true for yes.
|
|
19
|
+
*/
|
|
20
|
+
async function confirm(question, defaultYes = true) {
|
|
21
|
+
const rl = createInterface();
|
|
22
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
rl.question(`${question} ${hint} `, (answer) => {
|
|
25
|
+
rl.close();
|
|
26
|
+
const trimmed = answer.trim().toLowerCase();
|
|
27
|
+
if (trimmed === "") {
|
|
28
|
+
resolve(defaultYes);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Asks a checkbox-style question. Returns array of selected labels.
|
|
38
|
+
*/
|
|
39
|
+
async function checkbox(question, items) {
|
|
40
|
+
const rl = createInterface();
|
|
41
|
+
console.log(`\n${question}`);
|
|
42
|
+
items.forEach((item, i) => {
|
|
43
|
+
const checked = item.defaultSelected ? "x" : " ";
|
|
44
|
+
console.log(` ${i + 1}. [${checked}] ${item.label} — ${item.description}`);
|
|
45
|
+
});
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
rl.question("\nEnter numbers to toggle (e.g., 1 3 4), or press Enter for defaults: ", (answer) => {
|
|
48
|
+
rl.close();
|
|
49
|
+
const trimmed = answer.trim();
|
|
50
|
+
if (trimmed === "") {
|
|
51
|
+
resolve(items.filter((item) => item.defaultSelected).map((item) => item.label));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const toggled = new Set(trimmed
|
|
55
|
+
.split(/[\s,]+/)
|
|
56
|
+
.map(Number)
|
|
57
|
+
.filter((n) => n >= 1 && n <= items.length));
|
|
58
|
+
const selected = items
|
|
59
|
+
.filter((_item, i) => {
|
|
60
|
+
const isDefault = items[i].defaultSelected;
|
|
61
|
+
const wasToggled = toggled.has(i + 1);
|
|
62
|
+
return isDefault ? !wasToggled : wasToggled;
|
|
63
|
+
})
|
|
64
|
+
.map((item) => item.label);
|
|
65
|
+
resolve(selected);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Asks a single-choice question. Returns the selected label.
|
|
71
|
+
*/
|
|
72
|
+
async function select(question, options) {
|
|
73
|
+
const rl = createInterface();
|
|
74
|
+
console.log(`\n${question}`);
|
|
75
|
+
options.forEach((opt, i) => {
|
|
76
|
+
console.log(` ${i + 1}. ${opt.label} — ${opt.description}`);
|
|
77
|
+
});
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
rl.question("\nEnter number (default: 1): ", (answer) => {
|
|
80
|
+
rl.close();
|
|
81
|
+
const trimmed = answer.trim();
|
|
82
|
+
if (trimmed === "") {
|
|
83
|
+
resolve(options[0].label);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const idx = Number(trimmed) - 1;
|
|
87
|
+
if (idx >= 0 && idx < options.length) {
|
|
88
|
+
resolve(options[idx].label);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
resolve(options[0].label);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Asks for free-text input.
|
|
98
|
+
*/
|
|
99
|
+
async function input(question, defaultValue = "") {
|
|
100
|
+
const rl = createInterface();
|
|
101
|
+
const hint = defaultValue ? ` [${defaultValue}]` : "";
|
|
102
|
+
return new Promise((resolve) => {
|
|
103
|
+
rl.question(`${question}${hint}: `, (answer) => {
|
|
104
|
+
rl.close();
|
|
105
|
+
resolve(answer.trim() || defaultValue);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
package/dist/scan.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ScanFinding {
|
|
2
|
+
category: "linter" | "formatter" | "sast" | "ci" | "dependency";
|
|
3
|
+
status: "found" | "missing" | "outdated";
|
|
4
|
+
tool: string;
|
|
5
|
+
recommendation: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Scans a project directory for existing tooling and identifies gaps.
|
|
9
|
+
* Returns a list of findings with actionable recommendations.
|
|
10
|
+
*/
|
|
11
|
+
export declare function scanProject(targetDir: string): ScanFinding[];
|
|
12
|
+
/**
|
|
13
|
+
* Formats scan findings as a human-readable report.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatScanReport(findings: ScanFinding[]): string;
|
package/dist/scan.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
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.scanProject = scanProject;
|
|
7
|
+
exports.formatScanReport = formatScanReport;
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const files_1 = require("./files");
|
|
10
|
+
/**
|
|
11
|
+
* Scans a project directory for existing tooling and identifies gaps.
|
|
12
|
+
* Returns a list of findings with actionable recommendations.
|
|
13
|
+
*/
|
|
14
|
+
function scanProject(targetDir) {
|
|
15
|
+
const findings = [];
|
|
16
|
+
// Linters
|
|
17
|
+
const linters = [
|
|
18
|
+
{ file: ".eslintrc.js", tool: "ESLint" },
|
|
19
|
+
{ file: ".eslintrc.json", tool: "ESLint" },
|
|
20
|
+
{ file: ".eslintrc.yml", tool: "ESLint" },
|
|
21
|
+
{ file: "eslint.config.js", tool: "ESLint (flat config)" },
|
|
22
|
+
{ file: "eslint.config.mjs", tool: "ESLint (flat config)" },
|
|
23
|
+
{ file: "biome.json", tool: "Biome" },
|
|
24
|
+
{ file: ".pylintrc", tool: "pylint" },
|
|
25
|
+
{ file: "setup.cfg", tool: "flake8/pylint" },
|
|
26
|
+
{ file: "pyproject.toml", tool: "ruff/pylint" },
|
|
27
|
+
{ file: ".rubocop.yml", tool: "RuboCop" },
|
|
28
|
+
{ file: ".golangci.yml", tool: "golangci-lint" },
|
|
29
|
+
];
|
|
30
|
+
const foundLinter = linters.find((l) => (0, files_1.fileExists)(path_1.default.join(targetDir, l.file)));
|
|
31
|
+
if (foundLinter) {
|
|
32
|
+
findings.push({
|
|
33
|
+
category: "linter",
|
|
34
|
+
status: "found",
|
|
35
|
+
tool: foundLinter.tool,
|
|
36
|
+
recommendation: `${foundLinter.tool} detected. Consider adding a PostToolUse hook to run it on file save for immediate feedback.`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Check package.json for lint script
|
|
41
|
+
const pkg = (0, files_1.readFile)(path_1.default.join(targetDir, "package.json"));
|
|
42
|
+
if (pkg && pkg.includes('"lint"')) {
|
|
43
|
+
findings.push({
|
|
44
|
+
category: "linter",
|
|
45
|
+
status: "found",
|
|
46
|
+
tool: "npm lint script",
|
|
47
|
+
recommendation: "Lint script found in package.json. Consider adding a PostToolUse hook to run it automatically.",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
findings.push({
|
|
52
|
+
category: "linter",
|
|
53
|
+
status: "missing",
|
|
54
|
+
tool: "none",
|
|
55
|
+
recommendation: "No linter detected. Add ESLint, Biome, or a language-appropriate linter to catch issues early.",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Formatters
|
|
60
|
+
const formatters = [
|
|
61
|
+
{ file: ".prettierrc", tool: "Prettier" },
|
|
62
|
+
{ file: ".prettierrc.js", tool: "Prettier" },
|
|
63
|
+
{ file: ".prettierrc.json", tool: "Prettier" },
|
|
64
|
+
{ file: "prettier.config.js", tool: "Prettier" },
|
|
65
|
+
{ file: ".editorconfig", tool: "EditorConfig" },
|
|
66
|
+
{ file: "biome.json", tool: "Biome" },
|
|
67
|
+
{ file: "rustfmt.toml", tool: "rustfmt" },
|
|
68
|
+
{ file: ".clang-format", tool: "clang-format" },
|
|
69
|
+
];
|
|
70
|
+
const foundFormatter = formatters.find((f) => (0, files_1.fileExists)(path_1.default.join(targetDir, f.file)));
|
|
71
|
+
if (foundFormatter) {
|
|
72
|
+
findings.push({
|
|
73
|
+
category: "formatter",
|
|
74
|
+
status: "found",
|
|
75
|
+
tool: foundFormatter.tool,
|
|
76
|
+
recommendation: `${foundFormatter.tool} detected. Consider a pre-commit hook or PostToolUse hook to auto-format on save.`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
findings.push({
|
|
81
|
+
category: "formatter",
|
|
82
|
+
status: "missing",
|
|
83
|
+
tool: "none",
|
|
84
|
+
recommendation: "No formatter detected. Add Prettier, Biome, or a language-appropriate formatter to enforce consistent style.",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// SAST / Security scanning
|
|
88
|
+
const sastConfigs = [
|
|
89
|
+
{ file: ".semgrep.yml", tool: "Semgrep" },
|
|
90
|
+
{ file: ".semgrep", tool: "Semgrep" },
|
|
91
|
+
{ file: ".snyk", tool: "Snyk" },
|
|
92
|
+
{ file: ".trivyignore", tool: "Trivy" },
|
|
93
|
+
{ file: "sonar-project.properties", tool: "SonarQube" },
|
|
94
|
+
{ file: ".bandit", tool: "Bandit" },
|
|
95
|
+
{ file: ".safety-policy.yml", tool: "Safety" },
|
|
96
|
+
];
|
|
97
|
+
const foundSast = sastConfigs.find((s) => (0, files_1.fileExists)(path_1.default.join(targetDir, s.file)));
|
|
98
|
+
if (foundSast) {
|
|
99
|
+
findings.push({
|
|
100
|
+
category: "sast",
|
|
101
|
+
status: "found",
|
|
102
|
+
tool: foundSast.tool,
|
|
103
|
+
recommendation: `${foundSast.tool} detected. Ensure it runs in CI and consider adding @dev-team-szabo for complementary AI-driven security review.`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
findings.push({
|
|
108
|
+
category: "sast",
|
|
109
|
+
status: "missing",
|
|
110
|
+
tool: "none",
|
|
111
|
+
recommendation: "No SAST tool detected. Consider adding Semgrep, Snyk, or language-appropriate static analysis. @dev-team-szabo provides AI review but does not replace automated scanning.",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// CI/CD
|
|
115
|
+
const ciConfigs = [
|
|
116
|
+
{ path: ".github/workflows", tool: "GitHub Actions" },
|
|
117
|
+
{ path: ".gitlab-ci.yml", tool: "GitLab CI" },
|
|
118
|
+
{ path: ".circleci", tool: "CircleCI" },
|
|
119
|
+
{ path: "Jenkinsfile", tool: "Jenkins" },
|
|
120
|
+
{ path: ".travis.yml", tool: "Travis CI" },
|
|
121
|
+
{ path: "azure-pipelines.yml", tool: "Azure Pipelines" },
|
|
122
|
+
{ path: "bitbucket-pipelines.yml", tool: "Bitbucket Pipelines" },
|
|
123
|
+
];
|
|
124
|
+
const foundCi = ciConfigs.find((c) => {
|
|
125
|
+
const fullPath = path_1.default.join(targetDir, c.path);
|
|
126
|
+
return (0, files_1.fileExists)(fullPath) || (0, files_1.dirExists)(fullPath);
|
|
127
|
+
});
|
|
128
|
+
if (foundCi) {
|
|
129
|
+
findings.push({
|
|
130
|
+
category: "ci",
|
|
131
|
+
status: "found",
|
|
132
|
+
tool: foundCi.tool,
|
|
133
|
+
recommendation: `${foundCi.tool} detected. Verify it runs lint, format check, tests, and security scans. Consider parallel steps for independent jobs.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
findings.push({
|
|
138
|
+
category: "ci",
|
|
139
|
+
status: "missing",
|
|
140
|
+
tool: "none",
|
|
141
|
+
recommendation: "No CI/CD pipeline detected. Add GitHub Actions, GitLab CI, or equivalent. At minimum: lint, format check, and test steps.",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Dependency audit
|
|
145
|
+
const lockFiles = [
|
|
146
|
+
{ file: "package-lock.json", tool: "npm audit" },
|
|
147
|
+
{ file: "yarn.lock", tool: "yarn audit" },
|
|
148
|
+
{ file: "pnpm-lock.yaml", tool: "pnpm audit" },
|
|
149
|
+
{ file: "Gemfile.lock", tool: "bundle audit" },
|
|
150
|
+
{ file: "poetry.lock", tool: "pip-audit / safety" },
|
|
151
|
+
{ file: "Cargo.lock", tool: "cargo audit" },
|
|
152
|
+
{ file: "go.sum", tool: "govulncheck" },
|
|
153
|
+
];
|
|
154
|
+
const foundLock = lockFiles.find((l) => (0, files_1.fileExists)(path_1.default.join(targetDir, l.file)));
|
|
155
|
+
if (foundLock) {
|
|
156
|
+
findings.push({
|
|
157
|
+
category: "dependency",
|
|
158
|
+
status: "found",
|
|
159
|
+
tool: foundLock.tool,
|
|
160
|
+
recommendation: `Lock file detected (${foundLock.file}). Run \`${foundLock.tool}\` regularly and add it to CI.`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return findings;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Formats scan findings as a human-readable report.
|
|
167
|
+
*/
|
|
168
|
+
function formatScanReport(findings) {
|
|
169
|
+
const lines = [];
|
|
170
|
+
lines.push("Deming scan — Project tooling assessment\n");
|
|
171
|
+
const missing = findings.filter((f) => f.status === "missing");
|
|
172
|
+
const found = findings.filter((f) => f.status === "found");
|
|
173
|
+
if (missing.length === 0) {
|
|
174
|
+
lines.push(" All checked tooling categories are covered.\n");
|
|
175
|
+
}
|
|
176
|
+
for (const f of found) {
|
|
177
|
+
lines.push(` [OK] ${f.category}: ${f.tool}`);
|
|
178
|
+
}
|
|
179
|
+
for (const f of missing) {
|
|
180
|
+
lines.push(` [MISSING] ${f.category}: ${f.recommendation}`);
|
|
181
|
+
}
|
|
182
|
+
if (missing.length > 0) {
|
|
183
|
+
lines.push("\n Tip: Run @dev-team-deming for deeper analysis and automated setup.");
|
|
184
|
+
}
|
|
185
|
+
return lines.join("\n");
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=scan.js.map
|