software-engineer 0.1.13 → 0.1.16

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/claude.js CHANGED
@@ -21,29 +21,15 @@ export async function runClaude(options, config) {
21
21
  }
22
22
  logInfo('Calling Claude...');
23
23
  return new Promise((resolve) => {
24
- let capturedOutput = '';
25
24
  // Spawn Claude using child_process
26
- // Use 'inherit' for stdin to allow interactive input
27
- // Use 'pipe' for stdout/stderr to capture output while passing through
25
+ // Use 'inherit' for all stdio to allow Claude's interactive UI to work properly
26
+ // Claude CLI requires a TTY for its rich terminal features (spinners, progress, etc.)
27
+ // Piping stdout/stderr causes Claude to detect non-TTY and buffer/disable output
28
28
  const child = spawn('claude', args, {
29
29
  cwd: process.cwd(),
30
30
  env: process.env,
31
- stdio: ['inherit', 'pipe', 'pipe'],
31
+ stdio: 'inherit',
32
32
  });
33
- // Capture and pass through stdout
34
- if (child.stdout) {
35
- child.stdout.on('data', (data) => {
36
- const text = data.toString();
37
- process.stdout.write(text);
38
- capturedOutput += text;
39
- });
40
- }
41
- // Capture and pass through stderr
42
- if (child.stderr) {
43
- child.stderr.on('data', (data) => {
44
- process.stderr.write(data.toString());
45
- });
46
- }
47
33
  // Handle process exit
48
34
  child.on('close', (exitCode) => {
49
35
  if (exitCode === EXIT_INTERRUPTED || exitCode === 2) {
@@ -52,11 +38,11 @@ export async function runClaude(options, config) {
52
38
  }
53
39
  else if (exitCode === EXIT_SUCCESS) {
54
40
  logSuccess('Claude completed');
55
- resolve({ success: true, output: capturedOutput });
41
+ resolve({ success: true, output: '' });
56
42
  }
57
43
  else {
58
44
  logError(`Claude exited with code ${exitCode}`);
59
- resolve({ success: false, output: capturedOutput });
45
+ resolve({ success: false, output: '' });
60
46
  }
61
47
  });
62
48
  // Handle spawn errors
package/dist/pipeline.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { log, logHeader, setLogFile, logInfo } from './logger.js';
3
- import { stepBranchManagement, stepImplement, stepSimplify, stepReview, stepSolidCleanCode, stepTest, stepCommit, stepChangelog, } from './steps/index.js';
3
+ import { stepBranchManagement, stepUnderstandCodebase, stepImplement, stepSimplify, stepReview, stepSolidCleanCode, stepTest, stepCommit, stepChangelog, } from './steps/index.js';
4
4
  let signalHandlersRegistered = false;
5
5
  export async function runPipeline(config) {
6
6
  // Setup logging
@@ -31,13 +31,19 @@ export async function runPipeline(config) {
31
31
  // Extract adaptive analysis for step decisions
32
32
  const adaptive = branchResult.adaptiveAnalysis;
33
33
  const rec = adaptive?.stepRecommendation;
34
- // Step 2: Implement
34
+ // Step 2: Understand Codebase
35
+ const understandSuccess = await stepUnderstandCodebase(config);
36
+ if (!understandSuccess) {
37
+ console.log(chalk.red('\nUnderstand codebase step failed. Exiting.'));
38
+ process.exit(1);
39
+ }
40
+ // Step 3: Implement
35
41
  const implSuccess = await stepImplement(config);
36
42
  if (!implSuccess) {
37
43
  console.log(chalk.red('\nImplementation step failed. Exiting.'));
38
44
  process.exit(1);
39
45
  }
40
- // Step 3: Simplify (can be skipped by adaptive execution)
46
+ // Step 4: Simplify (can be skipped by adaptive execution)
41
47
  if (rec?.skipSimplify) {
42
48
  logInfo('Simplify step skipped (adaptive execution)');
43
49
  }
@@ -48,7 +54,7 @@ export async function runPipeline(config) {
48
54
  process.exit(1);
49
55
  }
50
56
  }
51
- // Step 4: Review loop (can be skipped or adjusted by adaptive execution)
57
+ // Step 5: Review loop (can be skipped or adjusted by adaptive execution)
52
58
  if (rec?.skipReview) {
53
59
  logInfo('Review step skipped (adaptive execution)');
54
60
  }
@@ -67,7 +73,7 @@ export async function runPipeline(config) {
67
73
  }
68
74
  }
69
75
  }
70
- // Step 5: SOLID & Clean Code (can be skipped by adaptive execution)
76
+ // Step 6: SOLID & Clean Code (can be skipped by adaptive execution)
71
77
  if (rec?.skipSolid) {
72
78
  logInfo('SOLID review step skipped (adaptive execution)');
73
79
  }
@@ -78,8 +84,14 @@ export async function runPipeline(config) {
78
84
  process.exit(1);
79
85
  }
80
86
  }
81
- // Step 6: Test (can be skipped by adaptive execution or CLI flag)
82
- const skipTestsReason = rec?.skipTests ? 'adaptive execution' : config.skipTests ? '--skip-tests' : null;
87
+ // Step 7: Test (can be skipped by adaptive execution or CLI flag)
88
+ let skipTestsReason = null;
89
+ if (rec?.skipTests) {
90
+ skipTestsReason = 'adaptive execution';
91
+ }
92
+ else if (config.skipTests) {
93
+ skipTestsReason = '--skip-tests';
94
+ }
83
95
  if (skipTestsReason) {
84
96
  logInfo(`Test step skipped (${skipTestsReason})`);
85
97
  }
@@ -90,13 +102,13 @@ export async function runPipeline(config) {
90
102
  process.exit(1);
91
103
  }
92
104
  }
93
- // Step 7: Commit
105
+ // Step 8: Commit
94
106
  const commitSuccess = await stepCommit(config);
95
107
  if (!commitSuccess) {
96
108
  console.log(chalk.red('\nCommit step failed. Exiting.'));
97
109
  process.exit(1);
98
110
  }
99
- // Step 8: Changelog (can be skipped by adaptive execution)
111
+ // Step 9: Changelog (can be skipped by adaptive execution)
100
112
  if (rec?.skipChangelog) {
101
113
  logInfo('Changelog step skipped (adaptive execution)');
102
114
  }
@@ -46,7 +46,7 @@ function branchMatchesRequirement(currentBranch, analysis) {
46
46
  return overlap || (prefixMatches && suggestedKeywords.length === 0);
47
47
  }
48
48
  export async function stepBranchManagement(config) {
49
- logStep('1/8', 'SMART BRANCH MANAGEMENT');
49
+ logStep('1/9', 'SMART BRANCH MANAGEMENT');
50
50
  const adaptiveAnalysis = config.adaptiveExecution ? await performAdaptiveAnalysis(config) : null;
51
51
  if (config.skipBranchManagement) {
52
52
  logInfo('Branch management skipped (--skip-branch-management)');
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepChangelog(config) {
4
- logStep('8/8', 'UPDATE CHANGELOG');
4
+ logStep('9/9', 'UPDATE CHANGELOG');
5
5
  const prompt = `Update CHANGELOG.md:
6
6
 
7
7
  ## Format (Keep a Changelog):
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepCommit(config) {
4
- logStep('7/8', 'COMMIT CHANGES');
4
+ logStep('8/9', 'COMMIT CHANGES');
5
5
  const pushInstruction = config.skipPush ? '' : 'Then push to remote.';
6
6
  const prompt = `Commit the changes:
7
7
 
@@ -1,15 +1,14 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepImplement(config) {
4
- logStep('2/8', 'IMPLEMENT REQUIREMENT');
4
+ logStep('3/9', 'IMPLEMENT REQUIREMENT');
5
5
  const prompt = `${config.requirement}
6
6
 
7
7
  ## Implementation Guidelines:
8
- - Understand the existing codebase structure first
9
8
  - Write clean, idiomatic code following project conventions
10
9
  - Handle edge cases and errors appropriately
11
10
  - Add necessary comments for complex logic
12
- - Keep changes focused and minimal`;
13
- const result = await runClaude({ prompt }, config);
11
+ - Keep changes focused and minimal. Once the work is completed, exit.`;
12
+ const result = await runClaude({ prompt, continueConversation: true }, config);
14
13
  return result.success;
15
14
  }
@@ -1,4 +1,5 @@
1
1
  export { stepBranchManagement, type BranchResult } from './branchManagement.js';
2
+ export { stepUnderstandCodebase } from './understand.js';
2
3
  export { stepImplement } from './implement.js';
3
4
  export { stepSimplify } from './simplify.js';
4
5
  export { stepReview, type ReviewResult, type ReviewDepth } from './review.js';
@@ -1,4 +1,5 @@
1
1
  export { stepBranchManagement } from './branchManagement.js';
2
+ export { stepUnderstandCodebase } from './understand.js';
2
3
  export { stepImplement } from './implement.js';
3
4
  export { stepSimplify } from './simplify.js';
4
5
  export { stepReview } from './review.js';
@@ -60,7 +60,7 @@ function getPromptForDepth(depth) {
60
60
  }
61
61
  export async function stepReview(iteration, config, depth = 'standard') {
62
62
  const depthLabel = depth !== 'standard' ? ` [${depth}]` : '';
63
- logStep('4/8', `CODE REVIEW (Round ${iteration}/${config.reviewIterations})${depthLabel}`);
63
+ logStep('5/9', `CODE REVIEW (Round ${iteration}/${config.reviewIterations})${depthLabel}`);
64
64
  const prompt = getPromptForDepth(depth);
65
65
  const result = await runClaude({ prompt, continueConversation: true }, config);
66
66
  const noIssuesFound = result.success && detectNoIssues(result.output);
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepSimplify(config) {
4
- logStep('3/8', 'CODE SIMPLIFICATION');
4
+ logStep('4/9', 'CODE SIMPLIFICATION');
5
5
  const prompt = `Refine the recently modified code for clarity, consistency, and maintainability while preserving all functionality.
6
6
 
7
7
  ## Core Principles:
@@ -1,7 +1,7 @@
1
1
  import { logStep } from '../logger.js';
2
2
  import { runClaude } from '../claude.js';
3
3
  export async function stepSolidCleanCode(config) {
4
- logStep('5/8', 'SOLID PRINCIPLES & CLEAN CODE');
4
+ logStep('6/9', 'SOLID PRINCIPLES & CLEAN CODE');
5
5
  const prompt = `Review the code for SOLID principles and Clean Code compliance:
6
6
 
7
7
  ## SOLID Principles:
@@ -2,7 +2,7 @@ import chalk from 'chalk';
2
2
  import { logStep } from '../logger.js';
3
3
  import { runClaude } from '../claude.js';
4
4
  export async function stepTest(config) {
5
- logStep('6/8', 'TESTING');
5
+ logStep('7/9', 'TESTING');
6
6
  if (config.skipTests) {
7
7
  console.log(chalk.yellow('[SKIPPED]') + ' Testing step skipped via configuration');
8
8
  return true;
@@ -0,0 +1,2 @@
1
+ import type { Config } from '../config.js';
2
+ export declare function stepUnderstandCodebase(config: Config): Promise<boolean>;
@@ -0,0 +1,100 @@
1
+ import { logStep } from '../logger.js';
2
+ import { runClaude } from '../claude.js';
3
+ const UNDERSTAND_CODEBASE_PROMPT = `Goal
4
+ Build an internal map of the codebase. Do not change code. Do not refactor. Do not optimize.
5
+
6
+ Operating mode
7
+ Static analysis first. Minimal assumptions. Prefer certainty over completeness.
8
+
9
+ Required steps
10
+
11
+ 1. Detect codebase type
12
+
13
+ * Language(s)
14
+ * Runtime
15
+ * Frameworks
16
+ * Monorepo or single service
17
+
18
+ 2. Identify execution roots
19
+
20
+ * Primary entry files
21
+ * CLI commands
22
+ * Server startup paths
23
+ * Test runners
24
+
25
+ 3. Build directory graph
26
+
27
+ * Top level folders
28
+ * Purpose of each folder
29
+ * Ownership boundaries if visible
30
+
31
+ 4. Dependency flow analysis
32
+
33
+ * Module import graph
34
+ * Direction of dependencies
35
+ * Shared utilities vs feature code
36
+
37
+ 5. Architecture inference
38
+
39
+ * Architectural style if evident
40
+ * Layer boundaries
41
+ * Cross layer violations
42
+
43
+ 6. State and data flow
44
+
45
+ * Where state lives
46
+ * How data moves between modules
47
+ * Persistence boundaries
48
+
49
+ 7. External interfaces
50
+
51
+ * APIs exposed
52
+ * APIs consumed
53
+ * Databases, queues, filesystems
54
+
55
+ 8. Configuration and environment
56
+
57
+ * Config files
58
+ * Environment variables
59
+ * Feature flags
60
+
61
+ 9. Change impact map
62
+
63
+ * High blast radius files
64
+ * Core abstractions
65
+ * Unsafe modification zones
66
+
67
+ 10. Gaps and unknowns
68
+
69
+ * Missing docs
70
+ * Ambiguous responsibilities
71
+ * Implicit behavior
72
+
73
+ Output format
74
+
75
+ * Use structured bullet points
76
+ * Use short phrases, not prose
77
+ * Use file paths when referencing code
78
+ * Flag assumptions explicitly
79
+ * End with a one page mental model of the system
80
+
81
+ Constraints
82
+
83
+ * No code edits
84
+ * No speculative refactors
85
+ * No style commentary
86
+ * No opinions unless clearly labeled as inference
87
+
88
+ Primary objective
89
+ Enable safe future modifications by maximizing structural understanding.`;
90
+ export async function stepUnderstandCodebase(config) {
91
+ logStep('2/9', 'UNDERSTAND CODEBASE');
92
+ const prompt = `${UNDERSTAND_CODEBASE_PROMPT}
93
+
94
+ Context: I need to understand this codebase to implement the following requirement:
95
+ ${config.requirement}
96
+
97
+ Focus your analysis on areas most relevant to this requirement while still building a complete mental model.`;
98
+ const result = await runClaude({ prompt }, config);
99
+ return result.success;
100
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "software-engineer",
3
- "version": "0.1.13",
3
+ "version": "0.1.16",
4
4
  "description": "CLI that automates the full dev workflow with Claude AI - implement, review, test, and commit code with a single command",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",