# πŸ“‘ Issue #5 Phase 2b β€” μžλ™μ™„λ£Œ 운영 λ…ΈνŠΈ (Flag-Gated / Opt-In) - **λ¬Έμ„œ 버전**: Rev.1 - **μƒνƒœ**: κ΅¬ν˜„ μ™„λ£Œ, **κΈ°λ³Έ λΉ„ν™œμ„±(`MAM_AUTO_COMPLETE=0`)** --- ## 1. ν•œ λ¬Έμž₯ μš”μ•½ **λλ‚¬λ‹€λŠ” 사싀을 μ•„λŠ” μͺ½(μ—μ΄μ „νŠΈ)이 확정을 μ„ μ–Έν•˜κ³ , μ½λŠ” μͺ½μ€ κ·Έ 선언을 λ―Ώμ§€ μ•Šκ³  ν•΄μ‹œλ₯Ό λ‹€μ‹œ κ³„μ‚°ν•œλ‹€.** μ›Œμ²˜κ°€ 슀슀둜 ν•΄μ‹œλ₯Ό 계산해 λ§€λ‹ˆνŽ˜μŠ€νŠΈλ₯Ό λ§Œλ“€λ©΄ 그것은 "μ›Œμ²˜κ°€ μ•ˆμ •λœ νŒŒμΌμ„ λ΄€λ‹€"λŠ” 자기 증λͺ…일 뿐이닀. 이 이슈의 μ•žμ„  λΌμš΄λ“œμ—μ„œ 리뷰어가 κΈ°κ°ν•œ 증거 ν˜•νƒœμ΄λ©°, 같은 μ‹€μˆ˜λ₯Ό λ°˜λ³΅ν•˜μ§€ μ•ŠκΈ° μœ„ν•œ 섀계 결정이닀. ## 2. κ·Έλž˜μ„œ 미지원 μ—μ΄μ „νŠΈλŠ” μžλ™μœΌλ‘œ μ•ˆμ „ν•˜λ‹€ 확정을 μ„ μ–Έν•˜μ§€ μ•Šμ€ μ—μ΄μ „νŠΈλŠ” λ§€λ‹ˆνŽ˜μŠ€νŠΈλ₯Ό 남기지 μ•ŠλŠ”λ‹€. λ§€λ‹ˆνŽ˜μŠ€νŠΈκ°€ μ—†μœΌλ©΄ 정책이 이미 `hold`ν•œλ‹€(Phase 2aμ—μ„œ κ΅¬ν˜„Β·ν…ŒμŠ€νŠΈ μ™„λ£Œ). **"미지원 경둜 100% 보쑴"은 μƒˆ λΆ„κΈ°κ°€ μ•„λ‹ˆλΌ κΈ°μ‘΄ λ™μž‘μ˜ 귀결이닀.** ## 3. 3쀑 게이트 (μ „λΆ€ 참일 λ•Œλ§Œ 컀밋) | 게이트 | κΈ°λ³Έκ°’ | κ·Όκ±° | |---|---|---| | `MAM_AUTO_COMPLETE=1` | **`0` (OFF)** | μ „μ—­ 킬 μŠ€μœ„μΉ˜ | | λ°±μ—”λ“œ ν—ˆμš©λͺ©λ‘ | `claude,grok,codex` | μ •μ§€ μƒνƒœ(`idle`/`done`) **κ΄€μΈ‘ 증거가 μžˆλŠ” λ°±μ—”λ“œλ§Œ**. `agy`λŠ” `working`만 κ΄€μΈ‘, `hermes`Β·`opencode`λŠ” κ΄€μΈ‘ 0건 | | μž‘λ³„ opt-in | λ ˆμ½”λ“œ `auto_complete: true` | 작 λ‹¨μœ„ λ™μ˜ | `MAM_AUTO_COMPLETE_BACKENDS`둜 λͺ©λ‘μ„ **쒁힐 수만** μžˆλ‹€. κ΄€μΈ‘λœ 적 μ—†λŠ” 이름은 λ¬΄μ‹œλœλ‹€ β€” λ„“νžˆλ €λ©΄ 섀정이 μ•„λ‹ˆλΌ 증거가 ν•„μš”ν•˜λ‹€. ## 4. ν™•μ • 계약 (P2B-01) ``` μ—μ΄μ „νŠΈ: publish_event.py --job --event completed \ --finalize-report [--side-effect =] ... β‘  .tmp β†’ μ›μžμ  rename (반쯀 쓰인 리포트λ₯Ό μ΅œμ’…λ³ΈμœΌλ‘œ λ³Ό 수 μ—†κ²Œ) β‘‘ SHA-256 계산 β‘’ report-manifest.json μ›μžμ  기둝 (job_id, attempt_id, sha256, side_effects, declared_by) ``` - **리포트λ₯Ό λ‹€μ‹œ μ“°λ©΄ 선언은 μ¦‰μ‹œ 무효**κ°€ λœλ‹€. ν•΄μ‹œλ₯Ό λ‹€μ‹œ 계산해 λŒ€μ‘°ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€. μƒˆ λ³Έλ¬Έμ—λŠ” μƒˆ 확정이 ν•„μš”ν•˜λ‹€. - **μ„ μ–Έν•œ λΆ€μˆ˜νš¨κ³ΌλŠ” μ „λΆ€ 증거가 μžˆμ–΄μ•Ό ν•œλ‹€.** μΌλΆ€λ§Œ μžˆλŠ” 것은 μ—†λŠ” κ²ƒμœΌλ‘œ μ·¨κΈ‰ν•œλ‹€ β€” μž‘μ—…μ΄ 끝났닀고 μ•Œ 수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€. - 확정은 λ°œν–‰ **μ•žμ—** μΌμ–΄λ‚œλ‹€. 리포트λ₯Ό 아직 μ“°λŠ” 쀑인 `completed` μ΄λ²€νŠΈλŠ” 계약이 κΈˆμ§€ν•˜λŠ” λΆ€λΆ„ 리포트 채택을 λΆ€λ₯Έλ‹€. ## 5. μ§€μ—° μ•Œλ¦Ό (P2B-02) ``` 락 μ•ˆ: μƒνƒœ 컀밋 + pending_notification 기둝 ← ν•˜λ‚˜μ˜ μ›μžμ  μ“°κΈ° 락 λ°–: λ°œν–‰ β†’ 성곡 μ‹œ notification_settled μ „μ΄λ‘œ 정리 기동 μ‹œ: pending_notification이 남은 λ ˆμ½”λ“œλ₯Ό μž¬λ°œν–‰ (λ©±λ“±: κ΅¬λ…μžκ°€ seq둜 쀑볡 제거) ``` - **독립 Outbox μ €μž₯μ†Œλ₯Ό λ§Œλ“€μ§€ μ•ŠλŠ”λ‹€**(`state-transitions.md` Β§5 λͺ…μ‹œ). 이미 μ“°λŠ” λ ˆμ½”λ“œμ— ν•„λ“œ ν•˜λ‚˜λ₯Ό 더 μ“΄λ‹€. - **λ°œν–‰ μ‹€νŒ¨λŠ” μ˜λ„μ μœΌλ‘œ intentλ₯Ό 남긴닀.** 보내지 μ•Šμ€ μ•Œλ¦Όμ΄ 보낸 κ²ƒμ²˜λŸΌ λ³΄μ΄λŠ” 편이, μž¬μ‹œλ„λ˜λŠ” νŽΈλ³΄λ‹€ λ‚˜μ˜λ‹€. - `notification_settled`λŠ” **μƒνƒœλ₯Ό λ°”κΎΈμ§€ μ•ŠλŠ” bookkeeping μš”μ²­**이라 terminal μƒνƒœμ—μ„œλ„ ν—ˆμš©λœλ‹€. μ•Œλ¦Όμ€ terminal에 *κ΄€ν•œ* κ²ƒμ΄λ―€λ‘œ, terminal이 κ±°λΆ€ν•˜λŠ” μš”μ²­μœΌλ‘œλŠ” μ˜μ›νžˆ 정리할 수 μ—†λ‹€. ## 6. λ¬΄νŒμ • fail-closed λ§€λ‹ˆνŽ˜μŠ€νŠΈλ₯Ό 읽지 λͺ»ν•¨, 정책이 μ˜ˆμ™Έλ₯Ό 던짐, μ•Œ 수 μ—†λŠ” κ²°μ • β€” μ „λΆ€ `hold`λ‹€. **"νŒμ •ν•˜μ§€ λͺ»ν•¨"은 κ²°μ½” "μ™„λ£Œ"κ°€ μ•„λ‹ˆλ‹€.** 늦게 λ„μ°©ν•œ λͺ…μ‹œ terminal이 있으면 전이 경계가 μΆ”λ‘  μ™„λ£Œλ₯Ό κ±°λΆ€ν•˜λ©°, 그것은 경계가 제 일을 ν•œ 것이지 게이트의 였λ₯˜κ°€ μ•„λ‹ˆλ‹€. ## 7. 감사 ν‘œμ‹ μžλ™μ™„λ£Œλ‘œ λ“€μ–΄κ°„ terminalμ—λŠ” `completed_by: "auto_complete"`와 νŒμ • μ‚¬μœ κ°€ λ‚¨λŠ”λ‹€. κ΅¬λ…μžμ™€ λž˜νΌλŠ” μžλ™/λͺ…μ‹œ μ™„λ£Œλ₯Ό κ΅¬λ³„ν•˜μ§€ λͺ»ν•˜λ―€λ‘œ(`job_subscriber._check_disk_fallback`은 λ ˆμ§€μŠ€νŠΈλ¦¬ status만 λ³Έλ‹€), **사후에 ꡬ별할 수 μžˆλŠ” μœ μΌν•œ μˆ˜λ‹¨**이닀. ## 8. λ‘€λ°± 1. `MAM_AUTO_COMPLETE=0` β€” μ‹ κ·œ μžλ™μ™„λ£Œλ§Œ 쀑단. **이미 ν™•μ •λœ terminal λ ˆμ½”λ“œλŠ” 보쑴**ν•œλ‹€. 2. `MAM_ENGINE_CAS=0` β€” Phase 2a κ²½λ‘œκΉŒμ§€ λ˜λŒλ¦°λ‹€(μžλ™μ™„λ£ŒλŠ” κ·Έ μœ„μ— μžˆμœΌλ―€λ‘œ ν•¨κ»˜ 무λ ₯ν™”). 3. `.mam/shadow/`λŠ” λ ˆμ§€μŠ€νŠΈλ¦¬μ™€ λΆ„λ¦¬λ˜μ–΄ μžˆμ–΄ μ‚­μ œν•΄λ„ job μƒνƒœμ— 영ν–₯이 μ—†λ‹€. ## 9. κ³„νš λŒ€λΉ„ μ΄νƒˆ 1건 (λ ˆμ½”λ“œ μŠ€ν‚€λ§ˆ λ―Έλ³€κ²½) κ³„νšμ„œ Β§D2λŠ” `attempt_id`λ₯Ό job λ ˆμ½”λ“œμ˜ 1κΈ‰ ν•„λ“œλ‘œ μŠΉκ²©ν•  것을 κΆŒκ³ ν•˜κ³ , Phase 1이 λ™κ²°ν•œ "λ ˆμ½”λ“œ ν•„λ“œ λΆˆλ³€" κ³„μ•½μ˜ λ³€κ²½μ΄λ―€λ‘œ **리뷰어 μŠΉμΈμ„ μ„ ν–‰ 쑰건**으둜 κ±Έμ—ˆλ‹€. κ΅¬ν˜„ 쀑 μ‹€μΈ‘ν•œ κ²°κ³Ό **κ·Έ 변경이 ν•„μš”ν•˜μ§€ μ•Šμ•˜λ‹€**: - μ—”μ§„μ˜ `expected_attempt`λŠ” λ ˆμ½”λ“œμ˜ `attempt_id`(μ—†μŒ)λ₯Ό `iteration`(루프 회차)으둜 λŒ€μ²΄ λΉ„κ΅ν•œλ‹€ β€” 두 κ°œλ…μ΄ 달라 μ˜λ―Έκ°€ μ„±λ¦½ν•˜μ§€ μ•ŠλŠ”λ‹€. - 반면 **μ‹œλ„ 식별은 이미 증거 κ³„μΈ΅μ—μ„œ κ²€μ¦λœλ‹€**: `policy`κ°€ κ΄€μΈ‘ μ‹λ³„μžμ™€ shadow μ €μž₯μ†Œμ˜ dispatch λ ˆμ½”λ“œλ₯Ό λŒ€μ‘°ν•˜λ©°, μ‹œλ„κ°€ μ–΄κΈ‹λ‚˜λ©΄ `hold`ν•œλ‹€(μ‹€μΈ‘ 확인). λ”°λΌμ„œ μžλ™μ™„λ£ŒλŠ” 엔진에 `expected_attempt`λ₯Ό λ„˜κΈ°μ§€ μ•Šκ³  `expected_status="running"`(μ—”μ§„μ˜ 고유 μ˜μ—­μΈ μƒνƒœ)만 μ „μ œμ‘°κ±΄μœΌλ‘œ μ€€λ‹€. **μ‹œλ„ 보증은 μ‹œλ„ 정체성이 μ‹€μ œλ‘œ μ‚¬λŠ” 곳에 λ‘”λ‹€.** λ ˆμ½”λ“œ μŠ€ν‚€λ§ˆλŠ” λ°”λ€Œμ§€ μ•Šμ•˜κ³ , Phase 1 계약도 μœ μ§€λœλ‹€. `attempt_id` μŠΉκ²©μ€ μ—΄λ¦° 질문으둜 남긴닀. μŠΉκ²©ν•˜λ©΄ 엔진에 2μ°¨ 방어선이 μƒκΈ°μ§€λ§Œ 동결 계약을 λ°”κΏ”μ•Ό ν•˜λ©°, ν˜„μž¬λŠ” ν•„μš”ν•˜μ§€ μ•Šλ‹€. `test_x03_the_record_carries_iteration_not_an_attempt_id`κ°€ 이 μ „μ œλ₯Ό κ°μ‹œν•œλ‹€ β€” λ ˆμ½”λ“œκ°€ `attempt_id`λ₯Ό κ°–κ²Œ λ˜λŠ” μˆœκ°„ μ‹€νŒ¨ν•˜λ©°, κ·Έλ•Œκ°€ μž¬κ²€ν†  μ‹œμ μ΄λ‹€. ## 10. Phase 3 인계 1. `preexec_fn`: 2b도 데λͺ¬μ„ μŠ€ν°ν•˜μ§€ μ•Šμ•„ λ―Έλ…ΈμΆœ μœ μ§€. μ•Œλ¦Ό flushλŠ” κΈ°μ‘΄ κ΅¬λ…μž ν”„λ‘œμ„ΈμŠ€ μ•ˆμ—μ„œ μˆ˜ν–‰ν•œλ‹€. 2. λΆ€μˆ˜νš¨κ³Όμ˜ **원격** 확인(μ‹€μ œ push 도달 μ—¬λΆ€ λ“±)은 λΉ„λ²”μœ„ β€” 증거의 μ‘΄μž¬Β·λŒ€μ‘κΉŒμ§€λ§Œ κ²€μ¦ν•œλ‹€. 3. `agy`/`hermes`/`opencode` μžλ™μ™„λ£ŒλŠ” μ •μ§€ μƒνƒœ μ‹€μΈ‘ 증거 확보 ν›„ 별도 νŒλ‹¨.