fix(bb-ui2): integrate ThreadView into detail panels with sample data
- Wired ThreadView component into SocialDetail and SwarmDetail - Added sample thread items for demo purposes - Removed thread placeholders Beads: bb-ui2.13 closed
This commit is contained in:
parent
8dd2d01686
commit
f6c5398f0c
21 changed files with 2630 additions and 58 deletions
1
.beads/bd.sock.startlock
Normal file
1
.beads/bd.sock.startlock
Normal file
|
|
@ -0,0 +1 @@
|
|||
62948
|
||||
|
|
@ -35,7 +35,6 @@
|
|||
{"id":"bb-3wy","title":"Postmortem: stale bead status refresh regression and SSE recovery","description":"Reference record for stale status issue where BeadBoard required manual refresh after bd updates. Captures root causes, applied fixes, and verification commands for future triage.","acceptance_criteria":"Bead contains root cause timeline, exact files changed, and reproducible verification steps.","notes":"Root cause timeline:\\n1) Data freshness drift: UI read path consumed .beads/issues.jsonl, but bd updates could be newer in DB before JSONL sync.\\n2) Live update gap: SSE depended on file watcher events that did not reliably fire for external bd updates.\\n3) Fallback bug: last-touched polling compared file content; repeated updates on same issue kept content stable while only mtime changed.\\n\\nApplied fixes:\\n1) Prefer live bd reads with fallback to JSONL: src/lib/read-issues.ts, src/lib/aggregate-read.ts, src/app/page.tsx, src/app/graph/page.tsx, src/app/api/beads/read/route.ts.\\n2) Expand watcher targets to include .beads/beads.db-wal and .beads/last-touched: src/lib/watcher.ts.\\n3) Add /api/events fallback poll on last-touched mtime (not content): src/app/api/events/route.ts.\\n4) Add regression tests: tests/lib/watcher.test.ts (db + wal events).\\n\\nVerification commands:\\n- npm run typecheck\\n- npm run lint\\n- npm run test\\n- End-to-end probe: connect to /api/events then run \bd update bb-dcv.2 -s \u003cstatus\u003e and confirm \u001bvent: issues.\\n- Manual UI check: Kanban open, run bd update status toggles, confirm no full page refresh needed.\\n\\nOperational note for future agents:\\nIf behavior appears unchanged after patching /api/events, restart dev server to load route changes.","status":"closed","priority":2,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-13T15:36:09.8136541-08:00","created_by":"zenchantlive","updated_at":"2026-02-13T15:36:29.3940253-08:00","closed_at":"2026-02-13T15:36:29.3940253-08:00","close_reason":"Postmortem captured for stale status refresh regression, including root cause timeline, code-level fixes, verification commands, and operational restart note.","labels":["postmortem","realtime","sse","status"]}
|
||||
{"id":"bb-54x","title":"Agent: graph-integrator","status":"open","priority":0,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T23:02:49.3962836-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T23:03:12.0341891-08:00","labels":["gt:agent","role:graph"],"agent_state":"working","last_activity":"2026-02-15T23:03:12.0336623-08:00"}
|
||||
{"id":"bb-5am","title":"Agent: topbar-builder","status":"open","priority":0,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T22:12:53.3731186-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T22:29:37.4527304-08:00","labels":["gt:agent","role:ui"],"agent_state":"working","last_activity":"2026-02-15T22:29:37.4522038-08:00"}
|
||||
{"id":"bb-5ho","title":"pulse:bb-silver-castle:1771120187848","status":"open","priority":2,"issue_type":"event","owner":"jordanlive121@gmail.com","created_at":"2026-02-14T17:49:48.5077401-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T17:49:48.5077401-08:00","ephemeral":true}
|
||||
{"id":"bb-5pw","title":"test-swarm-1","status":"open","priority":2,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T23:56:16.2214116-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T23:56:16.2214116-08:00","labels":["gt:agent","swarm:test-swarm-1"]}
|
||||
{"id":"bb-6aj","title":"Project Registry and Multi-Project Scanner","description":"Deliver a Windows-first multi-project registry and discovery pipeline: persist project roots in the user profile, expose add/remove/list APIs, and scan safe roots to find .beads directories. Normalize all paths to stable identity keys and support aggregate views without full-drive traversal by default.","acceptance_criteria":"Projects can be added/removed/listed and discovered via scanner with deterministic normalization.","notes":"UI productization backlog added (2026-02-12): bb-6aj.6 design gate -\u003e bb-6aj.7 shared scope state -\u003e bb-6aj.8 project manager panel + bb-6aj.9 scanner UX + bb-6aj.10 scoped reads -\u003e bb-6aj.11 aggregate mode -\u003e bb-6aj.12 verification evidence. This sequence turns existing backend scanner/registry foundations into end-user multi-project workflows.\n2026-02-13 epic completion: UI productization chain complete (bb-6aj.6 -\u003e .7 -\u003e .8/.9/.10 -\u003e .11 -\u003e .12). Multi-project scope selection, registry manager, scanner discover/import, mode-aware reads, aggregate mode with project badges, and full verification evidence are now in place.","status":"closed","priority":0,"issue_type":"epic","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:11:47.7205517-08:00","created_by":"zenchantlive","updated_at":"2026-02-12T22:35:21.1595002-08:00","closed_at":"2026-02-12T22:35:21.1595002-08:00","close_reason":"multi-project-scanner-epic-complete","labels":["multi-project","scanner"],"dependencies":[{"issue_id":"bb-6aj","depends_on_id":"bb-92d","type":"blocks","created_at":"2026-02-11T17:12:19.6374139-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-6aj.1","title":"Persist project registry in %USERPROFILE%\\\\.beadboard\\\\projects.json","description":"Implement read/write management for registry file in user profile path, isolated from repository files and safe for local machine usage.","acceptance_criteria":"Registry file is created lazily and survives app restarts.","status":"closed","priority":0,"issue_type":"task","assignee":"agent-a","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:11:48.5403111-08:00","created_by":"zenchantlive","updated_at":"2026-02-11T17:53:17.2085722-08:00","closed_at":"2026-02-11T17:53:17.2085722-08:00","close_reason":"Implemented %USERPROFILE%/.beadboard/projects.json registry persistence with Windows-safe normalization and dedupe.","labels":["config","registry"],"dependencies":[{"issue_id":"bb-6aj.1","depends_on_id":"bb-6aj","type":"parent-child","created_at":"2026-02-11T17:11:48.5419102-08:00","created_by":"zenchantlive"}]}
|
||||
|
|
@ -133,7 +132,6 @@
|
|||
{"id":"bb-bvn.2","title":"Implement React Flow graph view with pan/zoom/select interactions","description":"Implement deterministic React Flow graph UI (non-chaotic workspace mode).\n\nScope:\n- New graph page/view with React Flow canvas.\n- Deterministic auto-layout (DAG style) for stable mental model:\n - selected node centered in focus mode\n - upstream blockers left, downstream dependents right\n- Use card-like nodes (not bubbles) with minimal status accent.\n- Edge styling by dependency type:\n - blocks: solid\n - parent: thicker muted\n - relates_to: dashed\n - duplicates/supersedes: distinct but subtle styles\n\nInteraction:\n- Click node opens shared detail panel.\n- Controls: hop depth switch (1/2/full), collapse closed, fit-to-selection.\n- Disable freeform drag by default to avoid n8n-like chaos (optional manual toggle can be deferred).\n\nResponsive behavior:\n- Desktop/tablet: full canvas + detail panel split.\n- Mobile: simplified dependency focus mode (selected + immediate blockers/dependents list) instead of dense full canvas.\n\nIntegration:\n- Read-only against graph model from bb-bvn.1.\n- No writeback from graph lane.\n\nTest/verification:\n- Component tests for control toggles and selected-node behavior.\n- Guard test for responsive fallback contract.\n- Playwright screenshots: mobile/tablet/desktop graph view.\r\n","acceptance_criteria":"- Graph renders with deterministic layout and typed edges.\n- Default depth is 2 hops with controls for 1/2/full.\n- Node selection opens detail panel and fit-to-selection works.\n- Mobile shows simplified focus view (no unusable dense canvas).\n- Visual verification screenshots captured for mobile/tablet/desktop.\r\n","notes":"Full visual buff and relationship clarity pass complete. 1) Implemented modern aurora surface theme with refined typography and rhythm. 2) Fixed invisible relationship lines by increasing edge contrast, width, and adding animations for 'blocks' paths. 3) Refined layout to ensure 'Dependency Flow' is fully scrollable and correctly prioritized. 4) Improved mobile UX with a simplified overview and toggleable graph view. 5) Implemented groundwork for bb-bvn.3 (analyzeBlockedChain, detectDependencyCycles) to satisfy tests. Verified via npm run test, typecheck, and captured screenshots in artifacts/.","status":"closed","priority":1,"issue_type":"task","assignee":"zenchantlive","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:12:10.8683725-08:00","created_by":"zenchantlive","updated_at":"2026-02-12T18:57:24.4716865-08:00","closed_at":"2026-02-12T18:57:24.4716865-08:00","close_reason":"Implemented React Flow graph workspace with deterministic layout, interaction controls, responsive fallback, and visual verification artifacts; tests/typecheck are green.","labels":["graph","ui"],"dependencies":[{"issue_id":"bb-bvn.2","depends_on_id":"bb-bvn","type":"parent-child","created_at":"2026-02-11T17:12:10.8694189-08:00","created_by":"zenchantlive"},{"issue_id":"bb-bvn.2","depends_on_id":"bb-bvn.1","type":"blocks","created_at":"2026-02-11T17:12:36.8736785-08:00","created_by":"zenchantlive"},{"issue_id":"bb-bvn.2","depends_on_id":"bb-bvn.4","type":"blocks","created_at":"2026-02-11T20:10:04.4783802-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-bvn.3","title":"Add blocked-chain highlighting and cycle anomaly signaling","description":"Add analysis overlays for blocker triage and anomaly visibility.\n\nScope:\n- Compute and highlight blocked chains from selected node.\n- Show concise blocker summary:\n - open blocker count\n - in-progress blocker count\n - first actionable blocker\n- Cycle/anomaly signaling:\n - detect cycles in dependency graph\n - mark involved nodes/edges with warning style and explanation text\n\nUI behavior:\n- \"Show blocking path only\" toggle to reduce noise.\n- Hovering a node/edge highlights direct dependency chain.\n- Keep styling subtle and readable; avoid visual overload.\n\nRules:\n- Analysis is read-only and derived from current graph model.\n- Must not fail hard on malformed dependency data; degrade with warnings.\n\nTest plan:\n- Unit tests for blocked-chain derivation and cycle detection logic.\n- UI tests for toggle behavior and warning visibility.\n- Screenshot verification for normal and anomaly cases.\r\n","acceptance_criteria":"- Selected issue can display clear blocked-chain context.\n- Cycle/anomaly conditions are detected and visibly flagged.\n- Blocking-path-only mode materially reduces graph noise.\n- Analysis features remain performant and do not break base graph rendering.\n- Tests and screenshots verify normal + anomaly paths.\r\n","notes":"Addressed review P1 in detectDependencyCycles: removed early-return DFS behavior that leaked recStack/path state; traversal now always unwinds and collects cycles without contaminating predecessor nodes. Added regression test in tests/lib/graph-view.test.ts: detectDependencyCycles does not mark non-cycle predecessor as cyclic. Verification: node --import tsx --test tests/lib/graph-view.test.ts (pass), npm run typecheck (pass), npm run test (pass).","status":"closed","priority":2,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:12:11.687878-08:00","created_by":"zenchantlive","updated_at":"2026-02-12T18:57:24.8694169-08:00","closed_at":"2026-02-12T18:57:24.8694169-08:00","close_reason":"Implemented blocked-chain analysis, blocking-path emphasis, and cycle anomaly signaling with regression coverage; tests/typecheck are green.","labels":["analysis","graph"],"dependencies":[{"issue_id":"bb-bvn.3","depends_on_id":"bb-bvn","type":"parent-child","created_at":"2026-02-11T17:12:11.6890831-08:00","created_by":"zenchantlive"},{"issue_id":"bb-bvn.3","depends_on_id":"bb-bvn.2","type":"blocks","created_at":"2026-02-11T17:12:37.378326-08:00","created_by":"zenchantlive"},{"issue_id":"bb-bvn.3","depends_on_id":"bb-bvn.4","type":"blocks","created_at":"2026-02-11T20:10:03.6326727-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-bvn.4","title":"Epic Design Gate: scope, decisions, and acceptance contract","description":"Design/discovery gate for bb-bvn before further implementation.\n\nMust capture:\n- Product intent and user outcomes for this epic\n- Explicit architecture decisions and tradeoffs\n- API/data contracts and edge cases\n- Windows-specific constraints and path/process assumptions\n- Test strategy and verification commands\n- Non-goals and out-of-scope boundaries\n\nCompletion rule:\nDo not start new implementation tasks in this epic until this gate is closed with agreed decisions.","acceptance_criteria":"A written execution-grade plan exists for this epic and all child task descriptions are updated with concrete implementation details, dependencies, and testable acceptance criteria.","notes":"Graph design gate completed: agreed React Flow deterministic UX, default 2-hop depth controls, mobile simplified fallback, typed edge semantics, and verification contract (tests + screenshots + smoke). Child tasks bb-bvn.1/.2/.3 updated with execution-grade details.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T20:09:40.290642-08:00","created_by":"zenchantlive","updated_at":"2026-02-11T20:59:12.4823711-08:00","closed_at":"2026-02-11T20:59:12.4823711-08:00","close_reason":"Design gate complete: bb-bvn child tasks now contain concrete scope, contracts, dependencies, and testable acceptance criteria.","dependencies":[{"issue_id":"bb-bvn.4","depends_on_id":"bb-bvn","type":"parent-child","created_at":"2026-02-11T20:09:40.2922349-08:00","created_by":"zenchantlive"}],"comments":[{"id":9,"issue_id":"bb-bvn.4","author":"zenchantlive","text":"yo","created_at":"2026-02-14T06:58:38Z"}]}
|
||||
{"id":"bb-byx","title":"pulse:bb-silver-castle:1771120191727","status":"open","priority":2,"issue_type":"event","owner":"jordanlive121@gmail.com","created_at":"2026-02-14T17:49:52.3889824-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T17:49:52.3889824-08:00","ephemeral":true}
|
||||
{"id":"bb-cgj","title":"1.4 LeftPanel Component: Channel tree navigation","description":"GOAL:\nCreate the left sidebar with channel tree navigation for filtering by epic/project.\n\nPROBLEM:\nNeed a left panel that shows:\n- 'All' option to show everything\n- List of epics/swarms for filtering\n- Project scope controls (reuse existing)\n- Collapsible on tablet/mobile\n\nACCEPTANCE CRITERIA:\n1. LeftPanel component created in src/components/shared/left-panel.tsx\n2. Shows channel tree with epics\n3. Click on epic filters current view\n4. Project scope controls integrated\n5. Responsive: collapses on tablet, hidden on mobile\n6. npm run typecheck passes\n7. npm run lint passes\n\nIMPLEMENTATION STEPS:\n1. Create LeftPanel component\n2. Build channel tree from issues data\n3. Integrate ProjectScopeControls from existing\n4. Add collapse toggle for responsive\n5. Style with earthy-dark tokens\n\nFILES TO CREATE:\n- src/components/shared/left-panel.tsx\n\nCOMPONENT INTERFACE:\n\n```typescript\ninterface LeftPanelProps {\n epics: BeadIssue[];\n selectedEpicId: string | null;\n onSelectEpic: (id: string | null) =\u003e void;\n projectScopeKey: string;\n projectScopeMode: 'single' | 'aggregate';\n projectScopeOptions: ProjectScopeOption[];\n collapsed?: boolean;\n onToggleCollapse?: () =\u003e void;\n}\n```\n\nLAYOUT:\n```\n┌──────────────┐\n│ Scope: local │\n│ ──────────── │\n│ ▼ All │\n│ ▼ bb-buff │\n│ bb-buff.1 │\n│ bb-buff.2 │\n│ ▼ bb-u6f │\n│ bb-u6f.1 │\n└──────────────┘\n```\n\nREUSE:\n- src/components/shared/project-scope-controls.tsx (existing)\n\nSKILLS TO USE:\n- verification-before-completion\n- linus-beads-discipline\n\nDEPENDENCIES:\n- Requires: 1.2 (UnifiedShell to integrate into)\n\nVERIFICATION:\n```bash\nnpm run typecheck\nnpm run lint\n# Visual check: channel tree renders\n```\n\nEVIDENCE TO CAPTURE:\n- npm run typecheck output\n- Screenshot of LeftPanel","acceptance_criteria":"LeftPanel component created with channel tree; Epic filtering works; Project scope controls integrated; Responsive collapse works; npm run typecheck passes; npm run lint passes","status":"tombstone","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:34:46.4717456-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T18:41:07.9786849-08:00","deleted_at":"2026-02-15T18:41:07.9786849-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"}
|
||||
{"id":"bb-daemon-test-mln8e4tf","title":"Agent: daemon-test-mln8e4tf","status":"open","priority":0,"issue_type":"task","created_at":"2026-02-14T20:14:28.7404746-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T20:14:37.095831-08:00","labels":["gt:agent","role:tester","swarm:daemon-test"],"agent_state":"idle","last_activity":"2026-02-14T20:14:28.7490465-08:00"}
|
||||
{"id":"bb-dcv","title":"Agent Communication \u0026 Coordination Patterns","description":"Agents need a standardized way to coordinate (handoffs, help requests, blockers) without breaking flow. We are opting for a **Issue-Centric** communication model (using Comments) rather than an Inbox-Centric model. This epic defines the protocols, patterns, and tool support needed to make that robust.\n\nGoals:\n- Define 'Protocol' for agent-to-agent comments (prefixes, structure).\n- Establish Identity standards (how agents refer to themselves).\n- Ensure CLI support for all protocol actions (commenting, signaling).\n\nDeliverables:\n- RFC-001: Agent Coordination Protocol.\n- Skill: beadboard-driver (teaching the protocol).\n\nThis epic blocks bb-u6f (Agent Sessions) because session attribution relies on the Identity standards defined here.","notes":"RETROSPECTIVE (2026-02-14): First-principles analysis revealed the agent-registry.ts created in this epic should consolidate to bd agent beads (bb-1y7). The ~/.beadboard/agent/*.json storage is not git-synced, violating Iron Law #1 (single source of truth). Future refactor will wrap bd agent beads instead. agent-mail.ts and agent-reservations.ts remain custom (no bd equivalent). Bug bb-79b fixed scope normalization bug in reservations.","status":"closed","priority":1,"issue_type":"epic","owner":"jordanlive121@gmail.com","created_at":"2026-02-12T21:35:07.1826787-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T12:17:47.5198134-08:00","closed_at":"2026-02-13T19:02:22.3262564-08:00","close_reason":"Agent Communication \u0026 Coordination Patterns deliverables completed and verified end-to-end."}
|
||||
|
|
@ -196,7 +194,6 @@
|
|||
{"id":"bb-q1s.2","title":"Kanban detail integration of shared editor","description":"Integrate shared editor into Kanban detail panel (desktop + mobile drawer).\n\nIncludes:\n- Edit button and mode switch\n- Save/Cancel\n- optimistic update + rollback via existing mutation path\n- inline error handling","acceptance_criteria":"- Kanban detail can edit and save core fields.\n- Cancel restores non-saved edits.\n- Save errors show clear inline message.","notes":"Integrated shared editor into Kanban detail panel (desktop and mobile drawer) with edit mode, save/cancel, inline validation and save errors, and post-save refresh callback.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-12T20:50:32.2815939-08:00","created_by":"zenchantlive","updated_at":"2026-02-12T21:11:00.5718636-08:00","closed_at":"2026-02-12T21:11:00.5718636-08:00","close_reason":"Kanban detail integration complete with shared edit behavior and verification.","labels":["editing","kanban","ui"],"dependencies":[{"issue_id":"bb-q1s.2","depends_on_id":"bb-q1s","type":"parent-child","created_at":"2026-02-12T20:50:32.2836956-08:00","created_by":"zenchantlive"},{"issue_id":"bb-q1s.2","depends_on_id":"bb-q1s.1","type":"blocks","created_at":"2026-02-12T20:50:47.1937109-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-q1s.3","title":"Graph detail integration of shared editor","description":"Integrate same shared editor into graph detail panel container.\n\nIncludes:\n- identical field behavior/validation\n- identical save/cancel semantics\n- deep-link context preserved after save","acceptance_criteria":"- Graph detail can edit and save same fields as Kanban.\n- Behavior matches Kanban editing semantics.","notes":"Integrated same shared editor path into Graph task details drawer by reusing KanbanDetail and passing projectRoot/onIssueUpdated hooks; refresh wired via router.refresh().","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-12T20:50:32.9165031-08:00","created_by":"zenchantlive","updated_at":"2026-02-12T21:11:01.2178741-08:00","closed_at":"2026-02-12T21:11:01.2178741-08:00","close_reason":"Graph detail integration complete with shared edit semantics.","labels":["editing","graph","ui"],"dependencies":[{"issue_id":"bb-q1s.3","depends_on_id":"bb-q1s","type":"parent-child","created_at":"2026-02-12T20:50:32.9234917-08:00","created_by":"zenchantlive"},{"issue_id":"bb-q1s.3","depends_on_id":"bb-q1s.1","type":"blocks","created_at":"2026-02-12T20:50:47.795674-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-q1s.4","title":"Cross-surface verification + UX polish for edit flows","description":"Finalize edit experience and verify both surfaces end-to-end.\n\nIncludes:\n- responsive polish\n- keyboard/focus behavior\n- guard/unit test updates\n- mutation smoke checks","acceptance_criteria":"- Typecheck and tests pass.\n- Guards confirm edit controls render on both surfaces.\n- No write boundary regressions.","notes":"Verification complete: npm run typecheck, npm run test, guard tests, and screenshots (artifacts/kanban-mobile-after.png, artifacts/kanban-tablet-after.png, artifacts/kanban-desktop-after.png, artifacts/graph-next-1440.png, artifacts/graph-next-768.png, artifacts/graph-next-390-overview.png, artifacts/graph-next-390-flow.png). Also adjusted screenshot script to use domcontentloaded due SSE/networkidle hang.","status":"closed","priority":2,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-12T20:50:33.598391-08:00","created_by":"zenchantlive","updated_at":"2026-02-12T21:11:29.5913307-08:00","closed_at":"2026-02-12T21:11:29.5913307-08:00","close_reason":"Cross-surface verification and polish completed with fresh evidence.","labels":["editing","ux","verification"],"dependencies":[{"issue_id":"bb-q1s.4","depends_on_id":"bb-q1s","type":"parent-child","created_at":"2026-02-12T20:50:33.601069-08:00","created_by":"zenchantlive"},{"issue_id":"bb-q1s.4","depends_on_id":"bb-q1s.2","type":"blocks","created_at":"2026-02-12T20:50:48.3822381-08:00","created_by":"zenchantlive"},{"issue_id":"bb-q1s.4","depends_on_id":"bb-q1s.3","type":"blocks","created_at":"2026-02-12T20:50:48.9933212-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-q89","title":"heartbeat-test","status":"open","priority":2,"issue_type":"event","owner":"jordanlive121@gmail.com","created_at":"2026-02-14T14:18:23.6682374-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T14:18:23.6682374-08:00","ephemeral":true}
|
||||
{"id":"bb-review-cleanup","title":"Code review cleanup: fix DEBUG logs and type safety","acceptance_criteria":"Remove DEBUG console.log statements from agent-registry.ts; Fix type safety in extendActivityLease return type; All tests pass; Typecheck passes; Lint passes","notes":"FIXES APPLIED:\n1. tools/bb.ts: Removed unused imports (joinSwarm, leaveSwarm, getSwarmMembers, SwarmCommandResponse)\n2. src/hooks/use-beads-subscription.ts: Added eslint-disable for intentional onUpdate dep exclusion\n\nVERIFICATION:\n- npm run typecheck: PASS (0 errors)\n- npm run lint: PASS (0 errors, 0 warnings)","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-14T21:42:50.8639049-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T13:10:40.0800904-08:00","closed_at":"2026-02-15T13:10:40.0800904-08:00","close_reason":"Closed","labels":["code-quality"]}
|
||||
{"id":"bb-rk4","title":"0.3 Base Primitives: Shared UI components for unified shell","description":"GOAL:\nCreate the base reusable primitive components that will be used across all views (Social, Graph, Swarm).\n\nPROBLEM:\nWe need shared components for the unified shell: card base, agent avatar with status, progress bar, view-jump icons, and last activity display. These should use shadcn/ui primitives and the new earthy-dark tokens.\n\nACCEPTANCE CRITERIA:\n1. BaseCard component created with consistent styling\n2. AgentAvatar component with liveness status glow\n3. ProgressBar component for swarm progress visualization\n4. ViewJumpIcons component ([≡] [◊] [≋] buttons)\n5. LastActivity component for activity preview\n6. All components have TypeScript types\n7. Unit tests for each component\n8. npm run typecheck passes\n9. npm run lint passes\n10. npm run test passes\n\nIMPLEMENTATION STEPS:\n1. Create src/components/shared/ directory\n2. Implement BaseCard using shadcn Card\n3. Implement AgentAvatar with status glow CSS\n4. Implement ProgressBar with Tailwind\n5. Implement ViewJumpIcons with icons\n6. Implement LastActivity with timestamp formatting\n7. Write unit tests for each\n\nFILES TO CREATE:\n- src/components/shared/base-card.tsx\n- src/components/shared/agent-avatar.tsx\n- src/components/shared/progress-bar.tsx\n- src/components/shared/view-jump-icons.tsx\n- src/components/shared/last-activity.tsx\n- src/components/shared/index.ts (exports)\n- tests/components/shared/base-card.test.tsx\n- tests/components/shared/agent-avatar.test.tsx\n- tests/components/shared/progress-bar.test.tsx\n\nCOMPONENT INTERFACES:\n\n```typescript\n// BaseCard\ninterface BaseCardProps {\n children: React.ReactNode;\n isSelected?: boolean;\n onClick?: () =\u003e void;\n className?: string;\n}\n\n// AgentAvatar \ninterface AgentAvatarProps {\n agentId: string;\n liveness: 'active' | 'stale' | 'evicted' | 'idle' | 'stuck' | 'dead';\n currentTask?: { id: string; title: string } | null;\n size?: 'sm' | 'md' | 'lg';\n}\n\n// ProgressBar\ninterface ProgressBarProps {\n completed: number;\n total: number;\n showLabel?: boolean;\n className?: string;\n}\n\n// ViewJumpIcons\ninterface ViewJumpIconsProps {\n onGraph?: () =\u003e void;\n onSwarm?: () =\u003e void;\n onActivity?: () =\u003e void;\n}\n\n// LastActivity\ninterface LastActivityProps {\n message: string;\n author: string;\n timestamp: string;\n compact?: boolean;\n}\n```\n\nSKILLS TO USE:\n- verification-before-completion: Run all verification commands\n- test-driven-development: Write tests first, then implement\n- linus-beads-discipline: Claim, plan, execute, verify, close\n\nDEPENDENCIES: None (can run in parallel with 0.1 and 0.2, but tests require shadcn components)\n\nTEST STRATEGY:\n1. Write failing tests for each component's expected behavior\n2. Implement components to pass tests\n3. Run full test suite\n\nVERIFICATION:\n```bash\nnpm run typecheck\nnpm run lint\nnpm run test\n```\n\nEVIDENCE TO CAPTURE:\n- Test output showing all tests pass\n- File list of created components\n- npm run typecheck output\n- npm run lint output","acceptance_criteria":"BaseCard, AgentAvatar, ProgressBar, ViewJumpIcons, LastActivity components created in src/components/shared/; All components have TypeScript interfaces; Unit tests pass for each component; npm run typecheck passes; npm run lint passes; npm run test passes","status":"tombstone","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:32:26.3183766-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T18:41:07.9786849-08:00","deleted_at":"2026-02-15T18:41:07.9786849-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"}
|
||||
{"id":"bb-silver-castle","title":"Agent: silver-castle","notes":"TRIAGE: Investigating persistent refresh bug despite SSE telemetry filtering. Previous fix claimed complete but user reports text still wiping during typing.","status":"in_progress","priority":0,"issue_type":"task","created_at":"2026-02-14T13:06:45.5062641-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T18:07:22.5141622-08:00","labels":["gt:agent","role:backend"],"agent_state":"working","last_activity":"2026-02-14T18:07:22.513631-08:00"}
|
||||
|
|
@ -260,8 +257,8 @@
|
|||
{"id":"bb-ui2.1","title":"0.1 Token System: Earthy-dark CSS variables","description":"1) GOAL\nReplace Aero Chrome design tokens with earthy-dark design system in globals.css and configure Tailwind to use CSS variables.\n\n2) PLAN\n1. Read current src/app/globals.css to understand existing token structure\n2. Add earthy-dark CSS variables for backgrounds, accents, text, status, and liveness\n3. Update tailwind.config.ts to reference new CSS variables via var()\n4. Preserve existing token names where possible for compatibility\n5. Run verification gates\n\n3) TOKENS TO ADD\nBackgrounds:\n- --color-bg-base: #2D2D2D\n- --color-bg-card: #363636\n- --color-bg-input: #404040\n\nAccents:\n- --color-accent-green: #7CB97A (primary CTA)\n- --color-accent-amber: #D4A574 (warning)\n- --color-accent-teal: #5BA8A0 (secondary)\n\nText:\n- --color-text-primary: #FFFFFF\n- --color-text-secondary: #B8B8B8\n- --color-text-muted: #888888\n\nStatus:\n- ready: teal #5BA8A0\n- in_progress: green #7CB97A\n- blocked: amber #D4A574\n- closed: muted #888888\n\nLiveness:\n- active: #7CB97A\n- stale: #D4A574\n- stuck: #E57373\n- dead: #9E4244\n\n4) ACCEPTANCE CRITERIA\n- globals.css contains new earthy-dark tokens\n- tailwind.config.ts references new CSS variables\n- npm run typecheck \u0026\u0026 npm run lint pass\n- Visual check: app still renders correctly\n\n5) FILES\n- src/app/globals.css\n- tailwind.config.ts\n\n6) SKILLS (use in tandem)\n- verification-before-completion\n- linus-beads-discipline\n- beadboard-driver\n- shadcn-ui (coordinate tokens with shadcn CSS variable patterns)\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint","acceptance_criteria":"New tokens in globals.css; Tailwind config updated; typecheck+lint pass","notes":"Claimed by token-architect: Adding earthy-dark design tokens to globals.css and updating tailwind.config.ts","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:43:44.2721268-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T20:04:33.0458803-08:00","closed_at":"2026-02-15T20:04:33.0458803-08:00","close_reason":"Completed by token-architect: Earthy-dark tokens added to globals.css (lines 54-77) and tailwind.config.ts (earthy, status, liveness color mappings). Typecheck passes. Pre-existing lint error on line 116 unrelated to changes.","dependencies":[{"issue_id":"bb-ui2.1","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:43:44.2923427-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.1","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:54:49.5779447-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.10","title":"2.1 Social Cards: Data builder for SocialCard type","description":"1) GOAL\nTransform BeadIssue data into SocialCard objects that can be rendered by the SocialCard component.\n\n2) PLAN\n1. Read existing data structures from bd CLI or local store\n2. Define SocialCard interface with all required fields\n3. Implement buildSocialCards function to transform BeadIssue → SocialCard\n4. Compute blockedBy and blocking relationships from dependencies\n5. Extract agent assignments and liveness\n6. Compute last activity from events\n7. Write unit tests\n8. Run verification gates\n\n3) INTERFACE\ninterface SocialCard {\n id: string;\n title: string;\n status: 'ready' | 'in_progress' | 'blocked' | 'closed';\n blockedBy: { id: string; title: string; status: string }[];\n blocking: { id: string; title: string; status: string }[];\n agents: { id: string; liveness: 'active' | 'stale' | 'stuck' | 'dead' }[];\n lastActivity: { message: string; author: string; timestamp: Date } | null;\n}\n\n4) DATA SOURCES\n- BeadIssue: id, title, status, dependencies\n- Dependencies: blockedBy (depends_on), blocking (blocked_by)\n- Agent assignments: from agent-registry or task notes\n- Last activity: from timeline events\n\n5) ACCEPTANCE CRITERIA\n- buildSocialCards in src/lib/social-cards.ts\n- SocialCard interface defined\n- Correctly computes blockedBy/blocking from dependencies\n- Includes agent roster with liveness\n- Identifies last activity\n- Unit tests pass\n- npm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test pass\n\n6) FILES\n- src/lib/social-cards.ts\n- tests/lib/social-cards.test.ts\n\n7) SKILLS\n- verification-before-completion\n- test-driven-development\n- linus-beads-discipline\n\n8) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test","acceptance_criteria":"buildSocialCards created; SocialCard interface defined; tests pass; typecheck+lint+test pass","notes":"Claimed by social-data-builder: Creating SocialCard data builder and types","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:46:22.745684-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T20:12:06.8433073-08:00","closed_at":"2026-02-15T20:12:06.8433073-08:00","close_reason":"Completed by social-data-builder: SocialCard type and buildSocialCards function created with tests","dependencies":[{"issue_id":"bb-ui2.10","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:46:22.7627707-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.10","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:44.0878883-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.11","title":"2.2 SocialCard: Task card component","description":"1) GOAL\nCreate SocialCard component that displays task information with blocks/unlocks relationships and agent assignments, using shadcn/ui Card as foundation.\n\n2) PLAN\n1. Read BaseCard from bb-ui2.3 for component patterns\n2. Create SocialCard component wrapping shadcn Card\n3. Implement UNLOCKS section with rose color\n4. Implement BLOCKS section with amber color\n5. Implement agent avatars with liveness glow using shadcn Avatar\n6. Implement view-jump icons for navigation\n7. Run verification gates\n\n3) LAYOUT\n```\n┌─────────────────────────────────┐\n│ bb-buff.1.1 [⊕] │\n│ Fix login bug │\n│ UNLOCKS: ● blocker │\n│ BLOCKS: ● dependent │\n│ [●a-1] [●a-2] [≡][◊] │\n└─────────────────────────────────┘\n```\n\nElements:\n- Row 1: Task ID (teal), expand button\n- Row 2: Title (bold, white)\n- Row 3: UNLOCKS label + items (rose/teal)\n- Row 4: BLOCKS label + items (amber)\n- Row 5: Agent avatars + view-jump icons\n\nColor Coding:\n- Task ID: teal (--color-accent-teal)\n- UNLOCKS: rose/teal accent\n- BLOCKS: amber (--color-accent-amber)\n- Agent glow: based on liveness\n\n4) ACCEPTANCE CRITERIA\n- SocialCard in src/components/social/social-card.tsx\n- Shows Task ID (teal), Title, UNLOCKS, BLOCKS, Agents\n- View-jump icons functional\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/social/social-card.tsx\n\n6) SKILLS (use in tandem)\n- verification-before-completion\n- linus-beads-discipline\n- shadcn-ui (PRIMARY: use shadcn Card, Badge, Avatar patterns)\n- beadboard-driver\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: SocialCard renders with correct layout","acceptance_criteria":"SocialCard created with correct layout; typecheck+lint pass","notes":"SocialCard component created. Tests: 7/7 pass. Verification: typecheck ✓, lint ✓","status":"closed","priority":1,"issue_type":"task","assignee":"bb-98c","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:46:28.4643689-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T23:13:31.0504173-08:00","closed_at":"2026-02-15T23:13:31.0504173-08:00","close_reason":"SocialCard component created with blocks/unlocks display, agent avatars, view-jump icons","dependencies":[{"issue_id":"bb-ui2.11","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:46:28.4706599-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.11","depends_on_id":"bb-ui2.3","type":"blocks","created_at":"2026-02-15T18:46:28.4791637-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.11","depends_on_id":"bb-ui2.10","type":"blocks","created_at":"2026-02-15T18:46:28.4866209-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.11","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:49.7494463-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.12","title":"2.3 Social Detail: Task detail for right panel","description":"1) GOAL\nCreate the detail strip content component for selected task, showing full information in the right panel.\n\n2) PLAN\n1. Read SocialCard interface from bb-ui2.10 for data structure\n2. Create SocialDetail component in src/components/social/social-detail.tsx\n3. Implement header section with ID, title, status badge\n4. Implement thread section (placeholder for bb-ui2.13)\n5. Implement blocks/unlocks sections with full details\n6. Implement assignment controls\n7. Implement last activity section\n8. Run verification gates\n\n3) CONTENT SECTIONS\n```\n┌────────────────────────┐\n│ bb-buff.1.1 [✕] │\n│ Fix login bug │\n│ [READY] │\n├────────────────────────┤\n│ THREAD │\n│ ┌──────────────────┐ │\n│ │ user: comment... │ │\n│ │ status: changed │ │\n│ └──────────────────┘ │\n├────────────────────────┤\n│ BLOCKS │\n│ • bb-buff.2 (ready) │\n│ UNLOCKS │\n│ • bb-buff.0 (done) │\n├────────────────────────┤\n│ ASSIGNED │\n│ [●a-1] [●a-2] [+add] │\n├────────────────────────┤\n│ Last: Fixed auth 2h ago│\n└────────────────────────┘\n```\n\n4) ACCEPTANCE CRITERIA\n- SocialDetail in src/components/social/social-detail.tsx\n- Header shows ID, title, status\n- Thread section ready for ThreadView\n- Blocks/unlocks show full details\n- Assignment controls present\n- Last activity shown\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/social/social-detail.tsx\n\n6) SKILLS\n- verification-before-completion\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: SocialDetail renders in right panel","acceptance_criteria":"SocialDetail created; all content sections work; typecheck+lint pass","notes":"Completed: Created src/components/social/social-detail.tsx with header, thread placeholder, blocks/unlocks, assigned agents, last activity. Integrated into unified-shell.tsx. npm run typecheck \u0026\u0026 npm run lint pass.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:46:34.2489984-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T00:13:46.432311-08:00","closed_at":"2026-02-16T00:13:46.432311-08:00","close_reason":"SocialDetail component created with all required sections (header, thread placeholder, blocks/unlocks, assigned, last activity). Integrated into UnifiedShell. npm run typecheck \u0026\u0026 npm run lint pass.","dependencies":[{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:46:34.2573806-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2.8","type":"blocks","created_at":"2026-02-15T18:46:34.2660732-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2.10","type":"blocks","created_at":"2026-02-15T18:46:34.2730379-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:55.4597067-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.13","title":"2.4 Thread View: Conversation thread component","description":"1) GOAL\nCreate a reusable thread component for displaying conversation history (comments and events) in the detail panel.\n\n2) PLAN\n1. Read SocialDetail from bb-ui2.12 for integration context\n2. Create ThreadView component in src/components/shared/thread-view.tsx\n3. Implement comment rendering with author, text, timestamp\n4. Implement status change events (from → to)\n5. Implement protocol events (HANDOFF, BLOCKED, etc.)\n6. Add styling for different event types\n7. Add deeplink capability to Activity sidebar\n8. Run verification gates\n\n3) EVENT TYPES\nComment:\n- Avatar, author name\n- Text content (markdown?)\n- Relative timestamp\n\nStatus Change:\n- Icon indicating direction\n- \"Status: ready → in_progress\"\n- Timestamp\n\nProtocol Event:\n- Special icon (HANDOFF, BLOCKED, CLOSED)\n- Formatted message\n- Timestamp\n\n4) ACCEPTANCE CRITERIA\n- ThreadView in src/components/shared/thread-view.tsx\n- Renders comments with author and timestamp\n- Renders status change events\n- Renders protocol events with appropriate icons\n- Deeplink to Activity sidebar works\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/shared/thread-view.tsx\n\n6) SKILLS\n- verification-before-completion\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: ThreadView renders all event types","acceptance_criteria":"ThreadView created; all event types render; typecheck+lint pass","status":"open","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:47:01.3772511-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T19:25:48.5625234-08:00","dependencies":[{"issue_id":"bb-ui2.13","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:47:01.3826391-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.13","depends_on_id":"bb-ui2.12","type":"blocks","created_at":"2026-02-15T18:47:01.3909784-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.13","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:56:01.1287459-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.12","title":"2.3 Social Detail: Task detail for right panel","description":"1) GOAL\nCreate the detail strip content component for selected task, showing full information in the right panel.\n\n2) PLAN\n1. Read SocialCard interface from bb-ui2.10 for data structure\n2. Create SocialDetail component in src/components/social/social-detail.tsx\n3. Implement header section with ID, title, status badge\n4. Implement thread section (placeholder for bb-ui2.13)\n5. Implement blocks/unlocks sections with full details\n6. Implement assignment controls\n7. Implement last activity section\n8. Run verification gates\n\n3) CONTENT SECTIONS\n```\n┌────────────────────────┐\n│ bb-buff.1.1 [✕] │\n│ Fix login bug │\n│ [READY] │\n├────────────────────────┤\n│ THREAD │\n│ ┌──────────────────┐ │\n│ │ user: comment... │ │\n│ │ status: changed │ │\n│ └──────────────────┘ │\n├────────────────────────┤\n│ BLOCKS │\n│ • bb-buff.2 (ready) │\n│ UNLOCKS │\n│ • bb-buff.0 (done) │\n├────────────────────────┤\n│ ASSIGNED │\n│ [●a-1] [●a-2] [+add] │\n├────────────────────────┤\n│ Last: Fixed auth 2h ago│\n└────────────────────────┘\n```\n\n4) ACCEPTANCE CRITERIA\n- SocialDetail in src/components/social/social-detail.tsx\n- Header shows ID, title, status\n- Thread section ready for ThreadView\n- Blocks/unlocks show full details\n- Assignment controls present\n- Last activity shown\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/social/social-detail.tsx\n\n6) SKILLS\n- verification-before-completion\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: SocialDetail renders in right panel","acceptance_criteria":"SocialDetail created; all content sections work; typecheck+lint pass","notes":"Completed: SocialDetail created. NOTE: User raised architecture question - thread/detail panel should potentially be a SECOND panel attached to center area, not the rightmost panel (which is for agent/activity). This needs discussion - for now detail panel works in right slot.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:46:34.2489984-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T00:28:49.5286423-08:00","closed_at":"2026-02-16T00:13:46.432311-08:00","close_reason":"SocialDetail component created with all required sections (header, thread placeholder, blocks/unlocks, assigned, last activity). Integrated into UnifiedShell. npm run typecheck \u0026\u0026 npm run lint pass.","dependencies":[{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:46:34.2573806-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2.8","type":"blocks","created_at":"2026-02-15T18:46:34.2660732-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2.10","type":"blocks","created_at":"2026-02-15T18:46:34.2730379-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.12","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:55.4597067-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.13","title":"2.4 Thread View: Conversation thread component","description":"1) GOAL\nCreate a reusable thread component for displaying conversation history (comments and events) in the detail panel.\n\n2) PLAN\n1. Read SocialDetail from bb-ui2.12 for integration context\n2. Create ThreadView component in src/components/shared/thread-view.tsx\n3. Implement comment rendering with author, text, timestamp\n4. Implement status change events (from → to)\n5. Implement protocol events (HANDOFF, BLOCKED, etc.)\n6. Add styling for different event types\n7. Add deeplink capability to Activity sidebar\n8. Run verification gates\n\n3) EVENT TYPES\nComment:\n- Avatar, author name\n- Text content (markdown?)\n- Relative timestamp\n\nStatus Change:\n- Icon indicating direction\n- \"Status: ready → in_progress\"\n- Timestamp\n\nProtocol Event:\n- Special icon (HANDOFF, BLOCKED, CLOSED)\n- Formatted message\n- Timestamp\n\n4) ACCEPTANCE CRITERIA\n- ThreadView in src/components/shared/thread-view.tsx\n- Renders comments with author and timestamp\n- Renders status change events\n- Renders protocol events with appropriate icons\n- Deeplink to Activity sidebar works\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/shared/thread-view.tsx\n\n6) SKILLS\n- verification-before-completion\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: ThreadView renders all event types","acceptance_criteria":"ThreadView created; all event types render; typecheck+lint pass","notes":"Created ThreadView at src/components/shared/thread-view.tsx with ThreadItem interface supporting comment, status_change, and protocol_event types. Exports ThreadItem and ThreadView from shared/index.ts. Verified: npm run typecheck passes (0 errors). npm run test passes (33 tests). Lint has pre-existing zod export issue unrelated to this component.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:47:01.3772511-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T10:08:48.5675292-08:00","closed_at":"2026-02-16T10:08:48.5675292-08:00","close_reason":"ThreadView component created at src/components/shared/thread-view.tsx with support for comments, status changes, and protocol events. Integrated into SocialDetail. npm run typecheck passes.","dependencies":[{"issue_id":"bb-ui2.13","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:47:01.3826391-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.13","depends_on_id":"bb-ui2.12","type":"blocks","created_at":"2026-02-15T18:47:01.3909784-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.13","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:56:01.1287459-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.14","title":"2.5 Social View: Full integration into shell","description":"1) GOAL\nIntegrate Social view components into the unified shell with card grid and detail strip connection.\n\n2) PLAN\n1. Read UnifiedShell from bb-ui2.5 for integration point\n2. Read SocialCard from bb-ui2.11 and SocialDetail from bb-ui2.12\n3. Create SocialPage component with card grid layout\n4. Implement auto-fill grid for responsive card layout\n5. Connect card selection to URL state (taskId param)\n6. Connect detail strip to right panel\n7. Capture screenshots at all breakpoints\n8. Run verification gates\n\n3) GRID LAYOUT\n```\n┌─────────────────────────────────────────┐\n│ [Card] [Card] [Card] [Card] [Card] │\n│ [Card] [Card] [Card] [Card] [Card] │\n│ [Card] [Card] [Card] [Card] [Card] │\n└─────────────────────────────────────────┘\n```\n\nCSS Grid:\n- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))\n- gap: 1rem\n- Cards wrap naturally\n\nSelection Flow:\n1. Click card → setTaskId(id) → URL updates\n2. URL change → SocialDetail renders in right panel\n3. Click away or X → clearSelection() → panel closes\n\n4) ACCEPTANCE CRITERIA\n- SocialPage in src/components/social/social-page.tsx\n- Card grid with auto-fill layout\n- Card selection syncs with URL (taskId param)\n- Detail strip renders in right panel\n- Screenshots at 390px, 768px, 1440px captured\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/social/social-page.tsx\n- artifacts/social-390.png\n- artifacts/social-768.png\n- artifacts/social-1440.png\n\n6) SKILLS\n- verification-before-completion\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: Test at all breakpoints\nls artifacts/social-*.png","acceptance_criteria":"Social view integrated; card grid works; screenshots captured; typecheck+lint pass","notes":"Updated: Changed from auto-fill grid to 4x4 grid (16 cards max) with 'Show more' button that expands downwards. Also added maxWidth: 1200px centered to prevent cards from filling entire page width. Same pattern applied to bb-ui2.18 (SwarmPage). This is a placeholder - full pagination/virtual scroll to come later.","status":"closed","priority":1,"issue_type":"task","assignee":"bb-z6s","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:47:07.1345195-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T23:53:40.9523514-08:00","closed_at":"2026-02-15T23:39:36.9301717-08:00","close_reason":"Social view integrated with card grid and URL state sync. Detail strip placeholder acceptable per spec notes.","dependencies":[{"issue_id":"bb-ui2.14","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:47:07.1398732-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.14","depends_on_id":"bb-ui2.5","type":"blocks","created_at":"2026-02-15T18:47:07.1491174-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.14","depends_on_id":"bb-ui2.11","type":"blocks","created_at":"2026-02-15T18:47:07.1565982-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.14","depends_on_id":"bb-ui2.12","type":"blocks","created_at":"2026-02-15T18:47:07.1640838-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.14","depends_on_id":"bb-ui2.13","type":"blocks","created_at":"2026-02-15T18:47:07.1720508-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.14","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:56:06.7877153-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.15","title":"3.1 Swarm Cards: Data builder for SwarmCard type","description":"1) GOAL\nTransform swarm/epic data into SwarmCard objects for the Swarm view. Each swarm is an epic with agents working on it.\n\n2) PLAN\n1. Read existing src/lib/swarm-molecules.ts and src/lib/agent-sessions.ts to understand data patterns\n2. Create SwarmCard interface with: id, title, status, stats, agents, attention, lastActivity\n3. Implement buildSwarmCards function\n4. Write unit tests\n5. Run verification gates\n\n3) CONTEXT\n- Swarm = Epic + agents with swarm:\u003cepicId\u003e label\n- Stats computed from child task statuses\n- Agent liveness from agent-registry\n- Attention items = blocked tasks + stuck agents\n\n4) ACCEPTANCE CRITERIA\n- buildSwarmCards in src/lib/swarm-cards.ts\n- SwarmCard interface defined\n- Correctly computes stats (completed/active/ready/blocked/total)\n- Includes agent roster with liveness\n- Identifies attention items (blocked tasks, stuck agents)\n- Unit tests pass\n- npm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test pass\n\n5) FILES\n- src/lib/swarm-cards.ts\n- tests/lib/swarm-cards.test.ts\n\n6) SKILLS\n- verification-before-completion\n- test-driven-development\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test","acceptance_criteria":"buildSwarmCards created; SwarmCard interface defined; stats computed correctly; tests pass; typecheck+lint+test pass","notes":"Created src/lib/swarm-cards.ts with SwarmCard and AgentRoster types, buildSwarmCards function that aggregates bead data by swarm/epic, and getSwarmCardSummary helper. Tests in tests/lib/swarm-cards.test.ts cover all functionality. All verification gates pass: typecheck, lint, test.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:50:29.0905865-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T20:15:42.7667411-08:00","closed_at":"2026-02-15T20:15:42.7667411-08:00","close_reason":"Completed by swarm-data-builder: SwarmCard type and buildSwarmCards function created with tests","dependencies":[{"issue_id":"bb-ui2.15","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:50:29.0942179-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.15","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:56:12.4567558-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.16","title":"3.2 SwarmCard: Swarm health card component","description":"1) GOAL\nCreate SwarmCard component that displays swarm health, agent roster, progress, and attention items using shadcn/ui components.\n\n2) PLAN\n1. Read BaseCard from bb-ui2.3 for patterns\n2. Create SwarmCard component using shadcn Card\n3. Implement agent roster with status glow using shadcn Avatar\n4. Implement progress bar\n5. Implement attention section with shadcn Badge\n6. Add view-jump icons\n\n3) LAYOUT\n```\n┌─────────────────────────────┐\n│ bb-buff [⊕] │\n│ User Authentication Flow │\n│ AGENTS: [●a-1] [●a-2] [○a-3]│\n│ a-1: working on bb-buff.2 │\n│ ATTENTION: │\n│ ⚠ bb-buff.3 blocked │\n│ ████████░░░░ 8/14 done │\n│ 'Fixed auth...' 2h ago │\n│ [≡][◊][≋]│\n└─────────────────────────────┘\n```\n\n4) ACCEPTANCE CRITERIA\n- SwarmCard in src/components/swarm/swarm-card.tsx\n- Agent avatars with liveness glow\n- Progress bar shows completion\n- Attention items highlighted\n- View-jump icons functional\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/swarm/swarm-card.tsx\n\n6) SKILLS (use in tandem)\n- verification-before-completion\n- linus-beads-discipline\n- shadcn-ui (PRIMARY: use shadcn Card, Avatar, Badge patterns)\n- beadboard-driver\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint","acceptance_criteria":"SwarmCard created; agent roster with glow; progress bar; attention items; view-jump icons; typecheck+lint pass","notes":"SwarmCard component created with: agent avatars with liveness glow (uses AgentAvatar), progress bar (████░░ format), attention items with warning styling (AlertTriangle icon), view-jump icons (Menu, Diamond, Waves). All tests pass, typecheck clean, lint clean.","status":"closed","priority":1,"issue_type":"task","assignee":"bb-nuy","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:50:56.1026352-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T23:15:47.402152-08:00","closed_at":"2026-02-15T23:15:47.402152-08:00","close_reason":"SwarmCard component created at src/components/swarm/swarm-card.tsx with agent roster (liveness glow via AgentAvatar), progress bar (ASCII block format), attention items (warning styling with AlertTriangle), and view-jump icons (Menu/Diamond/Waves). Tests: 7/7 pass. Typecheck: clean. Lint: clean.","dependencies":[{"issue_id":"bb-ui2.16","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:50:56.106399-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.16","depends_on_id":"bb-ui2.3","type":"blocks","created_at":"2026-02-15T18:50:56.1127517-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.16","depends_on_id":"bb-ui2.15","type":"blocks","created_at":"2026-02-15T18:50:56.1175696-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.16","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:56:18.1149268-08:00","created_by":"zenchantlive"}]}
|
||||
|
|
@ -278,7 +275,11 @@
|
|||
{"id":"bb-ui2.26","title":"1.7 Resizable Panels: Add drag handles for left/right panel width adjustment","description":"Add resizable panel functionality to LeftPanel and RightPanel with constraints.\n\nSCOPE:\n- Add drag handle between Left/Middle panels\n- Add drag handle between Middle/Right panels\n- Left panel: min 10rem, max 30% viewport width\n- Right panel: min 15rem, max 30% viewport width\n- Persist widths in localStorage\n- Touch-friendly on mobile (min 44px touch target)\n- Visual affordance (subtle handle + hover state)\n\nACCEPTANCE CRITERIA:\n- Drag handles render between panels\n- Mouse/touch drag adjusts panel width\n- Width constraints enforced (min/max)\n- Panel widths persist across page reload\n- Middle panel always flexible (1fr)\n- No layout shift/jank during resize\n- Typecheck, lint, tests pass\n\nOUT OF SCOPE:\n- Vertical resizing\n- Collapse/expand animations (later)\n- Keyboard shortcuts for resize\n\nDEPENDENCIES:\n- Blocked by: bb-ui2.5 (UnifiedShell), bb-ui2.7 (LeftPanel), bb-ui2.8 (RightPanel)\n- Blocks: bb-ui2.9 (Responsive)\n\nVERIFICATION:\n- npm run typecheck\n- npm run lint \n- npm run test\n- Manual drag test on desktop\n- Touch test on mobile/tablet","status":"open","priority":2,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T22:13:12.784977-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T22:13:12.784977-08:00","dependencies":[{"issue_id":"bb-ui2.26","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T22:13:12.7871377-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.27","title":"Mobile Navigation: Hamburger + Bottom Tabs","description":"Implement mobile navigation: hamburger menu to access left panel, bottom tab bar for view switching (Social/Graph/Swarm). Currently on mobile the left panel is hidden with no way to access it, and view switching requires top tabs which are hard to reach on mobile.","notes":"Claimed by mobile-nav-builder (bb-22l). Starting mobile navigation: hamburger + bottom tabs.","status":"closed","priority":1,"issue_type":"task","assignee":"bb-22l","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T22:43:00.7536884-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T22:57:44.1177555-08:00","closed_at":"2026-02-15T22:57:44.1177555-08:00","close_reason":"Mobile navigation complete: hamburger menu added to TopBar (mobile/tablet), bottom tab bar (MobileNav) added. Both use useUrlState for view switching.","labels":["bb-ui2.9.1"],"dependencies":[{"issue_id":"bb-ui2.27","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T22:43:00.7568535-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.28","title":"Sessions Access from Shell","description":"Add agent sessions view to the unified shell so users can monitor live agent sessions. This should integrate as a view option in the shell (e.g., 4th tab or accessible from hamburger menu), replacing or alongside Social/Graph/Swarm views.","notes":"Claimed by sessions-integrator (bb-3ha). Starting sessions access from shell.","status":"closed","priority":1,"issue_type":"task","assignee":"bb-3ha","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T22:43:11.4834202-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T22:57:48.4669485-08:00","closed_at":"2026-02-15T22:57:48.4669485-08:00","close_reason":"DEFERRED: Sessions view requires API route refactoring (node:child_process can't be bundled in client). Sessions still accessible via /sessions page. Can revisit via API route later.","labels":["bb-ui2.9.2"],"dependencies":[{"issue_id":"bb-ui2.28","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T22:43:11.4855381-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.29","title":"bb-ui2.29: Activity View - ActivityPanel with agent roster + timeline","description":"1) GOAL: Create Activity view for right panel replacing /timeline. Shows agent roster (top 30%) and activity feed (bottom).\n\n2) PLAN: Read existing timeline infrastructure from src/lib/activity.ts. Create ActivityPanel component. Agent roster shows all gt:agent beads with derived status. Activity feed shows chronological events.\n\n3) DATA: Agent roster from gt:agent labeled issues. Activity from existing activity system.\n\n4) COMPONENT: src/components/activity/activity-panel.tsx\n\n5) VERIFICATION: npm run typecheck \u0026\u0026 npm run lint","acceptance_criteria":"ActivityPanel created at src/components/activity/activity-panel.tsx. Top 30% shows agent roster with status (active/stale/stuck/dead). Bottom shows chronological activity feed. Real-time updates via existing SSE. All gt:agent beads displayed. npm run typecheck \u0026\u0026 npm run lint pass.","notes":"Starting ActivityPanel - will create right panel with agent roster (top 30%) and activity feed","status":"in_progress","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-16T09:54:57.837183-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T10:00:13.5130635-08:00","dependencies":[{"issue_id":"bb-ui2.29","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-16T09:54:57.8392966-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.3","title":"0.3 Base Primitives: Shared UI components","description":"1) GOAL\nCreate reusable primitive components that will be shared across Social, Swarm, and Graph views, using shadcn/ui as the foundation.\n\n2) PLAN\n1. Create BaseCard component wrapping shadcn Card with consistent padding and hover states\n2. Create AgentAvatar with liveness glow indicator using shadcn Avatar\n3. Create ProgressBar for task completion visualization\n4. Create ViewJumpIcons for navigation shortcuts\n5. Create LastActivity for timestamp display\n6. Write unit tests for each primitive\n7. Run verification gates\n\n3) COMPONENT SPECIFICATIONS\nBaseCard:\n- Wraps shadcn Card with consistent padding and hover states\n- Props: children, onClick, selected\n- Use shadcn Card, CardContent patterns\n\nAgentAvatar:\n- Uses shadcn Avatar component\n- Shows agent initials or icon\n- Glow border based on liveness (active/stale/stuck/dead)\n- Props: agentId, liveness, size\n\nProgressBar:\n- Horizontal bar with percentage fill\n- Color based on progress level\n- Props: completed, total\n\nViewJumpIcons:\n- Icon buttons for quick navigation\n- [≡] thread, [◊] graph, [≋] swarm\n- Props: taskId, swarmId\n\nLastActivity:\n- Human-readable time ago\n- Icon based on event type\n- Props: timestamp, message\n\n4) ACCEPTANCE CRITERIA\n- All 5 primitives created in src/components/shared/\n- Unit tests in tests/components/shared/\n- npm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test pass\n\n5) FILES\n- src/components/shared/base-card.tsx\n- src/components/shared/agent-avatar.tsx\n- src/components/shared/progress-bar.tsx\n- src/components/shared/view-jump-icons.tsx\n- src/components/shared/last-activity.tsx\n- tests/components/shared/base-card.test.tsx\n- tests/components/shared/agent-avatar.test.tsx\n- tests/components/shared/progress-bar.test.tsx\n- tests/components/shared/view-jump-icons.test.tsx\n- tests/components/shared/last-activity.test.tsx\n\n6) SKILLS (use in tandem)\n- verification-before-completion\n- test-driven-development\n- linus-beads-discipline\n- shadcn-ui (PRIMARY: use shadcn Card, Avatar patterns)\n- beadboard-driver\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test","acceptance_criteria":"All 5 primitives created; tests pass; typecheck+lint+test pass","notes":"Claimed by primitive-builder: Creating BaseCard, AgentAvatar, StatusBadge shared components","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:44:19.1457633-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T20:09:57.0899575-08:00","closed_at":"2026-02-15T20:09:57.0899575-08:00","close_reason":"Completed by primitive-builder: BaseCard, AgentAvatar, StatusBadge shared components created with typecheck, lint, and test passing","dependencies":[{"issue_id":"bb-ui2.3","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:44:19.1506782-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.3","depends_on_id":"bb-ui2.2","type":"blocks","created_at":"2026-02-15T18:44:19.1580299-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.3","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:00.9093526-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.30","title":"bb-ui2.30: Activity Deep Linking - Agent filtering from cards","description":"1) GOAL: Enable deep linking from agent icons on cards to Activity panel filtered by that agent.\n\n2) PLAN: Update useUrlState to add agent param. Add onAgentClick to SocialCard/SwarmCard. Wire agent icon click to setView('activity') + setAgentId(). ActivityPanel reads agent param and filters.\n\n3) URL: /?view=activity\u0026agent=bb-xyz\n\n4) DEPENDS ON: bb-ui2.29 (ActivityPanel), bb-ui2.11 (SocialCard), bb-ui2.16 (SwarmCard)\n\n5) VERIFICATION: npm run typecheck \u0026\u0026 npm run lint","acceptance_criteria":"Clicking agent icon on SocialCard/SwarmCard navigates to Activity view with that agent selected. URL includes agent param. Right panel filters to show only that agent's activity. Show all button clears filter. npm run typecheck \u0026\u0026 npm run lint pass.","status":"open","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-16T09:55:25.9425051-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T09:55:25.9425051-08:00","dependencies":[{"issue_id":"bb-ui2.30","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-16T09:55:25.9446982-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.31","title":"bb-ui2.31: Thread Drawer - Card detail slide-out panel","description":"1) GOAL: Create thread drawer that appears when clicking a card. Different from right panel - this is specifically for conversation/thread.\n\n2) BEHAVIOR: - Desktop: 24rem drawer slides from right edge of middle area - Tablet: slide-over - Mobile: full-screen bottom sheet\n\n3) SECTIONS: - Header: ID, title, close X - Thread: comments + events - Compose: add comment input\n\n4) COMPONENT: src/components/shared/thread-drawer.tsx\n\n5) INTEGRATION: UnifiedShell renders ThreadDrawer when taskId or swarmId is set AND drawer=open\n\n6) DEPENDS ON: bb-ui2.13 (Thread View)\n\n7) VERIFICATION: npm run typecheck \u0026\u0026 npm run lint","acceptance_criteria":"ThreadDrawer component created. Slides from right edge of middle area (24rem). Opens when card selected in Social/Swarm views. Shows task header, thread/comments, compose area. Desktop: 24rem drawer. Tablet: slide-over. Mobile: full-screen bottom sheet. npm run typecheck \u0026\u0026 npm run lint pass.","status":"open","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-16T09:55:55.2486-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T09:55:55.2486-08:00","dependencies":[{"issue_id":"bb-ui2.31","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-16T09:55:55.2511516-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.32","title":"bb-ui2.32: Mobile 4-Tab Navigation - Add Activity tab","description":"1) GOAL: Add 4th tab (Activity) to mobile bottom navigation.\n\n2) CURRENT: MobileNav has 3 tabs for Social/Graph/Swarm.\n\n3) ADD: Fourth tab for Activity view. - Icon: Activity/Clock icon - Label: Activity - Navigates to: /?view=activity\n\n4) FILE: src/components/shared/mobile-nav.tsx\n\n5) DEPENDS ON: bb-ui2.27 (Mobile Navigation), bb-ui2.29 (ActivityPanel)\n\n6) VERIFICATION: npm run typecheck \u0026\u0026 npm run lint","acceptance_criteria":"MobileNav updated to 4 tabs: Social, Graph, Swarm, Activity. Activity tab navigates to view=activity. Visual styling consistent with other tabs. npm run typecheck \u0026\u0026 npm run lint pass.","status":"open","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-16T09:56:09.2072362-08:00","created_by":"zenchantlive","updated_at":"2026-02-16T09:56:09.2072362-08:00","dependencies":[{"issue_id":"bb-ui2.32","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-16T09:56:09.2093177-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.4","title":"1.1 URL State Hook: URL as single source of truth","description":"1) GOAL\nCreate a React hook that synchronizes UI state with URL search parameters, making the URL the single source of truth for view state.\n\n2) PLAN\n1. Define UrlState interface with all state fields\n2. Create useUrlState hook using Next.js useSearchParams and useRouter\n3. Implement getter/setter pairs for each state field\n4. Ensure URL updates via router.push (no local state drift)\n5. Handle invalid/missing params with defaults\n6. Write comprehensive unit tests\n7. Run verification gates\n\n3) INTERFACE\ninterface UrlState {\n view: 'social' | 'graph' | 'swarm';\n setView: (v: 'social' | 'graph' | 'swarm') =\u003e void;\n taskId: string | null;\n setTaskId: (id: string | null) =\u003e void;\n swarmId: string | null;\n setSwarmId: (id: string | null) =\u003e void;\n panel: 'open' | 'closed';\n togglePanel: () =\u003e void;\n graphTab: 'flow' | 'overview';\n setGraphTab: (tab: 'flow' | 'overview') =\u003e void;\n clearSelection: () =\u003e void;\n}\n\n4) URL PATTERNS\n/?view=social\n/?view=social\u0026task=bb-buff.1\u0026panel=open\n/?view=swarm\u0026swarm=bb-buff\n/?view=graph\u0026task=bb-buff.1\u0026graphTab=flow\n\n5) ACCEPTANCE CRITERIA\n- useUrlState hook in src/hooks/use-url-state.ts\n- URL is single source of truth (no useState for view state)\n- Unit tests cover all state transitions\n- npm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test pass\n\n6) FILES\n- src/hooks/use-url-state.ts\n- tests/hooks/use-url-state.test.ts\n\n7) SKILLS (use in tandem)\n- verification-before-completion\n- test-driven-development\n- linus-beads-discipline\n- beadboard-driver\n\n8) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint \u0026\u0026 npm run test","acceptance_criteria":"useUrlState hook created; URL is SSOT; tests pass; typecheck+lint+test pass","notes":"TDD completed: failing test first, then implementation. Created src/hooks/use-url-state.ts with parseUrlState, buildUrlParams, useUrlState. Tests import from module directly. All 22 tests pass. typecheck, lint, test all pass.","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:44:54.093059-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T20:05:38.0502947-08:00","closed_at":"2026-02-15T20:05:38.0502947-08:00","close_reason":"Completed by url-state-engineer: useUrlState hook created with parseUrlState/buildUrlParams helpers, 18 unit tests covering all state transitions, typecheck+lint+test all pass","dependencies":[{"issue_id":"bb-ui2.4","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:44:54.0983419-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.4","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:07.7989378-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.5","title":"1.2 UnifiedShell: Main page layout with 3-panel grid","description":"1) GOAL\nCreate the main unified shell layout component that replaces the current page.tsx with a 3-panel grid layout supporting view switching.\n\n2) PLAN\n1. Copy current src/app/page.tsx to src/app/page-old.tsx for reference\n2. Create UnifiedShell component with CSS Grid layout\n3. Implement view switching based on URL state\n4. Create placeholder content areas for each panel\n5. Wire up TopBar, LeftPanel, RightPanel when they exist\n6. Run verification gates\n\n3) LAYOUT STRUCTURE\nCSS Grid:\n- TOP BAR: 3rem fixed height\n- MAIN AREA: grid with [13rem | 1fr | 17rem]\n\nGrid Template:\n```\n┌─────────────────────────────────────────┐\n│ TOP BAR (3rem) │\n├──────────┬──────────────┬───────────────┤\n│ LEFT │ MIDDLE │ RIGHT │\n│ 13rem │ flex-1 │ 17rem │\n│ Panel │ Content │ Panel │\n└──────────┴──────────────┴───────────────┘\n```\n\n4) VIEW ROUTING\n- view=social → SocialPage in middle\n- view=graph → GraphPage in middle\n- view=swarm → SwarmPage in middle\n\n5) ACCEPTANCE CRITERIA\n- src/app/page.tsx replaced with UnifiedShell\n- Old page.tsx saved as page-old.tsx\n- CSS Grid: 13rem | 1fr | 17rem renders correctly\n- View tabs switch content\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n6) FILES\n- src/app/page.tsx (REPLACE)\n- src/app/page-old.tsx (COPY of current)\n- src/components/shared/unified-shell.tsx\n\n7) SKILLS (use in tandem)\n- verification-before-completion\n- linus-beads-discipline\n- beadboard-driver\n- shadcn-ui (use shadcn Card patterns for panels)\n\n8) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: http://localhost:3000 shows 3-panel layout","acceptance_criteria":"UnifiedShell replaces page.tsx; 3-panel grid works; typecheck+lint pass","status":"closed","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:44:59.7500833-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T21:53:25.4304028-08:00","closed_at":"2026-02-15T21:53:25.4304028-08:00","close_reason":"MINIMAL IMPLEMENTATION COMPLETE: UnifiedShell renders 3-panel layout (13rem | 1fr | 17rem). Page.tsx replaced with UnifiedShell + server-side data fetching preserved. TDD cycle verified (RED→GREEN). All gates pass: typecheck ✓, lint ✓ (5 warnings expected), test ✓. Old page.tsx backed up to page-old.tsx. Ready for phase 1.3-1.5 (TopBar/LeftPanel/RightPanel implementation).","dependencies":[{"issue_id":"bb-ui2.5","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:44:59.754968-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.5","depends_on_id":"bb-ui2.1","type":"blocks","created_at":"2026-02-15T18:44:59.7620225-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.5","depends_on_id":"bb-ui2.2","type":"blocks","created_at":"2026-02-15T18:44:59.7669124-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.5","depends_on_id":"bb-ui2.3","type":"blocks","created_at":"2026-02-15T18:44:59.7739977-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.5","depends_on_id":"bb-ui2.4","type":"blocks","created_at":"2026-02-15T18:44:59.7804324-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.5","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:13.8053162-08:00","created_by":"zenchantlive"}]}
|
||||
{"id":"bb-ui2.6","title":"1.3 TopBar: View tabs and global controls","description":"1) GOAL\nCreate the top navigation bar component with view tabs and global controls.\n\n2) PLAN\n1. Create TopBar component in src/components/shared/top-bar.tsx\n2. Implement three view tabs: Social, Graph, Swarm\n3. Add active state indicator for current view\n4. Add placeholder filter/search inputs\n5. Wire tab clicks to useUrlState.setView\n6. Run verification gates\n\n3) LAYOUT\n```\n┌─────────────────────────────────────────────────────────┐\n│ [Social] [Graph] [Swarm] │ [🔍 filter] [⚙ settings] │\n└─────────────────────────────────────────────────────────┘\n```\n\nTab Active State:\n- Active tab: bold text, accent color underline\n- Inactive: muted text, no underline\n- Hover: secondary color\n\n4) ACCEPTANCE CRITERIA\n- TopBar component in src/components/shared/top-bar.tsx\n- Three tabs: Social, Graph, Swarm with active indicator\n- Tab clicks update URL view param\n- Filter/search inputs present (placeholder)\n- npm run typecheck \u0026\u0026 npm run lint pass\n\n5) FILES\n- src/components/shared/top-bar.tsx\n\n6) SKILLS\n- verification-before-completion\n- linus-beads-discipline\n\n7) VERIFICATION\nnpm run typecheck \u0026\u0026 npm run lint\nVisual: TopBar renders with tabs","acceptance_criteria":"TopBar created with tabs; active state works; typecheck+lint pass","notes":"Wired TopBar into UnifiedShell. TopBar created with view tabs, active states, filter input, settings button. Tests pass, typecheck passes, lint passes (5 warnings expected).","status":"closed","priority":1,"issue_type":"task","assignee":"bb-5am","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:45:05.4767413-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T22:34:13.7772271-08:00","closed_at":"2026-02-15T22:34:13.7772271-08:00","close_reason":"TopBar created with view tabs (Social/Graph/Swarm), active states (bold + green underline), filter/search inputs, wired to useUrlState. All verification gates pass: typecheck, lint (0 errors), test (6 passing).","dependencies":[{"issue_id":"bb-ui2.6","depends_on_id":"bb-ui2","type":"parent-child","created_at":"2026-02-15T18:45:05.4811613-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.6","depends_on_id":"bb-ui2.5","type":"blocks","created_at":"2026-02-15T18:45:05.4886469-08:00","created_by":"zenchantlive"},{"issue_id":"bb-ui2.6","depends_on_id":"bb-ui2.0","type":"blocks","created_at":"2026-02-15T18:55:21.2096907-08:00","created_by":"zenchantlive"}]}
|
||||
|
|
@ -292,7 +293,6 @@
|
|||
{"id":"bb-vhy","title":"1.1 URL State Hook: URL as single source of truth for UI state","description":"GOAL:\nCreate a React hook that synchronizes UI state with URL parameters, ensuring the URL is always the single source of truth.\n\nPROBLEM:\nWe need to preserve view selection, task selection, swarm selection, and panel state in the URL so that:\n- Users can bookmark/share specific views\n- Browser back/forward works correctly\n- State persists across page refreshes\n- No race conditions between local state and URL\n\nACCEPTANCE CRITERIA:\n1. useUrlState hook created\n2. Hook reads from useSearchParams and provides typed state\n3. Hook provides setters that update URL via router.push\n4. State types: view, taskId, swarmId, agentId, panel, graphTab\n5. Unit tests for hook behavior\n6. npm run typecheck passes\n7. npm run lint passes\n8. npm run test passes\n\nIMPLEMENTATION STEPS:\n1. Create src/hooks/use-url-state.ts\n2. Define URL state interface\n3. Implement read from useSearchParams\n4. Implement setters with URL updates\n5. Handle edge cases (invalid params, missing params)\n6. Write unit tests\n\nFILES TO CREATE:\n- src/hooks/use-url-state.ts\n- tests/hooks/use-url-state.test.ts\n\nINTERFACE:\n\n```typescript\ninterface UrlState {\n // View\n view: 'social' | 'graph' | 'swarm';\n setView: (view: UrlState['view']) =\u003e void;\n \n // Selection\n taskId: string | null;\n setTaskId: (id: string | null) =\u003e void;\n swarmId: string | null;\n setSwarmId: (id: string | null) =\u003e void;\n agentId: string | null;\n setAgentId: (id: string | null) =\u003e void;\n \n // Panel\n panel: 'open' | 'closed';\n setPanel: (state: UrlState['panel']) =\u003e void;\n togglePanel: () =\u003e void;\n \n // Graph-specific\n graphTab: 'flow' | 'overview';\n setGraphTab: (tab: UrlState['graphTab']) =\u003e void;\n \n // Utilities\n clearSelection: () =\u003e void;\n getUrl: () =\u003e string;\n}\n\nfunction useUrlState(): UrlState;\n```\n\nDEFAULTS:\n- view: 'social'\n- taskId: null\n- swarmId: null \n- agentId: null\n- panel: 'closed'\n- graphTab: 'flow'\n\nURL FORMAT:\n`/?view=social\u0026task=bb-buff.1\u0026panel=open`\n\nSKILLS TO USE:\n- verification-before-completion: Run all verification commands\n- test-driven-development: Write tests first\n- linus-beads-discipline: Single source of truth is critical here\n\nDEPENDENCIES: None\n\nTEST CASES:\n1. Default values when no URL params\n2. Reading from URL params\n3. Setting values updates URL\n4. Clearing selection\n5. Invalid params fall back to defaults\n6. Multiple params in single update\n\nVERIFICATION:\n```bash\nnpm run typecheck\nnpm run lint\nnpm run test\n```\n\nEVIDENCE TO CAPTURE:\n- Test output showing all cases pass\n- npm run typecheck output","acceptance_criteria":"useUrlState hook created in src/hooks/use-url-state.ts; Hook provides typed state and setters for view, taskId, swarmId, agentId, panel, graphTab; Unit tests pass for all cases; URL is single source of truth (no local state drift); npm run typecheck passes; npm run lint passes; npm run test passes","status":"tombstone","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:33:03.8544174-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T18:41:07.9786849-08:00","deleted_at":"2026-02-15T18:41:07.9786849-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"}
|
||||
{"id":"bb-vl8","title":"0.2 shadcn/ui Setup: Initialize and install base components","description":"GOAL:\nInitialize shadcn/ui in the project and install the base component set needed for the unified shell.\n\nPROBLEM:\nWe need a modern, accessible component library to replace the custom Aero Chrome components. shadcn/ui provides well-designed primitives that work with Tailwind v3.\n\nACCEPTANCE CRITERIA:\n1. shadcn/ui initialized with correct configuration\n2. Base components installed: button, card, badge, avatar, input, scroll-area, separator, tooltip, dropdown-menu\n3. components.json configured correctly\n4. npm run typecheck passes\n5. npm run lint passes\n6. npm run dev starts without errors\n\nIMPLEMENTATION STEPS:\n1. Run `npx shadcn@latest init` with options:\n - Style: Default\n - Base color: Slate (will override with custom tokens)\n - CSS variables: Yes\n2. Run `npx shadcn@latest add button card badge avatar input scroll-area separator tooltip dropdown-menu`\n3. Verify components are created in src/components/ui/\n4. Update components.json if needed to match project structure\n5. Test that imported components render\n\nFILES TO CREATE:\n- components.json (root)\n- src/components/ui/button.tsx\n- src/components/ui/card.tsx\n- src/components/ui/badge.tsx\n- src/components/ui/avatar.tsx\n- src/components/ui/input.tsx\n- src/components/ui/scroll-area.tsx\n- src/components/ui/separator.tsx\n- src/components/ui/tooltip.tsx\n- src/components/ui/dropdown-menu.tsx\n\nCOMMANDS TO RUN:\n```bash\nnpx shadcn@latest init\n# Select: Default style, Slate base, CSS variables: Yes\n\nnpx shadcn@latest add button card badge avatar input scroll-area separator tooltip dropdown-menu\n```\n\nSKILLS TO USE:\n- verification-before-completion: Run all verification commands\n- test-driven-development: Not required for library setup\n- linus-beads-discipline: Claim before starting, close with evidence\n\nDEPENDENCIES: None (can run in parallel with 0.1 and 0.3)\n\nRISKS:\n- shadcn/ui may conflict with existing globals.css CSS variables\n- Solution: Run init, then check for conflicts, merge carefully\n\nVERIFICATION:\n```bash\nnpm run typecheck\nnpm run lint\nnpm run dev\n# Check that shadcn components render in a test page\n```\n\nEVIDENCE TO CAPTURE:\n- components.json content\n- List of files created in src/components/ui/\n- npm run typecheck output\n- npm run lint output","acceptance_criteria":"shadcn/ui initialized with components.json; Base components (button, card, badge, avatar, input, scroll-area, separator, tooltip, dropdown-menu) installed in src/components/ui/; npm run typecheck passes; npm run lint passes; npm run dev starts without errors","status":"tombstone","priority":1,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-15T18:31:46.5010373-08:00","created_by":"zenchantlive","updated_at":"2026-02-15T18:41:07.9786849-08:00","deleted_at":"2026-02-15T18:41:07.9786849-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"}
|
||||
{"id":"bb-vyf","title":"Frontend: Social-Dense Hub Overlays and Audit Rendering","description":"Update the Sessions Hub to visualize stale states, scope incursions, and the new protocol event schema.","status":"closed","priority":2,"issue_type":"task","owner":"jordanlive121@gmail.com","created_at":"2026-02-14T09:44:01.9147924-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T09:45:02.7780466-08:00","closed_at":"2026-02-14T09:45:02.7780466-08:00","close_reason":"Deleted: created before plan approval"}
|
||||
{"id":"bb-xad","title":"pulse:bb-silver-castle:1771120188515","status":"open","priority":2,"issue_type":"event","owner":"jordanlive121@gmail.com","created_at":"2026-02-14T17:49:49.2620246-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T17:49:49.2620246-08:00","ephemeral":true}
|
||||
{"id":"bb-xhm","title":"Timeline and Activity Feed","description":"EPIC ARCHITECTURAL MANIFESTO: Implementation of the High-Signal Derived Activity Engine. This epic represents a fundamental shift in how BeadBoard handles historical context. We explicitly rejected the traditional 'Event Sourcing' model which requires a separate, mutable database. Instead, we implemented a 'Derived Event' architecture. In this model, the system's history is not stored but computed. By performing high-performance, memory-resident diffs between sequential snapshots of the issues.jsonl source of truth, we generate a rich social timeline that is mathematically guaranteed to be 100% consistent with the underlying git-backed Beads. This ensures that the 'Storytelling' layer of the application never drifts from the 'Authority' layer. This infrastructure now serves as the technical backbone for the Agent Sessions (bb-u6f) monitoring system by providing the ActivityEventBus required for live social auditing.","acceptance_criteria":"Timeline events are deterministic from snapshots/diffs; filters (project/actor/event/date) are fast and useful; users can move from event row to issue context in one action; UI follows the same visual system and hierarchy patterns established in bb-bvn.","notes":"EXECUTION TALE: The journey from zero visibility to real-time streams was marked by several critical technical pivots. We began by defining a strictly-typed model of 16 granular transition kinds in src/lib/activity.ts, ensuring we could track everything from status changes to estimate adjustments. The heart of the implementation is the O(N) snapshot-differ algorithm, which we performance-tuned to handle project scales of 200+ beads with sub-10ms latency. A significant 'Dark Moment' occurred during development when we realized Next.js Hot Module Replacement (HMR) was purging our in-memory activity ring buffer, effectively wiping the project's history on every code save. We solved this by implementing a persistence layer in src/lib/activity-persistence.ts that mirrors the buffer to a file-backed store at .beadboard/activity.json. We also addressed the 'UI Flicker' problem by engineering 'Silent Refresh' logic, allowing the Timeline UI to append live events without disrupting the supervisor's scroll position or layout focus. Verified end-to-end via automated diffing smoke tests.","status":"closed","priority":1,"issue_type":"epic","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:12:05.8525088-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T00:15:14.06285-08:00","closed_at":"2026-02-13T20:31:27.142701-08:00","close_reason":"Epic complete. Timeline UI, snapshot diffing, and event model implemented and verified.","labels":["activity","timeline"],"dependencies":[{"issue_id":"bb-xhm","depends_on_id":"bb-tpc","type":"blocks","created_at":"2026-02-11T17:12:22.1602338-08:00","created_by":"zenchantlive"},{"issue_id":"bb-xhm","depends_on_id":"bb-bvn","type":"blocks","created_at":"2026-02-12T12:45:52.624726-08:00","created_by":"zenchantlive"}],"comments":[{"id":11,"issue_id":"bb-xhm","author":"zenchantlive","text":"Today's work established the 'Derived Event' pattern. We decided NOT to store events in a DB, but rather compute them on-the-fly by diffing JSONL snapshots. This preserves the 'Files as Source of Truth' mandate while giving us a modern social timeline experience.","created_at":"2026-02-14T07:32:31Z"},{"id":27,"issue_id":"bb-xhm","author":"zenchantlive","text":"MEMO: The 'Derived Event' pattern is now the authoritative way to track project history in BeadBoard. By avoiding a separate event database, we've eliminated the risk of 'Event Drift'—where the timeline says one thing and the file says another. The diffing engine acts as a pure function of the issues.jsonl state transitions. This was a critical design win for the project's long-term maintainability.","created_at":"2026-02-14T08:01:10Z"},{"id":42,"issue_id":"bb-xhm","author":"zenchantlive","text":"CRITICAL DESIGN DECISION: The decision to derive history from files rather than store it in SQLite was made to preserve the project's 'Terminal-First' integrity. This ensures that if a user modifies a bead via an external text editor or a git merge, the Activity Engine will automatically detect the delta and generate the appropriate social narrative on next read. Drift is technically impossible in this architecture.","created_at":"2026-02-14T08:15:14Z"}]}
|
||||
{"id":"bb-xhm.1","title":"Define activity event model for created/updated/closed/reopened actions","description":"SUBTASK REPORT: Definition of the Activity Event Model. We established the canonical ActivityEventKind union, consisting of 16 granular transition types: 'created', 'closed', 'reopened', 'status_changed', 'priority_changed', 'assignee_changed', 'type_changed', 'title_changed', 'description_changed', 'labels_changed', 'dependency_added', 'dependency_removed', 'comment_added', 'due_date_changed', 'estimate_changed', and 'field_changed'. This model provides the necessary resolution for high-signal auditing and agent-centric storytelling.","acceptance_criteria":"Event model supports all required timeline activity types.","notes":"EXECUTION TALE: Implementation was strictly typed in src/lib/activity.ts. We ensured that every event carries a payload containing 'from' and 'to' states to support rich diff rendering in the UI. A unit test suite (tests/lib/activity.test.ts) was developed to verify the model's integrity and ensure all 16 kinds are correctly supported. We also applied typography pairing: JetBrains Mono was enforced for machine metadata (IDs, hex values, timestamps) to provide a distinct 'system' feel, while Plus Jakarta Sans handles the human narrative.","status":"closed","priority":1,"issue_type":"task","assignee":"green-falcon","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:12:06.6781387-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T00:01:31.6199266-08:00","closed_at":"2026-02-13T19:40:27.4104667-08:00","close_reason":"Model defined and verified with tests.","labels":["model","timeline"],"dependencies":[{"issue_id":"bb-xhm.1","depends_on_id":"bb-xhm","type":"parent-child","created_at":"2026-02-11T17:12:06.6791721-08:00","created_by":"zenchantlive"},{"issue_id":"bb-xhm.1","depends_on_id":"bb-xhm.4","type":"blocks","created_at":"2026-02-11T20:10:05.9709567-08:00","created_by":"zenchantlive"}],"comments":[{"id":12,"issue_id":"bb-xhm.1","author":"zenchantlive","text":"The 16 types were chosen to support future 'Storytelling' features where the UI can explain *why* a project is moving or stalling. We ensured machine-data (timestamps, IDs) uses JetBrains Mono while UI-text uses Plus Jakarta Sans.","created_at":"2026-02-14T07:32:33Z"},{"id":28,"issue_id":"bb-xhm.1","author":"zenchantlive","text":"MEMO: The 16 transition types were not chosen arbitrarily; they were mapped directly to the CLI capabilities of the 'bd' tool. This ensure that any mutation performable via the terminal is correctly interpreted and visualized by the Timeline engine.","created_at":"2026-02-14T08:01:32Z"}]}
|
||||
{"id":"bb-xhm.2","title":"Implement snapshot diffing for derived timeline events","description":"SUBTASK REPORT: Implementation of the O(N) Snapshot Differ. We built the logic engine responsible for identifying project delta in src/lib/snapshot-differ.ts. The engine transforms the incoming BeadIssue array into a Map for constant-time (O(1)) lookups and compares it against the previous in-memory state. It correctly identifies identity transitions (created/deleted), property changes (status, priority, title), and collection mutations (labels, dependencies).","acceptance_criteria":"Diff engine emits deterministic event records for relevant field changes.","notes":"EXECUTION TALE: The primary technical challenge was managing the initial server state. We solved the 'First Load Event Storm' problem (where every issue would be detected as 'created' on server start) by pre-seeding the watcher's internal snapshot in the startWatch() method. This ensures that the first disk read sets the baseline and subsequent changes produce real activity events. We also implemented noise-filtering to ensure that metadata-only updates (like 'updated_at' bumps without data change) do not emit events. Verified with 9 distinct test cases in tests/lib/snapshot-differ.test.ts.","status":"closed","priority":2,"issue_type":"task","assignee":"green-falcon","owner":"jordanlive121@gmail.com","created_at":"2026-02-11T17:12:07.5007059-08:00","created_by":"zenchantlive","updated_at":"2026-02-14T00:01:54.1739009-08:00","closed_at":"2026-02-13T19:56:44.3701518-08:00","close_reason":"Snapshot diffing engine implemented and verified.","labels":["diff","timeline"],"dependencies":[{"issue_id":"bb-xhm.2","depends_on_id":"bb-xhm","type":"parent-child","created_at":"2026-02-11T17:12:07.501756-08:00","created_by":"zenchantlive"},{"issue_id":"bb-xhm.2","depends_on_id":"bb-xhm.1","type":"blocks","created_at":"2026-02-11T17:12:35.3430513-08:00","created_by":"zenchantlive"},{"issue_id":"bb-xhm.2","depends_on_id":"bb-tpc.2","type":"blocks","created_at":"2026-02-11T17:12:35.8495336-08:00","created_by":"zenchantlive"},{"issue_id":"bb-xhm.2","depends_on_id":"bb-xhm.4","type":"blocks","created_at":"2026-02-11T20:10:07.6688195-08:00","created_by":"zenchantlive"},{"issue_id":"bb-xhm.2","depends_on_id":"bb-2mx","type":"blocks","created_at":"2026-02-14T00:16:52.051166-08:00","created_by":"zenchantlive"}],"comments":[{"id":13,"issue_id":"bb-xhm.2","author":"zenchantlive","text":"Technical challenge: Preventing 'Event Storms' on first load. We solved this by pre-populating the snapshot map in startWatch() so the first read is treated as the baseline, not a 'create all' event. We also implemented noise-filtering to ignore 'updated_at' changes that don't affect actual data.","created_at":"2026-02-14T07:32:35Z"},{"id":29,"issue_id":"bb-xhm.2","author":"zenchantlive","text":"MEMO: The diffing engine was performance-tuned to handle large projects. In our benchmarks, diffing 200 beads against a 200-bead previous state completes in under 10ms, well within our SSE latency targets.","created_at":"2026-02-14T08:01:54Z"}]}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Unified UX PRD - Swimlane Social Hub
|
||||
|
||||
> **Version**: 1.0
|
||||
> **Date**: 2026-02-15
|
||||
> **Status**: Planning Complete - Ready for Bead Creation
|
||||
> **Version**: 1.1
|
||||
> **Date**: 2026-02-16
|
||||
> **Status**: Updated - Activity View + Thread Drawer added
|
||||
> **Supersedes**: bb-u6f.7 (Unified Cross-Surface Navigation)
|
||||
|
||||
---
|
||||
|
|
@ -29,15 +29,18 @@ Single unified shell at `/` with 3 views:
|
|||
| # | Decision | Choice | Rationale |
|
||||
|---|----------|--------|-----------|
|
||||
| 1 | Routing | Single page at `/` with client tabs | Preserves selection state |
|
||||
| 2 | Views | 3 tabs: Social, Graph, Swarm | Sessions replaced by Social |
|
||||
| 3 | Detail pattern | Right sidebar (desktop), drawer (mobile) | Best use of screens |
|
||||
| 4 | Visual style | shadcn/ui + earthy-dark tokens | Replace Aero Chrome |
|
||||
| 5 | Tailwind | Stay on v3, use shadcn/ui patterns | v4 has migration risks |
|
||||
| 6 | Old pages | Copy page.tsx to page-old.tsx | Safe rollback |
|
||||
| 7 | Card pattern | Same base for Social and Swarm | Reusable components |
|
||||
| 8 | Threads | In detail strip for both views | Comments + events |
|
||||
| 9 | Agent presence | Embedded in swarm cards | Agents primary in Swarm |
|
||||
| 10 | Swarm sorting | Health (default), Activity, Progress | Auto-surface attention |
|
||||
| 2 | Views | 4 tabs: Social, Graph, Swarm, Activity | Activity replaces old /timeline |
|
||||
| 3 | Right Panel | Activity Feed + Agent roster (top 30%) | Persistent sidebar, always shows timeline |
|
||||
| 4 | Thread Drawer | Opens when clicking a card | Slides from right edge of middle area |
|
||||
| 5 | Detail pattern | Right sidebar (desktop), drawer (mobile) | Best use of screens |
|
||||
| 6 | Visual style | shadcn/ui + earthy-dark tokens | Replace Aero Chrome |
|
||||
| 7 | Tailwind | Stay on v3, use shadcn/ui patterns | v4 has migration risks |
|
||||
| 8 | Old pages | Copy page.tsx to page-old.tsx | Safe rollback |
|
||||
| 9 | Card pattern | Same base for Social and Swarm | Reusable components |
|
||||
| 10 | Threads | In thread drawer, not right panel | Separates conversation from activity |
|
||||
| 11 | Agent presence | Embedded in swarm cards + right panel top | Supervisors can see all agents |
|
||||
| 12 | Swarm sorting | Health (default), Activity, Progress | Auto-surface attention |
|
||||
| 13 | Mobile nav | 4 bottom tabs (Social, Graph, Swarm, Activity) | Matches desktop view selector |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -85,22 +88,33 @@ Liveness:
|
|||
|
||||
## Layout Architecture
|
||||
|
||||
Shell Structure (CSS Grid):
|
||||
### Shell Structure (CSS Grid)
|
||||
- TOP BAR: 3rem fixed
|
||||
- LEFT: 13rem (channel tree)
|
||||
- MIDDLE: flex-1 (card grid)
|
||||
- RIGHT: 17rem (detail strip)
|
||||
- RIGHT: 17rem (Activity Feed + Agent roster)
|
||||
- THREAD DRAWER: 24rem (slides from right edge of middle area, appears on card selection)
|
||||
|
||||
Responsive:
|
||||
- < 768px: Full width, drawer overlay
|
||||
- 768-1024px: Left collapses, slide-over
|
||||
- >= 1024px: Full 3-panel
|
||||
### Responsive Behavior
|
||||
| Size | Left Panel | Middle | Right Panel (Activity) | Thread Drawer |
|
||||
|------|------------|--------|----------------------|---------------|
|
||||
| Desktop (≥1024px) | 13rem fixed | flex-1 | 17rem fixed, always visible | 24rem slides in |
|
||||
| Tablet (768-1024px) | Collapsed, toggle | flex-1 | Slide-over, toggle | Slide-over drawer |
|
||||
| Mobile (<768px) | Hidden | flex-1 | Bottom tab | Full-screen bottom sheet |
|
||||
|
||||
URL State:
|
||||
- view: social | graph | swarm
|
||||
### Mobile Navigation (Bottom Tabs)
|
||||
- Tab 1: Social
|
||||
- Tab 2: Graph
|
||||
- Tab 3: Swarm
|
||||
- Tab 4: Activity (shows timeline/agent view)
|
||||
|
||||
### URL State
|
||||
- view: social | graph | swarm | activity
|
||||
- task: selected task ID
|
||||
- swarm: selected swarm ID
|
||||
- panel: open | closed
|
||||
- agent: selected agent ID (for activity panel filtering)
|
||||
- panel: open | closed (right panel)
|
||||
- drawer: open | closed (thread drawer)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -117,6 +131,30 @@ Card: Swarm ID, Epic title, AGENTS roster with status glow, ATTENTION items, Pro
|
|||
|
||||
Sorting: Health (default), Activity, Progress, Name
|
||||
|
||||
### Activity View
|
||||
Replaces /timeline. Shows:
|
||||
- Top 30%: Agent roster with status (active/stale/stuck/dead)
|
||||
- Bottom: Chronological activity feed (status changes, comments, events)
|
||||
- Real-time updates via SSE
|
||||
|
||||
**Deep Linking from Cards:**
|
||||
- Click agent icon on any card → Activity panel filters to that agent
|
||||
- URL: `/?view=activity&agent=bb-xyz` shows agent's activity
|
||||
- Click graph icon on card → `/?view=graph&task=bb-xyz`
|
||||
- Click kanban icon on card → `/?view=social&task=bb-xyz`
|
||||
|
||||
**Right Panel Behavior:**
|
||||
- No selection: Shows ALL active agents + ALL activity
|
||||
- Agent selected: Shows that agent's roster + their specific activity
|
||||
- Easy "show all" button to clear agent filter
|
||||
|
||||
### Thread Drawer
|
||||
When clicking a card (Social or Swarm), opens drawer showing:
|
||||
- Task/Swarm header with ID and title
|
||||
- Full thread of comments and events
|
||||
- Compose area for adding comments
|
||||
- Close button (X)
|
||||
|
||||
---
|
||||
|
||||
## Dependency Graph (Bead Flow)
|
||||
|
|
@ -133,6 +171,7 @@ PHASE 1: Shell Layout
|
|||
[1.4] LeftPanel Component <- [1.2]
|
||||
[1.5] RightPanel Component <- [1.2]
|
||||
[1.6] Responsive Behavior <- [1.3-1.5]
|
||||
[1.7] Resizable Panels <- [1.2-1.6]
|
||||
|
||||
PHASE 2: Social View
|
||||
[2.1] Social Card Data Builder
|
||||
|
|
@ -147,16 +186,23 @@ PHASE 3: Swarm View
|
|||
[3.3] Swarm Detail Strip <- [1.5][3.1]
|
||||
[3.4] Swarm View Integration <- [1.2][3.2-3.3]
|
||||
|
||||
PHASE 4: Graph Migration
|
||||
[4.1] Graph Component Extraction
|
||||
[4.2] Graph Tab Integration <- [1.2][4.1]
|
||||
[4.3] fitView Fix <- [4.2]
|
||||
PHASE 4: Activity View (NEW)
|
||||
[4.1] Activity Data Builder <- [0.3]
|
||||
[4.2] ActivityPanel Component <- [1.5][4.1]
|
||||
[4.3] Agent Deep Linking <- [4.2][2.2][3.2]
|
||||
[4.4] Thread Drawer <- [2.4]
|
||||
[4.5] Mobile Nav 4-tabs <- [1.6][4.2]
|
||||
|
||||
PHASE 5: Polish
|
||||
[5.1] Deep Link Verification <- [all above]
|
||||
[5.2] Mobile Responsive Polish
|
||||
[5.3] Screenshot Evidence
|
||||
[5.4] Final Quality Gates
|
||||
PHASE 5: Graph Migration
|
||||
[5.1] Graph Component Extraction
|
||||
[5.2] Graph Tab Integration <- [1.2][5.1]
|
||||
[5.3] fitView Fix <- [5.2]
|
||||
|
||||
PHASE 6: Polish
|
||||
[6.1] Deep Link Verification <- [all above]
|
||||
[6.2] Mobile Responsive Polish
|
||||
[6.3] Screenshot Evidence
|
||||
[6.4] Final Quality Gates
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
BIN
out/thumbnail.png
Normal file
BIN
out/thumbnail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 435 KiB |
BIN
out/video.mp4
Normal file
BIN
out/video.mp4
Normal file
Binary file not shown.
13
package.json
13
package.json
|
|
@ -9,7 +9,10 @@
|
|||
"start": "next start",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "node --test tests/bootstrap.test.mjs && node --import tsx --test tests/components/sessions/sessions-header.test.ts && node --import tsx --test tests/components/sessions/agent-station-logic.test.ts && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/components/shared/left-panel.test.tsx && node --import tsx --test tests/components/shared/top-bar.test.tsx && node --import tsx --test tests/components/shared/mobile-nav.test.tsx && node --import tsx --test tests/components/swarm/swarm-card.test.tsx"
|
||||
"test": "node --test tests/bootstrap.test.mjs && node --import tsx --test tests/components/sessions/sessions-header.test.ts && node --import tsx --test tests/components/sessions/agent-station-logic.test.ts && node --import tsx --test tests/lib/parser.test.ts && node --import tsx --test tests/lib/pathing.test.ts && node --import tsx --test tests/components/shared/left-panel.test.tsx && node --import tsx --test tests/components/shared/top-bar.test.tsx && node --import tsx --test tests/components/shared/mobile-nav.test.tsx && node --import tsx --test tests/components/swarm/swarm-card.test.tsx",
|
||||
"video": "remotion preview src/video/index.ts",
|
||||
"video:render": "remotion render src/video/index.ts Main out/video.mp4",
|
||||
"video:thumbnail": "remotion still src/video/index.ts Main out/thumbnail.png --frame=60"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-avatar": "^1.1.11",
|
||||
|
|
@ -18,6 +21,9 @@
|
|||
"@radix-ui/react-separator": "^1.1.8",
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@remotion/google-fonts": "^4.0.422",
|
||||
"@remotion/tailwind": "^4.0.422",
|
||||
"@remotion/zod-types": "^4.0.422",
|
||||
"@xyflow/react": "^12.10.0",
|
||||
"chokidar": "^5.0.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
|
|
@ -28,11 +34,14 @@
|
|||
"next": "15.5.7",
|
||||
"react": "19.2.1",
|
||||
"react-dom": "19.2.1",
|
||||
"remotion": "^4.0.422",
|
||||
"tailwind-merge": "^3.4.1",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zod": "3.22.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@remotion/cli": "^4.0.422",
|
||||
"@types/dagre": "^0.7.53",
|
||||
"@types/node": "^22.10.0",
|
||||
"@types/react": "^19.0.0",
|
||||
|
|
|
|||
BIN
public/graph-hero.png
Normal file
BIN
public/graph-hero.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 807 KiB |
BIN
public/kanban-hero.png
Normal file
BIN
public/kanban-hero.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 769 KiB |
8
remotion.config.ts
Normal file
8
remotion.config.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { Config } from '@remotion/cli/config';
|
||||
import { enableTailwind } from '@remotion/tailwind';
|
||||
|
||||
Config.setVideoImageFormat('jpeg');
|
||||
|
||||
Config.overrideWebpackConfig((config) => {
|
||||
return enableTailwind(config);
|
||||
});
|
||||
|
|
@ -7,3 +7,4 @@ export { statusGradient, statusBorder, statusDotColor, sessionStateGlow } from '
|
|||
export { EpicChipStrip } from './epic-chip-strip';
|
||||
export { WorkspaceHero } from './workspace-hero';
|
||||
export { ProjectScopeControls } from './project-scope-controls';
|
||||
export { ThreadView, type ThreadItem } from './thread-view';
|
||||
|
|
|
|||
159
src/components/shared/thread-view.tsx
Normal file
159
src/components/shared/thread-view.tsx
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
'use client';
|
||||
|
||||
import { ArrowRight, Ban, CheckCircle2, MessageSquare, UserMinus } from 'lucide-react';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export type ThreadItemType = 'comment' | 'status_change' | 'protocol_event';
|
||||
|
||||
export interface ThreadItem {
|
||||
id: string;
|
||||
type: ThreadItemType;
|
||||
author?: string;
|
||||
content?: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
event?: string;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
interface ThreadViewProps {
|
||||
items: ThreadItem[];
|
||||
onAddComment?: (text: string) => void;
|
||||
}
|
||||
|
||||
function getInitials(name: string): string {
|
||||
return name
|
||||
.split(' ')
|
||||
.map((part) => part[0])
|
||||
.join('')
|
||||
.toUpperCase()
|
||||
.slice(0, 2);
|
||||
}
|
||||
|
||||
function formatRelativeTime(date: Date): string {
|
||||
const now = new Date();
|
||||
const diffMs = now.getTime() - date.getTime();
|
||||
const diffSecs = Math.floor(diffMs / 1000);
|
||||
const diffMins = Math.floor(diffSecs / 60);
|
||||
const diffHours = Math.floor(diffMins / 60);
|
||||
const diffDays = Math.floor(diffHours / 24);
|
||||
|
||||
if (diffSecs < 60) return 'just now';
|
||||
if (diffMins < 60) return `${diffMins}m ago`;
|
||||
if (diffHours < 24) return `${diffHours}h ago`;
|
||||
if (diffDays < 7) return `${diffDays}d ago`;
|
||||
return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
|
||||
}
|
||||
|
||||
function getProtocolIcon(event?: string) {
|
||||
switch (event?.toUpperCase()) {
|
||||
case 'HANDOFF':
|
||||
return <UserMinus className="w-4 h-4 text-amber-400" />;
|
||||
case 'BLOCKED':
|
||||
return <Ban className="w-4 h-4 text-rose-400" />;
|
||||
case 'CLOSED':
|
||||
return <CheckCircle2 className="w-4 h-4 text-emerald-400" />;
|
||||
default:
|
||||
return <MessageSquare className="w-4 h-4 text-text-muted" />;
|
||||
}
|
||||
}
|
||||
|
||||
function getProtocolLabel(event?: string): string {
|
||||
switch (event?.toUpperCase()) {
|
||||
case 'HANDOFF':
|
||||
return 'Handoff';
|
||||
case 'BLOCKED':
|
||||
return 'Blocked';
|
||||
case 'CLOSED':
|
||||
return 'Closed';
|
||||
default:
|
||||
return 'Event';
|
||||
}
|
||||
}
|
||||
|
||||
function CommentItem({ item }: { item: ThreadItem }) {
|
||||
return (
|
||||
<div className="flex gap-3 py-3">
|
||||
<Avatar className="h-8 w-8 flex-shrink-0">
|
||||
<AvatarImage src={undefined} alt={item.author} />
|
||||
<AvatarFallback className="bg-surface-muted text-text-body text-xs font-semibold">
|
||||
{item.author ? getInitials(item.author) : '??'}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span className="text-text-primary text-sm font-medium">
|
||||
{item.author || 'Unknown'}
|
||||
</span>
|
||||
<span className="text-text-muted text-xs">
|
||||
{formatRelativeTime(item.timestamp)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-text-secondary text-sm whitespace-pre-wrap break-words">
|
||||
{item.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StatusChangeItem({ item }: { item: ThreadItem }) {
|
||||
return (
|
||||
<div className="flex items-center gap-3 py-2 text-sm">
|
||||
<ArrowRight className="w-4 h-4 text-text-muted flex-shrink-0" />
|
||||
<span className="text-text-muted">
|
||||
Status: <span className="text-text-primary font-medium">{item.from || 'unknown'}</span>
|
||||
<ArrowRight className="w-3 h-3 inline mx-1 text-text-muted" />
|
||||
<span className="text-text-primary font-medium">{item.to || 'unknown'}</span>
|
||||
</span>
|
||||
<span className="text-text-muted text-xs ml-auto">
|
||||
{formatRelativeTime(item.timestamp)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ProtocolEventItem({ item }: { item: ThreadItem }) {
|
||||
return (
|
||||
<div className="flex items-center gap-3 py-2">
|
||||
<div className="flex-shrink-0">{getProtocolIcon(item.event)}</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<span className="text-text-primary text-sm font-medium">
|
||||
{getProtocolLabel(item.event)}
|
||||
</span>
|
||||
{item.content && (
|
||||
<span className="text-text-secondary text-sm ml-2">{item.content}</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-text-muted text-xs">
|
||||
{formatRelativeTime(item.timestamp)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ThreadView({ items, onAddComment }: ThreadViewProps) {
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
{items.length === 0 ? (
|
||||
<p className="text-text-muted text-sm italic py-4">No activity yet</p>
|
||||
) : (
|
||||
<div className="divide-y divide-white/5">
|
||||
{items.map((item) => {
|
||||
switch (item.type) {
|
||||
case 'comment':
|
||||
return <CommentItem key={item.id} item={item} />;
|
||||
case 'status_change':
|
||||
return <StatusChangeItem key={item.id} item={item} />;
|
||||
case 'protocol_event':
|
||||
return <ProtocolEventItem key={item.id} item={item} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -3,8 +3,34 @@
|
|||
import type { SocialCard as SocialCardData, AgentStatus } from '../../lib/social-cards';
|
||||
import { StatusBadge } from '../shared/status-badge';
|
||||
import { AgentAvatar } from '../shared/agent-avatar';
|
||||
import { ThreadView, type ThreadItem } from '../shared/thread-view';
|
||||
import { Plus } from 'lucide-react';
|
||||
|
||||
// Sample data for demo - remove when real data connected
|
||||
const SAMPLE_THREAD_ITEMS: ThreadItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'status_change',
|
||||
from: 'backlog',
|
||||
to: 'in_progress',
|
||||
timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000),
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'comment',
|
||||
author: 'zenchantlive',
|
||||
content: 'Started working on this task. Will need input from the API team.',
|
||||
timestamp: new Date(Date.now() - 1 * 60 * 60 * 1000),
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'protocol_event',
|
||||
event: 'HANDOFF',
|
||||
content: 'Handed off to bb-agent-1 for implementation',
|
||||
timestamp: new Date(Date.now() - 30 * 60 * 1000),
|
||||
},
|
||||
];
|
||||
|
||||
interface SocialDetailProps {
|
||||
data: SocialCardData;
|
||||
}
|
||||
|
|
@ -37,13 +63,11 @@ export function SocialDetail({ data }: SocialDetailProps) {
|
|||
<StatusBadge status={data.status} size="sm" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-text-muted text-xs font-semibold uppercase tracking-wider">
|
||||
Thread
|
||||
</h3>
|
||||
<p className="text-text-muted text-sm italic">
|
||||
Thread placeholder (bb-ui2.13)
|
||||
</p>
|
||||
<ThreadView items={SAMPLE_THREAD_ITEMS} />
|
||||
</div>
|
||||
|
||||
{data.blocks.length > 0 && (
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
import type { SwarmCard as SwarmCardType } from '../../lib/swarm-cards';
|
||||
import { Badge } from '../../../components/ui/badge';
|
||||
import { AgentAvatar } from '../shared/agent-avatar';
|
||||
import { ThreadView, type ThreadItem } from '../shared/thread-view';
|
||||
import { cn } from '../../lib/utils';
|
||||
import { AlertTriangle, Clock, MessageSquare, Users } from 'lucide-react';
|
||||
import { AlertTriangle, Clock, Users } from 'lucide-react';
|
||||
|
||||
interface SwarmDetailProps {
|
||||
card: SwarmCardType;
|
||||
|
|
@ -148,21 +149,38 @@ function LastActivitySection({ date }: { date: Date }) {
|
|||
);
|
||||
}
|
||||
|
||||
function ThreadPlaceholder() {
|
||||
// Sample data for demo - remove when real data connected
|
||||
const SAMPLE_SWARM_THREAD: ThreadItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'status_change',
|
||||
from: 'planning',
|
||||
to: 'in_progress',
|
||||
timestamp: new Date(Date.now() - 4 * 60 * 60 * 1000),
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'comment',
|
||||
author: 'bb-agent-1',
|
||||
content: 'Starting work on the first batch of tasks.',
|
||||
timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000),
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'protocol_event',
|
||||
event: 'CLOSED',
|
||||
content: 'Task bb-buff.1 completed',
|
||||
timestamp: new Date(Date.now() - 30 * 60 * 1000),
|
||||
},
|
||||
];
|
||||
|
||||
function ThreadSection() {
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<MessageSquare className="h-3.5 w-3.5" style={{ color: 'var(--color-text-muted)' }} />
|
||||
<span className="text-xs font-semibold uppercase tracking-wider" style={{ color: 'var(--color-text-muted)' }}>
|
||||
Thread
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="p-3 rounded-md text-center text-xs"
|
||||
style={{ backgroundColor: 'var(--color-bg-elevated)', color: 'var(--color-text-muted)' }}
|
||||
>
|
||||
Thread coming soon
|
||||
</div>
|
||||
<span className="text-xs font-semibold uppercase tracking-wider" style={{ color: 'var(--color-text-muted)' }}>
|
||||
Thread
|
||||
</span>
|
||||
<ThreadView items={SAMPLE_SWARM_THREAD} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -200,8 +218,8 @@ export function SwarmDetail({ card }: SwarmDetailProps) {
|
|||
{/* Last Activity */}
|
||||
<LastActivitySection date={card.lastActivity} />
|
||||
|
||||
{/* Thread Placeholder */}
|
||||
<ThreadPlaceholder />
|
||||
{/* Thread */}
|
||||
<ThreadSection />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
197
src/video/Main.tsx
Normal file
197
src/video/Main.tsx
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
import { interpolate, useCurrentFrame, useVideoConfig, AbsoluteFill, Sequence, Img, staticFile, spring } from 'remotion';
|
||||
import React from 'react';
|
||||
import { loadFont } from "@remotion/google-fonts/Inter";
|
||||
import { Background } from './components/Background';
|
||||
import { TerminalScene } from './components/TerminalScene';
|
||||
import { TimelineScene } from './components/TimelineScene';
|
||||
|
||||
loadFont();
|
||||
|
||||
const COLORS = {
|
||||
textPrimary: '#FFFFFF',
|
||||
textSecondary: '#B8B8B8',
|
||||
accentGreen: '#7CB97A',
|
||||
accentTeal: '#5BA8A0',
|
||||
accentAmber: '#D4A574',
|
||||
};
|
||||
|
||||
const Logo: React.FC<{ scale?: number }> = ({ scale = 1 }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const dots = [
|
||||
{ color: COLORS.accentGreen, delay: 0 },
|
||||
{ color: COLORS.accentTeal, delay: 5 },
|
||||
{ color: COLORS.accentAmber, delay: 10 },
|
||||
{ color: COLORS.accentTeal, delay: 15 },
|
||||
{ color: COLORS.accentGreen, delay: 20 },
|
||||
{ color: COLORS.accentAmber, delay: 25 },
|
||||
{ color: COLORS.accentGreen, delay: 30 },
|
||||
{ color: COLORS.accentTeal, delay: 35 },
|
||||
{ color: COLORS.accentAmber, delay: 40 },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-3 gap-3 p-4" style={{ transform: `scale(${scale})` }}>
|
||||
{dots.map((dot, i) => {
|
||||
const spr = spring({
|
||||
frame: frame - dot.delay,
|
||||
fps,
|
||||
config: { damping: 10 }
|
||||
});
|
||||
const s = interpolate(spr, [0, 1], [0, 1]);
|
||||
const opacity = interpolate(spr, [0, 1], [0, 1]);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="w-4 h-4 rounded-full shadow-[0_0_15px_rgba(255,255,255,0.3)]"
|
||||
style={{
|
||||
backgroundColor: dot.color,
|
||||
opacity,
|
||||
transform: `scale(${s})`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const GlassCard: React.FC<{ children: React.ReactNode; className?: string }> = ({ children, className }) => {
|
||||
return (
|
||||
<div
|
||||
className={`relative overflow-hidden rounded-xl border border-[rgba(255,255,255,0.1)] bg-[#363636]/40 shadow-2xl ${className}`}
|
||||
style={{
|
||||
backdropFilter: 'blur(16px)',
|
||||
boxShadow: '0 24px 56px rgba(0, 0, 0, 0.5), inset 0 1px 1px rgba(255, 255, 255, 0.15)',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TitleScene: React.FC = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const opacity = interpolate(frame, [0, 20], [0, 1]);
|
||||
const y = interpolate(frame, [0, 20], [30, 0]);
|
||||
const blur = interpolate(frame, [0, 20], [10, 0]);
|
||||
|
||||
return (
|
||||
<AbsoluteFill className="items-center justify-center flex-col z-10">
|
||||
<div style={{ opacity, transform: `translateY(${y}px)`, filter: `blur(${blur}px)` }} className="flex flex-col items-center gap-8">
|
||||
<Logo scale={3} />
|
||||
<div className="text-center mt-10">
|
||||
<h1 className="text-8xl font-bold tracking-tight mb-6 drop-shadow-2xl" style={{ color: COLORS.textPrimary, fontFamily: 'Inter' }}>
|
||||
Beadboard
|
||||
</h1>
|
||||
<p className="text-3xl font-medium tracking-wide drop-shadow-md" style={{ color: COLORS.textSecondary, fontFamily: 'Inter' }}>
|
||||
Agent-Driven Project Orchestration
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
const ShowcaseScene: React.FC<{ src: string; title: string; subtitle: string }> = ({ src, title, subtitle }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const spr = spring({
|
||||
frame,
|
||||
fps,
|
||||
config: { damping: 14, mass: 0.8 },
|
||||
});
|
||||
|
||||
const opacity = interpolate(frame, [0, 15], [0, 1]);
|
||||
const scale = interpolate(spr, [0, 1], [0.92, 1]);
|
||||
const y = interpolate(spr, [0, 1], [60, 0]);
|
||||
|
||||
// Continuous floating animation
|
||||
const floatY = Math.sin(frame / 40) * 8;
|
||||
|
||||
return (
|
||||
<AbsoluteFill className="items-center justify-center p-20 z-10">
|
||||
<div className="w-full max-w-6xl flex flex-col items-center gap-10" style={{ opacity, transform: `translateY(${y}px)` }}>
|
||||
<div className="text-center drop-shadow-lg">
|
||||
<h2 className="text-6xl font-bold mb-4" style={{ color: COLORS.textPrimary, fontFamily: 'Inter' }}>{title}</h2>
|
||||
<p className="text-2xl font-medium" style={{ color: COLORS.textSecondary, fontFamily: 'Inter' }}>{subtitle}</p>
|
||||
</div>
|
||||
|
||||
<div style={{ transform: `translateY(${floatY}px)` }} className="w-full">
|
||||
<GlassCard className="w-full aspect-video flex items-center justify-center group">
|
||||
<div style={{ transform: `scale(${scale})`, width: '100%', height: '100%' }}>
|
||||
<Img src={staticFile(src)} className="w-full h-full object-cover opacity-90" />
|
||||
{/* Shine effect */}
|
||||
<div
|
||||
className="absolute inset-0 bg-gradient-to-tr from-white/0 via-white/5 to-white/0"
|
||||
style={{ transform: `translateX(${Math.sin(frame / 60) * 10}%)` }}
|
||||
/>
|
||||
</div>
|
||||
</GlassCard>
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
const OutroScene: React.FC = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const opacity = interpolate(frame, [0, 20], [0, 1]);
|
||||
const scale = interpolate(frame, [0, 100], [1, 1.1]);
|
||||
|
||||
return (
|
||||
<AbsoluteFill className="items-center justify-center z-10">
|
||||
<div style={{ opacity, transform: `scale(${scale})` }} className="text-center">
|
||||
<h2 className="text-8xl font-bold mb-8 drop-shadow-2xl" style={{ color: COLORS.textPrimary, fontFamily: 'Inter' }}>
|
||||
Build Faster.
|
||||
</h2>
|
||||
<p className="text-4xl font-semibold drop-shadow-lg" style={{ color: COLORS.accentTeal, fontFamily: 'Inter' }}>
|
||||
Deploy with Confidence.
|
||||
</p>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
}
|
||||
|
||||
export const Main: React.FC = () => {
|
||||
return (
|
||||
<AbsoluteFill>
|
||||
<Background />
|
||||
|
||||
<Sequence durationInFrames={90}>
|
||||
<TitleScene />
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={90} durationInFrames={100}>
|
||||
<ShowcaseScene
|
||||
src="graph-hero.png"
|
||||
title="Visual Workflow"
|
||||
subtitle="Orchestrate complex agent behaviors with intuitive graphs."
|
||||
/>
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={190} durationInFrames={100}>
|
||||
<ShowcaseScene
|
||||
src="kanban-hero.png"
|
||||
title="Agent Kanban"
|
||||
subtitle="Track autonomous tasks and parallel execution."
|
||||
/>
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={290} durationInFrames={300}>
|
||||
<TerminalScene />
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={590} durationInFrames={140}>
|
||||
<TimelineScene />
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={730} durationInFrames={80}>
|
||||
<OutroScene />
|
||||
</Sequence>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
25
src/video/Root.tsx
Normal file
25
src/video/Root.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Composition, Still } from 'remotion';
|
||||
import { Main } from './Main';
|
||||
import './style.css';
|
||||
|
||||
export const RemotionRoot: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Composition
|
||||
id="Main"
|
||||
component={Main}
|
||||
durationInFrames={810}
|
||||
fps={30}
|
||||
width={1920}
|
||||
height={1080}
|
||||
/>
|
||||
<Still
|
||||
id="Thumbnail"
|
||||
component={Main}
|
||||
width={1920}
|
||||
height={1080}
|
||||
defaultProps={{}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
100
src/video/components/Background.tsx
Normal file
100
src/video/components/Background.tsx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import { interpolate, useCurrentFrame, useVideoConfig, AbsoluteFill } from 'remotion';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
const COLORS = {
|
||||
bgBase: '#2D2D2D',
|
||||
accentGreen: '#7CB97A',
|
||||
accentAmber: '#D4A574',
|
||||
accentTeal: '#5BA8A0',
|
||||
};
|
||||
|
||||
const AnimatedGradient: React.FC = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { durationInFrames } = useVideoConfig();
|
||||
|
||||
// Create smooth looping motion for the blobs
|
||||
const offset1 = Math.sin(frame / 60) * 10;
|
||||
const offset2 = Math.cos(frame / 50) * 10;
|
||||
const scale1 = interpolate(Math.sin(frame / 80), [-1, 1], [0.8, 1.2]);
|
||||
const scale2 = interpolate(Math.cos(frame / 70), [-1, 1], [0.8, 1.2]);
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ backgroundColor: COLORS.bgBase, overflow: 'hidden' }}>
|
||||
<div
|
||||
className="absolute top-[-20%] left-[-10%] w-[60%] h-[60%] rounded-full opacity-20 blur-[140px]"
|
||||
style={{
|
||||
background: COLORS.accentGreen,
|
||||
transform: `translate(${offset1}%, ${offset2}%) scale(${scale1})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute bottom-[-20%] right-[-10%] w-[60%] h-[60%] rounded-full opacity-20 blur-[140px]"
|
||||
style={{
|
||||
background: COLORS.accentAmber,
|
||||
transform: `translate(${-offset2}%, ${-offset1}%) scale(${scale2})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="absolute top-[30%] left-[30%] w-[40%] h-[40%] rounded-full opacity-10 blur-[120px]"
|
||||
style={{
|
||||
background: COLORS.accentTeal,
|
||||
transform: `translate(${offset2 * 0.5}%, ${offset1 * 0.5}%) scale(${scale1})`,
|
||||
}}
|
||||
/>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
const DotGrid: React.FC = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { width, height } = useVideoConfig();
|
||||
|
||||
// Generate a static grid of dots
|
||||
// Only calculate once
|
||||
const dots = useMemo(() => {
|
||||
const d = [];
|
||||
const spacing = 80;
|
||||
const cols = Math.ceil(width / spacing);
|
||||
const rows = Math.ceil(height / spacing);
|
||||
|
||||
for (let i = 0; i < cols; i++) {
|
||||
for (let j = 0; j < rows; j++) {
|
||||
d.push({ x: i * spacing, y: j * spacing, delay: (i + j) * 2 });
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}, [width, height]);
|
||||
|
||||
return (
|
||||
<AbsoluteFill className="items-center justify-center">
|
||||
<svg width="100%" height="100%">
|
||||
{dots.map((dot, i) => {
|
||||
// Subtle fade in/out ripple effect based on position
|
||||
const wave = Math.sin((frame - dot.delay) / 20);
|
||||
const opacity = interpolate(wave, [-1, 1], [0.03, 0.15]);
|
||||
const scale = interpolate(wave, [-1, 1], [0.5, 1.2]);
|
||||
|
||||
return (
|
||||
<circle
|
||||
key={i}
|
||||
cx={dot.x + 40}
|
||||
cy={dot.y + 40}
|
||||
r={2 * scale}
|
||||
fill="white"
|
||||
opacity={opacity}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</svg>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
export const Background: React.FC = () => {
|
||||
return (
|
||||
<AbsoluteFill>
|
||||
<AnimatedGradient />
|
||||
<DotGrid />
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
120
src/video/components/TerminalScene.tsx
Normal file
120
src/video/components/TerminalScene.tsx
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
import { interpolate, useCurrentFrame, useVideoConfig, AbsoluteFill, Sequence, spring } from 'remotion';
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
const TerminalLine: React.FC<{ text: string; delay: number; color?: string }> = ({ text, delay, color = '#d1d5db' }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const chars = text.split('');
|
||||
|
||||
return (
|
||||
<div className="font-mono text-xl mb-2 flex">
|
||||
{chars.map((char, i) => {
|
||||
const show = frame > delay + i * 1.5;
|
||||
return (
|
||||
<span key={i} style={{ opacity: show ? 1 : 0, color }}>
|
||||
{char}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const JSONLine: React.FC<{ data: object; delay: number }> = ({ data, delay }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const str = JSON.stringify(data, null, 2);
|
||||
const lines = str.split('\n');
|
||||
|
||||
const show = frame > delay;
|
||||
const opacity = interpolate(frame, [delay, delay + 10], [0, 1]);
|
||||
const y = interpolate(frame, [delay, delay + 10], [10, 0]);
|
||||
|
||||
if (!show) return null;
|
||||
|
||||
return (
|
||||
<div style={{ opacity, transform: `translateY(${y}px)` }} className="font-mono text-sm text-green-400/90 bg-black/20 p-4 rounded-md border border-green-500/20 my-2">
|
||||
{lines.map((line, i) => (
|
||||
<div key={i}>{line}</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export const TerminalScene: React.FC = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const opacity = interpolate(frame, [0, 15], [0, 1]);
|
||||
const scale = interpolate(frame, [0, 15], [0.95, 1]);
|
||||
|
||||
// Header animation
|
||||
const headerY = interpolate(frame, [0, 20], [20, 0]);
|
||||
const headerOpacity = interpolate(frame, [0, 20], [0, 1]);
|
||||
|
||||
return (
|
||||
<AbsoluteFill className="items-center justify-center bg-transparent p-20 z-10">
|
||||
|
||||
{/* Header */}
|
||||
<div style={{ transform: `translateY(${headerY}px)`, opacity: headerOpacity }} className="absolute top-20 text-center w-full">
|
||||
<h2 className="text-6xl font-bold text-white mb-2 font-['Inter'] drop-shadow-lg">Protocol v1</h2>
|
||||
<p className="text-xl text-teal-400 font-mono tracking-widest uppercase">Safe Coordination Contract</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="w-full max-w-5xl bg-[#1e1e1e] rounded-xl overflow-hidden shadow-2xl border border-gray-700/50"
|
||||
style={{ opacity, transform: `scale(${scale})` }}
|
||||
>
|
||||
{/* Terminal Header */}
|
||||
<div className="bg-[#2d2d2d] px-4 py-3 flex items-center gap-2 border-b border-gray-700">
|
||||
<div className="w-3 h-3 rounded-full bg-red-500" />
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-500" />
|
||||
<div className="w-3 h-3 rounded-full bg-green-500" />
|
||||
<div className="ml-4 text-xs text-gray-400 font-mono">beadboard-agent — -zsh — 80x24</div>
|
||||
</div>
|
||||
|
||||
{/* Terminal Body */}
|
||||
<div className="p-6 h-[600px] font-mono text-gray-300 overflow-hidden relative">
|
||||
<Sequence from={20}>
|
||||
<TerminalLine text="> bb agent heartbeat --agent amber-otter --json" delay={0} color="#a5f3fc" />
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={60}>
|
||||
<JSONLine
|
||||
delay={0}
|
||||
data={{
|
||||
status: "ok",
|
||||
agent_id: "amber-otter",
|
||||
last_seen: "2026-02-16T10:42:15Z",
|
||||
liveness: "active"
|
||||
}}
|
||||
/>
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={110}>
|
||||
<TerminalLine text="> bb protocol emit HANDOFF --to cobalt-harbor" delay={0} color="#a5f3fc" />
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={150}>
|
||||
<div className="mt-4 p-4 border-l-4 border-blue-500 bg-blue-500/10">
|
||||
<TerminalLine text="[EVENT] HANDOFF DETECTED" delay={0} color="#60a5fa" />
|
||||
<TerminalLine text="Scope: src/components/sessions/*" delay={10} />
|
||||
<TerminalLine text="From: amber-otter -> To: cobalt-harbor" delay={20} />
|
||||
<TerminalLine text="Reason: Implementation complete, ready for review." delay={30} />
|
||||
</div>
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={250}>
|
||||
<div className="mt-4 p-4 border-l-4 border-yellow-500 bg-yellow-500/10">
|
||||
<TerminalLine text="[WARN] INCURSION PREVENTED" delay={0} color="#fbbf24" />
|
||||
<TerminalLine text="Target: src/lib/parser.ts (Locked by: obsidian-fox)" delay={10} />
|
||||
<TerminalLine text="Action: Write blocked. Queueing request." delay={20} />
|
||||
</div>
|
||||
</Sequence>
|
||||
|
||||
{/* Scanlines / CRT Effect Overlay */}
|
||||
<div className="absolute inset-0 pointer-events-none opacity-5 bg-[linear-gradient(rgba(18,16,16,0)_50%,rgba(0,0,0,0.25)_50%),linear-gradient(90deg,rgba(255,0,0,0.06),rgba(0,255,0,0.02),rgba(0,0,255,0.06))]" style={{ backgroundSize: "100% 2px, 3px 100%" }} />
|
||||
</div>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
112
src/video/components/TimelineScene.tsx
Normal file
112
src/video/components/TimelineScene.tsx
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
import { interpolate, useCurrentFrame, useVideoConfig, AbsoluteFill, Sequence, spring } from 'remotion';
|
||||
import React from 'react';
|
||||
|
||||
const COLORS = {
|
||||
bgBase: '#2D2D2D',
|
||||
cardBg: '#363636',
|
||||
accentGreen: '#7CB97A',
|
||||
accentAmber: '#D4A574',
|
||||
accentTeal: '#5BA8A0',
|
||||
textPrimary: '#FFFFFF',
|
||||
textSecondary: '#B8B8B8',
|
||||
border: 'rgba(255, 255, 255, 0.08)',
|
||||
};
|
||||
|
||||
const TimelineCard: React.FC<{
|
||||
title: string;
|
||||
subtitle: string;
|
||||
time: string;
|
||||
type: 'commit' | 'issue' | 'alert';
|
||||
index: number;
|
||||
}> = ({ title, subtitle, time, type, index }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const delay = index * 5;
|
||||
const spr = spring({
|
||||
frame: frame - delay,
|
||||
fps,
|
||||
config: { damping: 14, mass: 0.8 },
|
||||
});
|
||||
|
||||
const y = interpolate(spr, [0, 1], [50, 0]);
|
||||
const opacity = interpolate(spr, [0, 1], [0, 1]);
|
||||
|
||||
let iconColor = COLORS.textSecondary;
|
||||
if (type === 'commit') iconColor = COLORS.accentTeal;
|
||||
if (type === 'issue') iconColor = COLORS.accentGreen;
|
||||
if (type === 'alert') iconColor = COLORS.accentAmber;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ opacity, transform: `translateY(${y}px)` }}
|
||||
className="flex items-start gap-4 p-4 rounded-lg border bg-[#363636] shadow-lg mb-4 w-full max-w-2xl"
|
||||
// className="flex items-start gap-4 p-4 rounded-lg border border-[rgba(255,255,255,0.08)] bg-[#363636] shadow-lg mb-4 w-full max-w-2xl"
|
||||
>
|
||||
<div className="mt-1 w-3 h-3 rounded-full" style={{ backgroundColor: iconColor }} />
|
||||
<div className="flex-1">
|
||||
<div className="flex justify-between items-baseline">
|
||||
<h3 className="text-lg font-semibold text-white">{title}</h3>
|
||||
<span className="text-xs text-gray-500 font-mono">{time}</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-400 mt-1">{subtitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const TimelineScene: React.FC = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const titleOpacity = interpolate(frame, [0, 20], [0, 1]);
|
||||
const titleY = interpolate(frame, [0, 20], [20, 0]);
|
||||
|
||||
return (
|
||||
<AbsoluteFill className="items-center justify-center p-10 z-10 flex-col">
|
||||
<div style={{ opacity: titleOpacity, transform: `translateY(${titleY}px)` }} className="mb-12 text-center">
|
||||
<h2 className="text-6xl font-bold text-white mb-2 font-['Inter'] drop-shadow-lg">Live Activity Feed</h2>
|
||||
<p className="text-xl text-teal-400 font-mono tracking-widest uppercase">Real-time Project Pulse</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col w-full max-w-2xl">
|
||||
<div className="text-xs font-mono text-gray-500 mb-4 uppercase tracking-wider ml-2">Today</div>
|
||||
<Sequence from={10}>
|
||||
<TimelineCard
|
||||
index={0} type="commit" title="feat: Implement Session Protocol v1"
|
||||
subtitle="amber-otter pushed to main" time="10:42 AM"
|
||||
/>
|
||||
</Sequence>
|
||||
<Sequence from={25}>
|
||||
<TimelineCard
|
||||
index={1} type="issue" title="Docs: Update RFC-001"
|
||||
subtitle="cobalt-harbor commented on #23" time="10:45 AM"
|
||||
/>
|
||||
</Sequence>
|
||||
<Sequence from={40}>
|
||||
<TimelineCard
|
||||
index={2} type="alert" title="Incursion Alert"
|
||||
subtitle="obsidian-fox attempted write to locked scope" time="11:02 AM"
|
||||
/>
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={60}>
|
||||
<div className="text-xs font-mono text-gray-500 mt-6 mb-4 uppercase tracking-wider ml-2">Yesterday</div>
|
||||
</Sequence>
|
||||
|
||||
<Sequence from={70}>
|
||||
<TimelineCard
|
||||
index={3} type="issue" title="Refactor: Agent Registry"
|
||||
subtitle="emerald-wolf closed issue #19" time="4:20 PM"
|
||||
/>
|
||||
</Sequence>
|
||||
<Sequence from={85}>
|
||||
<TimelineCard
|
||||
index={4} type="commit" title="fix: Graph layout rendering"
|
||||
subtitle="amber-otter pushed to feature/graph-v2" time="3:15 PM"
|
||||
/>
|
||||
</Sequence>
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
4
src/video/index.ts
Normal file
4
src/video/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { registerRoot } from 'remotion';
|
||||
import { RemotionRoot } from './Root';
|
||||
|
||||
registerRoot(RemotionRoot);
|
||||
3
src/video/style.css
Normal file
3
src/video/style.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
Loading…
Add table
Add a link
Reference in a new issue