software-engineer 0.1.21 ā 0.1.23
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 +72 -3
- package/dist/claude.js +3 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +10 -1
- package/dist/index.js +16 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +8 -1
- package/dist/pipeline.js +82 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A CLI tool that automates the software development workflow using Claude AI. It runs an 8-step pipeline to implement features, simplify code, review, ensure quality, test, commit, and update changelogs with real-time progress visualization.
|
|
4
4
|
|
|
5
|
+
By default, Claude is automatically granted permission to **Edit, Read, and Bash** tools, allowing seamless autonomous operation without constant permission prompts.
|
|
6
|
+
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -13,6 +15,27 @@ npm install -g software-engineer
|
|
|
13
15
|
- Node.js >= 18.0.0
|
|
14
16
|
- [Claude CLI](https://github.com/anthropics/claude-code) installed and configured
|
|
15
17
|
|
|
18
|
+
## Recommended Workflow
|
|
19
|
+
|
|
20
|
+
For best results, follow this workflow:
|
|
21
|
+
|
|
22
|
+
1. **Plan with Claude**: Start a Claude session and use plan mode to design what needs to be done
|
|
23
|
+
- Discuss requirements with Claude
|
|
24
|
+
- Iterate and refine the plan until it's complete
|
|
25
|
+
- Claude will generate a plan file (usually a `.md` file)
|
|
26
|
+
|
|
27
|
+
2. **Execute with software-engineer**: Once your plan is finalized, close Claude and run:
|
|
28
|
+
```bash
|
|
29
|
+
sf "implement the plan mentioned in /path/to/plan.md"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. **Wait for completion**: The tool will automatically execute the entire pipeline and implement your plan
|
|
33
|
+
|
|
34
|
+
This approach gives you the best of both worlds:
|
|
35
|
+
- **Interactive planning** with Claude to ensure the approach is correct
|
|
36
|
+
- **Automated execution** with comprehensive quality checks
|
|
37
|
+
- **Seamless operation** - Claude automatically has permission to edit files, read code, and run commands without prompts
|
|
38
|
+
|
|
16
39
|
## Usage
|
|
17
40
|
|
|
18
41
|
```bash
|
|
@@ -22,7 +45,10 @@ sf "<requirement>"
|
|
|
22
45
|
### Examples
|
|
23
46
|
|
|
24
47
|
```bash
|
|
25
|
-
#
|
|
48
|
+
# Recommended: Use with a plan file from Claude
|
|
49
|
+
sf "implement the plan mentioned in ./docs/feature-plan.md"
|
|
50
|
+
|
|
51
|
+
# Basic usage with direct requirement
|
|
26
52
|
sf "add user authentication with JWT"
|
|
27
53
|
|
|
28
54
|
# Custom review iterations
|
|
@@ -38,6 +64,46 @@ sf --skip-tests --skip-push "update README"
|
|
|
38
64
|
sf --log pipeline.log "implement caching layer"
|
|
39
65
|
```
|
|
40
66
|
|
|
67
|
+
## Permission Management
|
|
68
|
+
|
|
69
|
+
By default, `software-engineer` automatically grants Claude permission to use **Edit, Read, and Bash** tools without prompting. This streamlines the workflow while maintaining control over file operations.
|
|
70
|
+
|
|
71
|
+
### Default Behavior
|
|
72
|
+
|
|
73
|
+
When you run the tool, it automatically passes `--allowedTools "Edit,Read,Bash"` to Claude:
|
|
74
|
+
- **Edit**: Modify existing files
|
|
75
|
+
- **Read**: Read file contents
|
|
76
|
+
- **Bash**: Execute shell commands (git, npm, build tools, etc.)
|
|
77
|
+
|
|
78
|
+
This means Claude can work autonomously on your codebase without constant permission prompts, making the pipeline smooth and efficient.
|
|
79
|
+
|
|
80
|
+
### Customizing Allowed Tools
|
|
81
|
+
|
|
82
|
+
You can customize which tools are auto-approved:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Allow additional tools
|
|
86
|
+
sf --allowedTools "Edit,Read,Write,Bash,Grep" "add new feature"
|
|
87
|
+
|
|
88
|
+
# Via environment variable
|
|
89
|
+
SF_ALLOWED_TOOLS="Edit,Read,Write,Bash" sf "implement caching"
|
|
90
|
+
|
|
91
|
+
# Restrict to read-only operations
|
|
92
|
+
sf --allowedTools "Read,Grep,Glob" "analyze the codebase"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Skipping All Permissions (Use with Caution)
|
|
96
|
+
|
|
97
|
+
For fully autonomous operation in trusted environments (like CI/CD), you can skip all permission checks:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
sf --dangerously-skip-permissions "implement feature"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Warning**: This bypasses ALL permission prompts. Only use in isolated, secure environments.
|
|
104
|
+
|
|
105
|
+
**Note**: When `--dangerously-skip-permissions` is used, the `allowedTools` setting is ignored.
|
|
106
|
+
|
|
41
107
|
## Options
|
|
42
108
|
|
|
43
109
|
| Option | Description |
|
|
@@ -49,7 +115,8 @@ sf --log pipeline.log "implement caching layer"
|
|
|
49
115
|
| `--skip-push` | Commit but don't push to remote |
|
|
50
116
|
| `--skip-branch-management` | Skip smart branch management |
|
|
51
117
|
| `--log <file>` | Log output to file |
|
|
52
|
-
| `--
|
|
118
|
+
| `--allowedTools <tools>` | Comma-separated list of allowed tools (default: "Edit,Read,Bash") |
|
|
119
|
+
| `--dangerously-skip-permissions` | Skip Claude permission prompts (overrides allowedTools) |
|
|
53
120
|
| `-h, --help` | Display help |
|
|
54
121
|
| `-V, --version` | Display version |
|
|
55
122
|
|
|
@@ -66,7 +133,8 @@ All options can be set via environment variables:
|
|
|
66
133
|
| `SF_SKIP_TESTS` | `true`/`false` to skip tests |
|
|
67
134
|
| `SF_SKIP_PUSH` | `true`/`false` to skip push |
|
|
68
135
|
| `SF_SKIP_BRANCH_MANAGEMENT` | `true`/`false` to skip branch management |
|
|
69
|
-
| `
|
|
136
|
+
| `SF_ALLOWED_TOOLS` | Comma-separated list of allowed tools (default: "Edit,Read,Bash") |
|
|
137
|
+
| `SF_DANGEROUSLY_SKIP_PERMISSIONS` | `true`/`false` to skip Claude permissions (overrides allowedTools) |
|
|
70
138
|
|
|
71
139
|
Example:
|
|
72
140
|
```bash
|
|
@@ -75,6 +143,7 @@ SF_REVIEW_ITERATIONS=3 sf "add feature X"
|
|
|
75
143
|
|
|
76
144
|
## Features
|
|
77
145
|
|
|
146
|
+
- **Automatic Permission Management**: Claude is pre-authorized to Edit, Read, and execute Bash commands by default - no constant permission prompts
|
|
78
147
|
- **Real-time Progress Visualization**: See exactly what Claude is doing with colorized, emoji-enhanced output
|
|
79
148
|
- š File reads in cyan
|
|
80
149
|
- āļø File writes in green
|
package/dist/claude.js
CHANGED
|
@@ -75,6 +75,9 @@ export async function runClaude(options, config) {
|
|
|
75
75
|
if (config.dangerouslySkipPermissions) {
|
|
76
76
|
args.push('--dangerously-skip-permissions');
|
|
77
77
|
}
|
|
78
|
+
else if (config.allowedTools) {
|
|
79
|
+
args.push('--allowedTools', config.allowedTools);
|
|
80
|
+
}
|
|
78
81
|
// Always pass -p for output and add streaming JSON output format
|
|
79
82
|
args.push('-p', '--output-format=stream-json', '--verbose');
|
|
80
83
|
if (options.continueConversation) {
|
package/dist/config.d.ts
CHANGED
|
@@ -6,8 +6,10 @@ export interface Config {
|
|
|
6
6
|
skipPush: boolean;
|
|
7
7
|
skipBranchManagement: boolean;
|
|
8
8
|
dangerouslySkipPermissions: boolean;
|
|
9
|
+
allowedTools?: string;
|
|
9
10
|
requirement: string;
|
|
10
11
|
adaptiveExecution: boolean;
|
|
12
|
+
implementationOnly: boolean;
|
|
11
13
|
}
|
|
12
14
|
export declare function loadConfigFromEnv(): Partial<Config>;
|
|
13
15
|
export declare function mergeConfig(envConfig: Partial<Config>, cliConfig: Partial<Config>): Config;
|
package/dist/config.js
CHANGED
|
@@ -19,10 +19,17 @@ export function loadConfigFromEnv() {
|
|
|
19
19
|
skipPush: parseBoolEnv(process.env.SF_SKIP_PUSH, false),
|
|
20
20
|
skipBranchManagement: parseBoolEnv(process.env.SF_SKIP_BRANCH_MANAGEMENT, false),
|
|
21
21
|
dangerouslySkipPermissions: parseBoolEnv(process.env.SF_DANGEROUSLY_SKIP_PERMISSIONS, false),
|
|
22
|
+
allowedTools: process.env.SF_ALLOWED_TOOLS || undefined,
|
|
22
23
|
adaptiveExecution: parseBoolEnv(process.env.SF_ADAPTIVE_EXECUTION, false),
|
|
24
|
+
implementationOnly: parseBoolEnv(process.env.SF_IMPLEMENTATION_ONLY, false),
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
27
|
export function mergeConfig(envConfig, cliConfig) {
|
|
28
|
+
const dangerouslySkipPermissions = cliConfig.dangerouslySkipPermissions ?? envConfig.dangerouslySkipPermissions ?? false;
|
|
29
|
+
// Set default allowedTools to "Edit,Read,Bash" unless dangerouslySkipPermissions is true
|
|
30
|
+
const allowedTools = dangerouslySkipPermissions
|
|
31
|
+
? undefined
|
|
32
|
+
: (cliConfig.allowedTools ?? envConfig.allowedTools ?? 'Edit,Read,Bash');
|
|
26
33
|
return {
|
|
27
34
|
reviewIterations: cliConfig.reviewIterations ?? envConfig.reviewIterations ?? DEFAULT_REVIEW_ITERATIONS,
|
|
28
35
|
dryRun: cliConfig.dryRun ?? envConfig.dryRun ?? false,
|
|
@@ -30,8 +37,10 @@ export function mergeConfig(envConfig, cliConfig) {
|
|
|
30
37
|
skipTests: cliConfig.skipTests ?? envConfig.skipTests ?? false,
|
|
31
38
|
skipPush: cliConfig.skipPush ?? envConfig.skipPush ?? false,
|
|
32
39
|
skipBranchManagement: cliConfig.skipBranchManagement ?? envConfig.skipBranchManagement ?? false,
|
|
33
|
-
dangerouslySkipPermissions
|
|
40
|
+
dangerouslySkipPermissions,
|
|
41
|
+
allowedTools,
|
|
34
42
|
requirement: cliConfig.requirement ?? '',
|
|
35
43
|
adaptiveExecution: cliConfig.adaptiveExecution ?? envConfig.adaptiveExecution ?? false,
|
|
44
|
+
implementationOnly: cliConfig.implementationOnly ?? envConfig.implementationOnly ?? false,
|
|
36
45
|
};
|
|
37
46
|
}
|
package/dist/index.js
CHANGED
|
@@ -47,8 +47,10 @@ program
|
|
|
47
47
|
.option('--skip-tests', 'Skip the testing step')
|
|
48
48
|
.option('--skip-push', 'Commit but do not push')
|
|
49
49
|
.option('--skip-branch-management', 'Skip smart branch management')
|
|
50
|
+
.option('--implementation-only', 'Run only: Implement ā Review ā SOLID (skips branch, tests, commit)')
|
|
50
51
|
.option('--log <file>', 'Log output to file')
|
|
51
52
|
.option('--dangerously-skip-permissions', 'Pass flag to claude to skip permission prompts')
|
|
53
|
+
.option('--allowedTools <tools>', 'Comma-separated list of allowed tools (default: "Edit,Read,Bash")')
|
|
52
54
|
.action(async (requirement, options) => {
|
|
53
55
|
// Check for updates (non-blocking, fails silently)
|
|
54
56
|
await checkForUpdates(pkg.name, pkg.version).catch(() => { });
|
|
@@ -67,9 +69,23 @@ program
|
|
|
67
69
|
skipBranchManagement: options.skipBranchManagement ?? undefined,
|
|
68
70
|
logFile: options.log ?? undefined,
|
|
69
71
|
dangerouslySkipPermissions: options.dangerouslySkipPermissions ?? undefined,
|
|
72
|
+
allowedTools: options.allowedTools ?? undefined,
|
|
70
73
|
adaptiveExecution: options.adaptive ?? undefined,
|
|
74
|
+
implementationOnly: options.implementationOnly ?? undefined,
|
|
71
75
|
};
|
|
72
76
|
const config = mergeConfig(envConfig, cliConfig);
|
|
77
|
+
// Handle implementation-only mode
|
|
78
|
+
if (config.implementationOnly) {
|
|
79
|
+
// Implementation-only mode automatically skips branch management and tests
|
|
80
|
+
config.skipBranchManagement = true;
|
|
81
|
+
config.skipTests = true;
|
|
82
|
+
// Warn if adaptive execution was explicitly requested but will be overridden
|
|
83
|
+
const adaptiveWasRequested = options.adaptive || process.env.SF_ADAPTIVE_EXECUTION === 'true';
|
|
84
|
+
if (config.adaptiveExecution && adaptiveWasRequested) {
|
|
85
|
+
console.log(chalk.yellow('ā Implementation-only mode overrides --adaptive flag'));
|
|
86
|
+
}
|
|
87
|
+
config.adaptiveExecution = false;
|
|
88
|
+
}
|
|
73
89
|
if (!config.requirement) {
|
|
74
90
|
console.error(chalk.red('Error:') + ' No requirement provided');
|
|
75
91
|
program.help();
|
package/dist/logger.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare function logHeader(config: {
|
|
|
6
6
|
reviewIterations: number;
|
|
7
7
|
dryRun: boolean;
|
|
8
8
|
dangerouslySkipPermissions: boolean;
|
|
9
|
+
allowedTools?: string;
|
|
10
|
+
implementationOnly: boolean;
|
|
9
11
|
}): void;
|
|
10
12
|
export declare function logSuccess(message: string): void;
|
|
11
13
|
export declare function logError(message: string): void;
|
package/dist/logger.js
CHANGED
|
@@ -52,12 +52,19 @@ export function logHeader(config) {
|
|
|
52
52
|
const authorLine = ' '.repeat(authorPadding) + author + ' '.repeat(BOX_WIDTH - authorPadding - author.length);
|
|
53
53
|
console.log(chalk.green('ā') + chalk.dim(authorLine) + chalk.green('ā'));
|
|
54
54
|
console.log(chalk.green(`ā ${line}ā£`));
|
|
55
|
-
|
|
55
|
+
let configLine = ` Reviews: ${config.reviewIterations} | Dry-run: ${config.dryRun}`;
|
|
56
|
+
if (config.implementationOnly) {
|
|
57
|
+
configLine += ' | Mode: implementation-only';
|
|
58
|
+
}
|
|
56
59
|
console.log(chalk.green('ā') + configLine.padEnd(BOX_WIDTH) + chalk.green('ā'));
|
|
57
60
|
if (config.dangerouslySkipPermissions) {
|
|
58
61
|
const permLine = ' ' + chalk.yellow('ā Skip permissions: enabled');
|
|
59
62
|
console.log(chalk.green('ā') + permLine + ' '.repeat(BOX_WIDTH - stripAnsi(permLine).length) + chalk.green('ā'));
|
|
60
63
|
}
|
|
64
|
+
else if (config.allowedTools) {
|
|
65
|
+
const toolsLine = ' ' + chalk.cyan(`š Allowed tools: ${config.allowedTools}`);
|
|
66
|
+
console.log(chalk.green('ā') + toolsLine + ' '.repeat(BOX_WIDTH - stripAnsi(toolsLine).length) + chalk.green('ā'));
|
|
67
|
+
}
|
|
61
68
|
console.log(chalk.green(`ā${line}ā`));
|
|
62
69
|
console.log();
|
|
63
70
|
}
|
package/dist/pipeline.js
CHANGED
|
@@ -1,7 +1,39 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { log, logHeader, setLogFile, logInfo } from './logger.js';
|
|
3
3
|
import { stepBranchManagement, stepImplement, stepSimplify, stepReview, stepSolidCleanCode, stepTest, stepCommit, stepChangelog, } from './steps/index.js';
|
|
4
|
+
const EXIT_CODE_FAILURE = 1;
|
|
5
|
+
const EXIT_CODE_INTERRUPT = 130;
|
|
4
6
|
let signalHandlersRegistered = false;
|
|
7
|
+
function exitWithError(message) {
|
|
8
|
+
console.log(chalk.red(`\n${message}`));
|
|
9
|
+
process.exit(EXIT_CODE_FAILURE);
|
|
10
|
+
}
|
|
11
|
+
function getSkipReason(implementationOnly, primaryReason, fallbackReason) {
|
|
12
|
+
return implementationOnly ? 'implementation-only mode' : primaryReason;
|
|
13
|
+
}
|
|
14
|
+
function determineSkipTestsReason(config, rec) {
|
|
15
|
+
if (config.implementationOnly)
|
|
16
|
+
return 'implementation-only mode';
|
|
17
|
+
if (rec?.skipTests)
|
|
18
|
+
return 'adaptive execution';
|
|
19
|
+
if (config.skipTests)
|
|
20
|
+
return '--skip-tests';
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function displayImplementationOnlyBanner() {
|
|
24
|
+
console.log(chalk.cyan('ā¶ Running in IMPLEMENTATION-ONLY mode'));
|
|
25
|
+
console.log(chalk.cyan('ā¶ Steps: Implement ā Review ā SOLID'));
|
|
26
|
+
console.log(chalk.dim('ā¶ Skipping: Branch Management, Simplify, Tests, Commit, Changelog\n'));
|
|
27
|
+
}
|
|
28
|
+
function displayCompletionMessage(implementationOnly) {
|
|
29
|
+
if (implementationOnly) {
|
|
30
|
+
console.log(chalk.green('\nā Implementation-only pipeline completed successfully'));
|
|
31
|
+
console.log(chalk.yellow('ā Changes are not committed - review and commit manually when ready\n'));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(chalk.green('\nā Pipeline completed successfully\n'));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
5
37
|
export async function runPipeline(config) {
|
|
6
38
|
// Setup logging
|
|
7
39
|
if (config.logFile) {
|
|
@@ -11,44 +43,54 @@ export async function runPipeline(config) {
|
|
|
11
43
|
if (!signalHandlersRegistered) {
|
|
12
44
|
process.on('SIGINT', () => {
|
|
13
45
|
console.log(chalk.red('\n\nPipeline interrupted'));
|
|
14
|
-
process.exit(
|
|
46
|
+
process.exit(EXIT_CODE_INTERRUPT);
|
|
15
47
|
});
|
|
16
48
|
process.on('SIGTERM', () => {
|
|
17
49
|
console.log(chalk.red('\n\nPipeline terminated'));
|
|
18
|
-
process.exit(
|
|
50
|
+
process.exit(EXIT_CODE_INTERRUPT);
|
|
19
51
|
});
|
|
20
52
|
signalHandlersRegistered = true;
|
|
21
53
|
}
|
|
22
54
|
// Display header
|
|
23
55
|
logHeader(config);
|
|
56
|
+
if (config.implementationOnly) {
|
|
57
|
+
displayImplementationOnlyBanner();
|
|
58
|
+
}
|
|
24
59
|
log(`Starting pipeline for: ${config.requirement}`);
|
|
25
|
-
// Step 1: Smart Branch Management
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
60
|
+
// Step 1: Smart Branch Management
|
|
61
|
+
let adaptive = null;
|
|
62
|
+
let rec = null;
|
|
63
|
+
const shouldSkipBranchManagement = config.implementationOnly || config.skipBranchManagement;
|
|
64
|
+
if (shouldSkipBranchManagement) {
|
|
65
|
+
const reason = getSkipReason(config.implementationOnly, '--skip-branch-management', '--skip-branch-management');
|
|
66
|
+
logInfo(`Branch management step skipped (${reason})`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const branchResult = await stepBranchManagement(config);
|
|
70
|
+
if (!branchResult.success) {
|
|
71
|
+
exitWithError('Branch management step failed. Exiting.');
|
|
72
|
+
}
|
|
73
|
+
adaptive = branchResult.adaptiveAnalysis;
|
|
74
|
+
rec = adaptive?.stepRecommendation;
|
|
75
|
+
}
|
|
34
76
|
// Step 2: Implement
|
|
35
77
|
const implSuccess = await stepImplement(config);
|
|
36
78
|
if (!implSuccess) {
|
|
37
|
-
|
|
38
|
-
process.exit(1);
|
|
79
|
+
exitWithError('Implementation step failed. Exiting.');
|
|
39
80
|
}
|
|
40
|
-
// Step
|
|
41
|
-
|
|
42
|
-
|
|
81
|
+
// Step 3: Simplify
|
|
82
|
+
const shouldSkipSimplify = config.implementationOnly || rec?.skipSimplify;
|
|
83
|
+
if (shouldSkipSimplify) {
|
|
84
|
+
const reason = getSkipReason(config.implementationOnly, 'adaptive execution', 'adaptive execution');
|
|
85
|
+
logInfo(`Simplify step skipped (${reason})`);
|
|
43
86
|
}
|
|
44
87
|
else {
|
|
45
88
|
const simplifySuccess = await stepSimplify(config);
|
|
46
89
|
if (!simplifySuccess) {
|
|
47
|
-
|
|
48
|
-
process.exit(1);
|
|
90
|
+
exitWithError('Simplification step failed. Exiting.');
|
|
49
91
|
}
|
|
50
92
|
}
|
|
51
|
-
// Step 5: Review loop
|
|
93
|
+
// Step 5: Review loop
|
|
52
94
|
if (rec?.skipReview) {
|
|
53
95
|
logInfo('Review step skipped (adaptive execution)');
|
|
54
96
|
}
|
|
@@ -57,61 +99,56 @@ export async function runPipeline(config) {
|
|
|
57
99
|
for (let i = 1; i <= reviewIterations; i++) {
|
|
58
100
|
const reviewResult = await stepReview(i, config, rec?.reviewDepth);
|
|
59
101
|
if (!reviewResult.success) {
|
|
60
|
-
|
|
61
|
-
process.exit(1);
|
|
102
|
+
exitWithError('Review step failed. Exiting.');
|
|
62
103
|
}
|
|
63
|
-
// Skip remaining reviews if no issues were found
|
|
64
104
|
if (reviewResult.noIssuesFound) {
|
|
65
105
|
console.log(chalk.green('\nā Code review passed - no issues found, skipping remaining reviews'));
|
|
66
106
|
break;
|
|
67
107
|
}
|
|
68
108
|
}
|
|
69
109
|
}
|
|
70
|
-
// Step 6: SOLID & Clean Code
|
|
110
|
+
// Step 6: SOLID & Clean Code
|
|
71
111
|
if (rec?.skipSolid) {
|
|
72
112
|
logInfo('SOLID review step skipped (adaptive execution)');
|
|
73
113
|
}
|
|
74
114
|
else {
|
|
75
115
|
const solidSuccess = await stepSolidCleanCode(config);
|
|
76
116
|
if (!solidSuccess) {
|
|
77
|
-
|
|
78
|
-
process.exit(1);
|
|
117
|
+
exitWithError('SOLID review step failed. Exiting.');
|
|
79
118
|
}
|
|
80
119
|
}
|
|
81
|
-
// Step 7: Test
|
|
82
|
-
|
|
83
|
-
if (rec?.skipTests) {
|
|
84
|
-
skipTestsReason = 'adaptive execution';
|
|
85
|
-
}
|
|
86
|
-
else if (config.skipTests) {
|
|
87
|
-
skipTestsReason = '--skip-tests';
|
|
88
|
-
}
|
|
120
|
+
// Step 7: Test
|
|
121
|
+
const skipTestsReason = determineSkipTestsReason(config, rec);
|
|
89
122
|
if (skipTestsReason) {
|
|
90
123
|
logInfo(`Test step skipped (${skipTestsReason})`);
|
|
91
124
|
}
|
|
92
125
|
else {
|
|
93
126
|
const testSuccess = await stepTest(config);
|
|
94
127
|
if (!testSuccess) {
|
|
95
|
-
|
|
96
|
-
process.exit(1);
|
|
128
|
+
exitWithError('Test step failed. Exiting.');
|
|
97
129
|
}
|
|
98
130
|
}
|
|
99
131
|
// Step 8: Commit
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
132
|
+
if (config.implementationOnly) {
|
|
133
|
+
logInfo('Commit step skipped (implementation-only mode)');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const commitSuccess = await stepCommit(config);
|
|
137
|
+
if (!commitSuccess) {
|
|
138
|
+
exitWithError('Commit step failed. Exiting.');
|
|
139
|
+
}
|
|
104
140
|
}
|
|
105
|
-
// Step 9: Changelog
|
|
106
|
-
|
|
107
|
-
|
|
141
|
+
// Step 9: Changelog
|
|
142
|
+
const shouldSkipChangelog = config.implementationOnly || rec?.skipChangelog;
|
|
143
|
+
if (shouldSkipChangelog) {
|
|
144
|
+
const reason = getSkipReason(config.implementationOnly, 'adaptive execution', 'adaptive execution');
|
|
145
|
+
logInfo(`Changelog step skipped (${reason})`);
|
|
108
146
|
}
|
|
109
147
|
else {
|
|
110
148
|
const changelogSuccess = await stepChangelog(config);
|
|
111
149
|
if (!changelogSuccess) {
|
|
112
|
-
|
|
113
|
-
process.exit(1);
|
|
150
|
+
exitWithError('Changelog step failed. Exiting.');
|
|
114
151
|
}
|
|
115
152
|
}
|
|
116
|
-
|
|
153
|
+
displayCompletionMessage(config.implementationOnly);
|
|
117
154
|
}
|
package/package.json
CHANGED