Wire shared EventDeduplicator across all ingestion paths (JSONL tailer,
OTLP/gRPC receiver, OTLP/HTTP receiver) so duplicate events from dual
ingestion are silently dropped on (session_id, worker_id, sequence).
Also adds docs/needle-exporter-wiring.md (OTLP configuration guide for
NEEDLE), SpanDag React component, EventFilter.eventType field, and
various test/layout fixes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace coarse NeedleWorkerStatus ('idle'|'executing'|'draining'|'starting')
with the real NEEDLE state machine: BOOTING→SELECTING→CLAIMING→WORKING→CLOSING→STOPPED.
- Add NeedleState type, VALID_TRANSITIONS map, needleStateToStatus() helper in types.ts
- Track needleState + lastStateTransition per worker by consuming worker.state_transition events
- Surface all six states in TUI worker cards (WorkerGrid, WorkerDetail) with per-state icons/colors
- Surface all six states in web WorkerGrid.tsx with NEEDLE_STATE_LABELS and NEEDLE_STATE_COLORS
- Add getNeedleStateColor/getNeedleStateIcon to colors.ts
- Rewire stuck detection to fire on state-transition gaps (state_gap pattern in stuckDetection.ts)
- Add sequence-based event ordering via compareEventsBySequence and queryOrdered()
- Legacy event-type fallback preserved for workers not emitting state_transition events
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
WorkerDetail now renders statuses in uppercase (ACTIVE/IDLE/ERROR) to
match NeedleState labels. Store only recognizes canonical event types
(bead.completed, not "Task completed") for state transitions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The web frontend SessionReplay component was sorting events by
timestamp, inconsistent with all other consumers (store, TUI replay,
export, analytics, narrative) which use compareEventsBySequence.
Switched to the canonical (worker, sequence) ordering so multi-host
OTLP ingestion produces correct replay order despite clock skew.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Mount OTLP/HTTP handlers on the existing Express web server via a second
HTTP listener so OTLP endpoints are reachable at the standard :4318
address without a separate process. Accepts both application/x-protobuf
and application/json content types, routing decoded records through the
same Normalizer pipeline as the gRPC receiver.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add state_gap stuck detection using lastStateTransition — fires when
a worker in an active NeedleState hasn't transitioned within the
configurable threshold (default 5min, critical at 2x).
- Update web WorkerDetail.tsx to display needleState with icons and
colors instead of coarse active/idle/error status.
- Add stuckDetection.test.ts with 16 tests covering gap-based detection,
legacy patterns, and edge cases.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds Budget panel (B key) to TUI with per-bead/per-worker cost tracking,
EMA-smoothed burn rate, time-series storage, and CostDashboard web component.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add types for fleet analytics dashboard:
- DurationBucket for bead completion histograms
- ModelPerformanceMetrics with duration distribution
- StrandMetrics for strand utilization tracking
- CompletionQualityIndicator for shallow completions
- FleetAnalytics aggregating all metrics
- FleetAnalyticsOptions for query configuration
Add CSS styles for analytics dashboard:
- Stats bar with quick metrics
- Tab navigation for Models/Strands/Quality/Fleet views
- Mini bar charts for duration distributions
- Sparkline charts for worker time series
- Quality cards for shallow completion tracking
- Responsive design for mobile/tablet views
Co-Authored-By: Claude Code (glm-5) <noreply@anthropic.com>
- Fixed corrupted auth middleware code in server.ts that was causing build failure
- Verified TUI color rendering works correctly (bd-2b3)
- Resolved bd-jec: Found 8 beads in ready queue, worker starvation was due to assignee filtering
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added authToken option to WebServerOptions interface
- Created createAuthMiddleware function for Bearer token auth
- Applied auth middleware to POST /api/events and /api/events/batch
- Updated CLI to read FABRIC_AUTH_TOKEN env var
- Added comprehensive tests for authentication scenarios
- Updated POST /api/events test cases to use auth token
- All tests passing successfully
- Add MAX_BATCH_SIZE constant (100 events limit)
- Implement POST /api/events/batch endpoint that accepts JSON array of events
- Validate array format, empty batches, and batch size limits
- Validate each event has required fields (ts, event)
- Store all valid events via store.add()
- Broadcast all ingested events via WebSocket
- Return 201 with ingested count, total count, and errors array
- Handle partial success (valid events processed, errors reported)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Add HTTP POST endpoint to receive NEEDLE telemetry events from the
fabric.sh forwarder. This bridges NEEDLE and FABRIC, enabling real-time
event ingestion via HTTP.
Changes:
- Add parseEventObject() to parser.ts for parsing JSON objects directly
- Add POST /api/events endpoint with JSON body parser (64KB limit)
- Validate required fields (ts, event) before processing
- Store events and broadcast to WebSocket clients in real-time
- Return 201 Created on success, 400 for invalid payloads
Acceptance criteria met:
- NEEDLE events sent via curl POST arrive in FABRIC's event store
- Events are broadcast to WebSocket clients in real-time
- Invalid payloads return appropriate error codes (400)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verified and closed bd-2u6 - FileContextPanel is fully implemented for both TUI and Web:
Features:
- Split view: Activity (left) | File Context (right)
- Auto-update when file event selected
- Syntax highlighting based on file extension (TS, JS, Python, Rust, Go, etc.)
- Line numbers with highlight on relevant lines
- Sticky panel - stays visible while scrolling activity
- File history: see all operations on this file
- Quick toggle between recently touched files ([/]/[] keys)
- 'Open in Editor' button (launches configured editor)
TUI Layout:
- Ctrl+F to toggle file context panel
- { and } to resize split view
- Tab to switch focus between panels
Web Layout:
- Collapsible side panel with toggle button
- Resizable divider
- Pop out to separate window
Editor Integration:
- Uses $EDITOR env var
- Supports VS Code, vim, nano, etc.
- Opens at specific line number
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Implements save/load/delete functionality for focus mode pin configurations:
**TUI Changes:**
- [ key to save current focus configuration as named preset
- ] key to cycle through saved presets
- Preset commands in CommandPalette (Ctrl+K):
- preset:save - Save current focus
- preset:list - List all presets
- preset:load:<name> - Load a specific preset
- preset:delete:<name> - Delete a preset
- Presets stored in ~/.fabric/focus-presets.json
- Updated help text with new keybindings
**Web Changes:**
- Preset dropdown in header with save/load/delete UI
- Modal dialog for saving new presets
- Presets stored in localStorage
- Styled with CSS matching existing UI
**Core:**
- FocusPresetManager utility class for preset CRUD operations
- Storage abstraction (Memory, LocalStorage, File-based)
- Full test coverage for preset management
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Add export/import functionality for session replay:
**Export Features:**
- Export as shareable link (base64 encoded events in URL parameter)
- Export as .fabric-replay file (JSON format)
- Share button in replay controls with dropdown menu
**Import Features:**
- Import from .fabric-replay file via file picker
- Import from URL parameter (?replay=base64EncodedEvents)
- Automatic detection and loading of replay data from URL
**Implementation:**
- src/utils/replayExport.ts: Core export/import utilities for Node.js
- src/web/frontend/src/utils/replayExport.ts: Browser-specific utilities
- Updated web SessionReplay.tsx with export dropdown and status messages
- Updated TUI SessionReplay.ts with exportToFile/importFromFile methods
- Added session replay panel to App.tsx with URL parameter support
- Added CSS styles for export dropdown, status messages, and replay panel
**Export Format:**
```json
{
"version": "1.0",
"exportedAt": 1709337600,
"eventCount": 150,
"events": [...],
"metadata": {
"sessionStart": 1709337000,
"sessionEnd": 1709337600,
"workerCount": 3
}
}
```
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add timeline visualization component to the web dashboard:
- Create TimelineView.tsx component showing worker activity over time
- Support time range selection (5m, 10m, 30m, 1h)
- Click on timeline bar to jump to that time in activity stream
- Color-code by worker status (active/idle/error)
- Add timeline toggle button in header
- Integrate with Focus Mode for filtering workers
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Implement robust WebSocket reconnection logic for the web frontend:
- Detect connection loss immediately via onclose handler
- Show 'Reconnecting...' status indicator with yellow dot
- Implement exponential backoff (1s, 2s, 4s, 8s, 16s, max 30s)
- Re-sync state automatically after successful reconnection
- Show reconnection attempt count in brackets
- Manual reconnect button appears after max retries (10)
- Green dot with glow for connected state
- Red dot for disconnected state
- Animated pulse effect on reconnecting indicator
UI States:
- Connected: Green dot with glow
- Reconnecting: Yellow pulsing dot with countdown and attempt count
- Disconnected: Red dot with manual retry button
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Worker <noreply@anthropic.com>
## TUI Theme Support
- Create ThemeManager class with dark/light theme palettes
- Update colors.ts to use theme system via proxy pattern
- Add Ctrl+T keybinding for theme toggle
- Add theme commands to CommandPalette (theme:toggle, theme:dark, theme:light)
- Persist theme preference to ~/.fabric/theme.json
- Update footer to show current theme
## Web Dashboard Theme Support
- Create ThemeContext with React context API
- Add light theme CSS variables (data-theme="light")
- Add ThemeToggle button to header
- Persist theme preference to localStorage
- Support system color scheme preference detection
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Added comprehensive E2E test suite for WorkerDetail component with 39 test cases covering:
- Worker status display (active, idle, error)
- Event count and current tool display
- Last seen timestamp formatting
- Recent events list rendering
- Collision alert display
- Current activity section
- CSS classes and accessibility features
- Edge cases and error handling
All tests passing.
Co-Authored-By: Claude Worker <noreply@anthropic.com>
FileHeatmap component is fully integrated into main TUI app:
- Keyboard shortcut 'H' toggles heatmap view
- Real-time file access aggregation from event store
- Shows most-touched files with multiple sort modes
- All tests passing (943 tests, including 130 FileHeatmap tests)
Additional fixes:
- Fixed ErrorGroupPanel options to support bottom property
- Added vitest globals configuration for proper TypeScript support
- Fixed type assertions in server.test.ts
- Created comprehensive integration documentation
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Implemented comprehensive filtering system for ActivityStream in both TUI and Web:
TUI Changes:
- Extended ActivityFilter interface with time range filters (since/until)
- Created FilterPanel component with all filter controls:
* Worker ID filter
* Log level filter (debug/info/warn/error)
* Search term filter
* Time range filters (since/until)
* Clear all filters button
- Added filter state persistence to file storage (~/.fabric-filter-state.json)
- Added getFilter(), getEventsCount(), getFilteredEventsCount() methods
- Updated ActivityStream tests with time range filtering tests
Web Changes:
- Created FilterControls component with all filter controls
- Implemented complete filtering logic in ActivityStream component
- Added filter state persistence using localStorage
- Added CSS styles for filter controls panel
- Updated ActivityStream to support showFilters prop
- Updated tests to cover filtering functionality
All 465 tests passing.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Integrated CrossReferenceManager with EventStore to enable cross-reference
hyperlinking across events, workers, files, and beads. This allows navigation
between related activities in the FABRIC dashboard.
Changes:
- Integrated CrossReferenceManager into InMemoryEventStore
- Added batch processing for cross-reference relationship detection
- Added 11 new API methods to store for cross-reference queries
- Updated web server to use store's cross-reference methods
- Added comprehensive test coverage (11 new tests)
- All 55 tests passing
Features:
- Automatic link detection between events, workers, files, and beads
- Relationship detection (same_bead, same_file, same_worker, temporal_proximity, etc.)
- Navigation path finding between entities
- Cross-reference statistics and queries
- Web API endpoints for cross-reference data
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Port TUI RecoveryPanel.ts to React web frontend:
- Add RecoverySuggestion, RecoveryAction, and related types to types.ts
- Create RecoveryPanel.tsx component with:
- Recovery suggestions list with expandable actions
- Priority badges and category icons
- Automated/manual action indicators
- Execute and dismiss buttons for actions
- Detail panel for selected suggestion
- Add CSS styles for recovery panel and toggle button
- Integrate RecoveryPanel into App.tsx with toggle button in header
All 442 tests pass.
Co-Authored-By: Claude Worker <noreply@anthropic.com>
- Add comprehensive test suite with 52 test cases covering:
- Constructor and initialization
- Event addition and formatting
- Pause/unpause functionality
- Filtering by worker, level, and search
- Key bindings (p for pause, C-c for clear)
- Edge cases (empty messages, unicode, special chars)
- Position options (string and numeric)
Co-Authored-By: Claude Worker <noreply@anthropic.com>
- 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>
Port TUI FileHeatmap.ts to React web frontend with:
- Full component implementation with heat visualization
- Sort mode cycling (modifications, recent, workers, collisions)
- Collision filtering and directory filtering
- Entry selection with detail panel
- Worker display and modification statistics
- Comprehensive test suite (15 tests)
- API endpoints already integrated in server
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create DependencyDag.tsx with interactive task dependency visualization
- Add DAG types to web frontend types
- Add /api/dag endpoint to server.ts
- Add CSS styles for DAG panel
- Add unit tests
Co-Authored-By: Claude Worker <noreply@anthropic.com>
- Create src/web/frontend/src/components/WorkerDetail.tsx as dedicated component
- Port TUI WorkerDetail functionality to React web frontend
- Features:
- Worker ID and status with status icon
- Activity statistics (event count, current tool)
- Timing information (last seen)
- Recent events list (last 10 events)
- Collision warning with affected files
- Close button to deselect worker
- Update App.tsx to use new WorkerDetail component
- Add comprehensive CSS styles for new component
Co-Authored-By: Claude Worker <noreply@anthropic.com>
Move ReplaySpeed and ReplayState types to central types file for
consistency and re-export them from the component for external use.
Co-Authored-By: Claude Worker <noreply@anthropic.com>
- Add comprehensive tests for /api/health endpoint
- Add tests for /api/workers and /api/workers/:id endpoints
- Add tests for /api/events with filtering (worker, level, limit)
- Add tests for /api/collisions and /api/workers/:id/collisions
- Add tests for cross-reference API endpoints (/api/xref/*)
- Add tests for WebSocket functionality exposure
- Add tests for server lifecycle and error handling
- All 42 new tests pass (225 total tests)
Co-Authored-By: Claude Worker <noreply@anthropic.com>