feat(telemetry): complete bb-buff.1.3 - Backend Liveness Refactor

STORY:
The session backend needed to aggregate agent health from a live
telemetry stream rather than static bead metadata. This refactor
makes liveness signals real-time and accurate.

COLLABORATION:
We extended the ActivityEvent model with a native 'heartbeat' kind,
updated extendActivityLease() to emit through the activity bus, and
refactored getAgentLivenessMap() to prioritize heartbeat activity
history over stale bead metadata.

DELIVERABLES:
- ActivityEvent extended with 'heartbeat' kind
- extendActivityLease() emits heartbeats through activity bus
- getAgentLivenessMap() prefers telemetry over static metadata
- Registry APIs support projectRoot injection for testing
- Tests verify preference logic via TDD

VERIFICATION:
- 93/93 tests PASSING
- Heartbeat override verified in isolated temp projects

CLOSES: bb-buff.1.3
BLOCKS: bb-buff.3.2, bb-buff.3.3, bb-buff.2.1
This commit is contained in:
zenchantlive 2026-02-15 21:14:05 -08:00
parent 0016b57e37
commit 4ee550c333
36 changed files with 1380 additions and 541 deletions

View file

@ -10,6 +10,7 @@ interface SessionTaskFeedProps {
selectedEpicId: string | null;
onSelectTask: (id: string) => void;
highlightTaskId?: string | null;
highlightingAgentId?: string | null;
}
export function IncursionTicker({ incursions }: { incursions: Incursion[] }) {
@ -35,7 +36,7 @@ export function IncursionTicker({ incursions }: { incursions: Incursion[] }) {
);
}
export function SessionTaskFeed({ feed, incursions = [], selectedEpicId, onSelectTask, highlightTaskId }: SessionTaskFeedProps) {
export function SessionTaskFeed({ feed, incursions = [], selectedEpicId, onSelectTask, highlightTaskId, highlightingAgentId }: SessionTaskFeedProps) {
const filteredFeed = useMemo(() => {
if (!selectedEpicId) return feed;
return feed.filter(b => b.epic.id === selectedEpicId);
@ -88,13 +89,15 @@ export function SessionTaskFeed({ feed, incursions = [], selectedEpicId, onSelec
task.owner && inc.agents.includes(task.owner)
);
const isAgentMission = highlightingAgentId ? task.owner === highlightingAgentId : false;
return (
<SessionFeedCard
key={task.id}
card={task}
onSelect={onSelectTask}
isHighlighted={highlightTaskId === task.id}
isHighlighted={highlightTaskId === task.id || isAgentMission}
incursion={taskIncursion}
highlightSource={isAgentMission ? 'agent' : undefined}
/>
);
})}