refactor: 문서 개선 중
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user