## Goal
Merge the duplicate graph implementations (?view=graph, ?view=swarm, and /graph page) into one enhanced graph view with two modes:
- Analysis mode (default): Full dependency DAG with progressive disclosure
- Assign mode (toggled): DAG highlights ready nodes, right panel shows assignment controls

## Problem
BeadBoard has two views (`?view=graph` and `?view=swarm`) that both render the same `WorkflowGraph` DAG component, creating duplication. The standalone `/graph` page (`DependencyGraphPage`) has rich dependency analysis features (hop depth, focus workspace, cycle detection, flow strip) that are stranded -- the shell's `?view=graph` is a bare 49-line wrapper (`SmartDag`) with none of them.

## Success Criteria
- ?view=graph shows enhanced DAG with all dependency analysis features
- 'Assign' toggle enables task assignment workflow
- ?view=swarm deprecated (falls back to default view)
- Archetypes/Templates accessible from assign mode right panel
- All implementation steps completed
- npm run typecheck, lint, test all pass

## Scope
- SmartDag rewrite with progressive disclosure + tabs + assign mode
- AssignmentPanel component for assign mode
- useGraphAnalysis hook extraction
- Swarm view removal from navigation
- Delete deprecated swarm files

## Out of Scope
- Backend API changes (use existing /api/swarm/prep)
- New archetypes/templates features
- Mobile-specific layouts

## Reference
PRD: docs/prd/unified-graph-view.md


SSE Test Bead


Phase 4 Agent Presence complete. livenessMap lifted to UnifiedShell; agent avatars on SocialCard + graph nodes with liveness animation; LeftPanel footer shows live workspace stats. Typecheck clean, lint clean, 29/31 tests pass (2 pre-existing url-state failures).

TASK CONTEXT
- Bead ID: (auto)
- Title: Phase 4: Agent Presence
- Parent/Epic: none (phase epic)
- Dependencies (must be done first): beadboard-0fi (Phase 2 — actor identity in shell)

TASK CONTRACT
- Goal: Move livenessMap from the deprecated SessionsHeader up to UnifiedShell and surface live agent state on both Social cards and Graph nodes, so an operator can see which agents are active and what they are working on within 5 seconds of opening the app.
- Success Criteria:
  - useSessionFeed called in UnifiedShell, livenessMap available at shell level
  - SocialCard shows agent avatar and liveness dot for the assigned agent
  - Graph nodes show agent avatar with pulse animation for stuck agents
  - LeftPanel footer replaced with live workspace stats (N agents active, M tasks in motion)
  - npm run typecheck && npm run lint && npm run test all pass
- Scope:
  - UnifiedShell livenessMap lift (src/hooks/use-session-feed.ts already exists)
  - SocialCard agent presence UI
  - SmartDag/graph node agent presence UI
  - LeftPanel footer stats
- Out of Scope:
  - Creating new API endpoints (liveness data already flows via SSE)
  - Agent detail right panel (covered in Phase 1)

IMPLEMENTATION CONSTRAINTS
- Preserve existing backend/API contracts unless explicitly stated otherwise.
- Reuse shared components and logic; avoid one-off forks.
- Keep changes targeted and minimal for this bead.

VERIFICATION REQUIREMENTS
- Required commands:
  - npm run typecheck
  - npm run lint
  - npm run test
- Report any remaining risks and follow-up beads explicitly.

Orchestrator agent beadboard-rnk claimed this epic. x3l.1 closed, x3l.2/3/4 dispatched as parallel sub-agents.

Phase 4: Agent Presence


useSessionFeed lifted to UnifiedShell; livenessMap+agentStats wired to SmartDag, SocialPage, LeftPanel props. Typecheck clean, tests 131/133 (2 pre-existing).

TASK CONTEXT
- Bead ID: beadboard-x3l.1
- Title: Move useSessionFeed/livenessMap up to UnifiedShell
- Parent/Epic: beadboard-x3l
- Dependencies (must be done first): none (first in phase)

TASK CONTRACT
- Goal: useSessionFeed is currently only called in sessions-page.tsx (deprecated route). Call it in UnifiedShell and make livenessMap available as a prop to SocialCard and SmartDag.
- Success Criteria:
  - useSessionFeed(projectRoot) called in UnifiedShell
  - livenessMap: Record<string, string> available in UnifiedShell scope
  - livenessMap passed down to SocialPage and SmartDag as a prop (even if they don't use it yet — that is beadboard-x3l.2 and beadboard-x3l.3)
  - No duplicate SSE connections opened (verify useSessionFeed does not re-subscribe on re-render)
  - npm run typecheck passes
- Scope:
  - src/components/shared/unified-shell.tsx — add useSessionFeed call
  - src/hooks/use-session-feed.ts — read to understand return shape before using
  - src/components/social/social-page.tsx — add livenessMap prop (pass through to cards later)
  - src/components/graph/smart-dag.tsx — add livenessMap prop (use in x3l.3)
- Out of Scope:
  - Rendering agent avatars yet (beadboard-x3l.2, x3l.3)
  - Removing useSessionFeed from sessions-page.tsx (leave it, legacy route)

IMPLEMENTATION CONSTRAINTS
- Preserve existing backend/API contracts unless explicitly stated otherwise.
- Reuse shared components and logic; avoid one-off forks.
- Keep changes targeted and minimal for this bead.

VERIFICATION REQUIREMENTS
- Required commands:
  - npm run typecheck
  - npm run lint
  - npm run test
- Report any remaining risks and follow-up beads explicitly.

DONE: Added useSessionFeed to UnifiedShell, livenessMap wired to SmartDag/SocialPage/LeftPanel. Typecheck clean. 131/133 tests pass (2 pre-existing failures in url-state-integration unrelated to this change).


AgentAvatar rendered in SocialCard header when assignee in livenessMap. mapLiveness helper exported. SocialPage passes livenessMap to cards. 9 new tests in social-card-liveness.test.ts. Typecheck clean, no regressions.

TASK CONTEXT
- Bead ID: beadboard-x3l.2
- Title: Render agent avatar and liveness dot on SocialCard
- Parent/Epic: beadboard-x3l
- Dependencies (must be done first): beadboard-x3l.1

TASK CONTRACT
- Goal: Each SocialCard for an assigned task should show the assigned agent's avatar and a liveness dot (active/stale/stuck) using livenessMap from the shell.
- Success Criteria:
  - SocialCard receives livenessMap: Record<string, string> prop
  - If issue.assignee exists and is in livenessMap, renders AgentAvatar component with liveness indicator
  - Liveness states: 'active' (green dot), 'stale' (amber dot), 'stuck' (red pulse)
  - Cards without an assignee show no avatar — no empty avatar placeholder
  - npm run typecheck passes
- Scope:
  - src/components/social/social-card.tsx — add livenessMap prop and avatar render
  - src/components/social/social-page.tsx — thread livenessMap through to each SocialCard
  - Check if AgentAvatar component exists (grep src/ for AgentAvatar) and use it; if not, render a simple initials circle
- Out of Scope:
  - Graph node agent presence (beadboard-x3l.3)
  - Inline assign affordance (Phase 3, beadboard-8ij.2)

IMPLEMENTATION CONSTRAINTS
- Preserve existing backend/API contracts unless explicitly stated otherwise.
- Reuse shared components and logic; avoid one-off forks.
- Keep changes targeted and minimal for this bead.

VERIFICATION REQUIREMENTS
- Required commands:
  - npm run typecheck
  - npm run lint
  - npm run test
- Report any remaining risks and follow-up beads explicitly.


AgentAvatar overlay added to GraphNodeCard (bottom-right, sm size) with liveness→status mapping. WorkflowGraph and SmartDag wired. 10 new tests in graph-node-liveness.test.ts. Typecheck clean, no regressions.

TASK CONTEXT
- Bead ID: beadboard-x3l.3
- Title: Render agent avatar on graph nodes with stuck-agent pulse
- Parent/Epic: beadboard-x3l
- Dependencies (must be done first): beadboard-x3l.1

TASK CONTRACT
- Goal: Active graph nodes should show the assigned agent's avatar. Nodes whose agent is in a 'stuck' liveness state should display a pulsing warning treatment so the operator can spot problems at a glance in the DAG view.
- Success Criteria:
  - Graph node card renders a small agent avatar when issue.assignee is present in livenessMap
  - Stuck agents (livenessMap value === 'stuck') show a CSS pulse/ring animation on the node border
  - Non-assigned nodes are visually unchanged
  - npm run typecheck passes
- Scope:
  - src/components/graph/smart-dag.tsx or the node card component it renders — add livenessMap prop and avatar/pulse render
  - Read SmartDag to find where individual node UI is rendered before editing
- Out of Scope:
  - SocialCard presence (beadboard-x3l.2)
  - Graph layout or DAG structure changes

IMPLEMENTATION CONSTRAINTS
- Preserve existing backend/API contracts unless explicitly stated otherwise.
- Reuse shared components and logic; avoid one-off forks.
- Keep changes targeted and minimal for this bead.

VERIFICATION REQUIREMENTS
- Required commands:
  - npm run typecheck
  - npm run lint
  - npm run test
- Report any remaining risks and follow-up beads explicitly.


LeftPanel footer replaced with WorkspaceStatsFooter showing live agent count + in-motion tasks from livenessMap/agentStats. Hardcoded Alex Chen removed. Typecheck clean, 10/10 left-panel tests pass.

TASK CONTEXT
- Bead ID: beadboard-x3l.4
- Title: Replace LeftPanel footer with live workspace stats
- Parent/Epic: beadboard-x3l
- Dependencies (must be done first): beadboard-x3l.1

TASK CONTRACT
- Goal: The LeftPanel footer currently shows a hardcoded identity string. Replace it with live stats: number of active agents and number of tasks currently in motion, derived from livenessMap and the live issues array.
- Success Criteria:
  - Footer shows 'N agents active, M tasks in motion' with real counts
  - Counts update reactively when SSE pushes changes
  - No hardcoded identity text remains in LeftPanel footer
  - npm run typecheck passes
- Scope:
  - src/components/shared/left-panel.tsx — update footer section
  - LeftPanel already receives issues prop — use it for task count
  - livenessMap passed from UnifiedShell (add to LeftPanelProps if not present)
- Out of Scope:
  - TopBar identity input (beadboard-0fi.1)
  - Changing LeftPanel navigation or epic tree

IMPLEMENTATION CONSTRAINTS
- Preserve existing backend/API contracts unless explicitly stated otherwise.
- Reuse shared components and logic; avoid one-off forks.
- Keep changes targeted and minimal for this bead.

VERIFICATION REQUIREMENTS
- Required commands:
  - npm run typecheck
  - npm run lint
  - npm run test
- Report any remaining risks and follow-up beads explicitly.


DAG Views UX Overhaul (Macro/Micro Contexts)


Completed: Fixed cross-view nav with atomic buildUrlParams URL updates. Commit c246cea.

Fixed cross-view navigation between Social and Graph views. GitBranch button on social cards navigates to graph with graphTab=flow (Dependencies/DAG tab). Columns2 button on DAG nodes navigates to Social view. Fixed stale closure bug by using single buildUrlParams() -> router.push() for atomic multi-param URL updates instead of sequential setState calls. Scope: social-card.tsx, smart-dag.tsx, graph-node-card.tsx, use-url-state.ts. Success Criteria: Cross-view buttons navigate correctly without race conditions.

Fix cross-view navigation: Social <-> Graph with atomic URL params


When working on an epic, skill reads the template:XXX label, looks up the template definition, and uses team composition to spawn appropriate agents

Already captured in bb-buff.4 as template label integration concept

When the skill spawns work on an epic, it should:\n1. Check for labels starting with 'template:'\n2. Look up the template from /api/swarm/templates\n3. Use the team composition (archetype counts) to determine how many agents to spawn\n4. Follow the protoFormula workflow\n\nThis allows the user to assign templates to epics in the UI, and the skill will automatically understand what team is needed when asked to work on that epic.

Skill should read template labels from epics


Implement Frontend UI


Make Archetypes and Templates Editable in Swarm View


Recreating as proper children of Phase 0 epic with correct naming

view=activity is a valid ViewType (in VALID_VIEWS in use-url-state.ts) but renderMiddleContent() in UnifiedShell returns null for it. SocialCard 'Jump to Activity' navigates users here, so they land on a blank page.

File: src/components/shared/unified-shell.tsx
Location: renderMiddleContent() function (around lines 103-140)

Change: Add before the final 'return null':
  if (view === 'activity') {
    return (
      <ActivityPanel
        issues={filteredIssues}
        projectRoot={projectRoot}
      />
    );
  }

Import: ActivityPanel is already used in contextual-right-panel.tsx:
  import { ActivityPanel } from '../activity/activity-panel';
Check ActivityPanel's props signature before adding - confirm it accepts issues and projectRoot.

Acceptance: Navigating to /?view=activity renders the activity feed. SocialCard 'Jump to Activity' link lands on content, not a blank page.

P0.2: Add activity render case to renderMiddleContent()


GraphNodeData interface includes labels field. WorkflowGraph passes issue.labels to node data. Tests verify labels are present in node data.

Completed. Added labels field to GraphNodeData interface and passed issue.labels through WorkflowGraph and dependency-graph-page. All 4 TDD tests pass. All verification gates pass.

## Completed Implementation

### Files Changed
- **src/components/graph/graph-node-card.tsx**: Added `labels: string[]` field to GraphNodeData interface
- **src/components/shared/workflow-graph.tsx**: Added `labels: issue.labels` to node data
- **src/components/graph/dependency-graph-page.tsx**: Added `labels: issue.labels` to node data (deprecated page kept working)
- **tests/components/graph/graph-node-labels.test.tsx**: Created 4 TDD tests
- **package.json**: Added new test file to test script

### Tests Written (TDD)
All 4 tests pass:
1. GraphNodeData interface includes labels field
2. GraphNodeData labels is typed as string array
3. WorkflowGraph passes issue.labels to node data
4. WorkflowGraph uses labels from issue in node mapping

### Verification Gates
- npm run typecheck: ✓ PASS
- npm run lint: ✓ PASS (0 errors, 21 warnings - all pre-existing)
- npm run test: ✓ PASS (all tests)

### Evidence
```
npm run typecheck
> tsc --noEmit
(no output = success)

npm run lint
✖ 21 problems (0 errors, 21 warnings)

npm run test
# tests 13 (including new graph-node-labels suite)
# pass 13
# fail 0
```

Pass labels to graph nodes


Anchors exist, at least 5 canonical memory nodes exist and are closed, links to anchors exist, and plan docs updated.

Phase 1 memory fabric bootstrapped in bd with anchors and canonical memory nodes

Implement Phase 1 native memory system in bd: create domain anchors, seed canonical memory decisions with strict schema labels, link via relates_to, and document evidence.

Evidence: created anchors beadboard-76p/fld/nq9/5r1/8st; created+closed canonical nodes beadboard-116,dvp,60a,zas,duo,6fv,fga; verified retrieval via bd query label=memory+mem-canonical+status=closed and connectivity via bd dep list.

Bootstrap Phase 1 Memory Fabric (anchors + canonical nodes)


Completed: Created TelemetryStrip with real /api/activity + SSE data. Commit 114bb18.

Created new TelemetryStrip component - a minimized right sidebar that shows recent activity event dots from /api/activity + SSE (same data source as ActivityPanel). Uses getEventTone() color coding. Includes maximize button to restore full activity feed. Scope: telemetry-strip.tsx (NEW), unified-shell.tsx. Success Criteria: TelemetryStrip shows real activity events as colored dots, maximize restores full feed.

Create TelemetryStrip minimized sidebar component


Given a behavior change touching multiple views, when implementation lands, then shared logic path is reused and covered by tests.
Verification command(s): rg "<shared-function-or-hook>" src tests; npm run test

Scope: Repeated logic used by multiple views or pages.
Out of Scope: One-off prototypes and disposable experiments.
Rule: Reuse shared paths/components for cross-view behavior; avoid one-off logic drift.
Rationale: Prevents silent divergence between Kanban, Graph, and API views.
Failure Mode: Patching one surface only creates inconsistent user behavior.

Provenance linked: beadboard-68k.4, beadboard-68k.5, beadboard-r1i.1

[MEMORY][ARCH][HARD] Shared logic for cross-view behavior