@kosuke-ai/cli 0.0.33 ā 0.0.34
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/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/kosuke/commands/build.d.ts +8 -4
- package/dist/kosuke/commands/build.d.ts.map +1 -1
- package/dist/kosuke/commands/build.js +75 -31
- package/dist/kosuke/commands/build.js.map +1 -1
- package/dist/kosuke/commands/getcode.d.ts.map +1 -1
- package/dist/kosuke/commands/getcode.js +1 -0
- package/dist/kosuke/commands/getcode.js.map +1 -1
- package/dist/kosuke/commands/lint.d.ts.map +1 -1
- package/dist/kosuke/commands/lint.js +7 -39
- package/dist/kosuke/commands/lint.js.map +1 -1
- package/dist/kosuke/commands/review.d.ts.map +1 -1
- package/dist/kosuke/commands/review.js +34 -34
- package/dist/kosuke/commands/review.js.map +1 -1
- package/dist/kosuke/commands/ship.d.ts +3 -3
- package/dist/kosuke/commands/ship.d.ts.map +1 -1
- package/dist/kosuke/commands/ship.js +51 -267
- package/dist/kosuke/commands/ship.js.map +1 -1
- package/dist/kosuke/commands/sync-rules.d.ts.map +1 -1
- package/dist/kosuke/commands/sync-rules.js +2 -0
- package/dist/kosuke/commands/sync-rules.js.map +1 -1
- package/dist/kosuke/commands/test.d.ts.map +1 -1
- package/dist/kosuke/commands/test.js +1 -23
- package/dist/kosuke/commands/test.js.map +1 -1
- package/dist/kosuke/types.d.ts +9 -5
- package/dist/kosuke/types.d.ts.map +1 -1
- package/dist/kosuke/utils/claude-agent.d.ts +2 -1
- package/dist/kosuke/utils/claude-agent.d.ts.map +1 -1
- package/dist/kosuke/utils/claude-agent.js +47 -10
- package/dist/kosuke/utils/claude-agent.js.map +1 -1
- package/dist/kosuke/utils/tickets-manager.d.ts +28 -0
- package/dist/kosuke/utils/tickets-manager.d.ts.map +1 -0
- package/dist/kosuke/utils/tickets-manager.js +54 -0
- package/dist/kosuke/utils/tickets-manager.js.map +1 -0
- package/dist/package.json +1 -1
- package/package.json +1 -1
|
@@ -9,35 +9,36 @@
|
|
|
9
9
|
* Usage:
|
|
10
10
|
* kosuke review # Review current git diff
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
13
|
-
import { join } from 'path';
|
|
14
|
-
import { runAgent, formatCostBreakdown } from '../utils/claude-agent.js';
|
|
12
|
+
import { formatCostBreakdown, runAgent } from '../utils/claude-agent.js';
|
|
15
13
|
import { getGitDiff, hasUncommittedChanges } from '../utils/git.js';
|
|
16
|
-
import { runComprehensiveLinting } from '../utils/validator.js';
|
|
17
14
|
import { logger, setupCancellationHandler } from '../utils/logger.js';
|
|
18
|
-
|
|
19
|
-
* Load CLAUDE.md rules
|
|
20
|
-
*/
|
|
21
|
-
function loadClaudeRules(cwd = process.cwd()) {
|
|
22
|
-
const claudePath = join(cwd, 'CLAUDE.md');
|
|
23
|
-
if (!existsSync(claudePath)) {
|
|
24
|
-
throw new Error(`CLAUDE.md not found in workspace root.\n` +
|
|
25
|
-
`Please ensure CLAUDE.md exists at: ${claudePath}`);
|
|
26
|
-
}
|
|
27
|
-
return readFileSync(claudePath, 'utf-8');
|
|
28
|
-
}
|
|
15
|
+
import { runComprehensiveLinting } from '../utils/validator.js';
|
|
29
16
|
/**
|
|
30
17
|
* Build system prompt for code review (git diff only)
|
|
31
18
|
*/
|
|
32
|
-
function buildReviewSystemPrompt(
|
|
33
|
-
|
|
19
|
+
function buildReviewSystemPrompt(gitDiff, context) {
|
|
20
|
+
const ticketContextSection = context
|
|
21
|
+
? `
|
|
22
|
+
**š« Ticket Being Implemented:**
|
|
23
|
+
- ID: ${context.ticketId}
|
|
24
|
+
- Title: ${context.ticketTitle}
|
|
25
|
+
- Description:
|
|
26
|
+
${context.ticketDescription}
|
|
34
27
|
|
|
35
|
-
**
|
|
36
|
-
|
|
28
|
+
**Ticket-Specific Review Requirements:**
|
|
29
|
+
- Verify changes align with the ticket description above
|
|
30
|
+
- Ensure all requirements from the ticket are addressed in the diff
|
|
31
|
+
- Check that the implementation matches the intended feature/fix
|
|
32
|
+
- Look for any obvious missing functionality described in the ticket
|
|
33
|
+
- Fix any misalignments between the code changes and ticket requirements
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
`
|
|
36
|
+
: '';
|
|
37
|
+
return `You are a senior code reviewer conducting a code quality review of recent changes.
|
|
40
38
|
|
|
39
|
+
**Your Task:**
|
|
40
|
+
Review the git diff below for compliance with the project's coding guidelines (CLAUDE.md will be loaded automatically).
|
|
41
|
+
${ticketContextSection}
|
|
41
42
|
**Git Diff to Review:**
|
|
42
43
|
\`\`\`diff
|
|
43
44
|
${gitDiff}
|
|
@@ -77,13 +78,16 @@ Review the changes shown in the diff and fix any issues you find.`;
|
|
|
77
78
|
/**
|
|
78
79
|
* Core review logic - reviews git diff only
|
|
79
80
|
*/
|
|
80
|
-
export async function reviewCore(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
export async function reviewCore(options = {}) {
|
|
82
|
+
const cwd = options.directory || process.cwd();
|
|
83
|
+
const { context } = options;
|
|
84
|
+
// Log ticket context if provided
|
|
85
|
+
if (context) {
|
|
86
|
+
console.log(`š« Reviewing changes for: ${context.ticketId} - ${context.ticketTitle}\n`);
|
|
87
|
+
}
|
|
84
88
|
// 1. Check for uncommitted changes
|
|
85
89
|
console.log('š Checking for uncommitted changes...');
|
|
86
|
-
const hasChanges = await hasUncommittedChanges();
|
|
90
|
+
const hasChanges = await hasUncommittedChanges(cwd);
|
|
87
91
|
if (!hasChanges) {
|
|
88
92
|
console.log(' ā¹ļø No uncommitted changes found. Nothing to review.\n');
|
|
89
93
|
return {
|
|
@@ -102,7 +106,7 @@ options = {}) {
|
|
|
102
106
|
console.log(' ā
Found uncommitted changes\n');
|
|
103
107
|
// 2. Get git diff
|
|
104
108
|
console.log('š Getting git diff...');
|
|
105
|
-
const gitDiff = await getGitDiff();
|
|
109
|
+
const gitDiff = await getGitDiff(cwd);
|
|
106
110
|
if (!gitDiff || gitDiff.trim().length === 0) {
|
|
107
111
|
console.log(' ā¹ļø No diff available. Nothing to review.\n');
|
|
108
112
|
return {
|
|
@@ -119,15 +123,11 @@ options = {}) {
|
|
|
119
123
|
};
|
|
120
124
|
}
|
|
121
125
|
console.log(` ā
Got diff (${gitDiff.length} characters)\n`);
|
|
122
|
-
// 3.
|
|
123
|
-
console.log('š Loading CLAUDE.md rules...');
|
|
124
|
-
const claudeRules = loadClaudeRules(cwd);
|
|
125
|
-
console.log(` ā
Loaded rules (${claudeRules.length} characters)\n`);
|
|
126
|
-
// 4. Review phase
|
|
126
|
+
// 3. Review phase
|
|
127
127
|
console.log(`\n${'='.repeat(60)}`);
|
|
128
128
|
console.log(`š Phase 1: Code Review of Git Diff`);
|
|
129
129
|
console.log(`${'='.repeat(60)}\n`);
|
|
130
|
-
const systemPrompt = buildReviewSystemPrompt(
|
|
130
|
+
const systemPrompt = buildReviewSystemPrompt(gitDiff, context);
|
|
131
131
|
const reviewResult = await runAgent('Review the git diff for compliance with CLAUDE.md rules and fix all issues found', {
|
|
132
132
|
systemPrompt,
|
|
133
133
|
cwd,
|
|
@@ -142,7 +142,7 @@ options = {}) {
|
|
|
142
142
|
console.log(`\n${'='.repeat(60)}`);
|
|
143
143
|
console.log(`š§ Phase 2: Linting & Quality Checks`);
|
|
144
144
|
console.log(`${'='.repeat(60)}\n`);
|
|
145
|
-
const lintResult = await runComprehensiveLinting();
|
|
145
|
+
const lintResult = await runComprehensiveLinting(cwd);
|
|
146
146
|
console.log(`\nā
Linting completed (${lintResult.fixCount} additional fixes applied)`);
|
|
147
147
|
return {
|
|
148
148
|
success: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../../kosuke/commands/review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../../kosuke/commands/review.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Ship command - Implement a ticket from tickets.json
|
|
3
3
|
*
|
|
4
4
|
* This command takes a ticket ID, implements it following CLAUDE.md rules,
|
|
5
|
-
* runs linting
|
|
5
|
+
* runs linting, and optionally performs code review with ticket context.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* kosuke ship --ticket=SCHEMA-1 # Implement ticket (local only)
|
|
9
|
-
* kosuke ship --ticket=BACKEND-2 --review # Implement with review
|
|
9
|
+
* kosuke ship --ticket=BACKEND-2 --review # Implement with code review
|
|
10
10
|
* kosuke ship --ticket=FRONTEND-1 --commit # Implement and commit to current branch
|
|
11
|
-
* kosuke ship --ticket=BACKEND-3 --
|
|
11
|
+
* kosuke ship --ticket=BACKEND-3 --review --commit # Implement, review, then commit
|
|
12
12
|
* kosuke ship --ticket=FRONTEND-1 --test # Implement and run tests
|
|
13
13
|
* kosuke ship --ticket=SCHEMA-1 --tickets=path/to/tickets.json
|
|
14
14
|
* kosuke ship --ticket=SCHEMA-1 --db-url=postgres://user:pass@host:5432/db
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ship.d.ts","sourceRoot":"","sources":["../../../kosuke/commands/ship.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAU,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ship.d.ts","sourceRoot":"","sources":["../../../kosuke/commands/ship.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAU,MAAM,aAAa,CAAC;AA8DnE;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA6PxE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiErE"}
|
|
@@ -2,88 +2,30 @@
|
|
|
2
2
|
* Ship command - Implement a ticket from tickets.json
|
|
3
3
|
*
|
|
4
4
|
* This command takes a ticket ID, implements it following CLAUDE.md rules,
|
|
5
|
-
* runs linting
|
|
5
|
+
* runs linting, and optionally performs code review with ticket context.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* kosuke ship --ticket=SCHEMA-1 # Implement ticket (local only)
|
|
9
|
-
* kosuke ship --ticket=BACKEND-2 --review # Implement with review
|
|
9
|
+
* kosuke ship --ticket=BACKEND-2 --review # Implement with code review
|
|
10
10
|
* kosuke ship --ticket=FRONTEND-1 --commit # Implement and commit to current branch
|
|
11
|
-
* kosuke ship --ticket=BACKEND-3 --
|
|
11
|
+
* kosuke ship --ticket=BACKEND-3 --review --commit # Implement, review, then commit
|
|
12
12
|
* kosuke ship --ticket=FRONTEND-1 --test # Implement and run tests
|
|
13
13
|
* kosuke ship --ticket=SCHEMA-1 --tickets=path/to/tickets.json
|
|
14
14
|
* kosuke ship --ticket=SCHEMA-1 --db-url=postgres://user:pass@host:5432/db
|
|
15
15
|
*/
|
|
16
|
-
import { existsSync,
|
|
16
|
+
import { existsSync, statSync } from 'fs';
|
|
17
17
|
import { join, resolve } from 'path';
|
|
18
18
|
import { formatCostBreakdown, runAgent } from '../utils/claude-agent.js';
|
|
19
19
|
import { commitAndPushCurrentBranch } from '../utils/git.js';
|
|
20
20
|
import { logger, setupCancellationHandler } from '../utils/logger.js';
|
|
21
|
-
import {
|
|
21
|
+
import { findTicket, loadTicketsFile, updateTicketStatus } from '../utils/tickets-manager.js';
|
|
22
22
|
import { runComprehensiveLinting } from '../utils/validator.js';
|
|
23
23
|
import { reviewCore } from './review.js';
|
|
24
24
|
import { testCore } from './test.js';
|
|
25
|
-
/**
|
|
26
|
-
* Load tickets from file
|
|
27
|
-
*/
|
|
28
|
-
function loadTicketsFile(ticketsPath) {
|
|
29
|
-
if (!existsSync(ticketsPath)) {
|
|
30
|
-
throw new Error(`Tickets file not found: ${ticketsPath}\n` +
|
|
31
|
-
`Please generate tickets first using: kosuke tickets`);
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const content = readFileSync(ticketsPath, 'utf-8');
|
|
35
|
-
return JSON.parse(content);
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
throw new Error(`Failed to parse tickets file: ${error instanceof Error ? error.message : String(error)}`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Save tickets to file
|
|
43
|
-
*/
|
|
44
|
-
function saveTicketsFile(ticketsPath, ticketsData) {
|
|
45
|
-
writeFileSync(ticketsPath, JSON.stringify(ticketsData, null, 2), 'utf-8');
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Find ticket by ID
|
|
49
|
-
*/
|
|
50
|
-
function findTicket(ticketsData, ticketId) {
|
|
51
|
-
return ticketsData.tickets.find((t) => t.id === ticketId);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Update ticket status in file
|
|
55
|
-
*/
|
|
56
|
-
function updateTicketStatus(ticketsPath, ticketId, status, error) {
|
|
57
|
-
const ticketsData = loadTicketsFile(ticketsPath);
|
|
58
|
-
const ticket = findTicket(ticketsData, ticketId);
|
|
59
|
-
if (!ticket) {
|
|
60
|
-
console.warn(`ā ļø Ticket ${ticketId} not found, skipping status update`);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
ticket.status = status;
|
|
64
|
-
if (error) {
|
|
65
|
-
ticket.error = error;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
delete ticket.error;
|
|
69
|
-
}
|
|
70
|
-
saveTicketsFile(ticketsPath, ticketsData);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Load CLAUDE.md rules
|
|
74
|
-
*/
|
|
75
|
-
function loadClaudeRules(cwd = process.cwd()) {
|
|
76
|
-
const claudePath = join(cwd, 'CLAUDE.md');
|
|
77
|
-
if (!existsSync(claudePath)) {
|
|
78
|
-
throw new Error(`CLAUDE.md not found in workspace root.\n` +
|
|
79
|
-
`Please ensure CLAUDE.md exists at: ${claudePath}`);
|
|
80
|
-
}
|
|
81
|
-
return readFileSync(claudePath, 'utf-8');
|
|
82
|
-
}
|
|
83
25
|
/**
|
|
84
26
|
* Build system prompt for ticket implementation
|
|
85
27
|
*/
|
|
86
|
-
function buildImplementationPrompt(ticket,
|
|
28
|
+
function buildImplementationPrompt(ticket, dbUrl) {
|
|
87
29
|
const isSchemaTicket = ticket.id.toUpperCase().startsWith('SCHEMA-');
|
|
88
30
|
const schemaMigrationInstructions = isSchemaTicket
|
|
89
31
|
? `
|
|
@@ -91,21 +33,20 @@ function buildImplementationPrompt(ticket, claudeRules, dbUrl) {
|
|
|
91
33
|
**Database Schema Changes (CRITICAL FOR SCHEMA TICKETS):**
|
|
92
34
|
This is a SCHEMA ticket. After making changes to database schema files:
|
|
93
35
|
1. Run \`bun run db:generate\` to generate Drizzle migrations
|
|
94
|
-
2. Run \`POSTGRES_URL="${dbUrl}" bun run db:migrate\` to apply migrations to the database
|
|
36
|
+
2. **CRITICAL**: Run \`POSTGRES_URL="${dbUrl}" bun run db:migrate\` to apply migrations to the database
|
|
37
|
+
ā ļø **MIGRATIONS MUST BE APPLIED AFTER GENERATION** - Generating migrations alone does NOT update the database!
|
|
38
|
+
ā ļø The database schema will NOT change until you run \`db:migrate\` to apply the generated migrations
|
|
39
|
+
ā ļø Skipping this step will cause runtime errors when the app expects the new schema
|
|
95
40
|
3. Run \`POSTGRES_URL="${dbUrl}" bun run db:seed\` to seed the database with initial data
|
|
96
41
|
4. Verify migration files were created in lib/db/migrations/
|
|
97
42
|
5. Handle any migration errors before proceeding
|
|
98
|
-
6. Ensure schema changes follow Drizzle ORM best practices from
|
|
99
|
-
|
|
100
|
-
**Database Connection:**
|
|
101
|
-
- Using database URL: ${dbUrl}
|
|
102
|
-
- Ensure the database is accessible before running migration commands
|
|
43
|
+
6. Ensure schema changes follow Drizzle ORM best practices from project guidelines
|
|
103
44
|
`
|
|
104
45
|
: '';
|
|
105
46
|
return `You are an expert software engineer implementing a feature ticket.
|
|
106
47
|
|
|
107
48
|
**Your Task:**
|
|
108
|
-
Implement the following ticket according to the project's coding standards and architecture patterns.
|
|
49
|
+
Implement the following ticket according to the project's coding standards and architecture patterns (CLAUDE.md will be loaded automatically).
|
|
109
50
|
|
|
110
51
|
**Ticket Information:**
|
|
111
52
|
- ID: ${ticket.id}
|
|
@@ -113,11 +54,8 @@ Implement the following ticket according to the project's coding standards and a
|
|
|
113
54
|
- Description:
|
|
114
55
|
${ticket.description}
|
|
115
56
|
|
|
116
|
-
**Project Rules (CLAUDE.md):**
|
|
117
|
-
${claudeRules}
|
|
118
|
-
|
|
119
57
|
**Implementation Requirements:**
|
|
120
|
-
1. Follow ALL guidelines
|
|
58
|
+
1. Follow ALL project guidelines from CLAUDE.md
|
|
121
59
|
2. Explore the current codebase to understand existing patterns and architecture
|
|
122
60
|
3. Write clean, well-documented code
|
|
123
61
|
4. Ensure TypeScript type safety
|
|
@@ -134,45 +72,6 @@ ${claudeRules}
|
|
|
134
72
|
|
|
135
73
|
Begin by exploring the current codebase, then implement the ticket systematically.`;
|
|
136
74
|
}
|
|
137
|
-
/**
|
|
138
|
-
* Build system prompt for review
|
|
139
|
-
*/
|
|
140
|
-
function buildReviewPrompt(ticket, claudeRules) {
|
|
141
|
-
return `You are a senior code reviewer ensuring compliance with project standards.
|
|
142
|
-
|
|
143
|
-
**Your Task:**
|
|
144
|
-
Review the implementation of ticket ${ticket.id} and ensure it follows CLAUDE.md rules.
|
|
145
|
-
|
|
146
|
-
**Ticket Context:**
|
|
147
|
-
- ID: ${ticket.id}
|
|
148
|
-
- Title: ${ticket.title}
|
|
149
|
-
|
|
150
|
-
**Project Rules (CLAUDE.md):**
|
|
151
|
-
${claudeRules}
|
|
152
|
-
|
|
153
|
-
**Review Requirements:**
|
|
154
|
-
1. Check compliance with CLAUDE.md guidelines
|
|
155
|
-
2. Verify code quality and best practices
|
|
156
|
-
3. Ensure TypeScript type safety
|
|
157
|
-
4. Check error handling
|
|
158
|
-
5. Verify naming conventions
|
|
159
|
-
6. Check for security issues
|
|
160
|
-
7. Ensure proper documentation
|
|
161
|
-
|
|
162
|
-
**If Issues Found:**
|
|
163
|
-
- Use search_replace or write tools to FIX them immediately
|
|
164
|
-
- Don't just report issues - FIX them!
|
|
165
|
-
- Make minimal necessary changes
|
|
166
|
-
- Ensure fixes don't break functionality
|
|
167
|
-
|
|
168
|
-
**Critical Instructions:**
|
|
169
|
-
- Read the files that were recently modified for this ticket
|
|
170
|
-
- Identify any violations of CLAUDE.md rules
|
|
171
|
-
- Fix ALL issues found
|
|
172
|
-
- Ensure the code is production-ready after your review
|
|
173
|
-
|
|
174
|
-
Begin by reading recent changes and reviewing them against the standards.`;
|
|
175
|
-
}
|
|
176
75
|
/**
|
|
177
76
|
* Core ship logic (git-agnostic, reusable)
|
|
178
77
|
*/
|
|
@@ -210,11 +109,7 @@ export async function shipCore(options) {
|
|
|
210
109
|
console.log('š Updating ticket status to InProgress...');
|
|
211
110
|
updateTicketStatus(ticketsPath, ticketId, 'InProgress');
|
|
212
111
|
console.log(' ā
Status updated\n');
|
|
213
|
-
// 3.
|
|
214
|
-
console.log('š Loading CLAUDE.md rules...');
|
|
215
|
-
const claudeRules = loadClaudeRules(cwd);
|
|
216
|
-
console.log(` ā
Loaded rules (${claudeRules.length} characters)\n`);
|
|
217
|
-
// 4. Context ready (using current working directory)
|
|
112
|
+
// 3. Context ready (using current working directory)
|
|
218
113
|
console.log('š Working in current directory context\n');
|
|
219
114
|
// Track metrics
|
|
220
115
|
let totalInputTokens = 0;
|
|
@@ -229,7 +124,7 @@ export async function shipCore(options) {
|
|
|
229
124
|
console.log(`\n${'='.repeat(60)}`);
|
|
230
125
|
console.log(`š Phase 1: Implementation`);
|
|
231
126
|
console.log(`${'='.repeat(60)}\n`);
|
|
232
|
-
const systemPrompt = buildImplementationPrompt(ticket,
|
|
127
|
+
const systemPrompt = buildImplementationPrompt(ticket, dbUrl);
|
|
233
128
|
const implementationResult = await runAgent(`Implement ticket ${ticketId}: ${ticket.title}`, {
|
|
234
129
|
systemPrompt,
|
|
235
130
|
cwd,
|
|
@@ -250,33 +145,26 @@ export async function shipCore(options) {
|
|
|
250
145
|
console.log(`${'='.repeat(60)}\n`);
|
|
251
146
|
const lintResult = await runComprehensiveLinting(cwd);
|
|
252
147
|
console.log(`\nā
Linting completed (${lintResult.fixCount} fixes applied)`);
|
|
253
|
-
// 7. Review phase (if review flag is set)
|
|
254
|
-
let reviewPerformed = false;
|
|
148
|
+
// 7. Review phase (if review flag is set) - with ticket context
|
|
255
149
|
if (review) {
|
|
256
150
|
console.log(`\n${'='.repeat(60)}`);
|
|
257
|
-
console.log(`š Phase 3:
|
|
151
|
+
console.log(`š Phase 3: Code Review (Git Diff)`);
|
|
258
152
|
console.log(`${'='.repeat(60)}\n`);
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
153
|
+
const reviewResult = await reviewCore({
|
|
154
|
+
directory: cwd,
|
|
155
|
+
context: {
|
|
156
|
+
ticketId: ticket.id,
|
|
157
|
+
ticketTitle: ticket.title,
|
|
158
|
+
ticketDescription: ticket.description,
|
|
159
|
+
},
|
|
265
160
|
});
|
|
266
|
-
reviewFixCount = reviewResult.
|
|
161
|
+
reviewFixCount = reviewResult.fixesApplied;
|
|
267
162
|
totalInputTokens += reviewResult.tokensUsed.input;
|
|
268
163
|
totalOutputTokens += reviewResult.tokensUsed.output;
|
|
269
164
|
totalCacheCreationTokens += reviewResult.tokensUsed.cacheCreation;
|
|
270
165
|
totalCacheReadTokens += reviewResult.tokensUsed.cacheRead;
|
|
271
166
|
totalCost += reviewResult.cost;
|
|
272
|
-
console.log(`\nāØ
|
|
273
|
-
console.log(`š° Review cost: ${formatCostBreakdown(reviewResult)}`);
|
|
274
|
-
// Run linting again after review fixes
|
|
275
|
-
if (reviewFixCount > 0) {
|
|
276
|
-
console.log('\nš§ Running linting after review fixes...');
|
|
277
|
-
await runComprehensiveLinting(cwd);
|
|
278
|
-
}
|
|
279
|
-
reviewPerformed = true;
|
|
167
|
+
console.log(`\n⨠Review completed (${reviewResult.issuesFound} issues found, ${reviewFixCount} fixes applied)`);
|
|
280
168
|
}
|
|
281
169
|
// 8. Test phase (if test flag is set) - ITERATIVE
|
|
282
170
|
let testFixCount = 0;
|
|
@@ -345,10 +233,7 @@ export async function shipCore(options) {
|
|
|
345
233
|
success: true,
|
|
346
234
|
implementationFixCount,
|
|
347
235
|
lintFixCount: lintResult.fixCount,
|
|
348
|
-
reviewPerformed,
|
|
349
236
|
reviewFixCount,
|
|
350
|
-
gitDiffReviewed: false,
|
|
351
|
-
gitDiffReviewFixCount: 0,
|
|
352
237
|
tokensUsed: {
|
|
353
238
|
input: totalInputTokens,
|
|
354
239
|
output: totalOutputTokens,
|
|
@@ -368,10 +253,7 @@ export async function shipCore(options) {
|
|
|
368
253
|
success: false,
|
|
369
254
|
implementationFixCount,
|
|
370
255
|
lintFixCount: 0,
|
|
371
|
-
reviewPerformed: false,
|
|
372
256
|
reviewFixCount,
|
|
373
|
-
gitDiffReviewed: false,
|
|
374
|
-
gitDiffReviewFixCount: 0,
|
|
375
257
|
tokensUsed: {
|
|
376
258
|
input: totalInputTokens,
|
|
377
259
|
output: totalOutputTokens,
|
|
@@ -383,27 +265,13 @@ export async function shipCore(options) {
|
|
|
383
265
|
};
|
|
384
266
|
}
|
|
385
267
|
}
|
|
386
|
-
/**
|
|
387
|
-
* Review git diff after implementation
|
|
388
|
-
*/
|
|
389
|
-
async function reviewGitDiff(cwd) {
|
|
390
|
-
console.log(`\n${'='.repeat(60)}`);
|
|
391
|
-
console.log(`š Reviewing Git Diff Against CLAUDE.md`);
|
|
392
|
-
console.log(`${'='.repeat(60)}\n`);
|
|
393
|
-
const result = await reviewCore({ directory: cwd });
|
|
394
|
-
return {
|
|
395
|
-
fixCount: result.fixesApplied,
|
|
396
|
-
cost: result.cost,
|
|
397
|
-
tokensUsed: result.tokensUsed,
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
268
|
/**
|
|
401
269
|
* Main ship command
|
|
402
270
|
*/
|
|
403
271
|
export async function shipCommand(options) {
|
|
404
|
-
const { ticket: ticketId, commit = false,
|
|
272
|
+
const { ticket: ticketId, commit = false, directory, noLogs = false } = options;
|
|
405
273
|
console.log(`š¢ Shipping Ticket: ${ticketId}\n`);
|
|
406
|
-
// Resolve directory
|
|
274
|
+
// Resolve directory
|
|
407
275
|
const cwd = directory ? resolve(directory) : process.cwd();
|
|
408
276
|
// Initialize logging context
|
|
409
277
|
const logContext = logger.createContext('ship', { noLogs });
|
|
@@ -413,122 +281,38 @@ export async function shipCommand(options) {
|
|
|
413
281
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
414
282
|
throw new Error('ANTHROPIC_API_KEY environment variable is required');
|
|
415
283
|
}
|
|
416
|
-
// Validate mutually exclusive flags
|
|
417
|
-
if (commit && pr) {
|
|
418
|
-
throw new Error('Cannot use --commit and --pr together.\n' +
|
|
419
|
-
'Use --commit to push to current branch, or --pr to create a new branch with pull request.');
|
|
420
|
-
}
|
|
421
|
-
if (pr && !process.env.GITHUB_TOKEN) {
|
|
422
|
-
throw new Error('GITHUB_TOKEN environment variable is required for --pr flag');
|
|
423
|
-
}
|
|
424
284
|
if (commit && !process.env.GITHUB_TOKEN) {
|
|
425
285
|
throw new Error('GITHUB_TOKEN environment variable is required for --commit flag');
|
|
426
286
|
}
|
|
427
|
-
//
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
const { result: shipResult, prInfo } = await runWithPR({
|
|
432
|
-
branchPrefix: `feat/ticket-${ticketId}`,
|
|
433
|
-
baseBranch: options.baseBranch,
|
|
434
|
-
commitMessage: `feat: implement ${ticketId}`,
|
|
435
|
-
prTitle: `feat: Implement ${ticketId}`,
|
|
436
|
-
prBody: `## š« Ticket Implementation
|
|
437
|
-
|
|
438
|
-
Implements ticket **${ticketId}** from tickets.json.
|
|
439
|
-
|
|
440
|
-
### š Details
|
|
441
|
-
- Implementation fixes: ${0} (will be filled by result)
|
|
442
|
-
- Linting fixes: ${0}
|
|
443
|
-
- Review performed: ${options.review ? 'Yes' : 'No'}
|
|
444
|
-
|
|
445
|
-
---
|
|
446
|
-
|
|
447
|
-
š¤ *Generated by Kosuke CLI (\`kosuke ship --ticket=${ticketId} ${options.review ? '--review ' : ''}--pr\`)*`,
|
|
448
|
-
cwd,
|
|
449
|
-
}, async () => {
|
|
450
|
-
// Run core implementation
|
|
451
|
-
const result = await shipCore(options);
|
|
452
|
-
// Track metrics
|
|
453
|
-
logger.trackTokens(logContext, result.tokensUsed);
|
|
454
|
-
logContext.fixesApplied +=
|
|
455
|
-
result.implementationFixCount + result.lintFixCount + result.reviewFixCount;
|
|
456
|
-
// Review git diff before committing
|
|
457
|
-
const diffReview = await reviewGitDiff(cwd);
|
|
458
|
-
diffReviewCost = diffReview.cost;
|
|
459
|
-
diffReviewFixCount = diffReview.fixCount;
|
|
460
|
-
// Track diff review metrics
|
|
461
|
-
logger.trackTokens(logContext, diffReview.tokensUsed);
|
|
462
|
-
logContext.fixesApplied += diffReview.fixCount;
|
|
463
|
-
return result;
|
|
464
|
-
});
|
|
465
|
-
// Display summary with updated values
|
|
466
|
-
console.log('\nā
Ship completed successfully!');
|
|
467
|
-
console.log(`š Implementation fixes: ${shipResult.implementationFixCount}`);
|
|
468
|
-
console.log(`š§ Linting fixes: ${shipResult.lintFixCount}`);
|
|
469
|
-
if (shipResult.reviewPerformed) {
|
|
470
|
-
console.log(`š Pre-review fixes: ${shipResult.reviewFixCount}`);
|
|
471
|
-
}
|
|
472
|
-
console.log(`š Git diff review fixes: ${diffReviewFixCount}`);
|
|
473
|
-
console.log(`š° Total cost: $${(shipResult.cost + diffReviewCost).toFixed(4)}`);
|
|
474
|
-
console.log(`š PR: ${prInfo.prUrl}`);
|
|
475
|
-
// Log successful execution
|
|
476
|
-
await logger.complete(logContext, 'success');
|
|
477
|
-
cleanupHandler();
|
|
287
|
+
// Run core implementation
|
|
288
|
+
const result = await shipCore(options);
|
|
289
|
+
if (!result.success) {
|
|
290
|
+
throw new Error(result.error || 'Ship failed');
|
|
478
291
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
// Track core metrics
|
|
486
|
-
logger.trackTokens(logContext, result.tokensUsed);
|
|
487
|
-
logContext.fixesApplied +=
|
|
488
|
-
result.implementationFixCount + result.lintFixCount + result.reviewFixCount;
|
|
489
|
-
// Review git diff before committing
|
|
490
|
-
const diffReview = await reviewGitDiff(cwd);
|
|
491
|
-
// Track diff review metrics
|
|
492
|
-
logger.trackTokens(logContext, diffReview.tokensUsed);
|
|
493
|
-
logContext.fixesApplied += diffReview.fixCount;
|
|
494
|
-
// Commit and push to current branch
|
|
292
|
+
// Track metrics
|
|
293
|
+
logger.trackTokens(logContext, result.tokensUsed);
|
|
294
|
+
logContext.fixesApplied =
|
|
295
|
+
result.implementationFixCount + result.lintFixCount + result.reviewFixCount;
|
|
296
|
+
// Commit if flag is set
|
|
297
|
+
if (commit) {
|
|
495
298
|
console.log('\nš Committing and pushing to current branch...');
|
|
496
299
|
await commitAndPushCurrentBranch(`feat: implement ${ticketId}`, cwd);
|
|
497
300
|
console.log(' ā
Changes committed and pushed\n');
|
|
498
|
-
console.log('\nā
Ship completed successfully!');
|
|
499
|
-
console.log(`š Implementation fixes: ${result.implementationFixCount}`);
|
|
500
|
-
console.log(`š§ Linting fixes: ${result.lintFixCount}`);
|
|
501
|
-
if (result.reviewPerformed) {
|
|
502
|
-
console.log(`š Pre-review fixes: ${result.reviewFixCount}`);
|
|
503
|
-
}
|
|
504
|
-
console.log(`š Git diff review fixes: ${diffReview.fixCount}`);
|
|
505
|
-
console.log(`š° Total cost: $${(result.cost + diffReview.cost).toFixed(4)}`);
|
|
506
|
-
// Log successful execution
|
|
507
|
-
await logger.complete(logContext, 'success');
|
|
508
|
-
cleanupHandler();
|
|
509
301
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
console.log('\nā
Ship completed successfully!');
|
|
521
|
-
console.log(`š Implementation fixes: ${result.implementationFixCount}`);
|
|
522
|
-
console.log(`š§ Linting fixes: ${result.lintFixCount}`);
|
|
523
|
-
if (result.reviewPerformed) {
|
|
524
|
-
console.log(`š Review fixes: ${result.reviewFixCount}`);
|
|
525
|
-
}
|
|
526
|
-
console.log(`š° Total cost: $${result.cost.toFixed(4)}`);
|
|
527
|
-
console.log('\nā¹ļø Changes applied locally. Use --commit to push or --pr to create a pull request.');
|
|
528
|
-
// Log successful execution
|
|
529
|
-
await logger.complete(logContext, 'success');
|
|
530
|
-
cleanupHandler();
|
|
302
|
+
// Display summary
|
|
303
|
+
console.log('\nā
Ship completed successfully!');
|
|
304
|
+
console.log(`š Implementation fixes: ${result.implementationFixCount}`);
|
|
305
|
+
console.log(`š§ Linting fixes: ${result.lintFixCount}`);
|
|
306
|
+
if (result.reviewFixCount > 0) {
|
|
307
|
+
console.log(`š Review fixes: ${result.reviewFixCount}`);
|
|
308
|
+
}
|
|
309
|
+
console.log(`š° Total cost: $${result.cost.toFixed(4)}`);
|
|
310
|
+
if (!commit) {
|
|
311
|
+
console.log('\nā¹ļø Changes applied locally. Use --commit to push to current branch.');
|
|
531
312
|
}
|
|
313
|
+
// Log successful execution
|
|
314
|
+
await logger.complete(logContext, 'success');
|
|
315
|
+
cleanupHandler();
|
|
532
316
|
}
|
|
533
317
|
catch (error) {
|
|
534
318
|
console.error('\nā Ship failed:', error);
|