@hyperdrive.bot/bmad-workflow 1.0.18 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/config/show.js +8 -2
- package/dist/commands/decompose.js +26 -5
- package/dist/commands/epics/create.d.ts +1 -0
- package/dist/commands/mcp/add.d.ts +16 -0
- package/dist/commands/mcp/add.js +77 -0
- package/dist/commands/mcp/credential/get.d.ts +14 -0
- package/dist/commands/mcp/credential/get.js +35 -0
- package/dist/commands/mcp/credential/list.d.ts +17 -0
- package/dist/commands/mcp/credential/list.js +67 -0
- package/dist/commands/mcp/credential/remove.d.ts +18 -0
- package/dist/commands/mcp/credential/remove.js +84 -0
- package/dist/commands/mcp/credential/set.d.ts +16 -0
- package/dist/commands/mcp/credential/set.js +41 -0
- package/dist/commands/mcp/credential/validate.d.ts +12 -0
- package/dist/commands/mcp/credential/validate.js +150 -0
- package/dist/commands/mcp/list.d.ts +17 -0
- package/dist/commands/mcp/list.js +80 -0
- package/dist/commands/mcp/logs.d.ts +15 -0
- package/dist/commands/mcp/logs.js +64 -0
- package/dist/commands/mcp/preset.d.ts +15 -0
- package/dist/commands/mcp/preset.js +84 -0
- package/dist/commands/mcp/remove.d.ts +14 -0
- package/dist/commands/mcp/remove.js +36 -0
- package/dist/commands/mcp/start.d.ts +12 -0
- package/dist/commands/mcp/start.js +80 -0
- package/dist/commands/mcp/status.d.ts +30 -0
- package/dist/commands/mcp/status.js +180 -0
- package/dist/commands/mcp/stop.d.ts +12 -0
- package/dist/commands/mcp/stop.js +47 -0
- package/dist/commands/stories/create.d.ts +1 -0
- package/dist/commands/stories/develop.d.ts +1 -0
- package/dist/commands/stories/qa.js +5 -2
- package/dist/commands/stories/review.d.ts +124 -0
- package/dist/commands/stories/review.js +516 -0
- package/dist/commands/workflow.d.ts +8 -0
- package/dist/commands/workflow.js +110 -2
- package/dist/mcp/types.d.ts +99 -0
- package/dist/mcp/types.js +7 -0
- package/dist/mcp/utils/docker-utils.d.ts +56 -0
- package/dist/mcp/utils/docker-utils.js +108 -0
- package/dist/mcp/utils/template-loader.d.ts +21 -0
- package/dist/mcp/utils/template-loader.js +60 -0
- package/dist/models/agent-options.d.ts +10 -1
- package/dist/models/workflow-config.d.ts +77 -0
- package/dist/models/workflow-result.d.ts +7 -0
- package/dist/services/agents/claude-agent-runner.js +19 -3
- package/dist/services/file-system/path-resolver.d.ts +10 -0
- package/dist/services/file-system/path-resolver.js +12 -0
- package/dist/services/mcp/mcp-config-manager.d.ts +54 -0
- package/dist/services/mcp/mcp-config-manager.js +146 -0
- package/dist/services/mcp/mcp-context-injector.d.ts +92 -0
- package/dist/services/mcp/mcp-context-injector.js +168 -0
- package/dist/services/mcp/mcp-credential-manager.d.ts +48 -0
- package/dist/services/mcp/mcp-credential-manager.js +124 -0
- package/dist/services/mcp/mcp-health-checker.d.ts +56 -0
- package/dist/services/mcp/mcp-health-checker.js +162 -0
- package/dist/services/mcp/types/health-types.d.ts +31 -0
- package/dist/services/mcp/types/health-types.js +7 -0
- package/dist/services/orchestration/dependency-graph-executor.js +1 -1
- package/dist/services/orchestration/task-decomposition-service.d.ts +2 -1
- package/dist/services/orchestration/task-decomposition-service.js +90 -36
- package/dist/services/orchestration/workflow-orchestrator.d.ts +54 -2
- package/dist/services/orchestration/workflow-orchestrator.js +303 -17
- package/dist/services/review/ai-review-scanner.d.ts +66 -0
- package/dist/services/review/ai-review-scanner.js +142 -0
- package/dist/services/review/coderabbit-scanner.d.ts +25 -0
- package/dist/services/review/coderabbit-scanner.js +31 -0
- package/dist/services/review/index.d.ts +20 -0
- package/dist/services/review/index.js +15 -0
- package/dist/services/review/lint-scanner.d.ts +46 -0
- package/dist/services/review/lint-scanner.js +172 -0
- package/dist/services/review/review-config.d.ts +62 -0
- package/dist/services/review/review-config.js +91 -0
- package/dist/services/review/review-phase-executor.d.ts +69 -0
- package/dist/services/review/review-phase-executor.js +152 -0
- package/dist/services/review/review-queue.d.ts +98 -0
- package/dist/services/review/review-queue.js +174 -0
- package/dist/services/review/review-reporter.d.ts +94 -0
- package/dist/services/review/review-reporter.js +386 -0
- package/dist/services/review/scanner-factory.d.ts +42 -0
- package/dist/services/review/scanner-factory.js +60 -0
- package/dist/services/review/self-heal-loop.d.ts +58 -0
- package/dist/services/review/self-heal-loop.js +132 -0
- package/dist/services/review/severity-classifier.d.ts +17 -0
- package/dist/services/review/severity-classifier.js +314 -0
- package/dist/services/review/tech-debt-tracker.d.ts +52 -0
- package/dist/services/review/tech-debt-tracker.js +245 -0
- package/dist/services/review/types.d.ts +93 -0
- package/dist/services/review/types.js +23 -0
- package/dist/services/validation/config-validator.d.ts +84 -0
- package/dist/services/validation/config-validator.js +78 -0
- package/dist/utils/credential-utils.d.ts +14 -0
- package/dist/utils/credential-utils.js +19 -0
- package/dist/utils/duration.d.ts +41 -0
- package/dist/utils/duration.js +89 -0
- package/dist/utils/shared-flags.d.ts +1 -0
- package/dist/utils/shared-flags.js +11 -2
- package/package.json +4 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Status Command
|
|
3
|
+
*
|
|
4
|
+
* Displays a structured dashboard showing gateway health, per-server health
|
|
5
|
+
* with latency, credential status, and current active preset name.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from '@oclif/core';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { DEFAULT_GATEWAY_URL, formatDockerError, isDockerAvailable } from '../../mcp/utils/docker-utils.js';
|
|
10
|
+
import { createLogger } from '../../utils/logger.js';
|
|
11
|
+
const logger = createLogger({ namespace: 'commands:mcp:status' });
|
|
12
|
+
/**
|
|
13
|
+
* Format latency for display
|
|
14
|
+
*/
|
|
15
|
+
function formatLatency(ms) {
|
|
16
|
+
if (ms === null)
|
|
17
|
+
return '—';
|
|
18
|
+
if (ms >= 1000)
|
|
19
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
20
|
+
return `${ms}ms`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Format health status with icon
|
|
24
|
+
*/
|
|
25
|
+
function formatStatus(status) {
|
|
26
|
+
switch (status) {
|
|
27
|
+
case 'disabled': {
|
|
28
|
+
return chalk.gray('✗ disabled');
|
|
29
|
+
}
|
|
30
|
+
case 'healthy': {
|
|
31
|
+
return chalk.green('✓ healthy');
|
|
32
|
+
}
|
|
33
|
+
case 'offline': {
|
|
34
|
+
return chalk.red('✗ offline');
|
|
35
|
+
}
|
|
36
|
+
case 'unhealthy': {
|
|
37
|
+
return chalk.yellow('! unhealthy');
|
|
38
|
+
}
|
|
39
|
+
default: {
|
|
40
|
+
return chalk.dim(status);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Render the status dashboard to the terminal
|
|
46
|
+
*/
|
|
47
|
+
function renderDashboard(healthReport, presetName, credentials) {
|
|
48
|
+
const lines = [];
|
|
49
|
+
// Header
|
|
50
|
+
lines.push(chalk.bold('MCP Gateway Status'));
|
|
51
|
+
lines.push(chalk.dim('=================='));
|
|
52
|
+
// Gateway line
|
|
53
|
+
const gwStatus = formatStatus(healthReport.gateway.status);
|
|
54
|
+
const gwLatency = formatLatency(healthReport.gateway.latency);
|
|
55
|
+
const gwLine = healthReport.gateway.latency !== null
|
|
56
|
+
? `${gwStatus} (${gwLatency})`
|
|
57
|
+
: gwStatus;
|
|
58
|
+
lines.push(`Gateway: ${healthReport.gateway.url} ${gwLine}`);
|
|
59
|
+
lines.push(`Preset: ${presetName}`);
|
|
60
|
+
// Servers section
|
|
61
|
+
lines.push('');
|
|
62
|
+
lines.push(chalk.bold('Servers:'));
|
|
63
|
+
if (healthReport.servers.length === 0) {
|
|
64
|
+
lines.push(chalk.dim(' No servers configured'));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Calculate column widths for alignment
|
|
68
|
+
const maxNameLen = Math.max(...healthReport.servers.map((s) => s.name.length));
|
|
69
|
+
for (const server of healthReport.servers) {
|
|
70
|
+
const name = server.name.padEnd(maxNameLen);
|
|
71
|
+
const status = formatStatus(server.status);
|
|
72
|
+
const latency = server.status === 'disabled' ? '—' : formatLatency(server.latency);
|
|
73
|
+
const padLatency = `(${latency})`.padEnd(10);
|
|
74
|
+
const useCase = server.useCase || '';
|
|
75
|
+
lines.push(` ${name} ${status} ${padLatency} ${useCase}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Credentials section
|
|
79
|
+
if (credentials.length > 0) {
|
|
80
|
+
lines.push('');
|
|
81
|
+
lines.push(chalk.bold('Credentials:'));
|
|
82
|
+
const maxKeyLen = Math.max(...credentials.map((c) => c.key.length));
|
|
83
|
+
for (const cred of credentials) {
|
|
84
|
+
const key = cred.key.padEnd(maxKeyLen);
|
|
85
|
+
if (cred.configured) {
|
|
86
|
+
lines.push(` ${key} ${chalk.green('✓ configured')}`);
|
|
87
|
+
}
|
|
88
|
+
else if (!cred.requiredByPreset) {
|
|
89
|
+
lines.push(` ${key} ${chalk.dim('— not set (not needed for current preset)')}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
lines.push(` ${key} ${chalk.yellow('✗ not set')}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return lines.join('\n');
|
|
97
|
+
}
|
|
98
|
+
export default class McpStatus extends Command {
|
|
99
|
+
static description = 'Display MCP gateway status dashboard with server health and credentials';
|
|
100
|
+
static examples = [
|
|
101
|
+
'<%= config.bin %> mcp status',
|
|
102
|
+
];
|
|
103
|
+
async run() {
|
|
104
|
+
logger.info('Checking MCP gateway status');
|
|
105
|
+
// 1. Check Docker availability
|
|
106
|
+
const dockerCheck = isDockerAvailable();
|
|
107
|
+
if (!dockerCheck.available) {
|
|
108
|
+
this.error(formatDockerError(dockerCheck), { exit: 1 });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// 2. Gather status data
|
|
112
|
+
// NOTE: McpHealthChecker, McpConfigManager, and McpCredentialManager
|
|
113
|
+
// are provided by Epic 1 / Story 2.4. Until those are implemented,
|
|
114
|
+
// we fall back to a direct health check and sensible defaults.
|
|
115
|
+
const healthReport = await this.getHealthReport();
|
|
116
|
+
const presetName = this.getPresetName();
|
|
117
|
+
const credentials = this.getCredentials();
|
|
118
|
+
// 3. Render dashboard
|
|
119
|
+
const dashboard = renderDashboard(healthReport, presetName, credentials);
|
|
120
|
+
this.log(dashboard);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get credentials status — delegates to McpCredentialManager when available
|
|
124
|
+
*/
|
|
125
|
+
getCredentials() {
|
|
126
|
+
try {
|
|
127
|
+
// TODO: Replace with McpCredentialManager.list() when Epic 1 is complete
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Gather health report — delegates to McpHealthChecker when available
|
|
136
|
+
*/
|
|
137
|
+
async getHealthReport() {
|
|
138
|
+
// TODO: Replace with McpHealthChecker.checkAll() when Story 2.4 is complete
|
|
139
|
+
// For now, do a simple gateway health check
|
|
140
|
+
const gatewayUrl = DEFAULT_GATEWAY_URL;
|
|
141
|
+
const healthUrl = `${gatewayUrl}/health`;
|
|
142
|
+
try {
|
|
143
|
+
const start = Date.now();
|
|
144
|
+
const response = await fetch(healthUrl, { signal: AbortSignal.timeout(5000) });
|
|
145
|
+
const latency = Date.now() - start;
|
|
146
|
+
return {
|
|
147
|
+
gateway: {
|
|
148
|
+
latency,
|
|
149
|
+
status: response.ok ? 'healthy' : 'unhealthy',
|
|
150
|
+
url: gatewayUrl,
|
|
151
|
+
},
|
|
152
|
+
servers: [],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return {
|
|
157
|
+
gateway: {
|
|
158
|
+
latency: null,
|
|
159
|
+
status: 'offline',
|
|
160
|
+
url: gatewayUrl,
|
|
161
|
+
},
|
|
162
|
+
servers: [],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get current preset name — delegates to McpConfigManager when available
|
|
168
|
+
*/
|
|
169
|
+
getPresetName() {
|
|
170
|
+
try {
|
|
171
|
+
// TODO: Replace with McpConfigManager.getPresetName() when Epic 1 is complete
|
|
172
|
+
return 'unknown';
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return 'unknown';
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Export the render function for testing
|
|
180
|
+
export { renderDashboard };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Stop Command
|
|
3
|
+
*
|
|
4
|
+
* Shuts down the Docker MCP gateway via docker compose down
|
|
5
|
+
* and confirms shutdown to the user.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from '@oclif/core';
|
|
8
|
+
export default class McpStop extends Command {
|
|
9
|
+
static description: string;
|
|
10
|
+
static examples: string[];
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Stop Command
|
|
3
|
+
*
|
|
4
|
+
* Shuts down the Docker MCP gateway via docker compose down
|
|
5
|
+
* and confirms shutdown to the user.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { Command } from '@oclif/core';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { dockerComposeFileExists, formatDockerError, getDockerComposeFilePath, isDockerAvailable, } from '../../mcp/utils/docker-utils.js';
|
|
11
|
+
import { createLogger } from '../../utils/logger.js';
|
|
12
|
+
const logger = createLogger({ namespace: 'commands:mcp:stop' });
|
|
13
|
+
export default class McpStop extends Command {
|
|
14
|
+
static description = 'Stop the Docker MCP gateway';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> mcp stop',
|
|
17
|
+
];
|
|
18
|
+
async run() {
|
|
19
|
+
logger.info('Stopping MCP gateway');
|
|
20
|
+
// 1. Check Docker availability
|
|
21
|
+
const dockerCheck = isDockerAvailable();
|
|
22
|
+
if (!dockerCheck.available) {
|
|
23
|
+
this.error(formatDockerError(dockerCheck), { exit: 1 });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// 2. Verify compose file exists
|
|
27
|
+
const composePath = getDockerComposeFilePath();
|
|
28
|
+
if (!dockerComposeFileExists()) {
|
|
29
|
+
this.error(`Docker Compose file not found at: ${composePath}\nNothing to stop — the gateway has not been initialized.`, { exit: 1 });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// 3. Shut down gateway
|
|
33
|
+
this.log(chalk.dim('Stopping MCP gateway containers...'));
|
|
34
|
+
try {
|
|
35
|
+
execSync(`docker compose -f "${composePath}" down`, { stdio: 'pipe', timeout: 60_000 });
|
|
36
|
+
this.log('');
|
|
37
|
+
this.log(chalk.green.bold('✓ MCP Gateway stopped successfully'));
|
|
38
|
+
logger.info('Gateway stopped');
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const err = error;
|
|
42
|
+
const stderr = err.stderr ? err.stderr.toString() : err.message;
|
|
43
|
+
logger.error('Failed to stop gateway: %s', stderr);
|
|
44
|
+
this.error(`Failed to stop MCP gateway:\n${stderr}`, { exit: 1 });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -39,6 +39,7 @@ export default class StoriesCreateCommand extends Command {
|
|
|
39
39
|
provider: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
40
40
|
task: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
41
41
|
timeout: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
|
+
'review-timeout': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
43
|
'max-retries': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
44
|
'retry-backoff': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
};
|
|
@@ -41,6 +41,7 @@ export default class StoriesDevelopCommand extends Command {
|
|
|
41
41
|
provider: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
42
|
task: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
43
|
timeout: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
|
+
'review-timeout': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
'max-retries': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
45
46
|
'retry-backoff': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
46
47
|
};
|
|
@@ -21,6 +21,7 @@ import { GlobMatcher } from '../../services/file-system/glob-matcher.js';
|
|
|
21
21
|
import { PathResolver } from '../../services/file-system/path-resolver.js';
|
|
22
22
|
import { StoryParserFactory } from '../../services/parsers/story-parser-factory.js';
|
|
23
23
|
import * as colors from '../../utils/colors.js';
|
|
24
|
+
import { parseDuration } from '../../utils/duration.js';
|
|
24
25
|
import { createLogger, generateCorrelationId } from '../../utils/logger.js';
|
|
25
26
|
import { runAgentWithRetry } from '../../utils/retry.js';
|
|
26
27
|
/**
|
|
@@ -84,9 +85,11 @@ export default class StoriesQaCommand extends Command {
|
|
|
84
85
|
description: 'Additional context files for agents',
|
|
85
86
|
multiple: true,
|
|
86
87
|
}),
|
|
87
|
-
timeout: Flags.
|
|
88
|
+
timeout: Flags.custom({
|
|
89
|
+
parse: async (input) => parseDuration(input),
|
|
90
|
+
})({
|
|
88
91
|
default: 2_700_000,
|
|
89
|
-
description: 'Agent execution timeout
|
|
92
|
+
description: 'Agent execution timeout — accepts durations like 30s, 5m, 1h, 90m, or raw milliseconds (default: 45m)',
|
|
90
93
|
helpGroup: 'Resilience',
|
|
91
94
|
}),
|
|
92
95
|
'agent-retries': Flags.integer({
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stories Review Command
|
|
3
|
+
*
|
|
4
|
+
* Standalone command that discovers and reviews existing story files outside
|
|
5
|
+
* the full workflow pipeline. Runs automated code review (scanners + self-heal)
|
|
6
|
+
* on matched stories and produces PASS/FAIL verdicts.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```bash
|
|
10
|
+
* bmad-workflow stories review "docs/qa/stories/AUTH-*.md"
|
|
11
|
+
* bmad-workflow stories review "stories/*.md" --scanners ai,lint --dry-run
|
|
12
|
+
* bmad-workflow stories review "stories/*.md" --json
|
|
13
|
+
* bmad-workflow stories review "stories/*.md" --block-on CRITICAL --max-fix 5
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import { Command } from '@oclif/core';
|
|
17
|
+
import { Severity } from '../../services/review/types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Parse and validate --scanners flag value
|
|
20
|
+
*
|
|
21
|
+
* @param value - Comma-separated scanner names
|
|
22
|
+
* @returns Array of valid scanner names
|
|
23
|
+
* @throws Error if any scanner name is invalid
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseScanners(value: string): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Parse and validate --block-on flag value
|
|
28
|
+
*
|
|
29
|
+
* @param value - Comma-separated severity names
|
|
30
|
+
* @returns Array of valid severity strings
|
|
31
|
+
* @throws Error if any severity is invalid
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseBlockOn(value: string): Severity;
|
|
34
|
+
/**
|
|
35
|
+
* Validate --max-fix is a positive integer
|
|
36
|
+
*
|
|
37
|
+
* @param value - Value to validate
|
|
38
|
+
* @returns The validated integer
|
|
39
|
+
* @throws Error if value is not a positive integer
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateMaxFix(value: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* Stories Review Command
|
|
44
|
+
*
|
|
45
|
+
* Discovers story files via glob pattern and runs automated code review on each.
|
|
46
|
+
* Supports --dry-run (findings only, no fixes) and --json (structured CI output).
|
|
47
|
+
*/
|
|
48
|
+
export default class StoriesReviewCommand extends Command {
|
|
49
|
+
static args: {
|
|
50
|
+
pattern: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
51
|
+
};
|
|
52
|
+
static description: string;
|
|
53
|
+
static examples: {
|
|
54
|
+
command: string;
|
|
55
|
+
description: string;
|
|
56
|
+
}[];
|
|
57
|
+
static flags: {
|
|
58
|
+
'block-on': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
59
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
60
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
61
|
+
'max-fix': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
62
|
+
scanners: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
63
|
+
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
64
|
+
cwd: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
65
|
+
model: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
66
|
+
provider: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
67
|
+
task: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
68
|
+
timeout: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
69
|
+
'review-timeout': import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
70
|
+
'max-retries': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
71
|
+
'retry-backoff': import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
72
|
+
};
|
|
73
|
+
private agentRunner;
|
|
74
|
+
private fileManager;
|
|
75
|
+
private globMatcher;
|
|
76
|
+
private logger;
|
|
77
|
+
private pathResolver;
|
|
78
|
+
private storyParserFactory;
|
|
79
|
+
/**
|
|
80
|
+
* Run the command
|
|
81
|
+
*/
|
|
82
|
+
run(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Validate and parse all CLI flags into a typed config object
|
|
85
|
+
*/
|
|
86
|
+
private validateFlags;
|
|
87
|
+
/**
|
|
88
|
+
* Discover story files matching the glob pattern
|
|
89
|
+
*/
|
|
90
|
+
private discoverStories;
|
|
91
|
+
/**
|
|
92
|
+
* Review all discovered stories sequentially
|
|
93
|
+
*/
|
|
94
|
+
private reviewStories;
|
|
95
|
+
/**
|
|
96
|
+
* Write review results to story files and session directory
|
|
97
|
+
*/
|
|
98
|
+
private writeResults;
|
|
99
|
+
/**
|
|
100
|
+
* Output structured JSON to stdout (for --json mode)
|
|
101
|
+
*/
|
|
102
|
+
private outputJson;
|
|
103
|
+
/**
|
|
104
|
+
* Display human-readable summary table
|
|
105
|
+
*/
|
|
106
|
+
private displaySummary;
|
|
107
|
+
/**
|
|
108
|
+
* Initialize service dependencies
|
|
109
|
+
*/
|
|
110
|
+
private initializeServices;
|
|
111
|
+
/**
|
|
112
|
+
* Extract story ID from file path
|
|
113
|
+
* e.g., "docs/stories/PROJ-story-1.001.md" → "PROJ-story-1.001"
|
|
114
|
+
*/
|
|
115
|
+
private extractStoryId;
|
|
116
|
+
/**
|
|
117
|
+
* Group issues by severity level
|
|
118
|
+
*/
|
|
119
|
+
private groupIssuesBySeverity;
|
|
120
|
+
/**
|
|
121
|
+
* Format duration in human-readable format
|
|
122
|
+
*/
|
|
123
|
+
private formatDuration;
|
|
124
|
+
}
|