Skip to content

v3.6.0 — Phase 1: Provenance (영구기억 출처 추적)

Choose a tag to compare

@etinpres etinpres released this 31 May 04:40
· 51 commits to master since this release

v3.6.0 — Phase 1: Provenance (영구기억 출처 추적)

Summary

"신뢰 가능한 효과적 회수(trustworthy effective recall)"를 향한 Phase-1 기반 로드맵의 첫 축 — 출처 추적(Provenance). 영구기억이 어디서 왔는지(어떤 세션·소스에서, 언제 포착됐는지)를 staging 시점에 frontmatter에 기록하고, 회수될 때 그 출처를 결과에 부착·표시한다. 사용자가 회수된 메모리를 볼 때 "이게 언제·어디서 온 기억인지"를 한 줄로 확인할 수 있어, AI의 "딴소리"를 검증·신뢰하는 근거가 된다.

12 커밋. 기능 골격(write → recall → format)을 먼저 깔고, 다단계 적대적 버그헌팅(find → adversarial verify → fix-the-fix, 2 라운드 + completeness sweep) 으로 프로덕션 갭과 직렬화 취약점을 교차 발견·수정했다. provenance 테스트 +28 (전체 668개 수집 · 667 passed · 1 skipped(pre-existing) · 25 subtests passed).

Added

  • staging 시 출처 기록 (write_staged): 영구기억 후보를 staged할 때 source_type / source_ref를 frontmatter에 남긴다. 기본값 파라미터(source_type="session", source_ref=session_id)라 기존 호출부는 무변경. Phase-2(URL ingest 등) 다양한 소스 유형을 받을 수 있도록 시그니처를 미리 열어둠.
  • 회수 시 provenance 부착 (recall_memory): 회수 결과에 메모리 파일의 frontmatter를 재파싱해 provenance(source_type / source_ref / captured_at)를 동반한다. (DB 스키마 불변 — 결과 path frontmatter 재파싱 방식, TOP_K=1이라 비용 무시 가능.)
  • 회수 출력 "출처:" 라벨 (_format_output): - [name] 라인 직후 출처: {source_type} {ref8} {date10} 짧은 한 줄을 삽입(ref·날짜는 앞 8·10자만, 토큰 낭비 방지). 노이즈 방지를 위해 unknown·빈 source_type은 미표시. Layer 4 hook(hooks/memory-recall.py _format_output)과 compact 재주입(src/recall_core.py format_memory_context)은 별도 구현이지만, parity 테스트(test_formatter_byte_equivalence)가 두 경로의 출력이 byte-동일함을 강제한다(provenance 4 shape 포함 — datetime captured_at / unknown 억제 / None ref / 8자 초과 ref).
  • 기존 메모리 backfill CLI (provenance_backfill_cli): 출처가 없는 기존 메모리에 소급 부여. 억측 금지 원칙 — 기록된 session id가 있으면 session, 없으면 unknown fallback(git blame류 추론 안 함). 실제 기록 형식을 모두 인식하도록 session id 우선순위를 staged_from_sessionoriginSessionId(top-level) → metadata.originSessionId(nested — memory-production 파이프라인의 실제 형식)로 확장. _procedural/ 디렉토리 포함(recall 인덱싱 범위와 일치), _staged/·MEMORY.md 제외, atomic write(tmp + os.replace), trailing-whitespace fence 파일도 crash 없이 처리. dry-run 기본 / --apply 시에만 쓰기, 멱등, skip·실패 파일명 리포트.

Fixed (adversarial sweep)

  • cmd_approve 승격 시 출처 소실 — 게이트1 프로덕션 갭 (핵심): write_staged는 출처를 staged frontmatter에 박았지만, cmd_approve가 승격(promote) 시 frontmatter를 처음부터 재구성하며 source_type/source_ref/captured_at를 통째로 떨어뜨려 — 완료 게이트 "신규 영구기억 출처 추적률 100%"를 정작 영구 진입 경로(/memory_review 승인)에서 깨고 있었다. _provenance_passthrough 헬퍼(_supersede_passthrough 패턴 미러)를 NEW-PROMOTE / UPDATE 두 final_fm 블록에 모두 wire-in. UPDATE 경로는 기존 영구메모리의 원본 출처를 우선하고, absent(또는 unknown)일 때만 staged 메타로 폴백 — donor를 원자적으로 선택해 incoherent한 source_type/source_ref 짝 섞임을 차단.
  • recall 핫패스 UnicodeDecodeError 견고화: provenance frontmatter 재파싱 루프가 (OSError, UnicodeDecodeError, KeyError)를 모두 catch — 비-UTF8/손상 메모리 파일 한 개가 recall 결과 전체를 [] 로 날리던 경로 차단(backfill CLI와 대칭).
  • source_ref str 정규화 (JSON-safe): recall_memory provenance 루프에서 source_refcaptured_at과 동일 방식으로 정규화(isoformat 우선, 그 외 비-None/비-빈은 str(), None/"" 유지). YAML이 bare 숫자·날짜를 int/date로 파싱해도 /recalljson.dumps가 깨지지 않도록 보장(+ recall_cli json.dumps(..., default=str) 방어).
  • contradiction-aware writer kwargs forward (Phase-2 forward-proof): make_contradiction_aware_writer의 wrapper가 **kwargs를 base_writer로 전달하지 않아, source_type/source_ref를 넘기는 미래 호출자(Phase-2 URL ingest 등)가 writer를 통과하며 provenance를 silently drop할 latent 버그를 사전 차단. 기존 caller(kwargs 없음) 무영향, contradiction detection 로직 변경 없음.
  • backfill 견고화: ref 확정 시 re.sub(r"\s+", " ", str(ref))로 multiline 값을 단일 라인으로 collapse(frontmatter 구조 보호), trailing-ws 닫는 fence를 tolerant 탐지(exact lines.index("---") ValueError → 전체 run abort + --apply half-migration 차단), per-file try/except로 한 파일 실패가 배치를 중단시키지 않음.

Tests

  • provenance end-to-end 통합(write_staged → cmd_approve 승격 → index → recall → format 출처 라벨), cmd_approve NEW/UPDATE/fallback·unknown-adopts-staged 커버리지, recall_core parity(provenance shape), JSON-safe 직렬화, trailing-ws fence·multiline-ref collapse 단언 등 +28 테스트.
  • vacuous(실제로 fix를 검증하지 못하던) fixture 교정 — multiline collapse 경로를 강제 트리거하도록 fixture에 실제 \n embed, docstring 부정확 기술 정정.
  • 전체 회귀: 668 collected · 667 passed · 1 skipped(pre-existing) · 25 subtests passed.

Notes

  • 기존 메모리 backfill은 별도 CLI(python -m src.provenance_backfill_cli <memory_dir> [--apply])로 수행 — 운영 메모리 172건(session 83 / unknown 89) 소급 적용 완료.
  • Phase-1의 나머지 두 축(②효과적 회수 self-check, ③stale 자동 감지)은 별도 릴리즈로 분리.