@kosuke-ai/cli 0.0.56 → 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 (251) 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 -516
  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 -35
  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 -273
  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 -659
  110. package/dist/kosuke/commands/build.js.map +0 -1
  111. package/dist/kosuke/commands/getcode.d.ts +0 -29
  112. package/dist/kosuke/commands/getcode.d.ts.map +0 -1
  113. package/dist/kosuke/commands/getcode.js +0 -221
  114. package/dist/kosuke/commands/getcode.js.map +0 -1
  115. package/dist/kosuke/commands/lint.d.ts +0 -21
  116. package/dist/kosuke/commands/lint.d.ts.map +0 -1
  117. package/dist/kosuke/commands/lint.js +0 -321
  118. package/dist/kosuke/commands/lint.js.map +0 -1
  119. package/dist/kosuke/commands/migrate.d.ts +0 -38
  120. package/dist/kosuke/commands/migrate.d.ts.map +0 -1
  121. package/dist/kosuke/commands/migrate.js +0 -284
  122. package/dist/kosuke/commands/migrate.js.map +0 -1
  123. package/dist/kosuke/commands/plan.d.ts +0 -28
  124. package/dist/kosuke/commands/plan.d.ts.map +0 -1
  125. package/dist/kosuke/commands/plan.js +0 -630
  126. package/dist/kosuke/commands/plan.js.map +0 -1
  127. package/dist/kosuke/commands/requirements.d.ts +0 -52
  128. package/dist/kosuke/commands/requirements.d.ts.map +0 -1
  129. package/dist/kosuke/commands/requirements.js +0 -615
  130. package/dist/kosuke/commands/requirements.js.map +0 -1
  131. package/dist/kosuke/commands/review.d.ts +0 -26
  132. package/dist/kosuke/commands/review.d.ts.map +0 -1
  133. package/dist/kosuke/commands/review.js +0 -303
  134. package/dist/kosuke/commands/review.js.map +0 -1
  135. package/dist/kosuke/commands/serve.d.ts +0 -9
  136. package/dist/kosuke/commands/serve.d.ts.map +0 -1
  137. package/dist/kosuke/commands/serve.js +0 -17
  138. package/dist/kosuke/commands/serve.js.map +0 -1
  139. package/dist/kosuke/commands/ship.d.ts +0 -37
  140. package/dist/kosuke/commands/ship.d.ts.map +0 -1
  141. package/dist/kosuke/commands/ship.js +0 -375
  142. package/dist/kosuke/commands/ship.js.map +0 -1
  143. package/dist/kosuke/commands/sync-rules.d.ts +0 -9
  144. package/dist/kosuke/commands/sync-rules.d.ts.map +0 -1
  145. package/dist/kosuke/commands/sync-rules.js +0 -379
  146. package/dist/kosuke/commands/sync-rules.js.map +0 -1
  147. package/dist/kosuke/commands/test.d.ts +0 -42
  148. package/dist/kosuke/commands/test.d.ts.map +0 -1
  149. package/dist/kosuke/commands/test.js +0 -540
  150. package/dist/kosuke/commands/test.js.map +0 -1
  151. package/dist/kosuke/commands/tickets.d.ts +0 -43
  152. package/dist/kosuke/commands/tickets.d.ts.map +0 -1
  153. package/dist/kosuke/commands/tickets.js +0 -499
  154. package/dist/kosuke/commands/tickets.js.map +0 -1
  155. package/dist/kosuke/serve/middleware/error-handler.d.ts +0 -14
  156. package/dist/kosuke/serve/middleware/error-handler.d.ts.map +0 -1
  157. package/dist/kosuke/serve/middleware/error-handler.js +0 -42
  158. package/dist/kosuke/serve/middleware/error-handler.js.map +0 -1
  159. package/dist/kosuke/serve/middleware/validation.d.ts +0 -13
  160. package/dist/kosuke/serve/middleware/validation.d.ts.map +0 -1
  161. package/dist/kosuke/serve/middleware/validation.js +0 -38
  162. package/dist/kosuke/serve/middleware/validation.js.map +0 -1
  163. package/dist/kosuke/serve/routes/build.d.ts +0 -6
  164. package/dist/kosuke/serve/routes/build.d.ts.map +0 -1
  165. package/dist/kosuke/serve/routes/build.js +0 -226
  166. package/dist/kosuke/serve/routes/build.js.map +0 -1
  167. package/dist/kosuke/serve/routes/health.d.ts +0 -6
  168. package/dist/kosuke/serve/routes/health.d.ts.map +0 -1
  169. package/dist/kosuke/serve/routes/health.js +0 -11
  170. package/dist/kosuke/serve/routes/health.js.map +0 -1
  171. package/dist/kosuke/serve/routes/plan.d.ts +0 -6
  172. package/dist/kosuke/serve/routes/plan.d.ts.map +0 -1
  173. package/dist/kosuke/serve/routes/plan.js +0 -106
  174. package/dist/kosuke/serve/routes/plan.js.map +0 -1
  175. package/dist/kosuke/serve/server.d.ts +0 -16
  176. package/dist/kosuke/serve/server.d.ts.map +0 -1
  177. package/dist/kosuke/serve/server.js +0 -67
  178. package/dist/kosuke/serve/server.js.map +0 -1
  179. package/dist/kosuke/serve/validation/build.d.ts +0 -41
  180. package/dist/kosuke/serve/validation/build.d.ts.map +0 -1
  181. package/dist/kosuke/serve/validation/build.js +0 -20
  182. package/dist/kosuke/serve/validation/build.js.map +0 -1
  183. package/dist/kosuke/serve/validation/plan.d.ts +0 -26
  184. package/dist/kosuke/serve/validation/plan.d.ts.map +0 -1
  185. package/dist/kosuke/serve/validation/plan.js +0 -15
  186. package/dist/kosuke/serve/validation/plan.js.map +0 -1
  187. package/dist/kosuke/types.d.ts +0 -469
  188. package/dist/kosuke/types.d.ts.map +0 -1
  189. package/dist/kosuke/types.js +0 -5
  190. package/dist/kosuke/types.js.map +0 -1
  191. package/dist/kosuke/utils/batch-creator.d.ts +0 -14
  192. package/dist/kosuke/utils/batch-creator.d.ts.map +0 -1
  193. package/dist/kosuke/utils/batch-creator.js +0 -76
  194. package/dist/kosuke/utils/batch-creator.js.map +0 -1
  195. package/dist/kosuke/utils/claude-agent.d.ts +0 -145
  196. package/dist/kosuke/utils/claude-agent.d.ts.map +0 -1
  197. package/dist/kosuke/utils/claude-agent.js +0 -504
  198. package/dist/kosuke/utils/claude-agent.js.map +0 -1
  199. package/dist/kosuke/utils/constants.d.ts +0 -40
  200. package/dist/kosuke/utils/constants.d.ts.map +0 -1
  201. package/dist/kosuke/utils/constants.js +0 -54
  202. package/dist/kosuke/utils/constants.js.map +0 -1
  203. package/dist/kosuke/utils/file-discovery.d.ts +0 -15
  204. package/dist/kosuke/utils/file-discovery.d.ts.map +0 -1
  205. package/dist/kosuke/utils/file-discovery.js +0 -80
  206. package/dist/kosuke/utils/file-discovery.js.map +0 -1
  207. package/dist/kosuke/utils/git.d.ts +0 -41
  208. package/dist/kosuke/utils/git.d.ts.map +0 -1
  209. package/dist/kosuke/utils/git.js +0 -145
  210. package/dist/kosuke/utils/git.js.map +0 -1
  211. package/dist/kosuke/utils/github.d.ts +0 -17
  212. package/dist/kosuke/utils/github.d.ts.map +0 -1
  213. package/dist/kosuke/utils/github.js +0 -22
  214. package/dist/kosuke/utils/github.js.map +0 -1
  215. package/dist/kosuke/utils/interactive-input.d.ts +0 -22
  216. package/dist/kosuke/utils/interactive-input.d.ts.map +0 -1
  217. package/dist/kosuke/utils/interactive-input.js +0 -124
  218. package/dist/kosuke/utils/interactive-input.js.map +0 -1
  219. package/dist/kosuke/utils/logger.d.ts +0 -161
  220. package/dist/kosuke/utils/logger.d.ts.map +0 -1
  221. package/dist/kosuke/utils/logger.js +0 -234
  222. package/dist/kosuke/utils/logger.js.map +0 -1
  223. package/dist/kosuke/utils/playwright-mcp-client.d.ts +0 -46
  224. package/dist/kosuke/utils/playwright-mcp-client.d.ts.map +0 -1
  225. package/dist/kosuke/utils/playwright-mcp-client.js +0 -135
  226. package/dist/kosuke/utils/playwright-mcp-client.js.map +0 -1
  227. package/dist/kosuke/utils/pr-orchestrator.d.ts +0 -49
  228. package/dist/kosuke/utils/pr-orchestrator.d.ts.map +0 -1
  229. package/dist/kosuke/utils/pr-orchestrator.js +0 -154
  230. package/dist/kosuke/utils/pr-orchestrator.js.map +0 -1
  231. package/dist/kosuke/utils/repository-manager.d.ts +0 -13
  232. package/dist/kosuke/utils/repository-manager.d.ts.map +0 -1
  233. package/dist/kosuke/utils/repository-manager.js +0 -94
  234. package/dist/kosuke/utils/repository-manager.js.map +0 -1
  235. package/dist/kosuke/utils/repository-resolver.d.ts +0 -12
  236. package/dist/kosuke/utils/repository-resolver.d.ts.map +0 -1
  237. package/dist/kosuke/utils/repository-resolver.js +0 -186
  238. package/dist/kosuke/utils/repository-resolver.js.map +0 -1
  239. package/dist/kosuke/utils/tickets-manager.d.ts +0 -64
  240. package/dist/kosuke/utils/tickets-manager.d.ts.map +0 -1
  241. package/dist/kosuke/utils/tickets-manager.js +0 -331
  242. package/dist/kosuke/utils/tickets-manager.js.map +0 -1
  243. package/dist/kosuke/utils/validator.d.ts +0 -45
  244. package/dist/kosuke/utils/validator.d.ts.map +0 -1
  245. package/dist/kosuke/utils/validator.js +0 -248
  246. package/dist/kosuke/utils/validator.js.map +0 -1
  247. package/dist/lib.d.ts +0 -96
  248. package/dist/lib.d.ts.map +0 -1
  249. package/dist/lib.js +0 -95
  250. package/dist/lib.js.map +0 -1
  251. package/dist/package.json +0 -99
@@ -1,659 +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 -> WEB-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('WEB-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
- if (isTestTicket) {
484
- // This is a test ticket - run test with retry
485
- console.log(`\n${'='.repeat(60)}`);
486
- console.log(`🧪 Running Test`);
487
- console.log(`${'='.repeat(60)}\n`);
488
- // Generate test prompt from ticket
489
- const testPrompt = generateWebTestPrompt(ticket);
490
- let testResult = await testCore({
491
- prompt: testPrompt,
492
- context: {
493
- ticketId: ticket.id,
494
- ticketTitle: ticket.title,
495
- ticketDescription: ticket.description,
496
- },
497
- url,
498
- headless,
499
- verbose,
500
- trace,
501
- noLogs,
502
- });
503
- let retryCount = 0;
504
- const maxRetries = 3;
505
- // Retry loop: if test fails, run ship to fix it
506
- while (!testResult.success && retryCount < maxRetries) {
507
- retryCount++;
508
- console.log(`\n⚠️ Test failed (attempt ${retryCount}/${maxRetries})`);
509
- console.log(`📝 Error: ${testResult.error}\n`);
510
- console.log(`🔧 Running ship to fix test failures...\n`);
511
- // Create a fix ticket for ship
512
- const fixTicket = {
513
- id: `${ticket.id}-FIX-${retryCount}`,
514
- title: `Fix ${ticket.id} test failures`,
515
- description: `Fix the following test failures:\n\n${testResult.error}\n\nOriginal ticket:\n${ticket.description}`,
516
- type: 'backend', // Use backend type for test fix tickets
517
- estimatedEffort: 5,
518
- status: 'InProgress',
519
- category: ticket.category,
520
- };
521
- const shipResult = await shipCore({
522
- ticketData: fixTicket,
523
- review: false, // Skip review for test fixes
524
- directory: cwd,
525
- dbUrl,
526
- noLogs,
527
- });
528
- if (!shipResult.success) {
529
- console.error(`\n❌ Fix attempt ${retryCount} failed: ${shipResult.error}`);
530
- continue;
531
- }
532
- console.log(`\n✅ Fix applied (attempt ${retryCount})`);
533
- console.log(`💰 Fix cost: $${shipResult.cost.toFixed(4)}\n`);
534
- // Re-run test
535
- console.log(`🔄 Re-running test...\n`);
536
- testResult = await testCore({
537
- prompt: testPrompt,
538
- context: {
539
- ticketId: ticket.id,
540
- ticketTitle: ticket.title,
541
- ticketDescription: ticket.description,
542
- },
543
- url,
544
- headless,
545
- verbose,
546
- trace,
547
- noLogs,
548
- });
549
- }
550
- if (!testResult.success) {
551
- throw new Error(`Test failed after ${maxRetries} fix attempts:\n${testResult.error}`);
552
- }
553
- console.log(`\n✅ ${ticket.id} test passed`);
554
- console.log(`💰 Test cost: $${testResult.cost.toFixed(4)}`);
555
- }
556
- else {
557
- // Regular implementation ticket - run ship
558
- const shipResult = await shipCore({
559
- ticketData: ticket,
560
- review,
561
- directory: cwd,
562
- dbUrl,
563
- noLogs,
564
- });
565
- if (!shipResult.success) {
566
- throw new Error(shipResult.error || 'Ship failed');
567
- }
568
- console.log(`\n✅ ${ticket.id} implemented successfully`);
569
- console.log(`📊 Implementation fixes: ${shipResult.implementationFixCount}`);
570
- console.log(`🔧 Linting fixes: ${shipResult.lintFixCount}`);
571
- if (shipResult.reviewFixCount > 0) {
572
- console.log(`🔍 Review fixes: ${shipResult.reviewFixCount}`);
573
- }
574
- console.log(`💰 Ship cost: $${shipResult.cost.toFixed(4)}`);
575
- // If this is a schema ticket, run migrations
576
- if (ticket.type === 'schema') {
577
- console.log(`\n${'='.repeat(60)}`);
578
- console.log(`🗄️ Phase 4: Database Migration & Validation`);
579
- console.log(`${'='.repeat(60)}\n`);
580
- const migrateResult = await migrateCore({
581
- directory: cwd,
582
- dbUrl,
583
- context: {
584
- ticketId: ticket.id,
585
- ticketTitle: ticket.title,
586
- ticketDescription: ticket.description,
587
- },
588
- noLogs,
589
- });
590
- if (!migrateResult.success) {
591
- throw new Error(`Migration failed: ${migrateResult.error}`);
592
- }
593
- console.log(`\n✅ Migrations applied and validated`);
594
- console.log(` ✓ Migrations applied: ${migrateResult.migrationsApplied}`);
595
- console.log(` ✓ Seeding completed: ${migrateResult.seedingCompleted}`);
596
- console.log(` ✓ Validation passed: ${migrateResult.validationPassed}`);
597
- console.log(`💰 Migration cost: $${migrateResult.cost.toFixed(4)}`);
598
- }
599
- }
600
- // Step 3: Update ticket status to Done
601
- console.log('\n📝 Updating ticket status to Done...');
602
- updateTicketStatus(ticketsPath, ticket.id, 'Done');
603
- console.log(` ✅ Ticket ${ticket.id} marked as Done\n`);
604
- // Step 4: Commit this ticket
605
- if (askCommit) {
606
- // Interactive: ask before committing
607
- const commitConfirmed = await promptConfirmation(`\n❓ Commit ${ticket.id}?`);
608
- if (commitConfirmed) {
609
- const commitMessage = await commitTicket(ticket, cwd);
610
- console.log(`\n ✅ Committed: ${commitMessage}\n`);
611
- }
612
- else {
613
- console.log(' ⏭️ Skipped commit for this ticket\n');
614
- }
615
- }
616
- else {
617
- // Default: auto-commit each ticket
618
- const commitMessage = await commitTicket(ticket, cwd);
619
- console.log(`\n ✅ Committed: ${commitMessage}\n`);
620
- }
621
- // Ask for confirmation before proceeding to next ticket (if not last ticket)
622
- if (askConfirm && i < ticketsToProcess.length - 1) {
623
- const shouldContinue = await promptConfirmation('\n❓ Proceed to next ticket?');
624
- if (!shouldContinue) {
625
- console.log('\n⏸️ Build paused by user');
626
- console.log(`📊 Progress: ${i + 1}/${ticketsToProcess.length} tickets completed`);
627
- console.log('ℹ️ Run build again to resume from remaining tickets\n');
628
- return;
629
- }
630
- }
631
- }
632
- catch (error) {
633
- const errorMessage = error instanceof Error ? error.message : String(error);
634
- console.error(`\n❌ Failed to process ${ticket.id}: ${errorMessage}`);
635
- // Update ticket status to Error
636
- updateTicketStatus(ticketsPath, ticket.id, 'Error', errorMessage);
637
- console.error('\n❌ Build stopped due to ticket failure');
638
- console.error('ℹ️ Fix the issue and run build again to resume from failed tickets\n');
639
- throw error;
640
- }
641
- }
642
- // 5. Display final summary
643
- console.log('\n' + '='.repeat(80));
644
- console.log('✅ Build Completed Successfully!');
645
- console.log('='.repeat(80));
646
- console.log(`📦 Total tickets processed: ${ticketsToProcess.length}`);
647
- console.log(`✅ All tickets have been implemented and committed`);
648
- console.log('='.repeat(80));
649
- console.log('\n💡 Next steps:');
650
- console.log(' - Review the commits: git log');
651
- console.log(' - Create a PR using: gh pr create');
652
- console.log(' - Or push to remote: git push origin <branch-name>\n');
653
- }
654
- catch (error) {
655
- console.error('\n❌ Build failed:', error);
656
- throw error;
657
- }
658
- }
659
- //# sourceMappingURL=build.js.map