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.
Files changed (36) hide show
  1. package/.claude/CLAUDE.md +1 -1
  2. package/.claude/agents/issue-plan-agent.md +84 -56
  3. package/.claude/agents/issue-queue-agent.md +120 -108
  4. package/.claude/commands/issue/execute.md +195 -363
  5. package/.claude/commands/issue/plan.md +70 -27
  6. package/.claude/commands/issue/queue.md +130 -66
  7. package/.claude/commands/workflow/init.md +75 -29
  8. package/.claude/commands/workflow/lite-fix.md +8 -0
  9. package/.claude/commands/workflow/lite-plan.md +8 -0
  10. package/.claude/commands/workflow/review-module-cycle.md +4 -0
  11. package/.claude/commands/workflow/review-session-cycle.md +4 -0
  12. package/.claude/commands/workflow/review.md +4 -4
  13. package/.claude/commands/workflow/session/solidify.md +299 -0
  14. package/.claude/commands/workflow/session/start.md +10 -7
  15. package/.claude/commands/workflow/tools/context-gather.md +17 -10
  16. package/.claude/workflows/cli-templates/schemas/queue-schema.json +225 -108
  17. package/.claude/workflows/cli-templates/schemas/solution-schema.json +60 -15
  18. package/.claude/workflows/context-tools.md +17 -25
  19. package/.codex/AGENTS.md +10 -5
  20. package/ccw/dist/commands/issue.d.ts.map +1 -1
  21. package/ccw/dist/commands/issue.js +348 -115
  22. package/ccw/dist/commands/issue.js.map +1 -1
  23. package/ccw/dist/core/routes/issue-routes.d.ts.map +1 -1
  24. package/ccw/dist/core/routes/issue-routes.js +68 -0
  25. package/ccw/dist/core/routes/issue-routes.js.map +1 -1
  26. package/ccw/src/commands/issue.ts +408 -148
  27. package/ccw/src/core/routes/issue-routes.ts +76 -0
  28. package/ccw/src/templates/dashboard-css/32-issue-manager.css +310 -1
  29. package/ccw/src/templates/dashboard-js/components/cli-status.js +1 -78
  30. package/ccw/src/templates/dashboard-js/i18n.js +0 -4
  31. package/ccw/src/templates/dashboard-js/views/cli-manager.js +0 -18
  32. package/ccw/src/templates/dashboard-js/views/issue-manager.js +294 -11
  33. package/package.json +1 -1
  34. package/.claude/workflows/cli-templates/schemas/issue-task-jsonl-schema.json +0 -136
  35. package/.claude/workflows/cli-templates/schemas/solutions-jsonl-schema.json +0 -125
  36. 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
- const queueItems = queue.tasks || [];
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">${group.task_count} tasks</span>
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
- <span class="queue-item-task text-sm">${item.task_id}</span>
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-tasks text-xs text-muted-foreground">${c.tasks.join(' → ')}</span>
563
- <span class="conflict-status ${c.resolved ? 'resolved' : 'pending'}">
564
- ${c.resolved ? 'Resolved' : 'Pending'}
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
- const item = issueData.queue.tasks?.find(q => q.item_id === itemId);
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.8",
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
- }