Executive Summary
파일럿 실측 결과
| 항목 | 실측값 | 판정 |
|---|---|---|
| 스테이징 | 502파일, 원본 2,796,241바이트. 이메일 41건·전화 10건을 치환했고 치환 후 PII/secret/SSOT 경로 잔존 0건, manifest 해시 불일치 0건. | 통과 |
| 색인 | full, persistence=false, 7.536초, peak working set 259MB, TCP 연결 표본 0건, cache 16,548,429바이트. | 안전 경계 통과 |
| coverage | 502파일 모두 처리됐으나 203파일(40.4%)이 partial parse. 2,982 nodes, 9,705 edges. | 품질 위험 |
| Q1–Q9 rg | 9 calls, 합산 명령시간 242.927ms, 원시 출력 40,270바이트. | 기준선 |
| Q1–Q9 CBM | 초기 9 calls + 정밀 추적 9 calls + 누락 검증 2 calls = 20 calls. 합산 질의시간 490.841ms, 응답 184,854바이트. | 호출 2.22×, 시간 2.02×, 출력 4.59× |
| 심각한 누락 | rg는 admin/src/components/CoinEditor.tsx:22의 supabase.rpc('admin_adjust_coins')를 확인. CBM은 정확한 SQL qualified name, cross_service, depth 8에서도 callers 0. | 중단 기준 발동 |
| Q10 detect_changes | 심각한 소비자 누락 1건 발견 시 즉시 중단한다는 사전 규칙에 따라 통제 diff를 만들지 않았다. | 의도적 미실행 |
측정 한계: 시간은 동일 로컬 PC의 프로세스/MCP 응답시간 합계이며 사람의 원문 검토시간은 별도 stopwatch로 확보하지 못했다. 토큰도 모델 tokenizer로 직접 계측하지 못해 원시 UTF-8 응답 바이트를 재현 가능한 대용 지표로 썼다. 이 대용 지표에서도 CBM이 절감되지 않았으므로 “토큰 절감” 합격을 주장할 근거가 없다.
질문별 관찰
- 유용: Q2에서
SignIncaller, Q3에서 phone/contact 화면 후보, Q7에서process_unlock_refunds의 5개 migration 정의, Q8에서 money-flows 테스트 내부 호출 31개를 구조화해 보여줬다. - 취약: Q1의 hook→Edge Function callee, Q4의 admin→SQL RPC, Q9의 mobile→photos-worker 경로가 end-to-end edge로 이어지지 않았다.
- 오탐 검토: Q4 초기 검색은 356건, Q9는 150건으로 각각 100건에서 잘렸다. 좁히기 위한 후속 호출이 필요해 rg보다 도구 호출이 줄지 않았다.
무엇이 빨라지고, 무엇은 그대로인가
| 구분 | 기대 변화 | 판정 |
|---|---|---|
| 함수·호출자·HTTP 경로·변경 영향 후보 탐색 | 일부 TS caller와 SQL 재정의 후보는 유용했으나 Supabase RPC/Edge/worker 경계를 놓쳤다. | 핵심 누락 |
| 새 세션의 구조 파악 | 심볼 후보를 빠르게 모았지만 초기 응답이 rg보다 4배 이상 커 후속 좁히기가 필요했다. | 제한적 가치 |
| 웹·앱 응답 속도와 배포 안정성 | 런타임 경로에 들어가지 않으므로 직접 개선 없음 | 변화 없음 |
| 테스트 통과, 실제 VM·Cloudflare·Supabase 상태 | 그래프 밖의 사실이며 별도 테스트·운영 확인 필요 | 보장 불가 |
| SQL 최신 정의, 정책·캐논·에셋 provenance | 사람과 기존 SSOT가 최종 판단 | 대체 금지 |
안정성 영향
직접: 정상적인 격리 파일럿은 서비스 실행·배포 경로를 건드리지 않으므로 중립이다. 간접 긍정: 누락된 소비자 후보를 더 일찍 찾으면 리뷰 품질이 좋아질 수 있다. 간접 부정: decorator·DI·문자열 이벤트·동적 호출을 잘못 연결하거나 놓쳤는데 그래프를 완전하다고 믿으면 변경 위험이 커진다. 따라서 coverage 확인과 원문·rg 교차검증을 유지한다.
토큰 절감 원리와 비보장 이유
그래프가 심볼·관계를 미리 계산해 작은 구조화 응답으로 돌려주면, 에이전트가 넓은 grep 결과와 여러 원문 파일을 반복 입력하는 양을 줄일 수 있다. 그러나 누락·오탐 검증, coverage가 낮은 파일의 재탐색, 도구 호출 포장 비용이 추가되고 작은 저장소에서는 기존 rg가 이미 싸다. 제작자의 “10× fewer tokens” 등은 외부 벤치마크 주장일 뿐 이 환경의 보장이 아니다.
설치 전에 확인한 변경 범위
소스 확인 현재 PowerShell installer는 GitHub release와 checksum을 내려받아 검증한 뒤 native install -y --force를 호출한다. native installer는 감지된 여러 에이전트의 설정·hook·skill·agent profile과 사용자 PATH를 바꿀 수 있으므로 이번 파일럿에서는 사용하지 않는다.
| 대상 | 자동 installer 사용 시 | 제안 수동 파일럿 |
|---|---|---|
| 실행 파일 | %LOCALAPPDATA%\Programs\codebase-memory-mcp\ 아래 binary·installer·고지 파일, 사용자 PATH | 별도 %LOCALAPPDATA%\codebase-memory-mcp-pilot\bin\만 사용, PATH 미변경 |
| Codex 전역 설정 | ~/.codex/config.toml, AGENTS.md, hooks, skills, agent profiles | 별도 %LOCALAPPDATA%\codebase-memory-mcp-pilot\codex-home\config.toml만 사용. 기본 config SHA-256 A3E129…C4 불변, 종료 시 MCP 항목 제거 |
| 다른 에이전트 | 설치 감지 결과에 따라 Claude 등 다수 설정 변경 가능 | 변경 없음 |
| 인덱스·설정 DB | 기본 ~/.cache/codebase-memory-mcp/에 프로젝트 DB·_config.db·logs·allowed roots | %LOCALAPPDATA%\codebase-memory-mcp-pilot\cache\로 격리 |
| daemon runtime | 기본 Windows rendezvous/lock 경로 사용 | %LOCALAPPDATA%\codebase-memory-mcp-pilot\runtime\로 격리 |
| 대상 프로젝트 | persistence=true면 .codebase-memory/graph.db.zst와 .gitattributes 생성 | persistence=false; 프로젝트 파일 변경 0건 |
Exhibit 1. 조건부 승인 보완 조사 결과
| 요구사항 | 검증 결과 | 판정 |
|---|---|---|
| 비용·라이선스 | GitHub API와 release LICENSE에서 MIT 확인. bundled Nomic embedding을 로컬 실행하며 별도 API key·hosted service가 필요 없다고 명시되어 있다. 증분 비용은 로컬 CPU·디스크와 기존 Codex 사용량뿐이다. | 충족 |
| staging 강제 | 허용 디렉터리·확장자·명시 파일만 복사하는 Preview-default PowerShell을 실행했다. 기존 staging이 있으면 중단하고 삭제·덮어쓰지 않는다. | 실행 통과 |
| PII·secret 검사 | 후보 502파일·2,796,241바이트에서 이메일 41건·전화 10건, 합계 51건/26파일을 치환했다. 치환 후 동일 PII와 secret 패턴은 0건이었다. 자유서술 이름 등 모든 PII가 없다는 보장은 아니다. | 패턴 기준 통과 |
| binary provenance | immutable release v0.10.5(2026-08-15)의 Windows amd64 archive를 임시 경로에 다운로드해 검증했다. SHA-256 1e5ba3…20273이 release checksum, GitHub asset digest, attestation subject와 모두 일치했다. attestation source 7719563은 tag와 로컬 감사 commit에 정확히 일치했다. | 검증 완료 |
| Codex 설정 격리 | 별도 CODEX_HOME에만 analysis 프로필 MCP를 수동 등록했다. 기본 config 해시는 전후 동일했고 중단 후 격리 MCP 항목을 제거했다. | 격리·롤백 완료 |
검사 방법: 6개 허용 소스 디렉터리의 코드 확장자 파일에서 inline JPEG 파일 1개를 제외했다. PII는 전화·이메일·주민번호, secret은 private key·JWT·AWS·Google·GitHub·Stripe·secret assignment 패턴을 검사했으며 검출값은 출력하지 않았다.
release 검증 결과
- archive SHA-256:
1e5ba3cca69194b9229f89a0cafe4a6538ba9e0040d892d57bf472e992420273. - release
checksums.txt및 GitHub API asset digest와 일치. - GitHub attestation subject digest와 일치.
- signer는
.github/workflows/_build.yml@refs/heads/main, GitHub-hosted runner이며 self-hosted runner 거부 조건으로 검증. - attestation source digest,
v0.10.5tag, 로컬 감사 commit이 모두77195634e13fd3bcd0d24543de5f876b4679f1cf로 일치. checksums.txt자체도release.ymlsigner와 self-hosted runner 거부 조건으로 별도 attestation 검증을 통과.
Sigstore release bundle의 .bundle 확장자는 GitHub CLI의 offline bundle 입력 형식과 맞지 않았지만, GitHub API attestation을 strict signer workflow·self-hosted runner 거부 조건으로 다시 검증해 provenance를 확인했다. archive는 그 후 격리 실행했다.
v0.10.5의 application.c에는 production update provider가 없고 curl 기반 GitHub check가 제거됐다고 명시돼 있다. 같은 tag의 SECURITY.md는 background update check를 기술해 뒤처져 있다. 실제 파일럿의 TCP 연결 표본은 0건이었지만 장시간 무통신 보장으로 확대 해석하지 않는다.staging 생성 스크립트 사전 공개본
기본값은 Preview다. 실행 중 Windows PowerShell의 Path.GetRelativePath·파일 Parent 호환성 문제가 복사 전에 발견되어, 경계 검사를 유지하는 호환 함수로 수정한 뒤 Preview와 Apply를 통과했다. 아래는 승인 당시 공개본이며 실제 실행본은 격리 pilot의 scripts 아래 보존했다.
param(
[ValidateSet('Preview','Apply')] [string]$Mode='Preview',
[string]$SourceRoot='D:\work\sales\apps\gongssum',
[string]$StageRoot="$env:LOCALAPPDATA\codebase-memory-mcp-pilot\staging\gongssum"
)
Set-StrictMode -Version Latest; $ErrorActionPreference='Stop'
$source=(Resolve-Path -LiteralPath $SourceRoot).Path.TrimEnd('\')
$pilotBase=[IO.Path]::GetFullPath("$env:LOCALAPPDATA\codebase-memory-mcp-pilot\staging")
$stage=[IO.Path]::GetFullPath($StageRoot)
if(-not $stage.StartsWith($pilotBase+'\',[StringComparison]::OrdinalIgnoreCase)){throw 'stage outside pilot base'}
if(Test-Path -LiteralPath $stage){throw 'stage exists; overwrite/delete forbidden'}
$dirs=@('mobile\src','backend\supabase\functions','backend\migrations','backend\tests','admin\src','photos-worker\src')
$fixed=@('mobile\package.json','mobile\tsconfig.json','mobile\app.json','backend\package.json',
'admin\package.json','admin\tsconfig.json','photos-worker\wrangler.jsonc')
$ext=@('.ts','.tsx','.js','.jsx','.mjs','.cjs','.sql','.json','.toml','.yaml','.yml')
$files=foreach($d in $dirs){Get-ChildItem (Join-Path $source $d) -Recurse -File |
Where-Object{$_.Extension -in $ext -and -not($_.Attributes -band [IO.FileAttributes]::ReparsePoint)}}
$files+=foreach($f in $fixed){Get-Item (Join-Path $source $f)}
$files=$files|Sort-Object FullName -Unique|Where-Object{
[IO.Path]::GetRelativePath($source,$_.FullName)-ne'mobile\src\lib\splash-data.ts'}
$secret=[ordered]@{private_key='-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----';
jwt='eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}';
aws='(?-i)AKIA[0-9A-Z]{16}';google='AIza[0-9A-Za-z_-]{35}';
github='(?i)(ghp_[A-Za-z0-9]{30,}|github_pat_[A-Za-z0-9_]{30,})';
stripe='(?i)sk_(live|test)_[A-Za-z0-9]{16,}'}
$pii=[ordered]@{email='(?i)[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,}';
phone='(?<!\d)01[016789][\s\-\.]?\d{3,4}[\s\-\.]?\d{4}(?!\d)';
rrn='(?<!\d)\d{6}[\s\-]?[1-4]\d{6}(?!\d)'}
$plan=foreach($file in $files){
$rel=[IO.Path]::GetRelativePath($source,$file.FullName);$text=[IO.File]::ReadAllText($file.FullName)
foreach($r in $secret.GetEnumerator()){if([regex]::IsMatch($text,$r.Value)){throw "secret $($r.Key) in $rel"}}
$n=0;foreach($r in $pii.GetEnumerator()){$n+=[regex]::Matches($text,$r.Value).Count
$text=[regex]::Replace($text,$r.Value,"<redacted-$($r.Key)>")}
[pscustomobject]@{Relative=$rel;Text=$text;Redactions=$n;
SourceSHA256=(Get-FileHash $file.FullName -Algorithm SHA256).Hash}}
$plan|Select-Object Relative,Redactions,SourceSHA256
if($Mode-eq'Preview'){return}
New-Item -ItemType Directory -Path $stage|Out-Null
$manifest=foreach($item in $plan){$dest=Join-Path $stage $item.Relative
New-Item -ItemType Directory -Force -Path (Split-Path $dest)|Out-Null
[IO.File]::WriteAllText($dest,$item.Text,[Text.UTF8Encoding]::new($false))
[pscustomobject]@{Path=$item.Relative;Redactions=$item.Redactions;SourceSHA256=$item.SourceSHA256;
StagedSHA256=(Get-FileHash $dest -Algorithm SHA256).Hash}}
$manifest|ConvertTo-Json -Depth 3|Set-Content -Encoding utf8 (Join-Path $pilotBase 'gongssum-manifest.json')
실행한 gongssum 수동 파일럿 범위
CODEX_HOME, cache, runtime을 사용하고 auto_index=false, auto_watch=false, UI off를 적용했다.full, persistence=false로 1회 색인했다. MCP에는 실제 지원값인 --tool-profile=analysis를 사용해 11개 조회 도구만 노출했다.detect_changes를 만들지 않았다.고정 질문 10개
mobile/src/api/identity.ts에서verify-identityEdge Function까지의 호출 경로identity-signup호출자와 응답 소비자- 본인인증 응답 필드 변경이 mobile 화면·상태에 미치는 영향
admin_adjust_coins의 admin 호출자→SQL 함수 경로- 코인 조정 이후 모바일 알림 소비자 후보
- 버디 차감 SQL 함수의 최신 재정의 후보와 호출자
- 무응답 환불 48시간·72시간 migration 간 재정의 관계
- money-flows test가 실제로 덮는 함수·누락 범위
- 사진 업로드에서 photos-worker·SQL·채팅방·알림으로 이어지는 후보
- 통제된 identity 또는 coin diff의
detect_changes결과와 reviewer checklist 차이
합격: 심각한 소비자 누락 0건, 평균 조사 시간 30% 이상 감소, 토큰·도구 호출 유의미한 감소, 오탐 검토 시간이 절감 시간보다 작음, 프로젝트·서비스·배포 변경 0건. 하나라도 핵심 조건을 어기면 제한 채택 또는 폐기다.
서비스가 깨질 수 있는 경로와 rollback
- Codex 설정 오류: MCP 시작 실패나 세션 지연은 가능하지만 서비스에는 직접 영향이 없다.
- 자원 경합: 색인 CPU·RAM·디스크가 같은 PC의 개발 서버를 느리게 할 수 있어 서비스/빌드 미가동 시간에 1회 실행한다.
- 민감정보 색인: 잘못 넓은 root가 가장 큰 위험이다.
CBM_ALLOWED_ROOT를 staging에만 고정하고 reports/assets·개인정보·logs·tmp·secrets를 복사하지 않으며 사전 secret scan을 통과해야 한다. - SQL 오판: migration의 여러
create or replace를 그래프가 최신 실제 DB 정의로 보장하지 않는다. migration 순서와 실제 DB 상태는 사람이 확인한다. - 저장소 쓰기: persistence를 켜거나 installer를 쓰면 의도치 않은 파일이 생길 수 있다. 둘 다 금지한다.
- 오판: 잘못된 edge를 사실로 취급하면 리뷰 누락이 생긴다. Manager·Memory·wiki/docs/decisions·RLS·테스트와 원문
rg를 대체하지 않는다.
Rollback: Codex를 닫고 MCP 블록 하나를 제거/비활성화한 뒤 격리된 bin·cache·runtime만 삭제한다. 프로젝트에는 되돌릴 변경이 없어야 하며, 전후 status와 파일 목록으로 이를 확인한다.
종료 상태와 rollback
codebase-memory-pilot MCP 항목을 제거했고 MCP 목록은 비었다. CBM 프로세스 0개, 기본 Codex config SHA-256 불변, gongssum 원본 작업 트리 clean을 확인했다.2026-08-16 D:\work\sales\apps\vendor\codebase-memory-mcp source clone을 삭제했다. 같은 날 %LOCALAPPDATA%\codebase-memory-mcp-pilot\의 다운로드·바이너리·staging·cache·runtime·결과 571개 파일(355,838,828바이트)도 삭제해 로컬 재현 증거는 남아 있지 않다. vendor/catalog.yaml의 중앙 거부 목록과 브로커 hard-deny가 재추천·재발견·재clone·설치·등록·활성화를 차단하며, 상세 제거 사유와 재검토 조건은 vendor/REJECTED-VENDORS.md에 보존한다. 재현이 필요하면 사용자 명시 승인 아래 공식 릴리스부터 새 격리 평가로 시작해야 한다.
근거와 한계
- 감사한 소스 커밋 7719563 — 기준일 로컬 clone과 일치.
- PowerShell installer 및 native installer 소스 — download·checksum·설정 변경 범위.
- Configuration 및 MCP tool registry — cache·root 제한·15개 도구·persistence 기본값.
- 제작자 README — 지원 언어와 benchmark 주장은 로컬 실측 전 미검증.
- SECURITY — runtime update 설명의 문서 불일치.
- OpenAI Codex MCP 문서 —
~/.codex/config.toml, stdio server, env와 tool allowlist. - OpenAI Codex 환경변수 및 설정 참조 —
CODEX_HOME, profile 파일과--profile. - v0.10.5 release — 검증한 immutable release와 checksum·bundle·SBOM·attestation 자산.
범위: 2026-08-15 현재 source·release provenance 감사와 gongssum 선별 snapshot의 단일 로컬 파일럿. Q1–Q9까지 수행 후 심각한 누락 기준으로 중단했으며 Q10은 미실행이다. 실제 서비스·DB·Cloudflare·Supabase 배포 상태는 조사하지 않았다. 제품 코드·배포 설정·프로젝트 SSOT는 변경하지 않았고 보고서만 갱신했다.