{
  "schema": "reconcile_evidence_json_schema_proposal.v1",
  "task_name": "task-2624 범위 A — RECONCILE_EVIDENCE_CONTRACT_DRY_RUN",
  "ts_kst": "2026-05-21 10:10 KST",
  "mode": "read-only · proposal-only · production 코드 수정 0",
  "baseline_3way_verified": {
    "post_merge_smoke_runner.py": {"blob": "a2c69bca117e7c756b8a93b35464aeb1d46f0687", "lines": 590, "clean": true},
    "lifecycle_reconciliation_manager.py": {"blob": "2ccfe44f5fa57f4b2964f9570081115631661717", "lines": 1932, "clean": true}
  },
  "current_state_facts": {
    "post_merge_smoke_output": {
      "method": "PostMergeSmokeRun.to_json() (L132-133)",
      "main_behavior": "print(run.to_json()) → stdout only (L579)",
      "file_write": "NONE — 표준 evidence file write 결선 0",
      "status_enum_5": ["PASS", "FAIL", "SKIPPED", "TIMEOUT", "BLOCKED"],
      "rich_fields": ["status", "smoke_command", "stdout_tail", "stderr_tail", "failure_reason", "duration_ms", "timestamp", "merge_commit", "stale", "allow_continuation"]
    },
    "reconcile_smoke_lookup": {
      "source_path": "memory/events/{task_id}.qc-result (lifecycle_reconciliation_manager.py L711)",
      "method": "content = qc_file.read_text().upper() → substring 'PASS'/'FAIL'/'SKIPPED' (L714-720)",
      "recognized_status_3": ["PASS", "FAIL", "SKIPPED"],
      "field": "LifecycleEvidence.smoke_status (단순 string)"
    },
    "gap": "post_merge_smoke 가 qc-result file 에 write 하지 않음 → reconcile 이 smoke evidence 못 봄. + status enum mismatch (5 vs 3): TIMEOUT/BLOCKED → reconcile else→SKIPPED 오분류 위험"
  },
  "proposed_evidence_contract": {
    "decision": "single-sided 우선 + reconcile status mapping 보정 (양쪽 최소)",
    "evidence_file_path": "memory/events/{task_id}.qc-result",
    "rationale_path": "reconcile 이 이미 이 path 를 source-of-truth 로 읽음 → post_merge_smoke 가 같은 path 에 write 하면 path contract 자동 성립 (신규 path 발명 불요)",
    "proposed_qc_result_format": {
      "line1_marker": "SMOKE_STATUS=<PASS|FAIL|SKIPPED|TIMEOUT|BLOCKED>",
      "line2_marker": "MERGE_COMMIT=<sha>",
      "line3_marker": "TASK_ID=<task_id>",
      "line4_marker": "TS=<iso8601>",
      "body": "post_merge_smoke to_json() full payload (rich fields · redacted)",
      "redaction": "stdout_tail/stderr_tail 에 token/credential 매칭 시 [REDACTED]"
    },
    "reconcile_status_mapping_fix": {
      "current": "PASS→PASS / FAIL→FAIL / else→SKIPPED",
      "proposed": "PASS→PASS / FAIL→FAIL / TIMEOUT→FAIL / BLOCKED→FAIL / SKIPPED→SKIPPED",
      "rationale": "TIMEOUT/BLOCKED 는 smoke 미통과이므로 reconcile 이 SKIPPED(통과 동급) 로 오분류하면 안 됨 → FINALIZED 오전이 위험"
    }
  },
  "schema_v1": {
    "schema_name": "post_merge_smoke_qc_result.v1",
    "first_line_contract": "SMOKE_STATUS=<enum> (reconcile substring 매칭 + 명시 마커 양립)",
    "fields": {
      "smoke_status": "PASS|FAIL|SKIPPED|TIMEOUT|BLOCKED",
      "merge_commit": "string (40 char)",
      "task_id": "string",
      "ts": "iso8601",
      "smoke_command": "list[str] | null",
      "duration_ms": "int",
      "stdout_tail": "string (redacted, capped)",
      "stderr_tail": "string (redacted, capped)",
      "failure_reason": "string | null",
      "stale": "bool",
      "allow_continuation": "bool"
    },
    "write_authority": "post_merge_smoke_runner only · atomic temp+rename · append/overwrite per task_id",
    "read_authority": "lifecycle_reconciliation_manager (gather_evidence smoke lookup) + 기존 qc-result 소비자"
  },
  "backward_compat_note": "기존 qc-result file 형식 (다른 producer 가 쓰던 경우) 과 충돌 검토 필요 — B 범위에서 grep 으로 qc-result writer 전수 확인 후 진행",
  "critical7_assessment": {"is_critical7": false, "rationale": "read-only proposal · 코드 변경 0"},
  "scope_invariants_preserved": [
    "read-only", "proposal-only", "production 코드 수정 0",
    "post_merge_smoke_runner.py 변경 0", "lifecycle_reconciliation_manager.py 변경 0",
    "PR/merge/branch/credential write 0", "Track C 미접촉",
    "task-2623 superseded artifacts 삭제 0"
  ]
}
