From 65b9885ccf3093cfd66cf897a817d0665bf8d4ea Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Wed, 16 Sep 2026 00:45:53 -0700 Subject: [PATCH] fix(agent-status): mint the canonical epoch on first use, not at construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hook server's canonical store was built in an instance-member initializer, so constructing AgentHookServer — which happens at import time for the module singleton — demanded a live randomUUID. Any importer that stubs node:crypto threw 'Invalid agent status store epoch' before a single test ran. The store is now created on first canonical access and reset by dropping it, so construction owes nothing to a crypto implementation and the epoch still rotates per authority incarnation. --- src/main/agent-hooks/server/server-state.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/agent-hooks/server/server-state.ts b/src/main/agent-hooks/server/server-state.ts index 47d147fe3f2..3302b89e1f4 100644 --- a/src/main/agent-hooks/server/server-state.ts +++ b/src/main/agent-hooks/server/server-state.ts @@ -22,7 +22,7 @@ import type { AgentHookSource } from '../../../shared/agent-hook-relay' import type { AgentStatusClearIpcPayload } from '../../../shared/agent-status-types' import type { LegacyPaneKeyAliasEntry } from '../../../shared/persisted-state-types' import type { SpoolRecord } from '../../../shared/agent-hook-spool' -import { createAgentStatusStore } from '../../../shared/agent-status-store' +import { createAgentStatusStore, type AgentStatusStore } from '../../../shared/agent-status-store' import { AGENT_STATUS_2A_CURRENT_PRODUCER_MODE } from '../../../shared/agent-status-legacy-adapter' import type { AgentStatusStructuredSessionSubject } from '../../../shared/agent-status-subject' import type { @@ -58,10 +58,16 @@ export abstract class AgentHookServerState { ) } - protected canonicalStatusStore = createAgentStatusStore({ - epoch: randomUUID(), - mode: 'authority' - }) + // Why: the epoch is minted on first canonical use, so constructing the server — which happens at + // import time for the module singleton — owes nothing to a live crypto implementation. + private canonicalStatusStoreInstance: AgentStatusStore | null = null + protected get canonicalStatusStore(): AgentStatusStore { + this.canonicalStatusStoreInstance ??= createAgentStatusStore({ + epoch: randomUUID(), + mode: 'authority' + }) + return this.canonicalStatusStoreInstance + } protected readonly canonicalListingOrder = new Map() protected readonly canonicalSubjectsByPane = new Map< string, @@ -71,7 +77,7 @@ export abstract class AgentHookServerState { protected nextStatusListingOrder = (): number => ++this.statusListingOrder protected resetCanonicalStatus(): void { - this.canonicalStatusStore = createAgentStatusStore({ epoch: randomUUID(), mode: 'authority' }) + this.canonicalStatusStoreInstance = null this.canonicalListingOrder.clear() this.canonicalSubjectsByPane.clear() }