-- t-paliad-263 Wave 0 + m/paliad#99 — Tier 0 deadline-rule corrections. -- -- Source: docs/research-deadlines-completeness-2026-05-25.md §10 Tier 0 -- (curie's bulletproof completeness audit, merged 2026-05-25 as commit -- 94a9e7e). 16 distinct single-row UPDATEs across UPC + DE-LG + DPMA + -- EPA proceedings; T0.5 + T0.6 were shipped separately as mig 124 -- (m/paliad#95, de.inf.lg Replik/Duplik sequencing) and are not -- repeated here. T0.8 (covered by T0.2) and T0.11 (covered by T0.1) -- are dedup'd out per the audit's own note. -- -- Also folds in m/paliad#99 (UPC Statement of Claim missing legal -- citation): upc.inf.cfi.soc.rule_code / legal_source backfilled to -- UPC RoP R.13(1). Same migration file, separate UPDATE block with -- its own guard. -- -- All fixes within the existing schema (no new columns). Each UPDATE -- is guarded by a WHERE clause that matches only the pre-fix row -- state (per mig 095 convention) — re-applying against a DB that -- already carries the fix matches zero rows and no-ops, so there are -- no duplicate deadline_rule_audit entries on idempotent re-runs. -- -- Verification DO block at the end RAISEs EXCEPTION if any of the -- patched rows is left in an inconsistent shape (mixing pre-fix and -- post-fix state). -- -- audit_reason set_config required at the top — the mig 079 trigger -- on paliad.deadline_rules raises EXCEPTION 'audit reason required' -- on any UPDATE without it. -- -- Slot 127 reserved per paliadin: sequence is 124 brunel #95 (done), -- 125 hermes #97, 126 icarus #80, 127 brunel Wave 0 + #99, 128+ next. SELECT set_config( 'paliad.audit_reason', 'mig 127: t-paliad-263 Wave 0 + m/paliad#99 — Tier 0 deadline-rule corrections from curie''s audit (docs/research-deadlines-completeness-2026-05-25.md §10) plus UPC SoC R.13 citation', true); -- ============================================================================= -- T0.1 upc.rev.cfi.defence — duration 3mo → 2mo per RoP.049.1. -- Zero-pads the rule_code citation to canonical form. Audit §5 -- (wrong period — every UPC_REV tracked in paliad today computes -- Defence at +3 months, statute says +2). Verbatim from -- UPCRoP.049.1: "The defendant shall lodge a Defence to revocation -- within two months of service of the Statement for revocation." -- ============================================================================= UPDATE paliad.deadline_rules SET duration_value = 2, rule_code = 'RoP.049.1', updated_at = now() WHERE submission_code = 'upc.rev.cfi.defence' AND is_active = true AND lifecycle_state = 'published' AND duration_value = 3 AND rule_code = 'RoP.49.1'; -- ============================================================================= -- T0.2 upc.rev.cfi.rejoin — duration 2mo → 1mo per RoP.052; add citation. -- Audit §5 (wrong period). Verbatim from UPCRoP.052: "Within one -- month of the service of the Reply the defendant may lodge a -- Rejoinder to the Reply to the Defence to revocation." -- ============================================================================= UPDATE paliad.deadline_rules SET duration_value = 1, rule_code = 'RoP.052', legal_source = 'UPC.RoP.52', updated_at = now() WHERE submission_code = 'upc.rev.cfi.rejoin' AND is_active = true AND lifecycle_state = 'published' AND duration_value = 2 AND rule_code IS NULL; -- ============================================================================= -- T0.3 upc.apl.merits.response — duration 2mo → 3mo per RoP.235.1. -- Audit §5 (wrong period — every main-track appellate respondent). -- Verbatim from UPCRoP.235.1: "Within three months of service of -- the Statement of grounds of appeal pursuant to Rule 224.2(a), -- any other party … may lodge a Statement of response." -- ============================================================================= UPDATE paliad.deadline_rules SET duration_value = 3, rule_code = 'RoP.235.1', legal_source = 'UPC.RoP.235.1', updated_at = now() WHERE submission_code = 'upc.apl.merits.response' AND is_active = true AND lifecycle_state = 'published' AND duration_value = 2 AND rule_code IS NULL; -- ============================================================================= -- T0.4 de.inf.lg.beruf_begr — parent_id = NULL (was de.inf.lg.berufung). -- Audit §7.1 — every DE-LG-Verletzung appeal renders the -- Berufungsbegründung at trigger + 1mo (Berufung) + 2mo = 3 months -- from Urteil-service. Per ZPO §520(2) "die Frist für die -- Berufungsbegründung beträgt zwei Monate. Sie beginnt mit der -- Zustellung des in vollständiger Form abgefassten Urteils" → 2 -- months from Urteil-service (parallel to, not chained off, the -- Berufungsfrist itself). NULL parent_id makes the rule anchor -- on the proceeding's trigger date — matches how the symmetric -- de.inf.olg.begruendung is modelled. -- ============================================================================= UPDATE paliad.deadline_rules SET parent_id = NULL, updated_at = now() WHERE submission_code = 'de.inf.lg.beruf_begr' AND is_active = true AND lifecycle_state = 'published' AND parent_id = ( SELECT id FROM paliad.deadline_rules WHERE submission_code = 'de.inf.lg.berufung' AND is_active = true AND lifecycle_state = 'published' LIMIT 1 ); -- ============================================================================= -- T0.5 / T0.6 de.inf.lg.replik + de.inf.lg.duplik — already shipped -- as mig 124 (m/paliad#95). Not repeated here. Idempotency of the -- audit's Tier 0 sweep against a fresh DB is preserved because mig -- 124 runs before this one and is itself guarded. -- ============================================================================= -- ============================================================================= -- T0.7 upc.rev.cfi.reply — backfill rule_code + legal_source per RoP.051. -- Audit §4.1 — duration (2mo) unchanged. Verbatim from UPCRoP.051: -- "Reply to Defence to revocation and Application to amend the -- patent. The claimant in the revocation action may, within two -- months of service of the Defence to revocation and the -- Application to amend the patent, if any, lodge a Reply…" -- ============================================================================= UPDATE paliad.deadline_rules SET rule_code = 'RoP.051', legal_source = 'UPC.RoP.51', updated_at = now() WHERE submission_code = 'upc.rev.cfi.reply' AND is_active = true AND lifecycle_state = 'published' AND rule_code IS NULL AND legal_source IS NULL; -- ============================================================================= -- T0.9 upc.apl.merits.notice — citation drift RoP.220.1 → RoP.224.1.a. -- Audit §4.1 — duration unchanged. R.220.1 is the umbrella ("an -- appeal may be brought"); R.224.1(a) carries the Notice-of-appeal -- 2-month period explicitly. -- ============================================================================= UPDATE paliad.deadline_rules SET rule_code = 'RoP.224.1.a', legal_source = 'UPC.RoP.224.1.a', updated_at = now() WHERE submission_code = 'upc.apl.merits.notice' AND is_active = true AND lifecycle_state = 'published' AND rule_code = 'RoP.220.1' AND legal_source = 'UPC.RoP.220.1'; -- ============================================================================= -- T0.10 upc.apl.merits.grounds — citation drift RoP.220.1 → RoP.224.2.a. -- Audit §4.1 — duration unchanged. R.224.2(a) sets the Grounds -- 4-month period for decisions referred to in R.220.1(a) and (b). -- ============================================================================= UPDATE paliad.deadline_rules SET rule_code = 'RoP.224.2.a', legal_source = 'UPC.RoP.224.2.a', updated_at = now() WHERE submission_code = 'upc.apl.merits.grounds' AND is_active = true AND lifecycle_state = 'published' AND rule_code = 'RoP.220.1' AND legal_source = 'UPC.RoP.220.1'; -- ============================================================================= -- T0.12 dpma.opp.dpma.erwiderung — flip is_court_set = true; drop the -- § 59(3) PatG citation. Audit §4.3 + §9.1: §59(3) addresses -- Anhörung, not a 4-month response period. No statutory -- Erwiderungsfrist exists in §59 — the 4-month figure is DPMA -- practice (DPMA-Richtlinien D-IV 5.2). Modelled court-set, the -- 4-month value remains the default-display heuristic the -- lawyer overrides via "Datum setzen". -- ============================================================================= UPDATE paliad.deadline_rules SET is_court_set = true, rule_code = NULL, legal_source = NULL, updated_at = now() WHERE submission_code = 'dpma.opp.dpma.erwiderung' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = false AND legal_source = 'DE.PatG.59.3'; -- ============================================================================= -- T0.13 dpma.appeal.bpatg.begruendung — flip is_court_set = true; drop -- the § 75 PatG citation. Audit §4.3 + §9.1: §75 PatG addresses -- aufschiebende Wirkung only, not a Begründungsfrist. No fixed -- Begründungsfrist for BPatG-Beschwerde exists in PatG §§73-80 — -- the BPatG sets it in the individual case. 1-month default -- retained as display heuristic. -- ============================================================================= UPDATE paliad.deadline_rules SET is_court_set = true, rule_code = NULL, legal_source = NULL, updated_at = now() WHERE submission_code = 'dpma.appeal.bpatg.begruendung' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = false AND legal_source = 'DE.PatG.75.1'; -- ============================================================================= -- T0.14 de.null.bpatg.erwidg — citation DE.PatG.82.1 → DE.PatG.82.3. -- Audit §4.4 — duration (2 months) is correct. §82(1) carries the -- 1-month Erklärungsfrist ("sich darüber zu erklären"); the full -- Klageerwiderung 2-month period lives in §82(3). -- ============================================================================= UPDATE paliad.deadline_rules SET rule_code = '§ 82 Abs. 3 PatG', legal_source = 'DE.PatG.82.3', updated_at = now() WHERE submission_code = 'de.null.bpatg.erwidg' AND is_active = true AND lifecycle_state = 'published' AND legal_source = 'DE.PatG.82.1'; -- ============================================================================= -- T0.15 de.null.bgh.begruendung — citation DE.PatG.111.1 → -- DE.ZPO.520.2 (via PatG §117). Audit §4.4 — duration (3 months) -- is correct. §111 PatG defines the Grounds of Berufung -- (Verletzung des Bundesrechts), not a Begründungsfrist; the -- 3-month figure is supplied by §117 PatG → ZPO §520(2). -- ============================================================================= UPDATE paliad.deadline_rules SET rule_code = '§ 520 Abs. 2 ZPO i.V.m. § 117 PatG', legal_source = 'DE.ZPO.520.2', updated_at = now() WHERE submission_code = 'de.null.bgh.begruendung' AND is_active = true AND lifecycle_state = 'published' AND legal_source = 'DE.PatG.111.1'; -- ============================================================================= -- T0.16 de.null.bgh.erwiderung — flip is_court_set = true; recite as -- DE.ZPO.521.2 (via PatG §117). Audit §4.4 + §9.1 — §111 PatG -- has no Erwiderungsfrist clause. The actual Erwiderungsfrist -- for BGH-Nichtigkeitsberufung is set by the court per §117 -- PatG → ZPO §521(2). 2-month default retained as display -- heuristic. -- ============================================================================= UPDATE paliad.deadline_rules SET is_court_set = true, rule_code = '§ 521 Abs. 2 ZPO i.V.m. § 117 PatG', legal_source = 'DE.ZPO.521.2', updated_at = now() WHERE submission_code = 'de.null.bgh.erwiderung' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = false AND legal_source = 'DE.PatG.111.3'; -- ============================================================================= -- T0.17 epa.opp.opd.erwidg — flip is_court_set = true. Audit §4.5 + -- §9.1: R.79(1) EPÜ authorises the Opposition Division to set -- the period, but does not specify a fixed 4 months. The 4-month -- figure is administrative practice (EPO Guidelines D-IV 5.2). -- Citation retained as the rule-of-authority for the OD's -- discretion. 4-month default retained as display heuristic. -- ============================================================================= UPDATE paliad.deadline_rules SET is_court_set = true, updated_at = now() WHERE submission_code = 'epa.opp.opd.erwidg' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = false AND legal_source = 'EU.EPC-R.79.1'; -- ============================================================================= -- m/paliad#99 upc.inf.cfi.soc — backfill UPC RoP R.13(1) citation. -- The Statement of Claim is defined in UPC RoP R.13 (R.13.1 -- lists the required contents). The row carries no statutory -- deadline (duration_value = 0, parent_id IS NULL — the SoC is -- the originating filing that anchors the proceeding's trigger -- date), but the catalog UI surfaces the rule citation in -- result cards and the Type=Statement-of-Claim / Rule=Auto -- resolution; both render blank today because rule_code + -- legal_source are NULL. Backfill leaves duration / anchor / -- party untouched. -- ============================================================================= UPDATE paliad.deadline_rules SET rule_code = 'RoP.013.1', legal_source = 'UPC.RoP.13.1', updated_at = now() WHERE submission_code = 'upc.inf.cfi.soc' AND is_active = true AND lifecycle_state = 'published' AND rule_code IS NULL AND legal_source IS NULL; -- ============================================================================= -- Hard assertions. Each touched row must end up in its post-fix -- shape. Re-running the migration after a successful first run is a -- no-op for the data but the assertions still pass because they -- check the post-fix state. -- ============================================================================= DO $$ DECLARE v_count integer; BEGIN -- T0.1 defence: dur=2 + canonical zero-padded rule_code SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.rev.cfi.defence' AND is_active = true AND lifecycle_state = 'published' AND duration_value = 2 AND rule_code = 'RoP.049.1'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.1: upc.rev.cfi.defence not in post-fix shape (got % matches)', v_count; END IF; -- T0.2 rejoin: dur=1 SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.rev.cfi.rejoin' AND is_active = true AND lifecycle_state = 'published' AND duration_value = 1 AND rule_code = 'RoP.052'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.2: upc.rev.cfi.rejoin not in post-fix shape (got % matches)', v_count; END IF; -- T0.3 response: dur=3 SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.apl.merits.response' AND is_active = true AND lifecycle_state = 'published' AND duration_value = 3 AND rule_code = 'RoP.235.1'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.3: upc.apl.merits.response not in post-fix shape (got % matches)', v_count; END IF; -- T0.4 beruf_begr: parent_id IS NULL SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'de.inf.lg.beruf_begr' AND is_active = true AND lifecycle_state = 'published' AND parent_id IS NULL; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.4: de.inf.lg.beruf_begr not in post-fix shape (got % matches)', v_count; END IF; -- T0.7 reply: citation backfilled SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.rev.cfi.reply' AND is_active = true AND lifecycle_state = 'published' AND rule_code = 'RoP.051' AND legal_source = 'UPC.RoP.51'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.7: upc.rev.cfi.reply not in post-fix shape (got % matches)', v_count; END IF; -- T0.9 notice: citation RoP.224.1.a SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.apl.merits.notice' AND is_active = true AND lifecycle_state = 'published' AND rule_code = 'RoP.224.1.a' AND legal_source = 'UPC.RoP.224.1.a'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.9: upc.apl.merits.notice not in post-fix shape (got % matches)', v_count; END IF; -- T0.10 grounds: citation RoP.224.2.a SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.apl.merits.grounds' AND is_active = true AND lifecycle_state = 'published' AND rule_code = 'RoP.224.2.a' AND legal_source = 'UPC.RoP.224.2.a'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.10: upc.apl.merits.grounds not in post-fix shape (got % matches)', v_count; END IF; -- T0.12 dpma.opp erwiderung: court-set, no citation SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'dpma.opp.dpma.erwiderung' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = true AND legal_source IS NULL AND rule_code IS NULL; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.12: dpma.opp.dpma.erwiderung not in post-fix shape (got % matches)', v_count; END IF; -- T0.13 dpma.appeal.bpatg begründung: court-set, no citation SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'dpma.appeal.bpatg.begruendung' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = true AND legal_source IS NULL AND rule_code IS NULL; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.13: dpma.appeal.bpatg.begruendung not in post-fix shape (got % matches)', v_count; END IF; -- T0.14 bpatg erwidg: §82.3 SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'de.null.bpatg.erwidg' AND is_active = true AND lifecycle_state = 'published' AND legal_source = 'DE.PatG.82.3'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.14: de.null.bpatg.erwidg not in post-fix shape (got % matches)', v_count; END IF; -- T0.15 bgh begründung: ZPO §520.2 SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'de.null.bgh.begruendung' AND is_active = true AND lifecycle_state = 'published' AND legal_source = 'DE.ZPO.520.2'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.15: de.null.bgh.begruendung not in post-fix shape (got % matches)', v_count; END IF; -- T0.16 bgh erwiderung: court-set, ZPO §521.2 SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'de.null.bgh.erwiderung' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = true AND legal_source = 'DE.ZPO.521.2'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.16: de.null.bgh.erwiderung not in post-fix shape (got % matches)', v_count; END IF; -- T0.17 epa.opp opd erwidg: court-set SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'epa.opp.opd.erwidg' AND is_active = true AND lifecycle_state = 'published' AND is_court_set = true; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 T0.17: epa.opp.opd.erwidg not in post-fix shape (got % matches)', v_count; END IF; -- #99 upc.inf.cfi.soc: citation backfilled SELECT count(*) INTO v_count FROM paliad.deadline_rules WHERE submission_code = 'upc.inf.cfi.soc' AND is_active = true AND lifecycle_state = 'published' AND rule_code = 'RoP.013.1' AND legal_source = 'UPC.RoP.13.1'; IF v_count <> 1 THEN RAISE EXCEPTION 'mig 127 #99: upc.inf.cfi.soc not in post-fix shape (got % matches)', v_count; END IF; END $$;