287 lines
11 KiB
PL/PgSQL
287 lines
11 KiB
PL/PgSQL
-- Created 2026-08-12. Filename intentionally follows the existing
|
|
-- 20260813010000 migration; the identifier is an ordering key.
|
|
begin;
|
|
|
|
alter table public.agentic_rectification_tool_receipts
|
|
add column if not exists executed_methods jsonb not null default '[]'::jsonb
|
|
check (jsonb_typeof(executed_methods) = 'array');
|
|
|
|
drop function if exists public.insert_agentic_rectification_tool_receipt(
|
|
uuid, uuid, uuid, text, text, text, text, text, text, text
|
|
);
|
|
|
|
create or replace function public.insert_agentic_rectification_tool_receipt(
|
|
p_user_id uuid,
|
|
p_case_id uuid,
|
|
p_turn_id uuid,
|
|
p_tool_name text,
|
|
p_public_phase text,
|
|
p_status text,
|
|
p_input_fingerprint text,
|
|
p_result_fingerprint text,
|
|
p_engine_version text,
|
|
p_safe_error_code text,
|
|
p_executed_methods jsonb
|
|
)
|
|
returns jsonb
|
|
language plpgsql
|
|
security definer
|
|
set search_path = ''
|
|
as $$
|
|
declare
|
|
v_receipt_id uuid;
|
|
v_turn_count bigint;
|
|
begin
|
|
if p_user_id is null or p_case_id is null or p_turn_id is null
|
|
or p_executed_methods is null
|
|
or jsonb_typeof(p_executed_methods) <> 'array'
|
|
or exists (
|
|
select 1
|
|
from jsonb_array_elements_text(p_executed_methods) as method(value)
|
|
where method.value not in (
|
|
'd1-rashi', 'd2-hora', 'd4-chaturthamsha', 'd9-navamsa',
|
|
'd10-dashamsa', 'd11-labhamsha', 'd24-chaturvimshamsha',
|
|
'd30-trimshamsha', 'vimshottari-dasha', 'narayana-dasha',
|
|
'gochara', 'ashtakavarga', 'shadbala', 'arudha-pada',
|
|
'functional-benefic-malefic'
|
|
)
|
|
) 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;
|
|
select count(*) into v_turn_count
|
|
from public.agentic_rectification_turns
|
|
where id = p_turn_id and case_id = p_case_id;
|
|
if v_turn_count = 0 then
|
|
raise exception 'agentic_rectification_turn_not_found' using errcode = 'P0001';
|
|
end if;
|
|
|
|
insert into public.agentic_rectification_tool_receipts (
|
|
case_id, turn_id, tool_name, public_phase, status,
|
|
input_fingerprint, result_fingerprint, engine_version, safe_error_code,
|
|
executed_methods, completed_at
|
|
) values (
|
|
p_case_id, p_turn_id, p_tool_name, p_public_phase, p_status,
|
|
p_input_fingerprint, p_result_fingerprint, p_engine_version, p_safe_error_code,
|
|
p_executed_methods,
|
|
case when p_status = 'completed' then pg_catalog.now() else null end
|
|
) returning id into v_receipt_id;
|
|
|
|
return jsonb_build_object('receipt_id', v_receipt_id);
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.insert_agentic_rectification_tool_receipt(
|
|
uuid, uuid, uuid, text, text, text, text, text, text, text, jsonb
|
|
) from public, anon, authenticated;
|
|
grant execute on function public.insert_agentic_rectification_tool_receipt(
|
|
uuid, uuid, uuid, text, text, text, text, text, text, text, jsonb
|
|
) to service_role;
|
|
|
|
create or replace function public.get_agentic_rectification_turn_receipt(
|
|
p_user_id uuid,
|
|
p_case_id uuid,
|
|
p_turn_id uuid
|
|
)
|
|
returns jsonb
|
|
language plpgsql
|
|
security definer
|
|
set search_path = ''
|
|
as $$
|
|
declare
|
|
v_turn public.agentic_rectification_turns%rowtype;
|
|
v_case public.agentic_rectification_cases%rowtype;
|
|
v_phases jsonb;
|
|
v_tools jsonb;
|
|
v_methods jsonb;
|
|
v_engine_version text;
|
|
begin
|
|
if p_user_id is null or p_case_id is null or p_turn_id is null then
|
|
raise exception 'agentic_rectification_invalid_input' using errcode = 'P0001';
|
|
end if;
|
|
select * into v_case
|
|
from public.agentic_rectification_cases
|
|
where id = p_case_id and user_id = p_user_id;
|
|
if not found then
|
|
raise exception 'agentic_rectification_case_not_found' using errcode = 'P0001';
|
|
end if;
|
|
select * into v_turn
|
|
from public.agentic_rectification_turns
|
|
where id = p_turn_id and case_id = p_case_id;
|
|
if not found then
|
|
raise exception 'agentic_rectification_turn_not_found' using errcode = 'P0001';
|
|
end if;
|
|
|
|
select coalesce(jsonb_agg(
|
|
jsonb_build_object('phase', rp.phase, 'tool', rp.tool_name)
|
|
order by rp.sequence
|
|
), '[]'::jsonb) into v_phases
|
|
from public.agentic_rectification_run_phases rp
|
|
where rp.turn_id = p_turn_id;
|
|
|
|
select coalesce(jsonb_agg(tool_name order by tool_name), '[]'::jsonb) into v_tools
|
|
from (
|
|
select distinct tr.tool_name
|
|
from public.agentic_rectification_tool_receipts tr
|
|
where tr.turn_id = p_turn_id and tr.status = 'completed'
|
|
) tools;
|
|
|
|
select coalesce(jsonb_agg(method order by method), '[]'::jsonb) into v_methods
|
|
from (
|
|
select distinct jsonb_array_elements_text(tr.executed_methods) as method
|
|
from public.agentic_rectification_tool_receipts tr
|
|
where tr.turn_id = p_turn_id and tr.status = 'completed'
|
|
) methods;
|
|
|
|
select max(tr.engine_version) into v_engine_version
|
|
from public.agentic_rectification_tool_receipts tr
|
|
where tr.turn_id = p_turn_id and tr.engine_version is not null;
|
|
|
|
return jsonb_build_object(
|
|
'turn_id', v_turn.id,
|
|
'status', v_turn.status,
|
|
'skill_name', v_case.skill_name,
|
|
'skill_version', v_case.skill_version,
|
|
'engine_version', v_engine_version,
|
|
'phases', v_phases,
|
|
'tools', v_tools,
|
|
'methods', v_methods,
|
|
'started_at', v_turn.created_at,
|
|
'completed_at', v_turn.completed_at
|
|
);
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.get_agentic_rectification_turn_receipt(uuid, uuid, uuid)
|
|
from public, anon, authenticated;
|
|
grant execute on function public.get_agentic_rectification_turn_receipt(uuid, uuid, uuid)
|
|
to service_role;
|
|
|
|
create temporary table rectification_birth_context_affected_cases on commit drop as
|
|
select c.id
|
|
from public.agentic_rectification_cases c
|
|
join public.profiles p on p.id = c.user_id
|
|
where c.status = any (public.agentic_rectification_resumable_statuses())
|
|
and (
|
|
nullif(btrim(c.baseline_birth_snapshot ->> 'birth_place_label'), '') is null
|
|
or nullif(btrim(c.baseline_birth_snapshot ->> 'timezone_id'), '') is null
|
|
or c.baseline_birth_snapshot ->> 'birth_place_label' is distinct from p.birth_place_label
|
|
or c.baseline_birth_snapshot ->> 'timezone_id' is distinct from p.timezone_id
|
|
);
|
|
|
|
update public.agentic_rectification_cases c
|
|
set baseline_birth_snapshot = c.baseline_birth_snapshot
|
|
|| jsonb_build_object(
|
|
'birth_place_label', p.birth_place_label,
|
|
'timezone_id', p.timezone_id
|
|
)
|
|
from public.profiles p, rectification_birth_context_affected_cases affected
|
|
where c.id = affected.id
|
|
and p.id = c.user_id
|
|
and nullif(btrim(coalesce(p.birth_place_label, '')), '') is not null
|
|
and nullif(btrim(coalesce(p.timezone_id, '')), '') is not null;
|
|
|
|
update public.agentic_rectification_cases c
|
|
set status = 'needs_rebaseline',
|
|
updated_at = pg_catalog.now(),
|
|
last_activity_at = pg_catalog.now()
|
|
from rectification_birth_context_affected_cases affected
|
|
where c.id = affected.id;
|
|
|
|
update public.agentic_rectification_results r
|
|
set invalidated_at = pg_catalog.now(),
|
|
updated_at = pg_catalog.now()
|
|
from rectification_birth_context_affected_cases affected
|
|
where r.case_id = affected.id
|
|
and r.invalidated_at is null;
|
|
|
|
create or replace function public.agentic_rectification_profiles_rebaseline_guard()
|
|
returns trigger
|
|
language plpgsql
|
|
security definer
|
|
set search_path = ''
|
|
as $$
|
|
begin
|
|
if old.birth_date is distinct from new.birth_date
|
|
or old.birth_place_label is distinct from new.birth_place_label
|
|
or old.reported_birth_time is distinct from new.reported_birth_time
|
|
or old.active_birth_time is distinct from new.active_birth_time
|
|
or old.birth_time_source is distinct from new.birth_time_source
|
|
or old.birth_time_period is distinct from new.birth_time_period
|
|
or old.uncertainty_before_minutes is distinct from new.uncertainty_before_minutes
|
|
or old.uncertainty_after_minutes is distinct from new.uncertainty_after_minutes
|
|
or old.latitude is distinct from new.latitude
|
|
or old.longitude is distinct from new.longitude
|
|
or old.timezone_id is distinct from new.timezone_id
|
|
or old.timezone_offset is distinct from new.timezone_offset then
|
|
update public.agentic_rectification_cases
|
|
set status = 'needs_rebaseline',
|
|
updated_at = pg_catalog.now(),
|
|
last_activity_at = pg_catalog.now()
|
|
where user_id = new.id
|
|
and status = any (public.agentic_rectification_resumable_statuses());
|
|
end if;
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.agentic_rectification_profiles_rebaseline_guard()
|
|
from public, anon, authenticated;
|
|
drop trigger if exists agentic_rectification_profiles_rebaseline_guard_trigger on public.profiles;
|
|
create trigger agentic_rectification_profiles_rebaseline_guard_trigger
|
|
after update of birth_date, birth_place_label, reported_birth_time, active_birth_time,
|
|
birth_time_source, birth_time_period, uncertainty_before_minutes, uncertainty_after_minutes,
|
|
latitude, longitude, timezone_id, timezone_offset
|
|
on public.profiles
|
|
for each row execute function public.agentic_rectification_profiles_rebaseline_guard();
|
|
|
|
create or replace function public.invalidate_agentic_rectification_results_on_profile_change()
|
|
returns trigger
|
|
language plpgsql
|
|
security definer
|
|
set search_path = ''
|
|
as $$
|
|
begin
|
|
if old.birth_date is distinct from new.birth_date
|
|
or old.birth_place_label is distinct from new.birth_place_label
|
|
or old.reported_birth_time is distinct from new.reported_birth_time
|
|
or old.birth_time_source is distinct from new.birth_time_source
|
|
or old.birth_time_period is distinct from new.birth_time_period
|
|
or old.uncertainty_before_minutes is distinct from new.uncertainty_before_minutes
|
|
or old.uncertainty_after_minutes is distinct from new.uncertainty_after_minutes
|
|
or old.latitude is distinct from new.latitude
|
|
or old.longitude is distinct from new.longitude
|
|
or old.timezone_id is distinct from new.timezone_id
|
|
or old.timezone_offset is distinct from new.timezone_offset
|
|
or (
|
|
(old.active_birth_time is distinct from new.active_birth_time
|
|
or old.birth_time_status is distinct from new.birth_time_status)
|
|
and coalesce(new.birth_time_status, '') not in ('accepted', 'confirmed')
|
|
) then
|
|
update public.agentic_rectification_results
|
|
set invalidated_at = pg_catalog.now(),
|
|
updated_at = pg_catalog.now()
|
|
where user_id = new.id
|
|
and invalidated_at is null;
|
|
end if;
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.invalidate_agentic_rectification_results_on_profile_change()
|
|
from public, anon, authenticated;
|
|
drop trigger if exists profiles_invalidate_agentic_rectification_results on public.profiles;
|
|
create trigger profiles_invalidate_agentic_rectification_results
|
|
after update of birth_date, birth_place_label, reported_birth_time, active_birth_time,
|
|
birth_time_status, birth_time_source, birth_time_period, uncertainty_before_minutes,
|
|
uncertainty_after_minutes, latitude, longitude, timezone_id, timezone_offset
|
|
on public.profiles
|
|
for each row execute function public.invalidate_agentic_rectification_results_on_profile_change();
|
|
|
|
commit;
|