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:
jeda 2026-03-03 15:26:44 +00:00
parent 2456b6262e
commit 7f813ae99d
4 changed files with 113 additions and 1 deletions

View file

@ -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"]}

View file

@ -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>
);

View file

@ -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;

View file

@ -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 }>;
}