feat(FN-4056): restore bound reports lookup in heartbeat executor

Restores the bound reports lookup in the heartbeat executor (FN-4056), updating the relevant logic in `agent-heartbeat.ts` with a corresponding test and documentation clarification in `agents.md`.

Fusion-Task-Id: FN-4056
This commit is contained in:
Fusion
2026-05-12 00:59:55 -07:00
committed by gsxdsm
parent 43c8aa58f9
commit 079772a106
3 changed files with 24 additions and 3 deletions

View File

@@ -221,6 +221,25 @@ describe("executeHeartbeat", () => {
expect(section).toContain("**stale**");
});
it("buildReportsHealthSection preserves AgentStore method binding for direct-report lookups", async () => {
const now = new Date().toISOString();
const report = { id: "agent-004", name: "bound-report", state: "active", taskId: "FN-102", reportsTo: "agent-001", lastHeartbeatAt: now, updatedAt: now } as Agent;
const store = createStoreWithAgentForExec() as AgentStore & {
listAgents: ReturnType<typeof vi.fn>;
getAgentsByReportsTo: (agentId: string) => Promise<Agent[]>;
};
store.listAgents = vi.fn().mockResolvedValue([mockAgent, report]);
store.getAgentsByReportsTo = async function (agentId: string) {
const agents = await this.listAgents();
return agents.filter((candidate: Agent) => candidate.reportsTo === agentId);
};
const monitor = new HeartbeatMonitor({ store, taskStore: mockTaskStore, rootDir: "/tmp" });
const section = await (monitor as any).buildReportsHealthSection("agent-001", store);
expect(section).toContain("bound-report");
expect(store.listAgents).toHaveBeenCalledTimes(1);
});
it("executeHeartbeat includes reports health section when agent has reports", async () => {
const store = createStoreWithAgentForExec({ taskId: "FN-001" });
const now = new Date().toISOString();

View File

@@ -2430,14 +2430,14 @@ export class HeartbeatMonitor {
}
private async buildReportsHealthSection(agentId: string, agentStore: AgentStore): Promise<string | null> {
const getReports = (agentStore as AgentStore & { getAgentsByReportsTo?: (id: string) => Promise<Agent[]> }).getAgentsByReportsTo;
if (typeof getReports !== "function") {
const storeWithReports = agentStore as AgentStore & { getAgentsByReportsTo?: (id: string) => Promise<Agent[]> };
if (typeof storeWithReports.getAgentsByReportsTo !== "function") {
return null;
}
let reports: Agent[];
try {
reports = await getReports(agentId);
reports = await storeWithReports.getAgentsByReportsTo(agentId);
} catch (err) {
heartbeatLog.warn(`Failed to load reports for ${agentId}: ${err instanceof Error ? err.message : String(err)}`);
return null;