agent-ecosystem/test/main/services/team/OpenCodeProductionE2EEvidence.test.ts

375 lines
11 KiB
TypeScript

import { promises as fs } from 'fs';
import * as os from 'os';
import * as path from 'path';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import {
assertOpenCodeProductionE2EArtifactGate,
buildOpenCodeProjectPathFingerprint,
OPENCODE_PRODUCTION_E2E_READY_CHECKPOINTS,
OPENCODE_PRODUCTION_E2E_REQUIRED_SIGNALS,
validateOpenCodeProductionE2EEvidence,
type OpenCodeProductionE2EEvidence,
} from '../../../../src/main/services/team/opencode/e2e/OpenCodeProductionE2EEvidence';
import { OpenCodeProductionE2EEvidenceStore } from '../../../../src/main/services/team/opencode/e2e/OpenCodeProductionE2EEvidenceStore';
import {
buildOpenCodeCanonicalMcpToolId,
REQUIRED_AGENT_TEAMS_RUNTIME_TOOLS,
} from '../../../../src/main/services/team/opencode/mcp/OpenCodeMcpToolAvailability';
describe('OpenCodeProductionE2EEvidence', () => {
let tempDir: string;
const now = new Date('2026-04-21T12:00:00.000Z');
beforeEach(async () => {
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'opencode-production-e2e-'));
});
afterEach(async () => {
await fs.rm(tempDir, { recursive: true, force: true });
});
it('accepts production evidence when runtime identity, project context and required MCP tools match', () => {
const evidence = passingEvidence();
expect(validateOpenCodeProductionE2EEvidence(evidence)).toEqual(evidence);
expect(
assertOpenCodeProductionE2EArtifactGate({
evidence,
artifactPath: '/tmp/opencode-e2e',
now,
expected: {
opencodeVersion: '1.14.19',
binaryFingerprint: 'version:1.14.19',
capabilitySnapshotId: 'cap-1',
selectedModel: 'openai/gpt-5.4-mini',
projectPathFingerprint: 'project-a',
requiredMcpTools: ['agent-teams_runtime_deliver_message'],
},
})
).toEqual({
ok: true,
diagnostics: [],
});
});
it('fails closed for stale, mismatched or incomplete evidence', () => {
const expired = passingEvidence({
expiresAt: '2026-04-21T11:59:59.000Z',
selectedModel: 'openrouter/anthropic/claude-sonnet-4.5',
requiredSignals: requiredSignals({ stale_run_rejected: false }),
mcpTools: {
requiredTools: ['agent-teams_runtime_deliver_message'],
observedTools: [],
},
});
expect(
assertOpenCodeProductionE2EArtifactGate({
evidence: expired,
artifactPath: '/tmp/opencode-e2e',
now,
expected: {
opencodeVersion: '1.14.19',
binaryFingerprint: 'version:1.14.19',
capabilitySnapshotId: 'cap-1',
selectedModel: 'openai/gpt-5.4-mini',
projectPathFingerprint: 'project-a',
requiredMcpTools: ['agent-teams_runtime_deliver_message'],
},
})
).toMatchObject({
ok: false,
diagnostics: expect.arrayContaining([
'OpenCode production E2E evidence is expired',
'OpenCode production E2E evidence is missing signals: stale_run_rejected',
'OpenCode production E2E evidence is missing observed MCP tools: agent-teams_runtime_deliver_message',
]),
});
});
it('reads missing evidence as a production-blocking diagnostic and quarantines corrupt artifacts', async () => {
const filePath = path.join(tempDir, 'production-e2e-evidence.json');
const store = new OpenCodeProductionE2EEvidenceStore({
filePath,
clock: () => now,
});
await expect(store.read()).resolves.toMatchObject({
ok: true,
evidence: null,
artifactPath: filePath,
diagnostics: ['OpenCode production E2E evidence artifact has not been written yet'],
});
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, '{broken', 'utf8');
const corrupt = await store.read();
expect(corrupt).toMatchObject({
ok: false,
evidence: null,
artifactPath: filePath,
});
expect(corrupt.diagnostics[0]).toContain(
'OpenCode production E2E evidence store is unreadable'
);
});
it('writes evidence with the store path as artifactPath when the input omits it', async () => {
const filePath = path.join(tempDir, 'production-e2e-evidence.json');
const store = new OpenCodeProductionE2EEvidenceStore({
filePath,
clock: () => now,
});
await store.write({
...passingEvidence(),
artifactPath: null,
});
await expect(store.read()).resolves.toMatchObject({
ok: true,
evidence: {
artifactPath: filePath,
evidenceId: 'e2e-1',
},
diagnostics: [],
});
});
it('stores production evidence for multiple raw model ids and reads exact model matches when no project context is provided', async () => {
const filePath = path.join(tempDir, 'production-e2e-evidence.json');
const store = new OpenCodeProductionE2EEvidenceStore({
filePath,
clock: () => now,
});
await store.write(passingEvidence({ selectedModel: 'opencode/big-pickle' }));
await store.write(
passingEvidence({
evidenceId: 'e2e-2',
selectedModel: 'opencode/minimax-m2.5-free',
})
);
await expect(
store.read({ selectedModel: 'opencode/minimax-m2.5-free' })
).resolves.toMatchObject({
ok: true,
evidence: {
evidenceId: 'e2e-2',
selectedModel: 'opencode/minimax-m2.5-free',
},
diagnostics: [],
});
await expect(store.read({ selectedModel: 'openai/gpt-5.4-mini' })).resolves.toMatchObject({
ok: true,
evidence: null,
diagnostics: [
'OpenCode production E2E evidence artifact has no entry for selected model openai/gpt-5.4-mini',
],
});
});
it('reuses the current project production proof even when the requested OpenCode model differs', async () => {
const filePath = path.join(tempDir, 'production-e2e-evidence.json');
const store = new OpenCodeProductionE2EEvidenceStore({
filePath,
clock: () => now,
});
await store.write(
passingEvidence({
evidenceId: 'e2e-project-a',
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-a'),
})
);
await store.write(
passingEvidence({
evidenceId: 'e2e-project-b',
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-b'),
})
);
await expect(
store.read({
selectedModel: 'opencode/nemotron-3-super-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-b'),
})
).resolves.toMatchObject({
ok: true,
evidence: {
evidenceId: 'e2e-project-b',
selectedModel: 'opencode/minimax-m2.5-free',
},
diagnostics: [],
});
});
it('prefers a runtime-compatible project proof over a newer stale one from the same cwd', async () => {
const filePath = path.join(tempDir, 'production-e2e-evidence.json');
const store = new OpenCodeProductionE2EEvidenceStore({
filePath,
clock: () => now,
});
await store.write(
passingEvidence({
evidenceId: 'stale-newer',
createdAt: '2026-04-21T12:05:00.000Z',
selectedModel: 'opencode/big-pickle',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-a'),
capabilitySnapshotId: 'cap-stale',
})
);
await store.write(
passingEvidence({
evidenceId: 'matching-older',
createdAt: '2026-04-21T12:00:00.000Z',
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-a'),
capabilitySnapshotId: 'cap-current',
})
);
await expect(
store.read({
selectedModel: 'opencode/nemotron-3-super-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-a'),
opencodeVersion: '1.14.19',
binaryFingerprint: 'version:1.14.19',
capabilitySnapshotId: 'cap-current',
})
).resolves.toMatchObject({
ok: true,
evidence: {
evidenceId: 'matching-older',
selectedModel: 'opencode/minimax-m2.5-free',
},
diagnostics: [],
});
});
it('stores production evidence for the same raw model across multiple project contexts', async () => {
const filePath = path.join(tempDir, 'production-e2e-evidence.json');
const store = new OpenCodeProductionE2EEvidenceStore({
filePath,
clock: () => now,
});
await store.write(
passingEvidence({
evidenceId: 'e2e-project-a',
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-a'),
})
);
await store.write(
passingEvidence({
evidenceId: 'e2e-project-b',
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-b'),
})
);
await expect(
store.read({
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-b'),
})
).resolves.toMatchObject({
ok: true,
evidence: {
evidenceId: 'e2e-project-b',
selectedModel: 'opencode/minimax-m2.5-free',
},
diagnostics: [],
});
await expect(
store.read({
selectedModel: 'opencode/minimax-m2.5-free',
projectPathFingerprint: buildOpenCodeProjectPathFingerprint('/repo-c'),
})
).resolves.toMatchObject({
ok: true,
evidence: null,
diagnostics: ['OpenCode production E2E evidence artifact has no entry for the current working directory'],
});
});
});
function passingEvidence(
overrides: Partial<OpenCodeProductionE2EEvidence> = {}
): OpenCodeProductionE2EEvidence {
const createdAt = '2026-04-21T12:00:00.000Z';
const sessionId = 'session-1';
const requiredToolIds = REQUIRED_AGENT_TEAMS_RUNTIME_TOOLS.map((tool) =>
buildOpenCodeCanonicalMcpToolId('agent-teams', tool)
);
return {
schemaVersion: 1,
evidenceId: 'e2e-1',
createdAt,
expiresAt: '2026-04-21T12:10:00.000Z',
version: '1.14.19',
passed: true,
artifactPath: '/tmp/opencode-e2e',
binaryFingerprint: 'version:1.14.19',
capabilitySnapshotId: 'cap-1',
selectedModel: 'openai/gpt-5.4-mini',
projectPathFingerprint: 'project-a',
requiredSignals: requiredSignals(),
mcpTools: {
requiredTools: requiredToolIds,
observedTools: requiredToolIds,
},
launch: {
runId: 'run-1',
teamId: 'team-a',
teamLaunchState: 'ready',
memberCount: 1,
sessions: [
{
memberName: 'Dev',
sessionId,
launchState: 'confirmed_alive',
},
],
durableCheckpoints: OPENCODE_PRODUCTION_E2E_READY_CHECKPOINTS.map((name) => ({
name,
observedAt: createdAt,
})),
},
reconcile: {
runId: 'run-1',
teamLaunchState: 'ready',
memberCount: 1,
},
stop: {
runId: 'run-1',
stopped: true,
stoppedSessionIds: [sessionId],
},
logProjection: {
observed: true,
projectedMessageCount: 1,
},
...overrides,
};
}
function requiredSignals(
overrides: Partial<
Record<(typeof OPENCODE_PRODUCTION_E2E_REQUIRED_SIGNALS)[number], boolean>
> = {}
) {
return Object.fromEntries(
OPENCODE_PRODUCTION_E2E_REQUIRED_SIGNALS.map((signal) => [signal, overrides[signal] ?? true])
) as OpenCodeProductionE2EEvidence['requiredSignals'];
}