Verfahrensablauf: R.109.1/R.109.4 deadlines mis-anchored + duplicate Simultanübersetzung row (upc.inf.cfi) #135

Open
opened 2026-05-26 13:36:52 +00:00 by mAi · 0 comments
Collaborator

Repro

https://paliad.de/tools/verfahrensablauf?side=defendant — pick proceeding upc.inf.cfi, any trigger date (e.g. SoC = 26.05.2026). The timeline renders three R.109-related events with dates that don't make legal sense:

Antrag auf Simultanübersetzung      Mo., 27.04.2026   UPC RoP R.109(1)   1 month before oral hearing
Antrag auf Simultanübersetzung      Mo., 27.04.2026   UPC RoP R.109(1)   (DUPLICATE row, identical)
Mitteilung Dolmetscherkosten        Di., 12.05.2026   UPC RoP R.109(4)   2 weeks before oral hearing
Klageerhebung                       Di., 26.05.2026   UPC RoP R.13(1)    Statement of Claim — TRIGGER

Bugs

Bug 1 — wrong anchor (most important)

R.109.1 and R.109.4 are defined as timing='before' with parent_id pointing to upc.inf.cfi.oral (the oral hearing rule) — see internal/db/migrations/132_wave1_tier1_rule_additions.up.sql:340-394. So in the rule data, they're correctly modeled as "1 month / 2 weeks before the oral hearing".

The rendered dates suggest the calc engine is anchoring them on the trigger date (SoC) instead of on the parent rule's computed date (oral hearing). Effect: R.109 deadlines end up in April 2026 (before the SoC of 26.05.2026), which is nonsensical — you can't file a translation request for an oral hearing before the lawsuit even exists.

Likely fix surface: pkg/litigationplanner/engine.go (or internal/services/fristenrechner.go legacy path) — the part that walks parent_id and computes the base for timing='before' rules. For child-of-parent rules with timing='before', the base should be the parent's computed date, not the trigger date.

Bug 2 — duplicate Simultanübersetzung row

The same R.109.1 event renders twice with identical content (date, citation, description, ↔ beide Seiten indicator). Worker should determine:

  • Is the rule inserted twice in the DB? (SELECT * FROM paliad.deadline_rules WHERE submission_code = 'upc.inf.cfi.translation_request' AND is_active = true — should return 1 row, not 2.)
  • Or is the render layer iterating the same rule twice (e.g. once per primary_party='both' perspective and not deduping)?

Given the rule's primary_party='both', my guess is the renderer is emitting one row for the user's side AND a mirror row for the opponent side, but failing to merge them on the both indicator. Compare with how other primary_party='both' rules (like Klageerwiderung placeholder) render — they should NOT duplicate.

Bug 3 — chronological ordering

Klageerhebung (the trigger event itself) renders at the bottom of the list. Conceptually, the trigger should appear first (everything is downstream of it). After Bug 1 is fixed, this ordering issue resolves itself naturally because R.109 deadlines will move to after the oral hearing (i.e. far in the future, not before the SoC). But worth confirming the sort key is date ASC not something else.

Worker scope

  1. Audit live: run mcp__supabase__execute_sql to confirm there's exactly one row for submission_code='upc.inf.cfi.translation_request' and upc.inf.cfi.interpreter_cost with lifecycle_state='published' AND is_active=true. Surface findings as a comment on this issue.
  2. Identify the anchor bug in pkg/litigationplanner/engine.go — find where timing='before' + parent_id is resolved, and verify whether the engine uses parent.computedDate or falls back to triggerDate. Add a unit test that reproduces the bug (synthetic rules + expected dates) before fixing.
  3. Identify the duplicate — bisect: is it data (DB row count) or rendering (frontend or lookup_events projection)?
  4. Fix both — minimal, targeted patches. Tests must lock the correct behaviour for at least these three rules: trigger event (SoC) → child before rule (translation_request) → grand-child rule (none here, but verify chains work).
  5. Manual verification in the worktree: a screenshot or curl test that the repro URL now renders R.109.1 and R.109.4 after the oral hearing (upc.inf.cfi.oral date), with no duplicates.

Acceptance

  1. https://paliad.de/tools/verfahrensablauf?side=defendant on upc.inf.cfi shows Klageerhebung first, then the rest of the chain in chronological order, and the R.109 events render after the oral hearing.
  2. No duplicate Simultanübersetzung row.
  3. go test ./pkg/litigationplanner/... ./internal/services/fristenrechner_*_test.go green, including a new test locking the before-parent anchor behaviour.
  4. No data migration unless audit reveals a real DB-level duplicate (in which case a small UPDATE-or-archive migration with set_config('paliad.audit_reason',…) is appropriate).

Anti-patterns to avoid

  • DON'T touch the rule data unless step 1 confirms a real DB duplicate.
  • DON'T write a migration with phantom column references (updated_at doesn't exist on proceeding_types; verify deadline_rules columns before any UPDATE).
  • DON'T skip set_config('paliad.audit_reason',…) if you do end up UPDATEing deadline_rules.
## Repro https://paliad.de/tools/verfahrensablauf?side=defendant — pick proceeding `upc.inf.cfi`, any trigger date (e.g. SoC = 26.05.2026). The timeline renders three R.109-related events with dates that don't make legal sense: ``` Antrag auf Simultanübersetzung Mo., 27.04.2026 UPC RoP R.109(1) 1 month before oral hearing Antrag auf Simultanübersetzung Mo., 27.04.2026 UPC RoP R.109(1) (DUPLICATE row, identical) Mitteilung Dolmetscherkosten Di., 12.05.2026 UPC RoP R.109(4) 2 weeks before oral hearing Klageerhebung Di., 26.05.2026 UPC RoP R.13(1) Statement of Claim — TRIGGER ``` ## Bugs ### Bug 1 — wrong anchor (most important) R.109.1 and R.109.4 are defined as `timing='before'` with `parent_id` pointing to `upc.inf.cfi.oral` (the oral hearing rule) — see `internal/db/migrations/132_wave1_tier1_rule_additions.up.sql:340-394`. So in the rule data, they're correctly modeled as "1 month / 2 weeks before the oral hearing". The rendered dates suggest the calc engine is anchoring them on the **trigger date (SoC)** instead of on the **parent rule's computed date (oral hearing)**. Effect: R.109 deadlines end up in *April 2026* (before the SoC of 26.05.2026), which is nonsensical — you can't file a translation request for an oral hearing before the lawsuit even exists. Likely fix surface: `pkg/litigationplanner/engine.go` (or `internal/services/fristenrechner.go` legacy path) — the part that walks `parent_id` and computes the base for `timing='before'` rules. For child-of-parent rules with `timing='before'`, the base should be the parent's computed date, **not** the trigger date. ### Bug 2 — duplicate Simultanübersetzung row The same R.109.1 event renders twice with identical content (date, citation, description, *↔ beide Seiten* indicator). Worker should determine: - Is the rule inserted twice in the DB? (`SELECT * FROM paliad.deadline_rules WHERE submission_code = 'upc.inf.cfi.translation_request' AND is_active = true` — should return 1 row, not 2.) - Or is the render layer iterating the same rule twice (e.g. once per `primary_party='both'` perspective and not deduping)? Given the rule's `primary_party='both'`, my guess is the renderer is emitting one row for the user's side AND a mirror row for the opponent side, but failing to merge them on the `both` indicator. Compare with how other `primary_party='both'` rules (like `Klageerwiderung` placeholder) render — they should NOT duplicate. ### Bug 3 — chronological ordering Klageerhebung (the trigger event itself) renders at the **bottom** of the list. Conceptually, the trigger should appear first (everything is downstream of it). After Bug 1 is fixed, this ordering issue resolves itself naturally because R.109 deadlines will move to *after* the oral hearing (i.e. far in the future, not before the SoC). But worth confirming the sort key is `date ASC` not something else. ## Worker scope 1. **Audit live**: run `mcp__supabase__execute_sql` to confirm there's exactly one row for `submission_code='upc.inf.cfi.translation_request'` and `upc.inf.cfi.interpreter_cost` with `lifecycle_state='published' AND is_active=true`. Surface findings as a comment on this issue. 2. **Identify the anchor bug** in `pkg/litigationplanner/engine.go` — find where `timing='before'` + `parent_id` is resolved, and verify whether the engine uses `parent.computedDate` or falls back to `triggerDate`. Add a unit test that reproduces the bug (synthetic rules + expected dates) before fixing. 3. **Identify the duplicate** — bisect: is it data (DB row count) or rendering (frontend or `lookup_events` projection)? 4. **Fix both** — minimal, targeted patches. Tests must lock the correct behaviour for at least these three rules: trigger event (SoC) → child `before` rule (translation_request) → grand-child rule (none here, but verify chains work). 5. **Manual verification** in the worktree: a screenshot or `curl` test that the repro URL now renders R.109.1 and R.109.4 *after* the oral hearing (`upc.inf.cfi.oral` date), with no duplicates. ## Acceptance 1. https://paliad.de/tools/verfahrensablauf?side=defendant on `upc.inf.cfi` shows Klageerhebung first, then the rest of the chain in chronological order, and the R.109 events render *after* the oral hearing. 2. No duplicate Simultanübersetzung row. 3. `go test ./pkg/litigationplanner/... ./internal/services/fristenrechner_*_test.go` green, including a new test locking the `before-parent` anchor behaviour. 4. No data migration unless audit reveals a real DB-level duplicate (in which case a small UPDATE-or-archive migration with `set_config('paliad.audit_reason',…)` is appropriate). ## Anti-patterns to avoid - DON'T touch the rule data unless step 1 confirms a real DB duplicate. - DON'T write a migration with phantom column references (`updated_at` doesn't exist on `proceeding_types`; verify `deadline_rules` columns before any UPDATE). - DON'T skip `set_config('paliad.audit_reason',…)` if you do end up UPDATEing `deadline_rules`.
mAi self-assigned this 2026-05-26 13:36:52 +00:00
mAi added the
done
label 2026-05-26 13:54:45 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#135
No description provided.