fix: TechLog 리비전 셋을 매니페스트에 맞추고, 「경고 0건」을 두 가지로 가른다

부채 ④. TechLog 의 tech-log-design-package 가 ca1bbfe·1aae8dc·ffa088b 를 적고 있었는데
매니페스트는 그 뒤 다시 만들어져 세 파일 모두를 tech-log-frontend @ 0d4d1e5 로 적는다.
옛 셋은 tech-log-frontend 에 없다 — 옛 매니페스트가 안 남아 그 사이 계약 내용이 바뀌었는지는
대조할 수 없고, 그 사실을 verified 에 적었다. 기록의 「검증 환경」이 적은 리비전은 그때 잰
조건이라 고치지 않는다. 파일 sha256 셋을 함께 적어 리비전 문자열이 아니라 내용에 못박는다.

  check_evidence --repo TechLog     exit 0 「문제 없음」 (3 → 0)
  review-package.py TechLog         exit 0 · 관문 10 전부 exit 0

R14. 이 묶음의 막는 경고는 전부 편집 전후 보존 비교에서 나오고(review-package.py 의
_warn 자리 둘이 모두 if preservation.get("available") 안이다) 그 비교는 --before 를 줘야
돈다. 빼면 검토 관문이 아무 줄도 안 남기고 통과한다.

- --before 를 필수로 만들지 않는다. 새로 쓴 기록엔 윤문 전 사본이 없어 첫 기록이 막힌다.
  없다는 것을 적고 출력한다
- preservation.reason 으로 두 원인을 가른다 — NO_BEFORE · CHECKER_UNREADABLE
- 묶음이 자기 입력을 적는다. 줬으면 before·beforeSha256, 안 줬으면 명시적 null.
  빠진 칸과 null 은 다르다
- 종료 코드는 양쪽 다 0 이다. 새 관문이 아니라 읽는 계약이라 갈리는 것은 문구다.
  _review_gate 의 stderr 와 계획 한 줄 요약 둘 다 가른다
- B-B004c-plans/verdict.json 을 지웠다. 옛 묶음 53ce6a5b… 에 묶여 있는데 지금 계획은
  0beb5420… 이라 읽히지 않는다 — 검토를 받은 것처럼 보이는 파일이 남는다

python3 -m unittest discover -s scripts/tests — Ran 266 · OK (skipped=13)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
This commit is contained in:
DongHyeonka
2026-09-11 09:18:45 +09:00
co-authored by Claude Opus 5
parent d2855d1e6c
commit 0f753c3be5
4 changed files with 212 additions and 10 deletions
+22 -3
View File
@@ -160,7 +160,10 @@ def _preservation(before: str, record: str) -> dict:
path = os.path.join(ROOT, "scripts", "check-preservation.py")
spec = importlib.util.spec_from_file_location("check_preservation", path)
if spec is None or spec.loader is None:
return {"available": False}
# **「비교를 안 했다」와 「비교기를 못 읽었다」는 다른 일이다.** 같은 값이면
# 묶음을 읽는 쪽이 왜 비어 있는지 모른다
return {"available": False, "reason": "CHECKER_UNREADABLE",
"detail": f"check-preservation.py 를 못 읽었다: {path}"}
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
res = m.compare(open(before, encoding="utf-8").read(),
@@ -223,7 +226,12 @@ def build(project: str, record: str, figures_dir: str | None = None,
gates.append(_run(["python3", "scripts/check-figure-overlap.py", project]))
warnings: list[dict] = []
preservation = _preservation(before, rec_abs) if before else {"available": False}
# **빠진 칸과 null 은 다르다.** `--before` 를 줬으면 경로와 해시를, 안 줬으면 `None` 을
# 명시적으로 적는다. 안 적으면 「비교가 없다」가 「비교할 것이 없었다」와 구별되지 않는다
preservation = (_preservation(before, rec_abs) if before else
{"available": False, "reason": "NO_BEFORE",
"detail": "--before 를 안 줬다. 편집 전후 비교를 돌리지 않았다",
"before": None, "beforeSha256": None})
def _warn(entry: dict) -> None:
"""경고에 안정 키를 붙여 담는다.
@@ -288,6 +296,11 @@ def build(project: str, record: str, figures_dir: str | None = None,
"warnings 는 관문이 아니다. 종료 코드로 안 걸리는 것만 여기 올라온다 — "
"유보 표현이 줄어든 자리가 그것이고, 확신 승격이 딱 그 모양이다. "
"gates 가 전부 0 이어도 warnings 는 따로 읽는다.",
"**경고 0 건이 「봤는데 없었다」는 뜻이 아니다.** 이 묶음의 막는 경고는 전부 "
"편집 전후 보존 비교에서 나오고, 그 비교는 `--before` 를 줘야 돈다. "
"`preservation.available` 이 false 면 경고가 0 건인 것은 **사정권 밖**이지 "
"초록이 아니다. `preservation.reason` 이 왜 안 돌았는지 적는다 — "
"`NO_BEFORE`(안 줬다) · `CHECKER_UNREADABLE`(비교기를 못 읽었다).",
"이 묶음이 못 보는 것이 있다. 수치도 인용도 없이 더한 산문 — 자료에 없는 1인칭 "
"경험이나 선택 이유 — 은 보호 구간 비교로 원리적으로 안 보이고 gates 도 warnings 도 "
"비어 있다. 본문을 읽는 것 말고는 방법이 없다.",
@@ -318,9 +331,15 @@ def main() -> int:
with open(args.out, "w", encoding="utf-8") as fh:
fh.write(text)
failed = [g for g in pkg["gates"] if g["exit"] != 0]
pres = pkg["preservation"]
# **`--before` 를 필수로 만들지 않는다** — 새로 쓴 기록에는 윤문 전 사본이 없어서
# 첫 기록이 저장을 못 하게 된다. 없다는 것을 적고 출력하는 것으로 가른다
note = ("경고 %d" % len(pkg["warnings"]) if pres.get("available") else
"경고 0건 — 편집 전후 비교를 안 돌렸다(%s). 사정권 밖이지 초록이 아니다"
% pres.get("reason", "?"))
print(f"{args.out} — 증거 {len(pkg['evidence'])} · 주장 후보 "
f"{len(pkg['claimCandidates'])} · 관문 {len(pkg['gates'])}"
f" (exit≠0 {len(failed)}건) · 경고 {len(pkg['warnings'])}")
f" (exit≠0 {len(failed)}건) · {note}")
else:
print(text, end="")
return 0