5편에서 Web Clipper 임계값 0.85가 원본 관찰에 없다는 걸 확인하고, “대화로 말한 적이 없어서 저장이 안 됐을 것”이라고 결론 냈었다. 하루도 안 지나서 이게 틀렸다는 게 밝혀졌다 — 그것도 아주 크게.
시작은 반박이었다
“이건도 물어보고 결정해서 블로그 글에 들어간 거거든… 실제로는 이걸 체크해서 주고, 이 정도 마진을 주고, 이걸로 하자고 추천해서 하자고 해서 코드에도 들어가 있어… 대화에 있는 내용이거든”
이 한마디에 5편의 결론이 무너졌다. “대화에 없었다”는 설명은 확인 없이 낸 추측이었다. Honcho가 지어낸 걸 검증하겠다고 벌인 시리즈에서, 정작 Claude Code가 낸 추측은 검증하지 않고 그대로 결론에 박아 넣은 거다.
원본 메시지부터 다시 찾았다
/representation은 dialectic이 검색한 결과였지, 진짜 원본이 아니었다. 이번엔
Postgres에 직접 붙어서 messages 테이블을 뒤졌다.
SELECT id, created_at, peer_name, content FROM messages
WHERE content ILIKE '%0.85%' OR content ILIKE '%안전 마진%';
있었다.
2026-07-15 01:15:44 | claude-code | 완벽한 데이터야 — 진짜 중복(1.000, 0.893)이랑
가짜(Blinkist끼리 0.69~0.73대)사이에 확실한 절벽이 있네. ... 안전하게 그 중간보다
진짜 쪽에 가깝게 0.85로 잡을게 — 진짜 중복은 다 넘기고, 가짜는 확실히 걸러지게.
2026-07-15 01:22:32 | claude-code | ...
const BODY_THRESHOLD = 0.85;
토씨 하나 안 틀리고 그대로였다. 코드에도 박혀 있었다.
deriver는 무죄였다
그럼 왜 관찰엔 없었나. documents 테이블(원본 관찰이 실제로 저장되는 곳)을
다시 뒤졌다.
2026-07-15 01:16:01 | observer: claude-code | observed: claude-code |
"claude-code identified a threshold of 0.85 as the boundary for detecting
duplicate clippings based on body similarity."
2026-07-15 01:16:01 | observer: claude-code | observed: claude-code |
"claude-code set the constant BODY_THRESHOLD to 0.85 in its provided
dataviewjs script."
있었다. 대화가 끝나고 17초 만에 정확하게 뽑아놨다. deriver는 처음부터 할 일을
했다. 문제는 이게 observer: claude-code, observed: claude-code로 저장됐다는
거였다 — 지금까지의 모든 조회가 봐온 건 user-default-hermes라는 전혀 다른
peer의 서랍이었다.
peer가 6개였고, 서랍이 갈라져 있었다
SELECT observer, observed, count(*) FROM documents
WHERE workspace_name='hermes' GROUP BY observer, observed
ORDER BY count(*) DESC;
claude-code | claude-code | 1,100
user-default-hermes | user-default-hermes | 522
claude-code 서랍이 user-default-hermes 서랍보다 두 배 넘게 컸다. 훅
(honcho_recall.sh)은 처음부터 끝까지 peers/user-default-hermes/chat만
불렀다. 1,100건짜리 서랍은 존재하는지도 몰랐던 거다.
원인은 설정 하나였다
session_peers 테이블에서 claude-code 세션의 관찰 설정을 봤다.
user-default-hermes | {"observe_me": null, "observe_others": null}
claude-code | {"observe_me": null, "observe_others": null}
둘 다 꺼져 있었다(null = 기본값 = self-only). honcho_store.sh가 매 턴을 두
메시지로 쪼개서 각자 다른 peer 이름으로 보내고 있었는데 — user-default-hermes가
한 말, claude-code가 한 말 — 서로를 관찰하도록 설정한 적이 없으니 Honcho
기본 동작대로 각자 자기 자신의 모델만 쌓은 거다.
Hermes는 어땠나 — 처음부터 맞았다
혹시나 해서 Hermes(진짜 AI 에이전트, hermes-agent)의 설정도 봤다.
[obsidian-gemini-butler 세션] hermes: {"observe_me": false, "observe_others": true}
[telegram 세션] hermes: {"observe_me": false, "observe_others": true}
[Pending 세션] hermes: {"observe_me": false, "observe_others": true}
[hermes 세션] hermes: {"observe_me": false, "observe_others": true}
Hermes가 속한 모든 세션에서 예외 없이 observe_others: true였다. 상대
인간 peer는 반대로 {"observe_me": true, "observe_others": false} — 처음부터
짝이 맞춰져 있었다. Claude Code용 훅만 이 설정이 통째로 빠져 있었다.
그런데 2편의 low/max 실험도 이걸 피해간 거였다
여기서 궁금해졌다 — 2편/3편에서 low와 max를 비교했을 때는 왜 멀쩡히
“작동하는 것처럼” 보였을까. 같은 구조적 문제가 그때도 있었을 텐데.
확인해보니, 2편의 실험은 애초에 hermes workspace를 안 썼다. 완전히 별도인
claude-code-memtest라는 workspace를 새로 파서 거기서 진행한 거였다.
SELECT peer_name, session_name, content FROM messages
WHERE workspace_name='claude-code-memtest' ORDER BY created_at;
넣은 테스트 사실 4개(Fire Pass, Cloudflare, dedup, Levenshtein) 전부
peer_name: claude-code로 들어가 있었다. 그리고 그때 low/max를 비교하며
물어봤던 질문도 claude-code peer 자신에게 물어본 거였다 — 원본 관찰도
확인해보니 9건 전부 observer: claude-code, observed: claude-code였다.
즉 넣은 peer와 물어본 peer가 같았다. self-observation은 observe_others
설정과 무관하게 항상 작동한다. 그러니까 2편의 “low는 가끔 비슷한 이름을
헷갈리고 max는 안정적이다”라는 결론 자체는 진짜였다 — 다만 그건 “claude-code가
자기 자신의 서랍을 들여다볼 때”의 얘기였다. 지금 실제 훅이 겪고 있는
“user-default-hermes가 claude-code 서랍을 보려는” 상황은 그 실험에서 한 번도
등장한 적이 없었다.
그리고 그 결정조차 실제 훅엔 반영이 안 됐다
한 가지 더 있었다. 3편은 이 실험 결과로 “기본 dialecticReasoningLevel을
low에서 max로 바꿨다”고 명확히 결론 냈다. 근데 실제 honcho_recall.sh
코드를 다시 보면:
'reasoning_level': 'low'
low가 그대로 박혀 있다. 3편의 결정이 어디로 갔는지 찾아보려고 07-14
하루치 메시지를 전부 훑었다 — “low로 되돌리자”는 재고 대화는 어디에도
없었다. 대신 발견한 건, 3편의 “기본값을 max로” 결정이 실제로는 Hermes
자신의 설정 파일(honcho.json의 dialecticReasoningLevel: max)에만
반영됐다는 거였다. honcho_recall.sh는 그거랑 무관하게 손으로 새로 짠
스크립트라서, 그 결정을 물려받지 못하고 그냥 기존 기본값(low)을 그대로
박아 넣은 걸로 보인다. 재고가 아니라 누락이었다.
(참고로 훅이 창조된 그 세션 자체는 Honcho에 안 남아 있다 — 훅이 존재하기 전에 훅을 만드는 대화였으니, 그 대화를 저장할 훅이 아직 없었던 셈이다.)
모델은 이미 맞는 걸 쓰고 있었다
[dialectic.levels.*.model_config] 전부 gemini-3-flash-preview
[deriver/summary/dream] 전부 gemini-3.1-flash-lite
dialectic 쪽은 이미 3편에서 검증한 모델로 통일돼 있다. 그러니 다음 관찰을
다시 시작할 때 모델 자체는 손댈 게 없다 — 이번에 진짜 고쳐야 했던 건 모델이
아니라 observe_others 설정과, 3편에서 이미 결정했지만 실제 훅엔 한 번도
반영된 적 없는 reasoning level이었다.
그래서 지금까지 쌓은 게 다 무의미한가
여기서 정직하게 짚어야 할 게 있다. 이 발견이 4편, 5편을 통째로 무효로 만드는 건 아니다.
- 릴리스 버전(0.89.9 답변) 건은 이 버그로 설명 안 된다.
user-default-hermes서랍 안에 0.89.12까지 이미 다 있었다 — 릴리스 승인은 사용자가 한 말로 기록되니까. 그런데도 dialectic이 최신 걸 안 골랐다. 이건 여전히 진짜 retrieval 문제다. - “이미 고쳤다”고 세 번 우긴 건(4편)도 이 버그로 설명 안 된다. 이건 없는 걸 있다고 지어낸 거지, 있는 걸 못 본 게 아니다.
- 반대로 Web Clipper 임계값(0.85), 그리고 아마 그 비슷한 성격의 “claude-code가 제안하고 결정한 것” 부류는 이 버그가 직접 원인이었을 가능성이 크다.
모델이 완전히 무죄인 것도, 이 설정 버그 하나가 전부인 것도 아니다. 둘 다 있었다. 근데 이 설정 버그는 07-14부터 지금까지 한 번도 안 꺼진 적이 없다 — 4편에서 모델을 바꾼 이후 일주일을 관찰하기로 한 계획은, 적어도 이 버그가 만드는 오차만큼은 처음부터 끝까지 껴 있는 채로 관찰하는 셈이었다.
이 시리즈를 시작한 이유가 “Honcho가 자신 있게 말하는 걸 그대로 믿지 말자”였다. 근데 이번엔 Honcho가 아니라 Claude Code가 자신 있게 틀린 설명을 냈다 — “대화에 없었을 것”이라고, 확인도 안 하고. 그걸 그냥 넘기지 않고 “아니야, 그거 대화에 있었어”라고 되받아친 반박이 없었으면 이 구조적 버그는 계속 안 보인 채로 남아 있었을 거다.
검증 습관은 Honcho의 답에만 적용할 게 아니라, Claude Code가 낸 그럴듯한 설명에도 똑같이 적용해야 했다. “그럴듯하게 들리는 원인 하나를 찾았다”는 게 “원인을 다 찾았다”는 뜻이 아니다 — 한 겹 더 파보니 그 밑에 훨씬 큰 게 있었다. 2편에서 모델과 반복 횟수를 분리하지 않고 뭉뚱그렸던 것과 같은 실수를, 이번엔 “모델 문제”와 “설정 문제”를 뭉뚱그리는 걸로 또 반복한 셈이다.
고친 것 두 가지
1. observe_others 켜기. Honcho API로 claude-code peer의 세션 설정을
바꿨다.
PUT /v3/workspaces/hermes/sessions/claude-code/peers/claude-code/config
{"observe_me": true, "observe_others": true}
Hermes 설정을 그대로 베끼면 observe_me: false가 되는데, 그건 안 했다.
Hermes는 AI 자신에 대한 모델이 필요 없어서 꺼둔 거지만, claude-code의
자기 자신에 대한 관찰(1,100건, 지금까지 이 시리즈가 찾으려던 바로 그 데이터)은
계속 쌓여야 해서 observe_me는 켜둔 채로 observe_others만 추가했다.
2. 훅이 쿼리하는 peer 바꾸기. honcho_recall.sh가 지금까지
peers/user-default-hermes/chat을 불렀는데, 이제 peers/claude-code/chat을
부르게 바꿨다 — Hermes가 실제로 쿼리하는 방식(AI 자신의 peer로) 그대로다.
reasoning_level은 low로 그대로 뒀다. max는 반복이 10회라 훅의 4초
타임아웃을 넘길 가능성이 크고, 지금은 비용/속도 면에서 일단 low로 일주일
정도 실사용해보고, 그래도 안 좋으면 그때 max로 가기로 했다.
바로 같은 질문을 다시 던져봤다
5편에서 세 개 다 틀렸던 그 질문 — “Web Clipper 중복 노트 정리에서 최종 임계값이 뭐고, 이 이슈는 해결된 상태야?” — 를 고치자마자 똑같이 다시 물어봤다.
이번엔:
최종 임계값은 0.85입니다. … 이 이슈는 2026년 7월 16일에 해결되었음을 확인하고 종료 처리되었습니다. … 체크박스로 선택한 중복 노트를 일괄 삭제(휴지통 이동)하는 UX까지 구현이 완료된 상태입니다.
세 개 다 맞았다. 임계값(0.893이 아니라 0.85), 해결 상태(아직 안 됐다가 아니라 07-16에 종료), 그리고 이번엔 존재하지도 않는 repo 이름을 지어내지도 않았다.
남는 생각
한 번 물어봐서 세 개 다 맞았다고 “고쳐졌다”고 선언하긴 이르다. 이 시리즈에서 계속 반복한 실수가 “그럴듯한 결과 하나로 성급하게 결론 내기”였다. 이제부터 다시 일주일 정도 실사용하면서, 같은 종류의 질문에서 이 정확도가 유지되는지 지켜볼 차례다. 결과는 다음 편에.