refactor: 문서 개선 중

This commit is contained in:
donghyeon-ka
2026-09-21 14:30:55 +09:00
parent c93cdea150
commit 805a18f486
1497 changed files with 525837 additions and 59152 deletions
@@ -9,6 +9,12 @@
// 2. frontmatter 의 source 앵커가 SSOT 를 가리키는가
// 3. 기록의 title 이 계약(tech-log-tree.json)의 title 과 같은가
//
// exit code:
// 0 = 확인한 범위에서 일치
// 1 = 실제 불일치
// 2 = 검사 대상/인자가 성립하지 않음
// 3 = --repo 원본이 이 머신에 없어 저장소 대조를 수행하지 못함
//
// 검사기가 못 보던 자리다. `verify-tech-log-tree.py` 는 slug 와 칸의 존재만 보고,
// 인용한 코드가 실재하는지도 제목이 계약과 같은지도 보지 않는다.
import { readFileSync, readdirSync, statSync, existsSync } from "node:fs";
@@ -82,6 +88,9 @@ function inSsot(line) {
}
const findings = [];
// 저장소가 이 머신에 마운트되지 않은 상태는 evidence mismatch가 아니다.
// 확인 자체를 못 한 것이므로 별도 상태로 보존하고 exit 3으로 돌려준다.
const unverifiable = [];
const studio = join(base, "tech-log-studio");
for (const topicDir of readdirSync(studio)) {
const tp = join(studio, topicDir);
@@ -140,7 +149,10 @@ if (withRepo) {
for (const repo of repos) {
const name = repo.name || project;
if (!repo.path) { findings.push(["tech-log-tree.json", "sourceRepository.path 가 없다", name]); continue; }
if (!existsSync(repo.path)) { findings.push(["tech-log-tree.json", "저장소 경로가 없다", `${name}${repo.path}`]); continue; }
if (!existsSync(repo.path)) {
unverifiable.push(["tech-log-tree.json", "저장소 경로가 이 기계에 없다", `${name}${repo.path}`]);
continue;
}
// 갈래가 여럿이면 revisions 로 적는다. 둘 다 없으면 verify-tech-log-tree.py 가 warn 을 낸다
const revs = repo.revision ? { revision: repo.revision } : (repo.revisions || {});
// 체크아웃이 없는 저장소는 반입한 쪽의 매니페스트가 리비전을 고정한다. 그럴 때는
@@ -166,12 +178,31 @@ for (const [f, rule, detail] of findings) {
if (!grouped.has(rule)) grouped.set(rule, []);
grouped.get(rule).push(`${f}${detail}`);
}
const unverifiableGrouped = new Map();
for (const [f, rule, detail] of unverifiable) {
if (!unverifiableGrouped.has(rule)) unverifiableGrouped.set(rule, []);
unverifiableGrouped.get(rule).push(`${f}${detail}`);
}
console.log(`\n[${project}] 증빙 대조${withRepo ? " (저장소 포함)" : ""}`);
if (!findings.length) { console.log(" 문제 없음"); process.exit(0); }
for (const [rule, items] of [...grouped].sort((a, b) => b[1].length - a[1].length)) {
console.log(`${String(items.length).padStart(4)} ${rule}`);
for (const it of items.slice(0, 3)) console.log(` · ${it}`);
if (items.length > 3) console.log(` … 외 ${items.length - 3}`);
}
console.log(`\n합계 ${findings.length}`);
process.exit(1);
for (const [rule, items] of [...unverifiableGrouped].sort((a, b) => b[1].length - a[1].length)) {
console.log(` ? ${String(items.length).padStart(4)} ${rule}`);
for (const it of items.slice(0, 3)) console.log(` · ${it}`);
if (items.length > 3) console.log(` … 외 ${items.length - 3}`);
}
if (!findings.length && !unverifiable.length) {
console.log(" 문제 없음");
process.exit(0);
}
if (findings.length) {
console.log(`\n불일치 ${findings.length}건 · 대조 불가 ${unverifiable.length}`);
process.exit(1);
}
console.log(`\n불일치 0건 · 대조 불가 ${unverifiable.length}`);
process.exit(3);