feat(bd-396): Integrate DependencyDag component into web dashboard
- Import and render DependencyDag component in App.tsx - Add showDependencyDag state toggle - Add DAG button in header with 🔗 icon - Add CSS styles for dag-toggle button - All 390 tests pass including 14 DependencyDag tests 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2456b6262e
commit
7f813ae99d
4 changed files with 113 additions and 1 deletions
|
|
@ -7,7 +7,7 @@
|
|||
{"id":"bd-1c6","title":"TEST-002: Add store integration tests","description":"Test Coverage: Add integration tests for EventStore - event indexing, LRU eviction, worker tracking, query performance.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-03-03T07:53:40.409846186Z","created_by":"coder","updated_at":"2026-03-03T07:53:40.409846186Z","closed_at":"2026-03-03T07:53:40.409846186Z","source_repo":".","compaction_level":0,"original_size":0,"labels":["store","testing"]}
|
||||
{"id":"bd-1cc","title":"Port FileHeatmap component to web dashboard","description":"Port the TUI FileHeatmap component (src/tui/components/FileHeatmap.ts) to React for the web dashboard. Add corresponding API endpoint if needed.","status":"closed","priority":3,"issue_type":"task","assignee":"coder","created_at":"2026-03-03T14:27:43.759301428Z","created_by":"coder","updated_at":"2026-03-03T15:08:13.822190937Z","closed_at":"2026-03-03T15:08:13.792085291Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"labels":["frontend","phase-4","web"]}
|
||||
{"id":"bd-1e1","title":"P3-001: Setup Express HTTP server with static file serving","description":"Phase 3 Web Dashboard: Create Express server in src/web/server.ts that serves static files and handles WebSocket upgrade. Foundation for web dashboard.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-03T07:52:09.228852666Z","created_by":"coder","updated_at":"2026-03-03T10:05:21.171663977Z","closed_at":"2026-03-03T10:05:21.171457522Z","source_repo":".","compaction_level":0,"original_size":0,"labels":["phase-3","server","web"]}
|
||||
{"id":"bd-1fe","title":"Add RecoveryPanel component to web frontend","description":"Port TUI RecoveryPanel.ts to React web frontend. Create src/web/frontend/src/components/RecoveryPanel.tsx showing recovery suggestions for stuck workers.","status":"open","priority":2,"issue_type":"task","created_at":"2026-03-03T14:26:22.464306236Z","created_by":"coder","updated_at":"2026-03-03T14:26:22.464306236Z","source_repo":".","compaction_level":0,"original_size":0,"labels":["frontend","phase-3","web"]}
|
||||
{"id":"bd-1fe","title":"Add RecoveryPanel component to web frontend","description":"Port TUI RecoveryPanel.ts to React web frontend. Create src/web/frontend/src/components/RecoveryPanel.tsx showing recovery suggestions for stuck workers.","status":"in_progress","priority":2,"issue_type":"task","assignee":"coder","created_at":"2026-03-03T14:26:22.464306236Z","created_by":"coder","updated_at":"2026-03-03T15:24:21.626219525Z","source_repo":".","compaction_level":0,"original_size":0,"labels":["frontend","phase-3","web"]}
|
||||
{"id":"bd-1fk","title":"P1: Add Express HTTP server for web dashboard","description":"Set up Express.js HTTP server with basic routing for web dashboard. Should serve static files and provide API endpoints for worker data. Part of Phase 3 Web Dashboard.","status":"closed","priority":1,"issue_type":"task","assignee":"claude-code-glm-5-alpha","created_at":"2026-03-03T07:50:12.280655428Z","created_by":"coder","updated_at":"2026-03-03T09:37:50.271173474Z","closed_at":"2026-03-03T08:51:00.693337164Z","source_repo":".","compaction_level":0,"original_size":0,"labels":["http","phase-3","server","web"],"comments":[{"id":10,"issue_id":"bd-1fk","author":"Jed Arden","text":"Express server implemented in src/web/server.ts","created_at":"2026-03-03T08:52:43Z"}]}
|
||||
{"id":"bd-1fm","title":"ALERT: Worker claude-code-glm-5-alpha has no work available","description":"# Worker Starvation Alert\n\nWorker **claude-code-glm-5-alpha** has exhausted all priorities and found zero work.\n\nThis is considered an error state - there should always be more work.\n\n## Worker State\n\n- **Executor:** claude-code-glm-5\n- **Model:** glm-5\n- **Workspace:** /home/coder/FABRIC\n- **Root Boundary:** /home/coder/FABRIC\n- **Last completion:** \n- **Beads completed:** 0\n- **Claim success rate:** %\n- **Uptime:** 31401s (h)\n- **Consecutive empty iterations:** 5\n\n## Priorities Exhausted\n\n1. ✗ Local workspace (bottoms-up): No beads in /home/coder/FABRIC or subfolders\n2. ✗ Parent exploration: No suitable workspaces found\n3. ✓ Maintenance: Completed (cleaned orphaned claims/locks)\n4. ✗ Gap analysis: false - No gaps found or created\n5. ✗ HUMAN alternatives: true - No HUMAN beads found to unblock\n\n## Discovered Workspaces\n\nTotal: 1\n\n- /home/coder/FABRIC\n\n## Required Actions\n\n1. Review discovery roots: Are all project folders being scanned?\n2. Check if projects need new features/tasks\n3. Review ROADMAP.md files across projects\n4. Enable gap analysis if disabled: `--enable-gap-analysis`\n5. Enable HUMAN alternatives if disabled\n6. Create manual beads to bootstrap work\n\n---\n*This alert was created automatically by Priority 6*","status":"closed","priority":0,"issue_type":"human","assignee":"coder","created_at":"2026-03-03T13:06:51.751924505Z","created_by":"coder","updated_at":"2026-03-03T13:08:06.993513587Z","closed_at":"2026-03-03T13:08:06.982302024Z","close_reason":"False positive worker starvation alert. Ready queue has 22 beads available. Worker discovery should check .beads/ready-queue.json before creating starvation alerts.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1fz","title":"Add React Testing Library tests for WorkerGrid component","description":"Add unit tests for src/web/frontend/src/components/WorkerGrid.tsx using React Testing Library and Vitest","status":"closed","priority":2,"issue_type":"task","assignee":"coder","created_at":"2026-03-03T14:27:27.809285552Z","created_by":"coder","updated_at":"2026-03-03T15:00:31.604214765Z","closed_at":"2026-03-03T15:00:31.576519565Z","close_reason":"completed","source_repo":".","compaction_level":0,"original_size":0,"labels":["frontend","phase-3","testing","web"]}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import ActivityStream from './components/ActivityStream';
|
|||
import WorkerDetail from './components/WorkerDetail';
|
||||
import CollisionAlert from './components/CollisionAlert';
|
||||
import FileHeatmap from './components/FileHeatmap';
|
||||
import DependencyDag from './components/DependencyDag';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [workers, setWorkers] = useState<WorkerInfo[]>([]);
|
||||
|
|
@ -14,6 +15,7 @@ const App: React.FC = () => {
|
|||
const [collisionAlerts, setCollisionAlerts] = useState<CollisionAlertData[]>([]);
|
||||
const [showCollisionPanel, setShowCollisionPanel] = useState(false);
|
||||
const [showFileHeatmap, setShowFileHeatmap] = useState(false);
|
||||
const [showDependencyDag, setShowDependencyDag] = useState(false);
|
||||
|
||||
const handleWebSocketMessage = useCallback((message: WebSocketMessage) => {
|
||||
if (message.type === 'init') {
|
||||
|
|
@ -118,6 +120,14 @@ const App: React.FC = () => {
|
|||
<header className="header">
|
||||
<h1>FABRIC</h1>
|
||||
<div className="header-actions">
|
||||
<button
|
||||
className="dag-toggle"
|
||||
onClick={() => setShowDependencyDag(!showDependencyDag)}
|
||||
title="View task dependency graph"
|
||||
>
|
||||
<span className="dag-toggle-icon">🔗</span>
|
||||
<span className="dag-toggle-label">DAG</span>
|
||||
</button>
|
||||
<button
|
||||
className="file-heatmap-toggle"
|
||||
onClick={() => setShowFileHeatmap(!showFileHeatmap)}
|
||||
|
|
@ -179,6 +189,13 @@ const App: React.FC = () => {
|
|||
onClose={() => setShowFileHeatmap(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showDependencyDag && (
|
||||
<DependencyDag
|
||||
visible={showDependencyDag}
|
||||
onClose={() => setShowDependencyDag(false)}
|
||||
/>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,32 @@ body {
|
|||
gap: 1rem;
|
||||
}
|
||||
|
||||
.dag-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
background: rgba(33, 150, 243, 0.2);
|
||||
border: 1px solid var(--info);
|
||||
color: var(--info);
|
||||
padding: 0.375rem 0.625rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.dag-toggle:hover {
|
||||
background: rgba(33, 150, 243, 0.3);
|
||||
}
|
||||
|
||||
.dag-toggle-icon {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.dag-toggle-label {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.collision-alert-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -237,3 +237,72 @@ export interface DagOptions {
|
|||
}
|
||||
|
||||
export type DagViewMode = 'tree' | 'blockers' | 'ready' | 'stats';
|
||||
|
||||
// ============================================
|
||||
// Recovery Playbook Types
|
||||
// ============================================
|
||||
|
||||
export type ErrorCategory =
|
||||
| 'network'
|
||||
| 'permission'
|
||||
| 'validation'
|
||||
| 'resource'
|
||||
| 'not_found'
|
||||
| 'timeout'
|
||||
| 'syntax'
|
||||
| 'tool'
|
||||
| 'unknown';
|
||||
|
||||
export type RecoveryPriority = 'immediate' | 'high' | 'normal' | 'low';
|
||||
|
||||
export type RecoveryActionType =
|
||||
| 'retry'
|
||||
| 'backoff'
|
||||
| 'alternative'
|
||||
| 'escalate'
|
||||
| 'skip'
|
||||
| 'fix_config'
|
||||
| 'install_dep'
|
||||
| 'fix_permissions'
|
||||
| 'cleanup'
|
||||
| 'restart'
|
||||
| 'investigate';
|
||||
|
||||
export interface RecoveryAction {
|
||||
id: string;
|
||||
type: RecoveryActionType;
|
||||
title: string;
|
||||
description: string;
|
||||
priority: RecoveryPriority;
|
||||
automated: boolean;
|
||||
command?: string;
|
||||
expectedOutcome?: string;
|
||||
prerequisites?: string[];
|
||||
riskLevel?: 'safe' | 'moderate' | 'risky';
|
||||
estimatedTime?: number;
|
||||
}
|
||||
|
||||
export interface RecoverySuggestion {
|
||||
id: string;
|
||||
errorGroupId: string;
|
||||
playbookId?: string;
|
||||
category: ErrorCategory;
|
||||
title: string;
|
||||
errorSummary: string;
|
||||
actions: RecoveryAction[];
|
||||
generatedAt: number;
|
||||
confidence: number;
|
||||
affectedWorkers: string[];
|
||||
relatedErrors?: string[];
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
export interface RecoveryStats {
|
||||
totalSuggestions: number;
|
||||
activeSuggestions: number;
|
||||
byCategory: Record<ErrorCategory, number>;
|
||||
automatedActions: number;
|
||||
manualActions: number;
|
||||
avgConfidence: number;
|
||||
topActionTypes: Array<{ type: RecoveryActionType; count: number }>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue