feat(t-paliad-183): mig 082 — backfill is_court_set from heuristic

Phase 3 Slice 2 Step B-1 (design §3.B). UPDATE paliad.deadline_rules
to set is_court_set=true where the live isCourtDeterminedRule()
heuristic returns true:

  primary_party = 'court'
    OR event_type IN ('hearing', 'decision', 'order')

Expected delta on the production corpus: 47 rows flipped false→true
(every primary_party='court' rule overlaps with a court event_type
in the current data, so the two predicates fully overlap at 47).

Replicates the live fristenrechner.go body EXACTLY, not the
ILIKE-padded sketch in msg 1746. Per head's ruling msg 1750:
padding with '%entscheidung%' / '%urteil%' would mis-flag party
filings like RoP.151 (Antrag auf Kostenentscheidung) and § 83 PatG
(Stellungnahme zum Hinweisbeschluss) as court-set. They aren't —
only their anchors are.

Audit footnote: ~8 'Zustellung…' rules (LG-Urteil, OLG-Urteil,
BPatG-Entscheidung, Beschwerdeentscheidung, DPMA-Entscheidung)
carry primary_party='both' + event_type='filing'. Semantically the
Zustellung date IS court-set; flagging them is left to the legal-
review pass mentioned in design §2.3, not this slice.

Idempotent via WHERE is_court_set = false. Audit-reason is set via
set_config('paliad.audit_reason', …, true) so the mig 079 trigger
captures one paliad.deadline_rule_audit row per flipped rule —
the persistent backfill trail.

Mig 081 was reserved for proceeding_types display_order verification
in design §3.1; it was a no-op and was not authored. Tracker
skips 081, advances 80 → 82. golang-migrate handles non-contiguous
numbers fine as long as the order ascends.
This commit is contained in:
mAi
2026-05-15 00:28:38 +02:00
parent c7fa0d6542
commit 755a1042ff
2 changed files with 89 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
-- t-paliad-183 down — reverts the is_court_set flips written by
-- 082_backfill_is_court_set.up.sql.
--
-- "Revert" here means: restore the post-Slice-1 default (false on every
-- row). We don't know after the fact which rows were already true
-- before the backfill (mig 078 created the column with DEFAULT false on
-- every existing row, so post-Slice-1 every row was false — there is
-- no pre-existing true population to preserve). Setting back to false
-- is therefore equivalent to "undo the backfill".
--
-- Audit-reason set so the trigger doesn't raise on the down-side
-- UPDATEs either.
SELECT set_config(
'paliad.audit_reason',
'rollback 082: reset is_court_set to mig 078 default (false)',
true);
UPDATE paliad.deadline_rules
SET is_court_set = false
WHERE is_court_set = true;

View File

@@ -0,0 +1,68 @@
-- t-paliad-183 / Fristen Phase 3 Slice 2 Step B-1 — backfill
-- paliad.deadline_rules.is_court_set from the live runtime heuristic.
--
-- Heuristic source-of-truth: internal/services/fristenrechner.go
-- isCourtDeterminedRule() — at the time of Slice 1 (commit c7fa0d6) the
-- body is precisely:
--
-- primary_party = 'court'
-- OR event_type IN ('hearing', 'decision', 'order')
--
-- The Slice 2 head instruction (msg 1746) suggested padding with
-- 'name ILIKE %entscheidung% OR %urteil%'; head's clarification
-- (msg 1750) rules that out: replicate the live code exactly. Padding
-- would mis-flag party submissions like 'Antrag auf Kostenentscheidung'
-- (RoP.151) and 'Stellungnahme zum Hinweisbeschluss' as court-set —
-- they are not (the party files them; only their anchor is set by the
-- court).
--
-- Audit footnote for the legal-review pass: ~8 'Zustellung…' rules
-- (Zustellung BPatG-Entscheidung, Zustellung LG-Urteil, etc.) carry
-- primary_party='both' + event_type='filing'. Semantically the
-- Zustellung date IS court-set, but the live heuristic doesn't treat
-- them as such and flagging them now would change calculator
-- rendering without legal review. Leaving them is_court_set=false
-- preserves current behaviour; the legal-review pass mentioned in
-- design §2.3 ("flag them informational in a Phase 3 slice") can
-- promote them later via a targeted UPDATE.
--
-- Audit-reason: set_config('paliad.audit_reason', …, true) scopes the
-- value to golang-migrate's implicit per-file transaction. The audit
-- trigger from mig 079 picks it up via current_setting() and writes
-- one paliad.deadline_rule_audit row per flipped rule — the compliance
-- trail for the backfill, persisted forever.
--
-- Idempotent: WHERE is_court_set = false guards re-runs against double-
-- counting audit rows.
--
-- Expected delta on the production corpus (172 rules): 47 rows flipped
-- false→true (every primary_party='court' rule also has a matching
-- event_type in the current data — the two predicates fully overlap).
--
-- Tracker note: mig 081 was reserved for proceeding_types display_order
-- verification per design §3.1; that was a no-op and not authored.
-- Slice 1 shipped 078/079/080; Slice 2 starts at 082. golang-migrate
-- only requires ascending order, not contiguity.
SELECT set_config(
'paliad.audit_reason',
'backfill 082: is_court_set from isCourtDeterminedRule heuristic '
|| '(primary_party=court OR event_type IN hearing/decision/order) '
|| 'per design §2.3 / fristenrechner.go',
true);
UPDATE paliad.deadline_rules
SET is_court_set = true
WHERE is_court_set = false
AND (
primary_party = 'court'
OR event_type IN ('hearing', 'decision', 'order')
);
DO $$
DECLARE
n_set int;
BEGIN
SELECT count(*) INTO n_set FROM paliad.deadline_rules WHERE is_court_set = true;
RAISE NOTICE 'backfill 082: is_court_set=true on % rules', n_set;
END $$;