6f3e53a56a
Add candidate auto-review pipeline, shadow audit tooling, admin metrics page, and user-visible memory recall hints in chat with phase-a readiness checks. Co-authored-by: Cursor <cursoragent@cursor.com>
73 lines
2.5 KiB
JavaScript
73 lines
2.5 KiB
JavaScript
#!/usr/bin/env node
|
|
import { pathToFileURL } from 'node:url';
|
|
import { createDbPool, isDatabaseConfigured } from '../db.mjs';
|
|
import { runCandidateAutoReviewBatch } from '../memory-v2-candidate-auto-review.mjs';
|
|
|
|
function usage() {
|
|
return [
|
|
'Usage: node scripts/auto-review-memory-v2-candidates.mjs [--apply] [--user-id <id>] [--limit <n>] [--json]',
|
|
'',
|
|
'Default is dry-run summary against pending candidates.',
|
|
].join('\n');
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const options = { apply: false, userId: null, limit: 200, json: false, help: false };
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const arg = argv[index];
|
|
if (arg === '--help' || arg === '-h') options.help = true;
|
|
else if (arg === '--apply') options.apply = true;
|
|
else if (arg === '--json') options.json = true;
|
|
else if (arg === '--user-id') options.userId = String(argv[++index] ?? '').trim() || null;
|
|
else if (arg === '--limit') options.limit = Number(argv[++index]);
|
|
else throw new Error(`Unknown argument: ${arg}`);
|
|
}
|
|
return options;
|
|
}
|
|
|
|
export async function runAutoReviewMemoryV2CandidatesCli(
|
|
argv = process.argv.slice(2),
|
|
env = process.env,
|
|
) {
|
|
const options = parseArgs(argv);
|
|
if (options.help) {
|
|
console.log(usage());
|
|
return { ok: true, mode: 'help' };
|
|
}
|
|
if (!isDatabaseConfigured()) {
|
|
throw new Error('DATABASE_URL or MYSQL_* must be configured');
|
|
}
|
|
const pool = createDbPool();
|
|
try {
|
|
const result = await runCandidateAutoReviewBatch(pool, {
|
|
env,
|
|
userId: options.userId,
|
|
limit: options.limit,
|
|
reviewedBy: options.apply ? 'system:auto-review-cli' : 'system:auto-review-dry-run',
|
|
dryRun: !options.apply,
|
|
});
|
|
const payload = {
|
|
...result,
|
|
mode: options.apply ? 'apply' : 'dry-run',
|
|
note: options.apply
|
|
? 'Auto-review applied to pending candidates'
|
|
: 'Dry-run only; pass --apply to mutate candidate statuses',
|
|
};
|
|
if (options.json) console.log(JSON.stringify(payload, null, 2));
|
|
else {
|
|
console.log(`${payload.mode}: scanned=${payload.scanned ?? 0} accept=${payload.accepted ?? 0} reject=${payload.rejected ?? 0} pending=${payload.pending ?? 0}`);
|
|
if (payload.samples?.length) console.log(JSON.stringify(payload.samples, null, 2));
|
|
}
|
|
return payload;
|
|
} finally {
|
|
await pool.end?.();
|
|
}
|
|
}
|
|
|
|
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
runAutoReviewMemoryV2CandidatesCli().catch((err) => {
|
|
console.error(err instanceof Error ? err.message : err);
|
|
process.exit(1);
|
|
});
|
|
}
|