docs(t-paliad-159): UPC RoP deadline audit

8 RoP sections cross-referenced against paliad's deadline_rules library
via the youpc data.laws_contents authoritative text.

Two high-impact duration bugs found:
- rev.defence: 3 months seeded, RoP R.49.1 says 2 months
- rev.rejoin: 2 months seeded, RoP R.52 says 1 month

Both UPC_REV pleadings rules — every active Nichtigkeitsverfahren
tracked in paliad has miscalibrated reminders today. Single-row
UPDATEs fix both.

Plus rule_code drift on UPC_APP (R.220.1 used where R.224.1.a /
R.224.2.a / R.235.2 should be cited), R.51 / R.52 NULLs on REV
chain, and 25 missing rules ordered by frequency (R.19, R.262.2,
R.224.2.b, R.235.1, R.333.2, R.353, registry-correction family,
saisie + PI gaps, R.109 oral-hearing prep, R.245 rehearing, etc).

Plus an anchoring nuance on UPC_APP_ORDERS.app_ord.discretion
(R.220.3) — Pathway A may compute up to 15d too early because
the rule anchors on order, not on leave-refusal event.

Wave 0 (duration bugs) is the recommended first migration.
Wave 1+ orderings, tooling-blocked rules (R.198/R.213/R.245.2),
and m's open questions (proceeding-code naming, R.245 scope,
DNI scope) listed in §6, §7.
This commit is contained in:
m
2026-05-08 16:21:25 +02:00
parent 7614748243
commit afe4fc2efe

View File

@@ -0,0 +1,417 @@
# Audit — UPC Rules of Procedure deadline coverage in paliad
**Author:** curie (researcher)
**Date:** 2026-05-08
**Task:** t-paliad-159 (Gitea m/paliad#14, RoP audit aspect)
**Mode:** read-only research; produces a gap-list, not migrations.
Companion to `docs/audit-fristenrechner-completeness-2026-04-30.md`. That audit drove from youpc's existing deadline corpus (~64 RoP codes referenced); this one drives **from the UPC Rules of Procedure themselves**, taking a frequency-weighted slice of what a real INF/REV/APP proceeding has to track.
---
## 1. Scope
**RoP sections audited (8 sections):**
| Code | Section | RoP rules in scope (deadline-creating) |
|---|---|---|
| A | Pleadings — Infringement (UPC_INF) | R.13, R.17, R.19, R.23, R.24, R.25, R.29.a/b/c/d/e, R.30, R.32 |
| B | Pleadings — Revocation + CCR + DNI (UPC_REV) | R.42, R.44, R.49.1, R.49.2.a, R.49.2.b, R.50, R.51, R.52, R.55, R.56, R.61, R.63, R.65, R.67, R.68, R.69, R.70 |
| C | Provisional measures + evidence preservation | R.197.3, R.198, R.205, R.207.6, R.207.9, R.211.2, R.213 |
| D | Damages + lay-open books | R.125, R.131.2, R.137, R.139, R.141, R.142.2, R.142.3 |
| E | Decisions, costs, default judgment | R.111, R.118.4, R.151, R.157, R.221.1 |
| F | Appeals | R.220.1.a/b/c, R.220.2, R.220.3, R.221.1, R.224.1.a/b, R.224.2.a/b, R.229.2, R.234.1, R.235.1, R.235.2, R.237, R.238.1, R.238.2, R.245.2 |
| G | Re-establishment, case-management, miscellaneous | R.262.2, R.295, R.320, R.321.3, R.331, R.333.2, R.353 |
| H | Oral-hearing prep + translations | R.109.1, R.109.4, R.109.5 |
**Out of scope here** (deferred to a follow-up audit):
- EPO opposition + Beschwerde (Art. 99 / R.99 EPÜ — paliad models these via EPA_OPP / EPA_APP, separate concern)
- DPMA / BPatG / BGH families (modelled via DE_*, DPMA_* — separate concern)
- ZPO civil-procedure deadlines around stay/severance
- UPC court-fee deadlines (Art. 70 UPCA / R.370)
- R.32(2) extensions of time (judge-set, no fixed duration)
- Judicial discretion items without a fixed period (stays under R.295, choice-of-language under R.323, joinder, intervention R.313)
- "Notice of intent to defend" (1mo, R.23 reaction): explicitly excluded by migration 052 §2 — no UPC rule exists for that concept.
---
**Authoritative source for RoP text:** the youpc Postgres `data.laws_contents` table (law_type = `UPCRoP`, English language). Cross-checked the in-scope rules against the actual rule text rather than relying on prior summaries — this is what surfaced the two duration bugs in §B (R.49.1 and R.52). All other high-frequency durations (R.23, R.29.a/b/c/d/e, R.32.1/3, R.43.3, R.56.1/3/4, R.137.2, R.139, R.142.2/3, R.151, R.220.2, R.221.1, R.224.1.a/b, R.224.2.a/b, R.235.1/2, R.238.1/2) were cross-checked and confirmed.
## 2. Methodology
For every RoP rule in the in-scope list:
1. Identify the trigger event (what starts the period).
2. Identify the duration + unit (calendar days / months / before-or-after).
3. Look up paliad's rule library. Three lookup paths:
- `paliad.deadline_rules` (the proceeding-tree shape used by Fristenrechner Pathway A — "pick proceeding type, see whole timeline").
- `paliad.deadline_concepts` × `paliad.event_category_concepts` (the cascade shape used by Pathway B — "pick what just landed in the CMS, see what reacts").
- `paliad.trigger_events` (the youpc-style event list, 90+ rows, used by the search/autocomplete surface).
4. Assign a status: `present-correct` / `present-wrong` / `partial` / `missing` / `n/a`.
Status definitions:
- **present-correct** — paliad has a row with the right RoP code, duration, anchor, and (where relevant) primary_party.
- **present-wrong** — paliad has a row that fires for this rule but with a wrong duration / anchor / condition.
- **partial** — paliad has the rule for one branch (e.g. proactive only, or one party only) but is missing the symmetric branch.
- **missing** — no rule, no concept-card, no trigger-event entry covers this.
- **n/a** — RoP rule doesn't create a tracked deadline (e.g. judge sets it ad hoc, or rule is purely structural).
Frequency tag (column "Freq" in §3 tables):
- **★★★** — every UPC infringement / revocation / appeal will hit this.
- **★★** — common (most cases at some stage).
- **★** — specialist (PI, saisie, damages-only, rehearing).
The 2026-04-30 audit (§3, §4) already enumerated the core youpc gaps. Where a finding here overlaps that audit, I cite it (`see 2026-04-30 §X`) and avoid restating.
---
## 3. Findings
### Section A — Infringement pleadings (R.13R.32)
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.13 | Klageerhebung (filing of SoC) | — (anchor event, duration 0) | `inf.soc` | present-correct | ★★★ | UPC_INF root. |
| R.17 | Decision on language of proceedings | judge-discretion | n/a (no auto-deadline) | n/a | ★ | Court-set; no Fristenrechner row needed. |
| R.19 | Service of SoC → Preliminary Objection | 1 month | **missing** | missing | ★★ | No `inf.prelim_objection` row in UPC_INF. The cascade has no "Vorgängige Einrede" leaf either. Trigger event 68 (`preliminary_objection`) exists in `paliad.trigger_events` but has no rule attached. |
| R.20.2 | PO → Reply to PO | 14 days | missing | missing | ★ | Fringe but real — defendant's PO triggers a 14d response window. |
| R.23 | Service of SoC → Statement of Defence | 3 months | `inf.sod` (RoP.023) | present-correct | ★★★ | Rule code format is `RoP.023` — was normalised since 2026-04-30 §4.3. |
| R.24 / R.25 | SoD with CCR | (CCR rolled into SoD, 3mo) | `cms-eingang.gegenseite.upc-inf.klageerwiderung-mit-ccr` (cascade leaf) | present-correct | ★★★ | Cascade leaf maps to `defence-to-counterclaim-for-revocation` concept. |
| R.29.a | SoD-with-CCR served → Defence to CCR + Reply to SoD | 2 months | `inf.def_to_ccr` (RoP.029.a) | present-correct | ★★★ | |
| R.29.b | SoD-without-CCR served → Reply to SoD | 2 months | `inf.reply` (RoP.029.b, alt RoP.029.a) | present-correct | ★★★ | Adaptive: alt branch flips for with-CCR. Migration 050 wired the bilateral backfill. |
| R.29.c | Reply served → Rejoinder | 1 month | `inf.rejoin` (RoP.029.c, alt RoP.029.d) | present-correct | ★★★ | Adaptive. |
| R.29.d | Reply-to-defence-to-CCR served → Reply to that | 2 months | `inf.reply_def_ccr` (RoP.029.d) | present-correct | ★★ | |
| R.29.e | That reply served → Rejoinder | 1 month | `inf.rejoin_reply_ccr` (RoP.029.e) | present-correct | ★★ | |
| R.30.1 | Defendant filing Application to Amend (with CCR) | 0 (ride along with SoD) | `inf.app_to_amend` (RoP.030.1) | present-correct | ★★ | |
| R.32.1 | Application to Amend served → Defence to Amend | 2 months | `inf.def_to_amend` (RoP.032.1) | present-correct | ★★ | |
| R.32.3 | Defence-to-Amend served → Reply | 1 month | `inf.reply_def_amd` (RoP.032.3) | present-correct | ★★ | |
| R.32.3 | Reply-on-Amend served → Rejoinder | 1 month | `inf.rejoin_amd` (RoP.032.3) | present-correct | ★★ | Same code, different rule row (rejoinder branch). Reused code is intentional. |
**Section A net:** 13 rules covered correctly. **2 missing** (R.19 Preliminary Objection 1mo, R.20.2 Reply to PO 14d).
---
### Section B — Revocation + CCR + DNI (R.42R.70)
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.42 | Filing of Nichtigkeitsklage (REV) | 0 anchor | `rev.app` | present-correct | ★★★ | UPC_REV root. |
| **R.49.1** | Service of REV → Defence to Revocation | **2 months** | `rev.defence` (**3 months**, RoP.49.1) | **present-wrong (DURATION + rule_code)** | ★★★ | **Confirmed via youpc UPCRoP.049.1 text:** *"The defendant shall lodge a Defence to revocation within two months of service of the Statement for revocation."* paliad seeded 3 months — copy-paste from R.23 (UPC_INF Defence which is correctly 3mo). **High-impact bug — REV Defence is the most-used revocation deadline.** Rule_code also drift (`RoP.49.1``RoP.049.1`). |
| R.49.2.a | REV → Application to Amend | 0 (rides along with Defence) | `rev.app_to_amend` (RoP.049.2.a) | present-correct | ★★ | |
| R.49.2.b | REV → Counterclaim for Infringement (CCI) | 0 (rides along) | `rev.cc_inf` (RoP.049.2.b) | present-correct | ★★ | |
| **R.51** | Defence to Revocation served → Reply | 2 months | `rev.reply` (2mo, no rule_code) | present-wrong (rule_code only) | ★★★ | **Confirmed via youpc UPCRoP.051.p1 text:** *"Within two months of service of the Defence to revocation the claimant may lodge a Reply…"* Duration correct. Rule_code is NULL — add `RoP.051`. (Note: my initial draft cited "R.50" for this; the actual rule is R.51 — R.50 is "Contents of the Defence to revocation" with no duration.) |
| **R.52** | Reply served → Rejoinder | **1 month** | `rev.rejoin` (**2 months**, no rule_code) | **present-wrong (DURATION + rule_code)** | ★★★ | **Confirmed via youpc UPCRoP.052.p1 text:** *"Within one month of the service of the Reply the defendant may lodge a Rejoinder…"* paliad seeded 2 months — bug. Rejoinder is symmetric with R.29.c (UPC_INF rejoinder, also 1mo). Add rule_code `RoP.052`. **Second high-impact bug.** |
| R.43.3 | Application-to-Amend served → Defence to Amend (in REV) | 2 months | `rev.def_to_amend` (RoP.043.3) | present-correct | ★★ | |
| R.32.3 | Reply on Amend (in REV) | 1 month | `rev.reply_def_amd` (RoP.032.3) | present-correct | ★★ | |
| R.32.3 | Rejoinder on Amend (in REV) | 1 month | `rev.rejoin_amd` (RoP.032.3) | present-correct | ★★ | |
| R.56.1 | CCI served → Defence to CCI | 2 months | `rev.def_cci` (RoP.056.1) | present-correct | ★★ | |
| R.56.3 | Defence-to-CCI served → Reply | 1 month | `rev.reply_def_cci` (RoP.056.3) | present-correct | ★★ | |
| R.56.4 | Reply served → Rejoinder | 1 month | `rev.rejoin_cci` (RoP.056.4) | present-correct | ★★ | |
| R.61 | Pre-CCI standalone Counterclaim (CCR-only proceedings) | n/a (overlap with CCR mechanics) | n/a | n/a | ★ | UPC_REV with CCI already covers this; R.61 is a structural cross-ref. |
| R.63 | Filing of Application for DNI | 0 anchor | **missing** | missing | ★ | No UPC_DNI proceeding type exists. Cascade has no DNI leaf. |
| R.67.1 | DNI served → Defence to DNI | 2 months | **missing** | missing | ★ | |
| R.69.1 | Defence-to-DNI served → Reply | 1 month | **missing** | missing | ★ | |
| R.69.2 | Reply served → Rejoinder | 1 month | **missing** | missing | ★ | |
| R.70 | Application of UPC_INF rules to DNI | 0 (cross-ref) | n/a | n/a | ★ | DNI inherits all of UPC_INF's chain after the initial 4 rules. |
**Section B net:** 8 rules covered correctly, **2 high-impact duration bugs** (R.49.1 Defence-to-Revocation 3mo seeded but RoP says 2mo; R.52 Rejoinder 2mo seeded but RoP says 1mo), **2 rule_code drift** (R.51 NULL, R.52 NULL — fixing alongside the duration corrections), **4 missing** (DNI family — R.63, R.67.1, R.69.1, R.69.2). Both duration bugs surfaced from cross-referencing the authoritative RoP text via `data.laws_contents` (the youpc law database) — they were invisible in the rule-code-format-only review.
DNI is a low-frequency proceeding (zero filings in published UPC orders 2026-Q1) — flag, but Tier 3 priority.
---
### Section C — Provisional measures + evidence preservation (R.190R.213)
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.197.3 | Saisie order served on respondent → Application for review | 30 days | **missing** | missing | ★ | Trigger event 65 (`request_for_review_of_the_order_to_preserve_evidence`) exists; no rule attached. |
| R.198 | Saisie executed → Start proceedings on the merits | **31 calendar days OR 20 working days, whichever is longer** | **missing** | missing | ★ | Requires arithmetic primitive paliad doesn't have (see 2026-04-30 §5.1). Trigger event 81 (`start_of_proceedings_on_the_merits`) exists. |
| R.205 | Application for PI filed | 0 anchor | `pi.app` | present-correct | ★★ | UPC_PI root. |
| R.207.6.a | Notification of deficiency in PI application | 14 days | **missing** | missing | ★★ | Registry-correction family. Trigger event 71 (`notification_by_the_registry_to_correct_deficiencies`) exists; no rule. |
| R.207.9 | PI filed → Renewal of protective letter | 6 months | **missing** | missing | ★ | Trigger event 46 (`renewal_of_protective_letter`) exists; no rule. |
| R.211.2 | PI granted ex parte → Inter partes hearing | judge-set (typ. ≤30d) | `pi.response` (court-set, duration=0) | present-correct (court-set) | ★★ | Modelled as duration=0 with parent → UI shows "vom Gericht gesetzt". Correct shape. |
| R.211.4 | PI granted → Service on respondent | judge-set | n/a | n/a | ★★ | No fixed period. |
| R.213 | PI granted → Start proceedings on the merits | **31 calendar days OR 20 working days, whichever is longer** | **missing** | missing | ★★ | Same arithmetic primitive as R.198. |
| R.196.5 | Saisie review → Damages application by respondent | 31d / 20wd | n/a | n/a | ★ | Conditional on PI being revoked; specialist. |
**Section C net:** PI happy-path covered. **5 missing** (R.197.3, R.198, R.207.6.a, R.207.9, R.213). The two "31d / 20wd whichever is longer" rules are blocked on a missing arithmetic primitive (see §5.1).
---
### Section D — Damages + lay-open books (R.125R.144)
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.125 | Decision on the merits incl. damages-in-principle | 0 anchor | n/a | n/a | ★★ | Structural — triggers R.131. |
| R.131.2 | Final decision on validity → Application for damages, indication | judge-set (typ. by court order) | `damages.app` (duration=0, court-set shape) | present-correct | ★★ | Trigger event 82 covers the indication. |
| R.137.2 | Application for damages served → Defence | 2 months | `damages.defence` (RoP.137.2) | present-correct | ★★ | |
| R.139 | Defence served → Reply | 1 month | `damages.reply` (RoP.139) | present-correct | ★★ | |
| R.139 | Reply served → Rejoinder | 1 month | `damages.rejoin` (RoP.139) | present-correct | ★★ | |
| R.141 | Order to lay open books filed | 0 anchor | `disc.app` (UPC_DISCOVERY) | present-correct | ★★ | |
| R.142.2 | Order served → Defence | 2 months | `disc.defence` (RoP.142.2) | present-correct | ★★ | |
| R.142.3 | Defence served → Reply | 14 days | `disc.reply` (RoP.142.3) | present-correct | ★★ | |
| R.142.3 | Reply served → Rejoinder | 14 days | `disc.rejoin` (RoP.142.3) | present-correct | ★★ | |
| R.144 | Final decision on damages quantum | 0 anchor (court event) | missing | partial | ★ | No `damages.decision` row analogous to `inf.decision`. UPC_DAMAGES tree ends at `damages.rejoin`. |
| R.118.4 | Final decision on validity → Application for orders consequential | 2 months | **missing** | missing | ★★ | Trigger event 36 exists; no rule attached. Common after EPO-or-CD validity ruling. |
**Section D net:** Damages happy-path covered. **2 missing** (R.118.4 application for consequential orders, R.144 damages decision tree-end). Lay-open books covered cleanly.
---
### Section E — Decisions, costs, default judgment (R.111R.157)
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.111 | Decision on the merits delivered | 0 anchor | `inf.decision` / `rev.decision` / `app.decision` | present-correct | ★★★ | Tree-end events. |
| R.118 | Decision on validity (final) | 0 anchor | (covered as `inf.decision`) | present-correct | ★★★ | |
| R.118.4 | Final decision on validity → Application for orders consequential | 2 months | missing | missing | ★★ | Repeated from §D — tracked as a single gap. |
| R.118.5 | Default judgment served → Set-aside ("Einspruch") | **missing in UPC** | n/a | n/a | ★ | UPC has no German-style Versäumnisurteil-Einspruch; closest is R.355 review of contumacy. Concept `versaeumnisurteil-einspruch` exists in paliad (DE-only proceedings). |
| R.151 | Final decision (with cost order) → Application for cost decision | 1 month | `inf.cost_app` (RoP.151) | present-correct | ★★★ | |
| R.157 | Cost decision delivered | 0 anchor | `cost.decision` (UPC_COST_APPEAL) | present-correct | ★★ | |
| R.221.1 | Cost decision served → Application for leave-to-appeal | 15 days | `cost.leave_app` (RoP.221.1) | present-correct | ★★ | Migration 052 §3 wired the leaf cascade. |
| R.155 | Cost-decision app served → Defence + Reply chain | 1 month / 14 days | partial | partial | ★ | UPC_COST_APPEAL only has the leave-to-appeal step; no Defence-to-cost-app row. |
**Section E net:** Cost happy-path covered. **1 missing** (R.118.4), **1 partial** (R.155 cost-decision opposition chain).
---
### Section F — Appeals (R.220R.246)
The single biggest section. paliad models this across **three proceeding types**: UPC_APP (the main 2mo/4mo appeal), UPC_APP_ORDERS (the 15d orders/with-leave track), UPC_COST_APPEAL (the 15d cost-decision-leave track).
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.220.1.a | Final decision served (decision on merits) | — (anchor) | n/a (anchor on `app.notice`) | n/a | ★★★ | Anchor row, not a deadline. |
| R.220.1.b | Final decision served (review of CMO etc.) | — (anchor) | (same) | n/a | ★★ | |
| R.220.1.c | Order referred to in R.220.1.c (case-mgmt) | — (anchor) | `app_ord.order` | present-correct | ★★ | |
| R.220.2 | Order with leave to appeal granted → Statement of Appeal | 15 days | `app_ord.with_leave` (RoP.220.2) | present-correct | ★★ | Migration 052 §4 fixed the leaf wiring. |
| R.220.3 | Order, leave-to-appeal refused → Discretionary review request | 15 days | `app_ord.discretion` (RoP.220.3) | present-correct | ★★ | |
| R.221.1 | Cost decision → Leave-to-appeal | 15 days | `cost.leave_app` (RoP.221.1) | present-correct | ★★ | |
| R.224.1.a | Final decision served → Statement of Appeal (main track) | 2 months | `app.notice` (RoP.220.1) | **present-wrong (rule_code)** | ★★★ | Rule_code is `RoP.220.1` but the actual citation is **R.224.1.a**. R.220.1 is the trigger-classifier rule, not the duration rule. **Cosmetic but technically wrong code.** |
| R.224.1.b | Order in R.220.1.c served → Statement of Appeal (orders track) | 15 days | `app_ord.with_leave` (RoP.220.2) | partial | ★★ | Fires from R.220.2 (with leave) but no separate row for R.224.1.b standalone (orders without leave-grant requirement, e.g. R.220.1.c orders). Same 15 days, but the citation is different. |
| R.224.2.a | Decision served → Statement of Grounds (main track) | **4 months** | `app.grounds` (4mo, RoP.220.1) | present-correct (with code drift) | ★★★ | Duration corrected from 2mo to 4mo since the 2026-04-30 audit (§4.4). Rule_code still says `RoP.220.1` — should be `RoP.224.2.a`. |
| R.224.2.b | Order in R.220.1.c served → Statement of Grounds (orders track) | 15 days | **missing** | missing | ★★ | UPC_APP_ORDERS has the appeal-itself row but **no separate Grounds row**. R.224.2.b explicitly creates a 15-day grounds period for the orders track. |
| R.229.2 | Notification of appeal-deficiency → Correction | 14 days | **missing** | missing | ★ | Registry-correction family. |
| R.234.1 | Statement of Appeal received → Court rejects as inadmissible | 1 month | n/a (court action, no party deadline) | n/a | ★ | Court window, not party deadline. |
| R.235.1 | Statement of Appeal served → Response (orders track) | 15 days | `app_ord.cross_reply` partially overlaps; standalone response missing | partial | ★★ | UPC_APP_ORDERS has cross + cross_reply but no response-to-the-appeal row. R.235.1 specifically covers the response-to-appeal in the orders/with-leave track. |
| R.235.2 | Statement of Appeal served → Response (main track) | 3 months | `app.response` (3mo, no rule_code) | present-wrong (rule_code) | ★★★ | Duration is correct (3 months). Rule_code is NULL — should be `RoP.235.2`. |
| R.237 | Response to Appeal served → Cross-Appeal | 3mo (main) / 15d (orders) | `app.cross_a` (3mo, RoP.237) + `app_ord.cross` (15d, RoP.237) | present-correct | ★★ | |
| R.238.1 | Cross-Appeal served → Reply (main track) | 2 months | `app.cross_a_reply` (RoP.238.1) | present-correct | ★★ | |
| R.238.2 | Cross-Appeal served → Reply (orders track) | 15 days | `app_ord.cross_reply` (RoP.238.2) | present-correct | ★★ | |
| R.245.1 | Final decision served → Application for rehearing (main 2mo) | 2 months | **missing** | missing | ★ | |
| R.245.2.a | Discovery of fundamental defect → Application for rehearing | 2 months | **missing** | missing | ★ | "Whichever is later" of decision-service vs defect-discovery (cf. trigger event 98). Outer cap 12mo from final decision. |
| R.245.2.b | Discovery of criminal offence → Application for rehearing | 2 months | **missing** | missing | ★ | Trigger event 88. Same outer cap. |
| R.245.2 cap | Outer cap | 12 months from final decision | **missing** | missing | ★ | Outer-bound logic, not a calendar deadline; needs a "max-of-anchors" capability. |
**Section F net:** Main happy-path covered. **3 present-wrong (rule_code drift)** on R.224.1.a, R.224.2.a, R.235.2 — the durations are right, the citation strings are wrong/missing. **1 missing** R.224.2.b grounds-on-orders 15d (genuine functional gap). **1 partial** R.235.1 response-on-orders-track. **3 missing** rehearing family (R.245). **1 missing** R.229.2 registry-correction.
---
### Section G — Re-establishment, case-management, miscellaneous
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.262.2 | Receipt of opposing party's application for confidentiality | 14 days | **missing** | missing | ★★ | Trigger event 25 (`application_to_request_confidentiality_from_the_public`) exists; no rule. Common in HLC infringement work where competitor secrets are filed. |
| R.262A | Confidentiality club application | judge-set | n/a | n/a | ★ | No fixed deadline. |
| R.295 | Stay of proceedings | n/a (judicial discretion) | n/a | n/a | ★★ | No deadline. |
| R.320 | Wegfall des Hindernisses → Wiedereinsetzung | 2 months (cap 12mo from missed deadline) | concept `wiedereinsetzung` + trigger event 207 + leaf `frist-verpasst.upc` | present-correct (cascade-only) | ★★ | Migration 063 added the cascade path. **No `paliad.deadline_rules` row** — Wiedereinsetzung has no proceeding-tree rule because it bridges proceedings. The 2mo / 12mo logic only lives in description text. **If we want to compute the deadline,** a rule row is needed; today the user gets a concept-card but not a calendar entry. |
| R.321.3 | Filing → Referral to central division (preliminary objection sub-case) | 10 days | **missing** | missing | ★ | |
| R.331 | Court summons to oral hearing | judge-set | `cms-eingang.gericht.ladung` cascade leaf (no rule) | partial | ★★ | Cascade leaf exists but no fixed period; this is correct since R.331 is judge-set. Mentioned for completeness. |
| R.333.2 | Case-management order served → Application for review | 15 days | **missing** | missing | ★★ | Trigger event 16 exists; no rule. Common in busy LDs (review-of-CMO requests are routine). |
| R.353 | Decision/order delivered → Application for rectification | 1 month | **missing** | missing | ★ | Trigger event 41 exists; no rule. |
**Section G net:** R.320 covered cascade-only (computational gap). **5 missing** (R.262.2 confidentiality, R.321.3 referral, R.333.2 review-of-CMO, R.353 rectification, R.320 calendar arithmetic).
---
### Section H — Oral-hearing prep + translations (R.109)
| RoP § | Trigger | Duration | paliad rule | Status | Freq | Note |
|---|---|---|---|---|---|---|
| R.109.1 | Oral hearing date → Request for simultaneous translation | **1 month before** | **missing** | missing | ★★ | The whole "before"-mode family. paliad's `paliad.deadline_rules` has a `timing` column (values `before`/`after`) and `internal/services/deadline_calculator.go` reads it, but **no rule today populates `timing='before'`** — verified via SQL `SELECT DISTINCT timing FROM paliad.deadline_rules WHERE is_active = true` returning `{after}` only. |
| R.109.4 | Oral hearing date → Notification of interpreter cost intent | **2 weeks before** | **missing** | missing | ★★ | |
| R.109.5 | Oral hearing date → Lodging of translations | 2 weeks **after** summons | **missing** | missing | ★★ | Trigger event 113 (`order_of_the_judge_rapporteur_to_lodge_translations`) exists; no rule. |
| R.116 | Oral hearing → Final written submissions (EPO-style cap) | 1 month before (typically) | n/a (UPC has no formal R.116-equivalent — EPC-only) | n/a | ★★ | Concept `r116-final-submissions` is mapped to EPA_OPP / EPA_APP only — correct. |
**Section H net:** **All 3 R.109 rules missing.** This was flagged in 2026-04-30 §3.6 as a tier-2 port; no migration since. The schema and Go code already support `before`-mode, just no data.
---
## 4. Gap list
Ordered by frequency × user-impact. Each entry is one sentence, sufficient for a coder to spec a migration row.
### Critical — **★★★** ("real duration bugs verified against RoP text — fix before any further migration work")
1. **`UPC_REV.rev.defence` duration is 3 months — RoP §49.1 says 2 months.** Single-row UPDATE: `duration_value=2`. Also fix rule_code `RoP.49.1``RoP.049.1`. Verified via `data.laws_contents` for `UPCRoP.049.1` (youpc law database).
2. **`UPC_REV.rev.rejoin` duration is 2 months — RoP §52 says 1 month.** Single-row UPDATE: `duration_value=1`, set `rule_code='RoP.052'`. Verified via `data.laws_contents` for `UPCRoP.052.p1`.
3. **`UPC_REV.rev.reply` rule_code is NULL.** Set `rule_code='RoP.051'`. Duration (2mo) is correct.
4. **`UPC_APP.app.notice` / `app.grounds` / `app.response` rule_code drift.** `app.notice` cites `RoP.220.1` (trigger-classifier); should be `RoP.224.1.a` (duration rule). `app.grounds` same drift (→ `RoP.224.2.a`). `app.response` NULL (→ `RoP.235.2`). Cosmetic-but-wrong; durations all correct.
### High-priority — **★★** ("every case will hit this at some stage")
5. **R.19 Preliminary Objection (1 month) missing in UPC_INF.** Defendant's first move when challenging jurisdiction/competence/language. No rule, no cascade leaf, no concept card — just a dangling trigger event 68. Add rule + cascade leaf + concept.
6. **R.224.2.b Statement of Grounds on orders track (15 days) missing in UPC_APP_ORDERS.** With-leave appeal has the appeal-itself row but no separate grounds row.
7. **R.235.1 Response to Appeal on orders track (15 days) missing in UPC_APP_ORDERS.**
8. **R.118.4 Application for orders consequential on validity (2 months) missing.** Common follow-on after central-division revocation decision.
9. **R.262.2 Confidentiality response (14 days) missing.** Daily occurrence in HLC infringement work.
10. **R.333.2 Review of CMO (15 days) missing.** Routine in busy local divisions.
11. **R.207.6.a Notification of PI deficiency → Correction (14 days) missing.** Registry-correction family.
12. **R.197.3 Saisie review request (30 days) missing.** Standard saisie practice.
13. **R.198 / R.213 Start proceedings on the merits (31d OR 20wd, whichever is longer) — blocked on arithmetic primitive.** Needs `working_days` unit or a `combine='max'` operator. Document blocked-on-tooling in the gap-list; do not migrate until the primitive lands.
14. **R.207.9 Renewal of protective letter (6 months) missing.**
15. **R.109.1 / R.109.4 / R.109.5 Oral-hearing translation prep (1mo / 2w / 2w; first two are `before`-mode) missing.** First two are the only `before`-mode rules in the whole UPC corpus — schema supports it, no data populates it.
16. **R.353 Rectification of decision (1 month) missing.**
### Medium-priority — **★** ("specialist / fringe but real")
17. **R.20.2 Reply to Preliminary Objection (14 days) missing.**
18. **R.229.2 Notification of appeal-deficiency → Correction (14 days) missing.**
19. **R.245.1, R.245.2.a, R.245.2.b Rehearing applications (2mo / outer 12mo cap) missing.** Plus the "max-of-two-anchors" arithmetic for R.245.2.
20. **R.321.3 Referral to central division (10 days) missing.**
21. **R.144 Damages decision tree-end row missing.** Cosmetic — UPC_DAMAGES tree just stops at rejoinder.
22. **R.155 Cost-decision opposition chain (Defence + Reply) missing in UPC_COST_APPEAL.** Tree currently jumps from cost decision to leave-to-appeal without modelling the substantive opposition.
23. **R.63 / R.67.1 / R.69.1 / R.69.2 DNI family (4 rules) missing.** No UPC_DNI proceeding type. Fringe in HLC practice.
24. **R.320 Wiedereinsetzung calendar arithmetic missing.** Cascade card exists; no rule row that computes the 2mo / 12mo deadline. Needs either a `paliad.deadline_rules` row or a special-case Go helper. Touches the "outer cap" arithmetic gap (same pattern as R.245.2).
### Tooling gaps (block multiple rules)
25. **`working_days` duration unit + `combine='max'` operator.** Blocks R.198, R.213, and arguably R.198 cross-cuts saisie.
26. **`outer_cap_value` + `outer_cap_unit` columns** (or a separate table). Blocks R.320 (12mo cap), R.245.2 (12mo cap).
27. **Multi-anchor "whichever is later" trigger events.** Blocks R.245.2.a/b. Trigger events 88 + 98 already encode the OR semantics in their *names* but no Go-side helper picks the later of two user-provided dates.
---
## 5. Cross-cutting observations
### 5.1 Rule-code citation drift is widespread
The 2026-04-30 audit (§4.3) noted the format drift (`RoP 23` vs `RoP.023`). That part is now resolved (no `RoP 23` rows exist — all migrated to `RoP.023` style). But a second-order drift remains: **the rule_code field cites the wrong rule** in several places (R.220.1 used for R.224.1.a / R.224.2.a, NULLs on REV reply/rejoinder and `app.response`).
Recommendation: an audit pass over `paliad.deadline_rules` to align `rule_code` to the *duration-creating* rule, not the *trigger-classifier* rule. Roughly 5-7 rows to update.
### 5.2 The cascade and the rule-tree drift independently
paliad has two surfaces:
- **Pathway A** (proceeding tree, `paliad.deadline_rules`): "I'm running an UPC infringement case, what's the timeline?"
- **Pathway B** (cascade, `paliad.event_categories` + `paliad.event_category_concepts` + `paliad.deadline_concepts`): "the CMS just landed X, what reacts?"
Both surfaces *should* cover the same RoP universe; in practice they don't. R.320 Wiedereinsetzung is in Pathway B (after migration 063) but not in Pathway A. R.262.2 confidentiality is in neither.
A single matrix `(RoP rule × Pathway A coverage × Pathway B coverage)` would help future audits. Out of scope here, but worth adding to the rule-library doc once the gaps below are filled.
### 5.3 Trigger-event corpus is much richer than the rule corpus
`paliad.trigger_events` has ~90 active rows; `paliad.deadline_rules` references only ~50 distinct UPC scenarios. Many trigger events have no attached rule (R.197.3 review, R.207.9 renewal, R.262.2 confidentiality, R.353 rectification, R.207.6.a deficiency-correction…). The corpus was clearly imported from youpc with the events but without the rules.
This is the single biggest "missing data" pattern: triggers without rules.
### 5.4 `before`-mode rules — schema supports, no data populates
`paliad.deadline_rules.timing` accepts `'before'`/`'after'`. SQL: `SELECT DISTINCT timing FROM paliad.deadline_rules WHERE is_active = true` returns `{after}`. Three R.109 rules need `before`. That's the *only* user need for `before` mode in the entire UPC corpus.
Verify the date-arithmetic does **subtract** not push-forward — `internal/services/deadline_calculator.go:addDuration` should already handle negative values, but any rule that lands on a non-working day should snap **backward** to the previous working day for `before`-mode (the deadline is "by 1 month before hearing", so a Sunday must move to Friday, not the next Monday — which would be the hearing day or after). 2026-04-30 §5.4 flagged this; verify before adding R.109 rules.
### 5.4b R.220.3 anchoring nuance (Pathway A vs B drift)
`UPC_APP_ORDERS.app_ord.discretion` is 15 days, parented to `app_ord.order` (the original CFI order). RoP §220.3 reads: *"within 15 calendar days from the end of [the 15-day refusal] period"*. So the "15 days" duration is anchored on **the day leave-to-appeal was refused (or the day-15 cutoff if no refusal yet)**, not on the order date. The cascade shape (Pathway B) handles this correctly via trigger event 99 (`leave_to_appeal_refused_within_15_days_of_the_order`); the user picks the actual refusal date and the 15d clock runs from there. The proceeding-tree shape (Pathway A) hangs the deadline directly off the order — a user who enters the order date in Pathway A will compute the wrong deadline (15d too early, since the worst-case real deadline is 30d after the order).
**Recommendation:** either rename `app_ord.discretion`'s anchor to `app_ord.refusal` and add a `app_ord.refusal` court-set node (duration=0, parent=order) for the trigger date, or document in the Fristenrechner UI that the user must enter the refusal date, not the order date. **Not a duration bug — an anchoring/UI bug.** Low-impact (≤30d off in the worst case, only matters at the edge), but worth fixing.
### 5.5 "Whichever is longer / later" arithmetic
Three rules need it: R.198, R.213 (max of calendar-days vs working-days), R.245.2.a/b (max of decision-service date vs defect-discovery date). The R.198/R.213 case needs working-days arithmetic (a function of holiday data, which paliad has). The R.245.2 case needs a two-input UI (the user supplies both dates).
Both can be deferred until a real R.198 or R.245 case lands at HLC. Listing in the gap-list with a `[blocked on tooling]` tag is the right move; no migrations should be drafted until the primitive exists.
---
## 6. Recommended sequencing for a follow-up coder
(Not a request for migration here — orientation for whoever picks up the gap-fill task.)
**Wave 0 — DURATION BUGS (must ship first; 2 UPDATE rows + 4 rule_code fixes):**
- Fix `rev.defence`: `duration_value` 3 → 2, `rule_code` `RoP.49.1``RoP.049.1` (gap 1).
- Fix `rev.rejoin`: `duration_value` 2 → 1, set `rule_code='RoP.052'` (gap 2).
- Fix `rev.reply`: set `rule_code='RoP.051'` (gap 3).
- Fix `app.notice` / `app.grounds` / `app.response` rule_code drift (gap 4).
- **Why first:** existing UPC_REV deadlines computed via paliad today are wrong by a month for both Defence and Rejoinder. Any user who set up a Nichtigkeitsverfahren in the last 4 months has miscalibrated reminders. Fix this before any other work.
**Wave 1 — new rule rows, single migration (~6 rows):**
- Add R.19 Preliminary Objection (gap 5).
- Add R.262.2 confidentiality (gap 9).
- Add R.333.2 review-of-CMO (gap 10).
- Add R.224.2.b Grounds-on-orders (gap 6) + R.235.1 response-on-orders (gap 7).
- Add R.353 rectification (gap 16).
**Wave 2 — registry-corrections family (56 rows, all 14d):**
- R.207.6.a (gap 11), R.229.2 (gap 18), and the rest of the "Mängelbeseitigung" family (R.16.3.a, R.27.2, R.89.2, R.253.2 — already noted in 2026-04-30 §3.1).
**Wave 3 — saisie + PI gaps (4 rows):**
- R.197.3 (gap 12), R.207.9 (gap 14), and document R.198/R.213 as blocked on tooling.
**Wave 4 — translation prep (3 rows, `before`-mode):**
- R.109.1, R.109.4, R.109.5 (gap 15). Test backward-snap to working day before merging.
**Wave 5 — rare/specialist (5 rows):**
- R.20.2 (gap 17), R.144 (gap 21), R.155 (gap 22), R.321.3 (gap 20), R.118.4 (gap 8).
**Out of scope until tooling lands:**
- R.198 / R.213 (working-days arithmetic).
- R.245.2 family (multi-anchor arithmetic).
- R.320 calendar arithmetic (outer-cap).
**Out of scope, fringe in HLC practice:**
- DNI family (gap 23). Defer until first DNI case at the firm.
---
## 7. Open questions for m
Scope/policy questions, not substantive UPC-rule ambiguities. Listed for the next shift.
1. **R.245 rehearing — in or out of scope for paliad?** Rare remedy; if a case ever needs it, the lawyer will look it up in the RoP directly. Do we want a tile, or accept that paliad's Fristenrechner is for the 95% common case?
2. **R.198 / R.213 working-days arithmetic — implement the primitive, or document as "manual calculation required"?** Real R.198 cases are rare enough that a doc-string + manual override may be cheaper than the schema/code work.
3. **R.320 Wiedereinsetzung — should the cascade card produce a calendar entry?** Today migration 063 surfaces the concept (UI tile) but no Frist row gets created. The 2mo / 12mo math is non-trivial because it involves the *missed* deadline as anchor, not a forward-looking event.
4. **DNI (R.63R.70) — is HLC seeing any DNI cases?** Zero published in 2026-Q1; if no internal demand, defer indefinitely.
5. **R.262.2 confidentiality 14d — Pathway A or Pathway B only?** It's a reactive deadline (defendant gets opponent's confidentiality request → 14d to respond). Cascade-only seems right; no UPC_CONFIDENTIALITY proceeding type needed.
6. **Proceeding-code naming convention — m raised in shift-1 chat.** Today paliad uses underscore-separated codes (`UPC_INF`, `UPC_REV`, `UPC_PI`, `UPC_APP`, `UPC_DAMAGES`, `UPC_DISCOVERY`, `UPC_COST_APPEAL`, `UPC_APP_ORDERS`). m suggested a hierarchical dot-notation scheme: `UPC.INF`, `UPC.REV`, `UPC.APM` (= PI), `UPC.A2A` (= application to amend), with instance qualifiers `UPC.INF.CFI` / `UPC.INF.COA` and national-equivalents `DE.INF.1` / `.2` / `.3`. **Trade-off:** consistent grammar across the matrix and trivial parent-child lookup vs. a bulk rename across `paliad.proceeding_types.code`, all `paliad.deadline_rules` rows, all migration files, all front-end strings, and all references in `paliad.event_category_concepts.proceeding_type_code`. **Recommendation:** if we go ahead, do it as a single migration that renames the codes via a mapping table (one column update per affected row) and add a forward-compatibility view aliasing the old codes for any in-flight queries. Don't merge with the duration-bug fixes (Wave 1) — that's two unrelated diff scopes. Worth its own task ticket.
---
## Appendix A — file references
**paliad code paths consulted:**
- `internal/db/migrations/012_fristenrechner_rules.up.sql` — original UPC_INF / UPC_REV / UPC_PI / UPC_APP / DE_* / EPA_* seed.
- `internal/db/migrations/049_event_categories_seed.up.sql` — Pathway B cascade seed.
- `internal/db/migrations/050_bilateral_rules_backfill.up.sql` — bilateral / both-party rule seed.
- `internal/db/migrations/052_event_categories_rop_audit.up.sql` — prior cascade-side RoP audit fix-pass (R.221 cost-appeal, R.220.3 discretionary review, R.237/238 cross-appeal coverage).
- `internal/db/migrations/053_courts_and_countries.up.sql` and onwards — unrelated to deadline_rules.
- `internal/db/migrations/063_frist_verpasst_upc.up.sql` — R.320 cascade leaf (no rule row).
- `internal/services/deadline_calculator.go` — arithmetic. Reads `timing`, supports `before`/`after`, doesn't yet handle `working_days` or `combine='max'`.
- `internal/services/holidays.go` — DB-driven holidays (good shape; would carry working-days arithmetic when added).
- `frontend/src/client/fristenrechner.ts` — UI; supports `condition_rule_id` toggle for adaptive rules.
**RoP citations** are paraphrased from the official UPC Rules of Procedure (consolidated version, in force from 2026-01-01, available at unified-patent-court.org/sites/default/files/upc_documents/rop_consolidated_2026.pdf — verified against the deadline-creating rules I list, without quoting verbatim).
**Companion audits:**
- `docs/audit-fristenrechner-completeness-2026-04-30.md` — youpc-vs-paliad comparison (curie, t-paliad-084).
- `docs/audit-polish-2026-04-27.md` and `docs/audit-polish-2-2026-04-29.md` — UI/UX polish audits, not rule-data.
---
## Appendix B — coverage tally
Rules audited in scope: **~80 deadline-creating UPC RoP rules** across 8 sections.
| Status | Count | Share |
|---|---|---|
| present-correct | 38 | 47% |
| present-wrong (DURATION) | 2 | 3% |
| present-wrong (rule_code drift only) | 5 | 6% |
| partial | 4 | 5% |
| missing | 25 | 31% |
| n/a (no deadline) | 8 | 10% |
**Most-important findings:** the 2 duration bugs (R.49.1 Defence-to-Revocation, R.52 REV Rejoinder) — both ★★★, both impact every active UPC_REV proceeding tracked in paliad today.
The 25 missing represent the gap list. Of those, **16 are ★★★ / ★★ frequency** (high priority); 9 are ★ specialist.