당신은 마르둑(Marduk), 개발5팀장입니다. task-2545+3 terminal corrected replacement PR을 즉시 생성합니다. ## 본질 명령 (회장 §명시 2026-05-11 Option A 승인 — terminal attempt) PR #94의 fresh Gemini review 6 unresolved code-changing threads를 same-PR push 없이 task-2545+3 corrected replacement PR에 반영. expected_files=7 내부 처리 가능 → "scope expansion" 표현 X, **"additional code-changing fix required after replacement review"**로 기록. ## §0. BOT_TOKEN_RUNTIME_RESOLUTION_STEP0 (4-step) ```bash python3 /home/jay/workspace/scripts/refresh_bot_token.py export $(grep -E "^BOT_GITHUB_TOKEN=" /home/jay/workspace/.env.keys | head -1) [[ -n "$BOT_GITHUB_TOKEN" ]] || exit 1 GH_TOKEN=$BOT_GITHUB_TOKEN gh api /installation/repositories ``` ## §1. clean worktree (origin/main 37d52f42 기반) ```bash cd /home/jay/workspace git fetch origin main git worktree add .worktrees/task-2545p3-dev5-terminal -b task/task-2545+3-dev5-terminal origin/main cd .worktrees/task-2545p3-dev5-terminal git diff origin/main..HEAD # 0 lines 어설션 ``` ## §2. PR #92 / #93 / #94 head 보존 검증 ```bash for n in 92 93 94; do gh pr view $n --repo Jeon-Jonghyuk/dev_workspace --json state,headRefOid \ --jq "{pr:$n,state:.state,head:.headRefOid[0:12]}" done # 어설션: # PR #92 head=15cf6ad0, OPEN # PR #93 head=5ad46d99, OPEN # PR #94 head=2996be25, OPEN ``` ## §3. PR #94 base 7 files 추출 (task-2545+2 contract와 동일) ```bash # PR #94 head 2996be25에서 7 files git show 추출 for f in \ "anu_v2/gemini_stale_prevention_runner.py" \ "anu_v2/tests/test_gemini_stale_prevention_runner_2545.py" \ "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"; do mkdir -p "$(dirname "$f")" git show 2996be25:"$f" > "$f" done ``` ## §4. 6 code-changing fix 적용 (회장 §명시 P9K~P9Y) 각 fix는 `anu_v2/gemini_stale_prevention_runner.py` 내부: **P9K**: `_is_code_change_required(self, body)` → `_is_code_change_required(self, body, classification=None)` 시그니처 변경 (default None for 호환성) **P9O**: `_is_code_change_required(body)` 호출부 → `_is_code_change_required(body, cls=classification)` 또는 positional 전달 (P9K 짝) **P9P**: `expected_files_original`이 list로 사용되어 O(N²) 반복 체크 → set으로 변환 후 O(N) 처리: ```python # Before: if path in expected_files_original (list, O(N)) # After: expected_set = set(expected_files_original); if path in expected_set (O(1)) ``` **P9Q**: thread `target_file` 추출 시 `path` 키 일관성 (line 651 등): ```python # Before: target = thread.get('file_path') or thread.get('original_file_path') # After: target = thread.get('path') or thread.get('file_path') or thread.get('original_file_path') ``` (또는 회장 명시한 lookup 우선순위 일관성 적용) **P9U**: 다른 호출부에도 P9O와 동일 `cls` 전달 **P9Y**: 다른 위치(예: 다른 함수)의 `path` 키 일관성 P9Q와 동일 적용 회귀 테스트(`test_gemini_stale_prevention_runner_2545.py`)에 시그니처 변경 반영: - _is_code_change_required 호출 테스트가 새 시그니처 호환되도록 수정 ## §5. 회귀/pyright 검증 ```bash cd .worktrees/task-2545p3-dev5-terminal python -m pytest anu_v2/tests/test_gemini_stale_prevention_runner_2545.py -v # 어설션: 13/13 이상 PASS pyright anu_v2/gemini_stale_prevention_runner.py anu_v2/tests/test_gemini_stale_prevention_runner_2545.py # 어설션: 0 errors ``` ## §6. effective diff + forbidden_paths 어설션 ```bash git diff --name-only origin/main..HEAD | sort # 어설션: 정확 7개 ``` forbidden_paths 변경 0 검증 (다른 anu_v2 모듈 / dispatch / scripts / dashboard / report_parser / utils / teams / tests/regression / .github/workflows / DB-Auth-Deploy / task-2545.* / task-2545+1.* / task-2545+2.* markers 등). ## §7. replacement_lineage 박제 `memory/events/task-2545+3.replacement-lineage.json`: ```json { "schema_version": "anu_v2.replacement_lineage.v1", "original_task": "task-2545", "original_pr": 92, "original_head": "15cf6ad011e184ca298996d47253501152700287", "failed_replacement_prs": [93, 94], "failed_replacement_heads": { "93": "5ad46d999988b4272ecc954add28e9b542dd286e", "94": "2996be2565ecd8b8ff37840fc43341fa0df40a76" }, "new_replacement_task": "task-2545+3", "classification": "REPLACEMENT_REQUIRED_BY_SELF_POLICY", "subtype": "ADDITIONAL_CODE_CHANGING_FIX_REQUIRED_AFTER_REPLACEMENT_REVIEW", "critical_7_mapping": 6, "same_pr_push_allowed": false, "reason": "SELF_POLICY_REPLACEMENT_CHAIN_CONTINUATION", "chain_limit": { "policy": "task-2545+3 이후 추가 code_changing 발견 시 자동 task-2545+4 발행 X", "next_action_on_limit_hit": "OWNER_DECISION_REQUIRED", "classification_on_limit_hit": "SELF_POLICY_REPLACEMENT_CHAIN_LIMIT_HIT" } } ``` ## §8. 20단계 finalize sequence §0 token → §1 worktree → §2 PR #92/#93/#94 read-only → §3 7 files 추출 → §4 6 fix 적용 → §5 회귀/pyright → §6 diff/forbidden 어설션 → §7 lineage 박제 → commit + push → PR open → Gemini fresh + unresolved 0 → CI 11/11 → BOT_GITHUB_TOKEN squash merge → smoke + reconcile + lineage 갱신 → PR #92/#93/#94 head unchanged 재확인. ## §9. chain limit (회장 §명시) task-2545+3 이후 Gemini가 추가 code-changing threads 발견 시: - classification = `SELF_POLICY_REPLACEMENT_CHAIN_LIMIT_HIT` - next_action = `OWNER_DECISION_REQUIRED` - 기존 PR들 head 보존 (#92/#93/#94/#95 모두) - write action 0 - Critical 7 후보로 보고 (자동 task-2545+4 발행 절대 X) ## §10. 금지 18건 PR #92/#93/#94 추가 commit / PR #94 admin override / direct push / force / rebase / empty commit / close-reopen / bot /gemini review / owner_pat / GH_TOKEN fallback / expected_files amendment / expected_files=1 재사용 / incorrect forbidden_paths 재사용 / md report fallback / 기존 audit 삭제 / 다른 PR 혼입 / long polling / self-register — 모두 X. ## §11. 완료 기준 16건 1. PR 생성 / 2. effective diff == 7 / 3. forbidden 0 / 4. regression PASS / 5. pyright 0 / 6. CI all SUCCESS / 7. Gemini unresolved 0 / 8. mergeStateStatus CLEAN / 9. BOT identity / 10. BOT squash merge / 11. mergedBy=app/jeon-jonghyuk-taskctl-bot / 12. smoke PASS / 13. reconcile evidence / 14. PR #92/#93/#94 head unchanged / 15. lineage chain 보존 / 16. 신규 Critical 7 없음 ## §12. 보고 MERGED (mergedBy=app/jeon-jonghyuk-taskctl-bot, 16/16 PASS, PR #92/#93/#94 head unchanged) 또는 ESCALATED (Critical 7 #N) 만 보고. ESCALATED 매핑: - Gemini OWNER trigger 필요 → #6 GEMINI_AUTO_REVIEW_NOT_TRIGGERED - 추가 code_changing 발견 → **#6 SELF_POLICY_REPLACEMENT_CHAIN_LIMIT_HIT** (OWNER_DECISION_REQUIRED, 자동 task-2545+4 발행 X) - 기타 → 직접 분류 ## 최종 원칙 ANU v2 자기참조 정책 chain의 **terminal attempt**. 6 fix(P9K~P9Y) 적용 후 머지되면 chain 종결 + `classify_replacement_contract_framing()` doctrine main 진입. 동일 사고 자동 차단 가능. chain limit hit 시 회장 결정 필요.