ktworkflow-mcp/scripts/build-live2d-variable-decisions.ts

85 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
import { resolveInsideRoot } from "../src/core/workspace.js";
import type { Live2DModuleMigrationDecisionCatalog } from "../src/tools/live2dModuleMigrations.js";
import {
buildLive2DVariableNameDecisionCatalog,
sha256Live2DVariableInput,
type Live2DVariableReviewReport,
} from "../src/tools/live2dVariableNames.js";
interface CliOptions {
moduleDecisionPath: string;
outputPath: string;
reportPaths: string[];
}
/** Parses bounded workspace paths for the deterministic variable decision builder. */
function parseOptions(argv: string[]): CliOptions {
const args = new Map<string, string>();
for (let index = 0; index < argv.length; index += 2) {
const key = argv[index];
const value = argv[index + 1];
if (!key?.startsWith("--") || value === undefined) {
throw new Error(`Invalid Live2D variable decision argument near ${key ?? "<end>"}`);
}
args.set(key.slice(2), value);
}
const reportPaths = (
args.get("reports") ??
[
".kt-workspace/subagents/results/2026-07-16-live2d-variable-review-a.json",
".kt-workspace/subagents/results/2026-07-16-live2d-variable-review-b.json",
".kt-workspace/subagents/results/2026-07-16-live2d-variable-review-c.json",
].join(",")
)
.split(",")
.map((entry) => resolveInsideRoot(entry.trim()));
return {
moduleDecisionPath: resolveInsideRoot(
args.get("module-decisions") ??
"docs/live2d-deobfuscation/module-migration-decisions.json",
),
outputPath: resolveInsideRoot(
args.get("output") ?? "docs/live2d-deobfuscation/variable-name-decisions.json",
),
reportPaths,
};
}
/** Reads one typed JSON input while its semantic shape is validated by the builder. */
function readJson<T>(filePath: string): T {
return JSON.parse(readFileSync(filePath, "utf8")) as T;
}
/** Builds all 1,747 explicit source binding decisions and writes stable pretty JSON. */
function main(): void {
const options = parseOptions(process.argv.slice(2));
const moduleCatalog = readJson<Live2DModuleMigrationDecisionCatalog>(
options.moduleDecisionPath,
);
const catalog = buildLive2DVariableNameDecisionCatalog({
moduleCatalog,
reports: options.reportPaths.map((reportPath) => {
const source = readFileSync(reportPath, "utf8");
return {
report: JSON.parse(source) as Live2DVariableReviewReport,
sha256: sha256Live2DVariableInput(source),
};
}),
});
mkdirSync(path.dirname(options.outputPath), { recursive: true });
writeFileSync(options.outputPath, `${JSON.stringify(catalog, null, 2)}\n`, "utf8");
process.stdout.write(
`${JSON.stringify({
decisionCount: catalog.decisions.length,
outputPath: path.relative(resolveInsideRoot("."), options.outputPath).replaceAll("\\", "/"),
sourceSha256: catalog.sourceSha256,
})}\n`,
);
}
main();