claude-code-workflow 6.3.8 → 6.3.10
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/.claude/CLAUDE.md +1 -1
- package/.claude/agents/issue-plan-agent.md +84 -56
- package/.claude/agents/issue-queue-agent.md +120 -108
- package/.claude/commands/issue/execute.md +195 -363
- package/.claude/commands/issue/plan.md +70 -27
- package/.claude/commands/issue/queue.md +130 -66
- package/.claude/commands/workflow/init.md +75 -29
- package/.claude/commands/workflow/lite-fix.md +8 -0
- package/.claude/commands/workflow/lite-plan.md +8 -0
- package/.claude/commands/workflow/review-module-cycle.md +4 -0
- package/.claude/commands/workflow/review-session-cycle.md +4 -0
- package/.claude/commands/workflow/review.md +4 -4
- package/.claude/commands/workflow/session/solidify.md +299 -0
- package/.claude/commands/workflow/session/start.md +10 -7
- package/.claude/commands/workflow/tools/context-gather.md +17 -10
- package/.claude/workflows/cli-templates/schemas/queue-schema.json +225 -108
- package/.claude/workflows/cli-templates/schemas/solution-schema.json +60 -15
- package/.claude/workflows/context-tools.md +17 -25
- package/.codex/AGENTS.md +10 -5
- package/ccw/dist/commands/issue.d.ts.map +1 -1
- package/ccw/dist/commands/issue.js +348 -115
- package/ccw/dist/commands/issue.js.map +1 -1
- package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
- package/ccw/dist/core/routes/issue-routes.js +68 -0
- package/ccw/dist/core/routes/issue-routes.js.map +1 -1
- package/ccw/src/commands/issue.ts +408 -148
- package/ccw/src/core/routes/issue-routes.ts +76 -0
- package/ccw/src/templates/dashboard-css/32-issue-manager.css +310 -1
- package/ccw/src/templates/dashboard-js/components/cli-status.js +1 -78
- package/ccw/src/templates/dashboard-js/i18n.js +0 -4
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +0 -18
- package/ccw/src/templates/dashboard-js/views/issue-manager.js +294 -11
- package/package.json +1 -1
- package/.claude/workflows/cli-templates/schemas/issue-task-jsonl-schema.json +0 -136
- package/.claude/workflows/cli-templates/schemas/solutions-jsonl-schema.json +0 -125
- package/.claude/workflows/context-tools-ace.md +0 -105
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// ========== Issue State ==========
|
|
7
7
|
var issueData = {
|
|
8
8
|
issues: [],
|
|
9
|
-
queue: { tasks: [], conflicts: [], execution_groups: [], grouped_items: {} },
|
|
9
|
+
queue: { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} },
|
|
10
10
|
selectedIssue: null,
|
|
11
11
|
selectedSolution: null,
|
|
12
12
|
selectedSolutionIssueId: null,
|
|
@@ -65,7 +65,7 @@ async function loadQueueData() {
|
|
|
65
65
|
issueData.queue = await response.json();
|
|
66
66
|
} catch (err) {
|
|
67
67
|
console.error('Failed to load queue:', err);
|
|
68
|
-
issueData.queue = { tasks: [], conflicts: [], execution_groups: [], grouped_items: {} };
|
|
68
|
+
issueData.queue = { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} };
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -360,13 +360,21 @@ function filterIssuesByStatus(status) {
|
|
|
360
360
|
// ========== Queue Section ==========
|
|
361
361
|
function renderQueueSection() {
|
|
362
362
|
const queue = issueData.queue;
|
|
363
|
-
|
|
363
|
+
// Support both solution-level and task-level queues
|
|
364
|
+
const queueItems = queue.solutions || queue.tasks || [];
|
|
365
|
+
const isSolutionLevel = !!(queue.solutions && queue.solutions.length > 0);
|
|
364
366
|
const metadata = queue._metadata || {};
|
|
365
367
|
|
|
366
368
|
// Check if queue is empty
|
|
367
369
|
if (queueItems.length === 0) {
|
|
368
370
|
return `
|
|
369
371
|
<div class="queue-empty-container">
|
|
372
|
+
<div class="queue-empty-toolbar">
|
|
373
|
+
<button class="btn-secondary" onclick="showQueueHistoryModal()" title="${t('issues.queueHistory') || 'Queue History'}">
|
|
374
|
+
<i data-lucide="history" class="w-4 h-4"></i>
|
|
375
|
+
<span>${t('issues.history') || 'History'}</span>
|
|
376
|
+
</button>
|
|
377
|
+
</div>
|
|
370
378
|
<div class="queue-empty">
|
|
371
379
|
<i data-lucide="git-branch" class="w-16 h-16"></i>
|
|
372
380
|
<p class="queue-empty-title">${t('issues.queueEmpty') || 'Queue is empty'}</p>
|
|
@@ -423,6 +431,10 @@ function renderQueueSection() {
|
|
|
423
431
|
<button class="btn-secondary" onclick="refreshQueue()" title="${t('issues.refreshQueue') || 'Refresh'}">
|
|
424
432
|
<i data-lucide="refresh-cw" class="w-4 h-4"></i>
|
|
425
433
|
</button>
|
|
434
|
+
<button class="btn-secondary" onclick="showQueueHistoryModal()" title="${t('issues.queueHistory') || 'Queue History'}">
|
|
435
|
+
<i data-lucide="history" class="w-4 h-4"></i>
|
|
436
|
+
<span>${t('issues.history') || 'History'}</span>
|
|
437
|
+
</button>
|
|
426
438
|
<button class="btn-secondary" onclick="createExecutionQueue()" title="${t('issues.regenerateQueue') || 'Regenerate Queue'}">
|
|
427
439
|
<i data-lucide="rotate-cw" class="w-4 h-4"></i>
|
|
428
440
|
<span>${t('issues.regenerate') || 'Regenerate'}</span>
|
|
@@ -433,8 +445,8 @@ function renderQueueSection() {
|
|
|
433
445
|
<!-- Queue Stats -->
|
|
434
446
|
<div class="queue-stats-grid mb-4">
|
|
435
447
|
<div class="queue-stat-card">
|
|
436
|
-
<span class="queue-stat-value">${metadata.total_tasks || queueItems.length}</span>
|
|
437
|
-
<span class="queue-stat-label">${t('issues.totalTasks') || 'Total'}</span>
|
|
448
|
+
<span class="queue-stat-value">${isSolutionLevel ? (metadata.total_solutions || queueItems.length) : (metadata.total_tasks || queueItems.length)}</span>
|
|
449
|
+
<span class="queue-stat-label">${isSolutionLevel ? (t('issues.totalSolutions') || 'Solutions') : (t('issues.totalTasks') || 'Total')}</span>
|
|
438
450
|
</div>
|
|
439
451
|
<div class="queue-stat-card pending">
|
|
440
452
|
<span class="queue-stat-value">${metadata.pending_count || queueItems.filter(i => i.status === 'pending').length}</span>
|
|
@@ -500,6 +512,9 @@ function renderQueueSection() {
|
|
|
500
512
|
|
|
501
513
|
function renderQueueGroup(group, items) {
|
|
502
514
|
const isParallel = group.type === 'parallel';
|
|
515
|
+
// Support both solution-level (solution_count) and task-level (task_count)
|
|
516
|
+
const itemCount = group.solution_count || group.task_count || items.length;
|
|
517
|
+
const itemLabel = group.solution_count ? 'solutions' : 'tasks';
|
|
503
518
|
|
|
504
519
|
return `
|
|
505
520
|
<div class="queue-group" data-group-id="${group.id}">
|
|
@@ -508,7 +523,7 @@ function renderQueueGroup(group, items) {
|
|
|
508
523
|
<i data-lucide="${isParallel ? 'git-merge' : 'arrow-right'}" class="w-4 h-4"></i>
|
|
509
524
|
${group.id} (${isParallel ? t('issues.parallelGroup') || 'Parallel' : t('issues.sequentialGroup') || 'Sequential'})
|
|
510
525
|
</div>
|
|
511
|
-
<span class="text-sm text-muted-foreground">${
|
|
526
|
+
<span class="text-sm text-muted-foreground">${itemCount} ${itemLabel}</span>
|
|
512
527
|
</div>
|
|
513
528
|
<div class="queue-items ${isParallel ? 'parallel' : 'sequential'}">
|
|
514
529
|
${items.map((item, idx) => renderQueueItem(item, idx, items.length)).join('')}
|
|
@@ -527,6 +542,9 @@ function renderQueueItem(item, index, total) {
|
|
|
527
542
|
blocked: 'blocked'
|
|
528
543
|
};
|
|
529
544
|
|
|
545
|
+
// Check if this is a solution-level item (has task_count) or task-level (has task_id)
|
|
546
|
+
const isSolutionItem = item.task_count !== undefined;
|
|
547
|
+
|
|
530
548
|
return `
|
|
531
549
|
<div class="queue-item ${statusColors[item.status] || ''}"
|
|
532
550
|
draggable="true"
|
|
@@ -535,7 +553,20 @@ function renderQueueItem(item, index, total) {
|
|
|
535
553
|
onclick="openQueueItemDetail('${item.item_id}')">
|
|
536
554
|
<span class="queue-item-id font-mono text-xs">${item.item_id}</span>
|
|
537
555
|
<span class="queue-item-issue text-xs text-muted-foreground">${item.issue_id}</span>
|
|
538
|
-
|
|
556
|
+
${isSolutionItem ? `
|
|
557
|
+
<span class="queue-item-solution text-sm" title="${item.solution_id || ''}">
|
|
558
|
+
<i data-lucide="package" class="w-3 h-3 inline mr-1"></i>
|
|
559
|
+
${item.task_count} ${t('issues.tasks') || 'tasks'}
|
|
560
|
+
</span>
|
|
561
|
+
${item.files_touched && item.files_touched.length > 0 ? `
|
|
562
|
+
<span class="queue-item-files text-xs text-muted-foreground" title="${item.files_touched.join(', ')}">
|
|
563
|
+
<i data-lucide="file" class="w-3 h-3"></i>
|
|
564
|
+
${item.files_touched.length}
|
|
565
|
+
</span>
|
|
566
|
+
` : ''}
|
|
567
|
+
` : `
|
|
568
|
+
<span class="queue-item-task text-sm">${item.task_id || '-'}</span>
|
|
569
|
+
`}
|
|
539
570
|
<span class="queue-item-priority" style="opacity: ${item.semantic_priority || 0.5}">
|
|
540
571
|
<i data-lucide="arrow-up" class="w-3 h-3"></i>
|
|
541
572
|
</span>
|
|
@@ -559,9 +590,12 @@ function renderConflictsSection(conflicts) {
|
|
|
559
590
|
${conflicts.map(c => `
|
|
560
591
|
<div class="conflict-item">
|
|
561
592
|
<span class="conflict-file font-mono text-xs">${c.file}</span>
|
|
562
|
-
<span class="conflict-
|
|
563
|
-
|
|
564
|
-
|
|
593
|
+
<span class="conflict-items text-xs text-muted-foreground">${(c.solutions || c.tasks || []).join(' → ')}</span>
|
|
594
|
+
${c.rationale ? `<span class="conflict-rationale text-xs text-muted-foreground" title="${c.rationale}">
|
|
595
|
+
<i data-lucide="info" class="w-3 h-3"></i>
|
|
596
|
+
</span>` : ''}
|
|
597
|
+
<span class="conflict-status ${c.resolved || c.resolution ? 'resolved' : 'pending'}">
|
|
598
|
+
${c.resolved || c.resolution ? 'Resolved' : 'Pending'}
|
|
565
599
|
</span>
|
|
566
600
|
</div>
|
|
567
601
|
`).join('')}
|
|
@@ -1146,7 +1180,9 @@ function escapeHtml(text) {
|
|
|
1146
1180
|
}
|
|
1147
1181
|
|
|
1148
1182
|
function openQueueItemDetail(itemId) {
|
|
1149
|
-
|
|
1183
|
+
// Support both solution-level and task-level queues
|
|
1184
|
+
const items = issueData.queue.solutions || issueData.queue.tasks || [];
|
|
1185
|
+
const item = items.find(q => q.item_id === itemId);
|
|
1150
1186
|
if (item) {
|
|
1151
1187
|
openIssueDetail(item.issue_id);
|
|
1152
1188
|
}
|
|
@@ -1529,6 +1565,253 @@ function hideQueueCommandModal() {
|
|
|
1529
1565
|
}
|
|
1530
1566
|
}
|
|
1531
1567
|
|
|
1568
|
+
// ========== Queue History Modal ==========
|
|
1569
|
+
async function showQueueHistoryModal() {
|
|
1570
|
+
// Create modal if not exists
|
|
1571
|
+
let modal = document.getElementById('queueHistoryModal');
|
|
1572
|
+
if (!modal) {
|
|
1573
|
+
modal = document.createElement('div');
|
|
1574
|
+
modal.id = 'queueHistoryModal';
|
|
1575
|
+
modal.className = 'issue-modal';
|
|
1576
|
+
document.body.appendChild(modal);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
// Show loading state
|
|
1580
|
+
modal.innerHTML = `
|
|
1581
|
+
<div class="issue-modal-backdrop" onclick="hideQueueHistoryModal()"></div>
|
|
1582
|
+
<div class="issue-modal-content" style="max-width: 700px; max-height: 80vh;">
|
|
1583
|
+
<div class="issue-modal-header">
|
|
1584
|
+
<h3><i data-lucide="history" class="w-5 h-5 inline mr-2"></i>Queue History</h3>
|
|
1585
|
+
<button class="btn-icon" onclick="hideQueueHistoryModal()">
|
|
1586
|
+
<i data-lucide="x" class="w-5 h-5"></i>
|
|
1587
|
+
</button>
|
|
1588
|
+
</div>
|
|
1589
|
+
<div class="issue-modal-body" style="overflow-y: auto; max-height: calc(80vh - 120px);">
|
|
1590
|
+
<div class="flex items-center justify-center py-8">
|
|
1591
|
+
<i data-lucide="loader-2" class="w-6 h-6 animate-spin"></i>
|
|
1592
|
+
<span class="ml-2">Loading...</span>
|
|
1593
|
+
</div>
|
|
1594
|
+
</div>
|
|
1595
|
+
</div>
|
|
1596
|
+
`;
|
|
1597
|
+
modal.classList.remove('hidden');
|
|
1598
|
+
lucide.createIcons();
|
|
1599
|
+
|
|
1600
|
+
// Fetch queue history
|
|
1601
|
+
try {
|
|
1602
|
+
const response = await fetch(`/api/queue/history?path=${encodeURIComponent(projectPath)}`);
|
|
1603
|
+
const data = await response.json();
|
|
1604
|
+
|
|
1605
|
+
const queues = data.queues || [];
|
|
1606
|
+
const activeQueueId = data.active_queue_id;
|
|
1607
|
+
|
|
1608
|
+
// Render queue list
|
|
1609
|
+
const queueListHtml = queues.length === 0
|
|
1610
|
+
? `<div class="text-center py-8 text-muted-foreground">
|
|
1611
|
+
<i data-lucide="inbox" class="w-12 h-12 mx-auto mb-2 opacity-50"></i>
|
|
1612
|
+
<p>No queue history found</p>
|
|
1613
|
+
</div>`
|
|
1614
|
+
: `<div class="queue-history-list">
|
|
1615
|
+
${queues.map(q => `
|
|
1616
|
+
<div class="queue-history-item ${q.id === activeQueueId ? 'active' : ''}" onclick="viewQueueDetail('${q.id}')">
|
|
1617
|
+
<div class="queue-history-header">
|
|
1618
|
+
<span class="queue-history-id font-mono">${q.id}</span>
|
|
1619
|
+
${q.id === activeQueueId ? '<span class="queue-active-badge">Active</span>' : ''}
|
|
1620
|
+
<span class="queue-history-status ${q.status || ''}">${q.status || 'unknown'}</span>
|
|
1621
|
+
</div>
|
|
1622
|
+
<div class="queue-history-meta">
|
|
1623
|
+
<span class="text-xs text-muted-foreground">
|
|
1624
|
+
<i data-lucide="layers" class="w-3 h-3 inline"></i>
|
|
1625
|
+
${q.issue_ids?.length || 0} issues
|
|
1626
|
+
</span>
|
|
1627
|
+
<span class="text-xs text-muted-foreground">
|
|
1628
|
+
<i data-lucide="check-circle" class="w-3 h-3 inline"></i>
|
|
1629
|
+
${q.completed_solutions || q.completed_tasks || 0}/${q.total_solutions || q.total_tasks || 0} ${q.total_solutions ? 'solutions' : 'tasks'}
|
|
1630
|
+
</span>
|
|
1631
|
+
<span class="text-xs text-muted-foreground">
|
|
1632
|
+
<i data-lucide="calendar" class="w-3 h-3 inline"></i>
|
|
1633
|
+
${q.created_at ? new Date(q.created_at).toLocaleDateString() : 'N/A'}
|
|
1634
|
+
</span>
|
|
1635
|
+
</div>
|
|
1636
|
+
<div class="queue-history-actions">
|
|
1637
|
+
${q.id !== activeQueueId ? `
|
|
1638
|
+
<button class="btn-sm btn-primary" onclick="event.stopPropagation(); switchToQueue('${q.id}')">
|
|
1639
|
+
<i data-lucide="arrow-right-circle" class="w-3 h-3"></i>
|
|
1640
|
+
Switch
|
|
1641
|
+
</button>
|
|
1642
|
+
` : ''}
|
|
1643
|
+
<button class="btn-sm btn-secondary" onclick="event.stopPropagation(); viewQueueDetail('${q.id}')">
|
|
1644
|
+
<i data-lucide="eye" class="w-3 h-3"></i>
|
|
1645
|
+
View
|
|
1646
|
+
</button>
|
|
1647
|
+
</div>
|
|
1648
|
+
</div>
|
|
1649
|
+
`).join('')}
|
|
1650
|
+
</div>`;
|
|
1651
|
+
|
|
1652
|
+
modal.querySelector('.issue-modal-body').innerHTML = queueListHtml;
|
|
1653
|
+
lucide.createIcons();
|
|
1654
|
+
|
|
1655
|
+
} catch (err) {
|
|
1656
|
+
console.error('Failed to load queue history:', err);
|
|
1657
|
+
modal.querySelector('.issue-modal-body').innerHTML = `
|
|
1658
|
+
<div class="text-center py-8 text-red-500">
|
|
1659
|
+
<i data-lucide="alert-circle" class="w-8 h-8 mx-auto mb-2"></i>
|
|
1660
|
+
<p>Failed to load queue history</p>
|
|
1661
|
+
</div>
|
|
1662
|
+
`;
|
|
1663
|
+
lucide.createIcons();
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
function hideQueueHistoryModal() {
|
|
1668
|
+
const modal = document.getElementById('queueHistoryModal');
|
|
1669
|
+
if (modal) {
|
|
1670
|
+
modal.classList.add('hidden');
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
async function switchToQueue(queueId) {
|
|
1675
|
+
try {
|
|
1676
|
+
const response = await fetch(`/api/queue/switch?path=${encodeURIComponent(projectPath)}`, {
|
|
1677
|
+
method: 'POST',
|
|
1678
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1679
|
+
body: JSON.stringify({ queueId })
|
|
1680
|
+
});
|
|
1681
|
+
|
|
1682
|
+
const result = await response.json();
|
|
1683
|
+
if (result.success) {
|
|
1684
|
+
showNotification(t('issues.queueSwitched') || 'Switched to queue: ' + queueId, 'success');
|
|
1685
|
+
hideQueueHistoryModal();
|
|
1686
|
+
await loadQueueData();
|
|
1687
|
+
renderIssueView();
|
|
1688
|
+
} else {
|
|
1689
|
+
showNotification(result.error || 'Failed to switch queue', 'error');
|
|
1690
|
+
}
|
|
1691
|
+
} catch (err) {
|
|
1692
|
+
console.error('Failed to switch queue:', err);
|
|
1693
|
+
showNotification('Failed to switch queue', 'error');
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
async function viewQueueDetail(queueId) {
|
|
1698
|
+
const modal = document.getElementById('queueHistoryModal');
|
|
1699
|
+
if (!modal) return;
|
|
1700
|
+
|
|
1701
|
+
// Show loading
|
|
1702
|
+
modal.querySelector('.issue-modal-body').innerHTML = `
|
|
1703
|
+
<div class="flex items-center justify-center py-8">
|
|
1704
|
+
<i data-lucide="loader-2" class="w-6 h-6 animate-spin"></i>
|
|
1705
|
+
<span class="ml-2">${t('common.loading') || 'Loading...'}</span>
|
|
1706
|
+
</div>
|
|
1707
|
+
`;
|
|
1708
|
+
lucide.createIcons();
|
|
1709
|
+
|
|
1710
|
+
try {
|
|
1711
|
+
const response = await fetch(`/api/queue/${queueId}?path=${encodeURIComponent(projectPath)}`);
|
|
1712
|
+
const queue = await response.json();
|
|
1713
|
+
|
|
1714
|
+
if (queue.error) {
|
|
1715
|
+
throw new Error(queue.error);
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
// Support both solution-level and task-level queues
|
|
1719
|
+
const items = queue.solutions || queue.queue || queue.tasks || [];
|
|
1720
|
+
const isSolutionLevel = !!(queue.solutions && queue.solutions.length > 0);
|
|
1721
|
+
const metadata = queue._metadata || {};
|
|
1722
|
+
|
|
1723
|
+
// Group by execution_group
|
|
1724
|
+
const grouped = {};
|
|
1725
|
+
items.forEach(item => {
|
|
1726
|
+
const group = item.execution_group || 'ungrouped';
|
|
1727
|
+
if (!grouped[group]) grouped[group] = [];
|
|
1728
|
+
grouped[group].push(item);
|
|
1729
|
+
});
|
|
1730
|
+
|
|
1731
|
+
const itemLabel = isSolutionLevel ? 'solutions' : 'tasks';
|
|
1732
|
+
|
|
1733
|
+
const detailHtml = `
|
|
1734
|
+
<div class="queue-detail-view">
|
|
1735
|
+
<div class="queue-detail-header mb-4">
|
|
1736
|
+
<button class="btn-sm btn-secondary" onclick="showQueueHistoryModal()">
|
|
1737
|
+
<i data-lucide="arrow-left" class="w-3 h-3"></i>
|
|
1738
|
+
Back
|
|
1739
|
+
</button>
|
|
1740
|
+
<div class="ml-4">
|
|
1741
|
+
<h4 class="text-lg font-semibold">${queue.name || queue.id || queueId}</h4>
|
|
1742
|
+
${queue.name ? `<span class="text-xs text-muted-foreground font-mono">${queue.id}</span>` : ''}
|
|
1743
|
+
</div>
|
|
1744
|
+
</div>
|
|
1745
|
+
|
|
1746
|
+
<div class="queue-detail-stats mb-4">
|
|
1747
|
+
<div class="stat-item">
|
|
1748
|
+
<span class="stat-value">${items.length}</span>
|
|
1749
|
+
<span class="stat-label">${isSolutionLevel ? 'Solutions' : 'Total'}</span>
|
|
1750
|
+
</div>
|
|
1751
|
+
<div class="stat-item completed">
|
|
1752
|
+
<span class="stat-value">${items.filter(t => t.status === 'completed').length}</span>
|
|
1753
|
+
<span class="stat-label">Completed</span>
|
|
1754
|
+
</div>
|
|
1755
|
+
<div class="stat-item pending">
|
|
1756
|
+
<span class="stat-value">${items.filter(t => t.status === 'pending').length}</span>
|
|
1757
|
+
<span class="stat-label">Pending</span>
|
|
1758
|
+
</div>
|
|
1759
|
+
<div class="stat-item failed">
|
|
1760
|
+
<span class="stat-value">${items.filter(t => t.status === 'failed').length}</span>
|
|
1761
|
+
<span class="stat-label">Failed</span>
|
|
1762
|
+
</div>
|
|
1763
|
+
</div>
|
|
1764
|
+
|
|
1765
|
+
<div class="queue-detail-groups">
|
|
1766
|
+
${Object.entries(grouped).map(([groupId, groupItems]) => `
|
|
1767
|
+
<div class="queue-group-section">
|
|
1768
|
+
<div class="queue-group-header">
|
|
1769
|
+
<i data-lucide="folder" class="w-4 h-4"></i>
|
|
1770
|
+
<span>${groupId}</span>
|
|
1771
|
+
<span class="text-xs text-muted-foreground">(${groupItems.length} ${itemLabel})</span>
|
|
1772
|
+
</div>
|
|
1773
|
+
<div class="queue-group-items">
|
|
1774
|
+
${groupItems.map(item => `
|
|
1775
|
+
<div class="queue-detail-item ${item.status || ''}">
|
|
1776
|
+
<div class="item-main">
|
|
1777
|
+
<span class="item-id font-mono text-xs">${item.item_id || item.queue_id || item.task_id || 'N/A'}</span>
|
|
1778
|
+
<span class="item-title text-sm">${isSolutionLevel ? (item.task_count + ' tasks') : (item.title || item.action || 'Untitled')}</span>
|
|
1779
|
+
</div>
|
|
1780
|
+
<div class="item-meta">
|
|
1781
|
+
<span class="item-issue text-xs">${item.issue_id || ''}</span>
|
|
1782
|
+
${isSolutionLevel && item.files_touched ? `<span class="item-files text-xs">${item.files_touched.length} files</span>` : ''}
|
|
1783
|
+
<span class="item-status ${item.status || ''}">${item.status || 'unknown'}</span>
|
|
1784
|
+
</div>
|
|
1785
|
+
</div>
|
|
1786
|
+
`).join('')}
|
|
1787
|
+
</div>
|
|
1788
|
+
</div>
|
|
1789
|
+
`).join('')}
|
|
1790
|
+
</div>
|
|
1791
|
+
</div>
|
|
1792
|
+
`;
|
|
1793
|
+
|
|
1794
|
+
modal.querySelector('.issue-modal-body').innerHTML = detailHtml;
|
|
1795
|
+
lucide.createIcons();
|
|
1796
|
+
|
|
1797
|
+
} catch (err) {
|
|
1798
|
+
console.error('Failed to load queue detail:', err);
|
|
1799
|
+
modal.querySelector('.issue-modal-body').innerHTML = `
|
|
1800
|
+
<div class="text-center py-8">
|
|
1801
|
+
<button class="btn-sm btn-secondary mb-4" onclick="showQueueHistoryModal()">
|
|
1802
|
+
<i data-lucide="arrow-left" class="w-3 h-3"></i>
|
|
1803
|
+
Back
|
|
1804
|
+
</button>
|
|
1805
|
+
<div class="text-red-500">
|
|
1806
|
+
<i data-lucide="alert-circle" class="w-8 h-8 mx-auto mb-2"></i>
|
|
1807
|
+
<p>Failed to load queue detail</p>
|
|
1808
|
+
</div>
|
|
1809
|
+
</div>
|
|
1810
|
+
`;
|
|
1811
|
+
lucide.createIcons();
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1532
1815
|
function copyCommand(command) {
|
|
1533
1816
|
navigator.clipboard.writeText(command).then(() => {
|
|
1534
1817
|
showNotification(t('common.copied') || 'Copied to clipboard', 'success');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-workflow",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.10",
|
|
4
4
|
"description": "JSON-driven multi-agent development framework with intelligent CLI orchestration (Gemini/Qwen/Codex), context-first architecture, and automated workflow execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "ccw/src/index.js",
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "Issue Task JSONL Schema",
|
|
4
|
-
"description": "Schema for individual task entries in tasks.jsonl file",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"required": ["id", "title", "type", "description", "depends_on", "delivery_criteria", "status", "current_phase", "executor"],
|
|
7
|
-
"properties": {
|
|
8
|
-
"id": {
|
|
9
|
-
"type": "string",
|
|
10
|
-
"description": "Unique task identifier (e.g., TASK-001)",
|
|
11
|
-
"pattern": "^TASK-[0-9]+$"
|
|
12
|
-
},
|
|
13
|
-
"title": {
|
|
14
|
-
"type": "string",
|
|
15
|
-
"description": "Short summary of the task",
|
|
16
|
-
"maxLength": 100
|
|
17
|
-
},
|
|
18
|
-
"type": {
|
|
19
|
-
"type": "string",
|
|
20
|
-
"enum": ["feature", "bug", "refactor", "test", "chore", "docs"],
|
|
21
|
-
"description": "Task category"
|
|
22
|
-
},
|
|
23
|
-
"description": {
|
|
24
|
-
"type": "string",
|
|
25
|
-
"description": "Detailed instructions for the task"
|
|
26
|
-
},
|
|
27
|
-
"file_context": {
|
|
28
|
-
"type": "array",
|
|
29
|
-
"items": { "type": "string" },
|
|
30
|
-
"description": "List of relevant files/globs",
|
|
31
|
-
"default": []
|
|
32
|
-
},
|
|
33
|
-
"depends_on": {
|
|
34
|
-
"type": "array",
|
|
35
|
-
"items": { "type": "string" },
|
|
36
|
-
"description": "Array of Task IDs that must complete first",
|
|
37
|
-
"default": []
|
|
38
|
-
},
|
|
39
|
-
"delivery_criteria": {
|
|
40
|
-
"type": "array",
|
|
41
|
-
"items": { "type": "string" },
|
|
42
|
-
"description": "Checklist items that define task completion",
|
|
43
|
-
"minItems": 1
|
|
44
|
-
},
|
|
45
|
-
"pause_criteria": {
|
|
46
|
-
"type": "array",
|
|
47
|
-
"items": { "type": "string" },
|
|
48
|
-
"description": "Conditions that should halt execution (e.g., 'API spec unclear')",
|
|
49
|
-
"default": []
|
|
50
|
-
},
|
|
51
|
-
"status": {
|
|
52
|
-
"type": "string",
|
|
53
|
-
"enum": ["pending", "ready", "in_progress", "completed", "failed", "paused", "skipped"],
|
|
54
|
-
"description": "Current task status",
|
|
55
|
-
"default": "pending"
|
|
56
|
-
},
|
|
57
|
-
"current_phase": {
|
|
58
|
-
"type": "string",
|
|
59
|
-
"enum": ["analyze", "implement", "test", "optimize", "commit", "done"],
|
|
60
|
-
"description": "Current execution phase within the task lifecycle",
|
|
61
|
-
"default": "analyze"
|
|
62
|
-
},
|
|
63
|
-
"executor": {
|
|
64
|
-
"type": "string",
|
|
65
|
-
"enum": ["agent", "codex", "gemini", "auto"],
|
|
66
|
-
"description": "Preferred executor for this task",
|
|
67
|
-
"default": "auto"
|
|
68
|
-
},
|
|
69
|
-
"priority": {
|
|
70
|
-
"type": "integer",
|
|
71
|
-
"minimum": 1,
|
|
72
|
-
"maximum": 5,
|
|
73
|
-
"description": "Task priority (1=highest, 5=lowest)",
|
|
74
|
-
"default": 3
|
|
75
|
-
},
|
|
76
|
-
"phase_results": {
|
|
77
|
-
"type": "object",
|
|
78
|
-
"description": "Results from each execution phase",
|
|
79
|
-
"properties": {
|
|
80
|
-
"analyze": {
|
|
81
|
-
"type": "object",
|
|
82
|
-
"properties": {
|
|
83
|
-
"status": { "type": "string" },
|
|
84
|
-
"findings": { "type": "array", "items": { "type": "string" } },
|
|
85
|
-
"timestamp": { "type": "string", "format": "date-time" }
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
"implement": {
|
|
89
|
-
"type": "object",
|
|
90
|
-
"properties": {
|
|
91
|
-
"status": { "type": "string" },
|
|
92
|
-
"files_modified": { "type": "array", "items": { "type": "string" } },
|
|
93
|
-
"timestamp": { "type": "string", "format": "date-time" }
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
"test": {
|
|
97
|
-
"type": "object",
|
|
98
|
-
"properties": {
|
|
99
|
-
"status": { "type": "string" },
|
|
100
|
-
"test_results": { "type": "string" },
|
|
101
|
-
"retry_count": { "type": "integer" },
|
|
102
|
-
"timestamp": { "type": "string", "format": "date-time" }
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
"optimize": {
|
|
106
|
-
"type": "object",
|
|
107
|
-
"properties": {
|
|
108
|
-
"status": { "type": "string" },
|
|
109
|
-
"improvements": { "type": "array", "items": { "type": "string" } },
|
|
110
|
-
"timestamp": { "type": "string", "format": "date-time" }
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
"commit": {
|
|
114
|
-
"type": "object",
|
|
115
|
-
"properties": {
|
|
116
|
-
"status": { "type": "string" },
|
|
117
|
-
"commit_hash": { "type": "string" },
|
|
118
|
-
"message": { "type": "string" },
|
|
119
|
-
"timestamp": { "type": "string", "format": "date-time" }
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
"created_at": {
|
|
125
|
-
"type": "string",
|
|
126
|
-
"format": "date-time",
|
|
127
|
-
"description": "Task creation timestamp"
|
|
128
|
-
},
|
|
129
|
-
"updated_at": {
|
|
130
|
-
"type": "string",
|
|
131
|
-
"format": "date-time",
|
|
132
|
-
"description": "Last update timestamp"
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
"additionalProperties": false
|
|
136
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "Solutions JSONL Schema",
|
|
4
|
-
"description": "Schema for each line in solutions/{issue-id}.jsonl",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"required": ["id", "tasks", "created_at"],
|
|
7
|
-
"properties": {
|
|
8
|
-
"id": {
|
|
9
|
-
"type": "string",
|
|
10
|
-
"description": "Unique solution identifier",
|
|
11
|
-
"pattern": "^SOL-[0-9]+$"
|
|
12
|
-
},
|
|
13
|
-
"description": {
|
|
14
|
-
"type": "string",
|
|
15
|
-
"description": "Solution approach description"
|
|
16
|
-
},
|
|
17
|
-
"tasks": {
|
|
18
|
-
"type": "array",
|
|
19
|
-
"description": "Task breakdown for this solution",
|
|
20
|
-
"items": {
|
|
21
|
-
"type": "object",
|
|
22
|
-
"required": ["id", "title", "scope", "action", "acceptance"],
|
|
23
|
-
"properties": {
|
|
24
|
-
"id": {
|
|
25
|
-
"type": "string",
|
|
26
|
-
"pattern": "^T[0-9]+$"
|
|
27
|
-
},
|
|
28
|
-
"title": {
|
|
29
|
-
"type": "string",
|
|
30
|
-
"description": "Action verb + target"
|
|
31
|
-
},
|
|
32
|
-
"scope": {
|
|
33
|
-
"type": "string",
|
|
34
|
-
"description": "Module path or feature area"
|
|
35
|
-
},
|
|
36
|
-
"action": {
|
|
37
|
-
"type": "string",
|
|
38
|
-
"enum": ["Create", "Update", "Implement", "Refactor", "Add", "Delete", "Configure", "Test", "Fix"]
|
|
39
|
-
},
|
|
40
|
-
"description": {
|
|
41
|
-
"type": "string",
|
|
42
|
-
"description": "1-2 sentences describing what to implement"
|
|
43
|
-
},
|
|
44
|
-
"modification_points": {
|
|
45
|
-
"type": "array",
|
|
46
|
-
"items": {
|
|
47
|
-
"type": "object",
|
|
48
|
-
"properties": {
|
|
49
|
-
"file": { "type": "string" },
|
|
50
|
-
"target": { "type": "string" },
|
|
51
|
-
"change": { "type": "string" }
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
"implementation": {
|
|
56
|
-
"type": "array",
|
|
57
|
-
"items": { "type": "string" },
|
|
58
|
-
"description": "Step-by-step implementation guide"
|
|
59
|
-
},
|
|
60
|
-
"acceptance": {
|
|
61
|
-
"type": "array",
|
|
62
|
-
"items": { "type": "string" },
|
|
63
|
-
"description": "Quantified completion criteria"
|
|
64
|
-
},
|
|
65
|
-
"depends_on": {
|
|
66
|
-
"type": "array",
|
|
67
|
-
"items": { "type": "string" },
|
|
68
|
-
"default": [],
|
|
69
|
-
"description": "Task IDs this task depends on"
|
|
70
|
-
},
|
|
71
|
-
"estimated_minutes": {
|
|
72
|
-
"type": "integer",
|
|
73
|
-
"description": "Estimated time to complete"
|
|
74
|
-
},
|
|
75
|
-
"executor": {
|
|
76
|
-
"type": "string",
|
|
77
|
-
"enum": ["codex", "gemini", "agent", "auto"],
|
|
78
|
-
"default": "auto"
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
"exploration_context": {
|
|
84
|
-
"type": "object",
|
|
85
|
-
"description": "ACE exploration results",
|
|
86
|
-
"properties": {
|
|
87
|
-
"project_structure": { "type": "string" },
|
|
88
|
-
"relevant_files": {
|
|
89
|
-
"type": "array",
|
|
90
|
-
"items": { "type": "string" }
|
|
91
|
-
},
|
|
92
|
-
"patterns": { "type": "string" },
|
|
93
|
-
"integration_points": { "type": "string" }
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
"analysis": {
|
|
97
|
-
"type": "object",
|
|
98
|
-
"properties": {
|
|
99
|
-
"risk": { "type": "string", "enum": ["low", "medium", "high"] },
|
|
100
|
-
"impact": { "type": "string", "enum": ["low", "medium", "high"] },
|
|
101
|
-
"complexity": { "type": "string", "enum": ["low", "medium", "high"] }
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
"score": {
|
|
105
|
-
"type": "number",
|
|
106
|
-
"minimum": 0,
|
|
107
|
-
"maximum": 1,
|
|
108
|
-
"description": "Solution quality score (0.0-1.0)"
|
|
109
|
-
},
|
|
110
|
-
"is_bound": {
|
|
111
|
-
"type": "boolean",
|
|
112
|
-
"default": false,
|
|
113
|
-
"description": "Whether this solution is bound to the issue"
|
|
114
|
-
},
|
|
115
|
-
"created_at": {
|
|
116
|
-
"type": "string",
|
|
117
|
-
"format": "date-time"
|
|
118
|
-
},
|
|
119
|
-
"bound_at": {
|
|
120
|
-
"type": "string",
|
|
121
|
-
"format": "date-time",
|
|
122
|
-
"description": "When this solution was bound to the issue"
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|