-- 画像水位对齐到 fact 层 + 就地刷新时刻。
--
-- 背景:画像读 patient_facts,但 stale 判定只看 event_watermark(patient_transactions)。
-- reparse 重写事实、不产新事务 → 2026-07-21「amount_cents 应收→实付」reparse 之后的全量重算
-- 被水位闸 noop 掉 325,979 人(生产日志),74% 存量画像的累计消费永久停在旧口径。
ALTER TABLE "personas"
  ADD COLUMN "fact_watermark" TIMESTAMPTZ(3),
  ADD COLUMN "refreshed_at"   TIMESTAMPTZ(3);

-- fact 水位查询(每次重算前 MAX(updated_at) per patient)的支撑索引:倒序扫首行即出,index-only。
-- 没它就得沿 (patient_id, status) 扫完该患者全部 fact 再回堆取 updated_at —— 闸本身变成开销。
-- IF NOT EXISTS:prod 先手动 CREATE INDEX CONCURRENTLY 预建(patient_facts 370 万行,免锁写),
--   再 deploy 时本句即 no-op。预建命令:
--   CREATE INDEX CONCURRENTLY IF NOT EXISTS "patient_facts_patient_id_updated_at_idx"
--     ON "patient_facts"("patient_id", "updated_at");
CREATE INDEX IF NOT EXISTS "patient_facts_patient_id_updated_at_idx"
  ON "patient_facts"("patient_id", "updated_at");

-- ⚠️ 部署后需一次性全量重算把存量 fact_watermark 补上(NULL 一律判 stale):
--   pnpm recompute-persona:prod -- --host=jvs-dw --concurrency=8 --force
-- --force 必带:同批上线的 next_boundary_at 以 NULL 表示"不再改档",不会自己判 stale,
--   只有强制跑一遍才写得上(见 20260726064759_persona_next_boundary)。
-- 不补 fact_watermark 也能自愈 —— 每晚 stale-scan 会按 LIMIT 速率回填,只是慢;
--   next_boundary_at 则**不会**自愈,必须这一次 --force。
