@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,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket CRUD operations - Multi-file structure
|
|
3
|
+
*/
|
|
4
|
+
import { join, dirname, basename } from 'node:path';
|
|
5
|
+
import { ensureDir, listDirs, pathExists, generateTicketKey, slugify, getTimestamp, moveDir, } from '../utils/fs.js';
|
|
6
|
+
import { loadTicket, writeDescription, updateMetadata, updateDescription, addCommentFile, addHistoryEntry, createTicketStructure, } from '../services/ticket-io.js';
|
|
7
|
+
import { getColumns, getColumnBySlug, getColumnByName } from './column.js';
|
|
8
|
+
/**
|
|
9
|
+
* Find a ticket directory by its key
|
|
10
|
+
*/
|
|
11
|
+
export function findTicketDir(rootDir, key) {
|
|
12
|
+
const columns = getColumns();
|
|
13
|
+
for (const column of columns) {
|
|
14
|
+
const ticketsDir = join(rootDir, column.slug, 'tickets');
|
|
15
|
+
if (!pathExists(ticketsDir))
|
|
16
|
+
continue;
|
|
17
|
+
const ticketDirs = listDirs(ticketsDir);
|
|
18
|
+
for (const ticketDir of ticketDirs) {
|
|
19
|
+
if (ticketDir.startsWith(`${key}__`)) {
|
|
20
|
+
return join(ticketsDir, ticketDir);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Find a ticket path by its key (for backwards compatibility)
|
|
28
|
+
* @deprecated Use findTicketDir instead
|
|
29
|
+
*/
|
|
30
|
+
export function findTicketPath(rootDir, key) {
|
|
31
|
+
const ticketDir = findTicketDir(rootDir, key);
|
|
32
|
+
if (!ticketDir)
|
|
33
|
+
return null;
|
|
34
|
+
return join(ticketDir, 'metadata.json');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get a ticket by its key
|
|
38
|
+
*/
|
|
39
|
+
export function getTicket(rootDir, key) {
|
|
40
|
+
const ticketDir = findTicketDir(rootDir, key);
|
|
41
|
+
if (!ticketDir)
|
|
42
|
+
return null;
|
|
43
|
+
return loadTicket(ticketDir);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a new ticket
|
|
47
|
+
*/
|
|
48
|
+
export function createTicket(rootDir, input) {
|
|
49
|
+
const key = generateTicketKey(rootDir);
|
|
50
|
+
const timestamp = getTimestamp();
|
|
51
|
+
const titleSlug = slugify(input.title);
|
|
52
|
+
// Default to backlog
|
|
53
|
+
const column = getColumnBySlug('00_backlog');
|
|
54
|
+
const ticketDir = join(rootDir, column.slug, 'tickets', `${key}__${titleSlug}`);
|
|
55
|
+
const metadata = {
|
|
56
|
+
key,
|
|
57
|
+
title: input.title,
|
|
58
|
+
priority: input.priority || 'P2',
|
|
59
|
+
labels: input.labels || [],
|
|
60
|
+
acceptance_criteria: input.acceptance_criteria || [],
|
|
61
|
+
semver: input.semver || 'patch',
|
|
62
|
+
history: [
|
|
63
|
+
{
|
|
64
|
+
at: timestamp,
|
|
65
|
+
action: 'created',
|
|
66
|
+
from: null,
|
|
67
|
+
to: column.slug,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
created_at: timestamp,
|
|
71
|
+
updated_at: timestamp,
|
|
72
|
+
};
|
|
73
|
+
const description = input.description || '';
|
|
74
|
+
createTicketStructure(ticketDir, metadata, description);
|
|
75
|
+
return loadTicket(ticketDir);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Update a ticket
|
|
79
|
+
*/
|
|
80
|
+
export function updateTicket(rootDir, key, updates) {
|
|
81
|
+
const ticketDir = findTicketDir(rootDir, key);
|
|
82
|
+
if (!ticketDir)
|
|
83
|
+
return null;
|
|
84
|
+
const ticket = loadTicket(ticketDir);
|
|
85
|
+
if (!ticket)
|
|
86
|
+
return null;
|
|
87
|
+
// Build metadata updates
|
|
88
|
+
const metadataUpdates = {};
|
|
89
|
+
if (updates.title !== undefined)
|
|
90
|
+
metadataUpdates.title = updates.title;
|
|
91
|
+
if (updates.priority !== undefined)
|
|
92
|
+
metadataUpdates.priority = updates.priority;
|
|
93
|
+
if (updates.labels !== undefined)
|
|
94
|
+
metadataUpdates.labels = updates.labels;
|
|
95
|
+
if (updates.acceptance_criteria !== undefined)
|
|
96
|
+
metadataUpdates.acceptance_criteria = updates.acceptance_criteria;
|
|
97
|
+
if (updates.semver !== undefined)
|
|
98
|
+
metadataUpdates.semver = updates.semver;
|
|
99
|
+
// Update metadata if any changes
|
|
100
|
+
if (Object.keys(metadataUpdates).length > 0) {
|
|
101
|
+
updateMetadata(ticketDir, metadataUpdates);
|
|
102
|
+
}
|
|
103
|
+
// Update description if changed
|
|
104
|
+
if (updates.description !== undefined) {
|
|
105
|
+
updateDescription(ticketDir, updates.description);
|
|
106
|
+
}
|
|
107
|
+
// Update title in description.md if title changed
|
|
108
|
+
if (updates.title !== undefined) {
|
|
109
|
+
writeDescription(ticketDir, updates.title, updates.description ?? ticket.description);
|
|
110
|
+
}
|
|
111
|
+
return loadTicket(ticketDir);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Add a comment to a ticket
|
|
115
|
+
*/
|
|
116
|
+
export function addComment(rootDir, key, text, column) {
|
|
117
|
+
const ticketDir = findTicketDir(rootDir, key);
|
|
118
|
+
if (!ticketDir)
|
|
119
|
+
return null;
|
|
120
|
+
const ticket = loadTicket(ticketDir);
|
|
121
|
+
if (!ticket)
|
|
122
|
+
return null;
|
|
123
|
+
const commentColumn = column || ticket.status || 'N/A';
|
|
124
|
+
addCommentFile(ticketDir, text, commentColumn);
|
|
125
|
+
return loadTicket(ticketDir);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Move a ticket to a new column
|
|
129
|
+
*/
|
|
130
|
+
export function moveTicket(rootDir, key, toColumnName, force = false) {
|
|
131
|
+
const ticketDir = findTicketDir(rootDir, key);
|
|
132
|
+
if (!ticketDir)
|
|
133
|
+
return null;
|
|
134
|
+
const ticket = loadTicket(ticketDir);
|
|
135
|
+
if (!ticket)
|
|
136
|
+
return null;
|
|
137
|
+
const toColumn = getColumnByName(toColumnName) || getColumnBySlug(toColumnName);
|
|
138
|
+
if (!toColumn)
|
|
139
|
+
return null;
|
|
140
|
+
const fromColumn = getColumnBySlug(ticket.column_slug);
|
|
141
|
+
if (!fromColumn)
|
|
142
|
+
return null;
|
|
143
|
+
// Determine action
|
|
144
|
+
const action = force ? 'forced' : 'moved';
|
|
145
|
+
// Add history entry
|
|
146
|
+
addHistoryEntry(ticketDir, action, fromColumn.slug, toColumn.slug);
|
|
147
|
+
// Move directory
|
|
148
|
+
const ticketDirName = basename(ticketDir);
|
|
149
|
+
const newTicketDir = join(rootDir, toColumn.slug, 'tickets', ticketDirName);
|
|
150
|
+
if (ticketDir !== newTicketDir) {
|
|
151
|
+
ensureDir(dirname(newTicketDir));
|
|
152
|
+
moveDir(ticketDir, newTicketDir);
|
|
153
|
+
}
|
|
154
|
+
return loadTicket(newTicketDir);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Move a ticket to the next column
|
|
158
|
+
*/
|
|
159
|
+
export function nextTicket(rootDir, key) {
|
|
160
|
+
const ticket = getTicket(rootDir, key);
|
|
161
|
+
if (!ticket)
|
|
162
|
+
return null;
|
|
163
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
164
|
+
if (!currentColumn)
|
|
165
|
+
return null;
|
|
166
|
+
const nextColumn = getColumns().find(c => c.index === currentColumn.index + 1);
|
|
167
|
+
if (!nextColumn)
|
|
168
|
+
return null;
|
|
169
|
+
return moveTicket(rootDir, key, nextColumn.name);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* List all tickets
|
|
173
|
+
*/
|
|
174
|
+
export function listTickets(rootDir) {
|
|
175
|
+
const tickets = [];
|
|
176
|
+
const columns = getColumns();
|
|
177
|
+
for (const column of columns) {
|
|
178
|
+
const ticketsDir = join(rootDir, column.slug, 'tickets');
|
|
179
|
+
if (!pathExists(ticketsDir))
|
|
180
|
+
continue;
|
|
181
|
+
const ticketDirs = listDirs(ticketsDir);
|
|
182
|
+
for (const ticketDirName of ticketDirs) {
|
|
183
|
+
const ticketDir = join(ticketsDir, ticketDirName);
|
|
184
|
+
const ticket = loadTicket(ticketDir);
|
|
185
|
+
if (ticket) {
|
|
186
|
+
tickets.push(ticket);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return tickets;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* List tickets in a specific column
|
|
194
|
+
*/
|
|
195
|
+
export function listTicketsInColumn(rootDir, columnSlug) {
|
|
196
|
+
const ticketsDir = join(rootDir, columnSlug, 'tickets');
|
|
197
|
+
if (!pathExists(ticketsDir))
|
|
198
|
+
return [];
|
|
199
|
+
const tickets = [];
|
|
200
|
+
const ticketDirs = listDirs(ticketsDir);
|
|
201
|
+
for (const ticketDirName of ticketDirs) {
|
|
202
|
+
const ticketDir = join(ticketsDir, ticketDirName);
|
|
203
|
+
const ticket = loadTicket(ticketDir);
|
|
204
|
+
if (ticket) {
|
|
205
|
+
tickets.push(ticket);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return tickets;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Find the first actionable ticket (for Claude processing)
|
|
212
|
+
*/
|
|
213
|
+
export function findActionableTicket(rootDir) {
|
|
214
|
+
const columns = getColumns();
|
|
215
|
+
// Skip backlog (0) and done (12)
|
|
216
|
+
for (const column of columns.slice(1, -1)) {
|
|
217
|
+
const tickets = listTicketsInColumn(rootDir, column.slug);
|
|
218
|
+
if (tickets.length > 0) {
|
|
219
|
+
// Return highest priority ticket
|
|
220
|
+
return tickets.sort((a, b) => {
|
|
221
|
+
const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
|
|
222
|
+
return priorityOrder[a.priority] - priorityOrder[b.priority];
|
|
223
|
+
})[0];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=ticket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.js","sourceRoot":"","sources":["../../src/core/ticket.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow transitions logic
|
|
3
|
+
*/
|
|
4
|
+
import type { Ticket, Column, WorkflowValidation } from '../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Validate a workflow transition
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateTransition(fromSlug: string, toSlug: string, force?: boolean): WorkflowValidation;
|
|
9
|
+
/**
|
|
10
|
+
* Get available transitions for a ticket
|
|
11
|
+
*/
|
|
12
|
+
export declare function getAvailableTransitions(ticket: Ticket): Column[];
|
|
13
|
+
/**
|
|
14
|
+
* Get all possible transitions (including forced)
|
|
15
|
+
*/
|
|
16
|
+
export declare function getAllPossibleTransitions(ticket: Ticket): Column[];
|
|
17
|
+
/**
|
|
18
|
+
* Check if ticket can advance to next column
|
|
19
|
+
*/
|
|
20
|
+
export declare function canAdvance(ticket: Ticket): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Check if ticket is in final column (done)
|
|
23
|
+
*/
|
|
24
|
+
export declare function isComplete(ticket: Ticket): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if ticket is in backlog
|
|
27
|
+
*/
|
|
28
|
+
export declare function isInBacklog(ticket: Ticket): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Get workflow progress percentage
|
|
31
|
+
*/
|
|
32
|
+
export declare function getProgress(ticket: Ticket): number;
|
|
33
|
+
/**
|
|
34
|
+
* Get column statistics
|
|
35
|
+
*/
|
|
36
|
+
export declare function getColumnStats(tickets: Ticket[]): Map<string, number>;
|
|
37
|
+
/**
|
|
38
|
+
* Get workflow summary
|
|
39
|
+
*/
|
|
40
|
+
export declare function getWorkflowSummary(tickets: Ticket[]): {
|
|
41
|
+
total: number;
|
|
42
|
+
byColumn: {
|
|
43
|
+
column: Column;
|
|
44
|
+
count: number;
|
|
45
|
+
}[];
|
|
46
|
+
inProgress: number;
|
|
47
|
+
completed: number;
|
|
48
|
+
backlog: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Transition a ticket to the next column
|
|
52
|
+
*/
|
|
53
|
+
export declare function advanceTicket(rootDir: string, key: string): {
|
|
54
|
+
success: boolean;
|
|
55
|
+
ticket?: Ticket;
|
|
56
|
+
error?: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Force transition a ticket to any column
|
|
60
|
+
*/
|
|
61
|
+
export declare function forceTransition(rootDir: string, key: string, toColumnName: string): {
|
|
62
|
+
success: boolean;
|
|
63
|
+
ticket?: Ticket;
|
|
64
|
+
error?: string;
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/core/workflow.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5E;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,UAAQ,GACZ,kBAAkB,CA+BpB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAchE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAQlE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAMlD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQlD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAqBA;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAmBvD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,GACnB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAYvD"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow transitions logic
|
|
3
|
+
*/
|
|
4
|
+
import { getColumnBySlug, getColumnByIndex, getColumns } from './column.js';
|
|
5
|
+
import { getTicket, moveTicket as moveTicketCore } from './ticket.js';
|
|
6
|
+
/**
|
|
7
|
+
* Validate a workflow transition
|
|
8
|
+
*/
|
|
9
|
+
export function validateTransition(fromSlug, toSlug, force = false) {
|
|
10
|
+
const fromColumn = getColumnBySlug(fromSlug);
|
|
11
|
+
const toColumn = getColumnBySlug(toSlug);
|
|
12
|
+
if (!fromColumn) {
|
|
13
|
+
return {
|
|
14
|
+
valid: false,
|
|
15
|
+
reason: `Source column '${fromSlug}' not found`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (!toColumn) {
|
|
19
|
+
return {
|
|
20
|
+
valid: false,
|
|
21
|
+
reason: `Destination column '${toSlug}' not found`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (force) {
|
|
25
|
+
return { valid: true };
|
|
26
|
+
}
|
|
27
|
+
// Standard workflow: only move forward by 1
|
|
28
|
+
if (toColumn.index !== fromColumn.index + 1) {
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
reason: `Cannot move from '${fromColumn.name}' (${fromColumn.index}) to '${toColumn.name}' (${toColumn.index}). Use --force to override.`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return { valid: true };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get available transitions for a ticket
|
|
38
|
+
*/
|
|
39
|
+
export function getAvailableTransitions(ticket) {
|
|
40
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
41
|
+
if (!currentColumn)
|
|
42
|
+
return [];
|
|
43
|
+
const columns = getColumns();
|
|
44
|
+
const transitions = [];
|
|
45
|
+
// Standard: next column only
|
|
46
|
+
const nextColumn = getColumnByIndex(currentColumn.index + 1);
|
|
47
|
+
if (nextColumn) {
|
|
48
|
+
transitions.push(nextColumn);
|
|
49
|
+
}
|
|
50
|
+
return transitions;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get all possible transitions (including forced)
|
|
54
|
+
*/
|
|
55
|
+
export function getAllPossibleTransitions(ticket) {
|
|
56
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
57
|
+
if (!currentColumn)
|
|
58
|
+
return [];
|
|
59
|
+
const columns = getColumns();
|
|
60
|
+
// All columns except current
|
|
61
|
+
return columns.filter(c => c.slug !== ticket.column_slug);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if ticket can advance to next column
|
|
65
|
+
*/
|
|
66
|
+
export function canAdvance(ticket) {
|
|
67
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
68
|
+
if (!currentColumn)
|
|
69
|
+
return false;
|
|
70
|
+
const nextColumn = getColumnByIndex(currentColumn.index + 1);
|
|
71
|
+
return nextColumn !== undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if ticket is in final column (done)
|
|
75
|
+
*/
|
|
76
|
+
export function isComplete(ticket) {
|
|
77
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
78
|
+
if (!currentColumn)
|
|
79
|
+
return false;
|
|
80
|
+
const columns = getColumns();
|
|
81
|
+
const maxIndex = Math.max(...columns.map(c => c.index));
|
|
82
|
+
return currentColumn.index === maxIndex;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if ticket is in backlog
|
|
86
|
+
*/
|
|
87
|
+
export function isInBacklog(ticket) {
|
|
88
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
89
|
+
return currentColumn?.index === 0;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get workflow progress percentage
|
|
93
|
+
*/
|
|
94
|
+
export function getProgress(ticket) {
|
|
95
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
96
|
+
if (!currentColumn)
|
|
97
|
+
return 0;
|
|
98
|
+
const columns = getColumns();
|
|
99
|
+
const maxIndex = Math.max(...columns.map(c => c.index));
|
|
100
|
+
if (maxIndex === 0)
|
|
101
|
+
return 100;
|
|
102
|
+
return Math.round((currentColumn.index / maxIndex) * 100);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get column statistics
|
|
106
|
+
*/
|
|
107
|
+
export function getColumnStats(tickets) {
|
|
108
|
+
const stats = new Map();
|
|
109
|
+
const columns = getColumns();
|
|
110
|
+
// Initialize all columns with 0
|
|
111
|
+
for (const column of columns) {
|
|
112
|
+
stats.set(column.slug, 0);
|
|
113
|
+
}
|
|
114
|
+
// Count tickets per column
|
|
115
|
+
for (const ticket of tickets) {
|
|
116
|
+
const count = stats.get(ticket.column_slug) || 0;
|
|
117
|
+
stats.set(ticket.column_slug, count + 1);
|
|
118
|
+
}
|
|
119
|
+
return stats;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get workflow summary
|
|
123
|
+
*/
|
|
124
|
+
export function getWorkflowSummary(tickets) {
|
|
125
|
+
const columns = getColumns();
|
|
126
|
+
const stats = getColumnStats(tickets);
|
|
127
|
+
const byColumn = columns.map(column => ({
|
|
128
|
+
column,
|
|
129
|
+
count: stats.get(column.slug) || 0,
|
|
130
|
+
}));
|
|
131
|
+
const maxIndex = Math.max(...columns.map(c => c.index));
|
|
132
|
+
return {
|
|
133
|
+
total: tickets.length,
|
|
134
|
+
byColumn,
|
|
135
|
+
backlog: byColumn.find(b => b.column.index === 0)?.count || 0,
|
|
136
|
+
completed: byColumn.find(b => b.column.index === maxIndex)?.count || 0,
|
|
137
|
+
inProgress: tickets.filter(t => {
|
|
138
|
+
const col = getColumnBySlug(t.column_slug);
|
|
139
|
+
return col && col.index > 0 && col.index < maxIndex;
|
|
140
|
+
}).length,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Transition a ticket to the next column
|
|
145
|
+
*/
|
|
146
|
+
export function advanceTicket(rootDir, key) {
|
|
147
|
+
const ticket = getTicket(rootDir, key);
|
|
148
|
+
if (!ticket) {
|
|
149
|
+
return { success: false, error: `Ticket '${key}' not found` };
|
|
150
|
+
}
|
|
151
|
+
if (!canAdvance(ticket)) {
|
|
152
|
+
return { success: false, error: `Ticket '${key}' cannot advance (already complete)` };
|
|
153
|
+
}
|
|
154
|
+
const currentColumn = getColumnBySlug(ticket.column_slug);
|
|
155
|
+
const nextColumn = getColumnByIndex(currentColumn.index + 1);
|
|
156
|
+
const updated = moveTicketCore(rootDir, key, nextColumn.name);
|
|
157
|
+
if (!updated) {
|
|
158
|
+
return { success: false, error: `Failed to move ticket '${key}'` };
|
|
159
|
+
}
|
|
160
|
+
return { success: true, ticket: updated };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Force transition a ticket to any column
|
|
164
|
+
*/
|
|
165
|
+
export function forceTransition(rootDir, key, toColumnName) {
|
|
166
|
+
const ticket = getTicket(rootDir, key);
|
|
167
|
+
if (!ticket) {
|
|
168
|
+
return { success: false, error: `Ticket '${key}' not found` };
|
|
169
|
+
}
|
|
170
|
+
const updated = moveTicketCore(rootDir, key, toColumnName, true);
|
|
171
|
+
if (!updated) {
|
|
172
|
+
return { success: false, error: `Failed to move ticket '${key}' to '${toColumnName}'` };
|
|
173
|
+
}
|
|
174
|
+
return { success: true, ticket: updated };
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/core/workflow.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;GAIG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REST API endpoints
|
|
3
|
+
*/
|
|
4
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
|
+
/**
|
|
6
|
+
* Handle API request
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleApiRequest(req: IncomingMessage, res: ServerResponse): Promise<boolean>;
|
|
9
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/server/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AA0VjE;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,CAqClB"}
|