-- BUG-633: persist answer.host_fallback when the host speaks after a -- completed evidence batch and the model emitted no answer text. begin; do $migration$ begin if current_user <> 'schema_owner' then raise exception 'rectification_host_fallback_phase_requires_schema_owner' using errcode = '42501'; end if; end $migration$; alter table public.agentic_rectification_run_phases drop constraint if exists agentic_rectification_run_phases_phase_check, add constraint agentic_rectification_run_phases_phase_check check ( phase in ( 'run.started', 'skill.started', 'skill.loaded', 'skill.bound', 'case.loaded', 'intent.classified', 'evidence.proposed', 'evidence.confirmed', 'candidates.comparing', 'candidates.updated', 'diagnostics.completed', 'candidate.accepted', 'birth_time.confirmed', 'answer.composed', 'answer.host_fallback', 'billing.settled', 'answer.delta', 'run.completed', 'run.failed' ) ); create or replace function public.insert_agentic_rectification_run_phase( p_user_id uuid, p_case_id uuid, p_turn_id uuid, p_phase text, p_tool_name text, p_sequence integer, p_attempt_id uuid ) returns jsonb language plpgsql security definer set search_path = '' as $$ declare v_attempt public.agentic_rectification_run_attempts%rowtype; v_phase_id uuid; begin if p_user_id is null or p_case_id is null or p_turn_id is null or p_attempt_id is null or p_phase not in ( 'run.started', 'skill.started', 'skill.loaded', 'skill.bound', 'case.loaded', 'intent.classified', 'evidence.proposed', 'evidence.confirmed', 'candidates.comparing', 'candidates.updated', 'diagnostics.completed', 'candidate.accepted', 'birth_time.confirmed', 'answer.composed', 'answer.host_fallback', 'billing.settled', 'answer.delta', 'run.completed', 'run.failed' ) then raise exception 'agentic_rectification_invalid_input' using errcode = 'P0001'; end if; if not exists ( select 1 from public.agentic_rectification_cases where id = p_case_id and user_id = p_user_id ) then raise exception 'agentic_rectification_case_not_found' using errcode = 'P0001'; end if; if not exists ( select 1 from public.agentic_rectification_turns where id = p_turn_id and case_id = p_case_id ) then raise exception 'agentic_rectification_turn_not_found' using errcode = 'P0001'; end if; select * into v_attempt from public.agentic_rectification_run_attempts where id = p_attempt_id and case_id = p_case_id and turn_id = p_turn_id for update; if not found then raise exception 'agentic_rectification_attempt_not_found' using errcode = 'P0001'; end if; if v_attempt.status <> 'started' then raise exception 'agentic_rectification_attempt_not_started' using errcode = 'P0001'; end if; insert into public.agentic_rectification_run_phases ( case_id, turn_id, attempt_id, phase, tool_name, sequence ) values ( p_case_id, p_turn_id, p_attempt_id, p_phase, p_tool_name, coalesce(p_sequence, 0) ) returning id into v_phase_id; return jsonb_build_object('phase_id', v_phase_id, 'attempt_id', p_attempt_id); end; $$; revoke all on function public.insert_agentic_rectification_run_phase( uuid, uuid, uuid, text, text, integer, uuid ) from public, anon, authenticated; grant execute on function public.insert_agentic_rectification_run_phase( uuid, uuid, uuid, text, text, integer, uuid ) to service_role; commit;