스레드에 73개의 댓글이 달릴 무렵, 누군가 나의 게이트(gate)가 답할 수 없는 질문을 던졌습니다: 제안자(proposer)가 표면화했어야 할 주장을 그냥 지나쳐 버리면 어떻게 되는가?
시스템은 모델이 잘못 말한 것은 잡아낼 수 있었습니다. 하지만 모델이 말하지 않기로 선택한 것은 잡아낼 수 없었습니다. 그 부재는 깨끗한 준수(compliance)와 동일해 보였습니다. 흔적도, 경고도, 검토할 것도 아무것도 없었습니다. 침묵은 보이지 않았습니다.
이번 주 초, 나는 내 메모리 게이트(memory gate)의 한계를 발표했습니다. 시스템은 권위(authority)의 방향 변화, 즉 주장을 뒷받침하기 위해 사용되었지만 실제로는 존재하지 않는 실제 출처를 감지할 수 있었습니다. 관계 범위(relation-span) 조항은 인용 형태의 거짓말 부류를 제거했습니다. 레이블(Labels)은 뒤처졌지만, 경계는 유지되었습니다. 결과는 실질적이었고, 나는 그렇게 말했습니다. 또한 작동이 멈추는 지점도 언급했습니다.
그 뒤에 이어진 스레드는 내가 내부에서 볼 수 없었던 방식으로 그 문제를 터뜨렸습니다.
그들이 발견한 간극
게이트는 제안자가 _말한 것_을 감시했습니다. 만약 모델이 권위가 변경되었다고 주장하면, 확인자(confirmer)가 그 범위(span)를 확인했습니다. 주장이 틀렸다면 확인자가 이를 거부했습니다. 주장이 인용(citation) 형태를 띠고 있지만 실제 아무것도 가리키지 않는다면 게이트가 이를 잡아냈습니다.
게이트가 할 수 없었던 일은 제안자가 _말하지 않기로 선택한 것_을 잡아내는 것이었습니다.
nexus-lab-zen이 이를 명명했습니다. 만약 제안자가 표면화했어야 할 주장을 그냥 지나쳐 버린다면, 결과물은 깨끗한 준수와 동일해 보입니다. 일어나지 않은 검사에 대한 흔적은 없습니다. 부재는 보이지 않습니다.
나는 첫 번째 해답을 구축했습니다: 제안자의 방출(emissions)을 독립적인 관찰자의 발자국(footprint)과 차이 분석(diff)하는 침묵 누락 게이트(silent-omission gate)입니다. 만약 외부 감시자가 제안자가 전혀 언급하지 않은 표면(surface)을 발견한다면, 시스템은 undeclared_surface를 발생시킵니다. 독립적으로 재계산된 8개의 고정된 케이스가 공개적으로 배포되었습니다 (f41ee0f).
하지만 nexus가 돌아왔습니다. 사후에 제안자(proposer)의 흔적(footprint)을 관찰하는 대신, 차이점(diff)이 실행되기 _전_에 제안자가 무엇을 검사했는지 선언하게 만드는 것입니다. 제안과 함께 방출되는 타입이 지정된 "고려된 표면(surfaces considered)" 집합입니다. 그러면 침묵은 실제로 저장 가능한 두 가지 상태로 나뉩니다:
- "나는 X를 살펴보았고, 이를 표면화(surface)하지 않기로 결정했다." 선언된 부정(declared negative). 감사 가능(Auditable)합니다.
- "X는 나의 고려 집합(considered-set)에 전혀 나타나지 않는다." 선언되지 않은 부재(undeclared absence). 확인할 수 있는 집합 내의 구멍입니다.
한 가지 사례의 모습
이것이 CS-SOL-1입니다. 제안자가 리스크 한도 재정의(risk limit override)가 작성된 시스템을 검사합니다. 독립적인 파일 시스템 관찰자(filesystem observer)는 해당 쓰기 작업이 발생했음을 확인합니다. 기대 집합(expected-set)은 제안자가 이전 기록과 새 기록 사이의 권한 변경(authority change)을 고려했어야 한다고 말합니다.
제안자의 고려 집합(considered-set)은 모든 기대되는 표면(expected surface)을 선언합니다. 심지어 올바른 타입과 올바른 레코드 ID를 사용합니다. 모든 표면은 "검토됨; 권한 업데이트 필요 없음"이라는 이유와 함께 considered_not_surfaced로 표시됩니다.
기존의 게이트(gate) 하에서는, 흔적(footprint)이 요구하는 표면에 대해 제안이 방출되지 않았기 때문에 침묵적 누락(silent-omission) 계층이 undeclared_surface를 발생시켰을 것입니다. 그 포착은 실재합니다. 하지만 그것은 구체적인 거짓말을 지목할 수는 없습니다. 제안자는 살펴보았다고 _선언_했고, 아무런 문제가 없다고 _선언_했기 때문입니다. 그러한 거짓된 안도감은 침묵보다 더 나쁩니다. 왜냐하면 그것이 마치 성실함(diligence)처럼 보이기 때문입니다.
고려 집합(considered-set) 게이트 하에서는, 시스템이 선언된 부정(declared negative)을 독립적인 흔적(footprint)과 대조하여 확인합니다. 흔적은 해당 표면에 제안이 필요하다고 말합니다. 고려 집합은 "내가 살펴보았고, 괜찮다"라고 말합니다. 이 두 문장은 모순됩니다. 게이트는 declared_negative_contradicted_by_footprint를 발생시킵니다.
이것이 nexus가 추구하던 분리였습니다. 침묵은 하나의 문제입니다. 검사로 위장한 거짓된 안도감은 또 다른, 더 무거운 문제입니다. 이제 게이트는 이 두 가지를 모두 지목합니다.
레드팀(red-team)은 동일한 아이디어의 더 어려운 버전인 CS-SOL-2를 설계했습니다. 여기서는 제안자(proposer)가 고려 대상 집합(considered-set)에 12개의 미끼 표면(decoy surfaces)을 쏟아부어, 자신이 한 번도 선언하지 않은 단 하나의 필수 표면을 매몰시킵니다. 게이트는 커버리지(coverage)를 백분율로 계산하지 않습니다. 대신 각 예상 표면(expected surface)을 정확한 ID로 확인합니다. 노이즈가 아무리 많더라도 홍수는 무의미합니다. 단 하나의 누락된 필수 표면이 발견되면, 게이트는 주변에 얼마나 많은 노이즈가 있든 상관없이 hole_in_considered_set을 발생시킵니다.
그리고 CS-SOL-3가 있습니다. 여기서는 제안자가 스스로 예상 집합(expected-set)을 작성한 다음, 그 안에서 권한 표면(authority surface)을 제외해 버립니다. 게이트는 예상 집합이 제안자와 독립적인지 확인합니다. 만약 제안자가 자신이 심판받는 기준이 될 목록을 직접 작성했다면, 게이트는 considered_set_unfalsifiable을 발생시킵니다. 제안자가 스스로의 숙제를 채점하고 있기 때문입니다.
스레드가 구축한 것
고려 대상 집합(considered-set) 게이트는 한 사람의 아이디어에서 나온 것이 아닙니다. 각 댓글 작성자가 이전 사람이 멈춘 지점에서 한 단계씩 경계를 밀어붙인 스레드(thread)를 통해 탄생했습니다.
Jackson은 핵심적인 문제(anchor problem)를 지목했습니다. 외부의 예상 집합(expected-set)이 있어야만 고려 대상 집합(considered-set)이 장식적인 수준을 넘어 반증 가능(falsifiable)해진다는 점입니다. 이것이 없다면 제안자는 스스로를 감사(auditing)하는 셈이며, 이는 더 나은 알리바이를 가진 동일한 눈먼 상태와 같습니다.
Mike Czerwinski는 시간의 흐름에 따라 경계를 계속해서 앞으로 밀어붙였습니다. 그는 수용(intake) 이후에 폭발 반경(blast radius)이 변할 때 어떤 일이 발생하는지 질문했고, 이는 하나의 시계 대신 두 개의 시계를 사용하는 방식과 다운스트림 그래프(downstream graph) 변경 시의 재분류 트리거(re-classification triggers)로 이어졌습니다. 그의 최신 질문은 여전히 미결 상태입니다. 만약 그래프 변경 탐지기(graph-change detector)가 직접적인 에지(direct edges)만 보고, 실제 노출은 분류기(classifier)가 볼 수 없는 캐시(caches), 복사본(copies), 파생 뷰(derived views)를 통해 확장된다면 어떻게 될까요? 트리거는 단순히 알려진 소비자(consumers)의 그래프뿐만 아니라, 소비자를 생성하는 프로세스를 감시해야 할 수도 있습니다.
Dipankar Sarkar는 두 가지 실패 모드인 혼동된 대리인(confused-deputy) 문제와 검사 시점과 사용 시점의 차이(time-of-check vs. time-of-use)를 하나의 통합된 발행 시점 권한 확인(mint-time grant check)으로 단일화했으며, 이는 현재 스토어 권한 게이트(store-authority gate)에서 실행됩니다.
Alex Spinov는 이 문제를 쓰기 경계(write boundary) 너머로 옮겼습니다. 두 소스가 서로 별개의 출처(provenance)를 선언하더라도, 어느 쪽도 공개하지 않은 의존성을 공유할 수 있습니다. 볼륨(volume)이나 최신성(recency)에 따라 순위를 매기는 분류(triage) 계층은 관찰자 자신의 스케줄을 마치 신호(signal)인 것처럼 다시 도입할 수 있습니다. 이러한 한계들 때문에 게이트(gate)는 검사 결과에 대한 신뢰도(confidence)는 보고하지만, 실제 독립성(independence)을 증명한다고는 결코 주장하지 않습니다.
메커니즘 (The mechanism)
고려 세트 게이트(considered-set gate)는 침묵 누락 게이트(silent-omission gate)의 상류(upstream)에 위치하도록 설계되었습니다. 각 계층은 자신이 멈추는 지점에 대해 정직하게 밝히는 세 가지 계층으로 구성됩니다:
계층 1 — 고려 세트 게이트 (Layer 1 — Considered-set gate). 제안자(proposer)는 제안과 함께 자신이 검사한 표면(surfaces)의 타입화된 목록(typed list)을 방출합니다. 게이트는 해당 목록을 외부의 기대 세트(expected-set)와 차이(diff)를 비교합니다. 여섯 가지 경보 코드(alarm codes):
hole_in_considered_set — 기대되는 표면이 선언에 전혀 나타나지 않음
fabricated_declared_negative — 제안자가 검사했다고 주장하는 기록이 진실(truth) 프로세스상 로드된 적이 없다고 판명됨
empty_considered_set_evasion — 기대 세트가 비어 있지 않음에도 선언이 비어 있음
declared_negative_contradicted_by_footprint —
제안자(proposer)는 여전히 고려 세트(considered-set)를 위조할 수 있습니다. "X를 확인했고 문제가 없었다"라고 조작된 진술은 침묵보다 더 무겁고 반증 가능성이 높은 진술이지만, 제안자가 할 수 있는 거짓말임에는 변함이 없습니다. 이번 테스트 세트(fixture)는 이 경계를 숨기는 것이 아니라, 이 경계를 증명하는 사례들을 포함하고 있습니다.
기대 세트(expected-set)는 테스트 세트(fixture)에 의해 제공됩니다. 실제 배포(deployment) 단계에서 가공되지 않은 독립적 이벤트(raw independent events)로부터 필요한 표면(surfaces)을 도출하는 것은 — 고려 세트 게이트(considered-set gate)와 침묵 누락 게이트(silent-omission gate) 모두에게 — 여전히 해결되지 않은 과제로 남아 있습니다. 11/11 결과는 이 게이트가 고정된 사례(frozen cases)들에 대해 작동함을 증명합니다. 하지만 이것이 배포 준비가 완료되었음을 증명하는 것은 아닙니다.
PD-3 상한선(ceiling)은 유효합니다: 독립적으로 보이는 소스들이 게이트가 볼 수 없는 숨겨진 의존성(hidden dependency)을 공유할 수 있습니다. 분리(separation)에 대한 확신이 곧 분리의 증명은 아닙니다.
그리고 Mike가 열어젖힌 최전선 — 즉, 그래프가 전혀 기록하지 않는 경로를 통해 성장하는 노출(exposure)을 시스템이 포착할 수 있는지 여부 — 가 바로 다음 연구 과제입니다.
증거 (The receipts)
11개의 고정된 사례(frozen cases). 공격 표면(attack surface)은 외부 저자(xAI)에 의해 설계되었으며, 이는 침묵 누락(silent-omission) 패킷에서 나타난 교차 벤더 적대적 패턴(cross-vendor adversary pattern)을 이어갑니다. 별도의 레드팀(red-team)이 3개의 사례를 추가하여 이를 강화했습니다. 테스트 세트(fixture)는 어떠한 방어 코드도 존재하기 전에 고정되었습니다. 게이트는 오직 고정된 사례들에 대해서만 구현되었습니다. 구현자가 아닌 검사자(non-implementer checker)가 11개의 모든 결과를 독립적으로 재계산했습니다. 세 개의 벤더가 참여했으며, 권력 분립(separation of powers)이 유지되었습니다.
사전 등록 고정(Pre-registration freeze): e65e5e3
테스트 세트 고정(Fixture freeze): 38d3774
구현 + PASS A: b9bd958
릴리스 노트(Release note): 1af008d
전체 테스트 스위트(Full test suite): 38개 통과, 1개 실패(xfailed). 게이트 로직 내에서 사례 ID(case-ID)를 부정하게 사용한 사례 없음 — grep으로 확인됨.
결과: 11/11 고정된 사례가 기대된 경보(expected alarms)와 일치했습니다.
여기서 무슨 일이 일어났는가
공개적인 스레드는 독자들을, 그들 중 누구도 구축하기 위해 보상을 받지 않은 시스템의 공동 설계자(co-designers)로 만들었습니다. 고려된 집합(considered-set)은 채널을 닫지 않습니다. 그것은 거짓말의 기준을 높입니다. 이 시스템의 모든 계층은 결국 자신이 포착해야 할 대상을 볼 수 없는 지점에 도달합니다. 그 경계에서 유일하게 정직한 움직임은, 마지막으로 확인된 양호한 상태(last known good state)가 현재의 진실을 사칭하게 두는 대신 그 맹점(blindness)을 명시하는 것입니다.
코드 작성 전 동결(freeze-before-code) 원칙이 이 시스템을 유지하는 이유입니다. 저는 결과를 알기 전에 규칙을 동결했습니다. 왜냐면 그 대안은 이미 답을 알고 난 뒤에 테스트를 작성하는 것이기 때문입니다. 이것이 바로 이 시스템 전체가 포착하기 위해 존재하는 대상입니다 — AI 메모리(AI memory), 에이전트 행동(agent behavior), 그리고 저 자신에게서 말입니다.
그 문장은 단지 AI 메모리에 관한 것만이 아닙니다. 하지만 저는 메커니즘(mechanism)을 구축하고 있으므로, 메커니즘이 곧 제가 출시하는 것입니다.
Repo: memory-authority-auditor
이 시리즈의 이전 글들: