@kosuke-ai/cli 0.0.57 → 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.
Files changed (263) hide show
  1. package/README.md +31 -448
  2. package/dist/commands/auth.js +117 -0
  3. package/dist/generated/commands/deploy/cancel.js +17 -0
  4. package/dist/generated/commands/deploy/messages.js +17 -0
  5. package/dist/generated/commands/deploy/run.js +60 -0
  6. package/dist/generated/commands/index.js +132 -0
  7. package/dist/generated/commands/preview/get.js +25 -0
  8. package/dist/generated/commands/preview/health.js +25 -0
  9. package/dist/generated/commands/preview/reset.js +27 -0
  10. package/dist/generated/commands/preview/share-create.js +36 -0
  11. package/dist/generated/commands/preview/share-delete.js +26 -0
  12. package/dist/generated/commands/preview/share-get.js +26 -0
  13. package/dist/generated/commands/preview/shared.js +17 -0
  14. package/dist/generated/commands/projects/create.js +37 -0
  15. package/dist/generated/commands/projects/delete.js +17 -0
  16. package/dist/generated/commands/projects/env-vars-add.js +21 -0
  17. package/dist/generated/commands/projects/env-vars-remove.js +21 -0
  18. package/dist/generated/commands/projects/get.js +17 -0
  19. package/dist/generated/commands/projects/list.js +15 -0
  20. package/dist/generated/commands/projects/services-add.js +87 -0
  21. package/dist/generated/commands/projects/services-list.js +18 -0
  22. package/dist/generated/commands/projects/services-remove.js +19 -0
  23. package/dist/generated/commands/projects/services-update.js +81 -0
  24. package/dist/generated/commands/projects/settings-get.js +18 -0
  25. package/dist/generated/commands/projects/settings-import.js +91 -0
  26. package/dist/generated/commands/projects/settings-update.js +77 -0
  27. package/dist/generated/commands/projects/skills.js +35 -0
  28. package/dist/generated/commands/projects/update.js +27 -0
  29. package/dist/generated/commands/sessions/activate.js +18 -0
  30. package/dist/generated/commands/sessions/checklist-generate.js +19 -0
  31. package/dist/generated/commands/sessions/checklist-get.js +19 -0
  32. package/dist/generated/commands/sessions/comments-add.js +63 -0
  33. package/dist/generated/commands/sessions/comments-delete.js +20 -0
  34. package/dist/generated/commands/sessions/comments-list.js +19 -0
  35. package/dist/generated/commands/sessions/comments-update.js +23 -0
  36. package/dist/generated/commands/sessions/create.js +126 -0
  37. package/dist/generated/commands/sessions/delete.js +18 -0
  38. package/dist/generated/commands/sessions/diff-files.js +19 -0
  39. package/dist/generated/commands/sessions/diff-patch.js +86 -0
  40. package/dist/generated/commands/sessions/edit-prompt.js +59 -0
  41. package/dist/generated/commands/sessions/files-get.js +27 -0
  42. package/dist/generated/commands/sessions/files-list.js +19 -0
  43. package/dist/generated/commands/sessions/files-write.js +41 -0
  44. package/dist/generated/commands/sessions/get.js +18 -0
  45. package/dist/generated/commands/sessions/git-commit-message.js +19 -0
  46. package/dist/generated/commands/sessions/git-commit.js +29 -0
  47. package/dist/generated/commands/sessions/git-push.js +19 -0
  48. package/dist/generated/commands/sessions/git-state.js +19 -0
  49. package/dist/generated/commands/sessions/jobs-cancel.js +20 -0
  50. package/dist/generated/commands/sessions/jobs-get.js +20 -0
  51. package/dist/generated/commands/sessions/list.js +81 -0
  52. package/dist/generated/commands/sessions/messages.js +18 -0
  53. package/dist/generated/commands/sessions/search.js +23 -0
  54. package/dist/generated/commands/sessions/send.js +98 -0
  55. package/dist/generated/commands/sessions/update.js +72 -0
  56. package/dist/generated/commands/workspaces/access-status.js +29 -0
  57. package/dist/generated/commands/workspaces/ai-provider-get.js +18 -0
  58. package/dist/generated/commands/workspaces/ai-provider-remove.js +42 -0
  59. package/dist/generated/commands/workspaces/ai-provider-set.js +21 -0
  60. package/dist/generated/commands/workspaces/credits.js +17 -0
  61. package/dist/generated/commands/workspaces/get.js +17 -0
  62. package/dist/generated/commands/workspaces/getting-started-get.js +18 -0
  63. package/dist/generated/commands/workspaces/getting-started-update.js +32 -0
  64. package/dist/generated/commands/workspaces/list.js +15 -0
  65. package/dist/generated/commands/workspaces/members.js +25 -0
  66. package/dist/generated/commands/workspaces/sandbox-limit.js +17 -0
  67. package/dist/generated/commands/workspaces/stop-sandboxes.js +27 -0
  68. package/dist/generated/commands/workspaces/usage.js +32 -0
  69. package/dist/index.js +5 -595
  70. package/dist/program.js +46 -0
  71. package/dist/runtime/attach.js +139 -0
  72. package/dist/runtime/attachments.js +58 -0
  73. package/dist/runtime/client.js +12 -0
  74. package/dist/runtime/config.js +49 -0
  75. package/dist/runtime/credentials.js +24 -0
  76. package/dist/runtime/descriptor.js +7 -0
  77. package/dist/runtime/invoke.js +152 -0
  78. package/dist/runtime/runtime.js +41 -0
  79. package/dist/runtime/version.js +5 -0
  80. package/openapi.json +5222 -0
  81. package/package.json +21 -79
  82. package/LICENSE +0 -21
  83. package/claude.costs.json +0 -34
  84. package/dist/__tests__/utils/file-discovery.test.d.ts +0 -5
  85. package/dist/__tests__/utils/file-discovery.test.d.ts.map +0 -1
  86. package/dist/__tests__/utils/file-discovery.test.js +0 -51
  87. package/dist/__tests__/utils/file-discovery.test.js.map +0 -1
  88. package/dist/__tests__/utils/logger-nologs.test.d.ts +0 -5
  89. package/dist/__tests__/utils/logger-nologs.test.d.ts.map +0 -1
  90. package/dist/__tests__/utils/logger-nologs.test.js +0 -34
  91. package/dist/__tests__/utils/logger-nologs.test.js.map +0 -1
  92. package/dist/__tests__/utils/logger.test.d.ts +0 -5
  93. package/dist/__tests__/utils/logger.test.d.ts.map +0 -1
  94. package/dist/__tests__/utils/logger.test.js +0 -243
  95. package/dist/__tests__/utils/logger.test.js.map +0 -1
  96. package/dist/__tests__/utils/validator.test.d.ts +0 -5
  97. package/dist/__tests__/utils/validator.test.d.ts.map +0 -1
  98. package/dist/__tests__/utils/validator.test.js +0 -206
  99. package/dist/__tests__/utils/validator.test.js.map +0 -1
  100. package/dist/index.d.ts +0 -37
  101. package/dist/index.d.ts.map +0 -1
  102. package/dist/index.js.map +0 -1
  103. package/dist/kosuke/commands/analyse.d.ts +0 -15
  104. package/dist/kosuke/commands/analyse.d.ts.map +0 -1
  105. package/dist/kosuke/commands/analyse.js +0 -304
  106. package/dist/kosuke/commands/analyse.js.map +0 -1
  107. package/dist/kosuke/commands/build.d.ts +0 -35
  108. package/dist/kosuke/commands/build.d.ts.map +0 -1
  109. package/dist/kosuke/commands/build.js +0 -660
  110. package/dist/kosuke/commands/build.js.map +0 -1
  111. package/dist/kosuke/commands/fix.d.ts +0 -21
  112. package/dist/kosuke/commands/fix.d.ts.map +0 -1
  113. package/dist/kosuke/commands/fix.js +0 -256
  114. package/dist/kosuke/commands/fix.js.map +0 -1
  115. package/dist/kosuke/commands/getcode.d.ts +0 -29
  116. package/dist/kosuke/commands/getcode.d.ts.map +0 -1
  117. package/dist/kosuke/commands/getcode.js +0 -248
  118. package/dist/kosuke/commands/getcode.js.map +0 -1
  119. package/dist/kosuke/commands/lint.d.ts +0 -21
  120. package/dist/kosuke/commands/lint.d.ts.map +0 -1
  121. package/dist/kosuke/commands/lint.js +0 -342
  122. package/dist/kosuke/commands/lint.js.map +0 -1
  123. package/dist/kosuke/commands/migrate.d.ts +0 -38
  124. package/dist/kosuke/commands/migrate.d.ts.map +0 -1
  125. package/dist/kosuke/commands/migrate.js +0 -284
  126. package/dist/kosuke/commands/migrate.js.map +0 -1
  127. package/dist/kosuke/commands/plan.d.ts +0 -28
  128. package/dist/kosuke/commands/plan.d.ts.map +0 -1
  129. package/dist/kosuke/commands/plan.js +0 -684
  130. package/dist/kosuke/commands/plan.js.map +0 -1
  131. package/dist/kosuke/commands/requirements.d.ts +0 -52
  132. package/dist/kosuke/commands/requirements.d.ts.map +0 -1
  133. package/dist/kosuke/commands/requirements.js +0 -615
  134. package/dist/kosuke/commands/requirements.js.map +0 -1
  135. package/dist/kosuke/commands/review.d.ts +0 -26
  136. package/dist/kosuke/commands/review.d.ts.map +0 -1
  137. package/dist/kosuke/commands/review.js +0 -303
  138. package/dist/kosuke/commands/review.js.map +0 -1
  139. package/dist/kosuke/commands/serve.d.ts +0 -9
  140. package/dist/kosuke/commands/serve.d.ts.map +0 -1
  141. package/dist/kosuke/commands/serve.js +0 -17
  142. package/dist/kosuke/commands/serve.js.map +0 -1
  143. package/dist/kosuke/commands/ship.d.ts +0 -37
  144. package/dist/kosuke/commands/ship.d.ts.map +0 -1
  145. package/dist/kosuke/commands/ship.js +0 -375
  146. package/dist/kosuke/commands/ship.js.map +0 -1
  147. package/dist/kosuke/commands/sync-rules.d.ts +0 -9
  148. package/dist/kosuke/commands/sync-rules.d.ts.map +0 -1
  149. package/dist/kosuke/commands/sync-rules.js +0 -414
  150. package/dist/kosuke/commands/sync-rules.js.map +0 -1
  151. package/dist/kosuke/commands/test.d.ts +0 -42
  152. package/dist/kosuke/commands/test.d.ts.map +0 -1
  153. package/dist/kosuke/commands/test.js +0 -540
  154. package/dist/kosuke/commands/test.js.map +0 -1
  155. package/dist/kosuke/commands/tickets.d.ts +0 -43
  156. package/dist/kosuke/commands/tickets.d.ts.map +0 -1
  157. package/dist/kosuke/commands/tickets.js +0 -876
  158. package/dist/kosuke/commands/tickets.js.map +0 -1
  159. package/dist/kosuke/commands/validate-tickets.d.ts +0 -23
  160. package/dist/kosuke/commands/validate-tickets.d.ts.map +0 -1
  161. package/dist/kosuke/commands/validate-tickets.js +0 -360
  162. package/dist/kosuke/commands/validate-tickets.js.map +0 -1
  163. package/dist/kosuke/serve/middleware/error-handler.d.ts +0 -14
  164. package/dist/kosuke/serve/middleware/error-handler.d.ts.map +0 -1
  165. package/dist/kosuke/serve/middleware/error-handler.js +0 -42
  166. package/dist/kosuke/serve/middleware/error-handler.js.map +0 -1
  167. package/dist/kosuke/serve/middleware/validation.d.ts +0 -13
  168. package/dist/kosuke/serve/middleware/validation.d.ts.map +0 -1
  169. package/dist/kosuke/serve/middleware/validation.js +0 -38
  170. package/dist/kosuke/serve/middleware/validation.js.map +0 -1
  171. package/dist/kosuke/serve/routes/build.d.ts +0 -6
  172. package/dist/kosuke/serve/routes/build.d.ts.map +0 -1
  173. package/dist/kosuke/serve/routes/build.js +0 -226
  174. package/dist/kosuke/serve/routes/build.js.map +0 -1
  175. package/dist/kosuke/serve/routes/health.d.ts +0 -6
  176. package/dist/kosuke/serve/routes/health.d.ts.map +0 -1
  177. package/dist/kosuke/serve/routes/health.js +0 -11
  178. package/dist/kosuke/serve/routes/health.js.map +0 -1
  179. package/dist/kosuke/serve/routes/plan.d.ts +0 -6
  180. package/dist/kosuke/serve/routes/plan.d.ts.map +0 -1
  181. package/dist/kosuke/serve/routes/plan.js +0 -106
  182. package/dist/kosuke/serve/routes/plan.js.map +0 -1
  183. package/dist/kosuke/serve/server.d.ts +0 -16
  184. package/dist/kosuke/serve/server.d.ts.map +0 -1
  185. package/dist/kosuke/serve/server.js +0 -67
  186. package/dist/kosuke/serve/server.js.map +0 -1
  187. package/dist/kosuke/serve/validation/build.d.ts +0 -41
  188. package/dist/kosuke/serve/validation/build.d.ts.map +0 -1
  189. package/dist/kosuke/serve/validation/build.js +0 -20
  190. package/dist/kosuke/serve/validation/build.js.map +0 -1
  191. package/dist/kosuke/serve/validation/plan.d.ts +0 -26
  192. package/dist/kosuke/serve/validation/plan.d.ts.map +0 -1
  193. package/dist/kosuke/serve/validation/plan.js +0 -15
  194. package/dist/kosuke/serve/validation/plan.js.map +0 -1
  195. package/dist/kosuke/types.d.ts +0 -539
  196. package/dist/kosuke/types.d.ts.map +0 -1
  197. package/dist/kosuke/types.js +0 -5
  198. package/dist/kosuke/types.js.map +0 -1
  199. package/dist/kosuke/utils/batch-creator.d.ts +0 -14
  200. package/dist/kosuke/utils/batch-creator.d.ts.map +0 -1
  201. package/dist/kosuke/utils/batch-creator.js +0 -76
  202. package/dist/kosuke/utils/batch-creator.js.map +0 -1
  203. package/dist/kosuke/utils/claude-agent.d.ts +0 -140
  204. package/dist/kosuke/utils/claude-agent.d.ts.map +0 -1
  205. package/dist/kosuke/utils/claude-agent.js +0 -388
  206. package/dist/kosuke/utils/claude-agent.js.map +0 -1
  207. package/dist/kosuke/utils/constants.d.ts +0 -40
  208. package/dist/kosuke/utils/constants.d.ts.map +0 -1
  209. package/dist/kosuke/utils/constants.js +0 -54
  210. package/dist/kosuke/utils/constants.js.map +0 -1
  211. package/dist/kosuke/utils/file-discovery.d.ts +0 -15
  212. package/dist/kosuke/utils/file-discovery.d.ts.map +0 -1
  213. package/dist/kosuke/utils/file-discovery.js +0 -80
  214. package/dist/kosuke/utils/file-discovery.js.map +0 -1
  215. package/dist/kosuke/utils/git.d.ts +0 -41
  216. package/dist/kosuke/utils/git.d.ts.map +0 -1
  217. package/dist/kosuke/utils/git.js +0 -145
  218. package/dist/kosuke/utils/git.js.map +0 -1
  219. package/dist/kosuke/utils/github.d.ts +0 -17
  220. package/dist/kosuke/utils/github.d.ts.map +0 -1
  221. package/dist/kosuke/utils/github.js +0 -22
  222. package/dist/kosuke/utils/github.js.map +0 -1
  223. package/dist/kosuke/utils/interactive-input.d.ts +0 -22
  224. package/dist/kosuke/utils/interactive-input.d.ts.map +0 -1
  225. package/dist/kosuke/utils/interactive-input.js +0 -124
  226. package/dist/kosuke/utils/interactive-input.js.map +0 -1
  227. package/dist/kosuke/utils/json-parser.d.ts +0 -14
  228. package/dist/kosuke/utils/json-parser.d.ts.map +0 -1
  229. package/dist/kosuke/utils/json-parser.js +0 -40
  230. package/dist/kosuke/utils/json-parser.js.map +0 -1
  231. package/dist/kosuke/utils/logger.d.ts +0 -161
  232. package/dist/kosuke/utils/logger.d.ts.map +0 -1
  233. package/dist/kosuke/utils/logger.js +0 -234
  234. package/dist/kosuke/utils/logger.js.map +0 -1
  235. package/dist/kosuke/utils/playwright-mcp-client.d.ts +0 -46
  236. package/dist/kosuke/utils/playwright-mcp-client.d.ts.map +0 -1
  237. package/dist/kosuke/utils/playwright-mcp-client.js +0 -135
  238. package/dist/kosuke/utils/playwright-mcp-client.js.map +0 -1
  239. package/dist/kosuke/utils/pr-orchestrator.d.ts +0 -49
  240. package/dist/kosuke/utils/pr-orchestrator.d.ts.map +0 -1
  241. package/dist/kosuke/utils/pr-orchestrator.js +0 -154
  242. package/dist/kosuke/utils/pr-orchestrator.js.map +0 -1
  243. package/dist/kosuke/utils/repository-manager.d.ts +0 -13
  244. package/dist/kosuke/utils/repository-manager.d.ts.map +0 -1
  245. package/dist/kosuke/utils/repository-manager.js +0 -94
  246. package/dist/kosuke/utils/repository-manager.js.map +0 -1
  247. package/dist/kosuke/utils/repository-resolver.d.ts +0 -12
  248. package/dist/kosuke/utils/repository-resolver.d.ts.map +0 -1
  249. package/dist/kosuke/utils/repository-resolver.js +0 -186
  250. package/dist/kosuke/utils/repository-resolver.js.map +0 -1
  251. package/dist/kosuke/utils/tickets-manager.d.ts +0 -34
  252. package/dist/kosuke/utils/tickets-manager.d.ts.map +0 -1
  253. package/dist/kosuke/utils/tickets-manager.js +0 -106
  254. package/dist/kosuke/utils/tickets-manager.js.map +0 -1
  255. package/dist/kosuke/utils/validator.d.ts +0 -45
  256. package/dist/kosuke/utils/validator.d.ts.map +0 -1
  257. package/dist/kosuke/utils/validator.js +0 -248
  258. package/dist/kosuke/utils/validator.js.map +0 -1
  259. package/dist/lib.d.ts +0 -104
  260. package/dist/lib.d.ts.map +0 -1
  261. package/dist/lib.js +0 -104
  262. package/dist/lib.js.map +0 -1
  263. package/dist/package.json +0 -99
@@ -1,660 +0,0 @@
1
- /**
2
- * Build command - Process all tickets from tickets.json
3
- *
4
- * This command processes all "Todo" and "Error" tickets sequentially,
5
- * implementing each one using the ship core engine and committing after each ticket.
6
- * Frontend tickets automatically run tests (unless --no-test is specified).
7
- * All tickets include code review by default (unless --no-review is specified).
8
- *
9
- * Usage:
10
- * kosuke build # Process and auto-commit all tickets
11
- * kosuke build --ask-commit # Ask before committing each ticket
12
- * kosuke build --ask-confirm # Ask before processing each ticket
13
- * kosuke build --reset # Reset all tickets to "Todo" and process from scratch
14
- * kosuke build --no-review # Skip code review phase
15
- * kosuke build --no-test # Skip testing phase for frontend tickets
16
- * kosuke build --headless # Run tests in headless mode (invisible)
17
- * kosuke build --verbose # Enable verbose test output
18
- * kosuke build --tickets=path/to/tickets.json
19
- * kosuke build --db-url=postgres://user:pass@host:5432/db
20
- *
21
- * Note: Create a feature branch before running build:
22
- * git checkout -b feat/implement-tickets
23
- * kosuke build
24
- * gh pr create
25
- */
26
- import { existsSync, statSync } from 'fs';
27
- import { join, resolve } from 'path';
28
- import * as readline from 'readline';
29
- import simpleGit from 'simple-git';
30
- import { DEFAULT_DB_URL } from '../utils/constants.js';
31
- import { loadTicketsFile, saveTicketsFile, updateTicketStatus, } from '../utils/tickets-manager.js';
32
- import { migrateCoreStream } from './migrate.js';
33
- import { migrateCore } from './migrate.js';
34
- import { shipCoreStream } from './ship.js';
35
- import { shipCore } from './ship.js';
36
- import { testCoreStream } from './test.js';
37
- import { testCore } from './test.js';
38
- /**
39
- * Generate a structured web test prompt from a ticket
40
- */
41
- function generateWebTestPrompt(ticket) {
42
- return `Test the following feature implementation:
43
-
44
- **Feature:** ${ticket.title}
45
-
46
- **Requirements:**
47
- ${ticket.description}
48
-
49
- **Testing Instructions:**
50
- 1. Navigate to the relevant page(s) for this feature
51
- 2. Verify all functionality described in the requirements works correctly
52
- 3. Check for any console errors or warnings
53
- 4. Confirm the implementation matches the ticket description
54
- 5. Test both happy path and edge cases
55
-
56
- **Success Criteria:**
57
- - All functionality works as described
58
- - No console errors
59
- - User experience is smooth and intuitive
60
- - Feature behaves correctly in different scenarios
61
-
62
- Return a clear success or failure status with details about what was tested and any issues found.`;
63
- }
64
- /**
65
- * Prompt user for confirmation to continue
66
- */
67
- async function promptConfirmation(message) {
68
- const rl = readline.createInterface({
69
- input: process.stdin,
70
- output: process.stdout,
71
- });
72
- return new Promise((resolve) => {
73
- rl.question(`\n${message} (y/n): `, (answer) => {
74
- rl.close();
75
- const response = answer.trim().toLowerCase();
76
- resolve(response === 'y' || response === 'yes');
77
- });
78
- });
79
- }
80
- /**
81
- * Filter and sort tickets for processing
82
- */
83
- function getTicketsToProcess(ticketsData) {
84
- // Get all Todo and Error tickets (automatic retry on Error)
85
- const tickets = ticketsData.tickets.filter((t) => t.status === 'Todo' || t.status === 'Error');
86
- // Sort by phase: SCHEMA -> DB-TEST -> BACKEND -> FRONTEND -> TEST
87
- tickets.sort((a, b) => {
88
- const getPhaseOrder = (id) => {
89
- if (id.startsWith('SCHEMA-'))
90
- return 1;
91
- if (id.startsWith('DB-TEST-'))
92
- return 2;
93
- if (id.startsWith('BACKEND-'))
94
- return 3;
95
- if (id.startsWith('FRONTEND-'))
96
- return 4;
97
- if (id.startsWith('TEST-'))
98
- return 5;
99
- return 6;
100
- };
101
- const phaseComparison = getPhaseOrder(a.id) - getPhaseOrder(b.id);
102
- if (phaseComparison !== 0)
103
- return phaseComparison;
104
- // Within same phase, sort by ticket number
105
- const aNum = parseInt(a.id.split('-').slice(-1)[0] || '0', 10);
106
- const bNum = parseInt(b.id.split('-').slice(-1)[0] || '0', 10);
107
- return aNum - bNum;
108
- });
109
- return tickets;
110
- }
111
- /**
112
- * Commit a single ticket to current branch
113
- * Returns the commit message
114
- */
115
- async function commitTicket(ticket, cwd) {
116
- const git = simpleGit(cwd);
117
- // Stage all changes
118
- await git.add('.');
119
- // Create commit message for this ticket
120
- const ticketType = ticket.type || 'feat';
121
- const commitMessage = `${ticketType}: ${ticket.id} - ${ticket.title}`;
122
- await git.commit(commitMessage, ['--no-verify']);
123
- return commitMessage;
124
- }
125
- /**
126
- * Streaming version of build - orchestrates all sub-commands with SSE events
127
- */
128
- export async function* buildCoreStream(options) {
129
- const { directory, ticketsFile = 'tickets.json', dbUrl = DEFAULT_DB_URL, reset = false, review = true, url, headless, verbose, trace, } = options;
130
- // 1. Validate and resolve directory
131
- const cwd = directory ? resolve(directory) : process.cwd();
132
- if (!existsSync(cwd)) {
133
- yield {
134
- type: 'done',
135
- data: {
136
- success: false,
137
- ticketsProcessed: 0,
138
- ticketsSucceeded: 0,
139
- ticketsFailed: 0,
140
- totalCost: 0,
141
- tokensUsed: { input: 0, output: 0, cacheCreation: 0, cacheRead: 0 },
142
- },
143
- };
144
- return;
145
- }
146
- const stats = statSync(cwd);
147
- if (!stats.isDirectory()) {
148
- yield {
149
- type: 'done',
150
- data: {
151
- success: false,
152
- ticketsProcessed: 0,
153
- ticketsSucceeded: 0,
154
- ticketsFailed: 0,
155
- totalCost: 0,
156
- tokensUsed: { input: 0, output: 0, cacheCreation: 0, cacheRead: 0 },
157
- },
158
- };
159
- return;
160
- }
161
- const ticketsPath = join(cwd, ticketsFile);
162
- // 2. Load tickets
163
- const ticketsData = loadTicketsFile(ticketsPath);
164
- // 3. Reset all tickets to "Todo" if --reset flag is provided
165
- if (reset) {
166
- ticketsData.tickets.forEach((ticket) => {
167
- if (ticket.status !== 'Todo') {
168
- ticket.status = 'Todo';
169
- delete ticket.error;
170
- }
171
- });
172
- saveTicketsFile(ticketsPath, ticketsData);
173
- }
174
- const ticketsToProcess = getTicketsToProcess(ticketsData);
175
- if (ticketsToProcess.length === 0) {
176
- yield {
177
- type: 'done',
178
- data: {
179
- success: true,
180
- ticketsProcessed: 0,
181
- ticketsSucceeded: 0,
182
- ticketsFailed: 0,
183
- totalCost: 0,
184
- tokensUsed: { input: 0, output: 0, cacheCreation: 0, cacheRead: 0 },
185
- },
186
- };
187
- return;
188
- }
189
- // Yield build started event
190
- yield {
191
- type: 'build_started',
192
- data: { totalTickets: ticketsToProcess.length, ticketsFile: ticketsPath },
193
- };
194
- // Track cumulative metrics
195
- let totalInputTokens = 0;
196
- let totalOutputTokens = 0;
197
- let totalCacheCreationTokens = 0;
198
- let totalCacheReadTokens = 0;
199
- let totalCost = 0;
200
- let ticketsSucceeded = 0;
201
- let ticketsFailed = 0;
202
- // 4. Process each ticket sequentially
203
- for (let i = 0; i < ticketsToProcess.length; i++) {
204
- const ticket = ticketsToProcess[i];
205
- // Yield ticket started
206
- yield {
207
- type: 'ticket_started',
208
- data: { ticket, index: i + 1, total: ticketsToProcess.length },
209
- };
210
- try {
211
- // Update status to InProgress
212
- updateTicketStatus(ticketsPath, ticket.id, 'InProgress');
213
- // Process ticket based on type
214
- const isTestTicket = ticket.type === 'test';
215
- if (isTestTicket) {
216
- // Test ticket with retry logic (Task 6)
217
- yield { type: 'ticket_phase', data: { phase: 'test', status: 'started' } };
218
- const testPrompt = generateWebTestPrompt(ticket);
219
- let testSuccess = false;
220
- let retryCount = 0;
221
- const maxRetries = 3;
222
- while (!testSuccess && retryCount <= maxRetries) {
223
- // Run test
224
- for await (const event of testCoreStream({
225
- prompt: testPrompt,
226
- context: {
227
- ticketId: ticket.id,
228
- ticketTitle: ticket.title,
229
- ticketDescription: ticket.description,
230
- },
231
- url,
232
- headless,
233
- verbose,
234
- trace,
235
- })) {
236
- yield { type: 'test_event', data: event };
237
- if (event.type === 'done') {
238
- const testResult = event.data;
239
- testSuccess = testResult.success;
240
- // Track metrics
241
- totalInputTokens += testResult.tokensUsed.input;
242
- totalOutputTokens += testResult.tokensUsed.output;
243
- totalCacheCreationTokens += testResult.tokensUsed.cacheCreation;
244
- totalCacheReadTokens += testResult.tokensUsed.cacheRead;
245
- totalCost += testResult.cost;
246
- // If test failed and we have retries left, create fix ticket
247
- if (!testSuccess && retryCount < maxRetries) {
248
- retryCount++;
249
- yield {
250
- type: 'test_retry',
251
- data: {
252
- attempt: retryCount,
253
- maxRetries,
254
- error: testResult.error || 'Test failed',
255
- },
256
- };
257
- // Create fix ticket
258
- const fixTicket = {
259
- id: `${ticket.id}-FIX-${retryCount}`,
260
- title: `Fix ${ticket.id} test failures`,
261
- description: `Fix the following test failures:\n\n${testResult.error}\n\nOriginal ticket:\n${ticket.description}`,
262
- type: 'backend',
263
- estimatedEffort: 5,
264
- status: 'InProgress',
265
- category: ticket.category,
266
- };
267
- // Run ship to fix test
268
- for await (const shipEvent of shipCoreStream({
269
- ticketData: fixTicket,
270
- review: false,
271
- directory: cwd,
272
- dbUrl,
273
- })) {
274
- yield { type: 'ship_event', data: shipEvent };
275
- if (shipEvent.type === 'done') {
276
- const shipResult = shipEvent.data;
277
- totalInputTokens += shipResult.tokensUsed.input;
278
- totalOutputTokens += shipResult.tokensUsed.output;
279
- totalCacheCreationTokens += shipResult.tokensUsed.cacheCreation;
280
- totalCacheReadTokens += shipResult.tokensUsed.cacheRead;
281
- totalCost += shipResult.cost;
282
- if (!shipResult.success) {
283
- // Fix failed, will retry test anyway
284
- break;
285
- }
286
- }
287
- }
288
- }
289
- }
290
- }
291
- }
292
- if (!testSuccess) {
293
- throw new Error(`Test failed after ${maxRetries} fix attempts`);
294
- }
295
- yield { type: 'ticket_phase', data: { phase: 'test', status: 'completed' } };
296
- }
297
- else {
298
- // Implementation ticket - run ship
299
- yield { type: 'ticket_phase', data: { phase: 'ship', status: 'started' } };
300
- let shipSuccess = false;
301
- for await (const event of shipCoreStream({
302
- ticketData: ticket,
303
- review,
304
- directory: cwd,
305
- dbUrl,
306
- })) {
307
- yield { type: 'ship_event', data: event };
308
- if (event.type === 'done') {
309
- const shipResult = event.data;
310
- shipSuccess = shipResult.success;
311
- totalInputTokens += shipResult.tokensUsed.input;
312
- totalOutputTokens += shipResult.tokensUsed.output;
313
- totalCacheCreationTokens += shipResult.tokensUsed.cacheCreation;
314
- totalCacheReadTokens += shipResult.tokensUsed.cacheRead;
315
- totalCost += shipResult.cost;
316
- if (!shipSuccess) {
317
- throw new Error(shipResult.error || 'Ship failed');
318
- }
319
- }
320
- }
321
- yield { type: 'ticket_phase', data: { phase: 'ship', status: 'completed' } };
322
- // If schema ticket, run migrations
323
- if (ticket.type === 'schema') {
324
- yield { type: 'ticket_phase', data: { phase: 'migrate', status: 'started' } };
325
- let migrateSuccess = false;
326
- for await (const event of migrateCoreStream({
327
- directory: cwd,
328
- dbUrl,
329
- context: {
330
- ticketId: ticket.id,
331
- ticketTitle: ticket.title,
332
- ticketDescription: ticket.description,
333
- },
334
- })) {
335
- yield { type: 'migrate_event', data: event };
336
- if (event.type === 'done') {
337
- const migrateResult = event.data;
338
- migrateSuccess = migrateResult.success;
339
- totalInputTokens += migrateResult.tokensUsed.input;
340
- totalOutputTokens += migrateResult.tokensUsed.output;
341
- totalCacheCreationTokens += migrateResult.tokensUsed.cacheCreation;
342
- totalCacheReadTokens += migrateResult.tokensUsed.cacheRead;
343
- totalCost += migrateResult.cost;
344
- if (!migrateSuccess) {
345
- throw new Error(migrateResult.error || 'Migration failed');
346
- }
347
- }
348
- }
349
- yield { type: 'ticket_phase', data: { phase: 'migrate', status: 'completed' } };
350
- }
351
- }
352
- // Ticket succeeded
353
- updateTicketStatus(ticketsPath, ticket.id, 'Done');
354
- ticketsSucceeded++;
355
- yield {
356
- type: 'ticket_completed',
357
- data: { ticket, result: 'success' },
358
- };
359
- // Auto-commit (no interactive prompts in streaming mode)
360
- const commitMessage = await commitTicket(ticket, cwd);
361
- yield {
362
- type: 'ticket_committed',
363
- data: { ticket, commitMessage },
364
- };
365
- // Yield progress
366
- yield {
367
- type: 'progress',
368
- data: {
369
- completed: i + 1,
370
- total: ticketsToProcess.length,
371
- percentage: Math.round(((i + 1) / ticketsToProcess.length) * 100),
372
- },
373
- };
374
- }
375
- catch (error) {
376
- const errorMessage = error instanceof Error ? error.message : String(error);
377
- // Update ticket status to Error
378
- updateTicketStatus(ticketsPath, ticket.id, 'Error', errorMessage);
379
- ticketsFailed++;
380
- yield {
381
- type: 'ticket_completed',
382
- data: { ticket, result: 'failed' },
383
- };
384
- // Continue to next ticket on failure (don't stop entire build)
385
- yield {
386
- type: 'progress',
387
- data: {
388
- completed: i + 1,
389
- total: ticketsToProcess.length,
390
- percentage: Math.round(((i + 1) / ticketsToProcess.length) * 100),
391
- },
392
- };
393
- }
394
- }
395
- // Yield final result
396
- yield {
397
- type: 'done',
398
- data: {
399
- success: ticketsFailed === 0,
400
- ticketsProcessed: ticketsToProcess.length,
401
- ticketsSucceeded,
402
- ticketsFailed,
403
- totalCost,
404
- tokensUsed: {
405
- input: totalInputTokens,
406
- output: totalOutputTokens,
407
- cacheCreation: totalCacheCreationTokens,
408
- cacheRead: totalCacheReadTokens,
409
- },
410
- },
411
- };
412
- }
413
- /**
414
- * Main build command - processes all tickets and commits each one
415
- */
416
- export async function buildCommand(options) {
417
- console.log('🏗️ Starting Build - Batch Ticket Processing\n');
418
- try {
419
- // Validate environment
420
- if (!process.env.ANTHROPIC_API_KEY) {
421
- throw new Error('ANTHROPIC_API_KEY environment variable is required');
422
- }
423
- if (!process.env.GITHUB_TOKEN) {
424
- throw new Error('GITHUB_TOKEN environment variable is required for build command');
425
- }
426
- const { directory, ticketsFile = 'tickets.json', dbUrl = DEFAULT_DB_URL, reset = false, askConfirm = false, askCommit = false, review = true, url, headless, verbose, trace, noLogs = false, } = options;
427
- // 1. Validate and resolve directory
428
- const cwd = directory ? resolve(directory) : process.cwd();
429
- if (!existsSync(cwd)) {
430
- throw new Error(`Directory not found: ${cwd}\n` +
431
- `Please provide a valid directory using --directory=<path>\n` +
432
- `Example: kosuke build --directory=./my-project`);
433
- }
434
- const stats = statSync(cwd);
435
- if (!stats.isDirectory()) {
436
- throw new Error(`Path is not a directory: ${cwd}\n` + `Please provide a valid directory path.`);
437
- }
438
- console.log(`📁 Using project directory: ${cwd}\n`);
439
- const ticketsPath = join(cwd, ticketsFile);
440
- // 2. Load tickets
441
- console.log('📋 Loading tickets...');
442
- const ticketsData = loadTicketsFile(ticketsPath);
443
- // 3. Reset all tickets to "Todo" if --reset flag is provided
444
- if (reset) {
445
- console.log('🔄 Resetting all tickets to "Todo" status...');
446
- let resetCount = 0;
447
- ticketsData.tickets.forEach((ticket) => {
448
- if (ticket.status !== 'Todo') {
449
- ticket.status = 'Todo';
450
- delete ticket.error;
451
- resetCount++;
452
- }
453
- });
454
- saveTicketsFile(ticketsPath, ticketsData);
455
- console.log(` ✅ Reset ${resetCount} ticket(s) to "Todo" status\n`);
456
- }
457
- const ticketsToProcess = getTicketsToProcess(ticketsData);
458
- if (ticketsToProcess.length === 0) {
459
- console.log('ℹ️ No tickets found with status "Todo" or "Error"');
460
- return;
461
- }
462
- console.log(` ✅ Found ${ticketsToProcess.length} ticket(s) to process\n`);
463
- // Display tickets to be processed
464
- console.log('📦 Tickets to be processed:');
465
- ticketsToProcess.forEach((ticket, index) => {
466
- console.log(` ${index + 1}. ${ticket.id}: ${ticket.title}`);
467
- });
468
- console.log('');
469
- // 4. Process each ticket sequentially
470
- for (let i = 0; i < ticketsToProcess.length; i++) {
471
- const ticket = ticketsToProcess[i];
472
- console.log('\n' + '='.repeat(80));
473
- console.log(`📦 Processing Ticket ${i + 1}/${ticketsToProcess.length}: ${ticket.id}`);
474
- console.log(`📝 ${ticket.title}`);
475
- console.log('='.repeat(80) + '\n');
476
- try {
477
- // Step 1: Update status to InProgress
478
- console.log('📝 Updating ticket status to InProgress...');
479
- updateTicketStatus(ticketsPath, ticket.id, 'InProgress');
480
- console.log(' ✅ Status updated\n');
481
- // Step 2: Process ticket based on type
482
- const isTestTicket = ticket.type === 'test';
483
- const isSchemaTicket = ticket.type === 'schema';
484
- if (isTestTicket) {
485
- // This is a test ticket - run test with retry
486
- console.log(`\n${'='.repeat(60)}`);
487
- console.log(`🧪 Running Test`);
488
- console.log(`${'='.repeat(60)}\n`);
489
- // Generate test prompt from ticket
490
- const testPrompt = generateWebTestPrompt(ticket);
491
- let testResult = await testCore({
492
- prompt: testPrompt,
493
- context: {
494
- ticketId: ticket.id,
495
- ticketTitle: ticket.title,
496
- ticketDescription: ticket.description,
497
- },
498
- url,
499
- headless,
500
- verbose,
501
- trace,
502
- noLogs,
503
- });
504
- let retryCount = 0;
505
- const maxRetries = 3;
506
- // Retry loop: if test fails, run ship to fix it
507
- while (!testResult.success && retryCount < maxRetries) {
508
- retryCount++;
509
- console.log(`\n⚠️ Test failed (attempt ${retryCount}/${maxRetries})`);
510
- console.log(`📝 Error: ${testResult.error}\n`);
511
- console.log(`🔧 Running ship to fix test failures...\n`);
512
- // Create a fix ticket for ship
513
- const fixTicket = {
514
- id: `${ticket.id}-FIX-${retryCount}`,
515
- title: `Fix ${ticket.id} test failures`,
516
- description: `Fix the following test failures:\n\n${testResult.error}\n\nOriginal ticket:\n${ticket.description}`,
517
- type: 'backend', // Use backend type for test fix tickets
518
- estimatedEffort: 5,
519
- status: 'InProgress',
520
- category: ticket.category,
521
- };
522
- const shipResult = await shipCore({
523
- ticketData: fixTicket,
524
- review: false, // Skip review for test fixes
525
- directory: cwd,
526
- dbUrl,
527
- noLogs,
528
- });
529
- if (!shipResult.success) {
530
- console.error(`\n❌ Fix attempt ${retryCount} failed: ${shipResult.error}`);
531
- continue;
532
- }
533
- console.log(`\n✅ Fix applied (attempt ${retryCount})`);
534
- console.log(`💰 Fix cost: $${shipResult.cost.toFixed(4)}\n`);
535
- // Re-run test
536
- console.log(`🔄 Re-running test...\n`);
537
- testResult = await testCore({
538
- prompt: testPrompt,
539
- context: {
540
- ticketId: ticket.id,
541
- ticketTitle: ticket.title,
542
- ticketDescription: ticket.description,
543
- },
544
- url,
545
- headless,
546
- verbose,
547
- trace,
548
- noLogs,
549
- });
550
- }
551
- if (!testResult.success) {
552
- throw new Error(`Test failed after ${maxRetries} fix attempts:\n${testResult.error}`);
553
- }
554
- console.log(`\n✅ ${ticket.id} test passed`);
555
- console.log(`💰 Test cost: $${testResult.cost.toFixed(4)}`);
556
- }
557
- else {
558
- // Regular implementation ticket - run ship
559
- const shipResult = await shipCore({
560
- ticketData: ticket,
561
- review,
562
- directory: cwd,
563
- dbUrl,
564
- noLogs,
565
- });
566
- if (!shipResult.success) {
567
- throw new Error(shipResult.error || 'Ship failed');
568
- }
569
- console.log(`\n✅ ${ticket.id} implemented successfully`);
570
- console.log(`📊 Implementation fixes: ${shipResult.implementationFixCount}`);
571
- console.log(`🔧 Linting fixes: ${shipResult.lintFixCount}`);
572
- if (shipResult.reviewFixCount > 0) {
573
- console.log(`🔍 Review fixes: ${shipResult.reviewFixCount}`);
574
- }
575
- console.log(`💰 Ship cost: $${shipResult.cost.toFixed(4)}`);
576
- // If this is a schema ticket, run migrations
577
- if (isSchemaTicket) {
578
- console.log(`\n${'='.repeat(60)}`);
579
- console.log(`🗄️ Phase 4: Database Migration & Validation`);
580
- console.log(`${'='.repeat(60)}\n`);
581
- const migrateResult = await migrateCore({
582
- directory: cwd,
583
- dbUrl,
584
- context: {
585
- ticketId: ticket.id,
586
- ticketTitle: ticket.title,
587
- ticketDescription: ticket.description,
588
- },
589
- noLogs,
590
- });
591
- if (!migrateResult.success) {
592
- throw new Error(`Migration failed: ${migrateResult.error}`);
593
- }
594
- console.log(`\n✅ Migrations applied and validated`);
595
- console.log(` ✓ Migrations applied: ${migrateResult.migrationsApplied}`);
596
- console.log(` ✓ Seeding completed: ${migrateResult.seedingCompleted}`);
597
- console.log(` ✓ Validation passed: ${migrateResult.validationPassed}`);
598
- console.log(`💰 Migration cost: $${migrateResult.cost.toFixed(4)}`);
599
- }
600
- }
601
- // Step 3: Update ticket status to Done
602
- console.log('\n📝 Updating ticket status to Done...');
603
- updateTicketStatus(ticketsPath, ticket.id, 'Done');
604
- console.log(` ✅ Ticket ${ticket.id} marked as Done\n`);
605
- // Step 4: Commit this ticket
606
- if (askCommit) {
607
- // Interactive: ask before committing
608
- const commitConfirmed = await promptConfirmation(`\n❓ Commit ${ticket.id}?`);
609
- if (commitConfirmed) {
610
- const commitMessage = await commitTicket(ticket, cwd);
611
- console.log(`\n ✅ Committed: ${commitMessage}\n`);
612
- }
613
- else {
614
- console.log(' ⏭️ Skipped commit for this ticket\n');
615
- }
616
- }
617
- else {
618
- // Default: auto-commit each ticket
619
- const commitMessage = await commitTicket(ticket, cwd);
620
- console.log(`\n ✅ Committed: ${commitMessage}\n`);
621
- }
622
- // Ask for confirmation before proceeding to next ticket (if not last ticket)
623
- if (askConfirm && i < ticketsToProcess.length - 1) {
624
- const shouldContinue = await promptConfirmation('\n❓ Proceed to next ticket?');
625
- if (!shouldContinue) {
626
- console.log('\n⏸️ Build paused by user');
627
- console.log(`📊 Progress: ${i + 1}/${ticketsToProcess.length} tickets completed`);
628
- console.log('ℹ️ Run build again to resume from remaining tickets\n');
629
- return;
630
- }
631
- }
632
- }
633
- catch (error) {
634
- const errorMessage = error instanceof Error ? error.message : String(error);
635
- console.error(`\n❌ Failed to process ${ticket.id}: ${errorMessage}`);
636
- // Update ticket status to Error
637
- updateTicketStatus(ticketsPath, ticket.id, 'Error', errorMessage);
638
- console.error('\n❌ Build stopped due to ticket failure');
639
- console.error('ℹ️ Fix the issue and run build again to resume from failed tickets\n');
640
- throw error;
641
- }
642
- }
643
- // 5. Display final summary
644
- console.log('\n' + '='.repeat(80));
645
- console.log('✅ Build Completed Successfully!');
646
- console.log('='.repeat(80));
647
- console.log(`📦 Total tickets processed: ${ticketsToProcess.length}`);
648
- console.log(`✅ All tickets have been implemented and committed`);
649
- console.log('='.repeat(80));
650
- console.log('\n💡 Next steps:');
651
- console.log(' - Review the commits: git log');
652
- console.log(' - Create a PR using: gh pr create');
653
- console.log(' - Or push to remote: git push origin <branch-name>\n');
654
- }
655
- catch (error) {
656
- console.error('\n❌ Build failed:', error);
657
- throw error;
658
- }
659
- }
660
- //# sourceMappingURL=build.js.map