{
  "task_id": "task-2670",
  "task_title": "PR_WATCHER_TERMINAL_CALLBACK_ROOT_CAUSE_PACKET",
  "executor": "dev8 라",
  "chair_authorization_id": "CHAIR-AUTH-PR-WATCHER-TERMINAL-CALLBACK-ROOT-CAUSE-20260525-JJONGS-RCA-001",
  "completion_state": "PR_WATCHER_TERMINAL_CALLBACK_ROOT_CAUSE_PACKET_READY",
  "task_md_sha256": "f2de5dd3df6c3d0cb9c8906da346907cdeb267c859ef553fe810da3f9a692d4f",
  "completed_at_utc": "2026-05-25T15:25:00Z",
  "base_branch_head": "2752182ad679024dcbcdbf090165387fb822be67",
  "worktree": ".worktrees/task-2670-dev8",
  "branch": "task/task-2670-dev8",
  "report_fields": {
    "1_root_cause_classification": {
      "type": "complex",
      "primary_candidates_p0": [
        "fresh unresolved 시 HOLD_FOR_CHAIR (spec 정명 CHAIR_REQUIRED) 조기 전환 조건 미흡",
        "terminal_state 5 enum evaluation policy 결함 (CHAIR_REQUIRED 분기 부재)",
        "unresolved callback timing policy 결함 (watcher.py 내 cokacdir --cron 호출 0)"
      ],
      "secondary_candidates_p1": [
        "max_watch_minutes 도달 전 HOLD 조건 누락 (LOOP_BOUNDARY elapsed-only)"
      ],
      "one_line": "classify() decision tree 가 spec §5 CHAIR_REQUIRED enum 자체를 모르고, callback fire 코드가 watcher.py 안에 0 줄이라, BLOCKED + fresh Gemini + new unresolved 신호가 silent 한 채 max_watch 까지 흘렀다."
    },
    "2_watcher_code_path_citation": {
      "file": "/home/jay/.cokacdir/workspace/29C74592/watcher.py",
      "lines": "L82-141 (classify body) + L184-244 (main body)",
      "critical_defects": [
        {"line": "L113", "verbatim": "return \"HOLD_FOR_CHAIR\", f\"head drift to {head}\"", "defect": "spec 정명 CHAIR_REQUIRED 와 명명 불일치 · head drift 외 escalate 분기 부재"},
        {"line": "L116-126", "verbatim": "MERGE_READY branch (mss==CLEAN ... unresolved==0)", "defect": "unresolved 변수가 이 분기 외 어디서도 evaluate 0"},
        {"line": "L141", "verbatim": "return None, \"continue\"", "defect": "fall-through 폭이 커서 BLOCKED+fresh+unresolved 가 silent fall-through"},
        {"line": "L226-244", "verbatim": "_terminal.json 저장 + log only", "defect": "cokacdir --cron callback fire 0회 · spec §6 step 4 위반"}
      ]
    },
    "3_terminal_state_classification_at_poll12": {
      "t_offset_sec": 1336,
      "elapsed_min": 22.27,
      "input_state": {
        "head_match_expected": true,
        "mergeStateStatus": "BLOCKED",
        "reviewDecision": "",
        "critical7_failures": [],
        "non_critical7_failures": ["gemini-review-gate", "phase3-merge-gate"],
        "unresolved_thread_count": 3,
        "latest_gemini_review": {
          "submittedAt": "2026-05-25T13:39:36Z",
          "commit_oid": "4bb627fe9252acacc1c32007211807fe9905809f",
          "head_match": true
        }
      },
      "current_classification": "None / continue",
      "correct_doctrine_classification": "CHAIR_REQUIRED",
      "doctrine_basis": "system_ci_watch_handoff_policy_spec_260523.md §5 — CHAIR_REQUIRED = Critical7 / credential expansion / expected_files 밖 수정 / admin override 필요 / post-merge smoke fail · BLOCKED + fresh Gemini with new unresolved = admin override 필요 등가물",
      "enum_table": [
        {"enum": "CI_FAILED_NON_REMEDIABLE", "watcher_line": "L107", "applies_at_poll12": false, "reason": "Critical7 FAILURE 0"},
        {"enum": "HOLD_FOR_CHAIR (watcher.py 표기)", "watcher_line": "L112", "applies_at_poll12": false, "reason": "head 일치"},
        {"enum": "MERGE_READY", "watcher_line": "L119", "applies_at_poll12": false, "reason": "mss=BLOCKED · unresolved=3 · 2 gates FAILURE"},
        {"enum": "GEMINI_EXTERNAL_TRIGGER_STALE", "watcher_line": "L131", "applies_at_poll12": false, "reason": "gemini_fresh=True"},
        {"enum": "LOOP_BOUNDARY", "watcher_line": "L138", "applies_at_poll12": false, "reason": "elapsed=1336<3600"},
        {"enum": "CHAIR_REQUIRED (spec 정명)", "watcher_line": "분기 부재", "applies_at_poll12": "spec doctrine: YES (현재 코드 미구현)", "reason": "BLOCKED + fresh Gemini + new unresolved = admin override 필요"}
      ]
    },
    "4_callback_registrar_path": {
      "spec_requirement": "system_ci_watch_handoff_policy_spec_260523.md §6 step 4 — watcher 는 terminal state 에서 ANU normal callback 을 발사한다",
      "current_implementation": "watcher.py main() L226-244 — _terminal.json 저장 + log only",
      "missing_keywords_in_watcher_py": ["cokacdir", "--cron", "--chat", "--key", "envelope", "callback"],
      "subprocess_run_for_callback_count": 0,
      "doctrine_compliance_pct": 0,
      "callback_arrival_source": "schedule_history/29C74592.log (status=ok, duration 4142s) — 별개 schedule (ANU 이참나 본체) 자연 종료의 부수효과 · watcher 가 발사한 게 아님",
      "should_be_called_at": "L244 직후 (terminal 박제 + _history.json 저장 후, log 발화 직후)"
    },
    "5_fix_packet_diff_preview": {
      "scope": "preview only · 실제 diff 0 · watcher.py 변경 0",
      "fixes": [
        {"id": "Fix#1", "priority": "P0", "location": "watcher.py L127-128 신설", "summary": "CHAIR_REQUIRED 자동 escalate 분기 (gemini_fresh + unresolved>0 + mss=BLOCKED)"},
        {"id": "Fix#2", "priority": "P0", "location": "watcher.py main() L244 직후", "summary": "subprocess.run(['cokacdir','--cron',envelope,'--at',absolute_now+30s,'--chat',ANU_CHAT_ID,'--key',ANU_KEY,'--once']) · envelope UTF-8 ≤3900 bytes · env-driven"},
        {"id": "Fix#3", "priority": "P1", "location": "watcher.py L138", "summary": "LOOP_BOUNDARY 도달 시 unresolved>0 또는 mss=BLOCKED 잔재 → CHAIR_REQUIRED 격상"},
        {"id": "Fix#4", "priority": "P2", "location": "policy decision", "summary": "non-Critical7 gates (gemini-review-gate · phase3-merge-gate) FAILURE 처리 — A/B/C 옵션 enumerate · 회장 verbatim 결정 필요"},
        {"id": "Fix#5", "priority": "P1", "location": "watcher.py L113", "summary": "HOLD_FOR_CHAIR → CHAIR_REQUIRED 명명 통합"}
      ],
      "preview_spec": "memory/specs/pr_watcher_terminal_callback_fix_diff_preview_260525.md"
    },
    "6_regression_suite": {
      "core_cases": [
        {"id": "RS-2670-A", "name": "LOOP_BOUNDARY-with-unresolved-residual", "covers_fix": "Fix#3"},
        {"id": "RS-2670-B", "name": "fresh-evidence-with-new-unresolved (poll #12 박제)", "covers_fix": "Fix#1"},
        {"id": "RS-2670-C", "name": "callback-registrar-failure", "covers_fix": "Fix#2"}
      ],
      "auxiliary_cases": ["B-pos (Fix#1 false-positive 방지)", "B-neg (stale gemini)", "B-edge (mss=BEHIND)", "C-fail (subprocess timeout)", "C-skip (env 부재)"],
      "acceptance_criteria_count": 7,
      "suite_spec": "memory/specs/pr_watcher_terminal_callback_regression_suite_260525.md"
    },
    "7_forbidden_action_count": 0,
    "7_forbidden_breakdown": {
      "code_modification_immediate": 0,
      "pr_created": 0,
      "merge": 0,
      "dev_bot_redispatch": 0,
      "live_settings_json": 0,
      "dispatch_py": 0,
      "hooks_live": 0,
      "axis_runtime_harness_enforced_running": 0,
      "forbidden_path_writes": 0,
      "bot_github_token_calls": 0,
      "task_2662_2669_file_collisions": 0,
      "watcher_py_modifications": 0
    },
    "8_recommended_next_action": {
      "step_1": "회장 보고: PR_WATCHER_TERMINAL_CALLBACK_ROOT_CAUSE_PACKET_READY",
      "step_2": "fix 적용은 별도 회장 verbatim chair_authorization_id (예: CHAIR-AUTH-...-FIX-APPLY-...) 발급 후 신규 task 발행",
      "step_3_expected_files_for_apply_task": [
        "utils/ci_watch_handoff_runner.py",
        "utils/ci_watch_handoff_schema.py",
        "tests/test_ci_watch_handoff_classify.py",
        "tests/test_ci_watch_handoff_callback.py",
        "tests/fixtures/poll_history/*.json"
      ],
      "step_4": "29C74592 workspace 는 사고 박제 보존용 — 수정 0 · 신규 schedule 로 watcher 발사",
      "step_5": "Fix #4 (non-Critical7 gates FAILURE 처리 정책) 는 별도 1:1 회장 verbatim 결정 필요 (A/B/C 옵션)"
    }
  },
  "incident_facts": {
    "schedule_id": "29C74592",
    "pr_number": 149,
    "pr_head_committed_utc": 1779714136,
    "expected_head": "4bb627fe9252acacc1c32007211807fe9905809f",
    "max_polls": 30,
    "poll_interval_sec": 120,
    "max_watch_minutes": 60,
    "actual_terminal_state": "LOOP_BOUNDARY",
    "actual_terminal_reason": "max polls reached, elapsed 3524s",
    "actual_elapsed_sec": 3524,
    "polls_completed": 30,
    "callback_arrived": true,
    "callback_source": "schedule_history/29C74592.log (status=ok, duration 4142s · 별개 schedule 부수효과)",
    "decisive_poll": 12,
    "decisive_poll_t_offset_sec": 1336,
    "decisive_poll_elapsed_min": 22.27,
    "decisive_poll_state_transition": {
      "before_poll12": {"unresolved": 0, "gemini_fresh": false, "gemini_at": "2026-05-25T12:40:36Z"},
      "from_poll12": {"unresolved": 3, "gemini_fresh": true, "gemini_at": "2026-05-25T13:39:36Z", "head_match": true}
    },
    "wasted_polls_after_decisive": 18,
    "wasted_time_after_decisive_min": 36.4
  },
  "expected_files_status": {
    "memory/specs/pr_watcher_terminal_callback_root_cause_packet_260525.md": "created",
    "memory/specs/pr_watcher_terminal_callback_root_cause_analysis_260525.md": "created",
    "memory/specs/pr_watcher_terminal_callback_fix_diff_preview_260525.md": "created",
    "memory/specs/pr_watcher_terminal_callback_regression_suite_260525.md": "created",
    "memory/events/task-2670.pr-watcher-terminal-callback-rca-result-260525.json": "this file",
    "memory/events/task-2670.done": "pending (after callback cron register)",
    "memory/reports/task-2670.md": "created"
  },
  "anu_callback_cron": {
    "method": "cokacdir --cron (envelope only) · ANU key c119085addb0f8b7 · self-key 0 · UTF-8 ≤3900 bytes · absolute timestamp now+30s",
    "schedule_id": "1BA839D2",
    "schedule_type": "absolute",
    "fire_at": "2026-05-26 00:34:30",
    "envelope_bytes": 1449,
    "envelope_within_3900": true,
    "chat_id": 6937032012,
    "anu_key_used": "c119085addb0f8b7",
    "self_key_used": false,
    "once": true
  },
  "anchors": [
    "root cause + fix packet only · 즉시 코드 수정 0 · watcher.py 변경 0",
    "dev7 watcher 자기 분석 모순 회피 · executor dev8 라 (task-2666 COMPLETED 후 슬롯 자유)",
    "watcher.py read-only 분석 + poll_history 30 + _history.json 검토",
    "fix 적용은 본 packet 박제 후 별도 회장 verbatim 강제",
    "task-2662~2669 파일 충돌 0 · prefix pr_watcher_terminal_callback_* 차별화"
  ]
}
