먼저 쟀다. 경고를 일괄 차단으로 올리면 채택된 편집 9건이 막힌다 — V-004 에서 고친 바로
그 9건이다. 그래서 경고는 검토로 보내고 차단은 검토가 판정할 때 일어나게 뒀다.
코드로 막은 것 셋. code[] 리비전 — check_evidence 는 리비전이 있는지만 보고 인용한 코드가
그 리비전에서 왔는지는 안 본다. 이 배치에서 실제로 났고 사람이 손으로 잡았다. 한글 수사와
그 경계 — 「다섯 개 → 여섯 개」는 결정적이다.
앵커 검사기의 오탐을 0 으로 만드는 데 시간의 절반이 갔다. 처음 판이 저장소 전체에서
401건을 냈고 전부 오탐이었다. code[] 는 한 모양이 아니다 — 심볼, 축약 경로, 줄 범위,
호스트 절대 경로, 설정 키가 섞여 있다. 축약 경로를 「없다」로 세면 있는 코드를 없다고 하는
것이고 그게 채택된 편집 아홉 건을 막았던 실패와 같은 모양이다. 판정할 수 있는 것만
판정하고 못 보는 것은 세어서 낸다.
검토로 보낸 것 다섯. D2 는 아무 계수도 안 움직이던 자리였다 — 수치도 인용도 없이 산문만
더하면 보호 구간 비교에 잡힐 것이 없다. 1인칭 표지가 늘어난 것만 보고 그 문장을 짚어 준다.
판정이 아니라 라우팅이다.
만들다 버그를 찾았다. 경고가 인용하는 문장이 파일 첫 문단에서 한 글자씩 깎이고 있었다.
rfind 가 -1 을 낼 때 +2 를 해서 1 이 됐다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
verify-pipeline.py 의 FORBIDDEN_LITERAL 가드가 scripts/ 안에서 저장소
체크아웃 이름을 금지한다. B-005 의 회귀가 그 이름으로 실제 원장을 찾다가
PIPELINE CONTRACT 를 FAIL 로 만들었다. glob 으로 아무 원장이나 고르게
바꿨고 시험의 뜻은 그대로다 — 더한 칸이 있어도 검사기가 읽는가.
병합에서 드러난 계약 충돌이라 통합 브랜치에서 조정한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GksxvQvM6A85xy8viYtWk6
이어받은 단계에 앞 세션이 관문을 써도 그대로 들어갔다. 원자성 문제가 아니다 — 파일은
온전한 채로 두 세션의 기록이 섞인다. 그리고 관문마다 누가 적었는지가 없어서 나중에
원장을 읽어도 가릴 수 없었다.
begin 이 세대를 올리고 주인을 적는다. 낮은 세대나 다른 주인의 쓰기는 거절한다.
bin/task.py 의 attempt 와 같은 자리다.
gate 와 end 도 --session 을 받아 적는다. 관문마다 session·generation·at 이 남고
end 는 finishedBy 를 남긴다.
주인이 없는 단계는 그대로 받는다. 세션을 안 쓰는 단일 세션 사용이 깨지지 않는다.
회귀에 그 대조를 넣었다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
원장을 손으로 써 왔다. 그래서 셋이 없었다. 쓰는 도중에 끊기면 반쪽 파일이 남고, 단계마다
시작·끝이 없어 「돌다 말았다」와 「아직 안 시작했다」가 PENDING 하나로 같아 보이고, 런 도중에
끼어든 일이 어디에도 안 남는다.
bin/task.py 가 이 계약의 초안이다 — flock 을 잡고 임시 파일에 완성한 뒤 os.replace 로 바꾸고
startedAt 부터 지금까지를 누적에 더한다. 그 규약을 runs/ 쪽으로 옮겼다. 새로 만든 것이 아니다.
끊긴 단계를 새 세션이 다시 열면 그 구간을 닫고 잇되, 누적에만 더하지 않고 interruptions 에
따로 적는다. 닫은 구간에는 세션이 죽어 있던 시간이 섞인다 — 「이 단계가 오래 걸렸다」와
「중간에 끊겼다」는 다른 말이다.
라이더에 자리를 만들었다. 이 배치에서 검증 한 작업의 누적 24분 가운데 17분 50초가 라이더였는데
상태 파일에 그 구분이 없었다. 단계가 아니라서 어느 칸에도 안 남던 것이다.
상태 전이를 거절한다 — 이미 있는 런을 덮어쓰기, 단계 겹쳐 열기, 건너뛸 수 없는 단계 건너뛰기,
사유 없는 SKIPPED, 영수증 없는 DONE, 종료 코드 없는 관문.
더한 칸이 있어도 기존 검사기가 그대로 읽는다. 통과한 원장에 새 칸을 더해도 통과하는 것을
확인했다. 손으로 쓴 원장도 계속 유효하고 이 도구는 선택적으로 부른다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
R5 — 원장은 관문의 명령과 종료 코드를 적는데 **그 명령이 어느 대상에 돌았는지는 아무도
안 봤다.** 다른 프로젝트에 돌려 받은 exit 0 을 적어도 통과로 셌다. `_wrong_target()` 이
`docs/<이름>/` 경로와 명령 인자의 프로젝트 이름 둘 다 본다.
정상 원장 넷 새 error 0 (B 의 document-haness 원장 PASS · warn 3)
프로젝트 인자를 바꾼 원장 FAIL 「관문이 다른 대상에 돌았다」
기록 경로를 바꾼 원장 FAIL
**유효 범위를 docstring 에 적었다** — 「다른 프로젝트」만 본다. 같은 프로젝트의 다른 기록에
돌린 관문은 안 잡는다. 기록 단위까지 보려면 관문마다 대상 단위를 계약이 먼저 정해야 한다.
R12 — `check-required-content.py` 를 `OUTPUT_CHECKS` 에 더한다. B-003 이 병합돼 이제 된다.
세 상태 표를 지키는 것을 확인했다 — `ca-tmpl` exit 2 · `keycloak-session-store` exit 0 ·
없는 프로젝트 exit 2.
`OUTPUT CHECKS` 의 error 가 5 → 7 이 된다. **부채가 늘어난 것이 아니라 세는 자리가 늘었다** —
`ca-tmpl` 에 계약이 없다는 한 사실이 `check_evidence` · `check-required-content` ·
`TECH LOG TREES` 세 곳에서 셈된다. 같은 사실을 세 번 세지 않는다.
회귀 `scripts/tests/test_run_target.py` 2건 (123 → 125). **「정상 원장은 그대로 통과한다」
대조를 함께 넣는다** — 무조건 거절로 성공률을 올리는 것이 R-003 이 든 실패다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wp9jNbePAmWc5jQwCYhK9v
문장 쪽에는 놨는데 그림 쪽에는 안 놨다. 화살표를 뒤집어도 관문이 전부 0 이고 경고도 비어
자동 통과했다.
설계가 「SVG 의 스크립트·외부 리소스는 저장 단계의 허용 정책으로 제한한다」고 적었는데 그
정책이 코드로 어디에도 없었다. 화살표 방향은 사람이 봐야 하지만 스크립트가 들어 있는지는
문자열로 판정된다 — 그림 쪽에서 기계가 할 수 있는 유일한 일이라 error 로 막는다.
script·foreignObject·이벤트 처리기·바깥 href·바깥 리소스·@import 여섯이다.
#fragment 와 data: 는 바깥으로 안 나가므로 막지 않는다.
그림이 검토 뒤에 바뀌면 경고로 올린다. 무엇이 바뀌었는지는 기계가 못 말하지만 바뀌었으니
보라는 말할 수 있다. 이것이 들어가면서 읽기 계약이 그림에도 걸린다.
실제 흐름과 개념 설명을 data-figure-kind 로 가른다. 표시가 없으면 error 가 아니라
warning 이다 — 지금 저장소의 그림 272장에 이 표시가 하나도 없고, 없다고 전부 막으면
정상을 막는 쪽으로 넘어간다. 설명용이라 밝힌 그림도 막지 않는다.
검사기를 조일 때마다 정상이 통과하는 대조를 같이 넣는다. 이번 대조군은 평범한 그림,
설명용이라 밝힌 그림, 내부·data 참조, 그리고 이 저장소의 그림 272장 전부다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
「확인하지 못한 것」 절을 통째로 지운 편집이 경고를 비운 채 지나갔다. 배관 문제가 아니라
실을 것이 없었다 — 지운 절에 보호 구간이 없었고 그 절의 문장이 유보 목록에 없었다.
그래서 「경고가 비면 자동 통과」라는 읽기 계약으로도 그대로 통과한다.
유보 목록이 추정·가능성 쪽에만 몰려 있었다. 한계를 밝히는 말은 대개 「안 했다」 모양인데
그쪽이 얇았다. 두 갈래로 나누고 뒤쪽을 채웠다.
그리고 `##` 절이 통째로 사라지면 그 자체를 경고에 올린다. 무엇이 사라졌는지는 절 제목으로
충분하다.
error 를 늘리지 않았다. 판정하는 것이 아니라 보이게 하는 것이다. 절을 덜어 낸 것인지
한계를 지운 것인지는 근거를 읽어야 안다.
채택된 편집 100쌍을 다시 돌려 막은 쌍이 1 그대로인 것을 확인했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
사람이 채택한 편집 100쌍 중 9건을 막고 있었다. 막은 것이 전부 자료가 뒷받침하지 않는
덧붙인 이득과 되풀이를 지운 편집이고, 지운 문장 안에 숫자나 인용부호가 있었다는 이유로
막혔다. 반대로 「확인하지 못한 것」 절을 통째로 지운 편집은 통과했다.
부수 문장 삭제와 조건 삭제는 같은 연산이다. 지운 문장에 숫자가 있었는지로는 안 갈린다.
그래서 사라진 것은 warning 으로 내리고 새로 생긴 것만 error 로 둔다. 없던 수치·인용·코드를
더한 것은 날조이고 그것은 코드가 판정할 수 있다.
경계도 고쳤다. `(?![\w.-])` 의 `\w` 가 한글도 낱말 문자로 세어 `500행`·`5개다` 처럼 조사나
명사가 붙으면 보호가 통째로 풀렸다. 한국어에서 숫자는 거의 항상 뭔가가 바로 붙으므로
보호가 가장 필요한 자리에서 가장 안 걸렸다.
경고마다 그 값이 있던 문장을 함께 낸다. 기제와 수치까지만 있으면 검토자가 다시 찾아야 한다.
review-package 의 reviewerNotes 맨 위에 읽는 계약을 넣었다 — gates 가 전부 0 이어도 그것만
으로 통과가 아니고, warnings 가 비어 있어야 자동 통과다.
막은 쌍 9 → 1. 남은 하나는 편집이 인라인 코드를 새로 넣은 쌍이라 규칙이 제대로 도는 것이다.
0 으로 만들려면 그 규칙을 풀어야 하고 그러면 지어낸 식별자가 함께 통과한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
서버 계약은 tech-log-backend @ a000f87 의 openapi 와 컨트롤러에서 읽었다.
Idempotency-Key 는 필수이고 200자 이하다. expectedVersion 은 스키마가 minimum 1 로
못 박으므로 빈 값은 「검사 안 함」이 아니라 「반드시 충돌」이다.
멱등 키를 기록 경로에서 유도한다. 프런트는 호출마다 새 uuid 를 만들어서 재시도가 문서를
둘 만든다. 만들기는 경로만으로 키를 만들어 몇 번을 다시 시도해도 문서가 하나이고,
저장은 보낼 내용을 키에 넣는다 — 경로만 쓰면 두 번째 저장이 첫 결과로 조용히 재생된다.
게시 요청을 만드는 코드가 없고, 계획이 게시 경로를 가리키면 거절한다. 지금까지 게시를
막고 있던 것은 스킬 문서의 문장 하나였다.
무인 저장은 꺼져 있다. 서버 권한이 studio:read·studio:write 둘뿐이라 저장 계정이 게시도
할 수 있다. 켜는 것은 studio:publish 가 갈라진 뒤의 판단이지 이 파일의 기본값이 아니다.
저장 뒤 되읽어 견줄 때 문자열 하나로 판정하지 않는다. 정규화가 지운 차이를 통과로 세면
비교 틀이 결함을 만들어 내거나 지운다. 정규화 뒤에만 같아지는 것은 whitespaceOnly 로,
되읽은 값이 보낸 값의 앞부분인 것은 truncated 로 따로 낸다. 못 보는 칸은 사유와 함께
적는다 — 조용히 건너뛰면 「전부 같다」가 「본 것만 같다」를 가린다.
회귀의 첫 줄은 대조군이다. 손대지 않은 쌍이 「같다」로 나오지 않으면 나머지 「잡았다」가
전부 틀 탓이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
겹침 검사기의 적용 범위를 적는다 — 판정에 쓰는 것은 <rect> 뿐이라
techviz 가 만든 SVG 에서만 유효하다. 손댄 SVG 는 배경 사각형이 안
따라 바뀌어 겹침이 있어도 없다고 답한다.
그리고 관문의 종료 코드를 셋으로 가른다. 「대상이 성립하지 않는다」를
exit 2 로 두어 오타 한 번에 관문이 조용히 무효가 되는 것을 막는다.
__pycache__ 는 .gitignore 에 이미 있는데 이 .pyc 하나만 추적되고 있어
두 세션의 작업 트리를 계속 더럽혔다. 추적에서 뺀다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GksxvQvM6A85xy8viYtWk6
R4 · R13 · R6 · R3. 네 가지가 같은 자리를 본다 — 검사기가 대상을 못 찾았을 때 무엇을
내는가.
세 상태를 가른다 (CLAUDE.md 「검사」 절의 표).
봤고 괜찮다 exit 0 문제 없음 · error 0
대상이 성립하지 않는다 exit 2 대상이 성립하지 않는다 — <이유>
볼 것이 아직 없다 exit 0 기록 0건 — 아직 쓴 기록이 없다
R4 — 없는 프로젝트를 주면 여섯 중 넷이 초록을 냈다. `verify-tech-log-tree.py` 는 그것을
「프로젝트 1 · error 0 · PASS」로 셌다 — 오타 한 번이면 검사를 다 돈 것처럼 보인다.
판정은 `techlog.check_targets()` 하나로 모은다. 여섯 곳에 같은 규칙을 따로 쓰면 다음에
하나만 어긋난다. `check_evidence.mjs` 는 이미 exit 2 라 문구만 맞춘다.
R13 — 프로젝트 이름 쪽만 고치면 `--file` 로 오타를 내는 순간 다시 조용히 0건이 된다.
`techlog.check_files()` 로 같은 자리에 둔다. `preview-figure.py` 는 인자가 아예 없을 때
exit 1 을 냈는데 그것도 「대상이 성립하지 않는다」다.
R6 — 두 자리를 함께 고쳐야 했다.
(a) `verify_projects()` 가 `docs/*/tech-log-studio` 만 훑어 계약 없는 프로젝트가
목록에서 사라졌다. 기준을 `final/document.md` 로 바꾼다 — SSOT 가 있으면 대상이다.
(b) `verify-tech-log-tree.py:194` 가 「분해 계약 없음」을 warn 으로 냈다. CLAUDE.md 는
「계약 미채택도 error 다 — 경고로 두면 옛 스키마로 남아 있는 한 검사를 피한다」고
적어 두었는데, 경고로 두었더니 실제로 그렇게 됐다.
R3 — `verify-pipeline.py` 가 `check-figure-text.py` 와 `check_evidence.mjs --repo` 를
프로젝트마다 돌린다(`OUTPUT CHECKS`). 게시 전에 돌리라고 적어 둔 검사인데 전체 훑기가
부르지 않아 결함이 있는 채로 PASS 로 보고됐다. `check-required-content.py` 자리는 주석으로
남겨 둔다 — 그 파일이 들어온 뒤에 더한다.
회귀 `scripts/tests/test_no_target.py` 7건 (92 → 99). 「실재하는 경로는 통과한다」 대조를
함께 넣는다 — 무조건 거절로 성공률을 올리는 것이 R-003 이 든 실패다. 판정을 일부러
되돌려 FAILED 가 나는 것을 확인한 뒤 복구했다.
알려진 부채는 그대로 둔다. `verify-pipeline.py` 는 exit 1 이다 — 미준수 런 1건과
`OUTPUT CHECKS` 5건, 그리고 `ca-tmpl` 의 계약 없음이 이제 `TECH LOG TREES` 에서도 보인다.
같은 사실이고 두 번 세지 않는다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wp9jNbePAmWc5jQwCYhK9v
R2 — `stage-contracts.md` 「관문 요약」이 정본인데 `STAGES` 가 넷을 빠뜨리고 있었다.
S4 `preview-figure.py` · S5 `check_evidence.mjs` · S6 `check_body.mjs`·`check_evidence.mjs` ·
S7 `build-tech-log-tree.py` 를 더한다.
그리고 `style_profile.mjs` 는 관문이 아니라 측정이다 — 문서 계약이 「error 0」을 붙인 것은
`check_prose` 뿐이다(`stage-contracts.md:178`·`:252`). 그런데 원장 검사기가 exit≠0 을 전부
error 로 세어서, 정직하게 exit 1 로 적은 원장은 무조건 실패하고 0 으로 고쳐 적으면 그건
지어낸 것이 된다. `MEASUREMENT_GATES` 로 갈라 **돌았다는 것만 요구하고 종료 코드 0 은
요구하지 않는다.** 대신 `exit` 칸이 없으면 error 다 — 안 돌리고 넘어가는 것을 막는다.
곁증명(`_side_proof`)에도 같은 규칙을 넣는다.
대조군 셋으로 확인했다.
preview-figure 를 뺀 원장 → FAIL 「관문이 빠졌다」
style_profile 을 exit 1 로 적은 원장 → PASS
style_profile 의 exit 칸을 지운 원장 → FAIL 「측정 관문의 종료 코드가 없다」
이 변경으로 `runs/virtualization/2026-09-08-1958/run.json` 이 빨개진다. S6 에서
`check_evidence.mjs` 를 실제로 안 돌린 원장이라 맞는 결과다. 낮춰서 초록으로 만들지 않는다.
R10 — `scripts/terminal-evidence/tests/` 가 문서에 적힌
`unittest discover -s scripts/tests` 범위 밖이고, 직접 `discover` 를 걸면 `render_terminal`
import 경로가 `sys.path` 에 없어 깨진다. 회귀가 초록인데 아무도 안 부르는 상태였다.
`scripts/tests/test_terminal_evidence.py` 가 `load_tests` 로 경로를 얹고 끌어온다 (86 → 92).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wp9jNbePAmWc5jQwCYhK9v
형식 관문 여덟이 확신 승격·수치 조작·화살표 뒤집기·필수 칸 삭제를 하나도 못 막는
것이 재현됐다. 그 가운데 결정적으로 판정 가능한 것을 코드로 옮긴다.
check-required-content.py — 종류가 요구하는 칸이 없거나 비었는지 본다.
audit-records.py 는 평문 칸 안에 마크업이 있는지만 보고 칸이 있는지는 안 센다.
고정 목차·자료 개수·답은 강제하지 않는다. 답이 없는 QUESTION 은 정상이고
「다음 검증」이 빈 것만 결함이다.
대상이 성립하지 않으면(프로젝트 없음·계약 없음) exit 2 로 막고, 계약은 있고 기록이
0건이면 통과시키되 초록으로 두지 않는다. 「봤고 괜찮다」와 「볼 것이 없어서 통과」는
다르다.
check-preservation.py — 윤문 전후를 견준다. 지금 관문 가운데 편집 전후를 보는 것이
하나도 없어 수치를 바꾸거나 유보를 지운 편집이 그대로 통과했다.
사라진 것과 새로 생긴 것을 따로 센다. 새로 생긴 수치는 지어낸 값일 수 있다.
유보 표현이 줄면 내되 옳은지는 판정하지 않는다. 늘어난 것은 세지 않는다.
review-package.py — 아무것도 판정하지 않는다. 판정할 사람이 받을 것을 모은다.
해시·검사기 버전·여기서 실제로 돌린 관문·주장 후보·판정 기준. 종료 코드로 안 걸리는
것은 warnings 로 따로 올린다 — 확신 승격이 딱 그 모양이라 안 실으면 아무도 못 본다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
두 가지가 겹쳐 있었다.
줄 맨 앞 앵커 때문에 `curl -H "Authorization: Bearer ..."` 처럼 명령 인자 안에 든
자격증명을 놓쳤다. 터미널 증거에서 Bearer 가 가장 흔히 나오는 자리가 그 명령줄이다.
그리고 키워드 패턴의 값이 `[^\s,;]+` 라 공백까지 먹어 닫는 따옴표를 넘어갔다.
`curl -H "X-Api-Key: TESTONLY-x" https://...` 가
`curl -H "X-Api-Key: [REDACTED] https://...` 가 된다. 다중 -H 에서는 다음 인자의
경계까지 무너진다. 증거에 실린 명령이 실제로 돌린 명령과 달라진다.
값의 끝을 따옴표 앞에서 막되, 감싼 따옴표는 되돌려 놓는다. 문자 집합만 좁히면
`TOKEN="eyJ..."` 가 여는 따옴표에서 막혀 아예 안 가려진다.
함께 메운 것: Authorization/Proxy-Authorization 의 Basic, `curl -u`/`--user`
(사용자 이름은 남긴다 — 어느 계정으로 붙었는지가 증거의 일부다), 그리고 JWT.
회귀는 「가려졌는가」만 묻지 않는다. 원문과 따옴표 수가 같은지 함께 본다.
앞선 회귀가 그것을 안 물어서 이 결함을 통과시켰다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
capture-evidence.py 는 명령을 subprocess 로 직접 돌리고 그 프로세스의 반환값을
그대로 메타에 적는다. 종료 코드를 인자로 받지 않으므로 손으로 적을 경로가 없다.
raw 원문과 실행 메타가 같은 이름으로 함께 떨어져 「raw 는 있는데 meta 가 없다」가
구조적으로 안 생긴다.
skill-versions.py 는 스킬 9개의 metadata.version 과 검사기 17개의 내용 해시를
한 장으로 낸다. 통과 판정을 검증기 버전에 묶으려면 묶을 값이 있어야 한다.
버전 칸이 없던 스킬 여덟에 1.0.0 을 붙였다. 산문은 한 줄도 안 바꿨다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
글감 1,001개 중 제1부(§3~§11) 앵커를 하나라도 가진 것은 112개뿐이었다. 나머지 889개는
제2부 모듈 분석 65편의 절 제목에서 나온 것이고, 그것이 재판정이 필요했던 이유다.
주제 44 → 16 (43개가 독자 질문 없이 있었다. 지금은 전부 있다)
글감 1,001 → 123 (제1부 앵커 112 + 제1부가 채택했는데 비어 있던 자리 11)
후보 965 → 1,088 · PENDING 905 → 0
error 3,042 → 0
내려온 889개는 후보 대장에 KEEP_IN_SSOT 로 남는다 — 버린 것이 아니라 분석에 남기고 독립
기록으로 만들지 않기로 한 것이다. 그 글감을 받치던 기록 파일 828개는 지웠다. 계약이 정본이고,
파일이 남아 있다는 이유로 계약에서 뺀 주제가 되살아나면 안 된다. 이력에는 그대로 있다 —
git checkout a0ca2bb -- <경로>.
제1부가 채택했는데 글감이 없던 자리 열하나를 채웠다: mongo high-water mark 가 재전달 이벤트를
삼킨 P1, admin plane 이 가드만 켜고 서비스는 켜지 않은 것과 그 짝인 결정, 실패 어휘 세 층과
SQLState 매트릭스 병합 규칙, 부하 아래에서만 새는 admission 경계, 발행 증거와 완료 판정의
분리, keyset·JSONB 결정 둘.
Concept 17개에 basis-version 을 채우고, 계약 제목과 기록 제목이 갈라져 있던 23건을 기록 쪽에
맞췄다. candidateScope 에 excludedAnchorPattern 을 적어 제2부 앵커만 가진 글감이 다시 올라올
수 없게 한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
keycloak-session-store 와 TechLog 는 SSOT 만 있고 분해 계약이 없었다. 두 프로젝트
모두 후보를 처분과 함께 남기고 PROMOTE 만 주제로 올린다.
keycloak-session-store 주제 6 · 글감 33 · 후보 42 (제외 9)
TechLog 주제 13 · 글감 56 · 후보 91 (제외 35)
TechLog 는 저장소가 셋이라 sourceRepository 를 목록으로 적는다. 설계 패키지는 이
기계에 체크아웃이 없고 반입한 쪽의 MANIFEST.sha256 이 세 계약의 원본 리비전을
고정하므로 그것을 리비전으로 적었다. 검사기 둘이 그 모양을 읽게 고친다 —
verify-tech-log-tree.py 는 목록의 항목마다 path·revision·verified 를 보고,
check_evidence.mjs 는 체크아웃이면 git 으로, 매니페스트면 그 파일이 리비전을
적고 있는지로 대조한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
리뷰 두 건을 반영했다.
계약
- tech-log-tree.json 하나가 분해 계약이자 색인이다. 사람이 읽는 트리·Node Specification·
후보 대장은 없어졌고, 문서에 남아 있던 그 개념을 걷어냈다
- candidateScope — 후보를 찾는 SSOT 범위. 접어 넣은 제2부·제3부는 근거이지 후보가 아니다
- sourceRepository — 분석한 저장소의 경로·리비전·판단 근거. 리비전을 모르면 null 로 두고
지어내지 않는다. 갈래가 여럿이면 revisions
- 검사기: 계약 미채택·PENDING·PROMOTE↔글감 양방향·candidateScope·sourceRepository 를
error/warn 으로 센다. 옛 스키마도 검사를 피하지 못한다. 테스트 22 → 31
기록 쓰기
- 템플릿 5종에 source·sourceRevision·topicName, Question 에 닫는 조건, 본문 없는 종류에서
assets 제거. 고정 절 개수 삭제
- check_evidence.mjs — 인용한 코드가 SSOT 에 있는지, 앵커가 SSOT 를 가리키는지, 제목이
계약과 같은지, 리비전이 저장소에 있는지. 게시된 기록에서 SSOT 와 다른 URL 을 잡았다
문체
- 문체 규칙의 정본을 ai-tells.md 로. explaining.md 의 질문체 제목·절 끝 대조 반복·그림 예고
규칙을 삭제해 충돌을 없앴다. 첫 절 「설명 뒤에 평가를 붙이지 않는다」에 지우는 사례 네 유형
- voice 스킬의 「독자 쪽을 본다」를 자료에 오독 기록이 있을 때로 좁히고, 평가만 더한 예시를 교체
- check_prose: 안내 문장을 요구하던 경고 제거, 문장이 끝나지 않은 채 문단이 끝나는 조각 검사 추가
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.run/의 세 런을 조사한 결과 claridoc run 파이프라인이 한 번도 완주하지
않았다. quality-gate.json 0건, stages/ 및 rounds/ 부재. 실사용 범위는
validate/collect/outline까지였고 글쓰기와 검수는 스킬이 담당했다.
파이썬 패키지, CLI, 스키마, 테스트, 예제, 조사 자료, 빌드·배포 산출물,
하네스 규약 문서를 제거한다. 남는 것은 Agent Skill 세 개, .run/의 문서
세 편, CLAUDE.md, README.md, LICENSE, 제거 결정 문서다.
examples/golden의 구버전 초안 두 편(n+1liner.md 1416줄,
claridoc-rewrite/document.md 1626줄)과 루트 document.md(.run 판과 md5
동일한 사본)도 함께 지운다. .run/에 더 진행된 판이 있다.
복구: git checkout pre-harness-removal -- <경로>
근거: docs/decisions/2026-08-07-remove-claridoc-harness.md
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>