{
  "schema": "task.dispatch_decision.v1",
  "task_id": "task-2550+1",
  "team": "dev5",
  "lead": "marduk",
  "issued_at_kst": "2026-05-12",
  "owner_directive": "회장 §명시 2026-05-12 KST — task-2550+1 dispatch 승인 (Lv.4 control-plane security/correctness). PR #100 IMPLEMENTATION_SPEC_INCOMPLETE 회복.",
  "level": "Lv.4",
  "track": "A (control-plane, replacement PR — PR #100 IMPLEMENTATION_SPEC_INCOMPLETE 회복)",
  "base_sha": "bf59e7d2c26baee692600bdfd4abd647b33748b3",
  "base_ref": "origin/main",
  "branch": "task/task-2550+1-dev5",
  "predecessor_pr": 100,
  "predecessor_head": "4067d8c43833155f5ea626255645549602a23bbb",
  "predecessor_classification": "IMPLEMENTATION_SPEC_INCOMPLETE",
  "dispatch_preconditions_met": {
    "pr_103_merged": {
      "pr_number": 103,
      "merge_commit": "4e05acdd",
      "satisfied": true,
      "note": "task-2549+1 scripts/ci.sh fix MERGED"
    },
    "pr_108_merged": {
      "pr_number": 108,
      "merge_commit": "b6dca5d1",
      "satisfied": true,
      "note": "task-2556 executor 자동 entry point — capability auto-activation MERGED"
    },
    "owner_trigger_only_capability_main": {
      "pr_number": 106,
      "merge_commit": "cd1aeba4",
      "satisfied": true,
      "note": "task-2554+2 OWNER_TRIGGER_ONLY_CAPABILITY 5 layer 통합 main 반영"
    },
    "executor_auto_entry_point_verification": {
      "satisfied": true,
      "note": "PR #108 MERGED — capability runner 자동 호출 가능 (FIRST_MISSING/STALE 시)"
    }
  },
  "no_long_polling_required": true,
  "long_polling_doctrine_inheritance": {
    "policy_module": "anu_v2/polling_policy.py",
    "constants_enforced": {
      "MAX_SINGLE_SLEEP_SECONDS": 900,
      "FIRST_TIMEOUT_SECONDS": 1800,
      "MAX_RECHECKS": 1,
      "NORMAL_WAIT_MIN_SECONDS": 300,
      "NORMAL_WAIT_MAX_SECONDS": 900
    },
    "exit_after_recheck": true,
    "note": "5min~15min cooldown × 30min first timeout × 1회 recheck × 종료 — 회장 박제 doctrine 1:1 상속"
  },
  "expected_files": [
    "anu_v2/worktree_cleanup.py",
    "anu_v2/post_merge_smoke_runner.py",
    "anu_v2/tests/test_worktree_cleanup_2550plus1.py",
    "anu_v2/tests/test_post_merge_smoke_worktree_2550plus1.py",
    "memory/reports/task-2550+1.md",
    "memory/events/task-2550+1.dispatch-decision.json",
    "memory/events/task-2550+1.replacement-lineage.json",
    "memory/events/task-2550+1.gemini_triage_decision.json",
    "memory/plans/tasks/task-2550+1/plan.md",
    "memory/plans/tasks/task-2550+1/context-notes.md",
    "memory/plans/tasks/task-2550+1/checklist.md"
  ],
  "expected_files_count": 11,
  "implementation_spec_authoritative_source": "this file (dispatch_decision.json) — task.md 와 audit json 보다 우선",
  "high_fixes_required": [
    {
      "id": "HIGH-1",
      "location": "anu_v2/worktree_cleanup.py:147 (PR #100 baseline 기준)",
      "issue": "task_id in headRefName substring 매칭 → task-25 가 task-2550-dev5 에 매칭 (BUG)",
      "fix": "regex r'(?:^|sep)task-{num}(?:sep|$)' strict 경계 + _extract_task_id 동등 비교 (replacement chain task-2550 vs task-2550+1 분리)",
      "test": "test_worktree_cleanup_2550plus1::test_high_boundary_*"
    }
  ],
  "medium_fixes_required": [
    {
      "id": "MED-1",
      "location": "anu_v2/worktree_cleanup.py:418 (PR #100 baseline 기준)",
      "issue": "abs(hash(path)) % 10**8 — Python hash() 비결정론 (PYTHONHASHSEED 의존)",
      "fix": "hashlib.sha256(path)[:8] 결정론 hash",
      "test": "test_medium_1_log_filename_uses_deterministic_sha256 / test_concurrency_log_filename_stable_under_pythonhashseed"
    },
    {
      "id": "MED-2",
      "location": "anu_v2/worktree_cleanup.py:227 (PR #100 baseline 기준)",
      "issue": "pgrep -f <path> 는 argv 매칭만 — CWD 사용 process 미감지",
      "fix": "lsof +D <path> 추가 AND 게이트 (pgrep PASS + lsof PASS 모두 안전해야 PASS)",
      "test": "test_medium_2_safety_5_lsof_*"
    },
    {
      "id": "MED-3",
      "location": "anu_v2/post_merge_smoke_runner.py:541 (PR #100 baseline 기준)",
      "issue": "r.all_safe 는 dry-run 에서 항상 False (apply_explicit FAIL) → cleanup_candidates 항상 0 (가시성 상실)",
      "fix": "is_safe_ignoring_apply(r) helper — safety 1~5 PASS + not main + not dirty 로 산정",
      "test": "test_medium_3_dry_run_cleanup_candidates_visible_when_safety_1to5_pass / test_medium_3_*"
    },
    {
      "id": "MED-4-dedupe",
      "issue": "MED-3 duplicate (PR #100 Gemini 5번째 findings)",
      "fix": "MED-3 와 통합 처리 — 별도 fix 미발생",
      "test": "MED-3 와 동일"
    }
  ],
  "chain_policy": "code-changing 재발 시 자동 task-2550+2 발행 X — OWNER_DECISION_REQUIRED",
  "forbidden_paths": [
    "PR #98/#99/#100/#101/#102/#103/#104/#105/#106/#107/#108/#109 branch 변경 0",
    "scripts/ci.sh / dashboard/ / dispatch/__init__.py / team_prompts.py / .github/workflows/ / .env(.keys) 변경 0",
    "다른 task markers (task-2545~2557 외) 변경 0",
    "POC 영역 (memory/poc/, tools/poc/, tests/poc/) 변경 0",
    "main 직접 push 0",
    ".worktrees/ 실제 삭제 0 (dry-run only)",
    "다른 anu_v2 modules (owner_trigger_only/decision/audit, merge_queue_executor, replacement_pr_runner, auto_gemini_triage, critical_escalation_reporter, gemini_stale_prevention_runner, pr_open_gemini_trigger_prevention, executor_scheduler, idle_pr_diagnoser, polling_policy) 변경 0"
  ],
  "forbidden_18_actions": [
    "PR #100 commit/push/merge/close/reopen 0",
    "force/rebase/empty commit 0",
    "bot /gemini review 0 (task-2552 0/5 박제)",
    "owner PAT live 0 (capability runner OWNER_GEMINI_TRIGGER_TOKEN 만)",
    "GH_TOKEN fallback 0",
    "md/report만 PASS 0",
    "다른 PR 혼입 0",
    "자동 task-2550+2 chain 발행 0",
    "worktree 격리 위반 0 (.worktrees/task-2550plus1-dev5 강제)",
    "회장 수동 /gemini review 0",
    ".worktrees/ 실제 삭제 0 (dry-run only)",
    "long polling 0 (polling_policy 상수 강제)"
  ]
}
