{
  "schema": "reconcile_evidence_B_scope_estimate.v1",
  "task_name": "task-2624 범위 A → B 산정",
  "ts_kst": "2026-05-21 10:15 KST",
  "mode": "read-only · proposal-only · B 미승인",
  "critical_finding_backward_compat": {
    "discovery": "memory/events/{task_id}.qc-result 는 이미 QC gate 산출물 (teams/shared/qc_verify.py --gate L594 + scripts/finish-task.sh L336/L381 + memory/task-timer.py --qc-result)",
    "implication": "reconcile L711 이 읽는 'smoke_status' 는 실은 머지 前 QC gate 결과지 post-merge smoke 결과가 아님. 두 개념 conflate.",
    "single_sided_rejected": "post_merge_smoke 가 같은 qc-result 에 write 하면 QC gate 산출물과 충돌 (REF5 현실화) → single-sided 불가",
    "corrected_approach": "post-merge smoke 전용 evidence path 분리 + reconcile 별도 lookup field"
  },
  "B_scope_definition": {
    "expected_files": [
      "utils/post_merge_smoke_runner.py (전용 evidence file write 추가)",
      "utils/lifecycle_reconciliation_manager.py (post_merge_smoke 전용 lookup + LifecycleEvidence 필드 + RECONCILING transition 반영)",
      "tests/regression/test_reconcile_evidence_contract_2624.py (신규 regression)"
    ],
    "expected_files_count": 3,
    "loc_estimate": {
      "post_merge_smoke_runner": "+~20 LOC (run_post_merge_smoke 완료 시 또는 main() 에서 memory/events/{task_id}.post-merge-smoke.json atomic write + redaction)",
      "lifecycle_reconciliation_manager": "+~30 LOC (LifecycleEvidence.post_merge_smoke_status 필드 + gather_evidence 별도 lookup + RECONCILING→FINALIZED/ESCALATED transition 반영)",
      "test": "+~90 LOC (10 fixtures)",
      "total_production": "~50 LOC",
      "total_with_test": "~140 LOC"
    },
    "evidence_path_proposed": "memory/events/{task_id}.post-merge-smoke.json (QC gate qc-result 와 분리 — 충돌 0)",
    "merge_policy": "tiered",
    "forbidden_paths": [
      "memory/events/{task_id}.qc-result (QC gate 영역 — 건드리지 말 것)",
      "teams/shared/qc_verify.py (QC gate producer 변경 0)",
      "scripts/finish-task.sh (변경 0)",
      ".github/workflows/*", "anu_v2/**", "dispatch/**"
    ]
  },
  "regression_fixture_list": [
    "REV1 — PASS path/timing (post-merge-smoke.json 생성 → reconcile FINALIZED)",
    "REV2 — FAIL (reconcile ESCALATED)",
    "REV3 — TIMEOUT → FAIL mapping (오분류 방지)",
    "REV4 — BLOCKED → FAIL mapping",
    "REV5 — first-line marker 우선 (substring false-positive 방지)",
    "REF1 — evidence 부재 → STUCK 잔류 (안전 측)",
    "REF2 — evidence 손상 → None + 로그",
    "REF3 — 레거시 형식 fallback",
    "REF4 — SKIPPED → FINALIZED 허용 정책 (회장 결정)",
    "REF5 — QC gate qc-result 와 분리 검증 (충돌 0)"
  ],
  "regression_risk": {
    "level": "LOW-MEDIUM",
    "rationale": "production 모듈 2개 변경 · 단 신규 path 분리(post-merge-smoke.json) 로 기존 QC gate(qc-result) 무영향 · reconcile 기존 smoke_status(QC gate) lookup 보존 + post_merge_smoke_status 신규 필드 추가 (additive)",
    "existing_tests_to_protect": [
      "tests/test_task_timer_qc.py",
      "anu_v2/tests/test_post_merge_smoke_runner_2539.py",
      "lifecycle_reconciliation_manager 기존 regression"
    ],
    "mitigation": "additive only (기존 smoke_status 필드/lookup 불변 · 신규 field/path 추가) · QC gate 충돌 0 검증 fixture(REF5)"
  },
  "policy_decisions_for_chair": [
    "REF4: post-merge smoke SKIPPED (smoke_command 미정의 + dry_run) 시 reconcile FINALIZED 허용 여부",
    "smoke_command registry 확장 정책 (task별 smoke_command 정의 의무화 여부)",
    "post-merge-smoke.json 과 qc-result 의 명확한 역할 분리 문서화"
  ],
  "critical7_assessment": {"is_critical7": false, "rationale": "범위 산정 proposal · 코드 변경 0"},
  "scope_invariants_preserved": [
    "read-only", "proposal-only", "production 코드 수정 0",
    "B 미승인", "PR/merge/credential write 0", "Track C 미접촉"
  ]
}
