{
  "schema": "reconcile_evidence_contract_proposal.v1",
  "track": "Track G — merge queue partial closure plan",
  "ts_kst": "2026-05-21 05:06 KST",
  "mode": "proposal-only · 실 코드 생성 0",
  "purpose": "14조건 #14 reconcile evidence configured 의 PARTIAL 잔여 closure — post_merge_smoke_runner ↔ lifecycle_reconciliation_manager evidence path contract 명문화",
  "current_state_assessment": {
    "lifecycle_reconciliation_manager_status": {
      "lines": 1932,
      "lifecycle_states": 7,
      "stuck_cases": 8,
      "extension_modules": ["BOT_CANCELLED 격상 4종 (task-2521)", "AUTO_FINALIZE_CHAIN_MISSING 4종 (task-2529)"],
      "evidence_source_of_truth": ["GitHub PR mergedAt", "CI status", "post-merge smoke", "task-timer", ".done/.done.acked markers"],
      "default_mode": "dry-run (--apply 없이 side effect 0)",
      "assessment": "FULLY_IMPLEMENTED · sole source for reconcile decision"
    },
    "post_merge_smoke_runner_status": {
      "lines": 590,
      "key_artifacts": ["SmokeStatus enum", "PostMergeSmokeRun dataclass", "task_id → smoke_command registry"],
      "critical7_path": "POST_MERGE_SMOKE_FAILED escalation",
      "assessment": "FULLY_IMPLEMENTED · smoke 단독 결선"
    },
    "gap_identified": "두 모듈은 각자 본질 결선 완비. 그러나 smoke 결과를 reconcile manager 의 evidence input 으로 흘려보내는 path contract (file location · schema · timing) 명문 부재 → 14조건 #14 'reconcile evidence configured' 의 PARTIAL 분류 사유"
  },
  "proposed_evidence_contract": {
    "evidence_file_path_pattern": "memory/events/post_merge_smoke_<task_id>.evidence.json",
    "schema": {
      "schema_name": "post_merge_smoke_evidence.v1",
      "task_id": "string",
      "ts_kst": "ISO8601",
      "pr_number": "int",
      "merge_commit_sha": "string (40 char)",
      "smoke_status": "SmokeStatus enum (PASS/FAIL/SKIPPED/TIMEOUT)",
      "smoke_command": "string (회장 verbatim hardcoded body)",
      "smoke_stdout_tail": "string (마지막 512 chars · redacted)",
      "smoke_stderr_tail": "string (마지막 512 chars · redacted)",
      "duration_ms": "int",
      "critical7_classification": "string | null",
      "reconcile_evidence_ready": "bool (true 인 경우 reconcile manager 가 finalize 진행)",
      "scope_invariants_preserved": ["list"]
    },
    "write_authority": "post_merge_smoke_runner 만 write — append-only · idempotent",
    "read_authority": "lifecycle_reconciliation_manager (RECONCILING state 진입 시 검색)",
    "ttl_policy": "{audit_root}/post_merge_smoke_<task_id>.evidence.json 무삭제 (audit append-only)",
    "redaction_invariant": "stdout/stderr tail 에 token/credential 매칭 시 [REDACTED] 치환"
  },
  "reconcile_manager_lookup_change_proposal": {
    "current_state": "8 stuck cases 중 CI_PASS_BUT_NOT_FINALIZED 가 smoke 미참조",
    "proposed_change": "RECONCILING state 진입 시: (a) post_merge_smoke_<task_id>.evidence.json 존재 여부 확인 → (b) smoke_status=PASS → reconcile_evidence_ready=true → FINALIZED 전이 / smoke_status=FAIL → ESCALATED + Critical7 / 파일 없음 → STUCK_NEEDS_RECONCILE 잔류 (HOLD)",
    "loc_estimate": "≤ 30 LOC (lookup helper + 1 transition guard)",
    "risk_class": "LOW · idempotent · dry-run preserved"
  },
  "post_merge_smoke_runner_change_proposal": {
    "current_state": "SmokeStatus 분기 + Critical7 escalation 결선됨 · evidence 파일 write 결선 부재",
    "proposed_change": "smoke 실행 완료 직후 (PASS/FAIL/SKIPPED/TIMEOUT 모두) evidence json append-only write (atomic temp + rename)",
    "loc_estimate": "≤ 25 LOC (write helper + redaction)",
    "risk_class": "LOW · 본 contract 외 동작 변경 0"
  },
  "non_goals": [
    "lifecycle_reconciliation_manager 7 lifecycle states 변경 (변경 0)",
    "8 stuck cases 명세 변경 (변경 0)",
    "post_merge_smoke_runner Critical7 escalation 변경 (변경 0)",
    "BOT_CANCELLED / AUTO_FINALIZE_CHAIN_MISSING 격상 모듈 변경 (변경 0)"
  ],
  "fixture_proposal": [
    {"id": "REC1", "scenario": "smoke PASS + evidence file 생성 + reconcile FINALIZED 전이", "expected_transition": "RECONCILING → FINALIZED"},
    {"id": "REC2", "scenario": "smoke FAIL + evidence file 생성 + reconcile ESCALATED 전이", "expected_transition": "RECONCILING → ESCALATED · Critical7"},
    {"id": "REC3", "scenario": "smoke evidence file 부재 (smoke 미실행)", "expected_state": "STUCK_NEEDS_RECONCILE 잔류 · HOLD"},
    {"id": "REC4", "scenario": "smoke evidence file 손상/parse 실패", "expected_state": "STUCK_NEEDS_RECONCILE + audit log error"},
    {"id": "REC5", "scenario": "smoke evidence file redaction 검증 (token-like string 포함)", "expected_redaction": "[REDACTED] 치환 후 write"}
  ],
  "expected_files_if_implemented": [
    "utils/post_merge_smoke_runner.py (변경: +25 LOC evidence write helper)",
    "utils/lifecycle_reconciliation_manager.py (변경: +30 LOC RECONCILING lookup helper)",
    "tests/test_post_merge_smoke_evidence_contract.py (신규 ~80 LOC · 5 fixtures)"
  ],
  "forbidden_paths": [
    ".github/workflows/* (변경 0)",
    "dispatch/__init__.py (task-2621 wiring intact 유지)",
    "anu_v2/* (변경 0)"
  ],
  "preconditions_for_chair_authorization": [
    "(a) 본 proposal ACCEPT",
    "(b) task ID 발행",
    "(c) expected_files anchor 정확 명시 (3 파일)",
    "(d) dispatch prompt 에 두 모듈 동시 변경 + idempotent + dry-run preserved 명문",
    "(e) regression test 5건 PASS 후 limited live merge pilot 진입 게이트 결합 가능"
  ],
  "auto_progress": false,
  "chair_approval_required": true,
  "scope_invariants_preserved": [
    "proposal-only", "실 코드 생성 0", "실 merge 0", "PR open 0",
    "smoke evidence write 0 (proposal 단계)", "reconcile apply 0",
    "GitHub write 0", "credential raw exposure 0"
  ]
}
