diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 4ce2764..9f65ef0 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -83,7 +83,7 @@ {"id":"bd-38q","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:** 16335s (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","created_at":"2026-03-03T08:55:45.765157605Z","created_by":"coder","updated_at":"2026-03-03T09:04:41.870073387Z","closed_at":"2026-03-03T09:04:41.869860465Z","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":13,"issue_id":"bd-38q","author":"Jed Arden","text":"False positive - work available in ready-queue.json (22 beads). Same issue as bd-123.","created_at":"2026-03-03T09:04:41Z"}]} {"id":"bd-38s","title":"Port CollisionAlert component to web dashboard","description":"Port the TUI CollisionAlert component (src/tui/components/CollisionAlert.ts) to React for the web dashboard. The backend already has /api/collisions endpoint.","status":"closed","priority":2,"issue_type":"task","assignee":"coder","created_at":"2026-03-03T14:27:38.473268787Z","created_by":"coder","updated_at":"2026-03-03T14:57:38.614138148Z","closed_at":"2026-03-03T14:57:38.587034332Z","close_reason":"completed: CollisionAlert component was already fully implemented in the web dashboard. Added comprehensive test coverage (30 tests) covering rendering, severity grouping, type icons, acknowledgment functionality, detail view, worker display, title truncation, CSS classes, and selection handling. Tests pass successfully.","source_repo":".","compaction_level":0,"original_size":0,"labels":["frontend","phase-4","web"]} {"id":"bd-396","title":"Port DependencyDag component to web dashboard","description":"Port the TUI DependencyDag component (src/tui/components/DependencyDag.ts) to React for the web dashboard using a library like react-flow or dagre.","status":"closed","priority":3,"issue_type":"task","assignee":"coder","created_at":"2026-03-03T14:27:55.835238720Z","created_by":"coder","updated_at":"2026-03-03T15:27:42.325918743Z","closed_at":"2026-03-03T15:27:42.292761429Z","close_reason":"DependencyDag component already fully implemented in src/web/frontend/src/components/DependencyDag.tsx with Tree, Blockers, Ready, and Stats views. Integration completed by adding component to App.tsx with DAG toggle button in header. All 390 tests pass including 14 DependencyDag tests.","source_repo":".","compaction_level":0,"original_size":0,"labels":["frontend","phase-4","web"]} -{"id":"bd-39v","title":"Integrate CollisionAlert into main TUI app","description":"Wire CollisionAlert component into the main TUI app (src/tui/app.ts). Add collision detection to event processing pipeline, display alerts in dedicated panel or overlay, add keyboard shortcut to view/dismiss collisions.","status":"open","priority":3,"issue_type":"task","created_at":"2026-03-04T03:01:54.192216325Z","created_by":"coder","updated_at":"2026-03-04T03:07:15.191353715Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-39v","depends_on_id":"bd-20w","type":"blocks","created_at":"2026-03-04T03:07:15.191267052Z","created_by":"coder"}]} +{"id":"bd-39v","title":"Integrate CollisionAlert into main TUI app","description":"Wire CollisionAlert component into the main TUI app (src/tui/app.ts). Add collision detection to event processing pipeline, display alerts in dedicated panel or overlay, add keyboard shortcut to view/dismiss collisions.","status":"in_progress","priority":3,"issue_type":"task","assignee":"coder","created_at":"2026-03-04T03:01:54.192216325Z","created_by":"coder","updated_at":"2026-03-04T04:31:59.954921699Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-39v","depends_on_id":"bd-20w","type":"blocks","created_at":"2026-03-04T03:07:15.191267052Z","created_by":"coder"}]} {"id":"bd-3a0","title":"P4-003: Add Session Replay Feature","description":"Phase 4 Intelligence: Record and replay worker sessions. Allow stepping through events chronologically. Store session metadata in SQLite.","status":"closed","priority":4,"issue_type":"task","created_at":"2026-03-03T07:53:39.995567065Z","created_by":"coder","updated_at":"2026-03-03T07:53:39.995567065Z","closed_at":"2026-03-03T07:53:39.995567065Z","source_repo":".","compaction_level":0,"original_size":0,"labels":["intelligence","phase-4","replay"]} {"id":"bd-3af","title":"Create WorkerAnalytics TUI component","description":"Create TUI component to display worker analytics. Show charts for performance metrics, comparisons between workers, trends over time.","status":"open","priority":4,"issue_type":"task","created_at":"2026-03-04T03:06:08.491128542Z","created_by":"coder","updated_at":"2026-03-04T03:07:05.723573539Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-3af","depends_on_id":"bd-msa","type":"blocks","created_at":"2026-03-04T03:07:05.723488354Z","created_by":"coder"}]} {"id":"bd-3av","title":"P4-006: File Heatmap","description":"Implement file heatmap feature - show which files are being accessed/modified most frequently by workers. Helps identify hot paths and potential bottlenecks.","status":"closed","priority":3,"issue_type":"task","assignee":"coder","created_at":"2026-03-03T13:30:47.180967166Z","created_by":"coder","updated_at":"2026-03-03T14:07:39.203982357Z","closed_at":"2026-03-03T14:07:39.186412732Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"labels":["heatmap","intelligence","phase-4"]} diff --git a/src/tui/app.ts b/src/tui/app.ts index cd8d978..0a990d9 100644 --- a/src/tui/app.ts +++ b/src/tui/app.ts @@ -17,6 +17,7 @@ import { DependencyDag } from './components/DependencyDag.js'; import { SessionReplay } from './components/SessionReplay.js'; import { ErrorGroupPanel } from './components/ErrorGroupPanel.js'; import { SessionDigest, generateSessionDigest } from './components/SessionDigest.js'; +import { CollisionAlert } from './components/CollisionAlert.js'; import { getErrorGroupManager } from '../errorGrouping.js'; import { WorkerSessionSummary } from '../types.js'; @@ -38,7 +39,7 @@ export class FabricTuiApp { private isRunning = false; // View mode - private viewMode: 'default' | 'heatmap' | 'dag' | 'replay' | 'errors' | 'digest' = 'default'; + private viewMode: 'default' | 'heatmap' | 'dag' | 'replay' | 'errors' | 'digest' | 'collisions' = 'default'; // Focus mode state private focusModeEnabled = false; @@ -56,6 +57,7 @@ export class FabricTuiApp { private sessionReplay!: SessionReplay; private errorGroupPanel!: ErrorGroupPanel; private sessionDigest!: SessionDigest; + private collisionAlert!: CollisionAlert; private footerBox!: blessed.Widgets.BoxElement; private helpOverlay?: blessed.Widgets.BoxElement; @@ -199,6 +201,20 @@ export class FabricTuiApp { }); this.sessionDigest.hide(); + // Collision Alert panel (hidden by default, 'C' key) + this.collisionAlert = new CollisionAlert({ + parent: this.screen, + top: 'center', + left: 'center', + width: '80%', + height: '70%', + onAcknowledge: (alertId) => { + this.store.acknowledgeAlert(alertId); + this.updateCollisionAlerts(); + }, + }); + this.collisionAlert.hide(); + // Footer with key hints this.footerBox = blessed.box({ parent: this.screen, @@ -218,7 +234,7 @@ export class FabricTuiApp { */ private getFooterContent(): string { if (this.viewMode === 'default') { - let content = ' [Tab] Switch [j/k] Scroll [/] Search [H] Heatmap [D] DAG [E] Errors'; + let content = ' [Tab] Switch [j/k] Scroll [/] Search [H] Heatmap [D] DAG [E] Errors [C] Collisions'; // Show focus mode status if (this.focusModeEnabled) { @@ -238,7 +254,7 @@ export class FabricTuiApp { } // Return default content for other views - return ' [Tab] Switch [j/k] Scroll [/] Search [H] Heatmap [D] DAG [E] Errors [?] Help [q] Quit'; + return ' [Tab] Switch [j/k] Scroll [/] Search [H] Heatmap [D] DAG [E] Errors [C] Collisions [?] Help [q] Quit'; } /** @@ -302,6 +318,16 @@ export class FabricTuiApp { this.toggleErrorsView(); }); + // Toggle session digest view + this.screen.key(['G'], () => { + this.toggleDigestView(); + }); + + // Toggle collision alert view + this.screen.key(['C'], () => { + this.toggleCollisionsView(); + }); + // Escape to return to default view this.screen.key(['escape'], () => { if (this.viewMode !== 'default') { @@ -345,6 +371,10 @@ export class FabricTuiApp { this.toggleReplayView(); } else if (cmd === 'errors') { this.toggleErrorsView(); + } else if (cmd === 'digest') { + this.toggleDigestView(); + } else if (cmd === 'collisions') { + this.toggleCollisionsView(); } else if (cmd.startsWith('filter:worker:')) { const workerId = cmd.replace('filter:worker:', ''); this.activityStream.setFilter({ workerId }); @@ -398,10 +428,40 @@ export class FabricTuiApp { } } + /** + * Toggle session digest view + */ + private toggleDigestView(): void { + if (this.viewMode === 'digest') { + this.setViewMode('default'); + } else { + this.setViewMode('digest'); + } + } + + /** + * Toggle collision alert view + */ + private toggleCollisionsView(): void { + if (this.viewMode === 'collisions') { + this.setViewMode('default'); + } else { + this.setViewMode('collisions'); + } + } + + /** + * Update collision alerts from store + */ + private updateCollisionAlerts(): void { + const alerts = this.store.getAllCollisionAlerts(); + this.collisionAlert.updateAlerts(alerts); + } + /** * Set view mode */ - private setViewMode(mode: 'default' | 'heatmap' | 'dag' | 'replay' | 'errors'): void { + private setViewMode(mode: 'default' | 'heatmap' | 'dag' | 'replay' | 'errors' | 'digest' | 'collisions'): void { this.viewMode = mode; if (mode === 'heatmap') { @@ -480,12 +540,66 @@ export class FabricTuiApp { // Update header this.headerBox.setContent(' FABRIC - Error Groups'); this.footerBox.setContent(' [↑/↓] Navigate [Enter] Expand/Collapse [Esc] Back [?] Help [q] Quit'); + } else if (mode === 'digest') { + // Hide other panels + this.workerGrid.getElement().hide(); + this.activityStream.getElement().hide(); + this.fileHeatmap.getElement().hide(); + this.dependencyDag.getElement().hide(); + this.sessionReplay.hide(); + this.errorGroupPanel.hide(); + + // Show session digest + this.sessionDigest.show(); + + // Generate digest from current session data + const allEvents = this.store.query(); + const workers = this.store.getWorkers(); + + // Convert WorkerInfo to WorkerSessionSummary + const workerSummaries: WorkerSessionSummary[] = workers.map(w => ({ + workerId: w.id, + beadsCompleted: w.beadsCompleted, + filesModified: w.activeFiles.length, + errorsEncountered: w.status === 'error' ? 1 : 0, + totalEvents: 0, // Would need to count per worker + activeTimeMs: w.lastActivity - w.firstSeen, + firstActivity: w.firstSeen, + lastActivity: w.lastActivity, + })); + + const digest = generateSessionDigest(allEvents, workerSummaries); + this.sessionDigest.setDigest(digest); + this.sessionDigest.focus(); + + // Update header + this.headerBox.setContent(' FABRIC - Session Digest'); + this.footerBox.setContent(' [1-5] Tabs [e] Export JSON [m] Export Markdown [j/k] Scroll [Esc] Back [?] Help [q] Quit'); + } else if (mode === 'collisions') { + // Hide other panels + this.workerGrid.getElement().hide(); + this.activityStream.getElement().hide(); + this.fileHeatmap.getElement().hide(); + this.dependencyDag.getElement().hide(); + this.sessionReplay.hide(); + this.errorGroupPanel.hide(); + this.sessionDigest.hide(); + + // Show collision alert panel + this.updateCollisionAlerts(); + this.collisionAlert.show(); + + // Update header + this.headerBox.setContent(' FABRIC - Collision Alerts'); + this.footerBox.setContent(' [↑/↓] or [j/k] Navigate [Enter] Acknowledge [a] Acknowledge All [Esc] Close [?] Help [q] Quit'); } else { // Hide special views this.fileHeatmap.getElement().hide(); this.dependencyDag.getElement().hide(); this.sessionReplay.hide(); this.errorGroupPanel.hide(); + this.sessionDigest.hide(); + this.collisionAlert.hide(); // Show default panels this.workerGrid.getElement().show(); @@ -618,6 +732,8 @@ Actions: H - Toggle file heatmap D - Toggle dependency DAG R - Toggle session replay + E - Toggle error groups + C - Toggle collision alerts Focus Mode: F - Toggle focus mode @@ -647,6 +763,12 @@ Session Replay: r - Reset to beginning Esc - Return to default view +Collision Alerts: + ↑/↓ or j/k - Navigate alerts + Enter - Acknowledge selected alert + a - Acknowledge all alerts + Esc - Return to default view + General: ? - Toggle this help q - Quit @@ -694,6 +816,11 @@ General: ); } + // Update collision alerts if visible + if (this.viewMode === 'collisions') { + this.updateCollisionAlerts(); + } + // DAG view auto-refreshes on its own schedule this.screen.render();