- Add SystemMemoryIndicator component showing sparkline and usage in fleet header
- Refactor systemCgroupMonitor.ts for cleaner implementation
- Update index.css with fleet-header layout styles
- Add fleet-header with separator between FleetSummaryBar and SystemMemoryIndicator
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add SystemMemoryPanel rendering in App.tsx main content area
- Add 'show:memory' command palette action for opening memory panel
- Fix import of SystemMemoryPanel (named export)
- Backend features already in place: /api/system/memory, /api/system/memory/history, OOM tracking, 5-min sparkline
This completes the integration of the system cgroup memory panel that shows:
- Current cgroup memory usage vs MemoryHigh (color-coded progress bar)
- 5-minute sparkline of memory usage sampled every 10s
- oom_kill counter from /sys/fs/cgroup/user.slice/memory.events
- Swap usage when enabled
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add MemorySampler that polls active worker PIDs every 10s to sample
/proc/<pid>/status for VmRSS, VmPeak, and VmSwap memory metrics.
Changes:
- Add MemorySampler class with periodic sampling (10s interval)
- Attach rssKb, peakRssKb, swapKb to WorkerState in types.ts
- Integrate with InMemoryEventStore to register PIDs from events
- Expose memory fields on GET /api/workers response
- Broadcast updated memory fields via WebSocket
- Add comprehensive test suite
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements the missing /api/spans/dag endpoint that was blocking the
SpanDag component. The endpoint queries span events from the store and
builds a hierarchical tree structure for visualization.
Changes:
- Added GET /api/spans/dag endpoint in src/web/server.ts
- Added SpanDagResponse interface to src/types.ts for JSON serialization
- Updated SpanNode interface to use nullable fields (null instead of undefined)
- Fixed src/dagUtils.ts to use nullable SpanNode fields
The endpoint accepts an optional trace_id query parameter to filter
spans by trace, and returns a SpanDagResponse with root spans, total
span count, and trace summary.
Closes: bf-82u8
Backend API endpoints (src/web/server.ts):
- GET /api/workers/compare?worker1=&worker2= — returns WorkerComparison via analyticsManager.compareWorkers()
- GET /api/analytics/workers — returns per-worker WorkerMetrics for leaderboard table
- GET /api/analytics/sessions — exposes historicalStore.getSessions() for cross-session comparisons
Frontend component (src/web/frontend/src/components/WorkerAnalyticsPanel.tsx):
- Comparison view mirroring TUI WorkerAnalyticsPanel behavior
- Leaderboard table with sortable columns
- Historical sessions list
- Worker selection for comparison with diff/percent/winner indicators
Wired into App.tsx with new "Workers" button (⚔️ icon) and command palette action (show:worker-analytics)
Closes: bf-4cqq
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Implements Phase 6 Historical session index for comparisons.
Backend (src/web/server.ts):
- GET /api/sessions — list sessions (paginated, with start/end filter)
- GET /api/sessions/:id — get single session detail with per-worker summaries
- GET /api/sessions/:id/workers — get worker summaries for a session
All endpoints use the existing HistoricalStore infrastructure.
Frontend (src/web/frontend/src/components/HistoricalSessionsPanel.tsx):
- Sessions list table with duration, workers, tasks, cost, tokens, time range
- Click-to-expand session detail with worker performance breakdown
- Metrics source badge (otlp-metric, otlp-span, log-derived)
- Empty state with helpful hint when no sessions exist
- Refresh button for manual reload
Integration:
- Added to App.tsx with Sessions toggle button in header
- Command palette action: show:sessions
- Follows existing panel patterns (ProductivityPanel, AnalyticsDashboard)
Closes: bf-5xch
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 9 implementation: Bead workspace scanner and project breakdown.
- Add beadWorkspaceScanner.ts to scan .beads/issues.jsonl files
- Count CLOSED beads per project, deriving project from bead id prefix
- Use close_reason/closed_at/assignee for productivity tracking
- Add configurable workspace list in config.ts (WorkspaceConfig interface)
- Extend GET /api/productivity to add byProject array
- Add By Project section to ProductivityPanel React component
- Add tests for bead workspace scanner
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds GET /api/productivity returning daily bead completion counts (last 30
days) from bead.released/release_success events and a worker leaderboard
sorted by beadsCompleted. Adds a Productivity tab in the web UI with a 14-day
SVG bar chart and a worker leaderboard table.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Integrate the conversationParser module with the InMemoryEventStore and web server
to provide complete conversation transcript functionality.
Store integration:
- Add conversation session caching with 5-second TTL
- Invalidate cache when conversation events are added
- Add methods: getConversationSessions, getWorkerConversationSessions,
getBeadConversationSession, getConversationSession,
getConversationEvents, getWorkerConversationEvents,
getBeadConversationEvents
Web API integration:
- GET /api/conversations/sessions - Get all conversation sessions
- GET /api/conversations/workers/:workerId - Get sessions for worker
- GET /api/conversations/beads/:beadId - Get session for bead
- GET /api/conversations/:sessionId - Get session by ID
- GET /api/conversations/events - Get all conversation events
- GET /api/conversations/workers/:workerId/events - Get worker events
- GET /api/conversations/beads/:beadId/events - Get bead events
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The dgram module's unix_dgram socket type is not properly reflected in
TypeScript's SocketType types. Added @ts-expect-error directives to allow
the working runtime code to compile.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Port TUI SemanticNarrativePanel to React. Provides:
- Standalone overlay panel showing narrative cards per active worker
- Phase detection (Research/Planning/Implementation/Testing/Debugging/Finalizing)
- Phase progress bar, sentiment indicator, accomplishments/challenges
- Expandable activity segments with entity details (files, tools)
- WorkerNarrativeInline component embedded in WorkerDetail narrative tab
- /api/narrative and /api/narrative/:workerId server endpoints
- CSS for all narrative UI elements
- Command palette and header button wired to show:narrative action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Port src/tui/components/SessionDigest.ts to React. The panel exposes:
- 5-tab view (Summary, Beads, Files, Errors, Workers) matching TUI output
- Generate Digest button calling /api/digest (GET, no auth required)
- Export to JSON, Markdown, and plain text via browser download
- CSS styles for all digest UI classes in index.css
- Integration in App.tsx via digest-toggle header button and show:digest command
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Port TUI ErrorGroupPanel to React — groups errors by signature with
occurrence count, affected workers, time span, severity badges, and
expandable detail cards. Links to similar past errors from fabric.db
error_history via /api/errors/history/similar endpoint.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add src/serverMetrics.ts (ServerMetrics class for /api/health + /api/metrics)
- Add scripts/fabric-health-check.sh (curl-based liveness probe)
- Wire sd_notify READY=1 on server start and WATCHDOG=1 keepalives in server.ts
so the Type=notify systemd service correctly reports start and keeps the
watchdog alive without an external npm package
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- /api/health returns {status, uptime_sec, version, event_count,
ingest_rate_per_sec, ws_clients, tailer_files_watched, dedup_dropped,
process_resident_memory_bytes}; returns HTTP 503 with status='overloaded'
when maxEventCount is exceeded
- /api/metrics exposes the same counters in Prometheus text format;
fabric_status=0 when overloaded
- Add ServerMetrics.eventCount setter so both endpoints sync from store.size
(fixes fabric_event_count in /api/metrics showing 0 when events added directly)
- Wire --max-events CLI option into `fabric web`; pass maxEventCount and
deduplicator to createWebServer so the memory-bomb guard and dedup_dropped
reporting are actually activated
- Track tailerFilesWatched: set after tailer.start() and update on each event
for DirectoryTailer (uses activeFiles.length getter)
- Add import for Node net module used by systemd watchdog notify
- Add tests: overload guard returns 503, within-limit returns 200, Prometheus
reflects fabric_status=0 when overloaded
systemd service already has Restart=on-failure + WatchdogSec=30 (scripts/fabric-web.service);
liveness guard in server.ts calls process.exit(1) after 3 consecutive overload
checks, triggering systemd restart.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Warn at startup when FABRIC_AUTH_TOKEN is unset so operators know
POST /api/events is open to any local process; surfaced before
"Press Ctrl+C to stop" so it's visible in systemd journal
- Add "Token rotation" section to README with step-by-step procedure:
generate new secret, update secrets.env (0600), restart service,
verify 401 enforcement; notes that NEEDLE workers reload on next task
start when auth_token uses \${FABRIC_AUTH_TOKEN} substitution
The full auth chain is now in place end-to-end:
~/.config/fabric/secrets.env (0600) → EnvironmentFile →
FABRIC_AUTH_TOKEN env var → server auth middleware → 401/403 on
unauthenticated POST; NEEDLE config auth_token: "\${FABRIC_AUTH_TOKEN}"
routes worker events through the same token.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move auth middleware before OTLP router mount and apply it as app-level
middleware for all POST requests. This protects event ingestion endpoints
(/api/events, /api/events/batch), OTLP endpoints (/v1/logs, /v1/traces,
/v1/metrics), and cost alert acknowledgement. GET endpoints remain open.
Adds comprehensive auth tests covering 401/403/201 responses.
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>
- 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>
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>
- 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>