{
  "task_id": "task-2729",
  "phase": "2",
  "audit_type": "audit-report-first",
  "generated_at": "2026-06-04T08:18:00Z",
  "generated_by": "perun(dev6-team-lead) + Explore audit",
  "base_branch": "task/task-2729-progress-watcher-gate-dev6 (Phase1, NOT merged to main)",
  "work_branch": "task/task-2729-phase2-dev6",
  "principle": "code exists != automation works. IMPLEMENTED/VERIFIED/WIRED/ACTIVE separated. production ACTIVE transition needs separate chair approval. ALL axes ACTIVE=false.",
  "current_code_paths": {
    "completion_callback_fallback_cancel.py": {
      "exists": true,
      "key_functions": [
        "cancel_fallback_on_success() L368-556 (DI remover, durable-evidence verify, safe-remove 5 conditions)",
        "prune_fallbacks_for_key() L630-753 (registry-based idempotent prune, remover(cron_id, dry_run))",
        "PruneCause enum L562-568 (CANCEL_NOT_WIRED/CANCEL_FAILED/SCHEDULE_NOT_FOUND/STALE_ROUND/STALE_HEAD/NORMAL_CALLBACK_ALREADY_COLLECTED)",
        "RealCokacdirCronRemover L101-141 (subprocess wrapper, dry_run sim)"
      ],
      "wiring_state": "prune primitives EXIST; live-prune observation hook into collector success transaction needs explicit wiring + live observability record"
    },
    "normal_completion_callback_collector_entrypoint.py": {
      "exists": true,
      "key_functions": [
        "collect_and_prune() L57-140 (entrypoint; trigger in {normal_callback_collected,result_collected,envelope_confirmed,terminal_marker}; returns prune_outcomes/unwired)",
        "success transaction L87-97 (result_json_exists/result_json_status)",
        "prune call L100-110 (prune_fallbacks_for_key)"
      ],
      "wiring_state": "collect_and_prune already calls prune; need to ASSERT success-transaction gating (only prune on real success) + emit live prune outcome for Phase1 watcher fallback_prune tracking"
    },
    "ci_watch_handoff_runner.py": {
      "exists": true,
      "key_functions": [
        "WatcherState dataclass L61-86 (6 states incl fallback_prune)",
        "run_once() L186-206 (classify -> terminal_state, reason)",
        "fire_terminal_callback() L140-183 (build_callback_envelope -> register_terminal_callback)",
        "main() L209-238 (--dry-run/--once skeleton, ACTIVE=false, no live gh polling)"
      ],
      "wiring_state": "Phase1 watcher skeleton + terminal callback only. base-sync / owner_gemini fire / authoritative-completion pipeline ABSENT (Phase2 new). All new pipeline must live HERE (expected_files locked, no 6th file)."
    },
    "anu_v2/owner_gemini_trigger_router.py": {
      "exists": true,
      "reuse_for_new_file": "utils/owner_gemini_trigger.py NEW reuses: is_gemini_trigger_comment (body '/gemini review'), nudge_count_for_pr_head (dedupe, NUDGE_HARD_LIMIT_PER_PR_HEAD=1), head-lock (40-char hex), _audit_append (jsonl), token_provider hash (OWNER PAT no-raw)",
      "key_interface": "OwnerGeminiTriggerRouter.route_for_pr(pr_number,current_head_sha,owner,repo,task_id,decision_path,observed_comment) -> RouterResult(final_state,...)"
    },
    "merge_queue_executor.py": {
      "exists": true,
      "FORBIDDEN_TO_MODIFY": true,
      "callable_functions": [
        "sync_pr_base(_pr_branch, pr_workdir, runner, merge_state_status) L412-437 -> {performed,method,conflict}; BEHIND -> git merge origin/main --no-edit; rebase/force blocked by assert_no_forbidden_git_flags",
        "fetch_merge_state() L857-870 -> mergeStateStatus (behind detect)"
      ],
      "decision": "base-sync (defect5) wired by CALLING sync_pr_base/fetch_merge_state from runner. NO direct modification (would be 6th file -> CHAIR_REQUIRED)."
    },
    "repository_policy_adapter.py": {
      "exists": true,
      "FORBIDDEN_TO_MODIFY": true,
      "callable_functions": ["infer_token_source_from_actor() L162-180 -> installation_app|owner_pat|bot_pat|unknown", "assert_no_admin_override()"]
    },
    "tests/regression/test_progress_watcher_gate_2729.py": {
      "exists": true,
      "must_remain_green": ["test_gate_pass_watcher_registered", "test_fallback_only_incomplete", "test_fire_terminal_callback_success_runner", "test_six_state_tracking", "test_run_once_head_drift_returns_terminal"]
    }
  },
  "wiring_gaps_and_minimal_changes": {
    "defect7_live_prune_not_wired": {
      "file": "utils/completion_callback_fallback_cancel.py + utils/normal_completion_callback_collector_entrypoint.py",
      "minimal_change": "Ensure collector success transaction (real result success only) drives prune_fallbacks_for_key against registry pending fallback -> real cancel/tombstone via injectable remover. Add live prune outcome record (cause enum preserved) so Phase1 watcher fallback_prune is observable. Fake remover for test.",
      "no_active": true
    },
    "defect6_owner_gemini_trigger_not_wired": {
      "file": "utils/owner_gemini_trigger.py (NEW) + scripts/ci_watch_handoff_runner.py (wire call)",
      "minimal_change": "NEW dedicated entrypoint: hardcoded body '/gemini review', dedupe (head-lock + nudge limit), head-lock 40hex, audit jsonl, OWNER PAT (hash-only, request-only). Runner auto-fires on NEW head (request-only) + review-settle collection. No live gh (mock).",
      "no_active": true
    },
    "defect5_base_sync_required_before_merge": {
      "file": "scripts/ci_watch_handoff_runner.py (CALL merge_queue_executor.sync_pr_base, NO modify)",
      "minimal_change": "After merge approval, if PR BEHIND -> base-sync (update-branch via sync_pr_base, NOT admin override) -> re-validate -> merge. Abort branches on conflict / diff-over-limit / admin|force needed.",
      "no_active": true
    },
    "defect4_authoritative_completion_by_scope_evidence": {
      "file": "scripts/ci_watch_handoff_runner.py (in-file, NO new file)",
      "minimal_change": "On finish-task EXTERNAL_DIRTY block, authoritative scope evidence (merge-base clean + CI + LOCAL_FIX_VERIFIED) -> completion-recognition marker. NOT manual .done forgery (forgery count must be 0).",
      "no_active": true
    }
  },
  "expected_files_reconfirm": {
    "count": 5,
    "within_limit": true,
    "files": [
      "utils/completion_callback_fallback_cancel.py",
      "utils/normal_completion_callback_collector_entrypoint.py",
      "utils/owner_gemini_trigger.py (NEW)",
      "scripts/ci_watch_handoff_runner.py",
      "tests/regression/test_pr_convergence_pipeline_2729.py"
    ],
    "support_files_allowed": ["memory/state/automation_capability_matrix.json", "memory/reports/task-2729.md", "memory/events/task-2729-p2.audit.json", "memory/events/task-2729-p2.done"],
    "chair_required_triggers_avoided": ["merge_queue_executor.py direct modify -> AVOIDED (call-only)", "6th file (finish_task_completion_marker.py) -> AVOIDED (defect4 in runner)"]
  },
  "forbidden_compliance": {
    "no_admin_override": true,
    "no_force_push": true,
    "no_rebase": true,
    "no_production_active_true": true,
    "no_credential_anu_key_raw": true,
    "no_finish_task_sh_modify": true,
    "no_critical_gap_py_modify": true,
    "no_terminal_state_callback_modify": true,
    "no_merge_queue_executor_modify": true,
    "no_systemd_github_deploy_modify": true
  },
  "status": "AUDIT_COMPLETE — expected_files=5 within lock. Proceed to implementation (delegate to 스바로그/벨레스). ACTIVE=false fixed."
}
