harb/tools/push3-evolution/seed-gen-cli.ts
openhands 89a2734bff fix: address review findings for diverse seed population (#638)
- evolve.sh: fix fail-in-subshell bug — run seed-gen-cli as a direct
  command so its exit code is checked by the parent shell and fail()
  aborts the script correctly; redirect stderr to log file instead of
  discarding it with 2>/dev/null
- seed-generator.ts: reorder enumerateVariants() to put
  STAKED_THRESHOLDS outermost (192 entries/block) so that
  selectVariants(6) with stride=192 covers all 6 staked% thresholds;
  remove false doc claim about "first variant is current seed config";
  add comments explaining CI=0n is intentional in all presets
- seed-gen-cli.ts: emit a stderr diagnostic when count exceeds the
  1152-variant cap so the cap is visible rather than silently producing
  fewer files than requested
- test: strengthen n=6 test to assert all STAKED_THRESHOLDS values are
  represented in the selected variants

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 05:21:05 +00:00

71 lines
2.3 KiB
TypeScript

/**
* seed-gen-cli.ts — CLI for generating diverse Push3 seed variants (#638).
*
* Usage:
* tsx seed-gen-cli.ts --count <N> --output-dir <dir>
*
* Writes N Push3 variant files to <dir>/variant_000.push3 ... variant_NNN.push3
* and prints each file path to stdout (one per line).
*
* The variants are systematically diverse: different staked% thresholds,
* penalty thresholds, bull/bear output params, and tax rate distributions.
*
* Options:
* --count <N> Number of variants to generate (required, positive integer)
* --output-dir <dir> Directory to write variant files (required, created if absent)
*/
import { mkdirSync, writeFileSync } from 'fs';
import { join } from 'path';
import { selectVariants, generateSeedVariant } from './seed-generator';
function usage(): void {
process.stderr.write('Usage: seed-gen-cli --count <N> --output-dir <dir>\n');
}
const args = process.argv.slice(2);
let count: number | undefined;
let outputDir: string | undefined;
for (let i = 0; i < args.length; i++) {
if (args[i] === '--count' && args[i + 1] !== undefined) {
count = parseInt(args[++i]!, 10);
} else if (args[i] === '--output-dir' && args[i + 1] !== undefined) {
outputDir = args[++i];
} else {
process.stderr.write(`Unknown argument: ${args[i]!}\n`);
usage();
process.exit(1);
}
}
if (count === undefined || isNaN(count) || count < 1) {
process.stderr.write('Error: --count must be a positive integer\n');
usage();
process.exit(1);
}
if (!outputDir) {
process.stderr.write('Error: --output-dir is required\n');
usage();
process.exit(1);
}
mkdirSync(outputDir, { recursive: true });
const variants = selectVariants(count);
if (variants.length < count) {
process.stderr.write(
`[seed-gen] Note: --count ${count} exceeds the 1152-variant parameter space;` +
` generating ${variants.length} variants. The remaining ${count - variants.length}` +
` slots in evolve.sh will be filled by mutating the seed.\n`,
);
}
for (let i = 0; i < variants.length; i++) {
const text = generateSeedVariant(variants[i]!);
const filename = `variant_${String(i).padStart(3, '0')}.push3`;
const filepath = join(outputDir, filename);
writeFileSync(filepath, text + '\n', 'utf8');
process.stdout.write(filepath + '\n');
}