claude-code-workflow 6.0.0 → 6.0.2
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/commands/workflow/review-fix.md +18 -58
- package/.claude/commands/workflow/review-module-cycle.md +20 -50
- package/.claude/commands/workflow/review-session-cycle.md +19 -48
- package/README.md +76 -10
- package/ccw/package.json +47 -0
- package/ccw/src/core/server.js +22 -1
- package/ccw/src/templates/dashboard-js/views/review-session.js +319 -0
- package/ccw/src/templates/dashboard.css +271 -0
- package/package.json +8 -7
- package/.claude/commands/workflow/status.md +0 -352
|
@@ -121,6 +121,9 @@ function renderReviewSessionDetailPage(session) {
|
|
|
121
121
|
|
|
122
122
|
</div>
|
|
123
123
|
|
|
124
|
+
<!-- Fix Progress Section (dynamically populated) -->
|
|
125
|
+
<div id="fixProgressSection" class="fix-progress-section-container"></div>
|
|
126
|
+
|
|
124
127
|
<!-- Enhanced Findings Section -->
|
|
125
128
|
<div class="review-enhanced-container">
|
|
126
129
|
<!-- Header with Stats & Controls -->
|
|
@@ -697,6 +700,11 @@ function initReviewSessionPage(session) {
|
|
|
697
700
|
// Reset state when page loads
|
|
698
701
|
reviewSessionState.session = session;
|
|
699
702
|
// Event handlers are inline onclick - no additional setup needed
|
|
703
|
+
|
|
704
|
+
// Start fix progress polling if in server mode
|
|
705
|
+
if (window.SERVER_MODE && session?.session_id) {
|
|
706
|
+
startFixProgressPolling(session.session_id);
|
|
707
|
+
}
|
|
700
708
|
}
|
|
701
709
|
|
|
702
710
|
// Legacy filter function for compatibility
|
|
@@ -709,3 +717,314 @@ function filterReviewFindings(severity) {
|
|
|
709
717
|
}
|
|
710
718
|
applyReviewSessionFilters();
|
|
711
719
|
}
|
|
720
|
+
|
|
721
|
+
// ==========================================
|
|
722
|
+
// FIX PROGRESS TRACKING
|
|
723
|
+
// ==========================================
|
|
724
|
+
|
|
725
|
+
// Fix progress state
|
|
726
|
+
let fixProgressState = {
|
|
727
|
+
fixPlan: null,
|
|
728
|
+
progressData: null,
|
|
729
|
+
pollInterval: null,
|
|
730
|
+
currentSlide: 0
|
|
731
|
+
};
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Discover and load fix-plan.json for the current review session
|
|
735
|
+
* Searches in: .review/fixes/{fix-session-id}/fix-plan.json
|
|
736
|
+
*/
|
|
737
|
+
async function loadFixProgress(sessionId) {
|
|
738
|
+
if (!window.SERVER_MODE) {
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
try {
|
|
743
|
+
// First, discover active fix session
|
|
744
|
+
const activeFixResponse = await fetch(`/api/file?path=${encodeURIComponent(projectPath + '/.review/fixes/active-fix-session.json')}`);
|
|
745
|
+
if (!activeFixResponse.ok) {
|
|
746
|
+
return null;
|
|
747
|
+
}
|
|
748
|
+
const activeFixSession = await activeFixResponse.json();
|
|
749
|
+
const fixSessionId = activeFixSession.fix_session_id;
|
|
750
|
+
|
|
751
|
+
// Load fix-plan.json
|
|
752
|
+
const planPath = `${projectPath}/.review/fixes/${fixSessionId}/fix-plan.json`;
|
|
753
|
+
const planResponse = await fetch(`/api/file?path=${encodeURIComponent(planPath)}`);
|
|
754
|
+
if (!planResponse.ok) {
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
const fixPlan = await planResponse.json();
|
|
758
|
+
|
|
759
|
+
// Load progress files for each group
|
|
760
|
+
const progressPromises = (fixPlan.groups || []).map(async (group) => {
|
|
761
|
+
const progressPath = `${projectPath}/.review/fixes/${fixSessionId}/${group.progress_file}`;
|
|
762
|
+
try {
|
|
763
|
+
const response = await fetch(`/api/file?path=${encodeURIComponent(progressPath)}`);
|
|
764
|
+
return response.ok ? await response.json() : null;
|
|
765
|
+
} catch {
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
const progressDataArray = await Promise.all(progressPromises);
|
|
770
|
+
|
|
771
|
+
// Aggregate progress data
|
|
772
|
+
const aggregated = aggregateFixProgress(fixPlan, progressDataArray.filter(d => d !== null));
|
|
773
|
+
|
|
774
|
+
fixProgressState.fixPlan = fixPlan;
|
|
775
|
+
fixProgressState.progressData = aggregated;
|
|
776
|
+
|
|
777
|
+
return aggregated;
|
|
778
|
+
} catch (err) {
|
|
779
|
+
console.error('Failed to load fix progress:', err);
|
|
780
|
+
return null;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Aggregate progress from multiple group progress files
|
|
786
|
+
*/
|
|
787
|
+
function aggregateFixProgress(fixPlan, progressDataArray) {
|
|
788
|
+
let totalFindings = 0;
|
|
789
|
+
let fixedCount = 0;
|
|
790
|
+
let failedCount = 0;
|
|
791
|
+
let inProgressCount = 0;
|
|
792
|
+
let pendingCount = 0;
|
|
793
|
+
const activeAgents = [];
|
|
794
|
+
|
|
795
|
+
progressDataArray.forEach(progress => {
|
|
796
|
+
if (progress.findings) {
|
|
797
|
+
progress.findings.forEach(f => {
|
|
798
|
+
totalFindings++;
|
|
799
|
+
if (f.result === 'fixed') fixedCount++;
|
|
800
|
+
else if (f.result === 'failed') failedCount++;
|
|
801
|
+
else if (f.status === 'in-progress') inProgressCount++;
|
|
802
|
+
else pendingCount++;
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
if (progress.assigned_agent && progress.status === 'in-progress') {
|
|
806
|
+
activeAgents.push({
|
|
807
|
+
agent_id: progress.assigned_agent,
|
|
808
|
+
group_id: progress.group_id,
|
|
809
|
+
current_finding: progress.current_finding
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
// Determine phase
|
|
815
|
+
let phase = 'planning';
|
|
816
|
+
if (fixPlan.metadata?.status === 'executing' || inProgressCount > 0 || fixedCount > 0 || failedCount > 0) {
|
|
817
|
+
phase = 'execution';
|
|
818
|
+
}
|
|
819
|
+
if (totalFindings > 0 && pendingCount === 0 && inProgressCount === 0) {
|
|
820
|
+
phase = 'completion';
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Calculate stage progress
|
|
824
|
+
const stages = (fixPlan.timeline?.stages || []).map(stage => {
|
|
825
|
+
const groupStatuses = stage.groups.map(groupId => {
|
|
826
|
+
const progress = progressDataArray.find(p => p.group_id === groupId);
|
|
827
|
+
return progress ? progress.status : 'pending';
|
|
828
|
+
});
|
|
829
|
+
let status = 'pending';
|
|
830
|
+
if (groupStatuses.every(s => s === 'completed' || s === 'failed')) status = 'completed';
|
|
831
|
+
else if (groupStatuses.some(s => s === 'in-progress')) status = 'in-progress';
|
|
832
|
+
return { stage: stage.stage, status, groups: stage.groups };
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
const currentStage = stages.findIndex(s => s.status === 'in-progress' || s.status === 'pending') + 1 || stages.length;
|
|
836
|
+
const percentComplete = totalFindings > 0 ? ((fixedCount + failedCount) / totalFindings) * 100 : 0;
|
|
837
|
+
|
|
838
|
+
return {
|
|
839
|
+
fix_session_id: fixPlan.metadata?.fix_session_id,
|
|
840
|
+
phase,
|
|
841
|
+
total_findings: totalFindings,
|
|
842
|
+
fixed_count: fixedCount,
|
|
843
|
+
failed_count: failedCount,
|
|
844
|
+
in_progress_count: inProgressCount,
|
|
845
|
+
pending_count: pendingCount,
|
|
846
|
+
percent_complete: percentComplete,
|
|
847
|
+
current_stage: currentStage,
|
|
848
|
+
total_stages: stages.length,
|
|
849
|
+
stages,
|
|
850
|
+
active_agents: activeAgents
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Render fix progress tracking card (carousel style)
|
|
856
|
+
*/
|
|
857
|
+
function renderFixProgressCard(progressData) {
|
|
858
|
+
if (!progressData) {
|
|
859
|
+
return '';
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
const { phase, total_findings, fixed_count, failed_count, in_progress_count, pending_count, percent_complete, current_stage, total_stages, stages, active_agents, fix_session_id } = progressData;
|
|
863
|
+
|
|
864
|
+
// Phase badge class
|
|
865
|
+
const phaseClass = phase === 'planning' ? 'phase-planning' : phase === 'execution' ? 'phase-execution' : 'phase-completion';
|
|
866
|
+
const phaseIcon = phase === 'planning' ? '📝' : phase === 'execution' ? '⚡' : '✅';
|
|
867
|
+
|
|
868
|
+
// Build stage dots
|
|
869
|
+
const stageDots = stages.map((s, i) => {
|
|
870
|
+
const dotClass = s.status === 'completed' ? 'completed' : s.status === 'in-progress' ? 'active' : '';
|
|
871
|
+
return `<span class="fix-stage-dot ${dotClass}" title="Stage ${i + 1}: ${s.status}"></span>`;
|
|
872
|
+
}).join('');
|
|
873
|
+
|
|
874
|
+
// Build carousel slides
|
|
875
|
+
const slides = [];
|
|
876
|
+
|
|
877
|
+
// Slide 1: Overview
|
|
878
|
+
slides.push(`
|
|
879
|
+
<div class="fix-carousel-slide">
|
|
880
|
+
<div class="fix-slide-header">
|
|
881
|
+
<span class="fix-phase-badge ${phaseClass}">${phaseIcon} ${phase.toUpperCase()}</span>
|
|
882
|
+
<span class="fix-session-id">${fix_session_id || 'Fix Session'}</span>
|
|
883
|
+
</div>
|
|
884
|
+
<div class="fix-progress-bar-mini">
|
|
885
|
+
<div class="fix-progress-fill" style="width: ${percent_complete}%"></div>
|
|
886
|
+
</div>
|
|
887
|
+
<div class="fix-progress-text">${percent_complete.toFixed(0)}% Complete · Stage ${current_stage}/${total_stages}</div>
|
|
888
|
+
</div>
|
|
889
|
+
`);
|
|
890
|
+
|
|
891
|
+
// Slide 2: Stats
|
|
892
|
+
slides.push(`
|
|
893
|
+
<div class="fix-carousel-slide">
|
|
894
|
+
<div class="fix-stats-row">
|
|
895
|
+
<div class="fix-stat">
|
|
896
|
+
<span class="fix-stat-value">${total_findings}</span>
|
|
897
|
+
<span class="fix-stat-label">Total</span>
|
|
898
|
+
</div>
|
|
899
|
+
<div class="fix-stat fixed">
|
|
900
|
+
<span class="fix-stat-value">${fixed_count}</span>
|
|
901
|
+
<span class="fix-stat-label">Fixed</span>
|
|
902
|
+
</div>
|
|
903
|
+
<div class="fix-stat failed">
|
|
904
|
+
<span class="fix-stat-value">${failed_count}</span>
|
|
905
|
+
<span class="fix-stat-label">Failed</span>
|
|
906
|
+
</div>
|
|
907
|
+
<div class="fix-stat pending">
|
|
908
|
+
<span class="fix-stat-value">${pending_count + in_progress_count}</span>
|
|
909
|
+
<span class="fix-stat-label">Pending</span>
|
|
910
|
+
</div>
|
|
911
|
+
</div>
|
|
912
|
+
</div>
|
|
913
|
+
`);
|
|
914
|
+
|
|
915
|
+
// Slide 3: Active agents (if any)
|
|
916
|
+
if (active_agents.length > 0) {
|
|
917
|
+
const agentItems = active_agents.slice(0, 2).map(a => `
|
|
918
|
+
<div class="fix-agent-item">
|
|
919
|
+
<span class="fix-agent-icon">🤖</span>
|
|
920
|
+
<span class="fix-agent-info">${a.current_finding?.finding_title || 'Working...'}</span>
|
|
921
|
+
</div>
|
|
922
|
+
`).join('');
|
|
923
|
+
slides.push(`
|
|
924
|
+
<div class="fix-carousel-slide">
|
|
925
|
+
<div class="fix-agents-header">${active_agents.length} Active Agent${active_agents.length > 1 ? 's' : ''}</div>
|
|
926
|
+
${agentItems}
|
|
927
|
+
</div>
|
|
928
|
+
`);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Build carousel navigation
|
|
932
|
+
const navDots = slides.map((_, i) => `
|
|
933
|
+
<span class="fix-nav-dot ${i === 0 ? 'active' : ''}" onclick="navigateFixCarousel(${i})"></span>
|
|
934
|
+
`).join('');
|
|
935
|
+
|
|
936
|
+
return `
|
|
937
|
+
<div class="fix-progress-card" id="fixProgressCard">
|
|
938
|
+
<div class="fix-card-header">
|
|
939
|
+
<span class="fix-card-title">🔧 Fix Progress</span>
|
|
940
|
+
<div class="fix-stage-dots">${stageDots}</div>
|
|
941
|
+
</div>
|
|
942
|
+
<div class="fix-carousel-container">
|
|
943
|
+
<div class="fix-carousel-track" id="fixCarouselTrack">
|
|
944
|
+
${slides.join('')}
|
|
945
|
+
</div>
|
|
946
|
+
</div>
|
|
947
|
+
<div class="fix-carousel-nav">
|
|
948
|
+
<button class="fix-nav-btn prev" onclick="navigateFixCarousel('prev')">‹</button>
|
|
949
|
+
<div class="fix-nav-dots">${navDots}</div>
|
|
950
|
+
<button class="fix-nav-btn next" onclick="navigateFixCarousel('next')">›</button>
|
|
951
|
+
</div>
|
|
952
|
+
</div>
|
|
953
|
+
`;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Navigate fix progress carousel
|
|
958
|
+
*/
|
|
959
|
+
function navigateFixCarousel(direction) {
|
|
960
|
+
const track = document.getElementById('fixCarouselTrack');
|
|
961
|
+
if (!track) return;
|
|
962
|
+
|
|
963
|
+
const slides = track.querySelectorAll('.fix-carousel-slide');
|
|
964
|
+
const totalSlides = slides.length;
|
|
965
|
+
|
|
966
|
+
if (typeof direction === 'number') {
|
|
967
|
+
fixProgressState.currentSlide = direction;
|
|
968
|
+
} else if (direction === 'next') {
|
|
969
|
+
fixProgressState.currentSlide = (fixProgressState.currentSlide + 1) % totalSlides;
|
|
970
|
+
} else if (direction === 'prev') {
|
|
971
|
+
fixProgressState.currentSlide = (fixProgressState.currentSlide - 1 + totalSlides) % totalSlides;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
track.style.transform = `translateX(-${fixProgressState.currentSlide * 100}%)`;
|
|
975
|
+
|
|
976
|
+
// Update nav dots
|
|
977
|
+
document.querySelectorAll('.fix-nav-dot').forEach((dot, i) => {
|
|
978
|
+
dot.classList.toggle('active', i === fixProgressState.currentSlide);
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* Start polling for fix progress updates
|
|
984
|
+
*/
|
|
985
|
+
function startFixProgressPolling(sessionId) {
|
|
986
|
+
if (fixProgressState.pollInterval) {
|
|
987
|
+
clearInterval(fixProgressState.pollInterval);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// Initial load
|
|
991
|
+
loadFixProgress(sessionId).then(data => {
|
|
992
|
+
if (data) {
|
|
993
|
+
updateFixProgressUI(data);
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
// Poll every 5 seconds
|
|
998
|
+
fixProgressState.pollInterval = setInterval(async () => {
|
|
999
|
+
const data = await loadFixProgress(sessionId);
|
|
1000
|
+
if (data) {
|
|
1001
|
+
updateFixProgressUI(data);
|
|
1002
|
+
// Stop polling if completed
|
|
1003
|
+
if (data.phase === 'completion') {
|
|
1004
|
+
clearInterval(fixProgressState.pollInterval);
|
|
1005
|
+
fixProgressState.pollInterval = null;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}, 5000);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Update fix progress UI
|
|
1013
|
+
*/
|
|
1014
|
+
function updateFixProgressUI(progressData) {
|
|
1015
|
+
const container = document.getElementById('fixProgressSection');
|
|
1016
|
+
if (!container) return;
|
|
1017
|
+
|
|
1018
|
+
container.innerHTML = renderFixProgressCard(progressData);
|
|
1019
|
+
fixProgressState.currentSlide = 0;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* Stop fix progress polling
|
|
1024
|
+
*/
|
|
1025
|
+
function stopFixProgressPolling() {
|
|
1026
|
+
if (fixProgressState.pollInterval) {
|
|
1027
|
+
clearInterval(fixProgressState.pollInterval);
|
|
1028
|
+
fixProgressState.pollInterval = null;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
@@ -7658,3 +7658,274 @@ code.ctx-meta-chip-value {
|
|
|
7658
7658
|
font-size: 0.7rem;
|
|
7659
7659
|
color: hsl(var(--muted-foreground));
|
|
7660
7660
|
}
|
|
7661
|
+
|
|
7662
|
+
/* ===================================
|
|
7663
|
+
Fix Progress Tracking Card (Carousel)
|
|
7664
|
+
=================================== */
|
|
7665
|
+
|
|
7666
|
+
.fix-progress-section-container {
|
|
7667
|
+
margin-bottom: 1rem;
|
|
7668
|
+
}
|
|
7669
|
+
|
|
7670
|
+
.fix-progress-card {
|
|
7671
|
+
background: hsl(var(--card));
|
|
7672
|
+
border: 1px solid hsl(var(--border));
|
|
7673
|
+
border-radius: 0.5rem;
|
|
7674
|
+
padding: 1rem;
|
|
7675
|
+
overflow: hidden;
|
|
7676
|
+
}
|
|
7677
|
+
|
|
7678
|
+
.fix-card-header {
|
|
7679
|
+
display: flex;
|
|
7680
|
+
justify-content: space-between;
|
|
7681
|
+
align-items: center;
|
|
7682
|
+
margin-bottom: 0.75rem;
|
|
7683
|
+
}
|
|
7684
|
+
|
|
7685
|
+
.fix-card-title {
|
|
7686
|
+
font-weight: 600;
|
|
7687
|
+
font-size: 0.9rem;
|
|
7688
|
+
color: hsl(var(--foreground));
|
|
7689
|
+
}
|
|
7690
|
+
|
|
7691
|
+
.fix-stage-dots {
|
|
7692
|
+
display: flex;
|
|
7693
|
+
gap: 0.375rem;
|
|
7694
|
+
align-items: center;
|
|
7695
|
+
}
|
|
7696
|
+
|
|
7697
|
+
.fix-stage-dot {
|
|
7698
|
+
width: 8px;
|
|
7699
|
+
height: 8px;
|
|
7700
|
+
border-radius: 50%;
|
|
7701
|
+
background: hsl(var(--muted));
|
|
7702
|
+
transition: all 0.2s ease;
|
|
7703
|
+
}
|
|
7704
|
+
|
|
7705
|
+
.fix-stage-dot.active {
|
|
7706
|
+
background: hsl(var(--primary));
|
|
7707
|
+
animation: pulse-dot 1.5s infinite;
|
|
7708
|
+
}
|
|
7709
|
+
|
|
7710
|
+
.fix-stage-dot.completed {
|
|
7711
|
+
background: hsl(var(--success));
|
|
7712
|
+
}
|
|
7713
|
+
|
|
7714
|
+
@keyframes pulse-dot {
|
|
7715
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
7716
|
+
50% { opacity: 0.6; transform: scale(1.2); }
|
|
7717
|
+
}
|
|
7718
|
+
|
|
7719
|
+
/* Carousel Container */
|
|
7720
|
+
.fix-carousel-container {
|
|
7721
|
+
overflow: hidden;
|
|
7722
|
+
margin-bottom: 0.75rem;
|
|
7723
|
+
}
|
|
7724
|
+
|
|
7725
|
+
.fix-carousel-track {
|
|
7726
|
+
display: flex;
|
|
7727
|
+
transition: transform 0.3s ease;
|
|
7728
|
+
}
|
|
7729
|
+
|
|
7730
|
+
.fix-carousel-slide {
|
|
7731
|
+
min-width: 100%;
|
|
7732
|
+
padding: 0.5rem;
|
|
7733
|
+
}
|
|
7734
|
+
|
|
7735
|
+
/* Slide Header */
|
|
7736
|
+
.fix-slide-header {
|
|
7737
|
+
display: flex;
|
|
7738
|
+
justify-content: space-between;
|
|
7739
|
+
align-items: center;
|
|
7740
|
+
margin-bottom: 0.75rem;
|
|
7741
|
+
}
|
|
7742
|
+
|
|
7743
|
+
.fix-phase-badge {
|
|
7744
|
+
display: inline-flex;
|
|
7745
|
+
align-items: center;
|
|
7746
|
+
gap: 0.25rem;
|
|
7747
|
+
padding: 0.25rem 0.75rem;
|
|
7748
|
+
border-radius: 9999px;
|
|
7749
|
+
font-size: 0.7rem;
|
|
7750
|
+
font-weight: 600;
|
|
7751
|
+
text-transform: uppercase;
|
|
7752
|
+
}
|
|
7753
|
+
|
|
7754
|
+
.fix-phase-badge.phase-planning {
|
|
7755
|
+
background: hsl(270 60% 90%);
|
|
7756
|
+
color: hsl(270 60% 40%);
|
|
7757
|
+
}
|
|
7758
|
+
|
|
7759
|
+
.fix-phase-badge.phase-execution {
|
|
7760
|
+
background: hsl(220 80% 90%);
|
|
7761
|
+
color: hsl(220 80% 40%);
|
|
7762
|
+
animation: pulse-badge 2s infinite;
|
|
7763
|
+
}
|
|
7764
|
+
|
|
7765
|
+
.fix-phase-badge.phase-completion {
|
|
7766
|
+
background: hsl(var(--success-light));
|
|
7767
|
+
color: hsl(var(--success));
|
|
7768
|
+
}
|
|
7769
|
+
|
|
7770
|
+
@keyframes pulse-badge {
|
|
7771
|
+
0%, 100% { opacity: 1; }
|
|
7772
|
+
50% { opacity: 0.7; }
|
|
7773
|
+
}
|
|
7774
|
+
|
|
7775
|
+
.fix-session-id {
|
|
7776
|
+
font-size: 0.7rem;
|
|
7777
|
+
color: hsl(var(--muted-foreground));
|
|
7778
|
+
font-family: var(--font-mono);
|
|
7779
|
+
}
|
|
7780
|
+
|
|
7781
|
+
/* Progress Bar Mini */
|
|
7782
|
+
.fix-progress-bar-mini {
|
|
7783
|
+
height: 6px;
|
|
7784
|
+
background: hsl(var(--muted));
|
|
7785
|
+
border-radius: 3px;
|
|
7786
|
+
overflow: hidden;
|
|
7787
|
+
margin-bottom: 0.5rem;
|
|
7788
|
+
}
|
|
7789
|
+
|
|
7790
|
+
.fix-progress-fill {
|
|
7791
|
+
height: 100%;
|
|
7792
|
+
background: linear-gradient(90deg, hsl(var(--primary)), hsl(var(--success)));
|
|
7793
|
+
border-radius: 3px;
|
|
7794
|
+
transition: width 0.3s ease;
|
|
7795
|
+
}
|
|
7796
|
+
|
|
7797
|
+
.fix-progress-text {
|
|
7798
|
+
font-size: 0.75rem;
|
|
7799
|
+
color: hsl(var(--muted-foreground));
|
|
7800
|
+
text-align: center;
|
|
7801
|
+
}
|
|
7802
|
+
|
|
7803
|
+
/* Stats Row (Slide 2) */
|
|
7804
|
+
.fix-stats-row {
|
|
7805
|
+
display: flex;
|
|
7806
|
+
justify-content: space-around;
|
|
7807
|
+
padding: 0.5rem 0;
|
|
7808
|
+
}
|
|
7809
|
+
|
|
7810
|
+
.fix-stat {
|
|
7811
|
+
text-align: center;
|
|
7812
|
+
}
|
|
7813
|
+
|
|
7814
|
+
.fix-stat-value {
|
|
7815
|
+
display: block;
|
|
7816
|
+
font-size: 1.25rem;
|
|
7817
|
+
font-weight: 700;
|
|
7818
|
+
color: hsl(var(--foreground));
|
|
7819
|
+
}
|
|
7820
|
+
|
|
7821
|
+
.fix-stat-label {
|
|
7822
|
+
display: block;
|
|
7823
|
+
font-size: 0.65rem;
|
|
7824
|
+
color: hsl(var(--muted-foreground));
|
|
7825
|
+
text-transform: uppercase;
|
|
7826
|
+
}
|
|
7827
|
+
|
|
7828
|
+
.fix-stat.fixed .fix-stat-value {
|
|
7829
|
+
color: hsl(var(--success));
|
|
7830
|
+
}
|
|
7831
|
+
|
|
7832
|
+
.fix-stat.failed .fix-stat-value {
|
|
7833
|
+
color: hsl(var(--destructive));
|
|
7834
|
+
}
|
|
7835
|
+
|
|
7836
|
+
.fix-stat.pending .fix-stat-value {
|
|
7837
|
+
color: hsl(var(--warning));
|
|
7838
|
+
}
|
|
7839
|
+
|
|
7840
|
+
/* Active Agents (Slide 3) */
|
|
7841
|
+
.fix-agents-header {
|
|
7842
|
+
font-size: 0.8rem;
|
|
7843
|
+
font-weight: 600;
|
|
7844
|
+
color: hsl(var(--foreground));
|
|
7845
|
+
margin-bottom: 0.5rem;
|
|
7846
|
+
}
|
|
7847
|
+
|
|
7848
|
+
.fix-agent-item {
|
|
7849
|
+
display: flex;
|
|
7850
|
+
align-items: center;
|
|
7851
|
+
gap: 0.5rem;
|
|
7852
|
+
padding: 0.375rem 0.5rem;
|
|
7853
|
+
background: hsl(var(--muted));
|
|
7854
|
+
border-radius: 0.25rem;
|
|
7855
|
+
margin-bottom: 0.375rem;
|
|
7856
|
+
}
|
|
7857
|
+
|
|
7858
|
+
.fix-agent-item:last-child {
|
|
7859
|
+
margin-bottom: 0;
|
|
7860
|
+
}
|
|
7861
|
+
|
|
7862
|
+
.fix-agent-icon {
|
|
7863
|
+
font-size: 0.875rem;
|
|
7864
|
+
animation: spin-agent 2s linear infinite;
|
|
7865
|
+
}
|
|
7866
|
+
|
|
7867
|
+
@keyframes spin-agent {
|
|
7868
|
+
0% { transform: rotate(0deg); }
|
|
7869
|
+
100% { transform: rotate(360deg); }
|
|
7870
|
+
}
|
|
7871
|
+
|
|
7872
|
+
.fix-agent-info {
|
|
7873
|
+
font-size: 0.75rem;
|
|
7874
|
+
color: hsl(var(--foreground));
|
|
7875
|
+
white-space: nowrap;
|
|
7876
|
+
overflow: hidden;
|
|
7877
|
+
text-overflow: ellipsis;
|
|
7878
|
+
}
|
|
7879
|
+
|
|
7880
|
+
/* Carousel Navigation */
|
|
7881
|
+
.fix-carousel-nav {
|
|
7882
|
+
display: flex;
|
|
7883
|
+
justify-content: center;
|
|
7884
|
+
align-items: center;
|
|
7885
|
+
gap: 0.75rem;
|
|
7886
|
+
}
|
|
7887
|
+
|
|
7888
|
+
.fix-nav-btn {
|
|
7889
|
+
width: 24px;
|
|
7890
|
+
height: 24px;
|
|
7891
|
+
border: none;
|
|
7892
|
+
background: hsl(var(--muted));
|
|
7893
|
+
color: hsl(var(--muted-foreground));
|
|
7894
|
+
border-radius: 50%;
|
|
7895
|
+
cursor: pointer;
|
|
7896
|
+
font-size: 1rem;
|
|
7897
|
+
font-weight: bold;
|
|
7898
|
+
display: flex;
|
|
7899
|
+
align-items: center;
|
|
7900
|
+
justify-content: center;
|
|
7901
|
+
transition: all 0.15s;
|
|
7902
|
+
}
|
|
7903
|
+
|
|
7904
|
+
.fix-nav-btn:hover {
|
|
7905
|
+
background: hsl(var(--hover));
|
|
7906
|
+
color: hsl(var(--foreground));
|
|
7907
|
+
}
|
|
7908
|
+
|
|
7909
|
+
.fix-nav-dots {
|
|
7910
|
+
display: flex;
|
|
7911
|
+
gap: 0.375rem;
|
|
7912
|
+
}
|
|
7913
|
+
|
|
7914
|
+
.fix-nav-dot {
|
|
7915
|
+
width: 6px;
|
|
7916
|
+
height: 6px;
|
|
7917
|
+
border-radius: 50%;
|
|
7918
|
+
background: hsl(var(--muted));
|
|
7919
|
+
cursor: pointer;
|
|
7920
|
+
transition: all 0.2s;
|
|
7921
|
+
}
|
|
7922
|
+
|
|
7923
|
+
.fix-nav-dot:hover {
|
|
7924
|
+
background: hsl(var(--muted-foreground));
|
|
7925
|
+
}
|
|
7926
|
+
|
|
7927
|
+
.fix-nav-dot.active {
|
|
7928
|
+
background: hsl(var(--primary));
|
|
7929
|
+
width: 16px;
|
|
7930
|
+
border-radius: 3px;
|
|
7931
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-workflow",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
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",
|
|
@@ -28,19 +28,20 @@
|
|
|
28
28
|
"node": ">=16.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"
|
|
32
|
-
"open": "^9.1.0",
|
|
31
|
+
"boxen": "^7.1.0",
|
|
33
32
|
"chalk": "^5.3.0",
|
|
33
|
+
"commander": "^11.0.0",
|
|
34
|
+
"figlet": "^1.7.0",
|
|
34
35
|
"glob": "^10.3.0",
|
|
36
|
+
"gradient-string": "^2.0.2",
|
|
35
37
|
"inquirer": "^9.2.0",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"boxen": "^7.1.0",
|
|
39
|
-
"gradient-string": "^2.0.2"
|
|
38
|
+
"open": "^9.1.0",
|
|
39
|
+
"ora": "^7.0.0"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"ccw/bin/",
|
|
43
43
|
"ccw/src/",
|
|
44
|
+
"ccw/package.json",
|
|
44
45
|
".claude/agents/",
|
|
45
46
|
".claude/commands/",
|
|
46
47
|
".claude/output-styles/",
|