{
  "schema": "callback_prompt_byte_guard_proposal.v1",
  "ts_kst": "2026-05-20 22:00 KST",
  "mode": "proposal-only · 자동 진행 0 · 회장 명시 결정 대기 (runtime guard 구현은 별도 chair-authorized task)",
  "scope_of_proposed_guard": [
    "anu_v3/dispatch_callback_contract.py 내 callback 등록 helper(예: build_anu_owned_callback_request 호출 경로) 에 byte-측정 + threshold check 추가",
    "dispatch/normal_fallback_callback_helper.py:build_anu_owned_callback_request 에 prompt UTF-8 byte 측정 + 3900 hard limit fail-closed 추가",
    "현재 task 범위 아님 — 본 record 는 후보 설계만"
  ],
  "guard_logic_design": {
    "step_1_measure": "callback prompt 조립 직후: `byte_count = len(prompt.encode('utf-8'))` (★ NOT len(prompt) — bytes 측정)",
    "step_2_classify": {
      "under_3200": "OK — no log",
      "between_3201_3500": "OK_NEAR_RECOMMENDED — log info",
      "between_3501_3900": "WARNING — log warn · 등록은 진행 (관측)",
      "between_3901_4096": "HARD_LIMIT_VIOLATION — 등록 금지 · fail-closed · file-envelope 전환 시도",
      "over_4096": "ABSOLUTE_DROP — 등록 금지 · CALLBACK_PROMPT_TOO_LARGE raise"
    },
    "step_3_file_envelope_fallback": "prompt 가 3900+ 일 때 폴백: 긴 보고 부분을 별도 파일(memory/events/<task_id>.callback_envelope_body.json) 에 분리 저장 · callback prompt 본문에는 파일 경로 + sha256 만 포함 → prompt byte 수 < 2000 로 강제 단축",
    "step_4_telemetry_record": "결과를 callback_prompt_byte_telemetry_YYMMDD.jsonl 에 append-only 기록(상기 schema 정합)"
  },
  "fail_closed_semantics": {
    "exception": "CallbackPromptTooLarge (RuntimeError 서브) — 4096 absolute 또는 3900 hard 위반 시 raise",
    "no_silent_drop": "guard 도입 후 silent drop 0 — 등록 시도 자체가 차단되어 호출자가 인지",
    "executor_self_key_already_handled": "기존 assert_collector_key_is_independent_anu 와 별개 fail-closed 추가 · 두 검사 모두 통과 시에만 cron 등록"
  },
  "test_fixture_design": [
    "(F1) prompt 800 bytes ASCII → REGISTERED_FIRED_OK 분류 PASS",
    "(F2) prompt 2500 bytes 한글 혼합 → REGISTERED_FIRED_OK 분류 PASS",
    "(F3) prompt 3600 bytes → WARNING 분류 · 등록 진행 PASS",
    "(F4) prompt 4000 bytes → HARD_LIMIT_VIOLATION fail-closed · CallbackPromptTooLarge raise · 등록 0",
    "(F5) prompt 4500 bytes → ABSOLUTE_DROP fail-closed",
    "(F6) file-envelope 전환: 4000 bytes 본문 → file-envelope 분리 → 최종 prompt < 2000 bytes 검증",
    "(F7) executor self-key 와 byte violation 동시 → 두 fail-closed 모두 raise(어느 쪽이든)",
    "(F8) normal callback / fallback safety-net 동일 guard 동등 적용 검증",
    "(F9) idempotency — guard 호출 후 부분상태(cron 등록 중단) 발생 시 retry safe"
  ],
  "blast_radius_assessment": {
    "modified_files": [
      "anu_v3/dispatch_callback_contract.py (ADDITIVE helper · 시그니처 byte-0)",
      "dispatch/normal_fallback_callback_helper.py (build_anu_owned_callback_request 에 ADDITIVE guard)",
      "tests/regression/test_callback_prompt_byte_guard.py (신규)"
    ],
    "blast_radius": "MEDIUM — callback registration helper 직접 변경 · 모든 dispatch 의 callback 경로 영향. 그러나 PASS path 무영향(작은 prompt 는 그대로 통과) · 위반 시에만 fail-closed",
    "byte_0_required": [
      "기존 dispatch_callback_contract API 시그니처(assert_collector_key_is_independent_anu·classify_dispatch_contract·evaluate·RecoveryWatcher)",
      "callback_owner_enforcer / cron_dispatch_guard / executor_completion_contract (+49 era)",
      "dispatch/__init__.py production fn(task-2621 ADDITIVE wiring 보존)",
      "CLOSED_ALL_SETTLED 산출물 · ledger 49행 + 본 audit deliverables append-only",
      "Track C task-2619 미접촉"
    ],
    "critical7_assessment": {
      "is_critical7": false,
      "rationale": "byte guard 도입은 defense-in-depth 강화 · SAFE 방향만 · detection coverage 감소 0 · permission/credential/forbidden-path/scope-expansion 활성 위반 아님"
    }
  },
  "chair_approval_required": true,
  "approval_basis": [
    "회장 verbatim: 'runtime guard 구현은 별도 회장 승인 후 진행'",
    "회장 결정 필요: (a) guard 진행 여부 (b) 10표본 분석 후 진행 vs 즉시 진행 (c) hard limit 정확값(3900 vs 더 보수적 2500 ··· 관측 max 2439 고려) (d) file-envelope fallback 도입 여부 (e) test_fixture F1~F9 scope"
  ],
  "next_action": "10표본 누적 → 상관관계 분석 → 회장 보고 → 회장 결정. 자동 진행 0."
}
