moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
/**
* M-11 BLOCKER-5 — wiki routes refuse to run with a mock embedder.
*
* The test server seeds no embedding API keys, so
* `createEmbeddingProvider` falls back to the mock provider in its fallback
* chain. Before this fix, wiki compile + health + the post-harvest recompile
* hook all silently produced results using zero-vector embeddings (see
* BUCKET-1 code review, BLOCKER-5). Now each endpoint must return an
* explicit degraded-state signal instead.
*/
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { MindDB, SessionStore, FrameStore } from '@waggle/core';
import { buildLocalServer } from '../../src/local/index.js';
import type { FastifyInstance } from 'fastify';
import { injectWithAuth } from '../test-utils.js';
describe('Wiki routes + mock embedder guard (M-11)', () => {
let server: FastifyInstance;
let tmpDir: string;
beforeAll(async () => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-wiki-mock-guard-'));
// Seed a harvest session + a couple of frames so the compile path has
// data to work with (we want to prove compile SKIPS not "returns zero
// because there's nothing to compile").
const personalPath = path.join(tmpDir, 'personal.mind');
const mind = new MindDB(personalPath);
new SessionStore(mind).ensure('harvest', 'harvest', 'harvest session');
const frames = new FrameStore(mind);
frames.createIFrame('harvest', '[Harvest:test] User works at Egzakta Advisory.', 'normal', 'import');
frames.createIFrame('harvest', '[Harvest:test] Partnered with Waggle OS team.', 'normal', 'import');
mind.close();
server = await buildLocalServer({ dataDir: tmpDir });
});
afterAll(async () => {
await server.close();
fs.rmSync(tmpDir, { recursive: true, force: true });
});
it('server boots with mock embedder in the test env (baseline sanity)', () => {
expect(server.embeddingProvider).toBeDefined();
expect(server.embeddingProvider.getActiveProvider()).toBe('mock');
});
it('POST /api/wiki/compile returns 503 with skippedReason instead of compiling against mock vectors', async () => {
const res = await injectWithAuth(server, {
method: 'POST',
url: '/api/wiki/compile',
payload: { mode: 'incremental' },
});
expect(res.statusCode).toBe(503);
const body = res.json();
expect(body.skippedReason).toBe('no_real_embedder');
expect(typeof body.error).toBe('string');
expect(body.error).toMatch(/embedding provider/i);
});
it('GET /api/wiki/health returns 503 with skippedReason on mock-only env', async () => {
const res = await injectWithAuth(server, {
method: 'GET',
url: '/api/wiki/health',
});
expect(res.statusCode).toBe(503);
const body = res.json();
expect(body.skippedReason).toBe('no_real_embedder');
});
it('POST /api/harvest/commit still succeeds but reports wikiSkippedReason = no_real_embedder', async () => {
// A minimal chatgpt-style payload so the adapter has 1+ items.
const payload = {
source: 'chatgpt',
data: [{
title: 'Test chat',
create_time: 1700000000,
mapping: {
n1: { message: { author: { role: 'user' }, content: { parts: ['Preference: VSCode with vim.'] }, create_time: 1700000001 } },
},
}],
};
const res = await injectWithAuth(server, {
method: 'POST',
url: '/api/harvest/commit',
payload,
});
expect(res.statusCode).toBe(200);
const body = res.json();
// Harvest itself succeeds (frames saved, cognify ran) — only the wiki
// compile step is skipped because we have no real embedder.
expect(body.saved).toBeGreaterThanOrEqual(0);
expect(body.wikiSkippedReason).toBe('no_real_embedder');
expect(body.wikiCompiled.pagesCreated).toBe(0);
expect(body.message).toMatch(/wiki skipped/i);
});
});