diff --git a/.claude/commands/workflow/execute.md b/.claude/commands/workflow/execute.md index 6844876a..f64b94cc 100644 --- a/.claude/commands/workflow/execute.md +++ b/.claude/commands/workflow/execute.md @@ -67,7 +67,9 @@ Phase 4: Execution Strategy & Task Execution ├─ Get next in_progress task from TodoWrite ├─ Lazy load task JSON ├─ Launch agent with task context - ├─ Mark task completed + ├─ Mark task completed (update IMPL-*.json status) + │ # Quick fix: Update task status for ccw dashboard + │ # TS=$(date -Iseconds) && jq --arg ts "$TS" '.status="completed" | .status_history=(.status_history // [])+[{"from":"in_progress","to":"completed","changed_at":$ts}]' IMPL-X.json > tmp.json && mv tmp.json IMPL-X.json └─ Advance to next task Phase 5: Completion diff --git a/ccw/src/core/lite-scanner.js b/ccw/src/core/lite-scanner.js index 6eeca0c8..a1bf4b28 100644 --- a/ccw/src/core/lite-scanner.js +++ b/ccw/src/core/lite-scanner.js @@ -39,6 +39,11 @@ function scanLiteDir(dir, type) { tasks: loadTaskJsons(sessionPath) }; + // For lite-fix sessions, also load diagnoses separately + if (type === 'lite-fix') { + session.diagnoses = loadDiagnoses(sessionPath); + } + // Calculate progress session.progress = calculateProgress(session.tasks); @@ -268,7 +273,7 @@ export function getLiteTaskDetail(workflowDir, type, sessionId) { if (!existsSync(dir)) return null; - return { + const detail = { id: sessionId, type, path: dir, @@ -277,6 +282,13 @@ export function getLiteTaskDetail(workflowDir, type, sessionId) { explorations: loadExplorations(dir), clarifications: loadClarifications(dir) }; + + // For lite-fix sessions, also load diagnoses + if (type === 'lite-fix') { + detail.diagnoses = loadDiagnoses(dir); + } + + return detail; } /** @@ -312,3 +324,50 @@ function loadClarifications(sessionPath) { return null; } } + +/** + * Load diagnosis files for lite-fix sessions + * Loads diagnosis-*.json files from session root directory + * @param {string} sessionPath - Session directory path + * @returns {Object} - Diagnoses data with manifest and items + */ +function loadDiagnoses(sessionPath) { + const result = { + manifest: null, + items: [] + }; + + // Try to load diagnoses-manifest.json first + const manifestPath = join(sessionPath, 'diagnoses-manifest.json'); + if (existsSync(manifestPath)) { + try { + result.manifest = JSON.parse(readFileSync(manifestPath, 'utf8')); + } catch { + // Continue without manifest + } + } + + // Load all diagnosis-*.json files from session root + try { + const diagnosisFiles = readdirSync(sessionPath) + .filter(f => f.startsWith('diagnosis-') && f.endsWith('.json')); + + for (const file of diagnosisFiles) { + const filePath = join(sessionPath, file); + try { + const content = JSON.parse(readFileSync(filePath, 'utf8')); + result.items.push({ + id: file.replace('diagnosis-', '').replace('.json', ''), + filename: file, + ...content + }); + } catch { + // Skip invalid files + } + } + } catch { + // Return empty items if directory read fails + } + + return result; +} diff --git a/ccw/src/templates/dashboard-css/04-lite-tasks.css b/ccw/src/templates/dashboard-css/04-lite-tasks.css index d21d64ed..e378ecb7 100644 --- a/ccw/src/templates/dashboard-css/04-lite-tasks.css +++ b/ccw/src/templates/dashboard-css/04-lite-tasks.css @@ -841,3 +841,331 @@ overflow: hidden; } +/* =================================== + Fix Plan Enhanced Styles + =================================== */ + +.plan-root-cause-text, +.plan-strategy-text, +.plan-requirements-text { + font-size: 0.875rem; + line-height: 1.6; + color: hsl(var(--foreground)); + background: hsl(var(--muted) / 0.3); + padding: 0.75rem; + border-radius: 0.375rem; + border-left: 3px solid hsl(var(--primary)); +} + +.severity-badge, +.risk-badge { + display: inline-block; + padding: 0.125rem 0.5rem; + border-radius: 0.25rem; + font-size: 0.75rem; + font-weight: 500; + text-transform: uppercase; +} + +.severity-badge.critical, +.risk-badge.high { + background: hsl(0 70% 50% / 0.15); + color: hsl(0 70% 45%); +} + +.severity-badge.high, +.risk-badge.medium { + background: hsl(30 90% 50% / 0.15); + color: hsl(30 90% 40%); +} + +.severity-badge.medium { + background: hsl(45 90% 50% / 0.15); + color: hsl(45 80% 35%); +} + +.severity-badge.low, +.risk-badge.low { + background: hsl(142 70% 50% / 0.15); + color: hsl(142 70% 35%); +} + +.fix-tasks-summary { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.fix-task-summary-item { + background: hsl(var(--card)); + border: 1px solid hsl(var(--border)); + border-radius: 0.5rem; + overflow: hidden; +} + +.fix-task-summary-item .collapsible-header { + padding: 0.75rem 1rem; +} + +.task-num { + font-weight: 600; + color: hsl(var(--primary)); + font-size: 0.85rem; +} + +.task-title-brief { + font-size: 0.875rem; + color: hsl(var(--foreground)); + flex: 1; +} + +.task-scope-badge { + padding: 0.125rem 0.5rem; + background: hsl(var(--muted)); + border-radius: 0.25rem; + font-size: 0.7rem; + color: hsl(var(--muted-foreground)); +} + +.task-detail-section { + margin-bottom: 1rem; +} + +.task-detail-section:last-child { + margin-bottom: 0; +} + +.task-detail-section strong { + display: block; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.025em; + color: hsl(var(--muted-foreground)); + margin-bottom: 0.5rem; +} + +.mod-points-list, +.verify-list { + margin: 0; + padding-left: 1rem; + font-size: 0.8rem; +} + +.mod-points-list li, +.verify-list li { + margin-bottom: 0.375rem; + line-height: 1.5; +} + +.mod-points-list code { + font-size: 0.75rem; + padding: 0.125rem 0.375rem; + background: hsl(var(--muted)); + border-radius: 0.25rem; + color: hsl(var(--primary)); +} + +.func-name { + color: hsl(var(--muted-foreground)); + font-size: 0.75rem; +} + +.change-type { + color: hsl(var(--muted-foreground)); + font-size: 0.7rem; + font-style: italic; +} + +/* =================================== + Diagnoses Tab Styles + =================================== */ + +.diagnoses-tab-content { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.diagnoses-section-title { + font-size: 1rem; + font-weight: 600; + color: hsl(var(--foreground)); + margin-bottom: 0.75rem; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.diagnoses-manifest-section { + background: hsl(var(--muted) / 0.3); + border: 1px solid hsl(var(--border)); + border-radius: 0.5rem; + padding: 1rem; +} + +.manifest-meta-grid { + display: flex; + flex-wrap: wrap; + gap: 1rem; +} + +.diagnoses-grid { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.diagnosis-card { + background: hsl(var(--card)); + border: 1px solid hsl(var(--border)); + border-radius: 0.5rem; + overflow: hidden; +} + +.diagnosis-header { + background: hsl(var(--muted) / 0.3); +} + +.diagnosis-id { + font-weight: 600; + color: hsl(var(--foreground)); + flex: 1; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.diag-section { + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 1px solid hsl(var(--border) / 0.5); +} + +.diag-section:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; +} + +.diag-section strong { + display: block; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.025em; + color: hsl(var(--muted-foreground)); + margin-bottom: 0.5rem; +} + +.diag-section p { + margin: 0; + font-size: 0.875rem; + line-height: 1.6; + color: hsl(var(--foreground)); +} + +.issues-list { + margin: 0; + padding-left: 1rem; + font-size: 0.85rem; +} + +.issue-item { + margin-bottom: 0.5rem; + padding: 0.5rem; + background: hsl(var(--muted) / 0.3); + border-radius: 0.25rem; +} + +.issue-title { + font-weight: 500; + color: hsl(var(--foreground)); +} + +.issue-location { + font-size: 0.75rem; + margin-top: 0.25rem; +} + +.issue-location code { + padding: 0.125rem 0.375rem; + background: hsl(var(--muted)); + border-radius: 0.25rem; + color: hsl(var(--primary)); +} + +.contracts-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.contract-item { + padding: 0.75rem; + background: hsl(var(--muted) / 0.3); + border: 1px solid hsl(var(--border)); + border-radius: 0.375rem; +} + +.contract-header { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.25rem; +} + +.contract-endpoint { + font-weight: 500; + color: hsl(var(--foreground)); +} + +.contract-method { + padding: 0.125rem 0.375rem; + background: hsl(var(--primary) / 0.15); + color: hsl(var(--primary)); + border-radius: 0.25rem; + font-size: 0.7rem; + font-weight: 600; +} + +.contract-desc { + font-size: 0.8rem; + color: hsl(var(--muted-foreground)); +} + +.contract-issues { + font-size: 0.75rem; + color: hsl(0 70% 50%); + margin-top: 0.25rem; +} + +.dataflow-details { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.df-item { + font-size: 0.85rem; +} + +.df-label { + font-weight: 500; + color: hsl(var(--muted-foreground)); +} + +.df-transforms { + margin: 0.25rem 0 0 1rem; + padding-left: 0; +} + +.recommendations-list { + margin: 0; + padding-left: 1.25rem; + font-size: 0.85rem; +} + +.recommendations-list li { + margin-bottom: 0.375rem; + line-height: 1.5; +} + diff --git a/ccw/src/templates/dashboard-js/views/lite-tasks.js b/ccw/src/templates/dashboard-js/views/lite-tasks.js index 06cc7764..5e76d0a7 100644 --- a/ccw/src/templates/dashboard-js/views/lite-tasks.js +++ b/ccw/src/templates/dashboard-js/views/lite-tasks.js @@ -136,6 +136,13 @@ function showLiteTaskDetailPage(sessionKey) { Plan + ${session.type === 'lite-fix' ? ` + + ` : ''} + + + + `; +} + +function renderDiagnosisContent(diag) { + let content = []; + + // Summary/Overview + if (diag.summary || diag.overview) { + content.push(` +
+ Summary: +

${escapeHtml(diag.summary || diag.overview)}

+
+ `); + } + + // Root Cause Analysis + if (diag.root_cause || diag.root_cause_analysis) { + content.push(` +
+ Root Cause: +

${escapeHtml(diag.root_cause || diag.root_cause_analysis)}

+
+ `); + } + + // Issues/Findings + if (diag.issues && Array.isArray(diag.issues)) { + content.push(` +
+ Issues Found (${diag.issues.length}): + +
+ `); + } + + // Affected Files + if (diag.affected_files && Array.isArray(diag.affected_files)) { + content.push(` +
+ Affected Files: +
+ ${diag.affected_files.map(f => `${escapeHtml(typeof f === 'string' ? f : f.path || f.file)}`).join('')} +
+
+ `); + } + + // API Contracts (for api-contracts diagnosis) + if (diag.contracts && Array.isArray(diag.contracts)) { + content.push(` +
+ API Contracts (${diag.contracts.length}): +
+ ${diag.contracts.map(contract => ` +
+
+ ${escapeHtml(contract.endpoint || contract.name || 'Unknown')} + ${contract.method ? `${escapeHtml(contract.method)}` : ''} +
+ ${contract.description ? `
${escapeHtml(contract.description)}
` : ''} + ${contract.issues?.length ? `
${contract.issues.length} issue(s)
` : ''} +
+ `).join('')} +
+
+ `); + } + + // Dataflow Analysis (for dataflow diagnosis) + if (diag.dataflow || diag.data_flow) { + const df = diag.dataflow || diag.data_flow; + content.push(` +
+ Data Flow Analysis: + ${typeof df === 'string' ? `

${escapeHtml(df)}

` : ` +
+ ${df.source ? `
Source: ${escapeHtml(df.source)}
` : ''} + ${df.sink ? `
Sink: ${escapeHtml(df.sink)}
` : ''} + ${df.transformations?.length ? ` +
+ Transformations: +
    ${df.transformations.map(t => `
  1. ${escapeHtml(t)}
  2. `).join('')}
+
+ ` : ''} +
+ `} +
+ `); + } + + // Recommendations + if (diag.recommendations && Array.isArray(diag.recommendations)) { + content.push(` +
+ Recommendations: +
    + ${diag.recommendations.map(rec => `
  1. ${escapeHtml(typeof rec === 'string' ? rec : rec.description || rec.action)}
  2. `).join('')} +
+
+ `); + } + + // If no specific content was rendered, show raw JSON preview + if (content.length === 0) { + content.push(` +
+
${escapeHtml(JSON.stringify(diag, null, 2))}
+
+ `); + } + + return content.join(''); +}