@autocode-cli/autocode 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -0
- package/bin/autocode +2 -0
- package/dist/cli/commands/comment.d.ts +9 -0
- package/dist/cli/commands/comment.d.ts.map +1 -0
- package/dist/cli/commands/comment.js +37 -0
- package/dist/cli/commands/comment.js.map +1 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +41 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/list.d.ts +9 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +78 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/move.d.ts +9 -0
- package/dist/cli/commands/move.d.ts.map +1 -0
- package/dist/cli/commands/move.js +59 -0
- package/dist/cli/commands/move.js.map +1 -0
- package/dist/cli/commands/new.d.ts +9 -0
- package/dist/cli/commands/new.d.ts.map +1 -0
- package/dist/cli/commands/new.js +74 -0
- package/dist/cli/commands/new.js.map +1 -0
- package/dist/cli/commands/next.d.ts +9 -0
- package/dist/cli/commands/next.d.ts.map +1 -0
- package/dist/cli/commands/next.js +46 -0
- package/dist/cli/commands/next.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +9 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +55 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/show.d.ts +9 -0
- package/dist/cli/commands/show.d.ts.map +1 -0
- package/dist/cli/commands/show.js +91 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/parser.d.ts +13 -0
- package/dist/cli/parser.d.ts.map +1 -0
- package/dist/cli/parser.js +54 -0
- package/dist/cli/parser.js.map +1 -0
- package/dist/core/column.d.ts +53 -0
- package/dist/core/column.d.ts.map +1 -0
- package/dist/core/column.js +128 -0
- package/dist/core/column.js.map +1 -0
- package/dist/core/ticket.d.ts +50 -0
- package/dist/core/ticket.d.ts.map +1 -0
- package/dist/core/ticket.js +228 -0
- package/dist/core/ticket.js.map +1 -0
- package/dist/core/workflow.d.ts +66 -0
- package/dist/core/workflow.d.ts.map +1 -0
- package/dist/core/workflow.js +176 -0
- package/dist/core/workflow.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/server/api.d.ts +9 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +313 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/dashboard.d.ts +8 -0
- package/dist/server/dashboard.d.ts.map +1 -0
- package/dist/server/dashboard.js +1865 -0
- package/dist/server/dashboard.js.map +1 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +94 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/watcher.d.ts +13 -0
- package/dist/server/watcher.d.ts.map +1 -0
- package/dist/server/watcher.js +62 -0
- package/dist/server/watcher.js.map +1 -0
- package/dist/server/websocket.d.ts +26 -0
- package/dist/server/websocket.d.ts.map +1 -0
- package/dist/server/websocket.js +165 -0
- package/dist/server/websocket.js.map +1 -0
- package/dist/services/claude.d.ts +52 -0
- package/dist/services/claude.d.ts.map +1 -0
- package/dist/services/claude.js +304 -0
- package/dist/services/claude.js.map +1 -0
- package/dist/services/ticket-io.d.ts +76 -0
- package/dist/services/ticket-io.d.ts.map +1 -0
- package/dist/services/ticket-io.js +248 -0
- package/dist/services/ticket-io.js.map +1 -0
- package/dist/types/index.d.ts +79 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config.d.ts +93 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +96 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/fs.d.ts +60 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +129 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/logger.d.ts +23 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +56 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +57 -0
- package/templates/columns/00_backlog.en.md +31 -0
- package/templates/columns/00_backlog.fr.md +31 -0
- package/templates/columns/01_ready.en.md +30 -0
- package/templates/columns/01_ready.fr.md +30 -0
- package/templates/columns/02_in-progress.en.md +30 -0
- package/templates/columns/02_in-progress.fr.md +30 -0
- package/templates/columns/03_review-best-practices.en.md +31 -0
- package/templates/columns/03_review-best-practices.fr.md +31 -0
- package/templates/columns/04_review-no-duplication.en.md +30 -0
- package/templates/columns/04_review-no-duplication.fr.md +30 -0
- package/templates/columns/05_review-consistency.en.md +31 -0
- package/templates/columns/05_review-consistency.fr.md +31 -0
- package/templates/columns/06_review-security.en.md +32 -0
- package/templates/columns/06_review-security.fr.md +32 -0
- package/templates/columns/07_testing-playwright.en.md +30 -0
- package/templates/columns/07_testing-playwright.fr.md +30 -0
- package/templates/columns/08_testing-cypress.en.md +31 -0
- package/templates/columns/08_testing-cypress.fr.md +31 -0
- package/templates/columns/09_update-docs.en.md +29 -0
- package/templates/columns/09_update-docs.fr.md +29 -0
- package/templates/columns/10_deploy-staging.en.md +29 -0
- package/templates/columns/10_deploy-staging.fr.md +29 -0
- package/templates/columns/11_validate-staging.en.md +32 -0
- package/templates/columns/11_validate-staging.fr.md +32 -0
- package/templates/columns/12_done.en.md +23 -0
- package/templates/columns/12_done.fr.md +23 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI integration service
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { appendFileSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { readFileSafe, writeFileSafe } from '../utils/fs.js';
|
|
8
|
+
import { getConfig } from '../utils/config.js';
|
|
9
|
+
import { getTicket, addComment, nextTicket, findTicketDir } from '../core/ticket.js';
|
|
10
|
+
import { getColumnBySlug } from '../core/column.js';
|
|
11
|
+
import { broadcast } from '../server/websocket.js';
|
|
12
|
+
import { logger } from '../utils/logger.js';
|
|
13
|
+
/**
|
|
14
|
+
* Get the ACTION.md content for a column
|
|
15
|
+
*/
|
|
16
|
+
export function getActionContent(columnSlug, lang = 'fr') {
|
|
17
|
+
const config = getConfig();
|
|
18
|
+
const actionFile = join(config.root, columnSlug, `ACTION.${lang}.md`);
|
|
19
|
+
return readFileSafe(actionFile);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build prompt for Claude based on ticket and column
|
|
23
|
+
*/
|
|
24
|
+
export function buildPrompt(ticket, actionContent) {
|
|
25
|
+
const prompt = `# Task: Process Ticket ${ticket.key}
|
|
26
|
+
|
|
27
|
+
## Ticket Information
|
|
28
|
+
|
|
29
|
+
- **Key**: ${ticket.key}
|
|
30
|
+
- **Title**: ${ticket.title}
|
|
31
|
+
- **Priority**: ${ticket.priority}
|
|
32
|
+
- **Status**: ${ticket.status}
|
|
33
|
+
- **Labels**: ${ticket.labels.join(', ') || 'None'}
|
|
34
|
+
|
|
35
|
+
## Description
|
|
36
|
+
|
|
37
|
+
${ticket.description}
|
|
38
|
+
|
|
39
|
+
## Acceptance Criteria
|
|
40
|
+
|
|
41
|
+
${ticket.acceptance_criteria.map(c => `- ${c}`).join('\n')}
|
|
42
|
+
|
|
43
|
+
## Column Instructions
|
|
44
|
+
|
|
45
|
+
${actionContent}
|
|
46
|
+
|
|
47
|
+
## Previous Comments
|
|
48
|
+
|
|
49
|
+
${ticket.comments.length > 0
|
|
50
|
+
? ticket.comments.map(c => `[${c.column}] ${c.text}`).join('\n\n')
|
|
51
|
+
: 'No previous comments.'}
|
|
52
|
+
|
|
53
|
+
## Your Task
|
|
54
|
+
|
|
55
|
+
Follow the column instructions above to process this ticket.
|
|
56
|
+
Provide a detailed response of what was done.
|
|
57
|
+
If any issues were encountered, explain them clearly.
|
|
58
|
+
`;
|
|
59
|
+
return prompt;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Write prompt to file for Claude
|
|
63
|
+
*/
|
|
64
|
+
export function writePromptFile(ticket, prompt) {
|
|
65
|
+
const config = getConfig();
|
|
66
|
+
const column = getColumnBySlug(ticket.column_slug);
|
|
67
|
+
if (!column) {
|
|
68
|
+
throw new Error(`Column not found: ${ticket.column_slug}`);
|
|
69
|
+
}
|
|
70
|
+
const promptFile = join(config.root, column.slug, `.claude_prompt_${ticket.key}.md`);
|
|
71
|
+
writeFileSafe(promptFile, prompt);
|
|
72
|
+
return promptFile;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Execute Claude CLI with a prompt (with live logging to file)
|
|
76
|
+
*/
|
|
77
|
+
export async function executeClaudeCLI(promptFile, ticketKey) {
|
|
78
|
+
const config = getConfig();
|
|
79
|
+
const startTime = Date.now();
|
|
80
|
+
// Find ticket directory for log file
|
|
81
|
+
let logPath = null;
|
|
82
|
+
if (ticketKey) {
|
|
83
|
+
const ticketDir = findTicketDir(config.root, ticketKey);
|
|
84
|
+
if (ticketDir) {
|
|
85
|
+
logPath = join(ticketDir, 'claude-code.log');
|
|
86
|
+
// Reset log file
|
|
87
|
+
writeFileSync(logPath, `[${new Date().toISOString()}] Starting Claude processing...\n`);
|
|
88
|
+
}
|
|
89
|
+
broadcast({ type: 'claude_start', ticket: ticketKey });
|
|
90
|
+
}
|
|
91
|
+
// Read prompt file content for stdin
|
|
92
|
+
const promptContent = readFileSafe(promptFile) || '';
|
|
93
|
+
return new Promise((resolve) => {
|
|
94
|
+
const child = spawn('claude', [
|
|
95
|
+
'--output-format', 'stream-json',
|
|
96
|
+
'--verbose',
|
|
97
|
+
'--dangerously-skip-permissions',
|
|
98
|
+
], {
|
|
99
|
+
cwd: process.cwd(),
|
|
100
|
+
timeout: config.claudeTimeout,
|
|
101
|
+
});
|
|
102
|
+
// Send prompt via stdin
|
|
103
|
+
child.stdin.write(promptContent);
|
|
104
|
+
child.stdin.end();
|
|
105
|
+
let stdout = '';
|
|
106
|
+
let stderr = '';
|
|
107
|
+
child.stdout.on('data', (data) => {
|
|
108
|
+
const lines = data.toString().split('\n').filter(Boolean);
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
try {
|
|
111
|
+
const event = JSON.parse(line);
|
|
112
|
+
// Show system init status
|
|
113
|
+
if (event.type === 'system' && event.subtype === 'init') {
|
|
114
|
+
const initMsg = `🚀 Claude initialized (${event.mcp_servers?.length || 0} MCP servers)\n`;
|
|
115
|
+
process.stdout.write(initMsg);
|
|
116
|
+
if (logPath) {
|
|
117
|
+
appendFileSync(logPath, initMsg);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Extract text from assistant message (full response)
|
|
121
|
+
if (event.type === 'assistant' && event.message?.content) {
|
|
122
|
+
for (const block of event.message.content) {
|
|
123
|
+
if (block.type === 'text' && block.text) {
|
|
124
|
+
const text = block.text + '\n\n'; // Add line breaks between messages
|
|
125
|
+
stdout += text;
|
|
126
|
+
process.stdout.write(text);
|
|
127
|
+
if (logPath) {
|
|
128
|
+
appendFileSync(logPath, text);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Extract text from content deltas (streaming)
|
|
134
|
+
if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta') {
|
|
135
|
+
const text = event.delta.text;
|
|
136
|
+
stdout += text;
|
|
137
|
+
process.stdout.write(text);
|
|
138
|
+
if (logPath) {
|
|
139
|
+
appendFileSync(logPath, text);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Mark tool calls
|
|
143
|
+
if (event.type === 'content_block_start' && event.content_block?.type === 'tool_use') {
|
|
144
|
+
const toolName = event.content_block.name;
|
|
145
|
+
const marker = `\n🔧 [${toolName}]\n`;
|
|
146
|
+
stdout += marker;
|
|
147
|
+
process.stdout.write(marker);
|
|
148
|
+
if (logPath) {
|
|
149
|
+
appendFileSync(logPath, marker);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Non-JSON line, ignore
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Notify dashboard to refresh (without data)
|
|
158
|
+
if (ticketKey) {
|
|
159
|
+
broadcast({ type: 'claude_stream', ticket: ticketKey });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
child.stderr.on('data', (data) => {
|
|
163
|
+
const chunk = data.toString();
|
|
164
|
+
stderr += chunk;
|
|
165
|
+
// Write errors to log file
|
|
166
|
+
if (logPath) {
|
|
167
|
+
appendFileSync(logPath, `[ERROR] ${chunk}`);
|
|
168
|
+
}
|
|
169
|
+
if (ticketKey) {
|
|
170
|
+
broadcast({ type: 'claude_stream', ticket: ticketKey });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
child.on('close', (code) => {
|
|
174
|
+
const duration = Date.now() - startTime;
|
|
175
|
+
// Write completion to log
|
|
176
|
+
if (logPath) {
|
|
177
|
+
const status = code === 0 ? 'SUCCESS' : 'FAILED';
|
|
178
|
+
appendFileSync(logPath, `\n[${new Date().toISOString()}] ${status} (${duration}ms)\n`);
|
|
179
|
+
}
|
|
180
|
+
if (ticketKey) {
|
|
181
|
+
broadcast({
|
|
182
|
+
type: 'claude_end',
|
|
183
|
+
ticket: ticketKey,
|
|
184
|
+
success: code === 0,
|
|
185
|
+
duration,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (code === 0) {
|
|
189
|
+
resolve({
|
|
190
|
+
success: true,
|
|
191
|
+
output: stdout,
|
|
192
|
+
duration,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
resolve({
|
|
197
|
+
success: false,
|
|
198
|
+
error: stderr || `Claude exited with code ${code}`,
|
|
199
|
+
duration,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
child.on('error', (error) => {
|
|
204
|
+
if (logPath) {
|
|
205
|
+
appendFileSync(logPath, `\n[${new Date().toISOString()}] ERROR: ${error.message}\n`);
|
|
206
|
+
}
|
|
207
|
+
if (ticketKey) {
|
|
208
|
+
broadcast({
|
|
209
|
+
type: 'claude_end',
|
|
210
|
+
ticket: ticketKey,
|
|
211
|
+
success: false,
|
|
212
|
+
error: error.message,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
resolve({
|
|
216
|
+
success: false,
|
|
217
|
+
error: error.message,
|
|
218
|
+
duration: Date.now() - startTime,
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Process a ticket with Claude
|
|
225
|
+
*/
|
|
226
|
+
export async function processTicketWithClaude(key, options = {}) {
|
|
227
|
+
const config = getConfig();
|
|
228
|
+
// Get ticket
|
|
229
|
+
const ticket = getTicket(config.root, key);
|
|
230
|
+
if (!ticket) {
|
|
231
|
+
return { success: false, error: `Ticket '${key}' not found` };
|
|
232
|
+
}
|
|
233
|
+
// Get action content
|
|
234
|
+
const actionContent = getActionContent(ticket.column_slug, config.lang);
|
|
235
|
+
if (!actionContent) {
|
|
236
|
+
return { success: false, error: `No ACTION file for column '${ticket.column_slug}'` };
|
|
237
|
+
}
|
|
238
|
+
logger.info(`Processing ${key} with Claude...`);
|
|
239
|
+
// Build and write prompt
|
|
240
|
+
const prompt = buildPrompt(ticket, actionContent);
|
|
241
|
+
const promptFile = writePromptFile(ticket, prompt);
|
|
242
|
+
// Execute Claude (with streaming to dashboard)
|
|
243
|
+
const result = await executeClaudeCLI(promptFile, key);
|
|
244
|
+
if (!result.success) {
|
|
245
|
+
logger.error(`Claude failed: ${result.error}`);
|
|
246
|
+
return { success: false, error: result.error };
|
|
247
|
+
}
|
|
248
|
+
// Add Claude's response as a comment
|
|
249
|
+
const comment = result.output || 'No output from Claude';
|
|
250
|
+
const updatedTicket = addComment(config.root, key, comment);
|
|
251
|
+
if (!updatedTicket) {
|
|
252
|
+
return { success: false, error: 'Failed to add comment' };
|
|
253
|
+
}
|
|
254
|
+
logger.success(`Claude processed ${key} in ${result.duration}ms`);
|
|
255
|
+
// Auto-advance if requested
|
|
256
|
+
if (options.autoAdvance) {
|
|
257
|
+
const advanced = nextTicket(config.root, key);
|
|
258
|
+
if (advanced) {
|
|
259
|
+
logger.info(`Advanced ${key} to ${advanced.status}`);
|
|
260
|
+
return { success: true, ticket: advanced };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { success: true, ticket: updatedTicket };
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Process all actionable tickets with Claude
|
|
267
|
+
*/
|
|
268
|
+
export async function processAllTickets(options = {}) {
|
|
269
|
+
const config = getConfig();
|
|
270
|
+
const { findActionableTicket } = await import('../core/ticket.js');
|
|
271
|
+
let processed = 0;
|
|
272
|
+
let errors = 0;
|
|
273
|
+
const limit = options.limit || Infinity;
|
|
274
|
+
while (processed + errors < limit) {
|
|
275
|
+
const ticket = findActionableTicket(config.root);
|
|
276
|
+
if (!ticket) {
|
|
277
|
+
logger.info('No more actionable tickets');
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
const result = await processTicketWithClaude(ticket.key, options);
|
|
281
|
+
if (result.success) {
|
|
282
|
+
processed++;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
errors++;
|
|
286
|
+
logger.error(`Failed to process ${ticket.key}: ${result.error}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
logger.info(`Processed: ${processed}, Errors: ${errors}`);
|
|
290
|
+
return { processed, errors };
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Check if Claude CLI is available
|
|
294
|
+
*/
|
|
295
|
+
export function isClaudeAvailable() {
|
|
296
|
+
try {
|
|
297
|
+
const result = spawn('claude', ['--version'], { stdio: 'pipe' });
|
|
298
|
+
return result.pid !== undefined;
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/services/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket I/O Service - Multi-file ticket storage
|
|
3
|
+
*
|
|
4
|
+
* Structure:
|
|
5
|
+
* tickets/AC-000001__titre/
|
|
6
|
+
* ├── metadata.json # JSON metadata
|
|
7
|
+
* ├── description.md # Pure markdown description
|
|
8
|
+
* └── comments/
|
|
9
|
+
* ├── 001.md # YAML frontmatter + markdown
|
|
10
|
+
* └── 002.md
|
|
11
|
+
*/
|
|
12
|
+
import type { Ticket, Comment, HistoryEntry, Priority, SemverType } from '../types/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Metadata stored in metadata.json (without status/column_slug - derived from path)
|
|
15
|
+
*/
|
|
16
|
+
export interface TicketMetadata {
|
|
17
|
+
key: string;
|
|
18
|
+
title: string;
|
|
19
|
+
priority: Priority;
|
|
20
|
+
labels: string[];
|
|
21
|
+
acceptance_criteria: string[];
|
|
22
|
+
semver: SemverType;
|
|
23
|
+
history: HistoryEntry[];
|
|
24
|
+
created_at: string;
|
|
25
|
+
updated_at: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse metadata.json from ticket directory
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseMetadata(ticketDir: string): TicketMetadata | null;
|
|
31
|
+
/**
|
|
32
|
+
* Read description.md from ticket directory
|
|
33
|
+
*/
|
|
34
|
+
export declare function readDescription(ticketDir: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Read all comments from comments/ directory
|
|
37
|
+
*/
|
|
38
|
+
export declare function readComments(ticketDir: string): Comment[];
|
|
39
|
+
/**
|
|
40
|
+
* Extract column_slug from ticket directory path
|
|
41
|
+
* e.g., /path/autodoc/02_in-progress/tickets/AC-000001__titre -> 02_in-progress
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractColumnSlug(ticketDir: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Load a complete Ticket from a ticket directory
|
|
46
|
+
*/
|
|
47
|
+
export declare function loadTicket(ticketDir: string): Ticket | null;
|
|
48
|
+
/**
|
|
49
|
+
* Write metadata.json to ticket directory
|
|
50
|
+
*/
|
|
51
|
+
export declare function writeMetadata(ticketDir: string, metadata: TicketMetadata): void;
|
|
52
|
+
/**
|
|
53
|
+
* Write description.md to ticket directory
|
|
54
|
+
*/
|
|
55
|
+
export declare function writeDescription(ticketDir: string, title: string, description: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* Add a new comment file to comments/ directory
|
|
58
|
+
*/
|
|
59
|
+
export declare function addCommentFile(ticketDir: string, text: string, column: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Update specific fields in metadata.json
|
|
62
|
+
*/
|
|
63
|
+
export declare function updateMetadata(ticketDir: string, updates: Partial<TicketMetadata>): void;
|
|
64
|
+
/**
|
|
65
|
+
* Add a history entry to metadata.json
|
|
66
|
+
*/
|
|
67
|
+
export declare function addHistoryEntry(ticketDir: string, action: HistoryEntry['action'], from: string | null, to: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* Update description in description.md (preserving title and structure)
|
|
70
|
+
*/
|
|
71
|
+
export declare function updateDescription(ticketDir: string, newDescription: string): void;
|
|
72
|
+
/**
|
|
73
|
+
* Create a new ticket with full structure
|
|
74
|
+
*/
|
|
75
|
+
export declare function createTicketStructure(ticketDir: string, metadata: TicketMetadata, description: string): void;
|
|
76
|
+
//# sourceMappingURL=ticket-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-io.d.ts","sourceRoot":"","sources":["../../src/services/ticket-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAUtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGzD;AA+BD;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAezD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK3D;AAWD;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B3D;AAMD;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAI/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAY5F;AAgBD;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAiBpF;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAWxF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,EAAE,EAAE,MAAM,GACT,IAAI,CAeN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CASjF;AAMD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,MAAM,GAClB,IAAI,CAMN"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket I/O Service - Multi-file ticket storage
|
|
3
|
+
*
|
|
4
|
+
* Structure:
|
|
5
|
+
* tickets/AC-000001__titre/
|
|
6
|
+
* ├── metadata.json # JSON metadata
|
|
7
|
+
* ├── description.md # Pure markdown description
|
|
8
|
+
* └── comments/
|
|
9
|
+
* ├── 001.md # YAML frontmatter + markdown
|
|
10
|
+
* └── 002.md
|
|
11
|
+
*/
|
|
12
|
+
import { join, dirname, basename } from 'node:path';
|
|
13
|
+
import { parse as parseYaml } from 'yaml';
|
|
14
|
+
import { readFileSafe, writeFileSafe, pathExists, ensureDir, listFiles, } from '../utils/fs.js';
|
|
15
|
+
// ============================================
|
|
16
|
+
// READING
|
|
17
|
+
// ============================================
|
|
18
|
+
/**
|
|
19
|
+
* Parse metadata.json from ticket directory
|
|
20
|
+
*/
|
|
21
|
+
export function parseMetadata(ticketDir) {
|
|
22
|
+
const metadataPath = join(ticketDir, 'metadata.json');
|
|
23
|
+
const content = readFileSafe(metadataPath);
|
|
24
|
+
if (!content)
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(content);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read description.md from ticket directory
|
|
35
|
+
*/
|
|
36
|
+
export function readDescription(ticketDir) {
|
|
37
|
+
const descPath = join(ticketDir, 'description.md');
|
|
38
|
+
return readFileSafe(descPath) || '';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse a single comment file with YAML frontmatter
|
|
42
|
+
*/
|
|
43
|
+
function parseCommentFile(filePath) {
|
|
44
|
+
const content = readFileSafe(filePath);
|
|
45
|
+
if (!content)
|
|
46
|
+
return null;
|
|
47
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
48
|
+
if (!match) {
|
|
49
|
+
// No frontmatter, treat as plain text
|
|
50
|
+
return {
|
|
51
|
+
text: content.trim(),
|
|
52
|
+
column: 'N/A',
|
|
53
|
+
created_at: new Date().toISOString(),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const frontMatter = parseYaml(match[1]);
|
|
58
|
+
return {
|
|
59
|
+
text: match[2].trim(),
|
|
60
|
+
column: String(frontMatter.column || 'N/A'),
|
|
61
|
+
created_at: String(frontMatter.created_at || new Date().toISOString()),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Read all comments from comments/ directory
|
|
70
|
+
*/
|
|
71
|
+
export function readComments(ticketDir) {
|
|
72
|
+
const commentsDir = join(ticketDir, 'comments');
|
|
73
|
+
if (!pathExists(commentsDir))
|
|
74
|
+
return [];
|
|
75
|
+
const files = listFiles(commentsDir)
|
|
76
|
+
.filter(f => f.endsWith('.md'))
|
|
77
|
+
.sort(); // 001.md, 002.md, etc.
|
|
78
|
+
const comments = [];
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
const comment = parseCommentFile(join(commentsDir, file));
|
|
81
|
+
if (comment)
|
|
82
|
+
comments.push(comment);
|
|
83
|
+
}
|
|
84
|
+
return comments;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extract column_slug from ticket directory path
|
|
88
|
+
* e.g., /path/autodoc/02_in-progress/tickets/AC-000001__titre -> 02_in-progress
|
|
89
|
+
*/
|
|
90
|
+
export function extractColumnSlug(ticketDir) {
|
|
91
|
+
// ticketDir = .../column_slug/tickets/ticketName
|
|
92
|
+
const ticketsDir = dirname(ticketDir); // .../column_slug/tickets
|
|
93
|
+
const columnDir = dirname(ticketsDir); // .../column_slug
|
|
94
|
+
return basename(columnDir); // column_slug
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get column name from slug
|
|
98
|
+
*/
|
|
99
|
+
function getColumnNameFromSlug(slug) {
|
|
100
|
+
// Remove prefix like "02_" and convert to title case
|
|
101
|
+
const name = slug.replace(/^\d{2}_/, '').replace(/-/g, ' ');
|
|
102
|
+
return name.split(' ').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Load a complete Ticket from a ticket directory
|
|
106
|
+
*/
|
|
107
|
+
export function loadTicket(ticketDir) {
|
|
108
|
+
const metadata = parseMetadata(ticketDir);
|
|
109
|
+
if (!metadata)
|
|
110
|
+
return null;
|
|
111
|
+
const description = readDescription(ticketDir);
|
|
112
|
+
const comments = readComments(ticketDir);
|
|
113
|
+
const columnSlug = extractColumnSlug(ticketDir);
|
|
114
|
+
return {
|
|
115
|
+
key: metadata.key,
|
|
116
|
+
title: metadata.title,
|
|
117
|
+
status: getColumnNameFromSlug(columnSlug),
|
|
118
|
+
column_slug: columnSlug,
|
|
119
|
+
priority: metadata.priority,
|
|
120
|
+
labels: metadata.labels,
|
|
121
|
+
description,
|
|
122
|
+
acceptance_criteria: metadata.acceptance_criteria,
|
|
123
|
+
semver: metadata.semver,
|
|
124
|
+
assignee: null, // Deprecated
|
|
125
|
+
reporter: null, // Deprecated
|
|
126
|
+
comments,
|
|
127
|
+
history: metadata.history,
|
|
128
|
+
created_at: metadata.created_at,
|
|
129
|
+
updated_at: metadata.updated_at,
|
|
130
|
+
_path: ticketDir,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// ============================================
|
|
134
|
+
// WRITING
|
|
135
|
+
// ============================================
|
|
136
|
+
/**
|
|
137
|
+
* Write metadata.json to ticket directory
|
|
138
|
+
*/
|
|
139
|
+
export function writeMetadata(ticketDir, metadata) {
|
|
140
|
+
const metadataPath = join(ticketDir, 'metadata.json');
|
|
141
|
+
ensureDir(ticketDir);
|
|
142
|
+
writeFileSafe(metadataPath, JSON.stringify(metadata, null, 2));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Write description.md to ticket directory
|
|
146
|
+
*/
|
|
147
|
+
export function writeDescription(ticketDir, title, description) {
|
|
148
|
+
const descPath = join(ticketDir, 'description.md');
|
|
149
|
+
const content = `# ${title}
|
|
150
|
+
|
|
151
|
+
## Context
|
|
152
|
+
|
|
153
|
+
${description || '[Description]'}
|
|
154
|
+
|
|
155
|
+
## Notes
|
|
156
|
+
|
|
157
|
+
`;
|
|
158
|
+
writeFileSafe(descPath, content);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get next comment number
|
|
162
|
+
*/
|
|
163
|
+
function getNextCommentNumber(ticketDir) {
|
|
164
|
+
const commentsDir = join(ticketDir, 'comments');
|
|
165
|
+
if (!pathExists(commentsDir))
|
|
166
|
+
return 1;
|
|
167
|
+
const files = listFiles(commentsDir).filter(f => f.endsWith('.md'));
|
|
168
|
+
if (files.length === 0)
|
|
169
|
+
return 1;
|
|
170
|
+
const numbers = files.map(f => parseInt(f.replace('.md', ''), 10)).filter(n => !isNaN(n));
|
|
171
|
+
return numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Add a new comment file to comments/ directory
|
|
175
|
+
*/
|
|
176
|
+
export function addCommentFile(ticketDir, text, column) {
|
|
177
|
+
const commentsDir = join(ticketDir, 'comments');
|
|
178
|
+
ensureDir(commentsDir);
|
|
179
|
+
const num = getNextCommentNumber(ticketDir);
|
|
180
|
+
const fileName = String(num).padStart(3, '0') + '.md';
|
|
181
|
+
const filePath = join(commentsDir, fileName);
|
|
182
|
+
const content = `---
|
|
183
|
+
column: ${column}
|
|
184
|
+
created_at: ${new Date().toISOString()}
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
${text}
|
|
188
|
+
`;
|
|
189
|
+
writeFileSafe(filePath, content);
|
|
190
|
+
}
|
|
191
|
+
// ============================================
|
|
192
|
+
// UPDATING
|
|
193
|
+
// ============================================
|
|
194
|
+
/**
|
|
195
|
+
* Update specific fields in metadata.json
|
|
196
|
+
*/
|
|
197
|
+
export function updateMetadata(ticketDir, updates) {
|
|
198
|
+
const metadata = parseMetadata(ticketDir);
|
|
199
|
+
if (!metadata)
|
|
200
|
+
return;
|
|
201
|
+
const updated = {
|
|
202
|
+
...metadata,
|
|
203
|
+
...updates,
|
|
204
|
+
updated_at: new Date().toISOString(),
|
|
205
|
+
};
|
|
206
|
+
writeMetadata(ticketDir, updated);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Add a history entry to metadata.json
|
|
210
|
+
*/
|
|
211
|
+
export function addHistoryEntry(ticketDir, action, from, to) {
|
|
212
|
+
const metadata = parseMetadata(ticketDir);
|
|
213
|
+
if (!metadata)
|
|
214
|
+
return;
|
|
215
|
+
const newEntry = {
|
|
216
|
+
at: new Date().toISOString(),
|
|
217
|
+
action,
|
|
218
|
+
from,
|
|
219
|
+
to,
|
|
220
|
+
};
|
|
221
|
+
metadata.history.push(newEntry);
|
|
222
|
+
metadata.updated_at = new Date().toISOString();
|
|
223
|
+
writeMetadata(ticketDir, metadata);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Update description in description.md (preserving title and structure)
|
|
227
|
+
*/
|
|
228
|
+
export function updateDescription(ticketDir, newDescription) {
|
|
229
|
+
const descPath = join(ticketDir, 'description.md');
|
|
230
|
+
const currentContent = readFileSafe(descPath) || '';
|
|
231
|
+
// Extract title from current content
|
|
232
|
+
const titleMatch = currentContent.match(/^# (.+)$/m);
|
|
233
|
+
const title = titleMatch ? titleMatch[1] : 'Untitled';
|
|
234
|
+
writeDescription(ticketDir, title, newDescription);
|
|
235
|
+
}
|
|
236
|
+
// ============================================
|
|
237
|
+
// CREATION
|
|
238
|
+
// ============================================
|
|
239
|
+
/**
|
|
240
|
+
* Create a new ticket with full structure
|
|
241
|
+
*/
|
|
242
|
+
export function createTicketStructure(ticketDir, metadata, description) {
|
|
243
|
+
ensureDir(ticketDir);
|
|
244
|
+
ensureDir(join(ticketDir, 'comments'));
|
|
245
|
+
writeMetadata(ticketDir, metadata);
|
|
246
|
+
writeDescription(ticketDir, metadata.title, description);
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=ticket-io.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket-io.js","sourceRoot":"","sources":["../../src/services/ticket-io.ts"],"names":[],"mappings":"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"}
|