v3.7.0 — Phase 1 ②: 효과적 회수 강화 (self-check 계약 + checkable 게이트)
v3.7.0 — Phase 1 ②: 효과적 회수 강화 (self-check 계약 + checkable 게이트)
Summary
직전 v3.6.0(Phase 1 ① Provenance, 출처 추적)에 이은 Phase-1 두 번째 축 — 효과적 회수(effective recall). 회수된 메모리가 답변 reasoning 에 거의 통합되지 않는 under-integration(strict cited 7.62% baseline — self_eval.recall_utilization 측정) 문제를 두 갈래로 손본다: ① 회수 출력 CONTRACT 에 self-check 조항을 추가해 옵션·권장·다음 단계를 제시할 때 회수 메모리의 룰·제약과 충돌하는 항목을 스스로 제거/표기하도록 의무화하고, ② self_eval 에 checkable pass/fail 게이트(recall_utilization_gate() + --target CLI)를 얹어 spec §4.3② 완료 기준("strict cited 상승")을 prose 가 아니라 운영 가능한 임계값으로 고정한다.
12 커밋. 기능을 먼저 깐 뒤 4라운드 adversarial audit(19렌즈 × 2인 검증) 으로 계약·게이트의 갭을 교차 발견·수정했다. 양 포맷터(Layer 4 hook / compact 재주입) byte-parity 와 self_eval ingestion·sanitize 회귀를 모두 가드. 전체 회귀 678 passed · 1 skipped(pre-existing) · 25 subtests passed.
Added
- 회수 CONTRACT 에 self-check 조항 (
hooks/memory-recall.py _format_output/src/recall_core.py CONTRACT): 기존 "회수 노트:" 의무 출력 + "모순되면 즉시 표기" 뒤에 한 문장을 덧붙인다 — "옵션·권장·다음 단계 제시 시 위 회수 메모리에 명시된 룰·제약과 충돌하는 항목은 제거하거나 \"회수 메모리 <이름> 위반 가능성\"으로 표기." Layer 4 hook 과 compact 재주입(SessionStart)은 별도 구현이지만 동일CONTRACT상수/문구를 싣고, parity 테스트가 두 경로 출력의 byte-동일을 강제한다. - strict cited 목표 게이트 (
src/self_eval.py recall_utilization_gate()):recall_utilization()결과를 받아 strict cited 목표 대비 pass/fail 을 판정한다.judged = cited + marker_only + unused(no_response 제외, 측정 정의와 일치)가min_judged(기본 30) 미만이면 소표본 noise 차단을 위해insufficient_sample(pass=False). 반환 dict 에pass / strict / target / judged / min_judged / scope / reason노출. 측정 로직은 불변 — 게이트는 판정만 얹고 임계값을 자동 튜닝하지 않는다(설계 D6). --targetCLI 플래그 (self_evalargparse):--recall-utilization의 strict cited 목표치를 [0.0~1.0] 유한 실수로 받는다(기본RECALL_UTILIZATION_TARGET = 0.15≈ 2× baseline).--json출력 시 결과에gate키를 동봉.- 상수:
RECALL_UTILIZATION_TARGET = 0.15,RECALL_UTILIZATION_MIN_JUDGED = 30,RECALL_UTILIZATION_SCOPE(측정면 = Layer-4 hook 회수만 — compact 재주입 효과 미측정 명시).
Changed / Fixed (4라운드 adversarial audit)
- R2E-1 — 계약을 비가시 type 의존 → content+이름 기반으로 재서술: 초기 self-check 문구가 회수 출력에 가시화되지 않는 정보(type-scoping)에 의존하던 약점을 교정. 회수 결과에 실제로 보이는 "위 회수 메모리에 명시된 룰·제약" 문구 + 구체 placeholder
<이름>기반으로 재서술해 모델이 실제로 따를 수 있게 했다(parity 테스트가 양 포맷터에서 해당 문구 존재를 명시 단언). - R2C-1 — 게이트 측정 scope 명시: 게이트가 신뢰하는 strict 는
recall_utilization의 측정면 = Layer-4 hook 회수(UserPromptSubmit)만 포함한다. compact 재주입(SessionStart)은 동일 CONTRACT 를 싣지만 measurement 면에서 제외(_compact_metric은 recalled_ids 미기록 +RECALL_INJECTION_HEADERS가 compact intro 의 em-dash 변형 미인식). 게이트가 '효과적 회수' 를 과대 인증하지 않도록scope키로 이를 명시(pass/insufficient 양 경로 모두 노출, 테스트로 가드). - R2A-1 —
--targetnan/inf 검증:_target_arg가[0.0, 1.0]유한 실수만 통과시킨다. nan/inf 가 통과하면json.dump가 비-스펙NaN/Infinitybare token 을 출력해 엄격 JSON 파서를 깨뜨리던 경로를 argparse 단계에서 차단(nan·inf·-inf·범위 밖·비숫자 모두ArgumentTypeError). - R2-D-1 — compact 전파 테스트 갭: "compact 재주입은
format_memory_context경유라 self-check 계약이 자동 전파된다"는 설계 주장(D7)을 prose 로만 두지 않고, 실제COMPACT_INTRO로 렌더해 조항이 들어가는지 직접 고정하는 테스트를 추가. - docs: 설계 doc(D2 content-scope, D3 확정 문구) 및 plan prose(Goal·회귀 예상치 675) 의 stale 기술을 audit round2/3 정정 반영(R3D-1/R3D-2).
Tests
- self_eval 게이트 (
tests/test_self_eval.py TestRecallUtilizationGate, +7): target 이상 pass / 미만 fail /insufficient_sample/strict == target경계 통과(>=) / 기본 상수 / scope 노출(R2C-1) /--targetnan·inf·범위밖 거부(R2A-1). - 계약 parity·회귀 (
tests/test_recall_core_parity.py, +4): self-check 조항이 양 포맷터에 존재하고 기존 "회수 노트:" 계약과 byte-parity 유지(D7), 새 계약 footer 가RECALLED_NAME_RE추출 noise 를 만들지 않음(ingestion 회귀), snippet 의</system-reminder>누출 차단(sanitize 회귀), compact intro(COMPACT_INTRO) 경로 전파(R2-D-1). - 전체 회귀: 678 passed · 1 skipped(pre-existing) · 25 subtests passed.
Notes
- 솔직한 한계 ①: self-check 계약은 회수 출력에 실린 지시일 뿐, hook 이 모델의 준수를 100% 강제하지는 못한다(계약 텍스트가 답변에 들어가도록 보장할 뿐, 옵션·권장 단계의 실제 cross-reference 수행은 모델 재량).
- 솔직한 한계 ②: strict cited 게이트는 Layer-4 hook 회수면(UserPromptSubmit)만 측정한다. compact 재주입(SessionStart) 효과는 미측정이며, 회수면 합산은 Phase 2 후속 과제(측정 로직 동결 — D6). 또한 strict cited 는 substring-match 기반 lower bound 라 목표(0.15) 미달이 곧 실패는 아니다(의역·rephrase 통합은 marker_only/unused 로 과소집계).
- 코드 변경은
src·hooks·tests5개 파일에 국한(+240 -2). 회수 측정 임계값(raw cosine/score)은 게이트 결과로 자동 튜닝하지 않는다. - Phase-1 마지막 축(③ stale 자동 감지)은 별도 릴리즈로 분리.