추론 엔진
쌓인 노트를 새로운 추론으로 바꾸는 방법, 결정론적 신호, 에이전트가 종합한 가설, 자동 무효화.
검색은 당신이 쓴 것을 꺼내옵니다. 추론 엔진은 한 걸음 더 나아갑니다, 어느 노트에도 단독으로 적혀 있지 않은, 노트 사이의 패턴을 드러내고, 그중 좋은 것을 출처가 박힌 지속적인 가설로 승격시킵니다.
설계 가설은 플래시백과 같습니다: 가치는 양이 아니라 연결에 있다. 다만 플래시백이 관련 노트 하나를 가리킨다면, 추론 엔진은 코퍼스 전체의 구조를 봅니다, 몇 년에 걸친 클러스터, 조용히 낡아버린 state 노트, 한 번도 종합하지 않은 테마.
핵심 원칙: memex는 LLM이 아니다
memex는 언어 모델을 호출하지 않습니다. 결정론적 구조 엔진으로 남습니다. 이 분리는 의도적입니다(firma가 사실과 서사를 나누는 것과 같은 방식):
- memex는 찾고·점수 매기고·저장한다, 싸게, 재현 가능하게, 환각 표면 없이.
- 에이전트(대화 중인 Claude)는 종합이라는 단 한 스텝만, 그것도 당신이 요청할 때만 한다.
이것이 시간이 지나도 브레인을 신뢰할 수 있게 합니다. 추론은 별도 테이블에 저장되고 search_notes 결과에 절대 섞이지 않습니다. 그래서 다음 종합이 이전의 (틀렸을 수도 있는) 추론을 재료로 먹는 일이 없습니다. 그 순환 메아리가 세컨드 브레인이 자가오염되는 경로인데, 테이블 분리가 이를 구조적으로 막습니다.
두 레이어: 신호 → 추론
notes ──(결정론적 탐지)──▶ signals ──(승인)──▶ 에이전트 종합 ──▶ inferences
▲ │
└────────── triage (dismiss/snooze) ────┘
신호 (Lv1, LLM 없음)
신호는 종합되지 않은 패턴을 가리킵니다, "여기 생각해볼 만한 게 있다." 4개의 탐지기, 전부 순수 SQL + 벡터 연산:
| 신호 | 잡아내는 것 |
|---|---|
hidden_arc | 명백히 한 묶음인데 한 번도 연결되지 않은, 오랜 시간에 걸친 노트 클러스터, 종합 안 된 스레드. |
stale_state | 마지막 업데이트 이후 더 새로운 연관 노트가 생긴 state 노트, "현재 진실"이 낡았을 수 있음. |
dangling_link | 아직 존재하지 않는 노트를 가리키는 [[링크]], 명시적인 미해결 질문. |
tag_burst | 몇 달 잠잠하다 다시 떠오른 태그, 관심의 부활. |
hidden_arc가 까다로운 녀석입니다. mutual-kNN 그래프(두 노트가 서로의 최근접 이웃일 때만 엣지)를 만들고, union-find로 disjoint 컴포넌트를 구한 뒤, 4~12개·기간 ≥180일·내부 링크 거의 0인 컴포넌트만 남깁니다. mutual-kNN은 무관한 아크들을 하나로 뭉쳐버리는 "허브" 노트를 제거하고, 크기·기간 필터는 진짜 아크(주기적 성찰)와 토픽(매일의 작업 흐름)을 분리합니다.
신호는 triage 상태(new / snoozed / dismissed / minted)와 함께 materialize됩니다. 그래서 노이즈를 dismiss하면 유지됩니다, 탐지를 다시 돌려도 이미 판단한 건 다시 안 뜹니다.
추론 (Lv2, 에이전트가 종합)
추론은 가설입니다: 여러 노트를 관통하지만 어디에도 적혀 있지 않은 비자명한 주장. 당신(또는 에이전트)이 신호의 근거를 읽고, 주장을 종합해, mint합니다. 저장되는 것:
- 제목 + 요약(주장과, 근거가 그것을 뒷받침하는 이유),
confidence점수와 그것을 만든model_id,- 모든 출처 노트로의 evidence 엣지, mint 시점 그 노트의 content 해시 스냅샷.
추론은 사실이 아니라 가설입니다. 에이전트가 추론을 사용할 때는 그렇게 인용합니다 ([Inference #42, conf 0.78, from notes #1, #2]) 절대 당신이 "아는 것"처럼 제시하지 않습니다.
무효화: 브레인은 썩지 않는다
content 해시 스냅샷이 시간이 지나도 추론을 정직하게 유지합니다. 추론을 읽을 때마다 memex는 출처 노트를 다시 해싱해 비교합니다:
- 출처의 내용이 바뀜 → 추론이
stale로 전환, - 출처가 삭제됨 → 고아로 플래그(evidence 행을 일부러 남겨서, 손실이 조용히 사라지지 않고 감지 가능하게).
stale 추론은 [!] STALE 마커와 문제된 출처 옆 ~/✗를 보여줍니다. 전부 결정론적입니다, 추론이 썩은 걸 알아채는 데 LLM이 필요 없습니다. 플래그된 추론은 다시 mint하면 됩니다(종합은 holistic하므로 부분 패치는 취약함). 출처가 다시 안정되면 active로 돌아옵니다.
기본은 lazy, 데몬 없음
탐지는 on-read입니다: memex signals·memex digest·MCP get_signals가 호출 시 돌립니다. 백그라운드 데몬은 없습니다, local-first CLI에 맞지 않으니까요.
on-read를 저렴하게 유지하려고 refreshSignals는 dirty-flag를 씁니다: 마지막 실행 이후 바뀐 노트가 없으면 탐지를 통째로 건너뜁니다(engine_meta 테이블로 추적). 그래서 정적인 코퍼스는 비용이 0이고, 실제로 뭔가 바뀌었을 때만 O(N·kNN) 비용을 치릅니다.
그래도 매일 알림을 원한다면? OS에게 맡기세요, memex schedule이 memex digest를 돌리는 cron/launchd 스니펫을 바로 붙여넣을 수 있게 출력합니다. memex는 여전히 장수 프로세스를 소유하지 않습니다.
어디서 나타나나
- CLI,
memex signals(dismiss/snooze포함),memex signals mint,memex inferences.memex digest는 이제 신호 요약과 active/stale 추론으로 끝맺습니다. - MCP,
get_signals,update_signal_status,list_inferences,get_inference,mint_inference. 에이전트는 신호를 보여주고, 당신이 명시적으로 요청할 때만 승인된 가설을 mint합니다. MCP 툴 참조.
가드레일 (왜 믿을 수 있나)
- 코어에 LLM 없음, 탐지와 무효화는 결정론적; 모델은 최종 요약만 쓴다.
- 추론 ≠ 노트, 별도 테이블, 검색에서 제외 → 종합이 자기 출력을 먹지 못함.
- 자동 mint 금지,
mint_inference는 명시적 사용자 승인(confirmed: true) 필요; 에이전트는 가설을 먼저 제시한다. - 출처 + 무효화, 모든 추론이 출처와 해시를 들고 있어 drift가 자동으로 잡힌다.