fix(agent-hooks): move advertised-capability source onto the ingest envelope

ingestRemote() gained a third positional argument in this PR
(advertisedAgentStatusCapabilities) to satisfy a new ratchet requiring
every legacy-ingress call site to name its capability source. Both
production callers pass the same constant every time, so the argument
carries zero runtime information — but Vitest's toHaveBeenCalledWith
matches argument count exactly, so the pre-existing SSH relay
integration test (which asserts a 2-argument call) started failing
even though nothing about the actual admission decision changed.

Capabilities are a property of the producing peer/connection, not an
orthogonal call parameter, so move the field onto the envelope object
instead of adding a third positional argument: ingestRemote reads
envelope.advertisedAgentStatusCapabilities (defaulting to the
unadvertised-legacy-peer set), and both call sites stamp the constant
onto their envelope literal. Call arity stays at two arguments, so the
pre-existing evidence test needs no change.

The envelope never crosses the wire in either caller: SSH rebuilds it
field-by-field from the RPC params, and the WSL path copies (never
mutates) the wire-deserialized notification before stamping the field
on, so this is purely an internal main-process shape change.

Also strengthens the ingress ratchet test that required this: it
previously only checked that the capability constant's name appeared
somewhere in each caller's source, which a stray unused import could
satisfy. It now asserts the actual
`advertisedAgentStatusCapabilities: AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES`
key:value binding is present.
This commit is contained in:
Brennan Benson
2026-09-14 18:21:03 -07:00
parent a1a7d05584
commit beb63eefca
6 changed files with 31 additions and 17 deletions
@@ -653,10 +653,10 @@ describe('AgentHookServer ingestRemote', () => {
paneKey: PANE,
tabId: 'tab-1',
worktreeId: 'wt-1',
advertisedAgentStatusCapabilities: [],
payload: { state: 'working', prompt: 'unsupported peer', agentType: 'claude' }
},
'conn-1',
[]
'conn-1'
)
const olderPeerRow = server.getStatusSnapshot()[0]
@@ -665,10 +665,10 @@ describe('AgentHookServer ingestRemote', () => {
paneKey: PANE,
tabId: 'tab-1',
worktreeId: 'wt-1',
advertisedAgentStatusCapabilities: [AGENT_STATUS_RUNS_RUNTIME_CAPABILITY],
payload: { state: 'done', prompt: 'capable peer', agentType: 'claude' }
},
'conn-1',
[AGENT_STATUS_RUNS_RUNTIME_CAPABILITY]
'conn-1'
)
expect(server.getStatusSnapshot()).toEqual([olderPeerRow])
@@ -52,15 +52,19 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS
/** Payload fields the relay dropped to fit an oversized frame; validated below. */
shedFields?: unknown
claudeRunningNonAgentTask?: unknown
/** The producing peer's advertised run-capability set — a property of the peer/connection that built this envelope, not an orthogonal call parameter. Absent (older relay/HTTP paths) defaults to the unadvertised-legacy-peer set. */
advertisedAgentStatusCapabilities?: readonly string[]
payload: unknown
},
connectionId: string | null,
advertisedAgentStatusCapabilities: readonly string[] = AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES
connectionId: string | null
): void {
if (
!canAdmitLegacyAgentStatus(
'main-status-update',
olderPeerAgentStatusLegacyMode(advertisedAgentStatusCapabilities)
olderPeerAgentStatusLegacyMode(
envelope?.advertisedAgentStatusCapabilities ??
AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES
)
)
) {
return
+11 -6
View File
@@ -100,12 +100,17 @@ export const defaultWslHookRelayDeps: WslHookRelayManagerDeps = {
spawnRelay: spawnWslRelayProcess,
runInstall: runWslInstallProcess,
waitForSentinel: waitForWslRelaySentinel,
ingest: (envelope, connectionId) =>
agentHookServer.ingestRemote(
envelope as Parameters<typeof agentHookServer.ingestRemote>[0],
connectionId,
AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES
),
// Why: the WSL relay protocol advertises no run-serving capability; stamped onto a copy so the
// wire-deserialized notification object itself is never mutated.
ingest: (envelope, connectionId) => {
const capped = {
...envelope,
advertisedAgentStatusCapabilities: AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES
}
type IngestEnvelope = Parameters<typeof agentHookServer.ingestRemote>[0]
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: envelope is the wire-deserialized notification; ingestRemote independently re-validates paneKey's type before trusting anything here.
return agentHookServer.ingestRemote(capped as IngestEnvelope, connectionId)
},
installHooks: installRemoteManagedAgentHooks,
installCodex: (runtimeHomePath, distro) =>
codexHookService.installForRuntimeHomeSerialized(runtimeHomePath, {
+3 -2
View File
@@ -1607,10 +1607,11 @@ export class SshRelaySession {
typeof envelope.claudeRunningNonAgentTask === 'boolean'
? envelope.claudeRunningNonAgentTask
: undefined,
// Why: the SSH relay protocol advertises no run-serving capability.
advertisedAgentStatusCapabilities: AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES,
payload: envelope.payload
},
this.targetId,
AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES
this.targetId
)
})
+1 -1
View File
@@ -33,7 +33,7 @@ export const AGENT_STATUS_PERSISTED_HYDRATION_MODE: AgentStatusLegacyAdmissionMo
kind: 'persisted-hydration'
})
/** Existing relay protocols advertise no run-serving capability. Production call sites pass this explicitly. */
/** Existing relay protocols advertise no run-serving capability. Production ingress call sites stamp this onto the envelope explicitly. */
export const AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES: readonly string[] = Object.freeze(
[]
)
@@ -116,8 +116,12 @@ describe('legacy agent-status ingress ratchet', () => {
'main/agent-hooks/wsl-hook-relay-deps.ts',
'main/ssh/ssh-relay-session.ts'
])
// Why: a bare import of the constant (unused elsewhere) would pass a substring check
// without ever stamping it onto the envelope — require the actual key:value binding.
for (const caller of callers) {
expect(caller.source).toContain('AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES')
expect(stripComments(caller.source)).toMatch(
/advertisedAgentStatusCapabilities\s*:\s*AGENT_STATUS_LEGACY_UNADVERTISED_PEER_CAPABILITIES\b/
)
}
})