// 순서 무관 codeblock 메서드 집합 비교. 본문 미출력 — 이름·차이 카운트만. // 메서드 이동 리팩터의 무손실 검증용: 워킹트리 codeblock vs ref(기본 HEAD). // 사용: node tools/verify/cbset.mjs [ref] import { readFileSync } from 'node:fs'; import { execSync } from 'node:child_process'; const PATH = 'RootDesk/MyDesk/SlayDeckController.codeblock'; const ref = process.argv[2] || 'HEAD'; function methodsOf(jsonText) { const obj = JSON.parse(jsonText); const arr = obj.ContentProto.Json.Methods; const map = new Map(); for (const m of arr) { map.set(m.Name, { code: m.Code, exec: m.ExecSpace, params: JSON.stringify(m.Parameters || []) }); } return map; } const work = methodsOf(readFileSync(PATH, 'utf8')); const base = methodsOf(execSync(`git show ${ref}:${PATH}`, { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 })); const onlyWork = [...work.keys()].filter((k) => !base.has(k)); const onlyBase = [...base.keys()].filter((k) => !work.has(k)); const changed = []; for (const k of work.keys()) { if (!base.has(k)) continue; const a = work.get(k); const b = base.get(k); if (a.code !== b.code || a.exec !== b.exec || a.params !== b.params) changed.push(k); } console.log(`ref=${ref} work=${work.size} base=${base.size}`); console.log(`only-in-work (${onlyWork.length}): ${onlyWork.join(', ') || '-'}`); console.log(`only-in-base (${onlyBase.length}): ${onlyBase.join(', ') || '-'}`); console.log(`body/exec/params changed (${changed.length}): ${changed.join(', ') || '-'}`); const ok = onlyWork.length === 0 && onlyBase.length === 0 && changed.length === 0; console.log(ok ? 'RESULT: IDENTICAL SET (무손실)' : 'RESULT: DIFFERENCES ABOVE'); process.exit(ok ? 0 : 1);