virtualization 의 setup 9편은 같은 커밋(2109f72)에서 한꺼번에 생겼는데 그때
Studio 반입이 7편만 덮고 둘을 빠뜨렸다. 둘 다 readiness 가 READY 이고 관문도
통과하는데 frontmatter 에 id 도 studio 도 없었다 — Studio 문서가 아예 없었다는
뜻이다. 빼놓을 이유가 없어서 만들었다.
- setup-tear-down-the-lab-and-know-what-survives -> 87e0138d-…
- setup-power-cycle-the-lab-and-reallocate-guest-memory -> 8a9ca3d4-…
주제는 새로 만들지 않고 같은 폴더의 기존 편에서 topicId·projectId 를 읽어
같은 값을 썼다. 둘 다 저장까지만 하고 게시하지 않았다(currentPublication: null).
pinnedVersions 의 40자 상한
- power-cycle 의 「기준 배치」 값이 51자여서 서버가 422 로 거절했다
(size must be between 1 and 40)
- 그 칸에 문장이 들어가 있었다. CLAUDE.md 는 Setup 에 대해 「명령이 본문에
들어가고 버전만 pinnedVersions 에 남는다」고 적는다
- 잘라내기 전에 그 설명이 본문에 있는지 먼저 봤다. 셋 다 있었다 — 63행이
호스트 RAM 증설, 176행이 2026-09-03, 215행이 2026-09-10 과의 날짜 엇갈림.
그래서 날짜만 남겼고 잃은 내용이 없다
- 저장소 전체를 훑어 40자를 넘는 값은 이것 하나뿐이었다
기록 두 편의 diff 는 frontmatter 뿐이고, tech-log-tree.json 은 파생 칸
(publication · studioId) 넷만 바뀌었다. 「게시됨」은 Studio 에 있다는 뜻이지
공개됐다는 뜻이 아니다.
관문: check_body PASS · check_prose error 0 · check_evidence 문제 없음 ·
verify-tech-log-tree error 0 · verify-project-layout error 0 ·
check-studio-whitespace PASS
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`bbd87dc` 에서 Studio 편집기가 다시 쓰는 공백을 맞춰 뒀는데 바로 다음
커밋 `7661f08` 에서 B-0 본문을 보강하며 같은 자리를 되살렸다. 사람이 눈으로
지키는 것으로는 안 되는 종류라 검사기를 만든다.
- setup-reproduce-b0-default-session-store.md 의 빈 줄 하나를 지웠다.
Studio 저장본과 편집 화면 미러가 1바이트 달랐던 원인이다
- scripts/check-studio-whitespace.py — 이어진 빈 줄과 닫는 펜스 뒤 빈 줄을
studio-body.py 로 변환한 모양에서 찾는다. --fix 로 고친다
검사 범위는 Case·Concept·Setup 뿐이다. Reference·Question·Decision 의 칸은
평문으로 렌더링되므로 블록 편집기를 거치지 않는다 — 범위를 안 좁히면 그
세 종류에서 47곳이 걸려 실제 결함이 묻힌다. 요약 줄이 안 본 기록 수를 따로 센다.
STUDIO WHITESPACE: PASS — 본문 있는 기록 193 · 본 것 193 · 어긋난 곳 0
· 못 본 기록 0 · 본문 없는 종류라 안 본 기록 175
`check_body` 는 이 결함을 못 잡는다 — 공백이 달라도 파싱은 성립한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
남아 있던 한 편이다. keycloak-pattern 에 이 실험과 무관한 변경이 39개(미추적
3개 더) 있어 따로 떼어낸 작업 트리에서 파일 넷을 고치고 이미지를 구워 두
노드에 넣었다. 원래 작업 트리는 한 글자도 안 바뀌었다.
자동구성이 고른 것
- 빈 321개 — 이 편이 예측한 숫자와 같다
- authorizedClientService -> InMemoryOAuth2AuthorizedClientService
- SessionRepository 빈이 하나도 없다. Spring Session 이 아예 안 걸렸고
세션을 톰캣이 자기 메모리의 HttpSession 에 직접 들고 있다
- 타입에 Redis 나 Jdbc 가 든 빈 0개
로그인이 replica 개수에서 갈린다
- 원 가이드는 브라우저로 한 번 해 보라고 적는데 그러면 한 번의 결과만 남는다.
쿠키 병을 쓰는 curl 로 같은 흐름을 여섯 번씩 돌려 양쪽을 같은 수로 견줬다
- replica 2 — 여섯 번 다 /login?error
- replica 1 — 여섯 번 다 200. 이쪽이 대조군이라, 거기서도 실패했으면 가설이
아니라 시험 방법을 의심해야 한다
- 토큰 경계는 원래 실행과 한 글자도 다르지 않았다
원상복구를 같은 명령으로 확인했다
- 빈 321 → 437, InMemory → Jdbc, Redis/Jdbc 빈 0 → 58, Redis 세션 키 6
- replica 2 에서 로그인이 다시 되는 것이 복구 판정이다
그리고 ⑤ 의 `git diff --stat` 점검은 작업 트리가 깨끗할 때만 성립한다는 것을
적었다. git worktree 로 떼어내면 그 점검이 다시 살아난다.
관문: check_body PASS · check_prose error 0 · check_evidence 문제 없음 ·
verify-tech-log-tree error 0 · verify-project-layout error 0 · 코드펜스 전수 0건
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Studio 의 블록 편집기는 본문을 화면에 풀 때 공백을 정규화한다. 이어진 빈 줄
둘을 하나로 줄이고, 닫는 코드펜스 뒤에 빈 줄이 없으면 하나를 넣는다. 저장된
값은 저장소와 바이트가 같지만, 사람이 편집 화면을 열고 저장을 누르는 순간
그 공백이 저장소와 갈린다 — 내용은 그대로인데 SHA 만 달라져서 어느 쪽이
정본인지 알 수 없게 된다.
setup 35편을 훑어 9편 11곳을 찾아 저장소 쪽을 편집기와 같은 모양으로 맞췄다.
빈 줄만 움직였고 내용 줄은 하나도 바꾸지 않았다(추가 2 · 삭제 9).
- 이어진 빈 줄 둘 → 하나: d4 · d4a(3곳) · a7 · b7a · c2 · b0 · tear-down
- 닫는 펜스 뒤 빈 줄 추가: c1 · create-three-guests
코드블록 안의 빈 줄과 frontmatter 는 건드리지 않았다.
관문: check_body PASS · check_prose error 0 · check_evidence 두 프로젝트 문제 없음 ·
verify-tech-log-tree error 0 · verify-project-layout error 0
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
B-0 의 주입 1 절(파일 넷 편집)과 2 절의 이미지 빌드를 2026-09-17 에 밟았다.
두 노드에 이미지를 밀어 넣는 단계부터는 안 밟았고 그대로 unknown 으로 적었다.
- ⑤ 의 `git diff --stat` 점검은 작업 트리가 깨끗할 때만 성립한다. 그 줄은
덜 지운 것을 잡으려는 것인데, keycloak-pattern 에 이 실험과 무관한 변경이
39개(미추적 3개 더) 있으면 아무것도 못 가린다. 따로 떼어낸 작업 트리에서
고치면 점검이 다시 살아난다 — git worktree 한 줄을 적었다
- 넷을 다 뺀 뒤 무엇이 남는지를 숫자로 확인해 적었다. pom.xml 은 XML 로
유효하고, SecurityConfig 에는 bffSecurity 하나만 남고, application.yml 의
spring 아래는 둘뿐이며, 매니페스트의 Redis Deployment·Service·PVC 는 남는다
- 빌드는 한 번에 통과했다. 이 편이 적어 둔 processDuplicateKeys 실패는
재현되지 않았다 — Tests run: 4, Failures: 0 · exit=0
- 앞서 「남은 걸림돌은 인증서 하나」라고 적힌 것을 해결됨으로 고쳤다.
인증서는 엣지로 옮기고 강제 갱신까지 끝났다
관문: check_body PASS · check_prose error 0 · check_evidence 문제 없음 ·
verify-tech-log-tree error 0 · verify-project-layout error 0 · 코드펜스 전수 0건
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
test-server 를 비우고 다시 세운 뒤 Setup 기록 35편(virtualization 9 ·
keycloak-session-store 26)을 문서에 적힌 명령 그대로 쳤다. 어긋난 자리를
기록과 SSOT 양쪽에 실측과 함께 넣었다.
막히던 것
- 04 의 인증서 경로가 live/hyeonworks.com 이라 nginx 가 [emerg] 로 안 떴다.
실제 계보는 live/auth.hyeonworks.com 이고 「문제가 생기면」은 진단이 거꾸로였다
- 인증서가 와일드카드가 아니다. SAN 이 auth·app1·app2 셋뿐이라 그 밖의 이름은
TLS 에서 끊기고 curl 이 exit 60 · %{http_code} 000 을 낸다. SSOT 안에서
두 문단이 서로 어긋나 있었다
- A-7 14번 ①이 kc-lab-1 에서 여섯 줄 다 실패하는데 마지막 date 만 「차단」을 찍는다
검사가 실패할 수 없던 자리
- B-1 의 세션 키 고르기는 앞 단계가 $KEY 를 채워 둬서 루프가 한 건도 못 맞혀도
통과한다. KEY= 로 비우고 키마다 1/0 을 찍게 바꿨다
- k3s-agent 유닛의 sed -i 는 패턴에 $HOME 이 들어 있어 아무 줄도 안 바꾼 채 성공한다
certbot
- renew --dry-run 의 종료 코드는 성공도 0, 실패도 0, 다른 사유의 실패는 1 이다.
본문의 renew failure(s) 로만 판정할 수 있다
- --dry-run 은 staging 서버를 쓰는데 renewal/*.conf 의 account= 는 운영 계정을
가리킨다. 실패한 dry-run 이 staging 계정을 하나 더 만들어 다음 실행이 계속 멎는다
- 훅을 755 로 놓고 시뮬레이션이 성공해도 Running deploy-hook command 는 안 나온다.
certbot 2.1.0 에는 --run-deploy-hooks 도 없다
- 강제 갱신은 실제로 쳤고 서빙까지 닿았다. serial 06F3E0EF…1373 → 065547…3DF1,
notAfter Dec 3 → Dec 16, nginx worker 2629 4712 → 4745 4754
독자가 칠 수 있는 형태로
- 안 되는 형태가 번호 붙은 단계에 앉아 있던 8곳을 뒤집고, 되는 형태를 ①로 올렸다
- 랩 안에서 공개 이름을 치는 curl 65줄에 --resolve 를 붙였다. 붙인 형태를 실제로
쳐서 문서가 적은 값과 같은지 확인했다
- 힙독·sed -i·echo >>·&&·|| 를 편집기 + 파일 리스팅 + 분할 형태로 바꿨다
- 닫는 코드펜스가 빠져 뒤 200여 줄의 블록 종류가 뒤집혀 있던 곳을 포함해 3곳을 고쳤다
관문: check_body PASS · check_prose error 0 · check_evidence 두 프로젝트 문제 없음 ·
verify-tech-log-tree error 0 · verify-project-layout error 0 · 코드펜스 전수 0건
남은 것: B-0 주입은 keycloak-pattern 저장소의 소스를 고치고 이미지를 다시 구워야
해서 안 했다(unknown).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기록과 SSOT 를 대조해 한쪽에만 들어간 실측을 찾았다. 넷이 기록에만 있었다.
- A-0 시험 0c 의 `9 + 5 = 14` 와 DB 총계 대조
- A-8 의 `created_on` 은 그대로이고 `last_session_refresh` 만 117초 뒤로 간 것
- 토큰 길이가 판마다 다르다는 것 (`612자`·`758자` 대 `1187자`·`2043자`)
나머지 실측은 양쪽에 다 들어가 있는 것을 확인했다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기반 가이드 7단계로 실험대를 철거하고 다시 세운 뒤 virtualization setup 9편과
keycloak-session-store 26편을 순서대로 밟았다. 24편은 끝까지, 11편은 되는 데까지
밟았고 밟은 범위를 편마다 적었다.
명령이 못 도는 것을 고쳤다.
- kubectl 을 `kc-lab-1` 에서 치라고 적었는데 그 기계에 kubeconfig 가 없다.
라벨 639개와 각 편의 「어디서 치는가」를 `[lab host]` 로 옮겼다
- `-o custom-columns=…[0]…` 이 zsh 에서 글로브로 읽혀 안 돈다. 28곳에 따옴표
- busybox `sed` 가 끝 개행을 안 붙여 A-3 의 측정이 언제나 0 이었다
- `--token-file ~/node-token` 뒤에 그 파일을 지우면 k3s agent 가 재부팅을
못 견딘다. `/etc/rancher/node-token` 으로 옮기는 처방을 재서 넣었다
- 게스트에 없는 도구를 전제로 한 명령 넷 — `conntrack`·`dig`·`strings`·`nginx -v`
- `echo` 와 JWT 헤더가 `"이름" : [ 값 ]` 으로 찍는데 문서는 공백 없이 옮겨 적어
그 실측으로 만든 grep·sed 가 한 줄도 못 잡는다
- B-0 이 `directAccessGrantsEnabled` 와 계정 완성을 빠뜨려 B-3 이 못 돈다
- D-4·D-4a 가 `test-server` 와 `certbot-renew.*` 를 가리키는데 실제로는
`kc-lab-edge` 의 `certbot.service` 다
- `virsh setmaxmem --config` 를 `dominfo` 로 판정하면 틀린다. `--inactive` 로
- `LIBVIRT_DEFAULT_URI` 를 rc 에만 넣으면 `ssh host '명령'` 에서 안 먹는다
결과가 조건부인 것을 갈랐다.
- readiness 는 즉시 안 뒤집힌다. A-1·A-2 의 60초 창을 적었다
- 03 의 층 ②③ `301` 은 04 이후의 값이고 그 단계에서는 `404` 다
- A-0 의 로그 필터를 요청 직후에 치면 정반대 결론이 나온다
- A-5 의 한 방향 차단은 잠깐 `1` 이었다 `2` 로 돌아온다
증거는 두 프로젝트의 `evidence/raw/` 에 99벌을 README 와 함께 남겼다. 비밀은
길이만 적었고 화면에 찍힌 토큰은 가렸다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
이번 파이프라인 작업과 무관하게 작업 트리에 남아 있던 것을 그대로 올린다.
사용자가 「전부 커밋」으로 정했고, 이번 작업과 섞이지 않게 커밋만 나눴다.
대부분은 clean-architecture-backend-template 의 그림 정본 재배치다 —
final/assets/diagrams/<이름>/ 에 있던 것이 CLAUDE.md 가 적은 배치인
final/assets/<이름>/ 로 옮겨졌고 .techviz/<이름>/ 이 함께 들어왔다.
삽입 줄의 대부분(3.15M)이 그 .techviz context.json 이다.
그 밖에 ca-tmpl·document-haness 의 정리, .claude/agents/ 열한 개,
writing-practitioner-guides 스킬, .playwright-mcp 세션 산출물,
scripts/check-ssot-facts.py 와 그 시험이 들어 있다.
이 커밋의 내용은 내가 만든 것이 아니라 이전 세션이 남긴 것이고 검증하지 않았다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
기록 84편을 계약 에이전트로 다시 썼다. 기존 71편(kss 25 · virt 46)과, 계약에만
있고 안 쓰여 있던 새 글감 13편이다. 원장 84개를 열어 단계마다 스킬 영수증과 관문
종료 코드를 적었고 verify-pipeline-run.py 가 error 0 으로 닫는다.
SSOT 결함 둘을 고쳤다.
- kss 의 `약 58일` 이 반입 중 `약 59일` 로 바뀌어 있었다. 원 증거 파일이
「남은 일수: 88일 … 실제 갱신까지 약 58일」로 산수를 직접 적는다. D-4a 쪽
`약 59일` 은 강제 갱신 뒤(`VALID: 89 days`)라 맞는 값이라 그대로 뒀다.
- virt §198 의 `11.6GB` 는 §178 의 원 측정 `Mem: 11648`(MiB)과 어긋나는데
원 가이드의 표기 그대로라 고치지 않고 쓰이는 자리에 대조를 적었다.
기록의 수치 오류 셋을 고쳤다 — CASE 요약의 「게스트 셋에 8240MB」(5120+3120 은
둘이다), k3s 편이 같은 것을 여섯·일곱·여덟로 세던 것, no-docker 편의 「셋을 더
든다」(§281 의 표는 네 행이고 디스크 행이 빠져 있었다).
계약을 셋 고쳤다.
- kss 의 sourceRepository 리비전이 cdac9b8 이었는데 그 커밋에는 docs/guides/**
28개가 아예 없다. 9465582b 로 바꾸고, 반입한 바이트가 어느 커밋과도 같지 않다는
것을 측정값과 함께 적었다 — 반입은 커밋이 아니라 그 시점의 작업 트리에서 떠 온
것이다(kss 297/306 · virt 12/14 가 작업 트리와 같고, 200 커밋을 거슬러 전수
대조했을 때 가장 가까운 커밋도 28개가 어긋났다).
- virt 계약이 「2026-09-11 재배분」이라고 적는데 SSOT 는 재배분 날짜를 적지 않고
재배분 뒤 값은 이미 2026-09-10 측정에 찍혀 있다.
- kss 후보 대장이 지나친 절 아홉에 처분을 적었다(warn 9 → 0). 새 글감은 0건이고
넷은 앵커가 h3 슬러그의 접두가 아니라 중간 토막이라 검사기가 못 본 것이었다.
style_profile.mjs 의 결함 둘을 고쳤다 — frontmatter 가 문장으로 세어져
(실측 398자짜리 「문장」 하나) 평균 길이를 기준 안으로 밀어 올리고 있었고,
engPerSent 의 분자는 목록을 포함한 글에서, 분모는 목록을 걷어낸 글에서 세고
있었다(Question 기록에서 11.94 → 3.86).
verify-pipeline.py 전 항목 PASS · error 0 · unittest 334건 OK.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
부채 ④. 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
check_evidence --repo 이 clean-architecture-backend-template 에서 141건을 세고 있었다.
124건 전부를 고정 리비전 21234e38 에 대조했더니 날조는 0 이었다 — 인용은 맞고 없던
쪽이 SSOT 였다. 그래서 SSOT 를 보강한다.
넣는 것은 기록이 옮겨 적은 문장이 아니라 저장소 원문이다. 기록을 복사해 넣으면
검사기는 초록이 되지만 옮겨 적기가 어긋나도 더는 못 잡는다. 원문을 넣으면 어긋난
기록은 계속 걸린다.
- 코드 124건 → 리프 절 일곱 곳에 원문 30조각(300줄). 자리는 기록의 source 앵커와
소스 파일의 모듈을 교차시켜 정했고, 둘이 갈린 다섯은 모듈을 따르고 그 사실을 적었다
- 식별자 13건 → spring.factories · MethodSecurityConfig 원문과 줄여 적힌 경로의 전체 경로
- source 앵커 4건 → 계약이 이미 적고 있던 SSOT 앵커를 기록 frontmatter 에 맞췄다.
맨 앵커를 한 줄씩 앞에 둔다 — `_record_sources` 가 `- <공백 없는 한 덩어리>` 만 잇달아 읽는다
- 인용 4건 → concept-signed-cursor-structure 의 `{ ... }` 생략을 저장소 원문 형태로 고쳤다.
생략한 자리는 `…` 로 남기고 무엇을 줄였는지 본문에 적는다
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
사용자가 studio:publish 권한 분리를 유예하고 write 권한을 가진 실계정으로 저장하기로
했다. 설계의 명시적 예외이고, 설계가 프롬프트 통제를 인정하지 않는 이유가 여기 그대로
적용된다 — 「이미 게시된 게시물은 건드리지 않는다」를 문장이 아니라 코드로 만든다.
한 번이라도 게시한 문서는 게시를 취소해도 삭제가 409 로 거절된다. public 이 찼거나
status 가 게시 중이면 저장 대상에서 뺀다. 저장소에서 두 표시가 같은 17건을 가리키지만
하나만 차 있어도 게시로 본다 — 한쪽이 뒤늦게 채워지는 경우를 놓치지 않는다.
frontmatter 는 저장소가 아는 것이지 서버가 아는 것이 아니다. 그래서 계획의 첫 단계가
서버에 게시 상태를 묻고, PUBLISHED 면 저장 단계로 넘어가지 않는다. 새 문서를 만드는
계획에는 그 단계가 없다 — 아직 없는 문서에는 물어볼 게시 상태가 없다.
시험 초안에 [HARNESS-TEST] 접두사를 붙일 수 있게 했다. 나중에 사람이 눈으로 가린다.
무인 저장은 그대로 꺼져 있다. CR-001 이 유예됐다는 것은 무인 저장을 켠다는 뜻이 아니다 —
사람이 보는 앞에서 저장하는 것과 사람 없이 저장하는 것은 다른 이야기다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
이 저장소 자신의 검사 층을 대상으로 삼았다. 파이프 뒤의 $? 를 읽고 검사기 열넷이
전부 --help 를 받는다고 적었다가, 파이프를 걷고 다시 재니 둘이 exit 1 이었던 일.
관찰·원인·조치가 한 사건으로 닫히고 조치가 capture-evidence.py 다.
증거 여덟 건은 전부 그 도구가 수집했다. proves/doesNotProve 로 「이 출력이 뒷받침하는
것」과 「뒷받침하지 못하는 것」을 증거 쪽에 적어 두었다 — 본문이 그 경계를 넘었는지
대조할 것이 생긴다.
함께 올린 Question 은 「검사할 것이 없을 때 관문은 무엇을 내야 하는가」다. 현상은
재현했고 조치가 없어 Case 로 올리지 않았다. 조치 없이 쓰면 관찰만 있고 결과가 없는
글이 된다.
런 원장은 단계마다 서브에이전트를 하나씩 띄운 기록이다. 넷이 실제로 무언가를 잡았다 —
S3 이 「argparse 를 쓰지 않는 셋」이 증거 원문과 어긋나는 것을(넷이다), S1 이 그
뿌리를 SSOT·앵커·증거 메타에서, S5 가 「증거 여섯 개」가 frontmatter 의 다섯과
어긋나는 것을, S6 이 계약의 「한 번밖에 안 써서」가 메타 여덟 건과 어긋나는 것을.
셋 다 한 세션이 일곱 단계를 겸했으면 안 나왔다. 내가 쓴 글을 내가 다시 읽는 것이기
때문이다.
style_profile 은 exit 1 로 그대로 적었다. 관문이 아니라 측정이고, 돌리지 않은 값을
0 으로 적는 것이 이 원장이 막으려는 바로 그것이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4vKjQo9KKBBokzxqXLCfk
§1.4 로 세운 도메인·비즈니스 규칙을 그것이 실제로 설명하는 기록에 넣었다.
프로젝트가 문서 게시 파이프라인을 안 타는 이유 → 화면 다섯이 비어 있던 Case
홈 focus 설정이 FK 없이 사는 설계 → 「열린 질문이 없습니다」 Case
결정이 자기 화면을 안 갖는 이유 → 목록이 문서 전체를 실어야 했던 Case
게시가 단계마다 다른 코드로 거절하는 설계 → 화면이 추측 셋을 출력한 Case (반대 사례)
종류마다 애그리거트와 테이블이 다르다 → 매퍼가 종류를 판정해야 하는 Case
축을 지우면 연결만 끊고 주제를 지우면 거절하는 이유 → 축 Concept
개념이 문서 테이블에 얹힌다 → 열세 곳 Case
화면 상태와 도메인 상태가 원래 갈려 있었다 → 이름을 두 번 바꾼 Case
Case 본문 중앙값 675 → 1,342 자. 검사 넷 전부 통과한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
이 문서는 결함 카탈로그로만 있었고 이 시스템이 무엇을 하는지가 없었다. 두 저장소의
도메인·유스케이스에서 확인해 §1.4 를 세웠다.
종류 다섯이 각자 자기 애그리거트와 테이블을 갖는다 (ADR-003) — 개념은 문서 테이블에
얹히고 concept_detail 에 기준 버전만 따로 둔다. §3 의 열세 건과 §14 의 외래키 없는
축 표가 여기서 나온다
화면 상태와 도메인 상태가 다르다 — 질문의 OPEN·INVESTIGATING·PAUSED 가 화면에서 하나로
접히고 결정의 ACCEPTED 가 ADOPTED 로 보인다
NextAction 판정 순서 — 서버가 조회 시점에 계산하고 저장하지 않는다. 프론트가 여러
endpoint 를 조합해 workflow 를 재추론하지 않게 하려는 것이다
검증·미리보기가 버려지지 않는 산출물인 이유와 그것이 유효한 조건 셋
게시가 단계마다 다른 코드로 거절하는 이유 — 고칠 것과 다시 검증할 것이 다르다
저장할 때와 공개할 때의 요구가 다르다 · 문서가 아닌 것은 다른 경로로 공개된다 ·
주제는 참조가 있으면 안 지우고 축은 연결만 끊는다 · 없는 것을 가리키는 설정을 막는다
SSOT 62,643 → 71,870 자. 인용은 전부 저장소의 javadoc 과 코드에서 옮겼다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SSOT 를 저장소에서 확인해 더 보강하고 그것으로 다시 썼다.
§7.2 참조 검사 SQL 을 문자열로 조립하는 실제 코드 — 컴파일러가 표 이름도
컬럼 이름도 보지 않는다는 것이 그 모양에서 드러난다
§11.2 section-heading-rank 가 미디어 쿼리 값을 먼저 걷어내는 이유(테스트 주석)
§16.1 질문 삭제는 참조가 둘뿐이라 같은 문제가 덜하다는 대조
Case 열 편과 Question 셋을 다시 썼다. Question 은 사실·가정·미지수·제약을 갈라
채우고 선택지마다 무엇을 감수하는지 적었다 — 오류 코드를 나누면 계약과 반입한 두
저장소가 함께 움직인다는 것처럼.
SSOT 62,643 → 68,319 자. 검사 넷 전부 통과한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
주제 11~13 을 다시 쓰고, Case 가 얇은 것들을 저장소에서 실물을 확인해 채웠다.
§13.4 ManagementClientSafeMessages — 삭제 관련 코드 여섯의 고정 문구와
원문 메시지를 내보내지 않는 이유(javadoc)
§16.1 다섯 참조가 전부 DOCUMENT_IN_USE 하나로 나가고, SSOT 가 인용한 영어 문장은
DeleteDocumentDraftUseCase 안에 남는 진단 메시지라 밖으로 나가지 않는다
§13.6 romanizeSyllable 실물과 음운 변동을 뺀 이유, 문서 slug 와 같은 정규식을 쓰는 이유
§15.4 check:types 가 도는 tsconfig 여섯 — app·node·test·recipes·web-worker·service-worker
SSOT 62,643 → 67,526 자. 인용한 코드는 전부 저장소에서 찾아 대조했다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
주소가 게시 시점에 굳어 저장되는 구조, 축 링크를 두 번 옮긴 순서, 한글 slug 가
간헐적으로 보인 두 가지 어긋남을 표로 갈랐다. 화면이 실패를 없음으로 그릴 때 작성
도구에서 왜 더 오래 숨는지, Promise.all 이 거절과 던짐에서 다른 경로를 타는 이유를
채웠다. CSS module 이 왜 전역 규칙에 닿지 않는지, 403 과 404 가 원인을 어떻게
좁혔는지도 적었다.
link-audit.py 를 감사 Case 의 evidence 로 걸어 배정한 증거 하나를 메웠다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
게시된 Reference 15편이 전부 규칙을 `### N. 제목` 으로 쓰고 적용 조건·예외·예시를 항목으로
쓴다. 내 15편은 규칙을 `**굵게**` 로, 나머지 셋을 문단으로 쓰고 있었다 — Studio 의
rules[]·applyWhen[]·exceptions[]·examples[] 는 배열이라 문단으로 두면 항목이 하나로 접힌다.
규칙 68개를 `### N. 제목` 으로 바꿨다 (편당 3~7개, 게시된 것은 4~10개)
적용 조건·예외·예시를 항목으로 갈랐다. 한 항목뿐이던 아홉 편은 조건을 나눠 적었다
주제 6 은 본문을 다시 썼다 — location = 이 정확히 일치하는 경로만 잡아 27개가 얼어붙은
구조, 여덟 곳이 우는 시점을 셋으로 가른 표, digest 를 다시 계산할 때 옛 값을 먼저
재현하는 이유.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
what-the-compiler-lets-through 중앙값 2,096 → 2,590 자
seams-no-test-crosses → 3,091 자
bivariance 가 왜 느슨한 판정을 받는지, never 캐스트가 왜 아무것도 요구하지 않는지처럼
「이름을 댔으면 왜 있는지도 댄다」를 채웠다. 네 가지가 각각 무엇을 통과시키고 어디서
드러났는지를 표로 갈랐다. 검사 넷 중 무엇이 SQL 을 실제로 돌리는지도 표로 세웠다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
건너뛴 참조 다섯을 읽고 나서 다시 썼다 — from-ssot-to-records.md 의 「그림과 증거는
배정 대상이다」, code-tables-diagrams.md 의 표·코드 규칙, explaining.md 의 「이름을
댔으면 왜 있는지도 댄다」.
**SSOT 를 먼저 고쳤다.** §3.3 의 코드블록이 저장소와 달랐다 — PATH_PREFIX_KINDS 는
Record 표가 아니라 튜플 배열이고, 진짜 경로 표는 EXPLORE_KIND_PATHS 다. 저장소에서
확인해 실물로 바꾸고, javadoc 이 적어 둔 이유를 함께 옮겼다. §16.7 에 BRANCH_FIELDS 와
pathOf 실물을, §4.3 에 ContractRouteCoverageTest 의 javadoc 과 면제 상수 둘을 더했다.
62,643 → 65,737 자.
**계약에 ssot-assets·ssot-evidence 를 배정했다.** 그 절차를 건너뛰어서 SSOT 가 이미
가진 그림과 측정이 글감에 배정되지 않은 채였다. TechLog 12 글감, keycloak-session-store
는 그림 21장·증거 19건을 배정하고 붙일 글감이 없는 그림 4장은 이유를 계약에 적었다.
배정하자 검사기가 「배정한 증거를 기록이 쓰지 않는다」 4건을 드러냈다.
**주제 셋을 다시 썼다.**
hand-listed-kinds 중앙값 1,925 → 3,760 자
declared-but-not-implemented → 2,608 자
values-lost-between-boundaries → 2,602 자
게시된 기록은 keycloak 4,546 · n+1liner 3,190 이다. 표와 코드를 SSOT 에서 옮기고,
Reference 에 담을 수 없던 표(§5.5 의 여덟 자리)를 짝이 되는 Case 로 내렸다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
writing-as-the-person-who-did-it 을 서브에이전트 셋으로 나눠 56편에 적용했다.
56편 중 20편만 고쳤다 — 나머지 36편은 SSOT 를 절 단위로 대조했을 때 옮길 흔적이
이미 옮겨져 있었거나 없었다. 없는 목소리를 채우지 않는다.
옮긴 것은 전부 SSOT 의 어느 절에서 왔는지 댈 수 있다.
§3.4 「눈으로 찾을 일이 아니었다」— 세 계약을 파싱해 뽑은 이유
§4.3 구현하지 않기로 한 것과 빠뜨린 것은 다르다
§8.5 표의 마지막 줄을 더할 때 이 목록을 또 빠뜨렸다
§9.4 「왜 주제 링크가 탐색으로 가지?」— 우회를 남겨 두면 계속 나온 질문
§11.3 「세 버튼」을 실제 이름으로 되돌리고 두 언어가 섞인 것을 그 자리에
§12.2 막지 않은 대신 메모리에 남긴 것
§13.1 여섯 벌 인용이 어느 커밋이 짚은 말인지
§13.3 고쳐 쓴 첫 안이 거절당한 것과 사용자가 고른 말 두 쌍
§14.3 「문서가 그대로 나온다」는 구조 차이가 아니라 내용 양의 차이라는 정정
§16.1 삭제가 막힌 실제 기록 이름과 그것을 막은 프로젝트 링크
§16.9 주제 논지와 축 결론이 AI 가 써서 DB 에 직접 넣은 미검토 초안이라는 것
§17.5 바운딩 박스로 잘못 지목한 대상이 「판단 기준」이었다는 것
검증 환경의 커밋 해시 하나가 틀려 있었다(ca1cfa2 → ca1fc92). SSOT §13.1 과
부록 A 가 적은 값이고 저장소에 그 커밋이 있다.
검사 넷 전부 통과한다 — check_prose 56편 error 0 · check_body PASS ·
check_evidence --repo 문제 없음 · verify-tech-log-tree 프로젝트 5 error 0 warn 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rewriting-technical-prose-naturally 를 서브에이전트 셋으로 나눠 56편에 적용했다.
ai-tells.md 의 첫 절대로 다른 표현으로 바꾸는 대신 문장을 통째로 지웠다.
설명한 것의 중요성을 다시 평가하는 꼬리 19
이미 설명한 것을 추상어로 되풀이 19
독자에게 읽는 법을 지시하거나 오해를 가정 9
자료가 뒷받침하지 않는 덧붙인 이득 4
문서군 전체의 문형 편중도 풀었다 — 함께 27→7(한 묶음), 그대로 22→12(두 묶음),
하게 된다 1→0. 한 편에서 세 번 반복되던 「같은 병이 ~에서도 났다」와 두 기록에
같은 문장으로 있던 세 쌍을 갈랐다.
계약 제목 「여덟 자리」가 본문의 「여덟 곳」과 어긋나 있었다. 제목이 spatial-metaphor
규칙에도 걸리므로 계약과 기록을 함께 「여덟 곳」으로 맞췄다.
검사 넷 전부 통과한다 — check_prose 56편 error 0 · check_body PASS ·
check_evidence --repo 문제 없음 · verify-tech-log-tree error 0 warn 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces the to-do list with the work itself. Eight layers, 42 concepts,
1200 lines, each with what it is, why it turns up here, how it fails, and
the command to check it.
Most values were read off the running system rather than recalled:
conntrack ESTABLISHED timeout 86400s — why A-1's injection sat unmatched
for 25 minutes was normal, not a fault
FORWARD chain position 1 KUBE-ROUTER-FORWARD — why -I FORWARD 1
counted zero packets
cgroup version v2, and the numbers in systemctl status
are read straight out of those files
nginx restart policy on-failure, 100ms, and it gives up after
5 failures in 10 seconds
Type and KillMode five units on this host, four different
combinations
Two facts could not be read locally and carry sources: Let's Encrypt
backdates notBefore by exactly one hour to tolerate client clock skew, and
Keycloak invalidates the whole SSO session on refresh token reuse. The
second one explains B-3 — the winning request's new token was not itself
rejected, the session it belonged to had just been deleted.
The systemd layer also explains the one CGroup line in systemctl status that
D-4 spent ps commands establishing: master 585 kept, worker replaced.
One item is marked as read rather than measured. Restart=on-failure comes
from the unit file; nginx has not been killed to watch it come back.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
주제 13개 · Case 28 · Concept 5 · Reference 15 · Question 4 · Decision 4.
계약의 노드마다 종류가 요구하는 칸을 채우고, 본문이 있는 두 종류에는 SSOT 가 이미
그려 둔 도식 셋(value-boundaries · decision-path-404 · topic-variant-model)을
tech-log-studio/ 로 옮겨 붙였다. 새로 그린 그림은 없다.
검사 셋 전부 통과한다.
check_body.mjs 56 편 중 본문이 있는 33 편 PASS
check_prose.mjs 56 편 error 0
check_evidence.mjs --repo 포함 문제 없음
verify-tech-log-tree.py 프로젝트 5 · error 0 · warn 0
인용한 코드블록은 전부 SSOT 에서 찾아 대조했다. check_evidence.mjs 가 본문의 각 줄과
source 앵커와 계약 제목을 다시 확인한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The lab wrote 26 experiments on top of names it never defined. Comparing the
terms used against the places that actually explain them: 24 have no
explanation anywhere. conntrack appears 35 times across the experiment
documents, refresh token rotation 17, JWKS and Liquibase 11 each.
The list groups them in eight layers with, for each, where it came up,
whether it is explained centrally, only inside one experiment, or nowhere,
and what specifically needs to be learned. It is mapped onto the six topics
of the decomposition contract rather than standing beside it — two glam of
operations-that-report-success cannot be written without systemd, and
Restart=, journald and Type=forking are all in the "nowhere" column.
The bottom layer is the worst of it. systemctl has been typed eight times
as a command and never explained, and the unit file, cgroup, restart policy
and crash-loop limit under it are unwritten.
Building the list turned up a piece of evidence the lab missed. B-7 recorded
that it narrowed the 502 by splitting layers and calling traefik directly to
bypass nginx. The host nginx journal had already written the cause in a
sentence — "upstream sent too big header ... /oauth2/callback" — and none of
the 147 evidence files contain it. That is what journald being in the
"nowhere" column cost.
Also fixes ten spatial-metaphor errors the tightened check_prose now
catches, nine of which predate this section.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
글감 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>
- 계약 채택 — 독자 질문, 후보 29건(PROMOTE 24 · MERGE_INTO 4 · KEEP_IN_SSOT 1). 게시 중
17건은 전부 유지. 저장소 keycloak-pattern 은 패턴 넷이 브랜치로 갈라져 있어 revisions 로
tip 넷을 적었다. keycloak-session-store 는 같은 저장소 @ cdac9b8
- 게시된 기록의 redirect_uri 가 SSOT·코드와 달랐다 — OAuth2callback.html → callback.html
(frontend/src/app.js 에서 확인). 계약 title 이 기록과 다른 7건도 기록 쪽으로 맞췄다
- 미작성 1건 작성 — 패턴 검증을 실제로 돌릴 때의 안전한 순서(Reference)
- 리뷰 100건 반영 — 설명 뒤에 붙은 평가·차례 예고·독자 오해 가정·작성 지시를 지웠다.
삭제가 남긴 조각 4건을 고치고, 원래부터 잘려 있던 로컬 미리보기 라벨 1건도 닫았다
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- 계약 채택 — schema 2 → 4. 독자 질문, 후보 36건(PROMOTE 24 · MERGE_INTO 8 ·
KEEP_IN_SSOT 4), 종류별 칸, kind:slug 관계. 저장소 github-project/ca-tmpl @ 761384d
(문서가 인용한 IT 7종이 그 커밋에 있다)
- 재선별 결과 기존 24건이 전부 살아남았다. 측정이 Reference 안에 들어 있었지만 독립성 검사를
통과하지 못해 Case 로 빼지 않았다
- 평문 칸의 백틱 제거, 「기준선」을 실제 이름으로, frontmatter 에 source·sourceRevision
- 리뷰 39건 반영 — 설명 뒤에 붙은 평가·예고·되풀이·독자 오해 가정을 지웠다. 사실을 담은
절반이 있는 문장은 평가만 뺐다
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다
- 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5
(PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를
techviz 로 만들었다
- 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs
돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다.
Concept 이 인용한 코드가 SSOT 에 없어 뺐다
- candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905)
Co-Authored-By: Claude Fable 5.1 <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>
Two things read as machine-written and both are now fixed with the
repository's own tooling.
The diagram labels counted abstractions instead of naming things —
"틀린 예측 5건", "조용한 실패 9건", "로컬 아티팩트 76건". Replaced with what
those actually were, which is also more useful in a drawing:
틀린 예측 5건 -> A-1 · A-2 · A-6 · B-4 · B-6
조용한 실패 9건 -> NetworkPolicy · tc · kill · iptables
로컬 아티팩트 76건 -> 연결수 0 · 50µs
A층 결론 3건 반전 -> A-1 · A-2 · A-8
The prose was staccato: 30.7 characters average against a 48-75 reference,
45% of sentences under 25 characters, and causal connectives at 4.9 per 100
against a floor of 6. check_prose reported an error for closing six
sentences with 「~것이 ~이다」.
Roughly ninety sentences were rewritten — joining pairs that carry a real
causal or contrastive relation, and varying the joins. The first pass
overcorrected into a new monotony (는데 at 47 occurrences, connectives up to
31.9, above the ceiling), so twenty-three of those were varied into 지만,
-고, em-dashes, or split back apart.
check_prose FAIL error 1 -> OK error 0
평균 문장 길이 30.7 -> 43.1
25자 미만 비율 45.4% -> 23.4%
이유 연결어미 4.9 -> within range
Two style_profile numbers still read outside the band, and the reason is
worth writing down rather than editing around: the tool counts each image
caption as a sentence, and this document carries 28 diagrams. Excluding
captions and separators the prose is 46.4 characters average with 14.3%
short — inside the reference range. Padding sentences to move the remaining
gap is what CLAUDE.md forbids, so it stops here.
Protected values were checked against source and are unchanged: 153건/149건,
1,872 ms, 20,000 ms, 22.2 초, 2305초, 845361바이트, 8856건, 205.7ms, 106초.
All 28 diagrams still lint clean with no sentence left on any canvas.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The skill says drawings carry names and sentences go in <desc> and the
paragraph beside the figure. I put sentences in node details and edge labels
instead, and 27 of the 28 diagrams shipped with prose inside the canvas —
"예측 다섯 개가 틀렸다", "아홉 번 조용히 실패했다", "막혀서 닿지 않는다".
Only label and details render on the canvas; description does not. So every
sentence moved to a noun phrase and the meaning stays in description, which
was already carrying it.
막혀서 닿지 않는다 -> 차단
아홉 번 조용히 실패했다 -> 조용한 실패 9건
예측 다섯 개가 틀렸다 -> 틀린 예측 5건
로그아웃이 정리하지 않는다 -> 로그아웃 미정리
볼륨이 없으면 여기까지다 -> 볼륨 없음
Three node labels were sentences too and became names: 세션 스냅샷, 예측
선기록, 대조군 확보.
What stays is what the rules protect — identifiers, commands and measured
values: PRIMARY KEY (client_registration_id, principal_name),
ValidationFailedException: 1 changesets check sum, nginx -t && nginx -s
reload, SET LOCAL synchronous_commit TO OFF. Those are names of things, not
prose about them.
294 canvas strings across 28 diagrams, none matching a sentence ending,
average 11 characters. All 28 still lint clean and re-rendered.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The originating repository's SVGs were drawn by hand and every one of them
put a title, a subtitle and an explanation band inside the canvas. This
repository forbids both, so they could not be carried over — the whole set
was rebuilt through the skill's pipeline instead.
Each diagram went through prepare, references, prompt, a VizSpec 1.1 citing
document line ranges, lint, and render. All 28 pass lint and produce the
same eight formats the existing keycloak project has. Sentences moved out of
the canvas into <desc> and the paragraph beside each figure; the drawings
carry names only.
Two lint rules did real work rather than formatting work:
edge-through-node caught arrows crossing an unrelated
node and implying an adjacency that
does not exist — four diagrams had to
be restructured, not just relaid out
evidence-outside-prepared-context caught a diagram citing another
section; its anchor moved from B-0 to
B-1 so all three sections it draws on
are inside the prepared context
lab-topology also had to change profile: its context offers a different
candidate set, and query-fanout with shard roles is what the section
actually shows — one entry point spreading to two Keycloak nodes.
The document now carries all 28 inline, one per claim that needed one, and
the section recording what was still missing is updated: the diagram gap is
closed, Studio records remain.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <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>
.run/의 세 런을 조사한 결과 claridoc run 파이프라인이 한 번도 완주하지
않았음을 확인했다. quality-gate.json 0건, stages/ 및 rounds/ 부재.
실사용 범위는 validate/collect/outline까지였고 글쓰기와 검수는 스킬이
담당했다.
하네스를 제거하고 korean-technical-blog-skills-bundle-v1의 스킬 세 개와
.run/의 문서 세 편만 남기기로 한 결정과, 보존/삭제 인벤토리, 안전장치,
검증 절차를 기록한다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>