# task-2503 — Merge Topology Gate code enforcement for dispatch

- 작업 유형: **dispatch layer hardening (schema + classifier + integration + audit + regression)**
- 작업 레벨: **Lv.3+** (코드 구현 + 회귀 테스트 + audit logger)
- 담당: **dev3-team (다그다)** — 분류/spec 경험 (task-2493 / task-2496)
- 우선순위: **★★ blocking** — 회장 §1 명시
- Track: **internal_doc / governance / dispatch_hardening**
- 일시: 2026-05-08
- 선행: task-2502 머지 완료 (SSOT 정상 main 반영, mergeCommit 46c16bee)

## ⚠️ 본 task의 본질 — 회장 §1 명시

> dispatch 단계에서 병렬 작업의 merge topology를 자동 판정하고, 충돌 가능성이 높은 task를 발행 전 **차단/보류/직렬화**한다. 정책 본체는 `memory/feedback/feedback_merge_topology_gate_260508.md`. 본 task는 **코드 기반 자동화 구현**.

## ★★ 회장 amendment (2026-05-08T11:32) — Phase 1 / Phase 2 분리

> task-2503은 **Phase 1만 진행**. Phase 2(dispatch.py production integration)는 **별도 후속 task-2504**로 분리한다. 자기참조 검증을 위해 Gate 본체 코드(schema/classifier)가 dispatch.py에 통합되기 전에 먼저 검증·머지되어야 함.

### Phase 1 허용 범위 (현재 task-2503)

a. **schema 코드** — `memory/specs/merge-topology-gate-schema.yml`
b. **classifier 코드** — `utils/merge_topology_gate.py` (pure function, dispatch.py import 금지)
c. **reason-code 정의** — BLOCK/LIMITED/REQUIRE 9 룰 enum
d. **audit format 코드** — `memory/orchestration-audit/merge-topology-gate.jsonl` schema 정의 + 빈 파일 생성
e. **regression tests** — classifier 직접 호출 (dispatch.py 미경유) 10건
f. **dry-run/helper** — `python utils/merge_topology_gate.py --dry-run --task-file <path>` CLI (dispatch.py 미수정)

### Phase 1 절대 금지 범위

a. **dispatch.py production hook** — Phase 2로 분리
b. **실제 dispatch 차단 로직 활성화** — Phase 2
c. **override flag (`--override-merge-topology-gate`) production 연결** — Phase 2
d. **auto_merge.py / finish-task.sh / merge executor 수정** — Phase 2
e. **active dispatch path 변경** — Phase 2

### Phase 2 (후속 task-2504 후보)

- task명: **Merge Topology Gate dispatch.py integration**
- parallel_policy: serial_only
- 회장 승인 필수
- task-2503 Phase 1 결과 보고 후 발행 여부 결정

### 자기참조 검증 (Phase 1 완료 조건)

- classifier가 task-2503.md 본체를 입력으로 받아 ALLOW 판정
- 통과 evidence를 `memory/events/task-2503.self-reference-pass`로 박제

## 회장 §1 task 명시

- task명: **Merge Topology Gate code enforcement for dispatch**
- priority: ★★
- level: Lv.3+
- parallel_policy: serial_only
- cherry_pick_allowed: false

## Merge Topology Gate 7 metadata (본 task spec 의무 준수)

```yaml
expected_files:
  # Phase 1만 변경 허용 (회장 amendment 2026-05-08T11:32)
  - "utils/merge_topology_gate.py"  # 신규 (classifier pure function + CLI dry-run helper)
  - "memory/specs/merge-topology-gate-schema.yml"  # 신규 schema 정의
  - "tests/regression/test_merge_topology_gate_schema_2503.py"  # 신규
  - "tests/regression/test_merge_topology_gate_classifier_2503.py"  # 신규
  - "tests/regression/test_merge_topology_gate_audit_format_2503.py"  # 신규 (audit jsonl 스키마 검증)
  - "memory/orchestration-audit/merge-topology-gate.jsonl"  # 신규 audit log (빈 파일 + 스키마 정의만)
  - "memory/events/task-2503.self-reference-pass"  # 자기참조 검증 evidence
  # ❌ 제거 (Phase 2 task-2504로 분리): "dispatch.py", "test_merge_topology_gate_dispatch_integration_2503.py"

risk_area: "dispatch_layer / governance / parallel_policy_enforcement"

dependency: ["task-2502.merged"]  # SSOT 정상 main 반영 후 dispatch 가능

parallel_policy: "serial_only"  # dispatch.py 침범으로 다른 dispatch 작업과 병렬 금지

merge_queue_position: 1  # 본 task가 최우선 머지 (다른 dispatch 변경 작업이 발생할 시)

stale_recheck_required: true  # main에 다른 dispatch 변경 머지 시 재검증 의무

cherry_pick_allowed: false  # 회장 §1 명시
```

## 회장 §2 구현 순서 5단계

### a. schema (1단계)
- `memory/specs/merge-topology-gate-schema.yml` 신규
- 7 metadata 필드 정의 (type / required / enum / regex 검증)
- task spec YAML 블록 또는 frontmatter에서 추출 가능하도록 명세

### b. classifier (2단계)
- `utils/merge_topology_gate.py` 신규
- 회장 §4 9개 BLOCK/LIMITED/REQUIRE 판정 룰 구현 (아래 §4 참조)
- 입력: 새 task spec + active task list (dispatch.py 또는 task-timers.json)
- 출력: ALLOW / LIMITED_PARALLEL / BLOCK / REQUIRE_CHAIR_OVERRIDE + reason_codes

### c. ⛔ Phase 2 분리 (회장 amendment 2026-05-08T11:32) — task-2504 후속 발행 대기
- ~~dispatch.py에 Merge Topology Gate hook 추가~~ → **task-2504 (Phase 2)**
- ~~task spec 로드 시점에 classifier 호출~~ → **task-2504 (Phase 2)**
- ~~BLOCK 시 dispatch 거부 + audit log 기록~~ → **task-2504 (Phase 2)**
- ~~LIMITED_PARALLEL 시 merge_queue_position 검증~~ → **task-2504 (Phase 2)**
- ~~REQUIRE_CHAIR_OVERRIDE 시 `--override-merge-topology-gate` 플래그 필요~~ → **task-2504 (Phase 2)**
- 본 task에서 dispatch.py 수정 금지. 만약 이미 수정한 commit이 있다면 Phase 1 PR에 포함하지 말고 별도 보고하라.

### c-alt. dry-run/helper CLI (Phase 1 대체 단계 — 회장 amendment 2026-05-08T11:32)
- `utils/merge_topology_gate.py` 내 CLI: `python utils/merge_topology_gate.py --dry-run --task-file <path>`
- dispatch.py 미경유. classifier만 직접 호출하여 ALLOW/LIMITED/BLOCK/REQUIRE 출력
- audit jsonl에는 dry-run 결과를 별도 dry_run=true 필드로 기록 (production 차단 동작 X)
- 본 dry-run helper는 Phase 2 통합 시 그대로 재사용 가능한 pure function 형태로 설계

### d. audit evidence (4단계)
- `memory/orchestration-audit/merge-topology-gate.jsonl` (append-only)
- 회장 §5 9 필드 기록

### e. regression tests (5단계)
- `tests/regression/test_merge_topology_gate_*_2503.py` 3종
- 회장 §6 10건 테스트 케이스 모두 PASS

## 회장 §4 필수 classifier 룰 (9건)

| # | 조건 | 판정 |
|---|---|---|
| 1 | metadata 누락 | **BLOCK** |
| 2 | 동일 파일 (expected_files 교집합) | **BLOCK** |
| 3 | 동일 함수/state machine | **BLOCK** |
| 4 | 동일 verifier | **BLOCK** 또는 **LIMITED** (정책에 따름) |
| 5 | 동일 QC/merge lifecycle | **LIMITED** |
| 6 | dependency 미충족 (선행 PR mergedAt == null) | **BLOCK** |
| 7 | cherry_pick_allowed=true | **REQUIRE_CHAIR_OVERRIDE** |
| 8 | limited_parallel + merge_queue_position 누락 | **BLOCK** |
| 9 | parallel_safe 허위 선언 (실제 expected_files 교집합 존재) | **BLOCK** |

## 회장 §5 필수 audit 필드 (9건)

```jsonl
{
  "task_id": "task-2503",
  "decision": "ALLOW | LIMITED_PARALLEL | BLOCK | REQUIRE_CHAIR_OVERRIDE",
  "reason_codes": ["DUPLICATE_FILE", "MISSING_DEPENDENCY"],
  "overlap_score": 0.85,
  "conflicting_tasks": ["task-2487+1", "task-2497"],
  "active_tasks_snapshot": [...],
  "open_prs_snapshot": [...],
  "override_used": false,
  "timestamp": "2026-05-08T11:40:00+09:00"
}
```

## 회장 §6 필수 회귀 테스트 (10건)

1. metadata 누락 → BLOCK
2. 동일 파일 overlap → BLOCK
3. 동일 verifier / risk_area → LIMITED
4. dependency unmerged → BLOCK
5. parallel_safe 허위 선언 → BLOCK
6. cherry_pick_allowed=true → REQUIRE_CHAIR_OVERRIDE
7. override audit 생성 검증
8. 정상 parallel_safe → ALLOW
9. limited_parallel + queue_position 누락 → BLOCK
10. stale_recheck_required → 강제 재검증 호출

## 회장 §7 절대 금지

1. 자동 cherry-pick 구현 금지
2. auto_merge 실행부와 섞기 금지
3. PR #52/#49/#50/#51 수정 금지
4. task-2497/2498/2494 재실행 흐름 방해 금지
5. dashboard / dispatch (override 외) / report_parser 등 비대상 파일 침범 금지

## allowed_resources

```yaml
allowed_resources:
  read_only_paths:
    - "memory/tasks/task-2503*"
    - "memory/feedback/feedback_merge_topology_gate_260508.md"
    - "memory/feedback/feedback_escalated_verifier_limitation_classification_260508.md"
    - "memory/orchestration/phase_b_integration_items_260507.md"
    - "memory/events/six-team-batch.essence-pass-escalated-verifier-limitation"
    - "memory/events/task-2487+1.scope-violation.json"
    - "memory/events/task-2502.essence-pass-escalated-verifier-limitation"
    - "utils/task_id_parser.py"
    - "dispatch.py"  # 기존 read 후 hook 추가
    - ".env.keys"
  paths:
    - "memory/tasks/task-2503*"
    - "memory/reports/task-2503*"
    - "memory/events/task-2503*"
    - "memory/plans/tasks/task-2503/**"
    - "memory/specs/merge-topology-gate-schema.yml"
    - "memory/orchestration-audit/merge-topology-gate.jsonl"
  workflow_paths:
    # Phase 1 한정 (회장 amendment 2026-05-08T11:32)
    - "utils/merge_topology_gate.py"  # 신규 (classifier pure function + CLI dry-run)
    - "tests/regression/test_merge_topology_gate_schema_2503.py"  # 신규
    - "tests/regression/test_merge_topology_gate_classifier_2503.py"  # 신규
    - "tests/regression/test_merge_topology_gate_audit_format_2503.py"  # 신규 (3종 — dispatch_integration은 Phase 2)
    # ❌ 제거: "dispatch.py" (Phase 2 task-2504로 분리)
  forbidden_paths:
    - ".secrets/**"
    - ".github/workflows/**"
    - "scripts/auto_merge.py"  # 회장 §7 금지
    - "scripts/finish-task.sh"  # Phase 2 task-2504로 분리 (amendment)
    - "dispatch.py"  # ★ Phase 1 금지 — Phase 2 task-2504에서만 수정 (amendment 2026-05-08T11:32)
    - "tests/regression/test_merge_topology_gate_dispatch_integration_*.py"  # Phase 2로 분리
    - "memory/events/task-2483*"
    - "memory/events/task-2487+1*"  # 회장 §7 PR #52 영역 보호
    - "memory/events/task-2497*"  # 회장 §7 흐름 방해 금지
    - "memory/events/task-2498*"
    - "memory/events/task-2494*"
    - "dashboard/**"  # 회장 §7
    - "report_parser.py"  # 회장 §7
    - "tests/poc/**"
    - "tools/poc/**"
    - "memory/poc/**"
  forbidden_actions:
    - admin_override
    - required_ci_bypass
    - manual_done_creation
    - existing_pr_force_push
    - existing_pr_close_or_delete
    - pr_52_modification
    - pr_49_50_51_modification
    - task_2497_2498_2494_rerun_interference  # 회장 §7-4
    - auto_cherry_pick_implementation  # 회장 §7-1
    - auto_merge_mixing  # 회장 §7-2
    - dashboard_intrusion
    - report_parser_modification
    - rebase
    - workspace_full_sync
    - audit_jsonl_real_write_outside_target  # merge-topology-gate.jsonl만 허용
    - token_value_logging
    # Phase 1 amendment 추가 금지 (회장 2026-05-08T11:32)
    - dispatch_py_modification  # Phase 1 절대 금지 — Phase 2 task-2504에서만
    - finish_task_sh_modification  # Phase 2 분리
    - merge_executor_modification  # Phase 2 분리
    - active_dispatch_path_change  # Phase 2 분리
    - override_flag_production_wiring  # Phase 2 분리
```

## 완료 조건 — Phase 1 한정 (회장 amendment 2026-05-08T11:32)

1. ✅ schema YAML 작성 + 7 필드 검증 룰 정의
2. ✅ classifier 9 BLOCK/LIMITED/REQUIRE 룰 구현 (pure function, dispatch.py import 금지)
3. ⛔ ~~dispatch.py hook 추가 + override flag 동작~~ → **Phase 2 task-2504로 분리**
3'. ✅ dry-run/helper CLI 동작 (`python utils/merge_topology_gate.py --dry-run --task-file <path>`)
4. ✅ audit jsonl schema 정의 + 빈 파일 생성 + dry_run=true 필드로 dry-run 결과 기록 (production 차단 X)
5. ✅ 회귀 테스트 10건 ALL PASS — 단 dispatch_integration 케이스(#10 stale_recheck)는 classifier 직접 호출로 검증 (dispatch.py 미경유)
6. ✅ 신규 PR 생성 + Merge Topology Gate **자기참조 PASS** (classifier가 task-2503.md 본체를 입력으로 ALLOW 판정 + `memory/events/task-2503.self-reference-pass` 박제)
7. ✅ CI 11/11 SUCCESS
8. ✅ Gemini fresh evidence 확보
9. ✅ PR #52/#49/#50/#51 보존
10. ✅ task-2497/2498/2494 흐름 방해 0건 (별도 dispatch와 충돌 0)
11. ✅ dispatch.py 미수정 명시 (`git diff origin/main -- dispatch.py` empty)
12. ✅ Phase 2 후속 task-2504 후보 evidence (`memory/events/task-2504-candidate.dispatch-integration-spec`) 작성

## 시스템 3문서 참조

- 정책 본체: `memory/feedback/feedback_merge_topology_gate_260508.md`
- Phase B 통합 항목 §9.7: `memory/orchestration/phase_b_integration_items_260507.md`
- 시스템 청사진: `/home/jay/.claude/projects/-home-jay--cokacdir-workspace-autoset/memory/system_bot_orchestration_blueprint_260506.md`
- 트리거 incident evidence:
  - `memory/events/task-2487+1.scope-violation.json` (60+ 파일 침범 사례)
  - `memory/events/six-team-batch.essence-pass-escalated-verifier-limitation` (동일 verifier 동시 사고)
  - `memory/events/task-2502.essence-pass-escalated-verifier-limitation`

## 보고

- SCQA 4섹션
- 회장 §2 5단계 구현 결과
- 회장 §3 7 metadata schema 검증
- 회장 §4 9 classifier 룰 검증
- 회장 §5 9 audit 필드 검증
- 회장 §6 10 회귀 테스트 결과
- 회장 §7 5 금지 위반 0건 명시
- Merge Topology Gate **자기참조 검증** (본 task 자체가 Gate 통과해야 함)
- 새 PR 번호 + headRefName + CI 상태 + Gemini APPROVED 여부
- 헤르메스/아누 통합 요약 경유, 회장 직접 장문 보고 X

## 후행 (자동 트리거 X — 회장 결정)

- task-2503 머지 후 모든 신규 dispatch는 Gate 의무 통과
- 기존 task (task-2502 등) 회고 metadata 보강 별도 task 검토
- 본 task는 task-2497/2498/2494 재실행 흐름과 **별도 critical path** (회장 §1 명시)