{
  "schema": "task-2680.callback_self_key_hardening_fix_result.v1",
  "task_id": "task-2680",
  "chair_authorization_id": "CHAIR-AUTH-CALLBACK-SELF-KEY-HARDENING-FIX-20260526-JJONGS-IMPLEMENT-001",
  "completion_state": "CALLBACK_SELF_KEY_REGISTRATION_HARDENING_FIX_IMPLEMENTED",
  "executor": "dev2 오딘",
  "date": "2026-05-26",
  "merge_policy": "fix_implementation_separate_pr_no_merge_chair_signature_required",
  "auto_progress": false,
  "chair_approval_required_for_merge": true,
  "modified_files": [
    "utils/callback_authority_4source_validator.py (신설 · 470 lines)",
    "utils/anu_callback_registrar.py (★ _build_cokacdir_cron_argv 내부 _assert + assert_cron_argv_uses_anu_key 신설)",
    "utils/callback_collector_helper_integration.py (★ classify_collector_authority_4source + emit_anu_independent_reverify_request wiring 추가)",
    "dispatch/normal_fallback_callback_helper.py (★ assert_argv_uses_anu_key 신설 + build_anu_owned_callback_request 의 argv post-build verifier 추가)",
    "tests/callback_authority_4source/__init__.py (신설)",
    "tests/callback_authority_4source/test_4source_validator.py (신설 · 29 케이스)",
    "memory/specs/system_callback_authority_4source_verify_doctrine_260526.md (신설)",
    "memory/events/task-2680.callback-self-key-hardening-fix-result-260526.json (본 파일)",
    "memory/events/task-2680.done",
    "memory/reports/task-2680.md"
  ],
  "six_goals_evidence": {
    "1_task_md_anu_vs_actual_self_key_prevention": {
      "code_hooks": [
        "utils/anu_callback_registrar.py:_build_cokacdir_cron_argv (argv builder 내부 fail-closed)",
        "utils/callback_authority_4source_validator.py:classify_collector_authority (post-fire detection)"
      ],
      "regression_tests": [
        "test_r1_track_a_self_key_detected_classification_self_collector",
        "test_r1_track_j_self_key_detected",
        "test_r1_anu_authoritative_when_only_anu_registered"
      ],
      "verdict": "PASS"
    },
    "2_helper_key_cron_layer_enforcement": {
      "code_hooks": [
        "utils/anu_callback_registrar.py:assert_cron_argv_uses_anu_key (신설 strict gate)",
        "dispatch/normal_fallback_callback_helper.py:assert_argv_uses_anu_key (신설 verdict dict)",
        "dispatch/normal_fallback_callback_helper.py:build_anu_owned_callback_request (post-build argv check 추가)"
      ],
      "regression_tests": [
        "test_r2_registrar_argv_builder_rejects_self_key",
        "test_r2_registrar_argv_builder_accepts_anu_key",
        "test_r2_assert_cron_argv_uses_anu_key_strict",
        "test_r2_helper_assert_argv_uses_anu_key_returns_dict",
        "test_r2_build_anu_owned_callback_request_self_key_fails",
        "test_r2_build_anu_owned_callback_request_anu_key_passes"
      ],
      "verdict": "PASS"
    },
    "3_actual_owner_key_callback_collector_gate": {
      "code_hooks": [
        "utils/callback_collector_helper_integration.py:classify_collector_authority_4source (wiring)",
        "utils/callback_authority_4source_validator.py:classify_collector_authority (4-source query)"
      ],
      "regression_tests": [
        "test_r3_collector_gate_calls_4source_validator",
        "test_r3_actual_owner_key_overrides_envelope_text"
      ],
      "verdict": "PASS"
    },
    "4_self_key_callback_auto_classification_non_authoritative": {
      "code_hooks": [
        "utils/callback_authority_4source_validator.py:NON_AUTHORITATIVE_SELF_COLLECTOR enum",
        "utils/callback_authority_4source_validator.py:classify_from_observed",
        "utils/callback_authority_4source_validator.py:is_self_key_callback"
      ],
      "regression_tests": [
        "test_r4_classify_from_observed_self_key",
        "test_r4_classify_from_observed_anu",
        "test_r4_classify_from_observed_unknown_3rd_key_drift",
        "test_r4_classify_from_observed_none_undetermined",
        "test_r4_classify_from_observed_envelope_prompt_drift",
        "test_r4_reverify_trigger_membership"
      ],
      "verdict": "PASS"
    },
    "5_anu_independent_reverify_flow_enforcement": {
      "code_hooks": [
        "utils/callback_authority_4source_validator.py:build_anu_independent_reverify_request",
        "utils/callback_authority_4source_validator.py:ReverifyRequest dataclass",
        "utils/callback_collector_helper_integration.py:emit_anu_independent_reverify_request"
      ],
      "regression_tests": [
        "test_r5_build_reverify_request_for_self_collector",
        "test_r5_no_reverify_request_for_authoritative",
        "test_r5_emit_anu_independent_reverify_request_self_collector",
        "test_r5_emit_no_reverify_for_authoritative"
      ],
      "verdict": "PASS"
    },
    "6_regression_4source_cross_check_collector_gate": {
      "regression_tests": [
        "test_r6_history_gap_undetermined",
        "test_r6_dual_owner_key_drift",
        "test_r6_prompt_drift_envelope_text_not_anu",
        "test_r6_subprocess_query_error_undetermined",
        "test_r6_evidence_has_4_sources",
        "test_r6_to_json_roundtrip",
        "test_track_a_91DDBCDA_78F385CF_dev4_self_key_full_flow",
        "test_track_j_A6200C2F_33E60E8B_dev5_self_key_full_flow"
      ],
      "verdict": "PASS"
    }
  },
  "regression_suite_summary": {
    "test_path": "tests/callback_authority_4source/test_4source_validator.py",
    "total_cases": 29,
    "passed": 29,
    "failed": 0,
    "duration_sec": 0.20,
    "command": "WORKSPACE_ROOT=$(pwd) python3 -m pytest tests/callback_authority_4source/ -v --tb=short"
  },
  "file_overlap_audit": {
    "pr_149_files_modified": 0,
    "pr_150_files_modified": 0,
    "task_2662_to_2679_event_overlap": 0,
    "forbidden_action_count": 0,
    "evidence": [
      "utils/anu_codex_micro_refinement_loop.py 변경 0 (PR #149)",
      "utils/codex_cc_decision_loop.py 변경 0 (PR #149)",
      "utils/pr_watcher_terminal_state_classifier.py 변경 0 (PR #150)",
      "tests/anu_codex_micro_refinement_loop/** 변경 0 (PR #149)",
      "tests/pr_watcher_terminal_state_classifier/** 변경 0 (PR #150)",
      "dispatch.py 변경 0",
      "Axis runtime 변경 0",
      ".github/** 변경 0",
      "hooks/** 변경 0",
      "live settings.json 변경 0",
      "scripts/finish-task.sh 변경 0"
    ]
  },
  "4source_doctrine_evidence": {
    "S1_schedule_history": "/home/jay/.cokacdir/schedule_history/<sid>.log → utils.callback_authority_4source_validator._read_schedule_history",
    "S2_cron_history": "cokacdir --cron-history <sid> --key <K> (ANU+self 2회 query) → utils.callback_authority_4source_validator._query_cron_history",
    "S3_envelope": "S1.prompt body parse → utils.callback_authority_4source_validator._parse_envelope_from_prompt",
    "S4_result_artifact": "memory/events/<task_id>.*-result-*.json → utils.callback_authority_4source_validator._read_result_artifact",
    "classification_transition_table_test": "tests/callback_authority_4source/test_4source_validator.py (R6 6 케이스 + Track A/J 2 케이스 1:1 재현)"
  },
  "pr_status_at_completion": "PR #151 opened (https://github.com/Jeon-Jonghyuk/dev_workspace/pull/151) — separate branch task/task-2680-dev2 · merge requires separate chair signature",
  "anu_normal_callback": {
    "schedule_id": "EEC6F294",
    "anu_key_used": "c119085addb0f8b7",
    "self_key_used": false,
    "fire_at_absolute_ts": "2026-05-26 03:01:22",
    "envelope_utf8_bytes": 669,
    "envelope_under_3900_limit": true,
    "registration_status": "REGISTERED",
    "helper_routed": true,
    "cron_layer_key_strict_gate_verified": "PASS — assert_cron_argv_uses_anu_key (task-2680 수정 목표 2)",
    "argv_first_3": "['/usr/local/bin/cokacdir', '--cron', '<envelope_json>']",
    "argv_key_value": "c119085addb0f8b7"
  },
  "pr_url": "https://github.com/Jeon-Jonghyuk/dev_workspace/pull/151",
  "recommended_next_action": [
    "회장 별도 chair signature 발급 (CHAIR-AUTH-CALLBACK-SELF-KEY-HARDENING-MERGE-... 신규 ID)",
    "PR review (Gemini · OWNER PAT 보유 시)",
    "merge 시 main 의 utils/callback_collector_helper_integration.py 와 충돌 가능성 — main divergence 5 commits 검토 필요 (origin/main 기반 branch)",
    "merge 후 봇 finalize 경로 (extract_followup / finish-task.sh) wiring 별도 task 권장 — 본 packet 은 helper layer + wiring layer 까지만"
  ],
  "scope_invariants_preserved": [
    "merge_policy=fix_implementation_separate_pr_no_merge_chair_signature_required",
    "PR #149 코드 변경 0",
    "PR #150 코드 변경 0",
    "task-2662~2679 event overlap 0",
    "Axis runtime 변경 0",
    "live settings.json 변경 0",
    "hooks live 변경 0",
    "dispatch.py 변경 0",
    "auto-merge 0",
    "기존 PR merge 0"
  ]
}
