당신은 마르둑(Marduk), 개발5팀장입니다. task-2545+2 / PR #94 finalize 재개를 즉시 진행합니다. ## 본질 명령 (회장 §명시 2026-05-11 OWNER 트리거 완료) 회장이 PR #94에 OWNER 계정 `/gemini review` 댓글 1회 트리거 완료. 직전 ESCALATED 원인(GEMINI_AUTO_REVIEW_NOT_TRIGGERED) RESOLVED. 잔여 §1~§15 finalize 즉시 재개. ## §0. BOT_GITHUB_TOKEN_RUNTIME_RESOLUTION_STEP0 (4-step, 50분 만료 가능성 대응) ```bash python3 /home/jay/workspace/scripts/refresh_bot_token.py 2>&1 | tail -3 export $(grep -E "^BOT_GITHUB_TOKEN=" /home/jay/workspace/.env.keys | head -1) [[ -n "$BOT_GITHUB_TOKEN" ]] || { echo "FATAL: BOT_GITHUB_TOKEN missing"; exit 1; } GH_TOKEN=$BOT_GITHUB_TOKEN gh api /installation/repositories --jq '.repositories[0].full_name' 2>&1 | head -1 ``` ## §1~§15 회장 §명시 finalize 재개 15단계 1:1 ### §1. Gemini fresh review 도착 확인 ```bash gh api repos/Jeon-Jonghyuk/dev_workspace/pulls/94/reviews \ --jq '.[] | select(.user.login | test("gemini|google-labs"; "i")) | {id, state, submitted_at, commit_id}' ``` 어설션: OWNER 트리거 후 신규 review 1건 이상 도착. ### §2. evidence commit_id == current head 2996be25 어설션 ```bash HEAD=$(gh pr view 94 --repo Jeon-Jonghyuk/dev_workspace --json headRefOid --jq '.headRefOid') # 어설션: HEAD == 2996be25... (cron 발사 시점, 추가 push 0) # Gemini commit_id == HEAD → FRESH ``` ### §3. unresolved thread triage ```bash gh api graphql -f query=' { repository(owner: "Jeon-Jonghyuk", name: "dev_workspace") { pullRequest(number: 94) { reviewThreads(first: 50) { nodes { id, isResolved, comments(first:1) { nodes { body, author { login } } } } } } } }' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)' ``` - unresolved 0 → §4 - unresolved 있으면 triage: - false_positive / style_only / no_code_change → reply + resolve (same-PR push 0) - code_changing_fix → ESCALATED (task-2545+3 권고, PR #94 close-reopen 금지) ### §4. unresolved 0 확인 (final) ```bash # §3 triage 후 unresolved threads 재조회 = 0건 어설션 ``` ### §5. CI 11/11 SUCCESS ```bash gh pr view 94 --repo Jeon-Jonghyuk/dev_workspace \ --json statusCheckRollup \ --jq '.statusCheckRollup[] | select(.conclusion != "SUCCESS") | {name, conclusion}' ``` 어설션: 미PASS 0건. gemini-review-gate / phase3-merge-gate 포함 11/11 SUCCESS. ### §6. mergeStateStatus CLEAN ```bash gh pr view 94 --repo Jeon-Jonghyuk/dev_workspace --json mergeStateStatus,mergeable ``` 어설션: mergeStateStatus=CLEAN, mergeable=MERGEABLE. ### §7. effective diff == expected_files 7개 재확인 ```bash gh pr view 94 --repo Jeon-Jonghyuk/dev_workspace --json files --jq '.files[].path' | sort ``` 어설션 (정확 7개): - `anu_v2/fixtures/stale_prevention_false_positive_same_pr_resolve.json` - `anu_v2/fixtures/stale_prevention_pr76_empty_commit_fail.json` - `anu_v2/fixtures/stale_prevention_pr86_same_pr_fix.json` - `anu_v2/fixtures/stale_prevention_pr88_unresolved_push.json` - `anu_v2/fixtures/stale_prevention_replacement_pr_clean_path.json` - `anu_v2/gemini_stale_prevention_runner.py` - `anu_v2/tests/test_gemini_stale_prevention_runner_2545.py` ### §8. forbidden_paths 변경 0 재검증 - task-2545.md / task-2545+1.md amendment 0 - task-2545.* / task-2545+1.* markers 변경 0 (단 task-2545+2.* 신규 OK) - 다른 anu_v2 모듈 (post_merge_smoke_runner, replacement_pr_runner, auto_gemini_triage 등) 변경 0 - PR #92 / PR #93 branch 변경 0 - POC 영역 변경 0 - audit jsonl append 1줄만 ### §9. BOT_GITHUB_TOKEN identity 재확인 ```bash GH_TOKEN=$BOT_GITHUB_TOKEN gh api /installation/repositories --jq '.repositories[0].full_name' 2>&1 ``` 어설션: BOT identity = installation token (app/jeon-jonghyuk-taskctl-bot). ### §10. BOT squash merge ```bash GH_TOKEN=$BOT_GITHUB_TOKEN gh pr merge 94 \ --repo Jeon-Jonghyuk/dev_workspace \ --squash --auto=false --delete-branch=false ``` mergedBy 직접 검증: ```bash gh pr view 94 --repo Jeon-Jonghyuk/dev_workspace --json mergedBy --jq '.mergedBy.login' ``` 어설션: `app/jeon-jonghyuk-taskctl-bot`. 다르면 BOT_IDENTITY_DIVERGENCE 박제 후 ESCALATED. ### §11. post_merge_smoke_runner 실행 ```bash cd /home/jay/workspace python3 -c " from anu_v2.post_merge_smoke_runner import PostMergeSmokeRunner runner = PostMergeSmokeRunner() result = runner.run_post_merge_smoke(task_id='task-2545+2', merge_commit='') print(result) " ``` 어설션: smoke PASS, marker `memory/events/task-2545+2.smoke-evidence` 생성. ### §12. reconcile evidence 생성 ```bash python3 /home/jay/workspace/utils/lifecycle_reconciliation_manager.py \ --reconcile --task-id "task-2545+2" --apply --json ``` 어설션: state=FINALIZED, marker `memory/events/task-2545+2.reconcile-evidence` 생성. ### §13. done.acked / merge-done 정리 - `memory/events/task-2545+2.done` 보존 - `memory/events/task-2545+2.done.acked` 생성/보존 - `memory/events/task-2545+2.merge-done` 생성 ### §14. replacement_lineage 갱신 파일: `memory/events/task-2545+2.replacement-lineage.json` ```python import json p = "/home/jay/workspace/memory/events/task-2545+2.replacement-lineage.json" data = json.loads(open(p).read()) prior = data.pop("dispatch_status", None) if "dispatch_status_history" not in data: data["dispatch_status_history"] = [] if prior: data["dispatch_status_history"].append(prior) data["dispatch_status"] = { "stage": "REPLACEMENT_PR_FINALIZED_AFTER_OWNER_GEMINI_TRIGGER", "outcome": "MERGED", "ts": "", "retry_index": len(data["dispatch_status_history"]), "merge_commit": "", "merged_by": "app/jeon-jonghyuk-taskctl-bot", "smoke_pass": True, "reconcile_evidence_path": "memory/events/task-2545+2.reconcile-evidence", "owner_gemini_trigger_required": True, "owner_gemini_trigger_completed_at": "", "regression_doctrine_pinned": "classify_replacement_contract_framing()" } open(p, "w").write(json.dumps(data, indent=2, ensure_ascii=False) + "\n") ``` ### §15. PR #92 / PR #93 close-safe audit는 별도 회장 승인 전까지 **close 금지** ```bash # read-only audit만 수행, close 액션 절대 금지 gh pr view 92 --repo Jeon-Jonghyuk/dev_workspace --json state,headRefOid \ --jq '. | "PR #92 state=\(.state) head=\(.headRefOid)"' gh pr view 93 --repo Jeon-Jonghyuk/dev_workspace --json state,headRefOid \ --jq '. | "PR #93 state=\(.state) head=\(.headRefOid)"' ``` 어설션: PR #92 head=`15cf6ad011e1` unchanged + OPEN, PR #93 head=`5ad46d999988` unchanged + OPEN. → close 액션은 회장 별도 승인 후. 본 cron에서 **close 0**. ## 금지 14건 (회장 §명시 1:1) 1. ❌ 추가 `/gemini review` 요청 (OWNER 1회로 충분) 2. ❌ bot `/gemini review` (신규 발사) 3. ❌ empty commit 4. ❌ close/reopen (PR #92/#93/#94 모두) 5. ❌ force push / rebase 6. ❌ PR #92 변경 7. ❌ PR #93 변경 8. ❌ PR #94에 Gemini 없이 추가 commit (Gemini fresh + unresolved 0 후만 허용) 9. ❌ owner PAT 사용 10. ❌ default GH_TOKEN fallback merge 11. ❌ expected_files amendment 12. ❌ 다른 task / PR 혼입 13. ❌ long polling / self-register 반복 14. ❌ md/report만으로 PASS 처리 (실제 marker / check_run / PR diff / 파일 존재 기준) ## 보고 MERGED (mergedBy=app/jeon-jonghyuk-taskctl-bot, 15/15 PASS, PR #92/#93 head unchanged) 또는 ESCALATED (Critical 7 #N 매핑) 만 보고. 무변화 polling / 회장 chat 노출 X. ESCALATED 매핑 가이드: - §1 Gemini fresh evidence 미도착 → #6 GEMINI_AUTO_REVIEW_DELAYED - §3 unresolved code_changing_fix 발견 → #6 GEMINI_REAL_BUG_REQUIRES_FURTHER_SCOPE_EXPANSION (task-2545+3) - §0/§9 token 만료 → #6 BOT_TOKEN_REFRESH_FAILED - §7/§8 어설션 fail → #1 FORBIDDEN_PATH 또는 #2 EFFECTIVE_DIFF_FAIL - §10 mergedBy 불일치 → BOT_IDENTITY_DIVERGENCE 박제 ## 최종 원칙 ANU v2 자기참조 정책 + corrected contract framing + GEMINI_EXTERNAL_TRIGGER_GAP handoff + finalize 14단계의 첫 통합 적용 사례. 본 PR #94 머지 후 `classify_replacement_contract_framing()` 회귀 doctrine이 main 진입하여 향후 동일 사고 자동 분류·차단 가능.