{
  "schema": "anu.fallback_acceptance_criteria.v1",
  "task_id": "task-2553+58",
  "track": "TRACK C — FALLBACK_ACCEPTANCE_CRITERION_FOR_NEXT_PILOT",
  "ts_kst": "2026-05-18 22:10 KST",
  "authority": "회장 §2 verbatim (memory/tasks/task-2553+58.md sha256 976d904dbe05971fad694ca0409d0cdbcd6cdc31434ac156371770ed9ea40f71). 다음 pilot 의 live acceptance criterion. 기준 정의·schema·검증 entrypoint 산출만 — 실 cron 강제삭제 0·실 dispatch 0.",
  "goal": "다음 pilot 에서 normal callback durable-success 이후 bound fallback 처리 기준을 명확히 한다.",
  "applicability": {
    "scope": "normal callback durable-success 가 선행하고, 그 task 에 bound fallback 이 존재하는 경우에만 본 운영 품질 기준을 적용한다.",
    "out_of_scope": "durable-success 가 선행하지 않은 fallback 발화는 정당 recovery 이며 본 품질 기준 비적용 → verdict=NOT_APPLICABLE. bound fallback 부재 시에도 NOT_APPLICABLE.",
    "trigger_doctrine": "fallback 은 절대 진행 트리거가 아니다 (회장 doctrine·+55 핵심원칙: registry_completed_event 만 progress trigger). 고정시각/dead-man/fallback 진행 트리거 0."
  },
  "criterion_a": {
    "id": "a",
    "name": "CANCEL_ON_SUCCESS_REMOVED",
    "definition": "normal callback durable-success 이후 bound fallback 이 cancel-on-success 로 제거된다 (발화 전 cron-remove). +37/+45 cancel-on-success live wiring 의 정상 종착.",
    "detected_by": "observation.cancel_on_success_applied == true AND observation.fallback_fired != true (제거되어 발화하지 않음).",
    "operational_quality": "PASS",
    "safety": "OK (normal_success_unchanged 디커플 불변 — cron-remove 실패/skip 이 normal success 를 뒤집지 않음, +45 9-R Layer A/B)."
  },
  "criterion_b": {
    "id": "b",
    "name": "REGISTRY_NON_BLOCKING_EXPLICIT_MARK",
    "definition": "cancel-on-success 로 제거되지 않은 잔존 bound fallback 이 registry 에 NON_BLOCKING(또는 LEGACY_PENDING)으로 schema-valid 하게 명시 마크된다.",
    "schema_ref": "schemas/non_blocking_fallback_schema.json",
    "schema_id": "schemas/non_blocking_fallback_schema.json",
    "schema_title": "task-2553+58.non_blocking_fallback_mark_v1",
    "detected_by": "observation.registry_non_blocking_mark 가 non_blocking_fallback_schema 에 valid 하고, mark.task_id == observation.task_id 이며 mark.fallback_cron_id == observation.fallback_cron_id (semantic_binding).",
    "semantic_binding": "schema 통과만으로 부족 — 마크가 가리키는 task/fallback_cron_id 가 관측 대상과 일치해야 기준 (b) 충족. 불일치 마크는 기준 (b) 미충족(무관 마크).",
    "operational_quality": "PASS",
    "safety": "OK (마크는 fallback safety path 를 약화하지 않음 — normal_success_unchanged const true·progress_trigger const false)."
  },
  "anti_pattern": {
    "id": "duplicate_ignored_only",
    "name": "UNMARKED_FALLBACK_THEN_DUPLICATE_CALLBACK_IGNORED_ONLY",
    "definition": "아무 마크 없이(criterion a/b 모두 미충족) fallback 이 발화한 뒤 DUPLICATE_CALLBACK_IGNORED(또는 NO-ACTION)로만 처리되는 것.",
    "safety": "OK (안전성은 보장 — normal_success_unchanged true).",
    "operational_quality": "FAIL — 운영 품질 PASS 로 보지 않는다 (회장 §2 verbatim). 차단성 결함은 아니나 깔끔히 닫히지 않은 legacy 잔여 (legacy-pending-fallback-inventory verdict 와 정합).",
    "precedent": "task-2553+49 CD2E3ACC (수렴 후 dead-man 발화 → NO-ACTION/additive disposition·파괴 0) / +50/+51/+52 ANU-key dead-man @22:05 → NO-ACTION 예상. 안전 처리 OK 이나 cancel-on-success 미적용·NON_BLOCKING 마크 부재로 redundant 발화."
  },
  "safety_invariant": {
    "rule": "normal_success_unchanged 는 본 기준의 전제이자 디커플 절대불변. observation.normal_success_unchanged != true 이면 기준 a/b 평가 이전에 verdict=SAFETY_FAIL (hard, fail-closed). 본 품질 기준은 '안전성 OK' 를 전제로 한 운영 품질 게이트이며 safety path 를 대체/약화하지 않는다 (§5).",
    "decouple_basis": "+45 cancel_on_success_audit 9-R Layer A/B — cron-remove 실패/skip/exception 이 normal collector success 를 절대 뒤집지 않는다."
  },
  "verdicts": [
    "OPERATIONAL_PASS",
    "OPERATIONAL_QUALITY_FAIL",
    "NOT_APPLICABLE",
    "SAFETY_FAIL"
  ],
  "decision_table": [
    {"when": "normal_success_unchanged != true", "verdict": "SAFETY_FAIL", "note": "fail-closed; 기준 a/b 평가 이전"},
    {"when": "durable-success 미선행 OR bound fallback 부재", "verdict": "NOT_APPLICABLE", "note": "정당 recovery / 적용 대상 아님"},
    {"when": "criterion_a 충족 (cancel-on-success 제거·미발화)", "verdict": "OPERATIONAL_PASS", "satisfied_criterion": ["a"]},
    {"when": "criterion_b 충족 (NON_BLOCKING schema-valid·binding 일치)", "verdict": "OPERATIONAL_PASS", "satisfied_criterion": ["b"]},
    {"when": "a·b 동시 충족", "verdict": "OPERATIONAL_PASS", "satisfied_criterion": ["a", "b"]},
    {"when": "a/b 모두 미충족 AND fallback 발화 AND handling ∈ {DUPLICATE_CALLBACK_IGNORED, NO-ACTION}", "verdict": "OPERATIONAL_QUALITY_FAIL", "reason": "DUPLICATE_IGNORED_ONLY_NO_MARK (회장 §2 anti_pattern)"},
    {"when": "a/b 모두 미충족 AND fallback 미발화 (제거도 마크도 없음)", "verdict": "OPERATIONAL_QUALITY_FAIL", "reason": "UNMARKED_NO_CANCEL_NO_NONBLOCK"},
    {"when": "a/b 모두 미충족 AND fallback 발화 AND handling ∉ {DUPLICATE_CALLBACK_IGNORED, NO-ACTION}", "verdict": "OPERATIONAL_QUALITY_FAIL", "reason": "UNMARKED_FALLBACK_NONIDLE_DISPOSITION"}
  ],
  "mutual_exclusivity": "criterion (a) 와 (b) 는 fallback 의 동일 잔존 상태에 대한 상호배타 경로 — 제거되었으면 (a)(별도 NON_BLOCKING 마크 불요·schema cancel_on_success_applied const false), 제거 안 됐으면 (b) 명시 마크. 둘 다 충족 시 PASS (satisfied=[a,b]).",
  "entrypoint": {
    "module": "scripts/validate_fallback_acceptance_2553plus58.py",
    "function": "evaluate_fallback_acceptance",
    "coherence_function": "check_criteria_schema_coherence",
    "schema_validator": "validate_non_blocking_mark",
    "note": "문서-only 금지 — 본 기준은 실 entrypoint 로 판정 가능하며 regression 이 실 entrypoint 를 직접 호출(mock-only FAIL)."
  },
  "pilot_adoption": {
    "applies_to": "다음 runtime structure pilot (task-2553+57 NEXT_RUNTIME_STRUCTURE_PILOT_PLAN 의 live acceptance criterion).",
    "live_criterion": "pilot 종료 시 각 dispatch 에 대해 normal callback durable-success 이후 bound fallback 이 (a) cancel-on-success 제거 OR (b) registry NON_BLOCKING 명시 마크 중 하나를 만족해야 pilot 운영 품질 PASS. 마크 없는 DUPLICATE_CALLBACK_IGNORED-only = 품질 FAIL(안전성 FAIL 아님).",
    "remediation_north_star": "cancel-on-success live adoption(+37/+45)이 본질 해소 → 기준 (a) 가 default 경로. live adoption 전까지는 기준 (b) 명시 마크가 최소 운영 품질 요건."
  },
  "references": {
    "legacy_pending_fallback_inventory": "memory/events/task-2553.legacy-pending-fallback-inventory_260518.json (findings.7 future_requirement 의 정식 기준화)",
    "plus37_dup_ignored_precedent": "memory/events/task-2553+37.fallback-duplicate-callback-ignored_260518.json (anti_pattern 실 선례)",
    "plus45_cancel_audit_decouple": "schemas/cancel_on_success_audit.schema.json (normal_success_unchanged 디커플 불변 근거)",
    "anu_key_code_canon": "+49 코드 정본 — callback owner/key = ANU key c119085addb0f8b7, executor self key 금지",
    "four_track_batch": "memory/events/task-2553-4track-ABCD-final-batch-registry-addendum_260518.json (Track C)"
  },
  "hold_for_chair": false,
  "no_actor_attribution_change": true
}
