RFC: full revision of the deadline + procedural-events system — two entry paths, unified scenario state, editorial completion #149

Open
opened 2026-05-27 08:52:51 +00:00 by mAi · 2 comments
Collaborator

Mandate

m (2026-05-27 10:48-10:51): full revision of the deadline + procedural-events system. "Some things are doing well, others are not at all."

Two primary user entry paths must work end-to-end:

  1. Sequence-from-proceeding-type — pick a proceeding type, see its full procedural ablauf, with optional events checkbox-toggleable to include / exclude from the timeline.
  2. Sequence-from-trigger-event — pick a specific event (a trigger), see the sequence that follows (mandatory + optional + conditional + spawn).

Both must share one underlying data model, one source of truth for scenario flags, one shared notion of "what is a trigger". Today's data foundation is mostly right; editorial coverage, scenario-state unification, and the two competing trigger semantics need work.

Live audit summary (2026-05-27)

What the data carries today

Concept Storage Coverage / quality
Events paliad.procedural_events (236 rows, 222 active+published, mig 153 in place) 5 event_kind buckets (filing / hearing / decision / order / NULL). Names + codes good.
Rules paliad.sequencing_rules (231 rows, 226 active+published) One rule = the deadline for one event.
Sequence linkage sequencing_rules.parent_id (FK to another rule) 107 rules (47%) have parent set. 119 (53%) have parent_id = NULL. 67 unique rules act as parent → 67 events are real triggers today.
Trigger (alternate model) sequencing_rules.trigger_event_id (bigint, → legacy paliad.trigger_events) 80 rules populate this. Semantic overlap with parent_id needs reconciling. Consumed only by /api/tools/event-deadlines (legacy).
Priority sequencing_rules.priority enum (mandatory / recommended / optional) Clean three-tier ladder.
Cross-party sequencing_rules.primary_party (claimant / defendant / both / court / NULL) Schema OK. UI mishandles (current /follow-ups bug, hiding cross-party rules).
Conditional sequencing_rules.condition_expr (jsonb) 18 rules carry it today. Expression language is informal (a few common keys).
Spawn sequencing_rules.is_spawn + spawn_proceeding_type_id 4 rows. The appeal_spawn family.
Court-set sequencing_rules.is_court_set (boolean) 45 rows. Date not computable until court issues.
Bilateral sequencing_rules.is_bilateral (boolean) 49 rows. Both sides file independently.
Sub-track sequencing_rules.spawn_label + family routing (e.g. UPC_INF + with_ccr → upc.inf.cfi sub-track) Routing layer landed in t-paliad-204; works, but tied to ad-hoc condition_flags.
Proceeding kind paliad.proceeding_types.kind (mig 153, 2026-05-27) Clean: 23 proceeding, 4 phase, 10 side_action, 9 meta.
Scenario flags paliad.project_event_choices (PK project_id + scenario_name + submission_code + choice_kind) AND paliad.projects.scenarios jsonb (mig 145) AND DOM state on result view Three independent stores. No single source of truth. Verfahrensablauf checkboxes write one, conditional rules read another.
Holidays / working days pkg/litigationplanner.HolidayCalendar interface + paliad.holidays table Works. Out of scope here.
Calculator pkg/litigationplanner.CalculateRule Works. Out of scope here.

What's actually broken

  1. Picker doesn't distinguish trigger-shaped events from leaf consequences. Today's Mode A search surfaces every active+published procedural_events row. upc.inf.cfi.appeal_spawn (a SPAWN consequence) and upc.inf.cfi.def_to_ccr (a leaf with no published children) both appear and produce confusing "Keine Folge-Fristen" or wrong-tree result views. m: 'we derive the trigger from whether an event is mentioned as a previous event in a sequence'. The data already supports this derivation but the picker hasn't been wired to it.
  2. Cross-party follow-ups are hidden by the perspective filter. For upc.inf.cfi.def_to_ccr (claimant-filed), the published child RoP.029.d → reply_def_ccr (defendant Replik) gets filtered out when perspective=claimant. Result: "Keine Folge-Fristen" lies — the workflow continues, just on the other side. UI should show + annotate, not hide.
  3. Scenario flag state is fragmented. Mit Widerklage auf Nichtigkeit and Mit Antrag auf Patentänderung (R.30) toggles on Verfahrensablauf don't drive the conditional checkboxes in result-view submission cards. Three stores diverge.
  4. Editorial completeness: 53% of rules have parent_id = NULL. Some are genuine roots (e.g. Klageerhebung — the start of a flow). Most are filing events whose chain back to a predecessor is unseeded. The whole 'trigger-from-sequence' derivation has gaps as a result.
  5. Two trigger models coexist. Old trigger_event_id (80 rules → bigint legacy table) overlaps with new parent_id chain semantics. One must win.
  6. No first-class 'sequence-from-proceeding-type' view. The legacy Procedure-mode page (upper half of frontend/src/fristenrechner.tsx) tries to do this but doesn't surface optionals as toggleable in a way that drives the rest of the system. The newly-shipped Verfahrensablauf in /admin/procedural-events is read-only.

What this RFC must answer

Architectural

  1. Trigger semantics — keep parent_id chains as the canonical link, deprecate trigger_event_id? Or unify both? If deprecating: migration plan for the 80 rules that use it.
  2. Trigger discoverability — derive trigger-eligibility from data (EXISTS a non-spawn rule with parent_id = this_rule.id), or maintain a materialised view, or carry an explicit derived flag?
  3. Scenario state — pick one home. Recommendation: paliad.projects.scenarios jsonb (already exists per mig 145). Migration: backfill from project_event_choices; deprecate the legacy table. Define the key namespace (with_ccr, with_amendment_r30, …). Wire the two surfaces (Verfahrensablauf checkboxes + result-view conditional checkboxes) to both read and write this jsonb.
  4. Cross-party display — backend stops filtering, returns all follow-ups with primary_party. UI groups: own-side checked-by-priority, cross-party annotated Gegenseitig + unchecked. Perspective remains the user's qualifier in the calc; the display is honest about who files what.
  5. Spawn handling — events whose only rule is is_spawn=true get excluded from picker (they're consequences, not triggers). They still surface in the parent event's result view under SPAWNED group.
  6. Sequence-from-proceeding-type view — design from scratch or extend the legacy Procedure-mode page? Goal: pick a proceeding_type, see the full ablauf as a tree (chronological, parent_id chains), with checkbox-toggleable optionals that drive what appears in result views downstream + on the project's actual deadline timeline.

Data quality

  1. Editorial backfill plan for the 119 parent_id-NULL rules — which are genuine roots, which are leaves missing chain links. Stage as drafts via /admin/procedural-events; m reviews + publishes at his leisure.
  2. condition_expr formalisation — today it's free-form jsonb. Pick a small expression grammar (requires, excludes, when_party, …) and document it. Validate at write time.
  3. Legacy paliad.trigger_events table fate — drop, archive, or repurpose?

UI

  1. Two entry paths design:
    • Entry A: sequence-from-proceeding-type. Where does it live (separate page? Mode C on Fristenrechner? folded into /tools/procedure-ablauf?). How do toggles persist to project state.
    • Entry B: sequence-from-trigger-event. Already the new Fristenrechner Mode A + Mode B (shipped 2026-05-27). Just needs the picker filter + cross-party display + scenario binding.
  2. Result-view evolution: integrate with Entry A so the same selected_optionals state drives both the timeline view and the per-event follow-up list.
  3. Migration & coexistence: keep legacy Procedure-mode page reachable behind ?legacy=1 for the deprecation window; ship the new sequence-from-proceeding-type view as a parallel surface, flip default after dogfooding.

Two-worker dispatch

m called for consultant + inventor.

Phase 1 — Consultant (assessment)

Deliverable: docs/assessment-deadline-system-2026-05-NN.md covering:

  • Comprehensive audit of every consumer of sequencing_rules + procedural_events (Fristenrechner, Litigation Planner, SmartTimeline, /admin/procedural-events, /admin/rules redirects, Verfahrensablauf, ProjectService.SetProceedingType, paliadin context, youpc-go snapshot).
  • Health-check on each: what works, what's broken, what's unused.
  • Rules-corpus quality audit: parent_id coverage, condition_expr usage patterns, spawn rule distribution, primary_party distribution, court-set coverage, legacy trigger_event_id overlap.
  • Editorial gap map: which proceeding_types have complete chains, which have stubs, which are zero-rule.
  • Risk register: every place where the data model leaks (e.g. legacy trigger_events table, three-store scenario state, perspective-filter overreach in /follow-ups).
  • Recommendation: order of operations for the inventor + downstream coders.

No design proposals — assessment only.

Phase 2 — Inventor (design)

Reads consultant's assessment + this RFC, then files:

docs/design-deadline-system-revision-2026-05-NN.md covering all 12 questions above, schema deltas (likely additive + a few drops), migration plan, two-entry-path UI specs, scenario-state unification migration, editorial-backfill plan (just the framework + counts; the actual content is editorial work for m), worked examples for both entry paths.

Uses AskUserQuestion batches for m's open calls. Park after DESIGN READY FOR REVIEW.

Coder phase (deferred)

After m ratifies the inventor's design, head hires coder(s) for the migration + UI + service changes. Estimate: multi-slice train, similar shape to the Fristenrechner overhaul (S1 backend → … → flip flag → cleanup).

Subsumed prior work

  • m/paliad#146 — Fristenrechner overhaul (shipped 2026-05-27). Entry B foundation. Will need follow-up surgery per this RFC.
  • m/paliad#147 — proceeding_types taxonomy (shipped 2026-05-27). Mig 153 kind discriminator. Solid foundation for both entry paths.
  • m/paliad#148 (CANCELLED) — Fristenrechner follow-up rules narrow design. Scope absorbed into this RFC.
  • t-paliad-181 — Phase 3 unification (largely shipped per atlas's audit). The sequencing_rules model itself.

Out of scope

  • Calculator changes (pkg/litigationplanner.CalculateRule). Working as designed.
  • Holiday/working-day logic. Working.
  • Calendar / Outlook sync (long-term goal, separate ticket).
  • Replacing UI design tokens. (Brunel just shipped dark-mode token migration t-paliad-326.)
  • AI-extracted deadlines from documents (deferred per memory b6a11b55…).
## Mandate m (2026-05-27 10:48-10:51): full revision of the deadline + procedural-events system. "Some things are doing well, others are not at all." Two primary user entry paths must work end-to-end: 1. **Sequence-from-proceeding-type** — pick a proceeding type, see its full procedural ablauf, with optional events checkbox-toggleable to include / exclude from the timeline. 2. **Sequence-from-trigger-event** — pick a specific event (a trigger), see the sequence that follows (mandatory + optional + conditional + spawn). Both must share one underlying data model, one source of truth for scenario flags, one shared notion of "what is a trigger". Today's data foundation is mostly right; editorial coverage, scenario-state unification, and the two competing trigger semantics need work. ## Live audit summary (2026-05-27) ### What the data carries today | Concept | Storage | Coverage / quality | |---|---|---| | Events | `paliad.procedural_events` (236 rows, 222 active+published, mig 153 in place) | 5 `event_kind` buckets (filing / hearing / decision / order / NULL). Names + codes good. | | Rules | `paliad.sequencing_rules` (231 rows, 226 active+published) | One rule = the deadline for one event. | | Sequence linkage | `sequencing_rules.parent_id` (FK to another rule) | **107 rules (47%) have parent set. 119 (53%) have parent_id = NULL.** 67 unique rules act as parent → 67 events are real triggers today. | | Trigger (alternate model) | `sequencing_rules.trigger_event_id` (bigint, → legacy `paliad.trigger_events`) | **80 rules populate this.** Semantic overlap with parent_id needs reconciling. Consumed only by `/api/tools/event-deadlines` (legacy). | | Priority | `sequencing_rules.priority` enum (`mandatory` / `recommended` / `optional`) | Clean three-tier ladder. | | Cross-party | `sequencing_rules.primary_party` (`claimant` / `defendant` / `both` / `court` / NULL) | Schema OK. UI mishandles (current /follow-ups bug, hiding cross-party rules). | | Conditional | `sequencing_rules.condition_expr` (jsonb) | 18 rules carry it today. Expression language is informal (a few common keys). | | Spawn | `sequencing_rules.is_spawn` + `spawn_proceeding_type_id` | 4 rows. The `appeal_spawn` family. | | Court-set | `sequencing_rules.is_court_set` (boolean) | 45 rows. Date not computable until court issues. | | Bilateral | `sequencing_rules.is_bilateral` (boolean) | 49 rows. Both sides file independently. | | Sub-track | `sequencing_rules.spawn_label` + family routing (e.g. UPC_INF + with_ccr → upc.inf.cfi sub-track) | Routing layer landed in t-paliad-204; works, but tied to ad-hoc condition_flags. | | Proceeding kind | `paliad.proceeding_types.kind` (mig 153, 2026-05-27) | Clean: 23 `proceeding`, 4 `phase`, 10 `side_action`, 9 `meta`. | | Scenario flags | `paliad.project_event_choices` (PK project_id + scenario_name + submission_code + choice_kind) **AND** `paliad.projects.scenarios` jsonb (mig 145) **AND** DOM state on result view | **Three independent stores. No single source of truth. Verfahrensablauf checkboxes write one, conditional rules read another.** | | Holidays / working days | `pkg/litigationplanner.HolidayCalendar` interface + `paliad.holidays` table | Works. Out of scope here. | | Calculator | `pkg/litigationplanner.CalculateRule` | Works. Out of scope here. | ### What's actually broken 1. **Picker doesn't distinguish trigger-shaped events from leaf consequences.** Today's Mode A search surfaces every active+published `procedural_events` row. `upc.inf.cfi.appeal_spawn` (a SPAWN consequence) and `upc.inf.cfi.def_to_ccr` (a leaf with no published children) both appear and produce confusing "Keine Folge-Fristen" or wrong-tree result views. **m: 'we derive the trigger from whether an event is mentioned as a previous event in a sequence'.** The data already supports this derivation but the picker hasn't been wired to it. 2. **Cross-party follow-ups are hidden by the perspective filter.** For `upc.inf.cfi.def_to_ccr` (claimant-filed), the published child `RoP.029.d → reply_def_ccr` (defendant Replik) gets filtered out when perspective=claimant. Result: "Keine Folge-Fristen" lies — the workflow continues, just on the other side. UI should show + annotate, not hide. 3. **Scenario flag state is fragmented.** `Mit Widerklage auf Nichtigkeit` and `Mit Antrag auf Patentänderung (R.30)` toggles on Verfahrensablauf don't drive the conditional checkboxes in result-view submission cards. Three stores diverge. 4. **Editorial completeness: 53% of rules have `parent_id = NULL`.** Some are genuine roots (e.g. `Klageerhebung` — the start of a flow). Most are filing events whose chain back to a predecessor is unseeded. The whole 'trigger-from-sequence' derivation has gaps as a result. 5. **Two trigger models coexist.** Old `trigger_event_id` (80 rules → bigint legacy table) overlaps with new `parent_id` chain semantics. One must win. 6. **No first-class 'sequence-from-proceeding-type' view.** The legacy Procedure-mode page (upper half of `frontend/src/fristenrechner.tsx`) tries to do this but doesn't surface optionals as toggleable in a way that drives the rest of the system. The newly-shipped Verfahrensablauf in /admin/procedural-events is read-only. ## What this RFC must answer ### Architectural 1. Trigger semantics — keep `parent_id` chains as the canonical link, deprecate `trigger_event_id`? Or unify both? If deprecating: migration plan for the 80 rules that use it. 2. Trigger discoverability — derive trigger-eligibility from data (EXISTS a non-spawn rule with parent_id = this_rule.id), or maintain a materialised view, or carry an explicit derived flag? 3. Scenario state — pick one home. Recommendation: `paliad.projects.scenarios` jsonb (already exists per mig 145). Migration: backfill from `project_event_choices`; deprecate the legacy table. Define the key namespace (`with_ccr`, `with_amendment_r30`, …). Wire the two surfaces (Verfahrensablauf checkboxes + result-view conditional checkboxes) to both read and write this jsonb. 4. Cross-party display — backend stops filtering, returns all follow-ups with `primary_party`. UI groups: own-side checked-by-priority, cross-party annotated `Gegenseitig` + unchecked. Perspective remains the user's qualifier in the calc; the display is honest about who files what. 5. Spawn handling — events whose only rule is `is_spawn=true` get excluded from picker (they're consequences, not triggers). They still surface in the parent event's result view under SPAWNED group. 6. Sequence-from-proceeding-type view — design from scratch or extend the legacy Procedure-mode page? Goal: pick a proceeding_type, see the full ablauf as a tree (chronological, parent_id chains), with checkbox-toggleable optionals that drive what appears in result views downstream + on the project's actual deadline timeline. ### Data quality 7. Editorial backfill plan for the 119 parent_id-NULL rules — which are genuine roots, which are leaves missing chain links. Stage as drafts via `/admin/procedural-events`; m reviews + publishes at his leisure. 8. `condition_expr` formalisation — today it's free-form jsonb. Pick a small expression grammar (`requires`, `excludes`, `when_party`, …) and document it. Validate at write time. 9. Legacy `paliad.trigger_events` table fate — drop, archive, or repurpose? ### UI 10. Two entry paths design: - Entry A: sequence-from-proceeding-type. Where does it live (separate page? Mode C on Fristenrechner? folded into /tools/procedure-ablauf?). How do toggles persist to project state. - Entry B: sequence-from-trigger-event. Already the new Fristenrechner Mode A + Mode B (shipped 2026-05-27). Just needs the picker filter + cross-party display + scenario binding. 11. Result-view evolution: integrate with Entry A so the same `selected_optionals` state drives both the timeline view and the per-event follow-up list. 12. Migration & coexistence: keep legacy Procedure-mode page reachable behind `?legacy=1` for the deprecation window; ship the new sequence-from-proceeding-type view as a parallel surface, flip default after dogfooding. ## Two-worker dispatch m called for **consultant + inventor**. ### Phase 1 — Consultant (assessment) Deliverable: `docs/assessment-deadline-system-2026-05-NN.md` covering: - Comprehensive audit of every consumer of `sequencing_rules` + `procedural_events` (Fristenrechner, Litigation Planner, SmartTimeline, /admin/procedural-events, /admin/rules redirects, Verfahrensablauf, ProjectService.SetProceedingType, paliadin context, youpc-go snapshot). - Health-check on each: what works, what's broken, what's unused. - Rules-corpus quality audit: parent_id coverage, condition_expr usage patterns, spawn rule distribution, primary_party distribution, court-set coverage, legacy `trigger_event_id` overlap. - Editorial gap map: which proceeding_types have complete chains, which have stubs, which are zero-rule. - Risk register: every place where the data model leaks (e.g. legacy `trigger_events` table, three-store scenario state, perspective-filter overreach in /follow-ups). - Recommendation: order of operations for the inventor + downstream coders. No design proposals — assessment only. ### Phase 2 — Inventor (design) Reads consultant's assessment + this RFC, then files: `docs/design-deadline-system-revision-2026-05-NN.md` covering all 12 questions above, schema deltas (likely additive + a few drops), migration plan, two-entry-path UI specs, scenario-state unification migration, editorial-backfill plan (just the framework + counts; the actual content is editorial work for m), worked examples for both entry paths. Uses AskUserQuestion batches for m's open calls. Park after DESIGN READY FOR REVIEW. ### Coder phase (deferred) After m ratifies the inventor's design, head hires coder(s) for the migration + UI + service changes. Estimate: multi-slice train, similar shape to the Fristenrechner overhaul (S1 backend → … → flip flag → cleanup). ## Subsumed prior work - m/paliad#146 — Fristenrechner overhaul (shipped 2026-05-27). Entry B foundation. Will need follow-up surgery per this RFC. - m/paliad#147 — proceeding_types taxonomy (shipped 2026-05-27). Mig 153 kind discriminator. Solid foundation for both entry paths. - m/paliad#148 (CANCELLED) — Fristenrechner follow-up rules narrow design. Scope absorbed into this RFC. - t-paliad-181 — Phase 3 unification (largely shipped per atlas's audit). The sequencing_rules model itself. ## Out of scope - Calculator changes (`pkg/litigationplanner.CalculateRule`). Working as designed. - Holiday/working-day logic. Working. - Calendar / Outlook sync (long-term goal, separate ticket). - Replacing UI design tokens. (Brunel just shipped dark-mode token migration t-paliad-326.) - AI-extracted deadlines from documents (deferred per memory `b6a11b55…`).
mAi self-assigned this 2026-05-27 08:52:51 +00:00
Author
Collaborator

Phase 2 coder train — status as of t-paliad-331 (ritchie)

Slices shipped + merged to main:

  • P0 d36cc9eprojects.scenario_flags SSoT (mig 154) + scenario_flag_catalog table + GET/PATCH /api/projects/{id}/scenario-flags endpoints + Mode B Fristenrechner flag bind + scenario-flags.ts client module + cross-surface scenario-flag-changed CustomEvent.
  • S1 + S1a 3533d79LookupFollowUps returns all rows + computes is_cross_party; UI muted-renders cross-party with Gegenseitig badge; write-back unconditionally excludes cross-party; SearchEvents filters out is_spawn=true so spawn-only events drop out of the picker (terminal leaves stay pickable per design §2.2 carve-out).
  • P1 3a4e99cupc.apl.unified retired; rules re-bound to upc.apl.merits / upc.apl.cost / upc.apl.order by event-code prefix (mig 155); upc.pi.cfi.appeal_spawn retargeted to orders track per design §3.1; lookup_events_test.go assertions updated.
  • P3 480332a — Three-way detail filter (Nur Pflicht / Gewählt / Alle Optionen) on /tools/verfahrensablauf; per-rule Aufnehmen/Entfernen chips writing rule:<uuid> entries to projects.scenario_flags; subtree-hide-on-unselected-ancestor render logic; localStorage-persisted view-mode; conditional rules treated as unselected in 'Gewählt' even when mandatory.

Pending merge:

  • P2 9940dd8condition_expr write-validator. Grammar locked to {flag} | {op:'and'|'or', args:[...]}; called from RuleEditorService.Create + UpdateDraft; 9 shape-unit tests + 2 live-DB tests gated on TEST_DATABASE_URL. All 18 active+published condition_expr rows in the DB conform.
  • P4 (partial) d6a5ded — Hybrid-rule cleanup (mig 156) NULL'd the 2 rules carrying both parent_id AND trigger_event_id per §2.1. POST /api/tools/event-deadlines now responds with Deprecation: true + RFC 8594 / 9745 Link header pointing at this issue.

Final P4 deferred (editorial follow-up — not coder scope):

Live-DB audit shows the table-drop cannot happen yet:

  • paliad.trigger_events carries 110 live rows
  • 78 active sequencing_rules still reference trigger_event_id (post-mig-156); of those, 73 are orphans (proceeding_type_id IS NULL) addressed only via trigger_event_id
  • 33 event_types rows reference trigger_event_id
  • 1 orphan rule has neither parent_id nor trigger_event_id (anomaly — flag for editorial review)

Editorial backlog (m's work, not coder):

  1. Reparent the 73 orphan globals via /admin/procedural-events?orphan=true&parent_filter=null (design §4.2). Per PT, walk each rule, assign proceeding_type_id + parent_id, set condition_expr where applicable, publish.
  2. Investigate the 1 'neither' rule.

Once orphan count hits zero, the next coder follow-up lands:

  • DROP TABLE paliad.trigger_events
  • ALTER TABLE paliad.sequencing_rules DROP COLUMN trigger_event_id
  • Drop the sequencing_rules_trigger_event_id_fkey FK
  • Remove POST /api/tools/event-deadlines handler + EventDeadlineService
  • Remove the 5 read sites enumerated in P4's scope (deadline_rule_service.go:226, event_deadline_service.go:79+244, event_type_service.go:40+414, export_service.go:1680, cmd/gen-upc-snapshot/main.go:185-202)
  • Port the deadline_rule_service.go:226-285 label-fallback path to procedural_events.name

Design reference: docs/design-deadline-system-revision-2026-05-27.md §2.1 / §3.4 / §4.3 / §5 P5 row.

**Phase 2 coder train — status as of t-paliad-331 (ritchie)** **Slices shipped + merged to main:** - **P0** d36cc9e — `projects.scenario_flags` SSoT (mig 154) + `scenario_flag_catalog` table + `GET/PATCH /api/projects/{id}/scenario-flags` endpoints + Mode B Fristenrechner flag bind + `scenario-flags.ts` client module + cross-surface `scenario-flag-changed` CustomEvent. - **S1 + S1a** 3533d79 — `LookupFollowUps` returns all rows + computes `is_cross_party`; UI muted-renders cross-party with Gegenseitig badge; write-back unconditionally excludes cross-party; `SearchEvents` filters out `is_spawn=true` so spawn-only events drop out of the picker (terminal leaves stay pickable per design §2.2 carve-out). - **P1** 3a4e99c — `upc.apl.unified` retired; rules re-bound to `upc.apl.merits` / `upc.apl.cost` / `upc.apl.order` by event-code prefix (mig 155); `upc.pi.cfi.appeal_spawn` retargeted to orders track per design §3.1; `lookup_events_test.go` assertions updated. - **P3** 480332a — Three-way detail filter (Nur Pflicht / Gewählt / Alle Optionen) on `/tools/verfahrensablauf`; per-rule Aufnehmen/Entfernen chips writing `rule:<uuid>` entries to `projects.scenario_flags`; subtree-hide-on-unselected-ancestor render logic; localStorage-persisted view-mode; conditional rules treated as unselected in 'Gewählt' even when mandatory. **Pending merge:** - **P2** 9940dd8 — `condition_expr` write-validator. Grammar locked to `{flag}` | `{op:'and'|'or', args:[...]}`; called from `RuleEditorService.Create` + `UpdateDraft`; 9 shape-unit tests + 2 live-DB tests gated on TEST_DATABASE_URL. All 18 active+published `condition_expr` rows in the DB conform. - **P4 (partial)** d6a5ded — Hybrid-rule cleanup (mig 156) NULL'd the 2 rules carrying both `parent_id` AND `trigger_event_id` per §2.1. `POST /api/tools/event-deadlines` now responds with `Deprecation: true` + RFC 8594 / 9745 `Link` header pointing at this issue. **Final P4 deferred (editorial follow-up — not coder scope):** Live-DB audit shows the table-drop cannot happen yet: - `paliad.trigger_events` carries 110 live rows - 78 active sequencing_rules still reference `trigger_event_id` (post-mig-156); of those, **73 are orphans** (`proceeding_type_id IS NULL`) addressed only via `trigger_event_id` - 33 `event_types` rows reference `trigger_event_id` - 1 orphan rule has neither `parent_id` nor `trigger_event_id` (anomaly — flag for editorial review) **Editorial backlog (m's work, not coder):** 1. Reparent the 73 orphan globals via `/admin/procedural-events?orphan=true&parent_filter=null` (design §4.2). Per PT, walk each rule, assign `proceeding_type_id` + `parent_id`, set `condition_expr` where applicable, publish. 2. Investigate the 1 'neither' rule. **Once orphan count hits zero, the next coder follow-up lands:** - `DROP TABLE paliad.trigger_events` - `ALTER TABLE paliad.sequencing_rules DROP COLUMN trigger_event_id` - Drop the `sequencing_rules_trigger_event_id_fkey` FK - Remove `POST /api/tools/event-deadlines` handler + `EventDeadlineService` - Remove the 5 read sites enumerated in P4's scope (`deadline_rule_service.go:226`, `event_deadline_service.go:79+244`, `event_type_service.go:40+414`, `export_service.go:1680`, `cmd/gen-upc-snapshot/main.go:185-202`) - Port the `deadline_rule_service.go:226-285` label-fallback path to `procedural_events.name` Design reference: `docs/design-deadline-system-revision-2026-05-27.md` §2.1 / §3.4 / §4.3 / §5 P5 row.
Author
Collaborator

EDITORIAL CLEANUP COMPLETE (t-paliad-333)

Result

  • 45 orphans reparented (proceeding_type_id assigned)
  • 44 NULL rule_codes backfilled (the orphan overlap)
  • +16 non-orphan NULL rule_codes backfilled (apl/disc/dmgs/inf/rev pleadings)
  • Total: 60 NULL rule_codes → 0 within is_active=true AND lifecycle_state='published'

Verification:

SELECT COUNT(*) FILTER (WHERE proceeding_type_id IS NULL) AS orphans,
       COUNT(*) FILTER (WHERE rule_code IS NULL) AS null_rule_codes
  FROM paliad.sequencing_rules
 WHERE is_active=true AND lifecycle_state='published';
-- → orphans=0, null_rule_codes=0

Clusters processed (9 transactions, each with paliad.audit_reason):

  1. UPC core pleadings (4 rules) — Klageerwiderung→RoP.023, Nichtigkeitswiderklage→RoP.025, Verletzungswiderklage→RoP.053, Erwiderung-CCR-und-Replik→RoP.029.
  2. Patentänderung-chain (9 rules) — split by trigger: statement_of_defence_with_CCR→inf.cfi/RoP.030.1; statement_for_revocation→rev.cfi/RoP.050; subsequent stages RoP.032.x / RoP.056.4 / RoP.052 per existing convention.
  3. UPC Appeal (12 rules) — Berufungsschrift+Begründung 220.1(a)/(b)→apl.merits/RoP.224.1(a), 220.1(c)→apl.order/RoP.224.1(b); Anschlussberufung→RoP.237; Wiederaufnahme→RoP.247.1/247.2; Anfechtung-Verwerfung→RoP.245.
  4. UPC Costs + leave-to-appeal (3 rules) — RoP.220.2 / RoP.220.3 / RoP.151.
  5. EPA-Entscheidungs-Überprüfung (2 rules) — UE-rejection→RoP.097, Office-decision→RoP.088 (both upc.epo.review).
  6. PI/BSV Hauptsache (2 rules) — saisie→bsv.cfi/RoP.198, PM→pi.cfi/RoP.213.
  7. UPC misc side-actions (9 rules) — RoP.007.4, RoP.109, RoP.109.5 ×2, RoP.197.3, RoP.262.2, RoP.323, RoP.333, RoP.353. Default PT upc.inf.cfi=8 where the side-action is context-agnostic.
  8. Schutzschrift-Erneuerung (1 rule) — upc.pl.cfi=188, RoP.207.9.
  9. DE+EPA (2 rules) — § 296a ZPO→de.inf.lg, Art. 121 EPÜ→epa.grant.exa.
  10. Rule_code backfill for non-orphan rules (16 rules) — apl.merits RoP.235.1/237, apl.order RoP.235.2/237, disc.cfi RoP.142 (×3), dmgs.cfi RoP.137 (×3), inf.cfi RoP.029 (×2) + RoP.056.1/056.3, rev.cfi RoP.049.1/052.

Compound-name rules — flagged for m's split-review (assigned dominant proceeding, may want split into separate rules):

  • 7b548c48 (1 mo, trigger reply-to-defence-CCR-infringement) — "Duplik … Verletzungswiderklage + Patentänderungsantrag" → assigned rev.cfi/RoP.056.4 (dominant: Verletzungswiderklage).
  • 02ae9c1f (1 mo, trigger reply-to-defence-counterclaim) — "Duplik zur Replik, Replik … Patentänderung" → assigned inf.cfi/RoP.029.
  • 37bd034b (2 mo, trigger defence-to-revocation) — "Replik Nichtigkeitsklage + Erwiderung Patentänderung + Erwiderung Verletzungswiderklage" → assigned rev.cfi/RoP.052 (dominant: revocation reply).
  • ec2a1274 (2 mo, trigger defence-to-counterclaim) — "Replik Widerklage + Duplik Klageerwiderung + Erwiderung Patentänderung" → assigned inf.cfi/RoP.029.
  • 7e65a434 / dfd52792 / 8cdf54eb (Patentänderung Erwiderung/Replik/Duplik single-events) — assigned inf.cfi/RoP.032.x dominant; the brief lists "Patentänderung-chain duplication into both inf.cfi+rev.cfi (3 rules need CREATE-ing copies — needs care)" as a separate ticket. Recommend creating rev.cfi copies (RoP.043.3 / RoP.032.3) in a follow-up.

Remaining for m's manual review:

  • 6 archived rules with NULL rule_code (lifecycle_state='archived', is_active=false) — 5 × "Mängelbeseitigung / Zahlung" duplicates + 1 × "Vorgängige Einrede". Out of scope (archived).
  • 1 draft rule with NULL proceeding_type_id16e262d2 "Antrag auf Weiterbehandlung (DPMA)" (§ 123a PatG) — draft, not yet published. m to publish with proceeding selection.
  • 11 MULTI-ROOT proceeding_types (separate ticket per RFC) — head consolidation deferred.
  • Two-trigger-model coexistence — these 45 reparented orphans all carry legacy trigger_event_id AND new-model parent_id-chained equivalents already exist for most. They duplicate semantically. The Phase 2 design (docs/design-deadline-system-revision-2026-05-27.md) calls for deprecating trigger_events; archiving these legacy rules is the cleanup target then. Not done here to avoid destructive ops without snapshot precedent (per brief).

Verification: mai/curie/researcher-lexy-finish branch (no code changes — DB-only via Supabase MCP, audit_reason set on every TX).

Refs: t-paliad-333, m/paliad#149.

### EDITORIAL CLEANUP COMPLETE (t-paliad-333) **Result** - **45 orphans reparented** (proceeding_type_id assigned) - **44 NULL rule_codes backfilled** (the orphan overlap) - **+16 non-orphan NULL rule_codes backfilled** (apl/disc/dmgs/inf/rev pleadings) - **Total: 60 NULL rule_codes → 0** within `is_active=true AND lifecycle_state='published'` Verification: ```sql SELECT COUNT(*) FILTER (WHERE proceeding_type_id IS NULL) AS orphans, COUNT(*) FILTER (WHERE rule_code IS NULL) AS null_rule_codes FROM paliad.sequencing_rules WHERE is_active=true AND lifecycle_state='published'; -- → orphans=0, null_rule_codes=0 ``` **Clusters processed (9 transactions, each with `paliad.audit_reason`):** 1. UPC core pleadings (4 rules) — Klageerwiderung→RoP.023, Nichtigkeitswiderklage→RoP.025, Verletzungswiderklage→RoP.053, Erwiderung-CCR-und-Replik→RoP.029. 2. Patentänderung-chain (9 rules) — split by trigger: `statement_of_defence_with_CCR`→inf.cfi/RoP.030.1; `statement_for_revocation`→rev.cfi/RoP.050; subsequent stages RoP.032.x / RoP.056.4 / RoP.052 per existing convention. 3. UPC Appeal (12 rules) — Berufungsschrift+Begründung 220.1(a)/(b)→apl.merits/RoP.224.1(a), 220.1(c)→apl.order/RoP.224.1(b); Anschlussberufung→RoP.237; Wiederaufnahme→RoP.247.1/247.2; Anfechtung-Verwerfung→RoP.245. 4. UPC Costs + leave-to-appeal (3 rules) — RoP.220.2 / RoP.220.3 / RoP.151. 5. EPA-Entscheidungs-Überprüfung (2 rules) — UE-rejection→RoP.097, Office-decision→RoP.088 (both upc.epo.review). 6. PI/BSV Hauptsache (2 rules) — saisie→bsv.cfi/RoP.198, PM→pi.cfi/RoP.213. 7. UPC misc side-actions (9 rules) — RoP.007.4, RoP.109, RoP.109.5 ×2, RoP.197.3, RoP.262.2, RoP.323, RoP.333, RoP.353. Default PT upc.inf.cfi=8 where the side-action is context-agnostic. 8. Schutzschrift-Erneuerung (1 rule) — upc.pl.cfi=188, RoP.207.9. 9. DE+EPA (2 rules) — § 296a ZPO→de.inf.lg, Art. 121 EPÜ→epa.grant.exa. 10. Rule_code backfill for non-orphan rules (16 rules) — apl.merits RoP.235.1/237, apl.order RoP.235.2/237, disc.cfi RoP.142 (×3), dmgs.cfi RoP.137 (×3), inf.cfi RoP.029 (×2) + RoP.056.1/056.3, rev.cfi RoP.049.1/052. **Compound-name rules — flagged for m's split-review (assigned dominant proceeding, may want split into separate rules):** - `7b548c48` (1 mo, trigger reply-to-defence-CCR-infringement) — "Duplik … Verletzungswiderklage + Patentänderungsantrag" → assigned rev.cfi/RoP.056.4 (dominant: Verletzungswiderklage). - `02ae9c1f` (1 mo, trigger reply-to-defence-counterclaim) — "Duplik zur Replik, Replik … Patentänderung" → assigned inf.cfi/RoP.029. - `37bd034b` (2 mo, trigger defence-to-revocation) — "Replik Nichtigkeitsklage + Erwiderung Patentänderung + Erwiderung Verletzungswiderklage" → assigned rev.cfi/RoP.052 (dominant: revocation reply). - `ec2a1274` (2 mo, trigger defence-to-counterclaim) — "Replik Widerklage + Duplik Klageerwiderung + Erwiderung Patentänderung" → assigned inf.cfi/RoP.029. - `7e65a434` / `dfd52792` / `8cdf54eb` (Patentänderung Erwiderung/Replik/Duplik single-events) — assigned inf.cfi/RoP.032.x dominant; the brief lists "Patentänderung-chain duplication into both inf.cfi+rev.cfi (3 rules need CREATE-ing copies — needs care)" as a separate ticket. Recommend creating rev.cfi copies (RoP.043.3 / RoP.032.3) in a follow-up. **Remaining for m's manual review:** - **6 archived rules with NULL rule_code** (`lifecycle_state='archived'`, `is_active=false`) — 5 × "Mängelbeseitigung / Zahlung" duplicates + 1 × "Vorgängige Einrede". Out of scope (archived). - **1 draft rule with NULL proceeding_type_id** — `16e262d2` "Antrag auf Weiterbehandlung (DPMA)" (§ 123a PatG) — draft, not yet published. m to publish with proceeding selection. - **11 MULTI-ROOT proceeding_types** (separate ticket per RFC) — head consolidation deferred. - **Two-trigger-model coexistence** — these 45 reparented orphans all carry legacy `trigger_event_id` AND new-model `parent_id`-chained equivalents already exist for most. They duplicate semantically. The Phase 2 design (`docs/design-deadline-system-revision-2026-05-27.md`) calls for deprecating `trigger_events`; archiving these legacy rules is the cleanup target then. Not done here to avoid destructive ops without snapshot precedent (per brief). Verification: `mai/curie/researcher-lexy-finish` branch (no code changes — DB-only via Supabase MCP, audit_reason set on every TX). Refs: t-paliad-333, m/paliad#149.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#149
No description provided.