mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-22 00:31:17 +00:00
* Initial plan * fix(analyze): preserve existing embeddings by default; add --drop-embeddings opt-out Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/da1da041-afcd-4d38-8a2f-39ca52a462ff Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * analyze: --force on embedded repo now regenerates embeddings (preserve+top-up) Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/e2759765-b8f6-453a-8c28-595439d23cb4 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> * analyze: wire dropEmbeddings into HTTP API; log cache-load failures; extract pure deriveEmbeddingMode + behavioral tests; sync GUARDRAILS.md Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/7d88e595-cbd8-47b2-ba4f-fb5b9a60cda4 Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
95 lines
4.2 KiB
TypeScript
95 lines
4.2 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { deriveEmbeddingMode } from '../../src/core/embedding-mode.js';
|
|
|
|
describe('run-analyze module', () => {
|
|
it('exports runFullAnalysis as a function', async () => {
|
|
const mod = await import('../../src/core/run-analyze.js');
|
|
expect(typeof mod.runFullAnalysis).toBe('function');
|
|
});
|
|
|
|
it('exports PHASE_LABELS', async () => {
|
|
const mod = await import('../../src/core/run-analyze.js');
|
|
expect(mod.PHASE_LABELS).toBeDefined();
|
|
expect(mod.PHASE_LABELS.parsing).toBe('Parsing code');
|
|
});
|
|
});
|
|
|
|
describe('deriveEmbeddingMode', () => {
|
|
// Default `analyze` on a repo with existing embeddings: must preserve, must
|
|
// NOT regenerate, must load the cache so phase 3.5 can re-insert vectors.
|
|
it('default + existing>0 → preserve only (load cache, no generation)', () => {
|
|
const m = deriveEmbeddingMode({}, 1234);
|
|
expect(m.preserveExistingEmbeddings).toBe(true);
|
|
expect(m.shouldGenerateEmbeddings).toBe(false);
|
|
expect(m.forceRegenerateEmbeddings).toBe(false);
|
|
expect(m.shouldLoadCache).toBe(true);
|
|
});
|
|
|
|
it('default + existing=0 → no-op (no preserve, no generation, no cache load)', () => {
|
|
const m = deriveEmbeddingMode({}, 0);
|
|
expect(m.preserveExistingEmbeddings).toBe(false);
|
|
expect(m.shouldGenerateEmbeddings).toBe(false);
|
|
expect(m.forceRegenerateEmbeddings).toBe(false);
|
|
expect(m.shouldLoadCache).toBe(false);
|
|
});
|
|
|
|
// The headline behavior change requested in PR feedback: --force on an
|
|
// already-embedded repo must regenerate (top up new/changed nodes), not
|
|
// silently downgrade to "preserve only".
|
|
it('--force + existing>0 → forceRegenerate + generate + load cache', () => {
|
|
const m = deriveEmbeddingMode({ force: true }, 500);
|
|
expect(m.forceRegenerateEmbeddings).toBe(true);
|
|
expect(m.shouldGenerateEmbeddings).toBe(true);
|
|
expect(m.preserveExistingEmbeddings).toBe(false);
|
|
expect(m.shouldLoadCache).toBe(true);
|
|
});
|
|
|
|
it('--force + existing=0 → no embedding work (force keeps prior semantics)', () => {
|
|
const m = deriveEmbeddingMode({ force: true }, 0);
|
|
expect(m.forceRegenerateEmbeddings).toBe(false);
|
|
expect(m.shouldGenerateEmbeddings).toBe(false);
|
|
expect(m.preserveExistingEmbeddings).toBe(false);
|
|
expect(m.shouldLoadCache).toBe(false);
|
|
});
|
|
|
|
it('--embeddings → generate + load cache (incremental top-up)', () => {
|
|
const m = deriveEmbeddingMode({ embeddings: true }, 500);
|
|
expect(m.shouldGenerateEmbeddings).toBe(true);
|
|
expect(m.preserveExistingEmbeddings).toBe(false);
|
|
expect(m.shouldLoadCache).toBe(true);
|
|
});
|
|
|
|
it('--embeddings + existing=0 → generate; cache load still fires (harmless empty load)', () => {
|
|
const m = deriveEmbeddingMode({ embeddings: true }, 0);
|
|
expect(m.shouldGenerateEmbeddings).toBe(true);
|
|
// Cache load is gated at the call site by `existingMeta`, not by count;
|
|
// when explicit `--embeddings` is set we always attempt the load so any
|
|
// stray vectors from a partial prior run get picked up.
|
|
expect(m.shouldLoadCache).toBe(true);
|
|
});
|
|
|
|
// --drop-embeddings is the explicit wipe path; it must suppress cache load
|
|
// even when --force is also set (the dominant escape hatch).
|
|
it('--drop-embeddings → suppresses cache load, no generation', () => {
|
|
const m = deriveEmbeddingMode({ dropEmbeddings: true }, 1234);
|
|
expect(m.shouldLoadCache).toBe(false);
|
|
expect(m.shouldGenerateEmbeddings).toBe(false);
|
|
expect(m.preserveExistingEmbeddings).toBe(false);
|
|
expect(m.forceRegenerateEmbeddings).toBe(false);
|
|
});
|
|
|
|
it('--force + --drop-embeddings → drop wins (no cache load, no generation)', () => {
|
|
const m = deriveEmbeddingMode({ force: true, dropEmbeddings: true }, 1234);
|
|
expect(m.shouldLoadCache).toBe(false);
|
|
expect(m.shouldGenerateEmbeddings).toBe(false);
|
|
expect(m.forceRegenerateEmbeddings).toBe(false);
|
|
});
|
|
|
|
it('--embeddings + --drop-embeddings → drop suppresses cache load (no preservation)', () => {
|
|
// --embeddings still generates, but the prior vectors are wiped first.
|
|
const m = deriveEmbeddingMode({ embeddings: true, dropEmbeddings: true }, 1234);
|
|
expect(m.shouldLoadCache).toBe(false);
|
|
expect(m.shouldGenerateEmbeddings).toBe(true);
|
|
expect(m.preserveExistingEmbeddings).toBe(false);
|
|
});
|
|
});
|