Verfahrensablauf appeal mode: side selector doesn't filter columns + missing trigger event + duration phrasing/duplication #136

Open
opened 2026-05-26 15:37:02 +00:00 by mAi · 0 comments
Collaborator

All surface on https://paliad.de/tools/verfahrensablauf with the unified Berufung tile (upc.apl.unified). Some apply to non-appeal proceedings too.

Bug 1 — Side selector does nothing on appeal

With upc.apl.unified picked, switching side=claimant ↔ defendant ↔ undefined doesn't change the column projection. After the #132 refactor we collapsed the two selectors into one, but the underlying engine filter / column-bucketing for appeals still acts as if side is undefined. The 5 chip targets (Endentscheidung etc.) do work; only side is dead.

Expected: with side=claimant on appeal, the Berufungskläger column owns the user's filings, the Berufungsbeklagter column shows the opponent's filings. Mirror for side=defendant. With side=undefined, both columns render every rule.

Bug 2 — Missing trigger event on the timeline

The initial event the appeal is anchored to (e.g. Final Decision under R.118, Cost Decision, Order) doesn't appear on the timeline. Only the downstream deadlines do. Lawyers need to see the anchor itself as the first row, so the timeline reads top-down as decision → deadlines → next decision.

Fix surface: pkg/litigationplanner/engine.go — when an appeal_target is set, emit a synthetic root event whose name comes from the existing TriggerEventLabelForAppealTarget(target, lang) helper (added in #132), dated to the trigger date. Render it as the first row of the timeline, marked as a trigger event (icon, dimmed, court-set).

Non-appeal proceedings should already do this — verify and align if needed.

Bug 3 — Duration label says "nach" without naming the anchor

The new duration affordance from #133 displays "4 Monate nach" but doesn't say nach what. Should be "4 Monate nach Zustellung der Endentscheidung" / "4 months after the final decision is served" etc.

Fix surface: frontend/src/client/views/verfahrensablauf-core.ts — when formatting the duration string, append the parent rule's name (or the trigger-event-label for root rules). The parent name is already on lp.TimelineEntry.ParentRuleName / ParentRuleNameEN (added in earlier slice for conditional-rule rendering, t-paliad-289).

Bug 4 — Duration duplicated when deadline_notes also mentions it

A handful of rules carry the duration in their free-text deadline_notes column (e.g. "Frist 1 Monat VOR der mündlichen Verhandlung (R.109.1)…"). After #133's duration affordance, the duration now renders twice — once as the new badge, once inside the notes.

Fix surface: same renderer. Two options:

  • (a) Cheapest: detect a leading "Frist N [VOR|nach] …" substring in deadline_notes and strip it before rendering the notes. Regex-based.
  • (b) Better long-term: stop putting duration prose into deadline_notes and let the renderer compose the full string from structured fields. Requires a data audit + rewrite of ~10-20 rule rows.

Worker should pick (a) for this slice — it's safe and reversible — and surface (b) as a follow-up for editorial cleanup.

Acceptance

  1. ?proceeding=upc.apl.unified&side=claimant → user column owns Berufungskläger-party rows, opponent column owns Berufungsbeklagter-party rows. Switching to side=defendant mirrors. side=undefined shows both.
  2. Timeline first row = the trigger event itself (per appeal_target choice, or per proceeding default for non-appeal). Synthetic court-set row, dated to trigger date.
  3. Every duration label reads "<n> <unit> nach <parent>" (or "vor <parent>"), where <parent> is the parent rule's name (or trigger event name for root rules).
  4. No duplicate duration phrase when deadline_notes also leads with one.
  5. go test ./pkg/litigationplanner/... ./internal/services/... green, including a new test covering the appeal-side-filter behaviour and the synthetic-trigger-event emission.
  6. bun run build clean. Frontend test for the notes-deduplication regex.

Worker scope

  • Read #132 (Berufung labels refactor) + #133 (duration affordance) + #135 (R.109 anchor fix) commits to understand the recent changes on this surface. Don't undo any of them.
  • Pre-flight: confirm lp.TimelineEntry.ParentRuleName* is populated for every row that has a parent (audit via the Go test or a quick handler call). If not, fix in engine.go first.
  • Single worker, single branch — these four bugs are tightly coupled on the same renderer/engine surface. Atomic commit or two-commit (engine + frontend) is fine.

Anti-patterns (lessons from today's mig 134 hotfix-3)

  • DON'T edit the duration prose in deadline_notes directly — go via a migration with set_config('paliad.audit_reason',…) if you absolutely have to. Today's pass should NOT touch deadline_rules at all; the notes-dedup is a render-side regex.
  • DON'T assume a column exists on any table; query information_schema.columns via Supabase MCP before any data work.
## Four related Verfahrensablauf bugs surfaced by m (2026-05-26 17:35) All surface on https://paliad.de/tools/verfahrensablauf with the unified Berufung tile (`upc.apl.unified`). Some apply to non-appeal proceedings too. ### Bug 1 — Side selector does nothing on appeal With `upc.apl.unified` picked, switching `side=claimant ↔ defendant ↔ undefined` doesn't change the column projection. After the #132 refactor we collapsed the two selectors into one, but the underlying engine filter / column-bucketing for appeals still acts as if side is undefined. The 5 chip targets (Endentscheidung etc.) do work; only side is dead. Expected: with `side=claimant` on appeal, the *Berufungskläger* column owns the user's filings, the *Berufungsbeklagter* column shows the opponent's filings. Mirror for `side=defendant`. With `side=undefined`, both columns render every rule. ### Bug 2 — Missing trigger event on the timeline The initial event the appeal is anchored to (e.g. *Final Decision under R.118*, *Cost Decision*, *Order*) doesn't appear on the timeline. Only the downstream deadlines do. Lawyers need to see the anchor itself as the first row, so the timeline reads top-down as decision → deadlines → next decision. Fix surface: `pkg/litigationplanner/engine.go` — when an `appeal_target` is set, emit a synthetic root event whose name comes from the existing `TriggerEventLabelForAppealTarget(target, lang)` helper (added in #132), dated to the trigger date. Render it as the first row of the timeline, marked as a trigger event (icon, dimmed, court-set). Non-appeal proceedings should already do this — verify and align if needed. ### Bug 3 — Duration label says "nach" without naming the anchor The new duration affordance from #133 displays "4 Monate nach" but doesn't say *nach what*. Should be "4 Monate nach Zustellung der Endentscheidung" / "4 months after the final decision is served" etc. Fix surface: `frontend/src/client/views/verfahrensablauf-core.ts` — when formatting the duration string, append the parent rule's name (or the trigger-event-label for root rules). The parent name is already on `lp.TimelineEntry.ParentRuleName` / `ParentRuleNameEN` (added in earlier slice for conditional-rule rendering, t-paliad-289). ### Bug 4 — Duration duplicated when deadline_notes also mentions it A handful of rules carry the duration in their free-text `deadline_notes` column (e.g. *"Frist 1 Monat VOR der mündlichen Verhandlung (R.109.1)…"*). After #133's duration affordance, the duration now renders twice — once as the new badge, once inside the notes. Fix surface: same renderer. Two options: - (a) Cheapest: detect a leading "Frist N <unit> [VOR|nach] …" substring in `deadline_notes` and strip it before rendering the notes. Regex-based. - (b) Better long-term: stop putting duration prose into `deadline_notes` and let the renderer compose the full string from structured fields. Requires a data audit + rewrite of ~10-20 rule rows. Worker should pick (a) for this slice — it's safe and reversible — and surface (b) as a follow-up for editorial cleanup. ## Acceptance 1. `?proceeding=upc.apl.unified&side=claimant` → user column owns Berufungskläger-party rows, opponent column owns Berufungsbeklagter-party rows. Switching to `side=defendant` mirrors. `side=undefined` shows both. 2. Timeline first row = the trigger event itself (per appeal_target choice, or per proceeding default for non-appeal). Synthetic court-set row, dated to trigger date. 3. Every duration label reads `"<n> <unit> nach <parent>"` (or `"vor <parent>"`), where `<parent>` is the parent rule's name (or trigger event name for root rules). 4. No duplicate duration phrase when `deadline_notes` also leads with one. 5. `go test ./pkg/litigationplanner/... ./internal/services/...` green, including a new test covering the appeal-side-filter behaviour and the synthetic-trigger-event emission. 6. `bun run build` clean. Frontend test for the notes-deduplication regex. ## Worker scope - Read #132 (Berufung labels refactor) + #133 (duration affordance) + #135 (R.109 anchor fix) commits to understand the recent changes on this surface. Don't undo any of them. - Pre-flight: confirm `lp.TimelineEntry.ParentRuleName*` is populated for every row that has a parent (audit via the Go test or a quick handler call). If not, fix in `engine.go` first. - Single worker, single branch — these four bugs are tightly coupled on the same renderer/engine surface. Atomic commit or two-commit (engine + frontend) is fine. ## Anti-patterns (lessons from today's mig 134 hotfix-3) - DON'T edit the duration prose in `deadline_notes` directly — go via a migration with `set_config('paliad.audit_reason',…)` if you absolutely have to. Today's pass should NOT touch `deadline_rules` at all; the notes-dedup is a render-side regex. - DON'T assume a column exists on any table; query `information_schema.columns` via Supabase MCP before any data work.
mAi self-assigned this 2026-05-26 15:37:02 +00:00
mAi added the
done
label 2026-05-26 15:57:43 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#136
No description provided.