docs: 수동 메모리 게이팅의 근거 정정 — USER.md는 prompts/ 아래 실재한다

a1033f6에서 "USER.md도 SOUL.md도 4명 전 사용자 누구에게도 없어서 memory_browse/read는
'not found' 에러만 낼 수 있다"고 적었는데 **틀렸다**. 감사 때 `ls workspace/*.md`로만 확인했고,
파일은 `workspace/prompts/` 아래에 있다 — resolvePromptPath가 PROMPT_FILES에 대해 그쪽을
**먼저** 본다(server.ts:1199). papa의 USER.md는 3.2KB에 카테고리 5개, 최종 수정 2026-08-06으로
homeclaw_memory 컬렉션의 최신 문서 날짜와 정확히 일치한다. 도구 셋 다 정상 동작한다.

게이팅 결정 자체는 유지한다 — 근거가 사용량이기 때문이다(1,011턴에서 browse 0 / read 2 /
write 1회인데 매 턴 357토큰). 다만 코드·테스트 주석에 박힌 거짓 근거를 걷어낸다. "죽은
레거시라 빼도 된다"와 "멀쩡하지만 거의 안 쓰여 게이팅한다"는 다음 사람이 내릴 판단이 달라진다.

memory_write는 파일이 없으면 만들지 않고 에러를 낸다는 점도 함께 정정했다(execute-tool.ts:1220).
앞선 커밋 메시지의 "없으면 새로 만든다"는 서술이 잘못이었다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rfme1WVEPkpNwnf5oVNXXc
This commit is contained in:
kim
2026-09-04 21:12:21 +09:00
co-authored by Claude Opus 5
parent a1033f6013
commit ddd276c15a
2 changed files with 19 additions and 20 deletions
+11 -10
View File
@@ -336,17 +336,18 @@ export function buildSkillToolFilter(input: ToolScopeInput): (toolName: string)
if (name === 'kakao_send_message' && !hasKakaoKeyword) return false;
// USER.md/SOUL.md 수동 메모리 3종. 2026-09-04 효율 감사로 게이팅.
//
// 이 세 개는 지금까지 **매 턴 무조건** 실려 357토큰을 냈다. 실측한 이유는 셋 다 호출이
// 사실상 0이어서인데(사용자 턴 1,011건에서 browse 0회 / read 2회 / write 1회), 파고 보니
// 더 근본적인 문제였다: **USER.md도 SOUL.md도 4명 전 사용자 누구에게도 없다.** 즉
// memory_browse와 memory_read는 파일이 없어 "USER.md not found. Create it first." 에러만
// 돌려줄 수 있는 상태로 매 턴 실려 있었다. 실제 장기기억은 일별 로그 + Chroma 벡터
// 추출(자동)이 담당한다([[project_vector_memory_chroma]]) — USER.md 경로는 그 시스템이
// 대체한 레거시다([[project_legacy_skill_system]]과 같은 유형).
// 근거는 순수하게 사용량이다: 실사용 1,011턴에서 browse 0회 / read 2회 / write 1회인데
// **매 턴 무조건** 실려 357토큰을 냈다. 게이트가 걸리면 0.3%의 턴에만 실린다.
//
// 제거가 아니라 게이팅인 이유: 사용자가 "기억해둬"라고 명시하는 턴에는 있어야 한다.
// memory_write는 파일이 없으면 새로 만들므로 그 경로는 지금도 유효하다.
// memory_stats는 벡터 스토어를 보므로 여기 해당하지 않는다(실제로 13회 호출됨).
// 도구 자체는 멀쩡하다. USER.md·SOUL.md는 `workspace/prompts/` 아래에 실제로 있고
// resolvePromptPath가 거기서 찾는다(papa의 USER.md는 3.2KB, 카테고리 5개). 감사 중에
// 워크스페이스 루트만 보고 "파일이 없다"고 잘못 판단했다가 정정한 자리다 — 셋 다
// 파일이 없으면 에러를 내므로, 없다는 판단이 맞았다면 통째로 죽은 도구였을 뻔했다.
//
// 제거가 아니라 게이팅인 이유: 사용자가 "기억해둬"라고 명시하는 턴에는 반드시 있어야 한다.
// 평상시 장기기억은 일별 로그 + Chroma 자동 추출이 담당하지만([[project_vector_memory_chroma]]),
// 그건 하루 뒤에 반영되는 배치라 "지금 이걸 기억해"의 대체재가 아니다.
// memory_stats는 벡터 스토어를 보므로 게이트 대상이 아니다(실제로 13회 호출됨).
if (manualMemoryToolNames.has(name) && !hasMemoryIntentKeyword) return false;
if (name === 'sqlite_query' && !hasSqliteKeyword) return false;
if (name === 'image_edit' && !hasImageEditKeyword) return false;
+8 -10
View File
@@ -40,9 +40,9 @@ describe('키워드 게이트 — 관련 없는 턴에서 도구가 따라붙지
test('핵심 도구는 항상 남는다', () => {
const f = filterFor('안녕');
// 2026-09-04: memory_read를 memory_stats로 바꿨다. USER.md/SOUL.md가 4명 전 사용자
// 누구에게도 없어서 memory_read는 "not found" 에러만 낼 수 있는 상태였고, 이제 기억 의도가
// 있는 턴에만 실린다. memory_stats는 벡터 스토어를 보므로 계속 무조건 남는다(실제 13회 호출).
// 2026-09-04: memory_read를 memory_stats로 바꿨다. memory_read는 이제 기억 의도가 있는
// 턴에만 실린다(사용량 기준 게이팅). memory_stats는 벡터 스토어를 보므로 계속 무조건 남는다
// — 실제로 13회 호출된 유일한 메모리 도구다.
for (const name of ['web_search', 'web_fetch', 'memory_stats', 'python_eval']) {
assert.equal(f(name), true, `${name} 이(가) 사라짐`);
}
@@ -404,14 +404,12 @@ describe('게이트 오탐 (2026-09-04 감사)', () => {
/**
* 수동 메모리 도구(USER.md/SOUL.md) — 2026-09-04 효율 감사.
*
* 이 셋은 매 턴 무조건 실려 357토큰을 냈다. 실사용 1,011턴에서 호출은 browse 0 / read 2 /
* write 1회. 파고 보니 더 근본적이었다: **USER.md도 SOUL.md도 4명 전 사용자 누구에게도 없다.**
* memory_browse와 memory_read는 파일이 없어 "USER.md not found. Create it first." 에러만
* 돌려줄 수 있는 상태로 매 턴 실려 있었다. 실제 장기기억은 일별 로그 + Chroma 벡터 추출이
* 담당한다 — USER.md 경로는 그 시스템이 대체한 레거시다.
* 근거는 순수하게 사용량이다: 실사용 1,011턴에서 browse 0 / read 2 / write 1회인데 매 턴
* 무조건 실려 357토큰을 냈다. 도구 자체는 멀쩡하다 — USER.md·SOUL.md는 workspace/prompts/
* 아래에 실제로 있고 resolvePromptPath가 거기서 찾는다.
*
* 제거가 아니라 게이팅인 이유: 사용자가 "기억해둬"라고 명시하는 턴에는 있어야 하고,
* memory_write는 파일이 없으면 새로 만들므로 그 경로는 지금도 유효하다.
* 제거가 아니라 게이팅인 이유: "기억해둬"라고 명시하는 턴에는 반드시 있어야 한다. 평상시
* 장기기억은 Chroma 자동 추출이 담당하지만 그건 하루 뒤 반영되는 배치라 대체재가 아니다.
*/
describe('수동 메모리 도구는 기억 의도가 있을 때만 (2026-09-04 감사)', () => {
const memTools = ['memory_browse', 'memory_write', 'memory_read'];