{
  "schema": "reconcile_evidence_dry_run_fixture_matrix.v1",
  "task_name": "task-2624 범위 A — RECONCILE_EVIDENCE_CONTRACT_DRY_RUN",
  "ts_kst": "2026-05-21 10:10 KST",
  "mode": "fixture design · dry-run · 실 execution 0 · production 코드 수정 0",
  "purpose": "evidence path/schema/timing 가정 + reconcile 실패 케이스를 fixture 로 실증 (회장 필수 #4, #5)",
  "path_timing_fixtures": [
    {
      "fixture_id": "REV1",
      "category": "path_timing",
      "scenario": "post_merge_smoke PASS → qc-result file write (제안 contract) → reconcile gather_evidence smoke_status=PASS",
      "current_behavior": "post_merge_smoke 는 stdout print only → qc-result file 미생성 → reconcile smoke_status=None (qc_file.exists()=False)",
      "expected_after_B": "qc-result file 생성 → reconcile smoke_status=PASS → RECONCILING→FINALIZED 가능",
      "verdict_current": "GAP_CONFIRMED (path 단절)"
    },
    {
      "fixture_id": "REV2",
      "category": "schema",
      "scenario": "post_merge_smoke FAIL → qc-result 'SMOKE_STATUS=FAIL' → reconcile smoke_status=FAIL",
      "current_behavior": "qc-result 미생성 → reconcile None",
      "expected_after_B": "reconcile smoke_status=FAIL → RECONCILING→ESCALATED (Critical7)",
      "verdict_current": "GAP_CONFIRMED"
    },
    {
      "fixture_id": "REV3",
      "category": "schema_mismatch",
      "scenario": "post_merge_smoke TIMEOUT → qc-result 'SMOKE_STATUS=TIMEOUT'",
      "current_behavior": "reconcile substring: 'TIMEOUT' 에 'PASS'/'FAIL' 없음 → else → SKIPPED 오분류 (smoke 미통과인데 통과 동급)",
      "expected_after_B": "reconcile mapping fix: TIMEOUT→FAIL → ESCALATED",
      "verdict_current": "SCHEMA_MISMATCH_CONFIRMED (5 status vs 3 인식)"
    },
    {
      "fixture_id": "REV4",
      "category": "schema_mismatch",
      "scenario": "post_merge_smoke BLOCKED (smoke_command 미정의 + non-dry-run) → qc-result 'SMOKE_STATUS=BLOCKED'",
      "current_behavior": "reconcile substring: 'BLOCKED' → else → SKIPPED 오분류",
      "expected_after_B": "BLOCKED→FAIL mapping → ESCALATED",
      "verdict_current": "SCHEMA_MISMATCH_CONFIRMED"
    },
    {
      "fixture_id": "REV5",
      "category": "false_positive_substring",
      "scenario": "qc-result body 의 stderr_tail 에 'PASS' 단어 우연 포함 (smoke FAIL 인데)",
      "current_behavior": "reconcile content.upper() substring 'PASS' in content → smoke_status=PASS 오판 (FAIL 인데 PASS 로 읽음)",
      "expected_after_B": "first_line marker 'SMOKE_STATUS=FAIL' 우선 파싱 → robust",
      "verdict_current": "FALSE_POSITIVE_RISK_CONFIRMED (substring 느슨 매칭)"
    }
  ],
  "reconcile_failure_fixtures": [
    {
      "fixture_id": "REF1",
      "scenario": "qc-result file 부재 (post_merge_smoke 미실행 or write 안 함)",
      "reconcile_behavior": "qc_file.exists()=False → smoke_status=None",
      "lifecycle_outcome": "CI_PASS_BUT_NOT_FINALIZED 또는 STUCK_NEEDS_RECONCILE 잔류 (smoke evidence 없어 FINALIZED 차단)",
      "is_correct_behavior": true,
      "note": "현재 동작이 안전 측 (evidence 없으면 HOLD) — 단 정상 PASS 인데도 qc-result 미생성 시 false STUCK"
    },
    {
      "fixture_id": "REF2",
      "scenario": "qc-result file 손상 (read 에러)",
      "reconcile_behavior": "except → smoke_status=None (L721-722)",
      "lifecycle_outcome": "STUCK 잔류 + 로그",
      "is_correct_behavior": true
    },
    {
      "fixture_id": "REF3",
      "scenario": "qc-result file 존재하나 SMOKE_STATUS 마커 없는 레거시 형식",
      "reconcile_behavior": "substring PASS/FAIL 검색 → 우연 매칭 or SKIPPED",
      "lifecycle_outcome": "비결정적 (레거시 호환 위험)",
      "is_correct_behavior": false,
      "note": "B 범위에서 first_line marker 우선 + 마커 부재 시 fallback 명시 필요"
    },
    {
      "fixture_id": "REF4",
      "scenario": "post_merge_smoke SKIPPED (smoke_command 미정의 + dry_run) → qc-result 'SMOKE_STATUS=SKIPPED'",
      "reconcile_behavior": "smoke_status=SKIPPED",
      "lifecycle_outcome": "정책 결정 필요 — SKIPPED 가 FINALIZED 허용인가 HOLD 인가",
      "is_correct_behavior": "POLICY_DECISION_NEEDED",
      "note": "회장 결정: smoke SKIPPED 시 reconcile FINALIZED 허용 여부"
    },
    {
      "fixture_id": "REF5",
      "scenario": "qc-result 가 다른 producer (기존 QC 파이프라인) 가 쓴 것과 충돌",
      "reconcile_behavior": "post_merge_smoke marker 와 기존 QC marker 혼재",
      "lifecycle_outcome": "비결정적",
      "is_correct_behavior": false,
      "note": "B 범위 선행 작업: qc-result writer 전수 grep 으로 충돌 확인"
    }
  ],
  "summary": {
    "total_fixtures": 10,
    "gap_confirmed": 2,
    "schema_mismatch_confirmed": 2,
    "false_positive_risk": 1,
    "reconcile_failure_safe": 2,
    "policy_decision_needed": 1,
    "legacy_compat_risk": 2
  },
  "dry_run_verdict": "PASS — gap/schema/timing 가정 모두 fixture 로 실증. evidence path 단절(REV1/REV2) + status enum mismatch(REV3/REV4) + substring false-positive(REV5) 확인. reconcile 실패 케이스(REF1/REF2)는 안전 측(HOLD) 동작.",
  "regression_implementation_proposal": {
    "test_file_candidate": "tests/regression/test_reconcile_evidence_contract_2624.py (B 범위 신규)",
    "execution_mode": "mock-based · 실 smoke 0 · 실 reconcile apply 0 · subprocess 0",
    "fixtures_data": "memory/fixtures/reconcile_evidence_*.json (REV1~REV5 + REF1~REF5)"
  },
  "critical7_assessment": {"is_critical7": false, "rationale": "fixture design only · 코드 변경 0"},
  "scope_invariants_preserved": [
    "fixture design only", "실 execution 0", "production 코드 수정 0",
    "post_merge_smoke_runner.py 변경 0", "lifecycle_reconciliation_manager.py 변경 0",
    "PR/merge/credential write 0", "Track C 미접촉",
    "task-2623 superseded artifacts 삭제 0"
  ]
}
