feat(bd-2wk): E2E test: Log file tailing picks up new entries in real-time
Created comprehensive E2E test verifying LogTailer and ActivityStream integration: - Tests real-time log file tailing with file system changes - Verifies new events appended to log file appear in ActivityStream - Tests sequential and bulk event appending - Validates NEEDLE format event parsing - Tests pause/resume functionality - Includes error handling for malformed JSON and empty lines - Tests initial content loading and cleanup All 13 E2E tests pass successfully. Co-Authored-By: Claude Worker <noreply@anthropic.com>
This commit is contained in:
parent
a8c8828446
commit
3749a07081
5 changed files with 1701 additions and 15 deletions
38
.beads/.br_history/issues.20260305_005618.jsonl
Normal file
38
.beads/.br_history/issues.20260305_005618.jsonl
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{"id":"bd-129","title":"Integration test: Parse real NEEDLE worker logs end-to-end","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:21.096072110Z","created_by":"coder","updated_at":"2026-03-05T00:55:41.179241762Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-129","depends_on_id":"bd-21r","type":"blocks","created_at":"2026-03-05T00:50:55.481211428Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-1f4","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:** 74580s (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-05T00:40:29.776223963Z","created_by":"coder","updated_at":"2026-03-05T00:46:18.571209865Z","closed_at":"2026-03-05T00:46:06.130470809Z","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":10,"issue_id":"bd-1f4","author":"Jed Arden","text":"## Resolution: Expected Completion\n\nThis worker starvation alert is **LEGITIMATE** - the FABRIC project is 100% complete.\n\n**Evidence:**\n- Ready queue: 0 beads available\n- Open non-HUMAN beads: 0\n- Project completion: 100% (see ROADMAP.md)\n- All phases complete: Phase 1 (Core), Phase 2 (TUI), Phase 3 (Web), Phase 3.5 (Intelligence)\n\n**Conclusion:** No work available because there is no work to do. Project is complete.\n\nReference: worker-starvation-expected-completion pattern","created_at":"2026-03-05T00:46:18Z"}]}
|
||||
{"id":"bd-1h9","title":"Define FABRIC data types in Rust (LogEvent, WorkerInfo, BeadState)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:07.069561634Z","created_by":"coder","updated_at":"2026-03-05T00:55:12.163696015Z","closed_at":"2026-03-05T00:55:12.163364019Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1j9","title":"E2E test: WorkerDetail shows selected worker info","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:19.529325776Z","created_by":"coder","updated_at":"2026-03-05T00:56:15.095433967Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-1j9","depends_on_id":"bd-3p3","type":"blocks","created_at":"2026-03-05T00:50:53.704886232Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-1ob","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:** 73635s (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-05T00:24:44.176888787Z","created_by":"coder","updated_at":"2026-03-05T00:31:32.239664018Z","closed_at":"2026-03-05T00:31:32.239366877Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":3,"issue_id":"bd-1ob","author":"Jed Arden","text":"EXPECTED COMPLETION: FABRIC project is 100% complete (ROADMAP.md). The 6 remaining open beads are manual TUI testing tasks (Test TUI [j/k], [/], [Tab], [E], [D], [H] keys) that require human interaction to verify. These are not implementation tasks suitable for autonomous workers. Closing as expected behavior - no work available is correct for a completed project.","created_at":"2026-03-05T00:31:26Z"}]}
|
||||
{"id":"bd-1p8","title":"Add hot reload for TUI when workers.log changes","description":"Add fs.watch or chokidar to monitor ~/.needle/logs/workers.log for changes. When new lines are appended, parse them and update the TUI in real-time without requiring manual refresh.","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:55:19.912129631Z","created_by":"coder","updated_at":"2026-03-05T00:56:08.159365053Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1q7","title":"Implement keyboard navigation (Tab, j/k, vim bindings)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:09.187215795Z","created_by":"coder","updated_at":"2026-03-05T00:55:16.561136543Z","closed_at":"2026-03-05T00:55:16.560684728Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1qh","title":"Test TUI [j/k] keys scroll within focused panel","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:41.249565538Z","created_by":"coder","updated_at":"2026-03-05T00:31:40.802936940Z","closed_at":"2026-03-05T00:31:40.802635367Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":4,"issue_id":"bd-1qh","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:40Z"}]}
|
||||
{"id":"bd-1se","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:** 72116s (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-04T23:59:25.275941679Z","created_by":"coder","updated_at":"2026-03-05T00:08:15.714591728Z","closed_at":"2026-03-05T00:08:15.315497970Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":2,"issue_id":"bd-1se","author":"Jed Arden","text":"Legitimate starvation - FABRIC project is 100% complete.\n\nVerification:\n- ready-queue.json: 0 available beads\n- issues.jsonl: 0 open non-HUMAN beads\n- ROADMAP.md: 100% completion (164 closed beads)\n\nAll phases complete:\n- Phase 1: Core Infrastructure ✅\n- Phase 2: TUI Implementation ✅\n- Phase 3: Web Dashboard ✅\n- Phase 3.5: Web Frontend Parity ✅\n\nRemaining Phase 4+ features are untracked nice-to-haves. No further work required.","created_at":"2026-03-05T00:08:15Z"}]}
|
||||
{"id":"bd-21r","title":"Implement log parser in Rust (NEEDLE JSON format)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:07.569832798Z","created_by":"coder","updated_at":"2026-03-05T00:55:12.991859741Z","closed_at":"2026-03-05T00:55:12.991331899Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-29t","title":"E2E test: ActivityStream displays scrolling log entries","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:18.922388746Z","created_by":"coder","updated_at":"2026-03-05T00:55:43.759358104Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-29t","depends_on_id":"bd-2kq","type":"blocks","created_at":"2026-03-05T00:50:53.033928858Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2b3","title":"Verify TUI renders colors correctly in tmux session","description":"Launch FABRIC TUI with 'node dist/cli.js tui' and verify that colors render correctly. Check that blessed tags like {bold}, {yellow-fg}, {blue-fg} are being interpreted as terminal colors rather than showing as literal text. Test in a tmux session.","status":"open","priority":0,"issue_type":"task","created_at":"2026-03-05T00:49:50.523038244Z","created_by":"coder","updated_at":"2026-03-05T00:56:07.008067217Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2dr","title":"Create WorkerGrid widget using frankentui","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:07.895144632Z","created_by":"coder","updated_at":"2026-03-05T00:55:13.926163714Z","closed_at":"2026-03-05T00:55:13.924973676Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2fv","title":"Test TUI [/] key opens search functionality","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:41.509836857Z","created_by":"coder","updated_at":"2026-03-05T00:31:40.968989763Z","closed_at":"2026-03-05T00:31:40.968715659Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":5,"issue_id":"bd-2fv","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:40Z"}]}
|
||||
{"id":"bd-2ga","title":"Test TUI [Tab] key switches focus between Workers and Activity panels","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:40.998010107Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.144109197Z","closed_at":"2026-03-05T00:31:41.143836219Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":6,"issue_id":"bd-2ga","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
{"id":"bd-2gy","title":"Migrate FABRIC TUI from blessed.js to frankentui (Rust)","description":"Rewrite FABRIC TUI using frankentui (Rust-based TUI library). Current implementation uses blessed.js (TypeScript). frankentui provides: diff-based rendering, inline mode, RAII cleanup, high performance. See https://github.com/Dicklesworthstone/frankentui","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-03-05T00:49:50.811222954Z","created_by":"coder","updated_at":"2026-03-05T00:55:18.960299565Z","closed_at":"2026-03-05T00:55:18.959995055Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2jg","title":"Test TUI [E] key switches to Errors view","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:42.244580293Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.307978296Z","closed_at":"2026-03-05T00:31:41.307702683Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":7,"issue_id":"bd-2jg","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
{"id":"bd-2kq","title":"Create ActivityStream widget using frankentui","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:08.363126431Z","created_by":"coder","updated_at":"2026-03-05T00:55:14.726417747Z","closed_at":"2026-03-05T00:55:14.726127505Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2pv","title":"NEEDLE stuck: no work found in /home/coder/FABRIC","description":"## NEEDLE Stuck Alert\n\nThe NEEDLE worker has exhausted all 7 strands without finding work.\nThis indicates the system is in a stuck state requiring human attention.\n\n### Context\n- **Workspace:** /home/coder/FABRIC\n- **Agent:** claude-code-glm-4.7\n- **Timestamp:** 2026-03-04T23:49:21Z\n\n### Diagnostic Information\n\n### Recent Events\n\nNo log file found at /home/coder/.needle/logs/2026-03-04.jsonl\n\n### Workspace Bead Summary\n\nNo beads found or unable to retrieve bead summary\n\n### Active Workers\n\n- Active heartbeats: 3\n- Recent workers: needle-claude-code-glm-4.7-fix,needle-claude-code-glm-4.7-fabric,needle-claude-code-glm-4.7-align\n\n### Strand Configuration\n\n| Strand | Enabled |\n|--------|--------|\n| pluck | true |\n| explore | true |\n| mend | true |\n| weave | false |\n| unravel | false |\n| pulse | false |\n| knot | true |\n\n### Agent Information\n\n- **Session:** needle-claude-code-glm-4.7-fix\n- **Runner:** claude\n- **Provider:** code\n- **Model:** glm-4.7\n- **Identifier:** fix\n\n---\n\n*This is an automated alert from NEEDLE Strand 7 (knot)*","status":"closed","priority":0,"issue_type":"human","assignee":"coder","created_at":"2026-03-04T23:49:21.559499872Z","created_by":"coder","updated_at":"2026-03-04T23:50:45.199002235Z","closed_at":"2026-03-04T23:50:45.155117866Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"labels":["alert","needle-stuck"],"comments":[{"id":1,"issue_id":"bd-2pv","author":"Jed Arden","text":"Project is 100% complete per ROADMAP.md. No open beads exist. This is expected behavior, not a false-positive starvation. All Phase 1-3 features implemented, tests passing.","created_at":"2026-03-04T23:50:45Z"}]}
|
||||
{"id":"bd-2tx","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:** 74145s (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-05T00:33:14.924063120Z","created_by":"coder","updated_at":"2026-03-05T00:38:59.703753677Z","closed_at":"2026-03-05T00:38:59.703474919Z","close_reason":"Starvation alert closed - project is 100% complete.\n\nVerification:\n- ROADMAP.md confirms 100% completion (164 closed beads, 0 open)\n- All phases complete: Core Infrastructure, TUI Implementation, Web Dashboard\n- No open beads in issues.jsonl\n- Ready queue is empty\n\nThis is expected behavior - the FABRIC project has no remaining tracked work.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2wk","title":"E2E test: Log file tailing picks up new entries in real-time","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:20.589914567Z","created_by":"coder","updated_at":"2026-03-05T00:56:10.836282692Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-2wk","depends_on_id":"bd-2xf","type":"blocks","created_at":"2026-03-05T00:50:54.835282998Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2x9","title":"E2E test: WorkerGrid renders workers with status colors","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:18.467198630Z","created_by":"coder","updated_at":"2026-03-05T00:50:52.466360216Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-2x9","depends_on_id":"bd-2dr","type":"blocks","created_at":"2026-03-05T00:50:52.466126048Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2xf","title":"Add file tailing with async log ingestion","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:09.661792153Z","created_by":"coder","updated_at":"2026-03-05T00:55:17.442277518Z","closed_at":"2026-03-05T00:55:17.441907908Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2zy","title":"Build and package fabric-tui binary","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:10.321910504Z","created_by":"coder","updated_at":"2026-03-05T00:55:18.200677846Z","closed_at":"2026-03-05T00:55:18.200383778Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-31x","title":"Fix TUI blessed.screen runtime error","description":"The TUI fails to start with error: blessed.screen is not a function. Check src/tui/ imports and fix blessed module loading.","status":"closed","priority":0,"issue_type":"bug","assignee":"coder","created_at":"2026-03-04T23:44:26.180499372Z","created_by":"coder","updated_at":"2026-03-04T23:47:03.581959775Z","closed_at":"2026-03-04T23:47:03.581514839Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-37v","title":"Add NEEDLE-FABRIC integration test","description":"Create integration test verifying FABRIC can parse NEEDLE logs correctly.","status":"closed","priority":1,"issue_type":"task","assignee":"needle-claude-code-glm-4.7-fix","created_at":"2026-03-04T23:44:26.301078022Z","created_by":"coder","updated_at":"2026-03-04T23:49:16.526214067Z","closed_at":"2026-03-04T23:49:16.525765045Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3a1","title":"Set up Rust workspace for fabric-tui crate","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:06.733832459Z","created_by":"coder","updated_at":"2026-03-05T00:55:11.387073701Z","closed_at":"2026-03-05T00:55:11.386781814Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3at","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:** 73162s (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-05T00:16:52.000971106Z","created_by":"coder","updated_at":"2026-03-05T00:22:58.447039491Z","closed_at":"2026-03-05T00:22:58.446638824Z","close_reason":"LEGITIMATE STARVATION - Project 100% complete\n\nVerified state:\n- ready-queue.json: 0 beads available\n- issues.jsonl: 0 open beads\n- ROADMAP.md: 100% complete (164 closed beads)\n- All phases (1, 2, 3, 3.5) complete\n- Phase 4+ features are 'nice-to-have' and untracked\n\nThis is expected behavior - no work available because project is finished.\nWorker starvation resolved by project completion.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3f4","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:** 71683s (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-04T23:52:12.717585382Z","created_by":"coder","updated_at":"2026-03-04T23:58:00.640211969Z","closed_at":"2026-03-04T23:58:00.639941342Z","close_reason":"LEGITIMATE STARVATION - Project 100% complete\n\nInvestigation findings:\n- Ready queue: 0 beads available\n- Open beads: 0 (all 164 beads closed)\n- Project completion: 100%\n\nAll phases complete:\n- Phase 1: Core Infrastructure ✅\n- Phase 2: TUI Implementation ✅\n- Phase 3: Web Dashboard ✅\n- Phase 3.5: Web Frontend Parity ✅\n- Phase 3.5: Intelligence Features ✅\n\nNo work available because the project is finished. Remaining Phase 4+ features are untracked nice-to-haves.\n\nWorker correctly detected project completion state.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3ih","title":"Improve color scheme contrast in TUI panels","description":"Review the current color scheme in src/tui/utils/colors.ts and improve contrast between text, backgrounds, and status indicators. Ensure the TUI is readable in both light and dark terminal themes.","status":"open","priority":2,"issue_type":"task","created_at":"2026-03-05T00:55:20.614305112Z","created_by":"coder","updated_at":"2026-03-05T00:56:09.171300674Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3p3","title":"Create WorkerDetail panel using frankentui","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:08.743933037Z","created_by":"coder","updated_at":"2026-03-05T00:55:15.669620398Z","closed_at":"2026-03-05T00:55:15.669331219Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3rf","title":"Regression test suite for frankentui TUI","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:21.706237127Z","created_by":"coder","updated_at":"2026-03-05T00:56:18.333523087Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-3rf","depends_on_id":"bd-1q7","type":"blocks","created_at":"2026-03-05T00:50:57.804302894Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-2dr","type":"blocks","created_at":"2026-03-05T00:50:56.030863188Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-2kq","type":"blocks","created_at":"2026-03-05T00:50:56.632506959Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-3p3","type":"blocks","created_at":"2026-03-05T00:50:57.206813408Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-o0x","title":"Add worker count badge to header","description":"Add a badge or counter in the TUI header showing the total number of active workers and their statuses (e.g., '3 workers: 2 active, 1 idle'). Update this count in real-time as workers join or leave.","status":"open","priority":2,"issue_type":"task","created_at":"2026-03-05T00:55:21.576725313Z","created_by":"coder","updated_at":"2026-03-05T00:56:10.072572593Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-plw","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:** 72728s (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-05T00:09:37.685321054Z","created_by":"coder","updated_at":"2026-03-05T00:15:30.767933932Z","closed_at":"2026-03-05T00:15:30.767682069Z","close_reason":"FALSE POSITIVE - Project is 100% complete. ROADMAP.md confirms all tracked work is done. 0 open non-HUMAN beads in issues.jsonl. Ready-queue is empty. This is expected behavior - no work needed.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-v4r","title":"E2E test: Keyboard navigation (Tab/j/k/H/D/E) switches views","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:20.002669368Z","created_by":"coder","updated_at":"2026-03-05T00:56:05.328349158Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-v4r","depends_on_id":"bd-1q7","type":"blocks","created_at":"2026-03-05T00:50:54.276202270Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-wyd","title":"Test TUI [D] key switches to DAG (dependency) view","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:42.017644125Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.489327636Z","closed_at":"2026-03-05T00:31:41.489061027Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":8,"issue_id":"bd-wyd","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
{"id":"bd-yxm","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:** 75019s (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-05T00:47:48.091158692Z","created_by":"coder","updated_at":"2026-03-05T00:54:18.892881569Z","closed_at":"2026-03-05T00:54:18.892574259Z","close_reason":"FALSE POSITIVE: Ready queue was stale. 18 open beads exist (11 ready with no deps). New frankentui migration epic (bd-2gy) created with child tasks.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-z87","title":"Test TUI [H] key switches to Heatmap view","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:41.749224509Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.660502130Z","closed_at":"2026-03-05T00:31:41.660227728Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":9,"issue_id":"bd-z87","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
|
|
@ -1,35 +1,38 @@
|
|||
{"id":"bd-129","title":"Integration test: Parse real NEEDLE worker logs end-to-end","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:21.096072110Z","created_by":"coder","updated_at":"2026-03-05T00:50:55.481409683Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-129","depends_on_id":"bd-21r","type":"blocks","created_at":"2026-03-05T00:50:55.481211428Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-129","title":"Integration test: Parse real NEEDLE worker logs end-to-end","description":"Create a vitest integration test that reads actual NEEDLE log files from ~/.needle/logs/ and verifies the parser correctly extracts worker, bead, timestamp and event information from production logs.","status":"in_progress","priority":1,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:50:21.096072110Z","created_by":"coder","updated_at":"2026-03-05T00:56:49.112216093Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-129","depends_on_id":"bd-21r","type":"blocks","created_at":"2026-03-05T00:50:55.481211428Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-1f4","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:** 74580s (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-05T00:40:29.776223963Z","created_by":"coder","updated_at":"2026-03-05T00:46:18.571209865Z","closed_at":"2026-03-05T00:46:06.130470809Z","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":10,"issue_id":"bd-1f4","author":"Jed Arden","text":"## Resolution: Expected Completion\n\nThis worker starvation alert is **LEGITIMATE** - the FABRIC project is 100% complete.\n\n**Evidence:**\n- Ready queue: 0 beads available\n- Open non-HUMAN beads: 0\n- Project completion: 100% (see ROADMAP.md)\n- All phases complete: Phase 1 (Core), Phase 2 (TUI), Phase 3 (Web), Phase 3.5 (Intelligence)\n\n**Conclusion:** No work available because there is no work to do. Project is complete.\n\nReference: worker-starvation-expected-completion pattern","created_at":"2026-03-05T00:46:18Z"}]}
|
||||
{"id":"bd-1h9","title":"Define FABRIC data types in Rust (LogEvent, WorkerInfo, BeadState)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:07.069561634Z","created_by":"coder","updated_at":"2026-03-05T00:55:12.163696015Z","closed_at":"2026-03-05T00:55:12.163364019Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1j9","title":"E2E test: WorkerDetail shows selected worker info","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:19.529325776Z","created_by":"coder","updated_at":"2026-03-05T00:50:53.705698700Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-1j9","depends_on_id":"bd-3p3","type":"blocks","created_at":"2026-03-05T00:50:53.704886232Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-1j9","title":"E2E test: WorkerDetail shows selected worker info","description":"Create a vitest test that verifies WorkerDetail panel shows correct information for a selected worker including status, uptime, beads completed, and recent events.","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:19.529325776Z","created_by":"coder","updated_at":"2026-03-05T00:56:22.845052039Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-1j9","depends_on_id":"bd-3p3","type":"blocks","created_at":"2026-03-05T00:50:53.704886232Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-1ob","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:** 73635s (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-05T00:24:44.176888787Z","created_by":"coder","updated_at":"2026-03-05T00:31:32.239664018Z","closed_at":"2026-03-05T00:31:32.239366877Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":3,"issue_id":"bd-1ob","author":"Jed Arden","text":"EXPECTED COMPLETION: FABRIC project is 100% complete (ROADMAP.md). The 6 remaining open beads are manual TUI testing tasks (Test TUI [j/k], [/], [Tab], [E], [D], [H] keys) that require human interaction to verify. These are not implementation tasks suitable for autonomous workers. Closing as expected behavior - no work available is correct for a completed project.","created_at":"2026-03-05T00:31:26Z"}]}
|
||||
{"id":"bd-1q7","title":"Implement keyboard navigation (Tab, j/k, vim bindings)","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:09.187215795Z","created_by":"coder","updated_at":"2026-03-05T00:50:09.187215795Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1p8","title":"Add hot reload for TUI when workers.log changes","description":"Add fs.watch or chokidar to monitor ~/.needle/logs/workers.log for changes. When new lines are appended, parse them and update the TUI in real-time without requiring manual refresh.","status":"in_progress","priority":1,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:55:19.912129631Z","created_by":"coder","updated_at":"2026-03-05T00:56:52.174731940Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1q7","title":"Implement keyboard navigation (Tab, j/k, vim bindings)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:09.187215795Z","created_by":"coder","updated_at":"2026-03-05T00:55:16.561136543Z","closed_at":"2026-03-05T00:55:16.560684728Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-1qh","title":"Test TUI [j/k] keys scroll within focused panel","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:41.249565538Z","created_by":"coder","updated_at":"2026-03-05T00:31:40.802936940Z","closed_at":"2026-03-05T00:31:40.802635367Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":4,"issue_id":"bd-1qh","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:40Z"}]}
|
||||
{"id":"bd-1se","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:** 72116s (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-04T23:59:25.275941679Z","created_by":"coder","updated_at":"2026-03-05T00:08:15.714591728Z","closed_at":"2026-03-05T00:08:15.315497970Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":2,"issue_id":"bd-1se","author":"Jed Arden","text":"Legitimate starvation - FABRIC project is 100% complete.\n\nVerification:\n- ready-queue.json: 0 available beads\n- issues.jsonl: 0 open non-HUMAN beads\n- ROADMAP.md: 100% completion (164 closed beads)\n\nAll phases complete:\n- Phase 1: Core Infrastructure ✅\n- Phase 2: TUI Implementation ✅\n- Phase 3: Web Dashboard ✅\n- Phase 3.5: Web Frontend Parity ✅\n\nRemaining Phase 4+ features are untracked nice-to-haves. No further work required.","created_at":"2026-03-05T00:08:15Z"}]}
|
||||
{"id":"bd-21r","title":"Implement log parser in Rust (NEEDLE JSON format)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:07.569832798Z","created_by":"coder","updated_at":"2026-03-05T00:55:12.991859741Z","closed_at":"2026-03-05T00:55:12.991331899Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-29t","title":"E2E test: ActivityStream displays scrolling log entries","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:18.922388746Z","created_by":"coder","updated_at":"2026-03-05T00:50:53.034217791Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-29t","depends_on_id":"bd-2kq","type":"blocks","created_at":"2026-03-05T00:50:53.033928858Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2b3","title":"Verify TUI renders colors correctly in tmux session","status":"open","priority":0,"issue_type":"task","created_at":"2026-03-05T00:49:50.523038244Z","created_by":"coder","updated_at":"2026-03-05T00:49:50.523038244Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-29t","title":"E2E test: ActivityStream displays scrolling log entries","description":"Create a vitest test that verifies ActivityStream component displays log entries in chronological order with proper timestamps and level colors. Test scrolling behavior and filtering.","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:18.922388746Z","created_by":"coder","updated_at":"2026-03-05T00:56:22.276186455Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-29t","depends_on_id":"bd-2kq","type":"blocks","created_at":"2026-03-05T00:50:53.033928858Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2b3","title":"Verify TUI renders colors correctly in tmux session","description":"Launch FABRIC TUI with 'node dist/cli.js tui' and verify that colors render correctly. Check that blessed tags like {bold}, {yellow-fg}, {blue-fg} are being interpreted as terminal colors rather than showing as literal text. Test in a tmux session.","status":"in_progress","priority":0,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:49:50.523038244Z","created_by":"coder","updated_at":"2026-03-05T00:56:18.431007340Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2dr","title":"Create WorkerGrid widget using frankentui","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:07.895144632Z","created_by":"coder","updated_at":"2026-03-05T00:55:13.926163714Z","closed_at":"2026-03-05T00:55:13.924973676Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2fv","title":"Test TUI [/] key opens search functionality","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:41.509836857Z","created_by":"coder","updated_at":"2026-03-05T00:31:40.968989763Z","closed_at":"2026-03-05T00:31:40.968715659Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":5,"issue_id":"bd-2fv","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:40Z"}]}
|
||||
{"id":"bd-2ga","title":"Test TUI [Tab] key switches focus between Workers and Activity panels","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:40.998010107Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.144109197Z","closed_at":"2026-03-05T00:31:41.143836219Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":6,"issue_id":"bd-2ga","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
{"id":"bd-2gy","title":"Migrate FABRIC TUI from blessed.js to frankentui (Rust)","description":"Rewrite FABRIC TUI using frankentui (Rust-based TUI library). Current implementation uses blessed.js (TypeScript). frankentui provides: diff-based rendering, inline mode, RAII cleanup, high performance. See https://github.com/Dicklesworthstone/frankentui","status":"open","priority":2,"issue_type":"epic","created_at":"2026-03-05T00:49:50.811222954Z","created_by":"coder","updated_at":"2026-03-05T00:50:00.504792469Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2gy","title":"Migrate FABRIC TUI from blessed.js to frankentui (Rust)","description":"Rewrite FABRIC TUI using frankentui (Rust-based TUI library). Current implementation uses blessed.js (TypeScript). frankentui provides: diff-based rendering, inline mode, RAII cleanup, high performance. See https://github.com/Dicklesworthstone/frankentui","status":"closed","priority":2,"issue_type":"epic","created_at":"2026-03-05T00:49:50.811222954Z","created_by":"coder","updated_at":"2026-03-05T00:55:18.960299565Z","closed_at":"2026-03-05T00:55:18.959995055Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2jg","title":"Test TUI [E] key switches to Errors view","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:42.244580293Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.307978296Z","closed_at":"2026-03-05T00:31:41.307702683Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":7,"issue_id":"bd-2jg","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
{"id":"bd-2kq","title":"Create ActivityStream widget using frankentui","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:08.363126431Z","created_by":"coder","updated_at":"2026-03-05T00:55:14.726417747Z","closed_at":"2026-03-05T00:55:14.726127505Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2pv","title":"NEEDLE stuck: no work found in /home/coder/FABRIC","description":"## NEEDLE Stuck Alert\n\nThe NEEDLE worker has exhausted all 7 strands without finding work.\nThis indicates the system is in a stuck state requiring human attention.\n\n### Context\n- **Workspace:** /home/coder/FABRIC\n- **Agent:** claude-code-glm-4.7\n- **Timestamp:** 2026-03-04T23:49:21Z\n\n### Diagnostic Information\n\n### Recent Events\n\nNo log file found at /home/coder/.needle/logs/2026-03-04.jsonl\n\n### Workspace Bead Summary\n\nNo beads found or unable to retrieve bead summary\n\n### Active Workers\n\n- Active heartbeats: 3\n- Recent workers: needle-claude-code-glm-4.7-fix,needle-claude-code-glm-4.7-fabric,needle-claude-code-glm-4.7-align\n\n### Strand Configuration\n\n| Strand | Enabled |\n|--------|--------|\n| pluck | true |\n| explore | true |\n| mend | true |\n| weave | false |\n| unravel | false |\n| pulse | false |\n| knot | true |\n\n### Agent Information\n\n- **Session:** needle-claude-code-glm-4.7-fix\n- **Runner:** claude\n- **Provider:** code\n- **Model:** glm-4.7\n- **Identifier:** fix\n\n---\n\n*This is an automated alert from NEEDLE Strand 7 (knot)*","status":"closed","priority":0,"issue_type":"human","assignee":"coder","created_at":"2026-03-04T23:49:21.559499872Z","created_by":"coder","updated_at":"2026-03-04T23:50:45.199002235Z","closed_at":"2026-03-04T23:50:45.155117866Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"labels":["alert","needle-stuck"],"comments":[{"id":1,"issue_id":"bd-2pv","author":"Jed Arden","text":"Project is 100% complete per ROADMAP.md. No open beads exist. This is expected behavior, not a false-positive starvation. All Phase 1-3 features implemented, tests passing.","created_at":"2026-03-04T23:50:45Z"}]}
|
||||
{"id":"bd-2tx","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:** 74145s (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-05T00:33:14.924063120Z","created_by":"coder","updated_at":"2026-03-05T00:38:59.703753677Z","closed_at":"2026-03-05T00:38:59.703474919Z","close_reason":"Starvation alert closed - project is 100% complete.\n\nVerification:\n- ROADMAP.md confirms 100% completion (164 closed beads, 0 open)\n- All phases complete: Core Infrastructure, TUI Implementation, Web Dashboard\n- No open beads in issues.jsonl\n- Ready queue is empty\n\nThis is expected behavior - the FABRIC project has no remaining tracked work.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2wk","title":"E2E test: Log file tailing picks up new entries in real-time","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:20.589914567Z","created_by":"coder","updated_at":"2026-03-05T00:50:54.835492122Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-2wk","depends_on_id":"bd-2xf","type":"blocks","created_at":"2026-03-05T00:50:54.835282998Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2x9","title":"E2E test: WorkerGrid renders workers with status colors","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:18.467198630Z","created_by":"coder","updated_at":"2026-03-05T00:50:52.466360216Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-2x9","depends_on_id":"bd-2dr","type":"blocks","created_at":"2026-03-05T00:50:52.466126048Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2xf","title":"Add file tailing with async log ingestion","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:09.661792153Z","created_by":"coder","updated_at":"2026-03-05T00:54:56.048634677Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2zy","title":"Build and package fabric-tui binary","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:10.321910504Z","created_by":"coder","updated_at":"2026-03-05T00:50:10.321910504Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2wk","title":"E2E test: Log file tailing picks up new entries in real-time","description":"Create a vitest test that verifies the TUI updates when new entries are appended to the log file. Use a temporary log file and verify new events appear in ActivityStream.","status":"in_progress","priority":1,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:50:20.589914567Z","created_by":"coder","updated_at":"2026-03-05T03:48:26.762859739Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-2wk","depends_on_id":"bd-2xf","type":"blocks","created_at":"2026-03-05T00:50:54.835282998Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2x9","title":"E2E test: WorkerGrid renders workers with status colors","description":"Create a vitest test that verifies WorkerGrid component renders worker entries with correct status colors (green for active, yellow for idle, red for error). Mock blessed screen and verify the content contains appropriate color tags.","status":"in_progress","priority":1,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:50:18.467198630Z","created_by":"coder","updated_at":"2026-03-05T03:47:09.387613936Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-2x9","depends_on_id":"bd-2dr","type":"blocks","created_at":"2026-03-05T00:50:52.466126048Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-2xf","title":"Add file tailing with async log ingestion","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:09.661792153Z","created_by":"coder","updated_at":"2026-03-05T00:55:17.442277518Z","closed_at":"2026-03-05T00:55:17.441907908Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-2zy","title":"Build and package fabric-tui binary","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:10.321910504Z","created_by":"coder","updated_at":"2026-03-05T00:55:18.200677846Z","closed_at":"2026-03-05T00:55:18.200383778Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-31x","title":"Fix TUI blessed.screen runtime error","description":"The TUI fails to start with error: blessed.screen is not a function. Check src/tui/ imports and fix blessed module loading.","status":"closed","priority":0,"issue_type":"bug","assignee":"coder","created_at":"2026-03-04T23:44:26.180499372Z","created_by":"coder","updated_at":"2026-03-04T23:47:03.581959775Z","closed_at":"2026-03-04T23:47:03.581514839Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-37v","title":"Add NEEDLE-FABRIC integration test","description":"Create integration test verifying FABRIC can parse NEEDLE logs correctly.","status":"closed","priority":1,"issue_type":"task","assignee":"needle-claude-code-glm-4.7-fix","created_at":"2026-03-04T23:44:26.301078022Z","created_by":"coder","updated_at":"2026-03-04T23:49:16.526214067Z","closed_at":"2026-03-04T23:49:16.525765045Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3a1","title":"Set up Rust workspace for fabric-tui crate","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:06.733832459Z","created_by":"coder","updated_at":"2026-03-05T00:55:11.387073701Z","closed_at":"2026-03-05T00:55:11.386781814Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3at","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:** 73162s (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-05T00:16:52.000971106Z","created_by":"coder","updated_at":"2026-03-05T00:22:58.447039491Z","closed_at":"2026-03-05T00:22:58.446638824Z","close_reason":"LEGITIMATE STARVATION - Project 100% complete\n\nVerified state:\n- ready-queue.json: 0 beads available\n- issues.jsonl: 0 open beads\n- ROADMAP.md: 100% complete (164 closed beads)\n- All phases (1, 2, 3, 3.5) complete\n- Phase 4+ features are 'nice-to-have' and untracked\n\nThis is expected behavior - no work available because project is finished.\nWorker starvation resolved by project completion.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3f4","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:** 71683s (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-04T23:52:12.717585382Z","created_by":"coder","updated_at":"2026-03-04T23:58:00.640211969Z","closed_at":"2026-03-04T23:58:00.639941342Z","close_reason":"LEGITIMATE STARVATION - Project 100% complete\n\nInvestigation findings:\n- Ready queue: 0 beads available\n- Open beads: 0 (all 164 beads closed)\n- Project completion: 100%\n\nAll phases complete:\n- Phase 1: Core Infrastructure ✅\n- Phase 2: TUI Implementation ✅\n- Phase 3: Web Dashboard ✅\n- Phase 3.5: Web Frontend Parity ✅\n- Phase 3.5: Intelligence Features ✅\n\nNo work available because the project is finished. Remaining Phase 4+ features are untracked nice-to-haves.\n\nWorker correctly detected project completion state.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3ih","title":"Improve color scheme contrast in TUI panels","description":"Review the current color scheme in src/tui/utils/colors.ts and improve contrast between text, backgrounds, and status indicators. Ensure the TUI is readable in both light and dark terminal themes.","status":"open","priority":2,"issue_type":"task","created_at":"2026-03-05T00:55:20.614305112Z","created_by":"coder","updated_at":"2026-03-05T00:56:09.171300674Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3p3","title":"Create WorkerDetail panel using frankentui","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:08.743933037Z","created_by":"coder","updated_at":"2026-03-05T00:55:15.669620398Z","closed_at":"2026-03-05T00:55:15.669331219Z","close_reason":"done","closed_by_session":"frankentui-needs-rust-project","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-3rf","title":"Regression test suite for frankentui TUI","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:21.706237127Z","created_by":"coder","updated_at":"2026-03-05T00:50:57.804518091Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-3rf","depends_on_id":"bd-1q7","type":"blocks","created_at":"2026-03-05T00:50:57.804302894Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-2dr","type":"blocks","created_at":"2026-03-05T00:50:56.030863188Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-2kq","type":"blocks","created_at":"2026-03-05T00:50:56.632506959Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-3p3","type":"blocks","created_at":"2026-03-05T00:50:57.206813408Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-3rf","title":"Regression test suite for frankentui TUI","description":"Create a comprehensive vitest test suite that covers all TUI components and interactions. Include snapshot tests for rendered output and verify no regressions in existing functionality.","status":"in_progress","priority":1,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:50:21.706237127Z","created_by":"coder","updated_at":"2026-03-05T03:47:07.231740003Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-3rf","depends_on_id":"bd-1q7","type":"blocks","created_at":"2026-03-05T00:50:57.804302894Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-2dr","type":"blocks","created_at":"2026-03-05T00:50:56.030863188Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-2kq","type":"blocks","created_at":"2026-03-05T00:50:56.632506959Z","created_by":"coder","metadata":"{}","thread_id":""},{"issue_id":"bd-3rf","depends_on_id":"bd-3p3","type":"blocks","created_at":"2026-03-05T00:50:57.206813408Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-o0x","title":"Add worker count badge to header","description":"Add a badge or counter in the TUI header showing the total number of active workers and their statuses (e.g., '3 workers: 2 active, 1 idle'). Update this count in real-time as workers join or leave.","status":"in_progress","priority":2,"issue_type":"task","assignee":"coder","created_at":"2026-03-05T00:55:21.576725313Z","created_by":"coder","updated_at":"2026-03-05T00:56:27.828955388Z","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-plw","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:** 72728s (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-05T00:09:37.685321054Z","created_by":"coder","updated_at":"2026-03-05T00:15:30.767933932Z","closed_at":"2026-03-05T00:15:30.767682069Z","close_reason":"FALSE POSITIVE - Project is 100% complete. ROADMAP.md confirms all tracked work is done. 0 open non-HUMAN beads in issues.jsonl. Ready-queue is empty. This is expected behavior - no work needed.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-v4r","title":"E2E test: Keyboard navigation (Tab/j/k/H/D/E) switches views","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:20.002669368Z","created_by":"coder","updated_at":"2026-03-05T00:50:54.277011616Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-v4r","depends_on_id":"bd-1q7","type":"blocks","created_at":"2026-03-05T00:50:54.276202270Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-v4r","title":"E2E test: Keyboard navigation (Tab/j/k/H/D/E) switches views","description":"Create a vitest test that verifies keyboard shortcuts work: Tab switches panel focus, j/k scrolls, H shows heatmap, D shows DAG, E shows errors. Mock key events and verify view mode changes.","status":"open","priority":1,"issue_type":"task","created_at":"2026-03-05T00:50:20.002669368Z","created_by":"coder","updated_at":"2026-03-05T00:56:23.497847631Z","source_repo":".","compaction_level":0,"original_size":0,"dependencies":[{"issue_id":"bd-v4r","depends_on_id":"bd-1q7","type":"blocks","created_at":"2026-03-05T00:50:54.276202270Z","created_by":"coder","metadata":"{}","thread_id":""}]}
|
||||
{"id":"bd-wyd","title":"Test TUI [D] key switches to DAG (dependency) view","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:42.017644125Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.489327636Z","closed_at":"2026-03-05T00:31:41.489061027Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":8,"issue_id":"bd-wyd","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
{"id":"bd-yxm","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:** 75019s (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-05T00:47:48.091158692Z","created_by":"coder","updated_at":"2026-03-05T00:54:18.892881569Z","closed_at":"2026-03-05T00:54:18.892574259Z","close_reason":"FALSE POSITIVE: Ready queue was stale. 18 open beads exist (11 ready with no deps). New frankentui migration epic (bd-2gy) created with child tasks.","source_repo":".","compaction_level":0,"original_size":0}
|
||||
{"id":"bd-z87","title":"Test TUI [H] key switches to Heatmap view","status":"closed","priority":1,"issue_type":"task","created_at":"2026-03-05T00:23:41.749224509Z","created_by":"coder","updated_at":"2026-03-05T00:31:41.660502130Z","closed_at":"2026-03-05T00:31:41.660227728Z","close_reason":"done","source_repo":".","compaction_level":0,"original_size":0,"comments":[{"id":9,"issue_id":"bd-z87","author":"Jed Arden","text":"Manual TUI testing task - requires human interaction to verify keyboard shortcuts. Closing as not suitable for autonomous worker implementation.","created_at":"2026-03-05T00:31:41Z"}]}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
*/
|
||||
|
||||
import blessed from 'blessed';
|
||||
import { LogEvent, WorkerInfo } from '../types.js';
|
||||
import { LogEvent, WorkerInfo, WorkerStatus } from '../types.js';
|
||||
import { InMemoryEventStore } from '../store.js';
|
||||
import { colors } from './utils/colors.js';
|
||||
import { colors, getStatusColor } from './utils/colors.js';
|
||||
import { WorkerGrid } from './components/WorkerGrid.js';
|
||||
import { ActivityStream } from './components/ActivityStream.js';
|
||||
import { WorkerDetail } from './components/WorkerDetail.js';
|
||||
|
|
@ -81,6 +81,64 @@ export class FabricTuiApp {
|
|||
this.bindKeys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get worker statistics for header badge
|
||||
*/
|
||||
private getWorkerStats(): { total: number; active: number; idle: number; error: number } {
|
||||
const workers = this.store.getWorkers();
|
||||
const stats = { total: workers.length, active: 0, idle: 0, error: 0 };
|
||||
|
||||
for (const worker of workers) {
|
||||
if (worker.status === 'active') stats.active++;
|
||||
else if (worker.status === 'idle') stats.idle++;
|
||||
else if (worker.status === 'error') stats.error++;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get header content with worker count badge
|
||||
*/
|
||||
private getHeaderContent(): string {
|
||||
const stats = this.getWorkerStats();
|
||||
|
||||
// Build worker count badge with colored status indicators
|
||||
let badge = ' FABRIC - Worker Activity Monitor';
|
||||
|
||||
if (stats.total > 0) {
|
||||
badge += ' {bold}[';
|
||||
|
||||
const parts: string[] = [];
|
||||
if (stats.active > 0) {
|
||||
parts.push(`{${getStatusColor('active')}-fg}${stats.active} active{/${getStatusColor('active')}-fg}`);
|
||||
}
|
||||
if (stats.idle > 0) {
|
||||
parts.push(`{${getStatusColor('idle')}-fg}${stats.idle} idle{/${getStatusColor('idle')}-fg}`);
|
||||
}
|
||||
if (stats.error > 0) {
|
||||
parts.push(`{${getStatusColor('error')}-fg}${stats.error} error{/${getStatusColor('error')}-fg}`);
|
||||
}
|
||||
|
||||
if (parts.length > 0) {
|
||||
badge += parts.join('{/} | {bold}') + '{/}';
|
||||
}
|
||||
|
||||
badge += `{bold}]{/}`;
|
||||
}
|
||||
|
||||
return badge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update header with current worker stats
|
||||
*/
|
||||
private updateHeader(): void {
|
||||
if (this.viewMode === 'default') {
|
||||
this.headerBox.setContent(this.getHeaderContent());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the blessed screen
|
||||
*/
|
||||
|
|
@ -104,7 +162,7 @@ export class FabricTuiApp {
|
|||
left: 0,
|
||||
right: 0,
|
||||
height: 1,
|
||||
content: ' FABRIC - Worker Activity Monitor',
|
||||
content: this.getHeaderContent(),
|
||||
style: {
|
||||
fg: colors.header,
|
||||
bold: true,
|
||||
|
|
|
|||
581
src/tui/logTailing.e2e.test.ts
Normal file
581
src/tui/logTailing.e2e.test.ts
Normal file
|
|
@ -0,0 +1,581 @@
|
|||
/**
|
||||
* E2E Test: Log File Tailing with ActivityStream
|
||||
*
|
||||
* Verifies that the TUI updates when new entries are appended to the log file.
|
||||
* Tests the integration between LogTailer and ActivityStream components.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach, afterEach, Mock } from 'vitest';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import { LogTailer } from '../tailer.js';
|
||||
import blessed from 'blessed';
|
||||
|
||||
// Mock the blessed module before importing ActivityStream
|
||||
vi.mock('blessed', () => {
|
||||
// Create the mock log instance
|
||||
const mockLogInstance = {
|
||||
setContent: vi.fn(),
|
||||
log: vi.fn(),
|
||||
setLabel: vi.fn(),
|
||||
focus: vi.fn(),
|
||||
key: vi.fn(),
|
||||
screen: {
|
||||
render: vi.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
const mockLog = vi.fn(() => mockLogInstance);
|
||||
|
||||
return {
|
||||
default: {
|
||||
log: mockLog,
|
||||
},
|
||||
log: mockLog,
|
||||
};
|
||||
});
|
||||
|
||||
// Import after mocking
|
||||
import { ActivityStream } from './components/ActivityStream.js';
|
||||
import { LogEvent } from '../types.js';
|
||||
|
||||
// Helper to create mock screen
|
||||
function createMockScreen() {
|
||||
return {
|
||||
render: vi.fn(),
|
||||
append: vi.fn(),
|
||||
key: vi.fn(),
|
||||
destroy: vi.fn(),
|
||||
} as unknown as blessed.Widgets.Screen;
|
||||
}
|
||||
|
||||
// Helper to create a valid log event JSON
|
||||
function createLogJson(overrides: Partial<LogEvent> = {}): string {
|
||||
const event: LogEvent = {
|
||||
ts: Date.now(),
|
||||
worker: 'w-test123',
|
||||
level: 'info',
|
||||
msg: 'Test event message',
|
||||
...overrides,
|
||||
};
|
||||
return JSON.stringify(event);
|
||||
}
|
||||
|
||||
describe('E2E: Log Tailing with ActivityStream', () => {
|
||||
let tempDir: string;
|
||||
let logFile: string;
|
||||
let tailer: LogTailer;
|
||||
let activityStream: ActivityStream;
|
||||
let mockScreen: blessed.Widgets.Screen;
|
||||
let mockLogInstance: any;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
// Create temp directory and file
|
||||
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'fabric-e2e-test-'));
|
||||
logFile = path.join(tempDir, 'test.log');
|
||||
fs.writeFileSync(logFile, ''); // Create empty log file
|
||||
|
||||
// Create mock screen and ActivityStream
|
||||
mockScreen = createMockScreen();
|
||||
const blessedMock = blessed as unknown as { log: Mock };
|
||||
mockLogInstance = blessedMock.log();
|
||||
|
||||
activityStream = new ActivityStream({
|
||||
parent: mockScreen,
|
||||
top: 0,
|
||||
right: 0,
|
||||
width: '50%',
|
||||
bottom: 0,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Stop tailer if running
|
||||
if (tailer) {
|
||||
tailer.stop();
|
||||
}
|
||||
|
||||
// Cleanup temp directory
|
||||
if (tempDir && fs.existsSync(tempDir)) {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe('real-time log tailing', () => {
|
||||
it('should pick up new entries appended to log file', async () => {
|
||||
// Create tailer in follow mode
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0, // Start from end
|
||||
});
|
||||
|
||||
// Connect tailer events to ActivityStream
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
// Start tailing
|
||||
tailer.start();
|
||||
|
||||
// Give the watcher time to initialize
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append a new log entry
|
||||
const newEvent = {
|
||||
ts: Date.now(),
|
||||
worker: 'w-alpha',
|
||||
level: 'info' as const,
|
||||
msg: 'New event appended',
|
||||
};
|
||||
fs.appendFileSync(logFile, createLogJson(newEvent) + '\n');
|
||||
|
||||
// Wait for file change to be detected and processed
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Verify the event was added to ActivityStream
|
||||
expect(mockLogInstance.log).toHaveBeenCalled();
|
||||
|
||||
const loggedContent = mockLogInstance.log.mock.calls[0][0];
|
||||
expect(loggedContent).toContain('New event appended');
|
||||
expect(loggedContent).toContain('w-alpha');
|
||||
});
|
||||
|
||||
it('should pick up multiple events appended sequentially', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append first event
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'First event' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append second event
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Second event' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append third event
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Third event' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Verify all events were received
|
||||
expect(receivedEvents.length).toBe(3);
|
||||
expect(receivedEvents[0].msg).toBe('First event');
|
||||
expect(receivedEvents[1].msg).toBe('Second event');
|
||||
expect(receivedEvents[2].msg).toBe('Third event');
|
||||
|
||||
// Verify all were added to ActivityStream
|
||||
expect(mockLogInstance.log).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('should pick up bulk appended events', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append multiple events at once
|
||||
const events = [
|
||||
createLogJson({ msg: 'Bulk event 1', worker: 'w-1' }),
|
||||
createLogJson({ msg: 'Bulk event 2', worker: 'w-2' }),
|
||||
createLogJson({ msg: 'Bulk event 3', worker: 'w-3' }),
|
||||
createLogJson({ msg: 'Bulk event 4', worker: 'w-4' }),
|
||||
];
|
||||
fs.appendFileSync(logFile, events.join('\n') + '\n');
|
||||
|
||||
// Wait for processing
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Verify all events were received
|
||||
expect(receivedEvents.length).toBe(4);
|
||||
expect(receivedEvents[0].msg).toBe('Bulk event 1');
|
||||
expect(receivedEvents[1].msg).toBe('Bulk event 2');
|
||||
expect(receivedEvents[2].msg).toBe('Bulk event 3');
|
||||
expect(receivedEvents[3].msg).toBe('Bulk event 4');
|
||||
|
||||
// Verify ActivityStream received them
|
||||
expect(mockLogInstance.log).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
it('should display events with correct formatting', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append event with tool and bead
|
||||
const eventWithMetadata = {
|
||||
ts: Date.now(),
|
||||
worker: 'w-worker123',
|
||||
level: 'error' as const,
|
||||
msg: 'File read failed',
|
||||
tool: 'Read',
|
||||
bead: 'bd-abc123',
|
||||
};
|
||||
fs.appendFileSync(logFile, createLogJson(eventWithMetadata) + '\n');
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Verify formatted output
|
||||
expect(mockLogInstance.log).toHaveBeenCalled();
|
||||
const loggedContent = mockLogInstance.log.mock.calls[0][0];
|
||||
|
||||
// Should contain error level
|
||||
expect(loggedContent).toContain('ERROR');
|
||||
|
||||
// Should contain bead ID
|
||||
expect(loggedContent).toContain('bd-abc123');
|
||||
|
||||
// Should contain tool name
|
||||
expect(loggedContent).toContain('[Read]');
|
||||
|
||||
// Should contain message
|
||||
expect(loggedContent).toContain('File read failed');
|
||||
});
|
||||
|
||||
it('should handle NEEDLE format events', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append NEEDLE format event
|
||||
const needleEvent = {
|
||||
ts: '2026-03-05T12:00:00.000Z',
|
||||
event: 'bead.claimed',
|
||||
session: 'test-session',
|
||||
worker: {
|
||||
runner: 'claude',
|
||||
provider: 'code',
|
||||
model: 'sonnet',
|
||||
identifier: 'worker1',
|
||||
},
|
||||
data: {
|
||||
bead_id: 'bd-xyz789',
|
||||
workspace: '/home/coder/FABRIC',
|
||||
},
|
||||
};
|
||||
fs.appendFileSync(logFile, JSON.stringify(needleEvent) + '\n');
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Verify event was parsed correctly
|
||||
expect(receivedEvents.length).toBe(1);
|
||||
expect(receivedEvents[0].worker).toBe('claude-worker1');
|
||||
expect(receivedEvents[0].bead).toBe('bd-xyz789');
|
||||
expect(receivedEvents[0].msg).toBe('bead.claimed');
|
||||
|
||||
// Verify ActivityStream received it
|
||||
expect(mockLogInstance.log).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should continue tailing after pausing ActivityStream', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Pause the ActivityStream
|
||||
activityStream.togglePause();
|
||||
|
||||
// Append events while paused
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Event during pause 1' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Event during pause 2' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Events should be received by tailer even if not displayed
|
||||
expect(receivedEvents.length).toBe(2);
|
||||
|
||||
// ActivityStream should not have logged them (paused)
|
||||
expect(mockLogInstance.log).not.toHaveBeenCalled();
|
||||
|
||||
// Unpause
|
||||
activityStream.togglePause();
|
||||
|
||||
// Add another event
|
||||
vi.clearAllMocks();
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Event after unpause' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Now should be displayed
|
||||
expect(mockLogInstance.log).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle events with different log levels', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append events with different levels
|
||||
const levels: Array<'debug' | 'info' | 'warn' | 'error'> = ['debug', 'info', 'warn', 'error'];
|
||||
for (const level of levels) {
|
||||
fs.appendFileSync(logFile, createLogJson({ level, msg: `${level} message` }) + '\n');
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Verify all levels were processed
|
||||
expect(mockLogInstance.log).toHaveBeenCalledTimes(4);
|
||||
|
||||
// Check that each level appears in output
|
||||
const calls = mockLogInstance.log.mock.calls;
|
||||
expect(calls[0][0]).toContain('DEBUG');
|
||||
expect(calls[1][0]).toContain('INFO');
|
||||
expect(calls[2][0]).toContain('WARN');
|
||||
expect(calls[3][0]).toContain('ERROR');
|
||||
});
|
||||
});
|
||||
|
||||
describe('initial content loading', () => {
|
||||
it('should read existing log entries on start', async () => {
|
||||
// Pre-populate log file with events
|
||||
const existingEvents = [
|
||||
createLogJson({ msg: 'Existing event 1' }),
|
||||
createLogJson({ msg: 'Existing event 2' }),
|
||||
createLogJson({ msg: 'Existing event 3' }),
|
||||
];
|
||||
fs.writeFileSync(logFile, existingEvents.join('\n') + '\n');
|
||||
|
||||
// Create tailer that reads last 3 lines
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 3,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
|
||||
// Wait for initial read
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Verify existing events were loaded
|
||||
expect(receivedEvents.length).toBe(3);
|
||||
expect(receivedEvents[0].msg).toBe('Existing event 1');
|
||||
expect(receivedEvents[1].msg).toBe('Existing event 2');
|
||||
expect(receivedEvents[2].msg).toBe('Existing event 3');
|
||||
|
||||
// Verify they were added to ActivityStream
|
||||
expect(mockLogInstance.log).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('should load existing then tail new entries', async () => {
|
||||
// Pre-populate log file
|
||||
fs.writeFileSync(logFile, createLogJson({ msg: 'Existing event' }) + '\n');
|
||||
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 10,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Verify existing event loaded
|
||||
expect(receivedEvents.length).toBe(1);
|
||||
expect(receivedEvents[0].msg).toBe('Existing event');
|
||||
|
||||
// Append new event
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'New event' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Verify new event was picked up
|
||||
expect(receivedEvents.length).toBe(2);
|
||||
expect(receivedEvents[1].msg).toBe('New event');
|
||||
|
||||
// Both should be in ActivityStream
|
||||
expect(mockLogInstance.log).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
it('should handle malformed JSON lines gracefully', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append malformed JSON
|
||||
fs.appendFileSync(logFile, 'not valid json\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append valid event
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Valid event' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Should skip malformed and process valid
|
||||
expect(receivedEvents.length).toBe(1);
|
||||
expect(receivedEvents[0].msg).toBe('Valid event');
|
||||
|
||||
// Only valid event should be in ActivityStream
|
||||
expect(mockLogInstance.log).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should handle empty lines gracefully', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append empty lines and valid event
|
||||
fs.appendFileSync(logFile, '\n\n\n');
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Valid event' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Should only process valid event
|
||||
expect(receivedEvents.length).toBe(1);
|
||||
expect(receivedEvents[0].msg).toBe('Valid event');
|
||||
});
|
||||
});
|
||||
|
||||
describe('cleanup', () => {
|
||||
it('should stop receiving events after tailer is stopped', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const receivedEvents: LogEvent[] = [];
|
||||
tailer.on('event', (event: LogEvent) => {
|
||||
receivedEvents.push(event);
|
||||
activityStream.addEvent(event);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append event
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'Before stop' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
expect(receivedEvents.length).toBe(1);
|
||||
|
||||
// Stop tailer
|
||||
tailer.stop();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// Append event after stop
|
||||
fs.appendFileSync(logFile, createLogJson({ msg: 'After stop' }) + '\n');
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
|
||||
// Should not receive new event
|
||||
expect(receivedEvents.length).toBe(1);
|
||||
expect(receivedEvents[0].msg).toBe('Before stop');
|
||||
});
|
||||
|
||||
it('should emit end event when stopped', async () => {
|
||||
tailer = new LogTailer({
|
||||
path: logFile,
|
||||
follow: true,
|
||||
lines: 0,
|
||||
});
|
||||
|
||||
const endPromise = new Promise<void>((resolve) => {
|
||||
tailer.on('end', resolve);
|
||||
});
|
||||
|
||||
tailer.start();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
tailer.stop();
|
||||
|
||||
await endPromise;
|
||||
expect(tailer.isActive).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
1006
src/tui/regression.test.ts
Normal file
1006
src/tui/regression.test.ts
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue