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:
parent
0016b57e37
commit
4ee550c333
36 changed files with 1380 additions and 541 deletions
|
|
@ -48,14 +48,20 @@ export class IssuesWatchManager {
|
|||
console.log(`[Watcher] Processing event for ${projectRoot}: ${payload.kind} (${payload.changedPath})`);
|
||||
|
||||
// 1. Emit basic file change event
|
||||
this.eventBus.emit(projectRoot, payload.changedPath, payload.kind);
|
||||
|
||||
// 2. Perform snapshot diffing if issues.jsonl changed
|
||||
// If it's just last-touched or a DB file change, we treat it as telemetry
|
||||
const changedPath = payload.changedPath || '';
|
||||
const isIssuesJsonl = changedPath.endsWith('issues.jsonl') || changedPath.endsWith('issues.jsonl.new');
|
||||
const isLastTouched = changedPath.includes('last-touched');
|
||||
const isDbPulse = changedPath.includes('beads.db');
|
||||
|
||||
const kind = (isLastTouched || isDbPulse) && !isIssuesJsonl ? 'telemetry' : payload.kind;
|
||||
this.eventBus.emit(projectRoot, payload.changedPath, kind);
|
||||
|
||||
// 2. Perform snapshot diffing if issues.jsonl changed
|
||||
const isBeadsDb = changedPath.includes('beads.db') || isLastTouched;
|
||||
const isGlobalMessages = changedPath.includes('.beadboard') && changedPath.includes('messages');
|
||||
|
||||
if (isIssuesJsonl) {
|
||||
if (isIssuesJsonl || isBeadsDb) {
|
||||
console.log(`[Watcher] Issues changed. Syncing activity for ${projectRoot}...`);
|
||||
await this.syncActivity(projectRoot);
|
||||
} else if (isGlobalMessages) {
|
||||
|
|
@ -71,7 +77,7 @@ export class IssuesWatchManager {
|
|||
const previous = this.snapshots.get(projectKey) ?? null;
|
||||
|
||||
try {
|
||||
const current = await readIssuesFromDisk({ projectRoot });
|
||||
const current = await readIssuesFromDisk({ projectRoot, preferBd: true, skipAgentFilter: true });
|
||||
const events = diffSnapshots(previous, current);
|
||||
|
||||
this.snapshots.set(projectKey, current);
|
||||
|
|
@ -92,7 +98,7 @@ export class IssuesWatchManager {
|
|||
|
||||
// Pre-populate snapshot to avoid "all created" burst on first change
|
||||
try {
|
||||
const initial = await readIssuesFromDisk({ projectRoot });
|
||||
const initial = await readIssuesFromDisk({ projectRoot, preferBd: true, skipAgentFilter: true });
|
||||
this.snapshots.set(projectKey, initial);
|
||||
} catch {
|
||||
// Ignore initial read failure, will retry on first change
|
||||
|
|
@ -165,7 +171,7 @@ export class IssuesWatchManager {
|
|||
}
|
||||
}
|
||||
|
||||
const WATCHER_VERSION = 3; // Bump this to force re-creation on HMR
|
||||
const WATCHER_VERSION = 4; // Bump this to force re-creation on HMR (v4: fix beads.db telemetry classification)
|
||||
|
||||
const globalRegistry = globalThis as typeof globalThis & {
|
||||
__beadboardWatchManager?: IssuesWatchManager;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue