mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-10-23 03:47:00 +09:00
test(ci): isolate witness fixture and search mocks
This commit is contained in:
1 parent
44ac70aa39
commit
24a80bd75d
4 files changed
+37
-7
No files matched your search
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"manifest": {
|
||||
"schema": "ruflo-witness/v1",
|
||||
"gitCommit": "synthetic-smoke-test-fixture",
|
||||
"fixes": [
|
||||
{
|
||||
"id": "test-source",
|
||||
"desc": "Synthetic source-only strict verification fixture",
|
||||
"file": "source.js",
|
||||
"sha256": "7efd9d12f48223fce735bfca349a8f96bcdc888d2dc8b8cfe3364cc545dd6a6e",
|
||||
"marker": "witnessSmokeMarker"
|
||||
}
|
||||
]
|
||||
},
|
||||
"integrity": {
|
||||
"manifestHash": "3fdc9d312a7364e8c4a9e55f48c858f51e3289f2184bb99714ea1863a7c1b92b",
|
||||
"publicKey": "d6b01eb8cf88be0eac71ff419ea32fc8c34de1e1790ff5c709a6fda16c71b6ac",
|
||||
"signature": "00ca3722db547fc5eb9af57b8ade4ef082cbb4d3657bba7ea9cc1b655652daedc8f52c98425a2629767770ebc6f455069f089398be416e5df1f85f80eab99d0f"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Synthetic witness smoke-test fixture; not a release artifact.
|
||||
export const witnessSmokeMarker = true;
|
||||
@@ -95,9 +95,13 @@ try {
|
||||
&& sourceResult?.signature?.publicKeyReproducible === true,
|
||||
`signature=${JSON.stringify(sourceResult?.signature)}`,
|
||||
);
|
||||
const strictClean = run(tmp, REAL_MANIFEST, '--source-only', '--strict');
|
||||
// The release witness hashes a historical tree, so legitimate later source
|
||||
// changes may drift. Test the zero-drift path against a fixed signed fixture.
|
||||
const fixtureRoot = resolve(REPO_ROOT, 'scripts/fixtures/witness-source-only');
|
||||
const fixtureManifest = join(fixtureRoot, 'manifest.json');
|
||||
const strictClean = run(fixtureRoot, fixtureManifest, '--source-only', '--strict');
|
||||
record(
|
||||
'--strict accepts an unchanged source tree',
|
||||
'--strict accepts the unchanged signed test fixture',
|
||||
strictClean.status === 0 && parseOutput(strictClean)?.summary?.drift === 0,
|
||||
`exit=${strictClean.status}, output=${strictClean.stdout.slice(0, 300)}`,
|
||||
);
|
||||
|
||||
@@ -25,7 +25,11 @@ interface SearchResponse {
|
||||
smartFallback?: string;
|
||||
stats?: { variantCount: number; rawCandidateCount: number };
|
||||
}
|
||||
let memoryModuleFactory: () => object | Promise<object>;
|
||||
async function search(input: Record<string, unknown>): Promise<SearchResponse> {
|
||||
// Register once per search: two queued doMock calls for this resolved ID
|
||||
// can finish out of order while Vite resolves their module IDs.
|
||||
vi.doMock('/@id/@claude-flow/memory', memoryModuleFactory);
|
||||
const { memoryTools } = await import('../src/mcp-tools/memory-tools.js');
|
||||
return memoryTools.find(t => t.name === 'memory_search')!.handler(input) as Promise<SearchResponse>;
|
||||
}
|
||||
@@ -37,7 +41,7 @@ beforeEach(() => {
|
||||
// are faked; this exercises the real MCP handler and its response whitelist.
|
||||
// The CLI's externalize-optional-deps plugin rewrites this dynamic import
|
||||
// to /@id/...; mock that resolved ID so Vitest 4 intercepts the import.
|
||||
vi.doMock('/@id/@claude-flow/memory', async () => import('../../memory/src/smart-retrieval.js'));
|
||||
memoryModuleFactory = async () => import('../../memory/src/smart-retrieval.js');
|
||||
});
|
||||
afterEach(() => vi.restoreAllMocks());
|
||||
|
||||
@@ -108,10 +112,10 @@ describe('memory_search score contract (#3327 Finding B)', () => {
|
||||
});
|
||||
|
||||
it.each(['missing export', 'import failure'])('preserves standard fallback on %s', async (reason) => {
|
||||
vi.doMock('/@id/@claude-flow/memory', () => {
|
||||
memoryModuleFactory = () => {
|
||||
if (reason === 'import failure') throw new Error('unavailable package');
|
||||
return { smartSearch: undefined };
|
||||
});
|
||||
};
|
||||
searchEntries.mockResolvedValue({ success: true, results: [entry('a', 0.49)] });
|
||||
const result = await search({ query: 'alpha', smart: true });
|
||||
expect(result.results).toEqual([{
|
||||
@@ -123,14 +127,14 @@ describe('memory_search score contract (#3327 Finding B)', () => {
|
||||
});
|
||||
|
||||
it('supplies rawScore to older SmartRetrieval implementations that preserve candidate fields', async () => {
|
||||
vi.doMock('/@id/@claude-flow/memory', () => ({
|
||||
memoryModuleFactory = () => ({
|
||||
// The existing return projection is {...candidate, score}. This fake
|
||||
// deliberately does not create rawScore: the MCP adapter must supply it.
|
||||
smartSearch: async (rawSearch: (request: RawSearchRequest) => Promise<{ results: object[] }>) => {
|
||||
const raw = await rawSearch({ query: 'alpha' });
|
||||
return { results: raw.results.map(r => ({ ...r, score: 0.05 })), stats: {} };
|
||||
},
|
||||
}));
|
||||
});
|
||||
searchEntries.mockResolvedValue({ success: true, results: [entry('a', 0)] });
|
||||
const result = await search({ query: 'alpha', smart: true, threshold: 0 });
|
||||
expect(result.results[0].similarity).toBe(0);
|
||||
|
||||
Reference in new issue
Block a user