test: cover opencode project evidence prepare

This commit is contained in:
777genius 2026-04-24 20:53:45 +03:00
parent 1f557712f1
commit 665fff14b5
2 changed files with 110 additions and 0 deletions

View file

@ -687,6 +687,56 @@ describe('TeamProvisioningService prepare/auth behavior', () => {
);
});
it('reports missing OpenCode project evidence as a provider note instead of model failures', async () => {
const projectEvidenceDiagnostic =
'OpenCode production E2E evidence artifact has no entry for the current working directory';
const projectEvidenceNote =
'OpenCode has not been verified on this project yet. This does not mean the selected models are broken.';
const prepare = vi.fn(async () => ({
ok: false as const,
providerId: 'opencode' as const,
reason: 'e2e_missing',
retryable: false,
diagnostics: [projectEvidenceDiagnostic],
warnings: [],
}));
const registry = new TeamRuntimeAdapterRegistry([
{
providerId: 'opencode',
prepare,
launch: vi.fn(),
reconcile: vi.fn(),
stop: vi.fn(),
} as any,
]);
const svc = new TeamProvisioningService();
svc.setRuntimeAdapterRegistry(registry);
const result = await svc.prepareForProvisioning(tempRoot, {
providerId: 'opencode',
forceFresh: true,
modelIds: ['opencode/minimax-m2.5-free', 'opencode/ling-2.6-flash-free'],
modelVerificationMode: 'compatibility',
});
expect(result.ready).toBe(true);
expect(result.message).toBe('CLI is ready to launch (see notes)');
expect(result.details).toEqual([
'Selected model opencode/minimax-m2.5-free verified for launch.',
'Selected model opencode/ling-2.6-flash-free verified for launch.',
]);
expect(result.warnings).toEqual([projectEvidenceNote]);
expect(result.message).not.toContain('unavailable');
expect(prepare).toHaveBeenCalledTimes(1);
expect(prepare).toHaveBeenCalledWith(
expect.objectContaining({
providerId: 'opencode',
model: undefined,
runtimeOnly: true,
})
);
});
it('treats retryable OpenCode compatibility failures as blocking selected-model diagnostics', async () => {
const prepare = vi.fn(async () => ({
ok: false as const,

View file

@ -256,6 +256,66 @@ describe('runProviderPrepareDiagnostics', () => {
);
});
it('shows missing OpenCode project evidence as a provider note instead of model failures', async () => {
const projectEvidenceNote =
'OpenCode has not been verified on this project yet. This does not mean the selected models are broken.';
const prepareProvisioning = vi
.fn<
(
cwd?: string,
providerId?: TeamProviderId,
providerIds?: TeamProviderId[],
selectedModels?: string[],
limitContext?: boolean,
modelVerificationMode?: 'compatibility' | 'deep'
) => Promise<TeamProvisioningPrepareResult>
>()
.mockResolvedValue({
ready: true,
message: 'CLI is ready to launch (see notes)',
details: [
'Selected model opencode/minimax-m2.5-free verified for launch.',
'Selected model opencode/ling-2.6-flash-free verified for launch.',
],
warnings: [projectEvidenceNote],
});
const result = await runProviderPrepareDiagnostics({
cwd: '/tmp/project',
providerId: 'opencode',
selectedModelIds: ['opencode/minimax-m2.5-free', 'opencode/ling-2.6-flash-free'],
prepareProvisioning,
});
expect(result.status).toBe('notes');
expect(result.details).toEqual([
'minimax-m2.5-free - verified',
'ling-2.6-flash-free - verified',
]);
expect(result.warnings).toEqual([projectEvidenceNote]);
expect(result.modelResultsById).toEqual({
'opencode/minimax-m2.5-free': {
status: 'ready',
line: 'minimax-m2.5-free - verified',
warningLine: null,
},
'opencode/ling-2.6-flash-free': {
status: 'ready',
line: 'ling-2.6-flash-free - verified',
warningLine: null,
},
});
expect(prepareProvisioning).toHaveBeenCalledTimes(1);
expect(prepareProvisioning).toHaveBeenCalledWith(
'/tmp/project',
'opencode',
['opencode'],
['opencode/minimax-m2.5-free', 'opencode/ling-2.6-flash-free'],
undefined,
'compatibility'
);
});
it('normalizes raw Codex API error envelopes into a clean model reason', async () => {
const prepareProvisioning = vi.fn<
(