mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-13 02:41:50 +08:00
refactor(issue): remove 'merged' queue status, use 'archived' instead
- Remove 'merged' from VALID_QUEUE_STATUSES constant - Update mergeQueues() to set status to 'archived' instead of 'merged' - Preserve merged_into/merged_at metadata for traceability - Update frontend to use 'archived' for button visibility checks - Fix queue --json returning fake queue ID when no active queue exists
This commit is contained in:
@@ -172,7 +172,7 @@ interface ExecutionGroup {
|
|||||||
interface Queue {
|
interface Queue {
|
||||||
id: string; // Queue unique ID: QUE-YYYYMMDD-HHMMSS (derived from filename)
|
id: string; // Queue unique ID: QUE-YYYYMMDD-HHMMSS (derived from filename)
|
||||||
name?: string; // Optional queue name
|
name?: string; // Optional queue name
|
||||||
status: 'active' | 'completed' | 'archived' | 'failed' | 'merged';
|
status: 'active' | 'completed' | 'archived' | 'failed';
|
||||||
issue_ids: string[]; // Issues in this queue
|
issue_ids: string[]; // Issues in this queue
|
||||||
tasks: QueueItem[]; // Task items (task-level queue)
|
tasks: QueueItem[]; // Task items (task-level queue)
|
||||||
solutions?: QueueItem[]; // Solution items (solution-level queue)
|
solutions?: QueueItem[]; // Solution items (solution-level queue)
|
||||||
@@ -235,7 +235,7 @@ const ISSUES_DIR = '.workflow/issues';
|
|||||||
|
|
||||||
// ============ Status Constants ============
|
// ============ Status Constants ============
|
||||||
|
|
||||||
const VALID_QUEUE_STATUSES = ['active', 'completed', 'archived', 'failed', 'merged'] as const;
|
const VALID_QUEUE_STATUSES = ['active', 'completed', 'archived', 'failed'] as const;
|
||||||
const VALID_ITEM_STATUSES = ['pending', 'ready', 'executing', 'completed', 'failed', 'blocked'] as const;
|
const VALID_ITEM_STATUSES = ['pending', 'ready', 'executing', 'completed', 'failed', 'blocked'] as const;
|
||||||
const VALID_ISSUE_STATUSES = ['registered', 'planning', 'planned', 'queued', 'executing', 'completed', 'failed', 'paused'] as const;
|
const VALID_ISSUE_STATUSES = ['registered', 'planning', 'planned', 'queued', 'executing', 'completed', 'failed', 'paused'] as const;
|
||||||
|
|
||||||
@@ -777,7 +777,7 @@ interface MergeResult {
|
|||||||
* Merge items from source queue into target queue
|
* Merge items from source queue into target queue
|
||||||
* - Skips duplicate items (same issue_id + solution_id)
|
* - Skips duplicate items (same issue_id + solution_id)
|
||||||
* - Re-generates item IDs for merged items
|
* - Re-generates item IDs for merged items
|
||||||
* - Marks source queue as 'merged' with metadata (or deletes if deleteSource=true)
|
* - Marks source queue as 'archived' with metadata (or deletes if deleteSource=true)
|
||||||
* - Updates queue index
|
* - Updates queue index
|
||||||
*/
|
*/
|
||||||
function mergeQueues(target: Queue, source: Queue, options?: { deleteSource?: boolean }): MergeResult {
|
function mergeQueues(target: Queue, source: Queue, options?: { deleteSource?: boolean }): MergeResult {
|
||||||
@@ -832,7 +832,7 @@ function mergeQueues(target: Queue, source: Queue, options?: { deleteSource?: bo
|
|||||||
// Write updated target queue
|
// Write updated target queue
|
||||||
writeQueue(target);
|
writeQueue(target);
|
||||||
|
|
||||||
// Handle source queue: delete or mark as merged
|
// Handle source queue: delete or mark as archived
|
||||||
const index = readQueueIndex();
|
const index = readQueueIndex();
|
||||||
|
|
||||||
if (options?.deleteSource) {
|
if (options?.deleteSource) {
|
||||||
@@ -843,8 +843,8 @@ function mergeQueues(target: Queue, source: Queue, options?: { deleteSource?: bo
|
|||||||
}
|
}
|
||||||
index.queues = index.queues.filter(q => q.id !== source.id);
|
index.queues = index.queues.filter(q => q.id !== source.id);
|
||||||
} else {
|
} else {
|
||||||
// Mark source queue as merged
|
// Mark source queue as archived (was merged)
|
||||||
source.status = 'merged';
|
source.status = 'archived';
|
||||||
if (!source._metadata) {
|
if (!source._metadata) {
|
||||||
source._metadata = {
|
source._metadata = {
|
||||||
version: '2.1',
|
version: '2.1',
|
||||||
@@ -862,7 +862,7 @@ function mergeQueues(target: Queue, source: Queue, options?: { deleteSource?: bo
|
|||||||
|
|
||||||
const sourceEntry = index.queues.find(q => q.id === source.id);
|
const sourceEntry = index.queues.find(q => q.id === source.id);
|
||||||
if (sourceEntry) {
|
if (sourceEntry) {
|
||||||
sourceEntry.status = 'merged';
|
sourceEntry.status = 'archived';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2265,7 +2265,7 @@ async function queueAction(subAction: string | undefined, issueId: string | unde
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mergeQueues marks source as 'merged' and updates index
|
// mergeQueues marks source as 'archived' and updates index
|
||||||
const result = mergeQueues(targetQueue, sourceQueue);
|
const result = mergeQueues(targetQueue, sourceQueue);
|
||||||
|
|
||||||
if (options.json) {
|
if (options.json) {
|
||||||
@@ -2285,7 +2285,7 @@ async function queueAction(subAction: string | undefined, issueId: string | unde
|
|||||||
console.log(chalk.gray(` Skipped ${result.skippedDuplicates} duplicate items`));
|
console.log(chalk.gray(` Skipped ${result.skippedDuplicates} duplicate items`));
|
||||||
}
|
}
|
||||||
console.log(chalk.gray(` Total items in target: ${result.totalItems}`));
|
console.log(chalk.gray(` Total items in target: ${result.totalItems}`));
|
||||||
console.log(chalk.gray(` Source queue ${sourceQueueId} marked as 'merged'`));
|
console.log(chalk.gray(` Source queue ${sourceQueueId} archived`));
|
||||||
} else {
|
} else {
|
||||||
console.log(chalk.yellow(`⚠ Merge skipped: ${result.reason}`));
|
console.log(chalk.yellow(`⚠ Merge skipped: ${result.reason}`));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -702,7 +702,7 @@ function renderQueueCard(queue, isActive) {
|
|||||||
const completedCount = queue.completed_solutions || queue.completed_tasks || 0;
|
const completedCount = queue.completed_solutions || queue.completed_tasks || 0;
|
||||||
const progressPercent = itemCount > 0 ? Math.round((completedCount / itemCount) * 100) : 0;
|
const progressPercent = itemCount > 0 ? Math.round((completedCount / itemCount) * 100) : 0;
|
||||||
const issueCount = queue.issue_ids?.length || 0;
|
const issueCount = queue.issue_ids?.length || 0;
|
||||||
const statusClass = queue.status === 'merged' ? 'merged' : queue.status || '';
|
const statusClass = queue.status || '';
|
||||||
const safeQueueId = escapeHtml(queue.id || '');
|
const safeQueueId = escapeHtml(queue.id || '');
|
||||||
|
|
||||||
return `
|
return `
|
||||||
@@ -740,17 +740,17 @@ function renderQueueCard(queue, isActive) {
|
|||||||
<button class="btn-sm" onclick="toggleQueueExpand('${safeQueueId}')" title="View details">
|
<button class="btn-sm" onclick="toggleQueueExpand('${safeQueueId}')" title="View details">
|
||||||
<i data-lucide="eye" class="w-3 h-3"></i>
|
<i data-lucide="eye" class="w-3 h-3"></i>
|
||||||
</button>
|
</button>
|
||||||
${!isActive && queue.status !== 'merged' ? `
|
${!isActive && queue.status !== 'archived' ? `
|
||||||
<button class="btn-sm btn-primary" onclick="activateQueue('${safeQueueId}')" title="Set as active">
|
<button class="btn-sm btn-primary" onclick="activateQueue('${safeQueueId}')" title="Set as active">
|
||||||
<i data-lucide="check-circle" class="w-3 h-3"></i>
|
<i data-lucide="check-circle" class="w-3 h-3"></i>
|
||||||
</button>
|
</button>
|
||||||
` : ''}
|
` : ''}
|
||||||
${queue.status !== 'merged' ? `
|
${queue.status !== 'archived' ? `
|
||||||
<button class="btn-sm" onclick="showMergeQueueModal('${safeQueueId}')" title="Merge into another queue">
|
<button class="btn-sm" onclick="showMergeQueueModal('${safeQueueId}')" title="Merge into another queue">
|
||||||
<i data-lucide="git-merge" class="w-3 h-3"></i>
|
<i data-lucide="git-merge" class="w-3 h-3"></i>
|
||||||
</button>
|
</button>
|
||||||
` : ''}
|
` : ''}
|
||||||
${queue.status !== 'merged' && issueCount > 1 ? `
|
${queue.status !== 'archived' && issueCount > 1 ? `
|
||||||
<button class="btn-sm" onclick="showSplitQueueModal('${safeQueueId}')" title="Split queue into multiple queues">
|
<button class="btn-sm" onclick="showSplitQueueModal('${safeQueueId}')" title="Split queue into multiple queues">
|
||||||
<i data-lucide="git-branch" class="w-3 h-3"></i>
|
<i data-lucide="git-branch" class="w-3 h-3"></i>
|
||||||
</button>
|
</button>
|
||||||
@@ -896,7 +896,7 @@ async function renderExpandedQueueView(queueId) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="queue-detail-actions">
|
<div class="queue-detail-actions">
|
||||||
${!isActive && queue.status !== 'merged' ? `
|
${!isActive && queue.status !== 'archived' ? `
|
||||||
<button class="btn-primary" onclick="activateQueue('${safeQueueId}')">
|
<button class="btn-primary" onclick="activateQueue('${safeQueueId}')">
|
||||||
<i data-lucide="check-circle" class="w-4 h-4"></i>
|
<i data-lucide="check-circle" class="w-4 h-4"></i>
|
||||||
<span>${t('issues.activate') || 'Activate'}</span>
|
<span>${t('issues.activate') || 'Activate'}</span>
|
||||||
@@ -1141,7 +1141,7 @@ function showMergeQueueModal(sourceQueueId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const otherQueues = queueData.queues.filter(q =>
|
const otherQueues = queueData.queues.filter(q =>
|
||||||
q.id !== sourceQueueId && q.status !== 'merged'
|
q.id !== sourceQueueId && q.status !== 'archived'
|
||||||
);
|
);
|
||||||
|
|
||||||
const safeSourceId = escapeHtml(sourceQueueId || '');
|
const safeSourceId = escapeHtml(sourceQueueId || '');
|
||||||
@@ -1170,7 +1170,7 @@ function showMergeQueueModal(sourceQueueId) {
|
|||||||
</div>
|
</div>
|
||||||
<p class="text-sm text-muted-foreground mt-2">
|
<p class="text-sm text-muted-foreground mt-2">
|
||||||
<i data-lucide="info" class="w-4 h-4 inline mr-1"></i>
|
<i data-lucide="info" class="w-4 h-4 inline mr-1"></i>
|
||||||
Items from source queue will be appended to target queue. Source queue will be marked as "merged".
|
Items from source queue will be appended to target queue. Source queue will be archived.
|
||||||
</p>
|
</p>
|
||||||
`}
|
`}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user