에이전트 영속 메모리를 실제 소스와 대조 — 각 메모리의 핵심 단언을 코드·DB·이슈 트래커·파일시스템에 대조해 stale 을 정정하고 dead 를 아카이브 후보로 리포트. 메모리가 30개를 넘거나, 스택/인프라 큰 변경(라이브러리 교체·버전 업그레이드·서버 이전·스키마 DROP) 직후, 메모리끼리 모순돼 보일 때, 또는 "메모리 정리/감사" 요청 시 사용.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add LeeYudok/agents-scaffold --skill memory-factcheck --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Memory Factcheck?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/leeyudok-memory-factcheck)More formats (shields.io, HTML) on the badges page.
---
name: memory-factcheck
description: 에이전트 영속 메모리를 실제 소스와 대조 — 각 메모리의 핵심 단언을 코드·DB·이슈 트래커·파일시스템에 대조해 stale 을 정정하고 dead 를 아카이브 후보로 리포트. 메모리가 30개를 넘거나, 스택/인프라 큰 변경(라이브러리 교체·버전 업그레이드·서버 이전·스키마 DROP) 직후, 메모리끼리 모순돼 보일 때, 또는 "메모리 정리/감사" 요청 시 사용.
---
# 메모리 사실 검증 (Memory Fact-Check)
> 원형: [leeyudok/doksam-skills](https://github.com/leeyudok/doksam-skills) 의 동명 스킬.
> 템플릿 동봉용으로 **의도적 분기** — 자동 동기하지 않으며, 좋은 개선은 수동 체리픽.
메모리는 부패한다. 쓸 때는 사실이었어도 코드·스키마·인프라가 움직이면 거짓이 된다.
**썩은 메모리는 없느니만 못하다** — 에이전트가 그걸 읽고 자신 있게 틀린 행동을 한다.
이건 **구조 위생 점검이 아니다**. 고아 파일·중복 항목·인덱스 비대·깨진 내부 링크는 전부
**메모리 파일들끼리** 비교하는 검사다. 이 스킬은 메모리를 **그것이 서술하는 실제 세상**과
비교한다 — 코드, 데이터베이스, 이슈 트래커, 파일시스템. 형식이 완벽하고 인덱스도 멀쩡하고
이번 주에 커밋된 메모리가 내용은 완전히 거짓일 수 있다.
자동 폐기는 금지한다. 무엇이 죽었는지는 원천 대조로만 판정 가능하고 사고 교훈의 유실 비용이
크다. 그래서 반자동 — **정정은 자유롭게, 아카이브는 승인 후, 삭제는 절대 금지.**
## 1. 위치 확인·인벤토리
메모리 세트를 찾는다. 우선순위:
- 프로젝트 지시문(`AGENTS.md`/`CLAUDE.md`)이 선언한 경로 — 선언이 모든 기본값을 이긴다
- 레포의 `.claude/memory/` (팀 공유·커밋됨)
- 호스트의 프로젝트별 메모리 디렉터리(예: `~/.claude/projects/<slug>/memory/`)
파일마다 frontmatter(`name`/`description`/`type`)와 최종 수정일(`git log -1 --format=%cs --
<파일>`, 미커밋이면 `stat`)을 수집한다. 인덱스 파일(`MEMORY.md`)이 있으면 함께 감사하되
인덱스는 메모리가 아니다.
**개인 파일은 범위 밖** — 프로젝트가 개인으로 표시한 것(`user_*.md` 등)은 소유자 것이므로
손대지 않는다.
**대량 읽기**: 메모리 50개를 한 번에 컨텍스트로 부으면 툴 출력 상한에 걸리고 예산만 태운다.
`########## <파일명>` 헤더를 붙여 스크래치 파일 하나로 합친 뒤 페이지 단위로 읽는다. 훑지 말
것 — 썩은 단언은 대개 멀쩡한 문단 안의 한 구절이다.
## 2. 핵심 단언 추출
파일마다 **행동을 바꾸는 단언 1~3개**만 고른다. 서술·배경·근거는 무시한다. 메모리의 부패
여부는 실행 가능한 단언에만 달려 있다.
핵심 단언의 모습: "X 는 경로 P 에 있다" · "테이블 T 는 N 행이다" · "#N 은 아직 열려 있다" ·
"기능 F 는 아직 없다" · "라이브러리 L 은 미설치다" · "이 건은 아직 처리 대기다" · "확인은
명령 C 로 한다".
## 3. 원천과 대조
**싸고 수확 많은 것부터** 돈다. 실무상 아래 순서가 유효하다 — 이슈 상태는 API 한 번인데
stale 을 가장 많이 잡는다. 작업 중에 메모리를 쓰고, 작업이 끝난 뒤 아무도 그 메모리를 고치러
돌아가지 않기 때문이다.
| 순서 | 단언 유형 | 검증 방법 |
| --- | --- | --- |
| 1 | **이슈/PR 상태** ("#N 열림", "#N 대기", "결정 대기") | forge CLI/API — `gh issue view N --json state` / `glab api projects/<enc>/issues/N`. 한 루프로 일괄 조회 |
| 2 | **경로/URL** (스크립트 위치, 배포 경로, 엔드포인트) | `ls`, `test -f`, `curl -s -o /dev/null -w '%{http_code}'` |
| 3 | **코드** (파일/클래스/설정 존재, 동작 방식) | 현재 트리 `grep`/`Read` — *SoT 는 코드지 메모리가 아니다* |
| 4 | **데이터/스키마** (테이블·컬럼·건수) | 프로젝트의 DB 수단으로 읽기 전용 조회. 카탈로그 추정치(`pg_class.reltuples`, `information_schema.columns`)를 먼저 쓰고, 정확한 `count(*)` 는 그 수치 자체가 쟁점일 때만 |
| 5 | **런타임/호스트** (크론, 서비스, 로그) | `ssh <host> 'ls …; crontab -l; tail <log>'` — 잡의 마지막 로그 줄이 단언의 시점을 정확히 찍어준다 |
독립적인 검증은 병렬로 돌린다. 원천에 접근할 수 없으면 리포트에 명시한다 — "확인 못 함"을
조용히 "확인함"으로 바꾸지 않는다.
## 4. 분류
- **fresh** — 단언 전부 유효. 손대지 않는다.
- **stale** — 일부 단언이 낡음(경로 이동, 수치 변화, 이슈 종결, 구멍이 메워짐).
→ **실측값과 날짜를 넣어 본문을 즉시 정정한다.** 정정은 자율 실행 범위다(삭제가 아니라 가필).
- **dead** — 핵심 전제가 소멸(라이브러리 제거, 기능 폐기, 완전 대체). → 아카이브 **후보**로만 표시.
## 5. 노려야 할 부패 유형
"숫자가 바뀌었다" 외에 반복되고 놓치기 쉬운 것들:
- **메워진 구멍(fixed-gap drift)** — 없는 기능을 기록한 메모리("기동 reconcile 없음",
"레이트리밋 아직 없음")인데 그 사이 구현됨. **가장 위험하다** — 에이전트가 이미 배포된 것을
다시 만들거나 다시 보고한다. 연결된 이슈 상태 **와 함께** 심볼 grep 으로 확인할 것.
- **메모리 간 모순** — 두 메모리가 서로 다른 말을 함(한쪽은 "이 스크립트로 X 를 한다", 다른
쪽은 "그 스크립트는 폐기"). 정의상 최소 한쪽은 stale 이다. 파일 단위로만 보지 말고 단언을
가로질러 비교한다.
- **규모 드리프트** — 몇 달 전 "테이블 T 는 약 800만 행"이 이제 25% 어긋남. 숫자 자체보다
거기서 파생된 조언(배치 크기, 타임아웃 예산, "이 쿼리 19초")이 같이 썩는 게 문제다.
- **레시피 부패** — 메모리가 검증된 레시피로 저장한 명령/쿼리가 오늘의 데이터 규모나 API
버전에서 더는 동작하지 않음. **저장된 레시피는 재실행한다** — 실행하지 않은 레시피는 미검증이다.
- **진행상태 드리프트** — 장기 작업(백필·마이그레이션) 메모리의 "현재 상태" 섹션이 몇 주
밀려 있거나, 서로 모순되는 상태 섹션이 두 개 쌓여 있음. 섹션마다 날짜를 박고 최신만 남기되
이전 것은 스냅샷으로 표시해 보존한다.
- **정체성 불일치** — `name`/`description` 과 본문이 정반대(예: `*-via-toolX` 라는 이름인데
본문은 "toolX 는 폐기했다"). 리콜은 description 으로 매칭되므로 엉뚱한 이유로 불려오거나
아예 안 불려온다.
## 6. 리포트 → 적용
무엇이든 바꾸기 전에 표로 먼저 보고한다 — 파일 · 분류 · 근거 1줄 · 조치:
| 파일 | 분류 | 근거 | 조치 |
| --- | --- | --- | --- |
| `reference_x.md` | stale | 스크립트가 `scripts/` → `data/` 이동 | 경로 정정 완료 |
| `project_y.md` | stale | "#302 reconcile 부재" 주장 ↔ `JobRunHistoryReconciler` 존재·#302 closed | 구현 완료로 재작성 |
| `project_z.md` | dead 후보 | #N 기능이 #M 에서 제거됨 | 승인 대기 |
그다음:
1. **stale 본문 정정** — 실측값 + 날짜. 원 관측이 교훈을 담고 있으면 이력으로 보존한다
("<날짜> 기준 800만이었고 <오늘> 995만").
2. **dead 후보는 사용자 승인 후에만 아카이브**: `<메모리>/archive/` 로 `git mv` 하고
frontmatter 에 `archived: <날짜> <사유>` 추가. `rm` 금지.
3. **인덱스 동기화** — 정정 반영, 아카이브 항목은 `MEMORY.md` 에서 제거.
4. **프로젝트 표준 워크플로로 커밋**(이슈 → 브랜치/워크트리 → PR/MR). 메모리는 팀 공유
자산이므로 main 직접 커밋 대상이 아니다.
## 판정 기준 — 보수적으로
- **검증 불가 ⇒ fresh.** 원천에 접근할 수 없으면 그대로 두고 "확인 못 함"이라고 적는다.
모르는 것은 죽은 게 아니다.
- **사고 교훈은 코드가 움직여도 fresh.** 무엇이 왜 깨졌는지 기록한 메모리는 재발 방지가
목적이지 호출 지점 스냅샷이 아니다. 낡은 경로 참조만 고치고 교훈 자체를 은퇴시키지 않는다.
- **드리프트는 보고하되 원인을 지어내지 않는다.** 수치가 설명 없이 뒤집혔으면 측정값만 기록하고
"원인 미확인"으로 표시한다. 그럴듯한 이야기를 메모리에 쓰면 내일의 거짓 사실이 된다.
- **신규 생성보다 병합.** 같은 주제 메모리가 둘이면 기존 것에 합치자고 제안한다.
- **감사가 발견한 비자명 사실은 새 메모리로** — 감사 자체가 원천이다.
## 실행 노트
- 최신 수정일은 아무것도 증명하지 않는다. 이번 주 커밋된 파일이 쓸 때부터 이미 틀렸을 수 있고,
몇 달 방치된 파일이 완벽히 참일 수 있다. 날짜로 정렬해 꼬리를 자르지 말고 단언을 검증한다.
- 큰 테이블 `count(*)` 가 statement timeout 에 걸리는 것 자체가 finding 이다 — 그 메모리가
"이 쿼리 빠름"이라고 적어놨다면.
- zsh 에서 글롭은 인용한다(`grep --include="*.java"`). 안 그러면 셸이 먹어치우고 조용히 0건이
나와 **가짜 fresh** 가 만들어진다.
- 이슈가 닫혔다는 사실만으로 그 작업이 배포됐다고 단정하지 않는다. 메워진 구멍 유형은 심볼
grep 을 함께 돌린다.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!