- Delete task.md / implementation_plan.md (deploy URL parameterization shipped in 6408f4a; checklists were stale) and session_isolation_discussion.md (superseded by implementation_plan.session_isolation.md; feature shipped and PASSed) - Remove the two inbound links to the deleted discussion doc - Add reviewer analysis reports and this cleanup plan under .agents/reports/
11 KiB
11 KiB
Implementation Plan — 세션 ID 중복 충돌 해소 / 역할별 세션 격리 (Rev.3)
- 작성자: Planner Agent
- 날짜: 2026-07-10 (Rev.2 → Rev.3 개정)
- 상태: Draft (Phase 0 검증 게이트 대기 — 구현 미착수)
- 관련 자료: Problem_Definition.md
- 확정된 방향 (Rev.3): all-L2 단일화 — 전 에이전트 isolation-UUID 격리 디렉터리 + 세션 row 영속화 + R1 claimed-set 불변식
0. Rev.2 → Rev.3 변경 이력 (Decision Log)
| # | 결정 | 사유 |
|---|---|---|
| D1 | L1(생성-시 대화 ID 인자 주입) 전략 폐기 | 관리 모델 통일 우선. claude --session-id는 실측 확정된 레버지만, agent별 L1/L2 분기 유지 비용보다 단일 격리 메커니즘의 일관성을 우선함 (트레이드오프 인지 후 사용자 확정) |
| D2 | 격리 식별자 = MAM 발급 isolation-UUID (CLI 대화 ID와 분리) | cline 등 비-UUID 자체 ID 포맷 문제 원천 소멸 — CLI가 자기 방식대로 대화 ID를 mint하되 자기만의 격리 디렉터리 안에서 하게 함 |
| D3 | 격리 정보를 세션 row(isolation 블록)로 영속화 |
resume/resolve/stop이 단일 디스패치로 재적용 → 주입/해석 불일치(RK2) 차단 |
| D4 | claude 격리 레버 = CLAUDE_CONFIG_DIR + auth 시딩 |
실측: ~/.claude/ 한 지붕 아래 .credentials.json+settings+plugins+projects/ 동거 확인. 대화만 옮기는 좁은 레버 부재 → 지붕 이동 + 시딩 계약 필수. ⚠️ 기존 문서의 CLAUDE_PROJECT_DIR은 MAM resolver 읽기 전용 변수(lib.sh:23,477)로 CLI 쓰기 위치를 바꾸지 못함 — Rev.2의 해당 서술 정정 |
| D5 | cline 격리 레버 = --data-dir + --config 분리 조합 |
실측: cline --data-dir <path>("Use isolated local state", default ~/.cline) + --config <path>(설정/auth, default ~/.cline/data/settings) 별도 플래그 확인 → 대화만 격리·auth 공유 가능, 시딩 불필요 예상 |
1. 배경 및 문제 정의
동일 CLI 계열(Claude/Cline)의 서로 다른 역할 에이전트가 같은 workspace에서 동시 구동될 때
동일한 대화 세션 ID를 공유하는 결함 (Problem_Definition.md).
1.1 근본 원인 (코드 근거) 및 all-L2가 끊는 방식
| # | 원인 | 근거 | all-L2 해소 기전 |
|---|---|---|---|
| C1 | spawn 시 세션 ID 미지정 → CLI "cwd 최근 대화 상속" | create_session.sh:125/:135 |
신규 격리 디렉터리엔 상속할 최근 대화가 없음 → 각자 fresh 시작 |
| C2 | 저장소가 workspace(cwd) 단위 키잉, role 차원 없음 | lib.sh:480, :615 |
격리 디렉터리가 UUID 네이밍 → cwd 파생 key 충돌 원천 소멸 |
| C3 | resolver Tier-2가 mtime 최신 파일 반환 → 동일 UUID 해석 | lib.sh:564 |
격리 디렉터리 안엔 대화가 하나뿐 → disk-scan 항상 유일 후보, mtime 경합 소멸 |
1.2 불변 전제 (변경 금지)
- cwd 공유: 모든 에이전트는
-c "$WORKSPACE"로 동일 workspace에서 기동 (협업 전제). 격리는 대화 상태 저장소의 위치만 env/플래그로 옮기며 cwd는 절대 건드리지 않음. - CLI(claude/cline/agy/hermes) 자체 미수정 — 인자/환경변수 인터페이스만 사용 (Non-Goal).
- 기존 단일-에이전트 워크플로우 회귀 0.
2. 설계 (all-L2 단일 격리 메커니즘)
2.1 격리 디렉터리
- 생성 시
uuidgen으로 isolation-UUID 발급. - 격리 루트:
<workspace>/.mam/agent_homes/<isolation-uuid>/.mam/하위 →.gitignore:11자동 커버,remove.sh/stop 청소 계약에 자연 포함.
2.2 세션 row 스키마 확장 (isolation 블록)
tmux_sessions:
- name: <session_name>
role: <role>
isolation:
uuid: <isolation-uuid>
root: .mam/agent_homes/<isolation-uuid>
lever: claude_config_dir | cline_data_dir | home | <agy/hermes 프로브 결과>
seeded: [".credentials.json", "settings.json", "plugins"] # 심링크 목록 (해당 시)
atomic_dump_yaml경유로 DB+YAML 동시 기록 (P1 상시 미러 수정본 전제).- resume/resolve/stop은 이 블록만 읽는 단일 디스패치 함수로 재적용 — agent별 레버 차이는 이 함수 내부에 캡슐화.
2.3 agent별 레버 매핑 — ✅ Phase 0 실측 확정 매트릭스 (2026-07-10)
| Agent | Spawn 레버 | 시딩 목록 (전부 심링크) | 격리 내 대화 저장 실경로 | 실증 |
|---|---|---|---|---|
| claude | CLAUDE_CONFIG_DIR=<root> env |
.credentials.json, settings.json, plugins/ |
<root>/projects/<key>/<uuid>.jsonl |
✅ 실호출 — jsonl 격리 생성, 로그인 유지, 실HOME 무변화(27→27) |
| cline | --data-dir <root> 플래그 |
settings/*(providers.json 등 5종), globalState.json |
<root>/sessions/<id>/<id>.json ⚠️ |
✅ 실호출 — 세션 격리 생성, 실HOME 무변화(13→13) |
| agy | HOME=<root> env |
~/.gemini/{oauth_creds.json, google_accounts.json, installation_id, settings.json, state.json} + antigravity-cli/{antigravity-oauth-token, installation_id, settings.json} |
<root>/.gemini/antigravity-cli/conversations/<uuid>.db |
✅ auth 검증(agy models — 시딩 전 실패/후 성공), fresh conversations/ 확인 |
| hermes | HOME=<root> env |
~/.hermes/{auth.json, config.yaml, .env} |
<root>/.hermes/state.db (sessions 테이블) |
✅ 읽기 격리 검증 — 격리 HOME "No sessions found" + fresh state.db, 실HOME 세션 비노출 |
Phase 0 실측 정정·주의사항:
- ⚠️ cline
--config가정 반증:--config ~/.cline/data/settings공유 지정만으로는 auth가 공유되지 않음(Unauthorized) — cline이 data-dir 안에 자체 settings를 생성. → cline도 시딩 필수 (Rev.3 본문 "시딩 불필요 예상" 정정). - ⚠️ cline 격리 레이아웃 상이: 격리 시
<root>/sessions/(실HOME은~/.cline/data/sessions/) — resolver 재적용(T5)에서 lever별 경로 템플릿 분기 필요. - hermes
config.yaml에 실HOME 절대경로(런타임hermes-agent) 내장 — 런타임은 읽기 공유라 무해하나, 격리 범위가 state/세션에 한정됨을 기록. - agy는 첫 실행 시 격리 HOME에 디렉터리 구조를 자동 부트스트랩(fresh
conversations/포함).
- resolver 연동: 디스패치 함수가 row의
isolation을 읽어HOME_DIR/CLAUDE_PROJECT_DIR(MAM 읽기 변수,lib.sh:22-23)를 격리 루트 기준으로 export한 뒤find_workspace_uuid/resume 호출.
2.4 공통 불변식 (전략 무관 유지)
- R1. claimed-set 필터: Tier-2 반환 전, 같은 workspace의 다른 running row 소유
*_own집합 제외 (lib.sh:540-575). 격리가 부분 실패해도 이중 배정 구조적 차단. - R2. 생성-시 유일성 assert: 새
*_own이 기존 running*_own과 충돌 시SystemExit(lib.sh:377근처).
3. 단계별 태스크
Phase 0 — 검증 게이트 (구현 전 필수·차단, Rev.3 재조준: 구 G1 삭제)
- G2-claude:
CLAUDE_CONFIG_DIR=<격리경로>기동 시 (a) 대화 jsonl이<격리경로>/projects/<key>/에 생성되는가 (b).credentials.json심링크만으로 로그인 유지되는가 (c) settings/plugins 심링크로 행동 드리프트 없는가. - G2-cline:
--data-dir <격리경로> --config ~/.cline/data/settings기동 시 (a) 세션이<격리경로>/data/sessions/(또는 상응 경로)에 격리 생성되는가 (b) auth/providers가 공유 config에서 정상 동작하는가. - G2-agy:
--new-projectper-role 부여 시 대화 격리 여부, 또는 데이터 경로 env 존재 여부. 부재 시HOME오버라이드+auth 시딩 유효성. - G2-hermes: home 이동 env/플래그 실측. 부재 시
HOME오버라이드+auth 시딩 유효성. - DoD:
{agent × (레버, 시딩 목록, 대화 저장 실경로)}매트릭스 확정 → §2.3 갱신.
Phase 1 — 공통 불변식 (Phase 0과 병렬 착수 가능)
- T1. claimed-set 필터 / T2. 생성-시 유일성 assert (§2.4).
- DoD: 동일 ID 강제 주입 2개 create → 두 번째 거부 (단위 재현).
Phase 2 — all-L2 격리 구현 (구 Phase 2/3 통합)
- T3. 격리 디렉터리 프로비저닝: create 시 isolation-UUID 발급 →
.mam/agent_homes/<uuid>/생성 → agent별 시딩(§2.3, 심링크) 수행. - T4. spawn 주입: 디스패치 함수가 agent별 레버(env/플래그)로 격리 루트 주입.
- T5. 스키마 영속화 + 재적용:
isolation블록 atomic_dump 기록, resume/resolve가 동일 디스패치로 재소싱 (저장+재적용은 원자적 세트 — RK2). - T6. stop 청소 계약:
stop_session.sh가isolation.root를 퍼지(rm -rf), 심링크 대상 원본은 보존 확인. - DoD: 동일 workspace, 같은 CLI 2개(다른 role) 동시 생성 → 대화 파일 물리 분리,
*_own상이, 교차 write 0.
Phase 3 — 통합 및 회귀 검증
- V1: planner/reviewer-a(claude) + developer/reviewer-b(cline) 4개 동시 기동 → 4개 대화 ID 전부 유일.
- V2: 동시 write 락 충돌·컨텍스트 오염 재현 불가.
- V3: 각 role resume이 자기 대화만 복원 (isolation 재적용 경유).
- V4: 단일-에이전트 기존 워크플로우 회귀 0 (격리 미사용 경로 불변).
- V5: stop 후 격리 저장소 잔존 0 + 실HOME auth/설정 원본 무손상.
4. 리스크 및 검수 포인트 (Rev.3 갱신)
| ID | 리스크 | 완화 |
|---|---|---|
| RK1 | 격리 실패/부분 적용 시 이중 배정 | R1 claimed-set 필터가 최후 방어선 (무조건 유지) |
| RK2 | spawn 주입 경로와 resolve/resume 스캔 경로 불일치 → 전역 회귀 | T5 "저장+재적용" 원자적 세트, 단일 디스패치 함수 강제 |
| RK3 | 시딩 드리프트: CLI 업데이트로 신규 파일 등장 시 심링크 목록 누락 → 행동 이상 | seeded 목록을 row에 기록, Phase 0 매트릭스에 파일 목록 명세, 온보딩 문서화 |
| RK4 | 토큰 갱신 발산 (복사 시딩 시) | 심링크 강제 — 갱신이 원본 단일 파일에 수렴 (현행 다중 인스턴스 동작과 동일) |
| RK5 | 비정상 종료 시 격리 디렉터리 누수 | .mam/ 하위 배치로 remove.sh 전체 청소 커버 + T6 stop 퍼지 + (선택) create 시 고아 agent_homes/* GC |
| RK6 | 단일-에이전트 기존 사용자 회귀 | 격리 발동을 명시 플래그/다중성 조건으로 제어 (--isolate 등, Phase 0 후 확정), V4 회귀 게이트 |
5. 승인 및 다음 단계
- 본 계획(Rev.3)은 Phase 0 게이트 통과 전 코드 구현 착수 금지를 대전제로 유지한다.
- 다음 액션: Phase 0 (G2-claude / G2-cline / G2-agy / G2-hermes) 프로브 실행 — 스크래치 워크스페이스에서 실측 후 §2.3 매트릭스 확정.