Skip to content

Instantly share code, notes, and snippets.

@magyargergo
Created June 16, 2026 12:47
Show Gist options
  • Select an option

  • Save magyargergo/9e65ebd4e8975538d46191259dd95254 to your computer and use it in GitHub Desktop.

Select an option

Save magyargergo/9e65ebd4e8975538d46191259dd95254 to your computer and use it in GitHub Desktop.
GitNexus issue #2225 repro script — wiki __wiki__ idle eviction
#!/usr/bin/env node
/**
* Reproduction harness for GitHub issue #2225:
* Error: LadybugDB not initialized for repo "__wiki__". Call initLbug first.
*
* Usage (from repo root):
* node gitnexus/scripts/repro-wiki-2225.mjs [scenario]
*
* Scenarios:
* baseline — query without init (expected failure, confirms error text)
* no-init-mock — WikiGenerator with initWikiDb mocked out (simulates broken init)
* pool-fill — fill LRU pool then run wiki init+query
* branch-slot — meta at flat path but lbug only under branches/<slug>/
* cli-chinese — full `gitnexus wiki --lang chinese` with stub LLM
* all — run every scenario
*/
import fs from 'fs/promises';
import path from 'path';
import os from 'os';
import { execSync, spawnSync } from 'child_process';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '../..');
const GITNEXUS = path.join(ROOT, 'gitnexus');
const DIST = path.join(GITNEXUS, 'dist');
const WORKSPACE_LBUG = path.join(ROOT, '.gitnexus/lbug');
const TARGET_ERR = 'LadybugDB not initialized for repo "__wiki__"';
async function importDist(subpath) {
return import(path.join(DIST, subpath));
}
function header(name) {
console.log(`\n${'='.repeat(60)}\n SCENARIO: ${name}\n${'='.repeat(60)}`);
}
function result(name, reproduced, detail) {
const tag = reproduced ? 'REPRODUCED' : 'NOT REPRODUCED';
console.log(`\n[${tag}] ${name}`);
if (detail) console.log(` ${detail}`);
return reproduced;
}
async function scenarioBaseline() {
header('baseline — executeQuery without initWikiDb');
const { executeQuery } = await importDist('core/lbug/pool-adapter.js');
try {
await executeQuery('__wiki__', 'RETURN 1');
return result('baseline', false, 'Query succeeded unexpectedly');
} catch (e) {
const msg = e.message || String(e);
const hit = msg.includes(TARGET_ERR);
return result('baseline', hit, hit ? msg : `Different error: ${msg}`);
}
}
async function scenarioNoInitMock() {
header('no-init-mock — graph query without initWikiDb (same as baseline)');
const { getFilesWithExports } = await importDist('core/wiki/graph-queries.js');
try {
await getFilesWithExports();
return result('no-init-mock', false, 'Query succeeded unexpectedly');
} catch (e) {
const msg = e.message || String(e);
const hit = msg.includes(TARGET_ERR);
return result('no-init-mock', hit, msg);
}
}
async function scenarioIdleEviction() {
header('idle-eviction — vitest fake timers (see wiki-2225-idle-eviction.test.ts)');
const run = spawnSync(
'npx',
['vitest', 'run', 'test/unit/wiki-2225-idle-eviction.test.ts'],
{ cwd: GITNEXUS, encoding: 'utf-8', timeout: 120_000 },
);
const out = `${run.stdout}\n${run.stderr}`;
const hit = run.status === 0 && out.includes('1 passed');
console.log(out.slice(-1500));
return result(
'idle-eviction',
hit,
hit ? 'Vitest repro passed — idle eviction triggers exact error' : `exit=${run.status}`,
);
}
async function scenarioPoolFill() {
header('pool-fill — LRU pool at capacity during wiki init');
const pool = await importDist('core/lbug/pool-adapter.js');
const { initWikiDb, getFilesWithExports, closeWikiDb } = await importDist(
'core/wiki/graph-queries.js',
);
const opened = [];
try {
for (let i = 0; i < 5; i++) {
const id = `repro-fill-${i}`;
await pool.initLbug(id, WORKSPACE_LBUG);
opened.push(id);
}
await initWikiDb(WORKSPACE_LBUG);
const rows = await getFilesWithExports();
await closeWikiDb();
return result('pool-fill', false, `Query OK after pool fill (${rows.length} files)`);
} catch (e) {
const msg = e.message || String(e);
const hit = msg.includes(TARGET_ERR);
return result('pool-fill', hit, msg);
} finally {
for (const id of opened) {
try {
await pool.closeLbug(id);
} catch {}
}
try {
await closeWikiDb();
} catch {}
}
}
async function scenarioBranchSlot() {
header('branch-slot — flat meta.json but lbug only under branches/<slug>/');
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'wiki2225-branch-'));
const storage = path.join(tmp, '.gitnexus');
const branchName = 'feature/test';
const { branchSlug } = await importDist('storage/branch-index.js');
const slug = branchSlug(branchName);
const branchDir = path.join(storage, 'branches', slug);
await fs.mkdir(branchDir, { recursive: true });
await fs.copyFile(WORKSPACE_LBUG, path.join(branchDir, 'lbug'));
await fs.writeFile(
path.join(storage, 'meta.json'),
JSON.stringify(
{
repoPath: tmp,
lastCommit: 'abc',
indexedAt: new Date().toISOString(),
branch: 'main',
},
null,
2,
),
);
const { initWikiDb, getFilesWithExports, closeWikiDb } = await importDist(
'core/wiki/graph-queries.js',
);
const flatLbug = path.join(storage, 'lbug');
try {
await initWikiDb(flatLbug);
await getFilesWithExports();
return result('branch-slot', false, 'Unexpected success with missing flat lbug');
} catch (e) {
const msg = e.message || String(e);
if (msg.includes(TARGET_ERR)) {
return result('branch-slot', true, msg);
}
return result('branch-slot', false, `Different error (expected): ${msg}`);
} finally {
try {
await closeWikiDb();
} catch {}
}
}
async function scenarioCliChinese() {
header('cli-chinese — gitnexus wiki --lang chinese (needs LLM; often fails on auth/network)');
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'wiki2225-cli-'));
spawnSync('git', ['init'], { cwd: tmp, stdio: 'ignore' });
spawnSync('git', ['config', 'user.email', 'repro@test.local'], { cwd: tmp, stdio: 'ignore' });
spawnSync('git', ['config', 'user.name', 'repro'], { cwd: tmp, stdio: 'ignore' });
await fs.writeFile(path.join(tmp, 'README.md'), '# repro\n');
spawnSync('git', ['add', '.'], { cwd: tmp, stdio: 'ignore' });
spawnSync('git', ['commit', '-m', 'init'], { cwd: tmp, stdio: 'ignore' });
const commit = execSync('git rev-parse HEAD', { cwd: tmp }).toString().trim();
const storage = path.join(tmp, '.gitnexus');
await fs.mkdir(storage, { recursive: true });
await fs.copyFile(WORKSPACE_LBUG, path.join(storage, 'lbug'));
await fs.writeFile(
path.join(storage, 'meta.json'),
JSON.stringify(
{
repoPath: tmp,
lastCommit: commit,
indexedAt: new Date().toISOString(),
},
null,
2,
),
);
const cli = path.join(DIST, 'cli/index.js');
const env = {
...process.env,
GITNEXUS_VERBOSE: '1',
OPENAI_API_KEY: 'sk-test-repro',
};
const run = spawnSync(
'node',
[
cli,
'wiki',
tmp,
'--lang',
'chinese',
'--provider',
'openai',
'--model',
'test',
'--base-url',
'http://127.0.0.1:65503/v1',
'--api-key',
'sk-test',
'--force',
'--review',
],
{ cwd: ROOT, env, encoding: 'utf-8', timeout: 30_000, input: 'n\n' },
);
const out = `${run.stdout}\n${run.stderr}`;
console.log(out.slice(-2000));
const hit = out.includes(TARGET_ERR);
return result('cli-chinese', hit, hit ? 'CLI emitted target error' : `exit=${run.status}`);
}
const scenarios = {
baseline: scenarioBaseline,
'no-init-mock': scenarioNoInitMock,
'idle-eviction': scenarioIdleEviction,
'pool-fill': scenarioPoolFill,
'branch-slot': scenarioBranchSlot,
'cli-chinese': scenarioCliChinese,
};
const chosen = process.argv[2] || 'all';
const toRun =
chosen === 'all' ? Object.entries(scenarios) : [[chosen, scenarios[chosen]]].filter(([, fn]) => fn);
if (toRun.length === 0) {
console.error(`Unknown scenario: ${chosen}`);
console.error(`Available: ${Object.keys(scenarios).join(', ')}, all`);
process.exit(2);
}
console.log(`GitNexus issue #2225 reproduction harness`);
console.log(`Target error substring: ${TARGET_ERR}`);
console.log(`Using lbug: ${WORKSPACE_LBUG}`);
const summary = [];
for (const [name, fn] of toRun) {
try {
summary.push({ name, reproduced: await fn() });
} catch (e) {
console.error(`Scenario ${name} crashed:`, e);
summary.push({ name, reproduced: false, crash: e.message });
}
}
console.log(`\n${'='.repeat(60)}\n SUMMARY\n${'='.repeat(60)}`);
for (const row of summary) {
console.log(` ${row.reproduced ? 'YES' : 'no '}${row.name}${row.crash ? ` (crashed: ${row.crash})` : ''}`);
}
process.exit(summary.some((r) => r.reproduced) ? 0 : 1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment