agent-ecosystem/test/main/services/team/OpenCodeBridgeCommandContract.test.ts
777genius 6e4f8ff8c4 fix: stabilize opencode mcp transport refresh
Keep OpenCode app MCP transport evidence durable, refresh stale sessions without consuming normal delivery attempts, and keep recoverable runtime diagnostics out of member card errors.

Cover stable MCP restart/fallback, forced session refresh, resolved_behavior_changed recovery, and renderer diagnostics with regression and safe e2e tests.
2026-05-18 13:08:34 +03:00

430 lines
13 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
assertBridgeEvidenceCanCommitToRuntimeStores,
assertBridgeResultCanMutateState,
createOpenCodeBridgeHandshakeIdentityHash,
createOpenCodeBridgeIdempotencyKey,
isOpenCodeBridgeCommandName,
OPEN_CODE_APP_MANAGED_BOOTSTRAP_CONTRACT_VERSION,
OPEN_CODE_DELIVERY_ACCEPTANCE_CONTRACT_VERSION,
OPEN_CODE_TASK_LEDGER_EVIDENCE_CONTRACT_VERSION,
parseSingleBridgeJsonResult,
stableHash,
validateBridgeResultEnvelope,
validateOpenCodeBridgeHandshake,
type OpenCodeBridgeCommandEnvelope,
type OpenCodeBridgeHandshake,
type OpenCodeBridgePeerIdentity,
type OpenCodeBridgeRuntimeSnapshot,
type OpenCodeBridgeSuccess,
} from '../../../../src/main/services/team/opencode/bridge/OpenCodeBridgeCommandContract';
describe('OpenCodeBridgeCommandContract', () => {
it('rejects bridge stdout with logs plus json', () => {
const result = parseSingleBridgeJsonResult('debug log\n{"ok":true}\n');
expect(result).toEqual({
ok: false,
error: 'Bridge stdout must contain exactly one JSON line, got 2',
});
});
it('parses exactly one bridge result JSON line', () => {
const stdout = `${JSON.stringify(
bridgeSuccess({
data: {
runId: 'run-1',
idempotencyKey: 'key-1',
runtimeStoreManifestHighWatermark: 10,
},
})
)}\n`;
const parsed = parseSingleBridgeJsonResult(stdout);
expect(parsed).toMatchObject({
ok: true,
value: {
ok: true,
requestId: 'req-1',
command: 'opencode.launchTeam',
},
});
});
it('accepts opencode.cleanupHosts as a bridge command', () => {
expect(isOpenCodeBridgeCommandName('opencode.cleanupHosts')).toBe(true);
});
it('accepts opencode.backfillTaskLedger as a read-only bridge command', () => {
expect(isOpenCodeBridgeCommandName('opencode.backfillTaskLedger')).toBe(true);
});
it('validates result request id and command against the command envelope', () => {
const envelope: OpenCodeBridgeCommandEnvelope<Record<string, never>> = {
schemaVersion: 1,
requestId: 'req-expected',
command: 'opencode.launchTeam',
cwd: '/tmp/project',
startedAt: '2026-04-21T12:00:00.000Z',
timeoutMs: 10_000,
body: {},
};
expect(validateBridgeResultEnvelope(bridgeSuccess({ requestId: 'other' }), envelope)).toEqual({
ok: false,
reason: 'OpenCode bridge requestId mismatch',
});
expect(
validateBridgeResultEnvelope(
bridgeSuccess({ requestId: 'req-expected', command: 'opencode.stopTeam' }),
envelope
)
).toEqual({
ok: false,
reason: 'OpenCode bridge command mismatch',
});
});
it('does not allow state mutation when capability snapshot mismatches', () => {
const result = bridgeSuccess({
runtime: { capabilitySnapshotId: 'old-snapshot' },
data: { runId: 'run-1' },
});
expect(() =>
assertBridgeResultCanMutateState(result, {
requestId: 'req-1',
command: 'opencode.launchTeam',
runId: 'run-1',
capabilitySnapshotId: 'new-snapshot',
})
).toThrow('OpenCode bridge capability snapshot mismatch');
});
it('allows state mutation when caller has no capability snapshot evidence to compare', () => {
const result = bridgeSuccess({
runtime: { capabilitySnapshotId: 'runtime-snapshot' },
data: { runId: 'run-1' },
});
expect(() =>
assertBridgeResultCanMutateState(result, {
requestId: 'req-1',
command: 'opencode.launchTeam',
runId: 'run-1',
capabilitySnapshotId: null,
})
).not.toThrow();
});
it('rejects state-changing bridge evidence with stale manifest or idempotency mismatch', () => {
const result = bridgeSuccess({
data: {
runId: 'run-1',
idempotencyKey: 'key-1',
runtimeStoreManifestHighWatermark: 9,
},
});
expect(() =>
assertBridgeEvidenceCanCommitToRuntimeStores({
result,
requestId: 'req-1',
command: 'opencode.launchTeam',
runId: 'run-1',
capabilitySnapshotId: 'cap-1',
manifest: { highWatermark: 10 },
idempotencyKey: 'key-1',
})
).toThrow('Bridge result manifest high watermark is stale');
expect(() =>
assertBridgeEvidenceCanCommitToRuntimeStores({
result: bridgeSuccess({
data: {
runId: 'run-1',
idempotencyKey: 'other-key',
runtimeStoreManifestHighWatermark: 10,
},
}),
requestId: 'req-1',
command: 'opencode.launchTeam',
runId: 'run-1',
capabilitySnapshotId: 'cap-1',
manifest: { highWatermark: 10 },
idempotencyKey: 'key-1',
})
).toThrow('Bridge result idempotency key mismatch');
});
it('rejects handshake when server manifest high watermark is stale', () => {
const client = peerIdentity('claude_team');
const server = peerIdentity('agent_teams_orchestrator', {
runtimeStoreManifestHighWatermark: 9,
});
const handshake = buildHandshake({ client, server });
expect(
validateOpenCodeBridgeHandshake({
handshake,
expectedClient: client,
requiredCommand: 'opencode.launchTeam',
expectedCapabilitySnapshotId: 'cap-1',
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
})
).toEqual({
ok: false,
reason: 'Bridge server runtime manifest high watermark is stale',
});
});
it('rejects handshake when identity hash does not match peer evidence', () => {
const client = peerIdentity('claude_team');
const server = peerIdentity('agent_teams_orchestrator');
const handshake: OpenCodeBridgeHandshake = {
...buildHandshake({ client, server }),
identityHash: 'tampered',
};
expect(
validateOpenCodeBridgeHandshake({
handshake,
expectedClient: client,
requiredCommand: 'opencode.launchTeam',
expectedCapabilitySnapshotId: 'cap-1',
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
})
).toEqual({
ok: false,
reason: 'Bridge handshake identity hash mismatch',
});
});
it('accepts handshake evidence contract version and rejects invalid values', () => {
const client = peerIdentity('claude_team');
const server = peerIdentity('agent_teams_orchestrator');
server.bridgeProtocol.opencodeTaskLedgerEvidenceContractVersion =
OPEN_CODE_TASK_LEDGER_EVIDENCE_CONTRACT_VERSION;
const validHandshake = buildHandshake({ client, server });
expect(
validateOpenCodeBridgeHandshake({
handshake: validHandshake,
expectedClient: client,
requiredCommand: 'opencode.launchTeam',
expectedCapabilitySnapshotId: 'cap-1',
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
})
).toEqual({ ok: true });
server.bridgeProtocol.opencodeTaskLedgerEvidenceContractVersion = 0;
const invalidHandshake = buildHandshake({ client, server });
expect(
validateOpenCodeBridgeHandshake({
handshake: invalidHandshake,
expectedClient: client,
requiredCommand: 'opencode.launchTeam',
expectedCapabilitySnapshotId: 'cap-1',
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
})
).toEqual({
ok: false,
reason: 'Bridge handshake peer identity is invalid',
});
});
it('requires the delivery acceptance contract only for acceptance-mode sendMessage', () => {
const client = peerIdentity('claude_team');
const server = peerIdentity('agent_teams_orchestrator');
client.bridgeProtocol.supportedCommands.push('opencode.sendMessage');
server.bridgeProtocol.supportedCommands.push('opencode.sendMessage');
let handshake = withAcceptedCommands(buildHandshake({ client, server }), [
'opencode.launchTeam',
'opencode.stopTeam',
'opencode.sendMessage',
]);
expect(
validateOpenCodeBridgeHandshake({
handshake,
expectedClient: client,
requiredCommand: 'opencode.sendMessage',
expectedCapabilitySnapshotId: null,
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
requiresDeliveryAcceptanceContract: false,
})
).toEqual({ ok: true });
expect(
validateOpenCodeBridgeHandshake({
handshake,
expectedClient: client,
requiredCommand: 'opencode.sendMessage',
expectedCapabilitySnapshotId: null,
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
requiresDeliveryAcceptanceContract: true,
})
).toEqual({
ok: false,
reason:
`OpenCode delivery acceptance mode is required, but the orchestrator does not advertise contract version ${OPEN_CODE_DELIVERY_ACCEPTANCE_CONTRACT_VERSION}. Falling back to observed delivery mode is required.`,
});
server.bridgeProtocol.opencodeDeliveryAcceptanceContractVersion =
OPEN_CODE_DELIVERY_ACCEPTANCE_CONTRACT_VERSION;
handshake = withAcceptedCommands(buildHandshake({ client, server }), [
'opencode.launchTeam',
'opencode.stopTeam',
'opencode.sendMessage',
]);
expect(
validateOpenCodeBridgeHandshake({
handshake,
expectedClient: client,
requiredCommand: 'opencode.sendMessage',
expectedCapabilitySnapshotId: null,
expectedManifestHighWatermark: 10,
expectedRunId: 'run-1',
requiresDeliveryAcceptanceContract: true,
})
).toEqual({ ok: true });
});
it('creates deterministic idempotency keys for equivalent JSON bodies', () => {
const first = createOpenCodeBridgeIdempotencyKey({
command: 'opencode.launchTeam',
teamName: 'Team A',
runId: 'run-1',
body: { a: 1, b: { c: true, d: ['x'] } },
});
const second = createOpenCodeBridgeIdempotencyKey({
command: 'opencode.launchTeam',
teamName: 'Team A',
runId: 'run-1',
body: { b: { d: ['x'], c: true }, a: 1 },
});
expect(first).toBe(second);
expect(first).toMatch(
/^opencode:opencode\.launchTeam:Team_A:no-lane:run-1:[a-f0-9]{32}$/
);
expect(stableHash({ b: 2, a: 1 })).toBe(stableHash({ a: 1, b: 2 }));
});
});
type BridgeSuccessOverrides = Omit<Partial<OpenCodeBridgeSuccess<unknown>>, 'runtime'> & {
runtime?: Partial<OpenCodeBridgeRuntimeSnapshot>;
data?: unknown;
};
function bridgeSuccess(overrides: BridgeSuccessOverrides = {}): OpenCodeBridgeSuccess<unknown> {
const { runtime: runtimeOverrides, ...rest } = overrides;
return {
ok: true,
schemaVersion: 1,
requestId: 'req-1',
command: 'opencode.launchTeam',
completedAt: '2026-04-21T12:00:01.000Z',
durationMs: 1000,
runtime: {
providerId: 'opencode',
binaryPath: '/usr/local/bin/opencode',
binaryFingerprint: 'bin-1',
version: '1.0.0',
capabilitySnapshotId: 'cap-1',
...runtimeOverrides,
},
diagnostics: [],
data: {
runId: 'run-1',
idempotencyKey: 'key-1',
runtimeStoreManifestHighWatermark: 10,
},
...rest,
};
}
function peerIdentity(
peer: OpenCodeBridgePeerIdentity['peer'],
runtimeOverrides: Partial<OpenCodeBridgePeerIdentity['runtime']> = {}
): OpenCodeBridgePeerIdentity {
return {
schemaVersion: 1,
peer,
appVersion: '1.0.0',
gitSha: 'git-1',
buildId: 'build-1',
bridgeProtocol: {
minVersion: 1,
currentVersion: 1,
supportedCommands: [
'opencode.handshake',
'opencode.commandStatus',
'opencode.launchTeam',
'opencode.stopTeam',
],
opencodeAppManagedBootstrapContractVersion:
OPEN_CODE_APP_MANAGED_BOOTSTRAP_CONTRACT_VERSION,
},
runtime: {
providerId: 'opencode',
binaryPath: '/usr/local/bin/opencode',
binaryFingerprint: 'bin-1',
version: '1.0.0',
capabilitySnapshotId: 'cap-1',
runtimeStoreManifestHighWatermark: 10,
activeRunId: 'run-1',
...runtimeOverrides,
},
featureFlags: {
opencodeTeamLaunch: true,
opencodeStateChangingCommands: true,
},
};
}
function buildHandshake(input: {
client: OpenCodeBridgePeerIdentity;
server: OpenCodeBridgePeerIdentity;
}): OpenCodeBridgeHandshake {
const withoutHash: Omit<OpenCodeBridgeHandshake, 'identityHash'> = {
schemaVersion: 1,
requestId: 'handshake-1',
client: input.client,
server: input.server,
agreedProtocolVersion: 1,
acceptedCommands: ['opencode.launchTeam', 'opencode.stopTeam'],
serverTime: '2026-04-21T12:00:00.000Z',
};
return {
...withoutHash,
identityHash: createOpenCodeBridgeHandshakeIdentityHash(withoutHash),
};
}
function withAcceptedCommands(
handshake: OpenCodeBridgeHandshake,
acceptedCommands: OpenCodeBridgeHandshake['acceptedCommands']
): OpenCodeBridgeHandshake {
const { identityHash: _identityHash, ...rest } = handshake;
const withoutHash: Omit<OpenCodeBridgeHandshake, 'identityHash'> = {
...rest,
acceptedCommands,
};
return {
...withoutHash,
identityHash: createOpenCodeBridgeHandshakeIdentityHash(withoutHash),
};
}