# task-2729+9 보고서 — BASE_SOURCE_ISOLATION

작성: 다그다(dev3 팀장) · 2026-06-06 13:xx · 판정: **BASE_SOURCE_ISOLATION_VERIFIED**

## SCQA

- **Situation**: dispatch/봇 worktree 생성이 fresh `origin/main`(e386d4cf)이 아닌 stale
  로컬 `main`(14ff8339)에서 분기 → #181 hardening 없는 base 위 작업·merge 충돌·
  EXTERNAL_DIRTY_BLOCKER.
- **Complication**: audit 가 지목한 fallback 은 canonical HEAD(75fdf540)를 줘야 하는데
  실제 base 는 14ff8339 → 정확한 분기점 미상. 추측 fix 금지(REPRODUCTION-FIRST).
- **Question**: 정확히 어느 코드가 로컬 main 을 base 로 주는가? 그 경로가 expected_files
  안인가? canonical 무손상으로 어떻게 고정·검증하는가?
- **Answer**: isolated 재현으로 **`worktree_manager.py cmd_create` 의 fallback
  `git worktree add -b <b> <p>`(base 미지정)** 이 origin/main 미해결 시 *그 순간의 HEAD*
  (=로컬 main)에서 silent 분기함을 입증. expected_files 안 → fail-closed(B1)+marker(B2)+
  pre-push merge-base 구분(B3)으로 고정. 모든 검증 isolated temp repo, canonical 무손상.

## 1. 재현 evidence (REPRODUCTION-FIRST)
isolated temp git repo(`/tmp/repro-2729p9/`, evidence `/tmp/repro-2729p9/evidence.log`):

- **재현 A (버그)**: origin/main 미해결(origin URL 깨짐 + 추적 ref 제거) + HEAD=로컬 main
  → worktree HEAD == SHA_STALE(로컬 main). `base_fallback=True`, `base_sha=null`,
  marker `enforced=false`. → **버그 재현 성공**.
- **재현 B (정상)**: origin/main 해결(추적 ref 존재) → worktree HEAD == SHA_FRESH(origin/main),
  `base_fallback=False`, `enforced=true`. → 정상 경로 확인.
- **정확한 buggy 라인**: `cmd_create` fallback `git worktree add -b <branch> <wt_path>`
  (base commit 인자 없음). **expected_files(`scripts/worktree_manager.py`) 안** → HOLD 불필요.

미스터리 해소: fallback 은 항상 *호출 시점의 repo HEAD* 를 base 로 쓴다. task-2729+8
생성 시점 HEAD 가 로컬 main(14ff8339)이었고 origin/main fetch/resolve 가 실패해 fallback
진입 → 14ff8339 분기. audit 의 HEAD=75fdf540 가정은 시점 차이를 놓친 것.

## 2. 구현 (B1/B2/B3)
### B1 base 고정 (fail-closed) — scripts/worktree_manager.py cmd_create
- origin/main 미해결 + **origin remote 존재** → fail-closed: worktree 미생성,
  `status="failed"`, HOLD 마커 `<task_id>.worktree-base-failed.json`
  (reason `STALE_BASE_ORIGIN_UNRESOLVED`, canonical_head_sha 기록). main() 은 exit 1.
- origin/main 미해결 + **origin remote 없음(로컬 전용)** → 현재 HEAD 를 explicit SHA 로
  base 지정(`base_source="local_head_no_origin"`) → 회귀 방지.
- origin/main 해결 시 → 기존 explicit origin SHA base 유지(`base_source="origin/main"`).

### B2 marker 강제 — 성공 marker 5축 확장
`base_source`·`base_sha`·`merge_base`·`origin_main_sha`·`canonical_head_sha` 추가 기록.

### B3 pre-push merge-base 구분 — scripts/git-hooks/pre-push
`merge_base==origin/main` → three-dot scope(오탐 제거) / `!=` → STALE_BASE 명시 차단(exit 1)
/ 미해결 → two-dot graceful fallback.

## 3. 생성/수정 파일 (정확히 5 — 초과 0)
1. `scripts/worktree_manager.py` (수정, +142/-9 범위) — B1+B2
2. `scripts/git-hooks/pre-push` (수정, +18) — B3
3. `tests/regression/test_base_source_isolation_2729p9.py` (신규, 495줄, 5 케이스)
4. `memory/reports/task-2729+9.md` (본 문서)
5. `memory/plans/p0b-pickup/base_source_isolation_design_260606.md` (OPT-A/B/C 비교 설계)

브랜치: `task/task-2729+9-dev3` (base=e386d4cf origin/main). 커밋: `2f5c8408`(구현),
`65b5d542`(테스트).

## 4. 테스트 결과
- 회귀 5/5 PASS: ① stale 로컬main→origin base 강제 ② origin존재+미해결→fail-closed
  ③ 로컬전용→explicit HEAD base ④ marker 5축 ⑤ pre-push merge-base 분기.
- 기존 `tests/test_worktree_auto_fix_1993.py` 7/7 PASS (회귀 없음).
- syntax: worktree_manager.py AST OK, pre-push `bash -n` OK.

## 5. ★ L1 스모크테스트 결과
- **서버 재시작**: 해당없음 (git 인프라 task — 서버/API/프론트 없음)
- **API 응답 확인**: 해당없음 (대신 실제 프로세스 실행 evidence 로 대체)
- **실제 실행 검증 (subprocess/정제 작업 기준)**:
  - L1-a: 회귀 suite 실제 git 실행 → `5 passed in 0.85s`.
  - L1-b: 하드닝된 worktree 버전 `cmd_create` 를 isolated temp repo 에서 **라이브 실행** →
    origin 존재+origin/main 미해결 시 `status=failed`, worktree **미생성**, HOLD 마커
    `STALE_BASE_ORIGIN_UNRESOLVED` 생성, `canonical_head(d8665c83)==stale` 확인
    (fail-closed 가 실제로 stale 분기를 차단함을 라이브 입증).
- **스크린샷**: 해당없음 (CLI/git — 위 라이브 실행 로그가 동등 evidence).

## 6. 발견 이슈 및 해결
- 재현 스크립트의 worktree HEAD 측정으로 buggy 라인을 line 390 으로 특정(추측 배제). 해결됨.
- 로컬 전용 repo 회귀 우려 → origin 유무로 fail-closed/explicit-HEAD 분기하여 task-2377 류
  보존(테스트 ③ 로 입증). 해결됨.
- worktree 의 pre-commit 훅이 canonical 경로를 보아 임시 lock 잔류 → 정리 완료(미커밋).

## 7. 모델 사용 기록
- 다그다(팀장, Opus): 설계·재현 지시·검토·L1·보고(직접 코딩 없음).
- 모리건(테스터, **Sonnet**): 재현 + 회귀 테스트(분석/QA → haiku 금지 준수).
- 루(백엔드, **Sonnet**): B1/B2/B3 구현.
- haiku 미사용.

## 8. 머지 판단
- **머지 필요**: Yes
- **브랜치**: `task/task-2729+9-dev3`
- **워크트리 경로**: `/home/jay/.cokacdir/workspace/A28A3654/wt-2729p9`
- **머지 의견**: base=fresh origin/main e386d4cf, 충돌 0(파일 IDENTICAL), 회귀 5/5+기존7/7
  PASS, L1 라이브 fail-closed 입증. self-referential 리스크 대비 **수동 .done 금지** —
  ANU normal callback(독립 ANU key c119085addb0f8b7) 등록으로 ANU manual pickup 회수.
  same-PR post-Gemini push 금지 doctrine 준수.

## 9. canonical 무손상 확인
- canonical HEAD `75fdf540` / branch `task-2716` 변경 없음(작업 전후 동일).
- 모든 검증 repo 는 `/tmp` 또는 pytest tmp_path 하위. canonical working tree 미편집.
- task-2729+8 stale branch / PR 미생성(evidence-only 보존).

판정: **BASE_SOURCE_ISOLATION_VERIFIED**
