@wundr.io/cli 1.0.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 +551 -0
- package/bin/wundr.js +39 -0
- package/dist/ai/ai-service.d.ts +152 -0
- package/dist/ai/ai-service.d.ts.map +1 -0
- package/dist/ai/ai-service.js +430 -0
- package/dist/ai/ai-service.js.map +1 -0
- package/dist/ai/claude-client.d.ts +130 -0
- package/dist/ai/claude-client.d.ts.map +1 -0
- package/dist/ai/claude-client.js +339 -0
- package/dist/ai/claude-client.js.map +1 -0
- package/dist/ai/conversation-manager.d.ts +164 -0
- package/dist/ai/conversation-manager.d.ts.map +1 -0
- package/dist/ai/conversation-manager.js +612 -0
- package/dist/ai/conversation-manager.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/cli.d.ts +36 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ai.d.ts +89 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +735 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/analyze-optimized.d.ts +14 -0
- package/dist/commands/analyze-optimized.d.ts.map +1 -0
- package/dist/commands/analyze-optimized.js +437 -0
- package/dist/commands/analyze-optimized.js.map +1 -0
- package/dist/commands/analyze.d.ts +65 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +435 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/batch.d.ts +71 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +738 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/chat.d.ts +71 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +674 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/claude-init.d.ts +28 -0
- package/dist/commands/claude-init.d.ts.map +1 -0
- package/dist/commands/claude-init.js +587 -0
- package/dist/commands/claude-init.js.map +1 -0
- package/dist/commands/claude-setup.d.ts +32 -0
- package/dist/commands/claude-setup.d.ts.map +1 -0
- package/dist/commands/claude-setup.js +570 -0
- package/dist/commands/claude-setup.js.map +1 -0
- package/dist/commands/computer-setup-commands.d.ts +39 -0
- package/dist/commands/computer-setup-commands.d.ts.map +1 -0
- package/dist/commands/computer-setup-commands.js +563 -0
- package/dist/commands/computer-setup-commands.js.map +1 -0
- package/dist/commands/computer-setup.d.ts +7 -0
- package/dist/commands/computer-setup.d.ts.map +1 -0
- package/dist/commands/computer-setup.js +481 -0
- package/dist/commands/computer-setup.js.map +1 -0
- package/dist/commands/create-command.d.ts +7 -0
- package/dist/commands/create-command.d.ts.map +1 -0
- package/dist/commands/create-command.js +158 -0
- package/dist/commands/create-command.js.map +1 -0
- package/dist/commands/create.d.ts +74 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +556 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dashboard.d.ts +91 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +537 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/govern.d.ts +70 -0
- package/dist/commands/govern.d.ts.map +1 -0
- package/dist/commands/govern.js +480 -0
- package/dist/commands/govern.js.map +1 -0
- package/dist/commands/init.d.ts +55 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +584 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/performance-optimizer.d.ts +30 -0
- package/dist/commands/performance-optimizer.d.ts.map +1 -0
- package/dist/commands/performance-optimizer.js +649 -0
- package/dist/commands/performance-optimizer.js.map +1 -0
- package/dist/commands/plugins.d.ts +87 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +685 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/setup.d.ts +29 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +399 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/test-init.d.ts +9 -0
- package/dist/commands/test-init.d.ts.map +1 -0
- package/dist/commands/test-init.js +222 -0
- package/dist/commands/test-init.js.map +1 -0
- package/dist/commands/test.d.ts +25 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +217 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/watch.d.ts +76 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +610 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/context/context-manager.d.ts +155 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +383 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +6 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/session-manager.d.ts +207 -0
- package/dist/context/session-manager.d.ts.map +1 -0
- package/dist/context/session-manager.js +682 -0
- package/dist/context/session-manager.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive/interactive-mode.d.ts +76 -0
- package/dist/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/interactive/interactive-mode.js +730 -0
- package/dist/interactive/interactive-mode.js.map +1 -0
- package/dist/nlp/command-mapper.d.ts +174 -0
- package/dist/nlp/command-mapper.d.ts.map +1 -0
- package/dist/nlp/command-mapper.js +623 -0
- package/dist/nlp/command-mapper.js.map +1 -0
- package/dist/nlp/command-parser.d.ts +106 -0
- package/dist/nlp/command-parser.d.ts.map +1 -0
- package/dist/nlp/command-parser.js +416 -0
- package/dist/nlp/command-parser.js.map +1 -0
- package/dist/nlp/index.d.ts +5 -0
- package/dist/nlp/index.d.ts.map +1 -0
- package/dist/nlp/index.js +8 -0
- package/dist/nlp/index.js.map +1 -0
- package/dist/nlp/intent-classifier.d.ts +59 -0
- package/dist/nlp/intent-classifier.d.ts.map +1 -0
- package/dist/nlp/intent-classifier.js +384 -0
- package/dist/nlp/intent-classifier.js.map +1 -0
- package/dist/nlp/intent-parser.d.ts +152 -0
- package/dist/nlp/intent-parser.d.ts.map +1 -0
- package/dist/nlp/intent-parser.js +739 -0
- package/dist/nlp/intent-parser.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +120 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +595 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/types/index.d.ts +224 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config-manager.d.ts +73 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +339 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/error-handler.d.ts +46 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +169 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +94 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +119 -0
- package/src/ai/ai-service.ts +595 -0
- package/src/ai/claude-client.ts +490 -0
- package/src/ai/conversation-manager.ts +907 -0
- package/src/ai/index.ts +8 -0
- package/src/cli.ts +202 -0
- package/src/commands/ai.ts +995 -0
- package/src/commands/analyze-optimized.ts +641 -0
- package/src/commands/analyze.ts +576 -0
- package/src/commands/batch.ts +935 -0
- package/src/commands/chat.ts +876 -0
- package/src/commands/claude-init.ts +715 -0
- package/src/commands/claude-setup.ts +697 -0
- package/src/commands/computer-setup-commands.ts +709 -0
- package/src/commands/computer-setup.ts +565 -0
- package/src/commands/create-command.ts +175 -0
- package/src/commands/create.ts +727 -0
- package/src/commands/dashboard.ts +691 -0
- package/src/commands/govern.ts +635 -0
- package/src/commands/init.ts +677 -0
- package/src/commands/performance-optimizer.ts +864 -0
- package/src/commands/plugins.ts +848 -0
- package/src/commands/setup.ts +508 -0
- package/src/commands/test-init.ts +242 -0
- package/src/commands/test.ts +264 -0
- package/src/commands/watch.ts +755 -0
- package/src/context/context-manager.ts +546 -0
- package/src/context/index.ts +9 -0
- package/src/context/session-manager.ts +1019 -0
- package/src/index.ts +64 -0
- package/src/interactive/interactive-mode.ts +830 -0
- package/src/nlp/command-mapper.ts +885 -0
- package/src/nlp/command-parser.ts +564 -0
- package/src/nlp/index.ts +4 -0
- package/src/nlp/intent-classifier.ts +458 -0
- package/src/nlp/intent-parser.ts +1101 -0
- package/src/plugins/plugin-manager.ts +744 -0
- package/src/types/index.ts +252 -0
- package/src/types/modules.d.ts +56 -0
- package/src/utils/config-manager.ts +391 -0
- package/src/utils/error-handler.ts +192 -0
- package/src/utils/logger.ts +104 -0
- package/templates/batch/ci-cd.yaml +62 -0
- package/templates/component/{{fileName}}.test.tsx +17 -0
- package/templates/component/{{fileName}}.tsx +21 -0
- package/templates/service/{{fileName}}.ts +98 -0
- package/templates/wundr-test.config.js +0 -0
- package/test-suites/api/health.spec.ts +134 -0
- package/test-suites/helpers/test-config.ts +84 -0
- package/test-suites/ui/accessibility.spec.ts +102 -0
- package/test-suites/ui/smoke.spec.ts +92 -0
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { ConfigManager } from '../utils/config-manager';
|
|
6
|
+
import { PluginManager } from '../plugins/plugin-manager';
|
|
7
|
+
import { logger } from '../utils/logger';
|
|
8
|
+
import { errorHandler } from '../utils/error-handler';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Governance commands for compliance and quality control
|
|
12
|
+
*/
|
|
13
|
+
export class GovernCommands {
|
|
14
|
+
constructor(
|
|
15
|
+
private program: Command,
|
|
16
|
+
private configManager: ConfigManager,
|
|
17
|
+
private pluginManager: PluginManager
|
|
18
|
+
) {
|
|
19
|
+
this.registerCommands();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private registerCommands(): void {
|
|
23
|
+
const governCmd = this.program
|
|
24
|
+
.command('govern')
|
|
25
|
+
.description('governance and compliance tools');
|
|
26
|
+
|
|
27
|
+
// Check compliance
|
|
28
|
+
governCmd
|
|
29
|
+
.command('check')
|
|
30
|
+
.description('run compliance checks')
|
|
31
|
+
.option('--rules <rules>', 'specific rules to check')
|
|
32
|
+
.option('--severity <level>', 'minimum severity level', 'warning')
|
|
33
|
+
.option('--fix', 'automatically fix violations where possible')
|
|
34
|
+
.option('--report', 'generate compliance report')
|
|
35
|
+
.action(async options => {
|
|
36
|
+
await this.checkCompliance(options);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Manage rules
|
|
40
|
+
governCmd.command('rules').description('manage governance rules');
|
|
41
|
+
|
|
42
|
+
governCmd
|
|
43
|
+
.command('rules list')
|
|
44
|
+
.description('list all available rules')
|
|
45
|
+
.option('--category <category>', 'filter by category')
|
|
46
|
+
.action(async options => {
|
|
47
|
+
await this.listRules(options);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
governCmd
|
|
51
|
+
.command('rules add <rule>')
|
|
52
|
+
.description('add a new rule')
|
|
53
|
+
.option('--severity <level>', 'rule severity', 'warning')
|
|
54
|
+
.option('--config <config>', 'rule configuration')
|
|
55
|
+
.action(async (rule, options) => {
|
|
56
|
+
await this.addRule(rule, options);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
governCmd
|
|
60
|
+
.command('rules remove <rule>')
|
|
61
|
+
.description('remove a rule')
|
|
62
|
+
.action(async rule => {
|
|
63
|
+
await this.removeRule(rule);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Policy management
|
|
67
|
+
governCmd.command('policy').description('manage governance policies');
|
|
68
|
+
|
|
69
|
+
governCmd
|
|
70
|
+
.command('policy create <name>')
|
|
71
|
+
.description('create a new policy')
|
|
72
|
+
.option('--template <template>', 'policy template')
|
|
73
|
+
.option('--rules <rules>', 'comma-separated rules')
|
|
74
|
+
.action(async (name, options) => {
|
|
75
|
+
await this.createPolicy(name, options);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
governCmd
|
|
79
|
+
.command('policy apply <policy>')
|
|
80
|
+
.description('apply a policy to project')
|
|
81
|
+
.option(
|
|
82
|
+
'--scope <scope>',
|
|
83
|
+
'application scope (project, workspace)',
|
|
84
|
+
'project'
|
|
85
|
+
)
|
|
86
|
+
.action(async (policy, options) => {
|
|
87
|
+
await this.applyPolicy(policy, options);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Quality gates
|
|
91
|
+
governCmd.command('gate').description('quality gate management');
|
|
92
|
+
|
|
93
|
+
governCmd
|
|
94
|
+
.command('gate check')
|
|
95
|
+
.description('run quality gate checks')
|
|
96
|
+
.option('--gate <name>', 'specific gate to check')
|
|
97
|
+
.option('--fail-on-error', 'fail if quality gate fails')
|
|
98
|
+
.action(async options => {
|
|
99
|
+
await this.checkQualityGate(options);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
governCmd
|
|
103
|
+
.command('gate create <name>')
|
|
104
|
+
.description('create a new quality gate')
|
|
105
|
+
.option('--conditions <conditions>', 'gate conditions')
|
|
106
|
+
.action(async (name, options) => {
|
|
107
|
+
await this.createQualityGate(name, options);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Audit
|
|
111
|
+
governCmd
|
|
112
|
+
.command('audit')
|
|
113
|
+
.description('run governance audit')
|
|
114
|
+
.option(
|
|
115
|
+
'--scope <scope>',
|
|
116
|
+
'audit scope (security, quality, compliance)',
|
|
117
|
+
'all'
|
|
118
|
+
)
|
|
119
|
+
.option('--export <path>', 'export audit results')
|
|
120
|
+
.action(async options => {
|
|
121
|
+
await this.runAudit(options);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Reports
|
|
125
|
+
governCmd
|
|
126
|
+
.command('report')
|
|
127
|
+
.description('generate governance reports')
|
|
128
|
+
.option(
|
|
129
|
+
'--type <type>',
|
|
130
|
+
'report type (compliance, quality, security)',
|
|
131
|
+
'compliance'
|
|
132
|
+
)
|
|
133
|
+
.option(
|
|
134
|
+
'--period <period>',
|
|
135
|
+
'report period (daily, weekly, monthly)',
|
|
136
|
+
'weekly'
|
|
137
|
+
)
|
|
138
|
+
.option('--output <path>', 'output file path')
|
|
139
|
+
.action(async options => {
|
|
140
|
+
await this.generateReport(options);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Check compliance against governance rules
|
|
146
|
+
*/
|
|
147
|
+
private async checkCompliance(options: any): Promise<void> {
|
|
148
|
+
try {
|
|
149
|
+
logger.info('Running compliance checks...');
|
|
150
|
+
|
|
151
|
+
const config = this.configManager.getConfig();
|
|
152
|
+
const rules = options.rules
|
|
153
|
+
? options.rules.split(',')
|
|
154
|
+
: config.governance.rules;
|
|
155
|
+
const violations: any[] = [];
|
|
156
|
+
|
|
157
|
+
for (const rule of rules) {
|
|
158
|
+
logger.debug(`Checking rule: ${rule}`);
|
|
159
|
+
const ruleViolations = await this.checkRule(rule, options.severity);
|
|
160
|
+
violations.push(...ruleViolations);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (violations.length > 0) {
|
|
164
|
+
logger.warn(`Found ${violations.length} compliance violations`);
|
|
165
|
+
|
|
166
|
+
if (options.fix) {
|
|
167
|
+
const fixedCount = await this.autoFixViolations(violations);
|
|
168
|
+
logger.success(`Fixed ${fixedCount} violations automatically`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this.displayViolations(violations);
|
|
172
|
+
} else {
|
|
173
|
+
logger.success('All compliance checks passed ✓');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (options.report) {
|
|
177
|
+
await this.generateComplianceReport(violations);
|
|
178
|
+
}
|
|
179
|
+
} catch (error) {
|
|
180
|
+
throw errorHandler.createError(
|
|
181
|
+
'WUNDR_GOVERN_CHECK_FAILED',
|
|
182
|
+
'Failed to run compliance checks',
|
|
183
|
+
{ options },
|
|
184
|
+
true
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* List available governance rules
|
|
191
|
+
*/
|
|
192
|
+
private async listRules(options: any): Promise<void> {
|
|
193
|
+
try {
|
|
194
|
+
const rules = await this.getAllRules();
|
|
195
|
+
const filteredRules = options.category
|
|
196
|
+
? rules.filter(rule => rule.category === options.category)
|
|
197
|
+
: rules;
|
|
198
|
+
|
|
199
|
+
if (filteredRules.length === 0) {
|
|
200
|
+
logger.info('No rules found');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
logger.info(`Available rules (${filteredRules.length}):`);
|
|
205
|
+
console.table(
|
|
206
|
+
filteredRules.map(rule => ({
|
|
207
|
+
Name: rule.name,
|
|
208
|
+
Category: rule.category,
|
|
209
|
+
Severity: rule.severity,
|
|
210
|
+
Description: rule.description,
|
|
211
|
+
Fixable: rule.fixable ? '✓' : '✗',
|
|
212
|
+
}))
|
|
213
|
+
);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
throw errorHandler.createError(
|
|
216
|
+
'WUNDR_GOVERN_LIST_RULES_FAILED',
|
|
217
|
+
'Failed to list rules',
|
|
218
|
+
{ options },
|
|
219
|
+
true
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Add a new governance rule
|
|
226
|
+
*/
|
|
227
|
+
private async addRule(rule: string, options: any): Promise<void> {
|
|
228
|
+
try {
|
|
229
|
+
logger.info(`Adding rule: ${chalk.cyan(rule)}`);
|
|
230
|
+
|
|
231
|
+
const config = this.configManager.getConfig();
|
|
232
|
+
if (!config.governance.rules.includes(rule)) {
|
|
233
|
+
config.governance.rules.push(rule);
|
|
234
|
+
await this.configManager.saveConfig();
|
|
235
|
+
logger.success(`Rule ${rule} added successfully`);
|
|
236
|
+
} else {
|
|
237
|
+
logger.warn(`Rule ${rule} already exists`);
|
|
238
|
+
}
|
|
239
|
+
} catch (error) {
|
|
240
|
+
throw errorHandler.createError(
|
|
241
|
+
'WUNDR_GOVERN_ADD_RULE_FAILED',
|
|
242
|
+
'Failed to add rule',
|
|
243
|
+
{ rule, options },
|
|
244
|
+
true
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Remove a governance rule
|
|
251
|
+
*/
|
|
252
|
+
private async removeRule(rule: string): Promise<void> {
|
|
253
|
+
try {
|
|
254
|
+
logger.info(`Removing rule: ${chalk.cyan(rule)}`);
|
|
255
|
+
|
|
256
|
+
const config = this.configManager.getConfig();
|
|
257
|
+
const index = config.governance.rules.indexOf(rule);
|
|
258
|
+
|
|
259
|
+
if (index > -1) {
|
|
260
|
+
config.governance.rules.splice(index, 1);
|
|
261
|
+
await this.configManager.saveConfig();
|
|
262
|
+
logger.success(`Rule ${rule} removed successfully`);
|
|
263
|
+
} else {
|
|
264
|
+
logger.warn(`Rule ${rule} not found`);
|
|
265
|
+
}
|
|
266
|
+
} catch (error) {
|
|
267
|
+
throw errorHandler.createError(
|
|
268
|
+
'WUNDR_GOVERN_REMOVE_RULE_FAILED',
|
|
269
|
+
'Failed to remove rule',
|
|
270
|
+
{ rule },
|
|
271
|
+
true
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Create a new governance policy
|
|
278
|
+
*/
|
|
279
|
+
private async createPolicy(name: string, options: any): Promise<void> {
|
|
280
|
+
try {
|
|
281
|
+
logger.info(`Creating policy: ${chalk.cyan(name)}`);
|
|
282
|
+
|
|
283
|
+
const policy = {
|
|
284
|
+
name,
|
|
285
|
+
description: `Policy: ${name}`,
|
|
286
|
+
rules: options.rules ? options.rules.split(',') : [],
|
|
287
|
+
severity: 'warning',
|
|
288
|
+
created: new Date().toISOString(),
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const policyPath = path.join(
|
|
292
|
+
process.cwd(),
|
|
293
|
+
'.wundr',
|
|
294
|
+
'policies',
|
|
295
|
+
`${name}.json`
|
|
296
|
+
);
|
|
297
|
+
await fs.ensureDir(path.dirname(policyPath));
|
|
298
|
+
await fs.writeJson(policyPath, policy, { spaces: 2 });
|
|
299
|
+
|
|
300
|
+
logger.success(`Policy ${name} created at ${policyPath}`);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
throw errorHandler.createError(
|
|
303
|
+
'WUNDR_GOVERN_CREATE_POLICY_FAILED',
|
|
304
|
+
'Failed to create policy',
|
|
305
|
+
{ name, options },
|
|
306
|
+
true
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Apply a policy to the project
|
|
313
|
+
*/
|
|
314
|
+
private async applyPolicy(policy: string, options: any): Promise<void> {
|
|
315
|
+
try {
|
|
316
|
+
logger.info(`Applying policy: ${chalk.cyan(policy)}`);
|
|
317
|
+
|
|
318
|
+
const policyPath = path.join(
|
|
319
|
+
process.cwd(),
|
|
320
|
+
'.wundr',
|
|
321
|
+
'policies',
|
|
322
|
+
`${policy}.json`
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
if (await fs.pathExists(policyPath)) {
|
|
326
|
+
const policyData = await fs.readJson(policyPath);
|
|
327
|
+
|
|
328
|
+
// Apply policy rules to configuration
|
|
329
|
+
const config = this.configManager.getConfig();
|
|
330
|
+
config.governance.rules.push(...policyData.rules);
|
|
331
|
+
|
|
332
|
+
// Remove duplicates
|
|
333
|
+
config.governance.rules = [...new Set(config.governance.rules)];
|
|
334
|
+
|
|
335
|
+
await this.configManager.saveConfig();
|
|
336
|
+
logger.success(`Policy ${policy} applied successfully`);
|
|
337
|
+
} else {
|
|
338
|
+
throw new Error(`Policy ${policy} not found`);
|
|
339
|
+
}
|
|
340
|
+
} catch (error) {
|
|
341
|
+
throw errorHandler.createError(
|
|
342
|
+
'WUNDR_GOVERN_APPLY_POLICY_FAILED',
|
|
343
|
+
'Failed to apply policy',
|
|
344
|
+
{ policy, options },
|
|
345
|
+
true
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Check quality gate
|
|
352
|
+
*/
|
|
353
|
+
private async checkQualityGate(options: any): Promise<void> {
|
|
354
|
+
try {
|
|
355
|
+
logger.info('Checking quality gates...');
|
|
356
|
+
|
|
357
|
+
const gates = await this.getQualityGates();
|
|
358
|
+
const gatesToCheck = options.gate
|
|
359
|
+
? [options.gate]
|
|
360
|
+
: gates.map(g => g.name);
|
|
361
|
+
|
|
362
|
+
let allPassed = true;
|
|
363
|
+
|
|
364
|
+
for (const gateName of gatesToCheck) {
|
|
365
|
+
const gate = gates.find(g => g.name === gateName);
|
|
366
|
+
if (!gate) {
|
|
367
|
+
logger.warn(`Quality gate ${gateName} not found`);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const result = await this.evaluateQualityGate(gate);
|
|
372
|
+
|
|
373
|
+
if (result.passed) {
|
|
374
|
+
logger.success(`✓ Quality gate ${gateName} passed`);
|
|
375
|
+
} else {
|
|
376
|
+
logger.error(`✗ Quality gate ${gateName} failed`);
|
|
377
|
+
result.failures.forEach(failure => {
|
|
378
|
+
logger.error(` - ${failure}`);
|
|
379
|
+
});
|
|
380
|
+
allPassed = false;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!allPassed && options.failOnError) {
|
|
385
|
+
process.exit(1);
|
|
386
|
+
}
|
|
387
|
+
} catch (error) {
|
|
388
|
+
throw errorHandler.createError(
|
|
389
|
+
'WUNDR_GOVERN_GATE_CHECK_FAILED',
|
|
390
|
+
'Failed to check quality gate',
|
|
391
|
+
{ options },
|
|
392
|
+
true
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Create a new quality gate
|
|
399
|
+
*/
|
|
400
|
+
private async createQualityGate(name: string, options: any): Promise<void> {
|
|
401
|
+
try {
|
|
402
|
+
logger.info(`Creating quality gate: ${chalk.cyan(name)}`);
|
|
403
|
+
|
|
404
|
+
const gate = {
|
|
405
|
+
name,
|
|
406
|
+
description: `Quality gate: ${name}`,
|
|
407
|
+
conditions: options.conditions ? options.conditions.split(',') : [],
|
|
408
|
+
created: new Date().toISOString(),
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const gatePath = path.join(
|
|
412
|
+
process.cwd(),
|
|
413
|
+
'.wundr',
|
|
414
|
+
'gates',
|
|
415
|
+
`${name}.json`
|
|
416
|
+
);
|
|
417
|
+
await fs.ensureDir(path.dirname(gatePath));
|
|
418
|
+
await fs.writeJson(gatePath, gate, { spaces: 2 });
|
|
419
|
+
|
|
420
|
+
logger.success(`Quality gate ${name} created at ${gatePath}`);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
throw errorHandler.createError(
|
|
423
|
+
'WUNDR_GOVERN_CREATE_GATE_FAILED',
|
|
424
|
+
'Failed to create quality gate',
|
|
425
|
+
{ name, options },
|
|
426
|
+
true
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Run governance audit
|
|
433
|
+
*/
|
|
434
|
+
private async runAudit(options: any): Promise<void> {
|
|
435
|
+
try {
|
|
436
|
+
logger.info('Running governance audit...');
|
|
437
|
+
|
|
438
|
+
const auditResults = {
|
|
439
|
+
timestamp: new Date().toISOString(),
|
|
440
|
+
scope: options.scope,
|
|
441
|
+
results: {
|
|
442
|
+
security:
|
|
443
|
+
options.scope === 'all' || options.scope === 'security'
|
|
444
|
+
? await this.auditSecurity()
|
|
445
|
+
: null,
|
|
446
|
+
quality:
|
|
447
|
+
options.scope === 'all' || options.scope === 'quality'
|
|
448
|
+
? await this.auditQuality()
|
|
449
|
+
: null,
|
|
450
|
+
compliance:
|
|
451
|
+
options.scope === 'all' || options.scope === 'compliance'
|
|
452
|
+
? await this.auditCompliance()
|
|
453
|
+
: null,
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
logger.info('Audit completed');
|
|
458
|
+
this.displayAuditResults(auditResults);
|
|
459
|
+
|
|
460
|
+
if (options.export) {
|
|
461
|
+
await fs.writeJson(options.export, auditResults, { spaces: 2 });
|
|
462
|
+
logger.success(`Audit results exported to ${options.export}`);
|
|
463
|
+
}
|
|
464
|
+
} catch (error) {
|
|
465
|
+
throw errorHandler.createError(
|
|
466
|
+
'WUNDR_GOVERN_AUDIT_FAILED',
|
|
467
|
+
'Failed to run audit',
|
|
468
|
+
{ options },
|
|
469
|
+
true
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Generate governance report
|
|
476
|
+
*/
|
|
477
|
+
private async generateReport(options: any): Promise<void> {
|
|
478
|
+
try {
|
|
479
|
+
logger.info(`Generating ${options.type} report...`);
|
|
480
|
+
|
|
481
|
+
const report = await this.createGovernanceReport(
|
|
482
|
+
options.type,
|
|
483
|
+
options.period
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
const outputPath =
|
|
487
|
+
options.output || `wundr-${options.type}-report-${Date.now()}.json`;
|
|
488
|
+
await fs.writeJson(outputPath, report, { spaces: 2 });
|
|
489
|
+
|
|
490
|
+
logger.success(`Report generated: ${outputPath}`);
|
|
491
|
+
} catch (error) {
|
|
492
|
+
throw errorHandler.createError(
|
|
493
|
+
'WUNDR_GOVERN_REPORT_FAILED',
|
|
494
|
+
'Failed to generate report',
|
|
495
|
+
{ options },
|
|
496
|
+
true
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Implementation methods
|
|
503
|
+
*/
|
|
504
|
+
private async checkRule(rule: string, severity: string): Promise<any[]> {
|
|
505
|
+
// Implementation for checking individual rules
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
private async autoFixViolations(violations: any[]): Promise<number> {
|
|
510
|
+
// Implementation for auto-fixing violations
|
|
511
|
+
return 0;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
private async getAllRules(): Promise<any[]> {
|
|
515
|
+
// Implementation for getting all available rules
|
|
516
|
+
return [
|
|
517
|
+
{
|
|
518
|
+
name: 'no-console',
|
|
519
|
+
category: 'quality',
|
|
520
|
+
severity: 'warning',
|
|
521
|
+
description: 'Disallow console statements',
|
|
522
|
+
fixable: true,
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: 'require-tests',
|
|
526
|
+
category: 'quality',
|
|
527
|
+
severity: 'error',
|
|
528
|
+
description: 'Require test files for all modules',
|
|
529
|
+
fixable: false,
|
|
530
|
+
},
|
|
531
|
+
];
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private async getQualityGates(): Promise<any[]> {
|
|
535
|
+
// Implementation for getting quality gates
|
|
536
|
+
return [];
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
private async evaluateQualityGate(
|
|
540
|
+
gate: any
|
|
541
|
+
): Promise<{ passed: boolean; failures: string[] }> {
|
|
542
|
+
// Implementation for evaluating quality gates
|
|
543
|
+
return { passed: true, failures: [] };
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
private async auditSecurity(): Promise<any> {
|
|
547
|
+
// Implementation for security audit
|
|
548
|
+
return { issues: [], score: 100 };
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
private async auditQuality(): Promise<any> {
|
|
552
|
+
// Implementation for quality audit
|
|
553
|
+
return { issues: [], score: 95 };
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
private async auditCompliance(): Promise<any> {
|
|
557
|
+
// Implementation for compliance audit
|
|
558
|
+
return { violations: [], score: 90 };
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
private async createGovernanceReport(
|
|
562
|
+
type: string,
|
|
563
|
+
period: string
|
|
564
|
+
): Promise<any> {
|
|
565
|
+
// Implementation for creating governance reports
|
|
566
|
+
return {
|
|
567
|
+
type,
|
|
568
|
+
period,
|
|
569
|
+
generated: new Date().toISOString(),
|
|
570
|
+
summary: {},
|
|
571
|
+
details: [],
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
private displayViolations(violations: any[]): void {
|
|
576
|
+
if (violations.length === 0) return;
|
|
577
|
+
|
|
578
|
+
console.log(chalk.yellow('\nCompliance Violations:'));
|
|
579
|
+
console.table(
|
|
580
|
+
violations.map(v => ({
|
|
581
|
+
Rule: v.rule,
|
|
582
|
+
Severity: v.severity,
|
|
583
|
+
File: v.file,
|
|
584
|
+
Line: v.line || 'N/A',
|
|
585
|
+
Description: v.description,
|
|
586
|
+
}))
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
private async generateComplianceReport(violations: any[]): Promise<void> {
|
|
591
|
+
const report = {
|
|
592
|
+
timestamp: new Date().toISOString(),
|
|
593
|
+
totalViolations: violations.length,
|
|
594
|
+
violations,
|
|
595
|
+
summary: this.createViolationsSummary(violations),
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
const reportPath = `compliance-report-${Date.now()}.json`;
|
|
599
|
+
await fs.writeJson(reportPath, report, { spaces: 2 });
|
|
600
|
+
logger.success(`Compliance report generated: ${reportPath}`);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
private createViolationsSummary(violations: any[]): any {
|
|
604
|
+
const summary = {
|
|
605
|
+
bySeverity: {},
|
|
606
|
+
byRule: {},
|
|
607
|
+
byFile: {},
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
violations.forEach(v => {
|
|
611
|
+
summary.bySeverity[v.severity] =
|
|
612
|
+
(summary.bySeverity[v.severity] || 0) + 1;
|
|
613
|
+
summary.byRule[v.rule] = (summary.byRule[v.rule] || 0) + 1;
|
|
614
|
+
summary.byFile[v.file] = (summary.byFile[v.file] || 0) + 1;
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
return summary;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
private displayAuditResults(results: any): void {
|
|
621
|
+
console.log(chalk.blue('\nAudit Results:'));
|
|
622
|
+
|
|
623
|
+
if (results.results.security) {
|
|
624
|
+
console.log(`Security Score: ${results.results.security.score}/100`);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (results.results.quality) {
|
|
628
|
+
console.log(`Quality Score: ${results.results.quality.score}/100`);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (results.results.compliance) {
|
|
632
|
+
console.log(`Compliance Score: ${results.results.compliance.score}/100`);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|