Fristenrechner: trigger picker accepts all events; cross-party follow-ups must show with annotation; scenario flags must sync with conditional checkboxes #148

Open
opened 2026-05-27 08:37:37 +00:00 by mAi · 0 comments
Collaborator

m's diagnosis (2026-05-27 10:35)

We dont carry the explicit event_rule, we derive the trigger from whether an event is mentioned as a previous event in a sequence. […] Either way, the system needs to be that we can select from ALL POSSIBLE EVENTS and then see the followups, optional and mandatory.

And from the 10:29 message:

'Mit Widerklage auf Nichtigkeit' / 'Mit Antrag auf Patentänderung (R.30)' — These options in the Verfahrensablauf should be in sync with the optional checkboxes in the submission cards. So if I decide to include the Counterclaim for Revocation, it should be there.

Premises verified live (2026-05-27)

Sample chains (paliad.sequencing_rules.parent_id → parent rule's procedural_event):

child rule parent rule predecessor event
Berufungsbegründung (§ 111 PatG) § 110 PatG Berufungsfrist
Anzeige der Verteidigungsbereitschaft (§ 276 ZPO) (anchor) Klageerhebung
Beschwerdebegründung (Art. 108 EPÜ) (anchor) Entscheidung
Berufungserwiderung (RoP.235.1) RoP.224.2.a Berufungsbegründung
Replik (RoP.029.b) RoP.023 Klageerwiderung
Duplik (RoP.029.c) RoP.029.b Replik
Erwiderung auf CCR (RoP.029.a) RoP.023 Klageerwiderung
Replik auf Erwiderung zur CCR (RoP.029.d) RoP.029.a Erwiderung auf CCR

Stats over paliad.sequencing_rules (active+published, 226 rows):

  • 107 (47%) have parent_id set — the rule sits below a predecessor in the cascade tree.
  • 119 (53%) have parent_id = NULL — these are top-of-tree anchors OR genuine leaves that haven't been linked yet.
  • 67 unique rules act as parent_id for at least one child — i.e. 67 events are real triggers in today's data.

m's architectural intent: derive trigger-ness from the data (a rule whose parent_id points at me means I'm a trigger). No need for an explicit event_role column on procedural_events.

B. The bug m saw (def_to_ccr → "Keine Folge-Fristen") is a perspective-filter overreach, not missing data

The event upc.inf.cfi.def_to_ccr (Erwiderung auf Nichtigkeitswiderklage, claimant-filed) DOES have a published child rule:

child  : RoP.029.d → upc.inf.cfi.reply_def_ccr (Replik auf Erwiderung zur CCR)
parent : RoP.029.a → upc.inf.cfi.def_to_ccr
party  : defendant

Knuth's FristenrechnerService.LookupFollowUps filters follow-ups to rules where primary_party = $perspective OR primary_party = 'both'. m's perspective was claimant. The child rule (defendant) got dropped, surfacing "Keine Folge-Fristen" — even though the workflow continues with the other side's next move.

The fix is semantic: a cross-party follow-up isn't "not a follow-up" — it's the other side's next move. The result view should render it with a Gegenseitig annotation (and keep it unchecked by default for write-back, since the user doesn't file deadlines for the opposing side). Hiding them breaks the user's mental model of the cascade.

C. Verfahrensablauf scenario flags ↔ result-view CONDITIONAL group are independent today

The legacy Procedure-mode page (/tools/fristenrechner?legacy=1, untouched upper half of frontend/src/fristenrechner.tsx) renders scenario checkboxes for the proceeding:

  • Mit Widerklage auf Nichtigkeit (with_ccr)
  • Mit Antrag auf Patentänderung (with_amendment_r30)
  • (others per paliad.project_event_choices + paliad.scenarios jsonb mig 145)

The new result view (S2-S6) renders a CONDITIONAL group of follow-ups (rules with condition_expr IS NOT NULL) with their own checkboxes — independent from the Verfahrensablauf scenario flags. m's intent: these should share state.

Today's missing wiring: condition_expr on a sequencing_rule references a scenario key (e.g. {"requires": ["with_ccr"]}). The Verfahrensablauf checkboxes write to paliad.project_event_choices (or projects.scenarios jsonb). The result view's conditional checkboxes only live in DOM state. Three independent stores. The design needs ONE source of truth that:

  • Persists scenario flags per project (projects.scenarios jsonb is the natural home — mig 145).
  • Drives Verfahrensablauf checkbox state on render.
  • Drives result-view conditional-rule visibility + checked-state on render.
  • Round-trips: ticking CCR in either surface persists, and the other surface picks it up on next render / live via a tiny event bus.

Scope

One inventor pass covering:

  1. Confirm + document the parent_id semantic. Update the design-fristenrechner-overhaul-2026-05-26.md §4.2 to make explicit: "follow-ups = sequencing_rules WHERE parent_id = anchor_rule.id" (already what knuth coded, but un-named in the original design — the doc said "anchored on sr.procedural_event_id = trigger.id" which is the anchor lookup, not the follow-up resolution).
  2. Cross-party follow-ups display contract. Spec out the result-view rendering when a follow-up's primary_party doesn't match the user's perspective:
    • Show the row
    • Add a Gegenseitig / Cross-Party badge
    • Default unchecked
    • Greyed-out visual treatment but the date is still computed + visible
    • Backend change: LookupFollowUps returns all rules; UI does the grouping/annotation; perspective stays a display qualifier in the result view.
  3. Scenario state binding. Design the single source of truth + the binding to both surfaces:
    • projects.scenarios jsonb shape (extend mig 145 schema if needed — minimal new keys, not a re-architect)
    • Verfahrensablauf checkbox read/write contract
    • Result-view conditional checkbox read/write contract
    • Tiny event bus (DOM CustomEvent or a single GET endpoint refreshed on focus — pick the lightest path)
    • Migration: today's project_event_choices rows mapped into projects.scenarios (or coexist)
  4. Editorial backlog flagged. 53% of rules have parent_id = NULL. Many of those should chain back to an anchor. NOT in scope for this design — flagged as a follow-up editorial task. The new picker UX should still cleanly handle leaves ("this event has no recorded follow-ups" is honest).

Out of scope

  • Adding an explicit event_role column on procedural_events (m: "we DON'T carry the explicit event_rule"). The architecture stays: derive trigger-ness from parent_id chains.
  • Editorial backfill of the 119 parent_id-null rules. Separate ticket once the picker/result-view UX is right.
  • Changing the calculator (pkg/litigationplanner.CalculateRule). Just the lookup + render layer.
  • Replacing the legacy Procedure-mode page. The Verfahrensablauf wiring lives in the new dual-mode UI; the legacy ?legacy=1 page can deprecate naturally.

Acceptance for the design pass

Deliverable: docs/design-fristenrechner-followup-rules-2026-05-NN.md covering:

  • Documented parent_id semantic (sequencing_rules.parent_id = predecessor rule in the cascade — child fires after parent's deadline).
  • Cross-party follow-up display spec (when to show, how to badge, default-checked rules per perspective).
  • Scenario state shape (in projects.scenarios jsonb), key naming convention (with_ccr, with_amendment_r30, …), schema delta if any.
  • Verfahrensablauf ↔ result-view binding (event bus or polling, write/read flow).
  • Backend changes to FristenrechnerService.LookupFollowUps: stop filtering by party server-side, return all + the rule's primary_party; UI takes responsibility for grouping/annotation.
  • Migration plan: backfill projects.scenarios from project_event_choices if both surfaces should round-trip.
  • Worked example: claimant user picks upc.inf.cfi.def_to_ccr as trigger → result view shows: own follow-ups (checked) + cross-party RoP.029.d (Replik auf Erwiderung zur CCR) with Gegenseitig badge, unchecked, date visible.
  • Worked example: user opens Verfahrensablauf → ticks 'Mit CCR' → switches to result-view of any UPC INF event → the conditional CCR-rule appears pre-checked.

No code yet — inventor → coder gate. Park after DESIGN READY FOR REVIEW.

Cross-references

  • Original Fristenrechner overhaul design: docs/design-fristenrechner-overhaul-2026-05-26.md (S2-S6 shipped 2026-05-27).
  • Proceeding_types taxonomy design: docs/design-proceeding-types-taxonomy-2026-05-26.md (mig 153 shipped 2026-05-27) — parallel surgical taxonomy fix, gives mental model for derive-don't-add design.
  • paliad.scenarios jsonb on projects: introduced mig 145 (Litigation Planner Slice D).
  • paliad.project_event_choices table: legacy scenario storage, PK (project_id, scenario_name, submission_code, choice_kind).
  • paliad.sequencing_rules.condition_expr (jsonb): per-rule scenario predicate.
## m's diagnosis (2026-05-27 10:35) > We dont carry the explicit event_rule, we derive the trigger from whether an event is mentioned as a previous event in a sequence. […] Either way, the system needs to be that we can select from ALL POSSIBLE EVENTS and then see the followups, optional and mandatory. And from the 10:29 message: > 'Mit Widerklage auf Nichtigkeit' / 'Mit Antrag auf Patentänderung (R.30)' — These options in the Verfahrensablauf should be in sync with the optional checkboxes in the submission cards. So if I decide to include the Counterclaim for Revocation, it should be there. ## Premises verified live (2026-05-27) ### A. `parent_id` IS the predecessor link Sample chains (`paliad.sequencing_rules.parent_id` → parent rule's `procedural_event`): | child rule | parent rule | predecessor event | |---|---|---| | Berufungsbegründung (§ 111 PatG) | § 110 PatG | Berufungsfrist | | Anzeige der Verteidigungsbereitschaft (§ 276 ZPO) | (anchor) | Klageerhebung | | Beschwerdebegründung (Art. 108 EPÜ) | (anchor) | Entscheidung | | Berufungserwiderung (RoP.235.1) | RoP.224.2.a | Berufungsbegründung | | Replik (RoP.029.b) | RoP.023 | Klageerwiderung | | Duplik (RoP.029.c) | RoP.029.b | Replik | | **Erwiderung auf CCR** (RoP.029.a) | RoP.023 | **Klageerwiderung** | | Replik auf Erwiderung zur CCR (RoP.029.d) | RoP.029.a | **Erwiderung auf CCR** | Stats over `paliad.sequencing_rules` (active+published, 226 rows): - 107 (47%) have `parent_id` set — the rule sits below a predecessor in the cascade tree. - 119 (53%) have `parent_id = NULL` — these are top-of-tree anchors OR genuine leaves that haven't been linked yet. - 67 unique rules act as `parent_id` for at least one child — i.e. **67 events are real triggers in today's data**. m's architectural intent: derive trigger-ness from the data (a rule whose parent_id points at me means I'm a trigger). No need for an explicit `event_role` column on `procedural_events`. ### B. The bug m saw (def_to_ccr → "Keine Folge-Fristen") is a perspective-filter overreach, not missing data The event `upc.inf.cfi.def_to_ccr` (Erwiderung auf Nichtigkeitswiderklage, claimant-filed) DOES have a published child rule: ``` child : RoP.029.d → upc.inf.cfi.reply_def_ccr (Replik auf Erwiderung zur CCR) parent : RoP.029.a → upc.inf.cfi.def_to_ccr party : defendant ``` Knuth's `FristenrechnerService.LookupFollowUps` filters follow-ups to rules where `primary_party = $perspective OR primary_party = 'both'`. m's perspective was `claimant`. The child rule (`defendant`) got dropped, surfacing "Keine Folge-Fristen" — even though the workflow continues with the other side's next move. The fix is semantic: a cross-party follow-up isn't "not a follow-up" — it's *the other side's next move*. The result view should render it with a `Gegenseitig` annotation (and keep it unchecked by default for write-back, since the user doesn't file deadlines for the opposing side). Hiding them breaks the user's mental model of the cascade. ### C. Verfahrensablauf scenario flags ↔ result-view CONDITIONAL group are independent today The legacy Procedure-mode page (`/tools/fristenrechner?legacy=1`, untouched upper half of `frontend/src/fristenrechner.tsx`) renders scenario checkboxes for the proceeding: - Mit Widerklage auf Nichtigkeit (`with_ccr`) - Mit Antrag auf Patentänderung (`with_amendment_r30`) - (others per `paliad.project_event_choices` + `paliad.scenarios` jsonb mig 145) The new result view (S2-S6) renders a **CONDITIONAL** group of follow-ups (rules with `condition_expr IS NOT NULL`) with their own checkboxes — independent from the Verfahrensablauf scenario flags. m's intent: these should share state. Today's missing wiring: `condition_expr` on a sequencing_rule references a scenario key (e.g. `{"requires": ["with_ccr"]}`). The Verfahrensablauf checkboxes write to `paliad.project_event_choices` (or `projects.scenarios` jsonb). The result view's conditional checkboxes only live in DOM state. Three independent stores. The design needs ONE source of truth that: - Persists scenario flags per project (`projects.scenarios` jsonb is the natural home — mig 145). - Drives Verfahrensablauf checkbox state on render. - Drives result-view conditional-rule visibility + checked-state on render. - Round-trips: ticking CCR in either surface persists, and the other surface picks it up on next render / live via a tiny event bus. ## Scope One inventor pass covering: 1. **Confirm + document the parent_id semantic.** Update the design-fristenrechner-overhaul-2026-05-26.md §4.2 to make explicit: "follow-ups = sequencing_rules WHERE parent_id = anchor_rule.id" (already what knuth coded, but un-named in the original design — the doc said "anchored on `sr.procedural_event_id = trigger.id`" which is the anchor lookup, not the follow-up resolution). 2. **Cross-party follow-ups display contract.** Spec out the result-view rendering when a follow-up's `primary_party` doesn't match the user's `perspective`: - Show the row - Add a `Gegenseitig` / `Cross-Party` badge - Default unchecked - Greyed-out visual treatment but the date is still computed + visible - Backend change: `LookupFollowUps` returns all rules; UI does the grouping/annotation; perspective stays a *display* qualifier in the result view. 3. **Scenario state binding.** Design the single source of truth + the binding to both surfaces: - `projects.scenarios` jsonb shape (extend mig 145 schema if needed — minimal new keys, not a re-architect) - Verfahrensablauf checkbox read/write contract - Result-view conditional checkbox read/write contract - Tiny event bus (DOM CustomEvent or a single GET endpoint refreshed on focus — pick the lightest path) - Migration: today's `project_event_choices` rows mapped into `projects.scenarios` (or coexist) 4. **Editorial backlog flagged.** 53% of rules have `parent_id = NULL`. Many of those should chain back to an anchor. NOT in scope for this design — flagged as a follow-up editorial task. The new picker UX should still cleanly handle leaves ("this event has no recorded follow-ups" is honest). ### Out of scope - Adding an explicit `event_role` column on `procedural_events` (m: "we DON'T carry the explicit event_rule"). The architecture stays: derive trigger-ness from parent_id chains. - Editorial backfill of the 119 parent_id-null rules. Separate ticket once the picker/result-view UX is right. - Changing the calculator (`pkg/litigationplanner.CalculateRule`). Just the lookup + render layer. - Replacing the legacy Procedure-mode page. The Verfahrensablauf wiring lives in the new dual-mode UI; the legacy `?legacy=1` page can deprecate naturally. ## Acceptance for the design pass Deliverable: `docs/design-fristenrechner-followup-rules-2026-05-NN.md` covering: - Documented parent_id semantic (sequencing_rules.parent_id = predecessor rule in the cascade — child fires after parent's deadline). - Cross-party follow-up display spec (when to show, how to badge, default-checked rules per perspective). - Scenario state shape (in `projects.scenarios` jsonb), key naming convention (`with_ccr`, `with_amendment_r30`, …), schema delta if any. - Verfahrensablauf ↔ result-view binding (event bus or polling, write/read flow). - Backend changes to `FristenrechnerService.LookupFollowUps`: stop filtering by party server-side, return all + the rule's primary_party; UI takes responsibility for grouping/annotation. - Migration plan: backfill `projects.scenarios` from `project_event_choices` if both surfaces should round-trip. - Worked example: claimant user picks `upc.inf.cfi.def_to_ccr` as trigger → result view shows: own follow-ups (checked) + cross-party `RoP.029.d` (Replik auf Erwiderung zur CCR) with `Gegenseitig` badge, unchecked, date visible. - Worked example: user opens Verfahrensablauf → ticks 'Mit CCR' → switches to result-view of any UPC INF event → the conditional CCR-rule appears pre-checked. No code yet — inventor → coder gate. Park after `DESIGN READY FOR REVIEW`. ## Cross-references - Original Fristenrechner overhaul design: `docs/design-fristenrechner-overhaul-2026-05-26.md` (S2-S6 shipped 2026-05-27). - Proceeding_types taxonomy design: `docs/design-proceeding-types-taxonomy-2026-05-26.md` (mig 153 shipped 2026-05-27) — parallel surgical taxonomy fix, gives mental model for derive-don't-add design. - `paliad.scenarios` jsonb on projects: introduced mig 145 (Litigation Planner Slice D). - `paliad.project_event_choices` table: legacy scenario storage, PK `(project_id, scenario_name, submission_code, choice_kind)`. - `paliad.sequencing_rules.condition_expr` (jsonb): per-rule scenario predicate.
mAi self-assigned this 2026-05-27 08:37:37 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#148
No description provided.