Files
paliad/docs/design-unified-procedural-events-tool-2026-05-27.md
mAi 0aaa523494
Some checks failed
Paliad CI gate / build (push) Has been cancelled
Paliad CI gate / test-go (push) Has been cancelled
Paliad CI gate / deploy (push) Has been cancelled
design: fold m's 12 decisions into unified procedural-events doc (m/paliad#151)
- §11.5 m's decisions section (9 on-rec + 3 divergent)
- diverged: Q2 /tools/procedures (English), Q3 all-tabs+search-in-filter-strip, Q11 hard cut no dual ship
- §11.5.1 changes triggered by divergences (URL rename, all-tabs behaviour, U4 rewrite)
- URL refs throughout body updated to /tools/procedures
- U4 slice rewritten to 301 hard-cut per Q11
2026-05-27 19:54:50 +02:00

50 KiB
Raw Permalink Blame History

Design — Unified procedural-events tool (m/paliad#151)

Task: t-paliad-334 Gitea: m/paliad#151 Inventor: cronus (shift-1, fresh context — name-recycled, not the cronus from earlier today) Date: 2026-05-27 Branch: mai/cronus/inventor-unified Status: Draft — coder gate held; awaiting m's go on the unification approach

Builds on:

  • docs/assessment-deadline-system-2026-05-27.md (athena, Phase 1 audit — premises)
  • docs/design-deadline-system-revision-2026-05-27.md (atlas, model + per-surface revisions — pre-locked decisions)
  • docs/design-fristenrechner-overhaul-2026-05-26.md (cronus 2026-05-26 inventor, Mode A + B + result shipped via t-paliad-322 / m/paliad#146 S1-S6)
  • docs/design-event-card-choices-2026-05-25.md, docs/design-determinator-row-cascade-2026-05-13.md (per-card choice + determinator routing — current Verfahrensablauf state)

m's framing (2026-05-27 19:13):

There are many dimensions by which we can display and filter our procedural events. Maybe we should hire an inventor to find out the best methods from the ones we already have? It makes sense to narrow things, display them in sequence and context, make selections etc. It just needs to be done well, preferably in a unitary tool. There should be alternative means to derive at what you want to derive at.


§0 Premises — what the inventor is and isn't doing

This is a surface-layer design. The model layer is locked by atlas's design-deadline-system-revision-2026-05-27.md (Q1-Q12 + 14:34/14:40 post-ratification additions, all m-decided 2026-05-27). The shipped Fristenrechner Mode A + Mode B + result view is the model-side foundation; the in-flight atlas P0-P5 train extends Verfahrensablauf and the scenario SSoT.

The inventor's question is not "how should the rule graph be modelled" — that's settled. It's: of the 6 surfaces that read this model, do we have the right surfaces? Should they unify into one tool, two, or stay as today's set?

Out of scope per the issue + paliadin/head brief:

  • Calculator (pkg/litigationplanner.CalculateRule) — working.
  • /admin/procedural-events as an editorial write surface — different audience, different action set, must stay separate.
  • /projects/{id} Verlauf — per-Akte actuals surface, not the ablauf-tool. Sister tool, not subsumable.
  • SmartTimeline projection — per-project read view that composes actuals + projections; sister to Verlauf, project-bound. Not subsumable.
  • youpc.org/deadlines — cross-repo public surface. Snapshot consumer.
  • Outlook / Calendar sync UI.

In-scope unification candidates (4 surfaces): the three Fristenrechner modes (A search + B wizard + result) and Verfahrensablauf — these read the same model (sequencing_rules + procedural_events + scenario_flags) to answer questions about the same underlying graph. The question is whether they're best presented as one URL with multi-mode entry, two URLs with shared vocabulary, or as today's split.


§1 Audit of the 6 surfaces

For each surface: question it answers, dimensions it filters/anchors on, what it does well, what it does poorly, overlap with neighbours.

§1.1 /tools/fristenrechner Mode A — "Direkt suchen" (shipped t-paliad-322 S3)

Question shape: "I know a procedural event happened (e.g. Klageerwiderung). What follow-ups come next?"

Dimensions used:

  • Filters (top strip): forum (UPC/DE/EPA/DPMA), proceeding_type, event_kind (filing/hearing/decision/order), primary_party.
  • Anchor (the search result): one procedural_event row → lock as trigger.
  • Inbox secondary chip (CMS / beA / postal): auto-derives forum.

Path: Filter strip → free-text search → result row click → linear follow-up view (handed off to §1.3).

Strengths: Power-user surface; one box does everything; forgiving to misspellings via pg_trgm; deep-linkable via ?mode=search&q=…&forum=….

Weaknesses: Search returns every event including spawn-only and leaves (atlas §2.2 P0 fix in flight); no visualisation of where the picked event sits in the proceeding tree.

Overlap: Picks the same procedural_event rows that Mode B R4 lands on; picks the same proceeding chips that Verfahrensablauf shows. Filter strip is a subset of Verfahrensablauf's filter chips.

§1.2 /tools/fristenrechner Mode B — "Geführt" wizard (shipped t-paliad-322 S4)

Question shape: Same as Mode A but for users who don't know how to phrase the question. Narrows by Q&A.

Dimensions used: All five Mode A filters reframed as wizard rows:

  • R1 event_kind (Filter badge)
  • R2 forum / jurisdiction (Filter, skipped if R1 narrows)
  • R3 proceeding_type (Qualifier, auto-skipped on single match)
  • R4 procedural_event (Qualifier — the landing question)
  • R5 primary_party (Qualifier, only when follow-ups differ by side)

Path: Q-by-Q chip pick → R4 lock → linear follow-up view (handed off to §1.3).

Strengths: Onboarding-friendly; auto-prefills from Akte (projects.proceeding_type_id → R3, projects.our_side → R5); preserves compatible downstream picks on back-nav.

Weaknesses: No tree-context view of the answer; the user lands on a flat result with no zoom-out.

Overlap: Same R4 event set as Mode A's search results. Same downstream result view.

§1.3 /tools/fristenrechner result view (shipped t-paliad-322 S2)

Question shape: Given a locked event + trigger date, what dated follow-ups exist?

Dimensions used:

  • Anchor: one sequencing_rule (the trigger's anchor rule).
  • Linear walk: one hop down via parent_id — children of the anchor, grouped by priority.
  • Display axes: priority (4 groups: mandatory / recommended / optional / conditional), party, condition flag, court-set, spawn.
  • Persistent state: per-rule checkboxes (selection for write-back), per-rule date overrides.
  • Write-back: POST /api/projects/{id}/deadlines/bulk with audit_reason.

Strengths: Clear list + write-back footer; sticky trigger card; deep-linkable; cross-party detection in atlas P0 (S1 from t-paliad-327).

Weaknesses: Only shows direct children of the anchor. No visibility of where this slice fits in the proceeding's wider graph. No way to pivot to "show the whole ablauf around this".

Overlap: Selection state UI vocabulary (per-rule checkbox + chip) is conceptually identical to Verfahrensablauf's per-rule selection chips that atlas's P3 will ship.

§1.4 /tools/verfahrensablauf (current state + atlas P3 in flight)

Question shape (today): "What does proceeding-type X look like in full?"

Dimensions used:

  • Anchor: one proceeding_type (chip-picked).
  • Filters: side (claimant/defendant), target (appeal-target — endentscheidung / kostenentscheidung / anordnung / schadensbemessung / bucheinsicht), trigger_date.
  • Scenario flags: CCR / inf_amend / rev_amend / rev_cci, plus per-card choices (appellant / include_ccr / skip).
  • View toggle: columns (3-column swimlane: Unsere Seite | Gericht | Gegnerseite) vs timeline (single-column chronological).
  • Detail-mode toggle (shipped today via m/paliad#149 P3): mandatory_only / selected / all_options.
  • Per-card affordances: [Aufnehmen] / [Entfernen] chips for optional/recommended rules, dotted-border for unselected, greyed for conditional-with-flag-off.

Strengths: The most data-rich surface — every rule for the proceeding rendered with computed dates against trigger_date. View-mode toggle gives detail-level control. URL params are clean (proceeding/side/target/trigger_date); noisy scenario flags live in localStorage (per verfahrensablauf-state.ts).

Weaknesses: The user must already know which proceeding to look at — no entry path from "an event happened" or "search by name". 3-column swimlane reads dense on desktop and unmanageably wide on mobile. Trigger-date is per-page (not per-rule), so the entire ablauf computes from one anchor — fine for kontextfrei browse, awkward for Akte where different rules have different real triggers.

Overlap: Detail-mode + per-rule selection chips share the design vocabulary that result view §1.3 should eventually adopt. Filter dimensions are a superset of Mode A's filter strip.

§1.5 /admin/procedural-events (shipped, Slice B.5)

Question shape: "I need to edit / publish / audit rules."

Dimensions used: Lifecycle filter (draft/published/archived), proceeding chip, trigger-event filter, free-text. Per-row click → editor form. Separate tab for orphans (Slice 10 fuzzy-match staging).

Strengths: Lifecycle-aware; clone-publish workflow; audit log; orphan resolution.

Weaknesses: None for editors. For readers, it's the wrong tool — too much editor-state metadata in the table; no tree / sequence / dates / scenario filtering.

Overlap: None functional. Shares the rule corpus but its action set (edit/publish/audit/resolve-orphan) is disjoint from the reader surfaces.

Verdict: keep separate. Different audience (editors only — m today, the partner team eventually), different action set, different lifecycle vocabulary. Cross-linking is sufficient: every reader-surface row should have a "Diese Regel bearbeiten" link to /admin/procedural-events/{id}/edit for editor users.

§1.6 /projects/{id} Verlauf — out of scope per brief

Project-bound timeline of actual deadlines + appointments + project_events for one Akte. Composes with SmartTimeline projections.

Question shape: "What's happened on my Akte and what's next for this specific case?"

This is conceptually downstream of the ablauf-tool: the ablauf-tool answers "what's the shape of proceeding X"; Verlauf answers "what's the state of my Akte that happens to be proceeding X". The shape becomes the actuals through user actions (write-back from Mode A result view, manual entry, CMS sync).

Verdict: keep separate. Different question, different data shape (instances vs templates).

§1.7 SmartTimeline / ProjectionService — out of scope per brief

Per-project read view via GET /api/projects/{id}/timeline that returns merged actuals + projected future rows (via FristenrechnerService) + parent-node lane aggregation. The render shape is project-bound and lookahead-capped; the model knows about levels (Case / Patent / Litigation / Client) and bubble-up events.

Verdict: keep separate. SmartTimeline composes the ablauf-tool's output with project actuals; it's a consumer, not a peer.

§1.8 youpc.org/deadlines — out of scope (cross-repo)

Public surface backed by the offline UPC snapshot (cmd/gen-upc-snapshot). Snapshot consumer only.

Verdict: keep separate. Different repo, different deploy.


§2 The question→surface→dimension matrix

The single source of truth for "which dimension lives where". Two questions answer "which view does this surface show":

User question Today's surface Anchor input Output shape Output detail
"What's the typical ablauf of upc.inf.cfi?" Verfahrensablauf proceeding_type Tree-or-columns of all rules Whole ablauf
"Was passiert nach Klageerhebung?" Fristenrechner Mode A procedural_event Linear follow-ups (priority groups) Slice through tree
"Was passiert nach… (don't know the event name)?" Fristenrechner Mode B Q&A → procedural_event Same as Mode A Same
"Welche Fristen für meine Akte ergeben sich?" Fristenrechner Mode A/B + ?project= Akte + procedural_event Linear follow-ups + write-back Same + actions
"Wie sieht der gesamte Ablauf für meine Akte aus?" Verfahrensablauf + ?project= Akte (derives proceeding_type) Tree-or-columns + scenario Whole ablauf + state
"Welche Regeln gibt's? Wie bearbeite ich sie?" /admin/procedural-events Editor table Editor metadata
"Was steht auf meinem Akten-Plan?" /projects/{id} Verlauf Akte Actuals timeline Per-instance state

Dimensions matrix — same dimension axis, varied surface presentation:

Dimension Cardinality Mode A Mode B Result Verfahrensablauf Admin
forum (jurisdiction) 4 top-chip filter R2 trigger-card badge — (anchored by PT) search facet
proceeding_type 23 top-chip filter R3 (auto-skip on single) trigger-card chip chip strip (the anchor) dropdown filter
event_kind 5 top-chip filter R1 trigger-card badge — (in cards) search facet
primary_party 5 top-chip filter R5 (when needed) per-rule chip swimlane column / per-card
priority 4 group header view-mode toggle + card style column
condition_expr (gating) bool conditional group greyed cards + flag strip rule editor field
is_spawn bool hidden (atlas filter) hidden "⇲ Verfahren öffnen" CTA leaf with ⇲ icon column
is_court_set bool "vom Gericht" badge greyed-date card column
parent_id (chain depth) derived "Folgen: N" count depth-1 only (children of anchor) depth-N indentation / tree walk "abhängig von" chip
selection state (scenario_flags rule:<uuid>) per-rule checkbox (write-back) [Aufnehmen]/[Entfernen] chips
scenario flags (named: with_ccr, with_amend, …) 3 bound checkboxes (read-only) flag strip (canonical edit surface) rule editor field
view-mode (detail level) 3 — (always "selected") top toggle
trigger_date date result view input result view input top of card per-page input

Reading the matrix. Every dimension lives at least two surfaces over. The user's mental model has to translate "the proceeding chip on Verfahrensablauf" to "R3 in Mode B" to "the proceeding filter strip in Mode A" — three names, same dimension. Same for forum, event_kind, party.

This is the friction m's framing pointed at: the dimensions are shared, but the surface vocabulary is not.


§3 Consolidation proposal

§3.1 The honest answer first

Of the 6 surfaces:

  • 2 stay separate, correctly/admin/procedural-events (editorial audience) and /projects/{id} Verlauf + SmartTimeline (per-Akte actuals). They serve different question shapes and audiences. Cross-link liberally; do not merge.
  • 4 are candidates for unification — Fristenrechner Mode A + Mode B + result + Verfahrensablauf. Same underlying data, same dimensions, two zoom levels on one graph. Today they sit at two URLs (/tools/fristenrechner + /tools/verfahrensablauf) with separate filter vocabularies.

§3.2 The unified surface: /tools/procedures

Proposal: consolidate the 4 reader surfaces into one page at /tools/procedures (the more general name; both "Fristenrechner" and "Verfahrensablauf" are sub-modes inside).

┌─────────────────────────────────────────────────────────────────────────┐
│  /tools/procedures                                                        │
│  ┌─ Akte / kontextfrei ─┐  ┌─ Filterleiste ────────────────────────────┐│
│  │ HL-2024-001 ▼ ohne   │  │ Forum • Verfahren • event_kind • Partei   ││
│  └──────────────────────┘  └───────────────────────────────────────────┘│
│  ┌─ Wie willst du einsteigen? ──────────────────────────────────────────┐│
│  │ (•) Verfahren wählen  ( ) Direkt suchen  ( ) Geführt  ( ) Aus Akte  ││
│  └─────────────────────────────────────────────────────────────────────┘│
│  ┌─ Ausgabe ── (Anzeige: Gewählt) ──────────────────────────────────────┐│
│  │  Either: TREE (proceeding-anchored)                                  ││
│  │     │ 📥 Klageerhebung                  [claimant · M]                ││
│  │     │   ├─ Klageerwiderung              [defendant · M]               ││
│  │     │   │    └─ Replik                  [claimant · M · ?with_ccr]    ││
│  │     │   ├─ Widerklage                   [defendant · O · ?with_ccr]   ││
│  │     │   └─ ⇲ Berufungsverfahren öffnen  [SPAWN]                       ││
│  │                                                                       ││
│  │  Or:    LINEAR (event-anchored, after locking)                       ││
│  │     │ 🎯 Klageerwiderung (defendant, 2026-04-01)                     ││
│  │     │ ─────────────────────────────────────────────                  ││
│  │     │ Pflicht: Replik (1 Monat) ☑                                    ││
│  │     │ Empfohlen: Vorl. Einwendungen ☑                                ││
│  │     │ Optional: …                                                     ││
│  │     │ Bedingt: …                                                      ││
│  │     │ [In Akte speichern]                                             ││
│  │                                                                       ││
│  │  Pivot: every card has "Im Ablauf zeigen" ↔ "Folge-Fristen anzeigen" ││
│  └─────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────┘

The page carries one URL, one filter strip, one Akte picker, one selection-state store (scenario_flags), one view-mode toggle, and two output shapes the user can toggle between:

  1. Tree output (proceeding-anchored): the current Verfahrensablauf rendering — every rule of a proceeding, depth-indented via parent_id, with per-rule chips for selection and the three view-modes (Nur Pflicht / Gewählt / Alle Optionen).
  2. Linear output (event-anchored): the current Mode A/B result view — sticky trigger card + 4 priority groups of follow-ups + write-back footer.

The entry mode selects which output you land on:

  • "Verfahren wählen" + chip → tree of that proceeding.
  • "Direkt suchen" + search → linear follow-ups of the picked event.
  • "Geführt" wizard → linear follow-ups of the wizarded event.
  • "Aus Akte" → tree of the Akte's proceeding, with scenario_flags pre-loaded.

The two outputs share the filter strip, the Akte context, the scenario state, the per-card UI vocabulary. Cross-pivoting is one click: from any rule card in the tree, "Folge-Fristen anzeigen" pivots to linear-from-that-anchor; from the linear view, "Im Ablauf zeigen" pivots back to the tree with the anchor highlighted.

§3.3 Alternative — keep the URLs split, tighten alignment

The minimum unification, if m balks at folding two pages into one: keep /tools/fristenrechner and /tools/verfahrensablauf as distinct URLs but:

  • Standardise the filter strip vocabulary (same chip names, same order, same colour coding).
  • Share the entry-mode dropdown / tab UI components.
  • Mutual deep-links: every result-view row has "Im Ablauf zeigen" → Verfahrensablauf URL with anchor; every Verfahrensablauf tree node has "Folge-Fristen" → Fristenrechner URL with event locked.
  • Selection state already shared via projects.scenario_flags from atlas P0.

This is the conservative path. It preserves URL stability but accepts that "which tool for which question" remains a learned concept rather than a single-doorway tool.

§3.4 Inventor's recommendation

Unify (§3.2) — m's framing ("preferably in a unitary tool") + the dimension matrix showing 6+ shared filters argue strongly. The cost of two URLs is two filter vocabularies, two mental models, two cmd-K targets. Folding them is a few weeks of frontend work after atlas's P3 lands; the data layer is already ready.

The risk is not the merge — it's the rename. /tools/fristenrechner is the name lawyers know. Naming choices in §11.Q2 below.


§4 Multi-dimensional filter spec

Where each dimension lives in the unified surface. Categories: anchor (the thing the output is rooted on), filter (narrows what's rendered), qualifier (refines the anchor), display (per-card affordance), state (persists across surface).

Dimension Category Where (entry mode) Where (tree output) Where (linear output)
forum filter top strip chip top strip chip (narrows PT chips) top strip chip + trigger-card badge
proceeding_type anchor (tree) / filter (linear) "Verfahren wählen" chip-grid; "Direkt"/"Geführt" filter strip The anchor — header above tree trigger-card chip
event_kind filter "Geführt" R1; Mode A filter chip per-card icon per-rule row icon
primary_party filter "Geführt" R5; Mode A filter chip; Akte (our_side) swimlane column OR per-card chip (view-mode-dependent) per-rule chip + Gegenseitig badge
priority display view-mode toggle + per-card style group header (4 groups)
condition_expr (gating) state greyed + flag-strip activation conditional group + read-only checkbox
is_spawn display filtered out of pickers (atlas §2.2) leaf with ⇲ icon "⇲ Verfahren öffnen" CTA, no date
is_court_set display greyed-date card with "vom Gericht" badge "vom Gericht" badge, no date
parent_id (chain depth) display tree indentation hidden (linear shows depth-1 only)
selection state rule:<uuid> state [Aufnehmen]/[Entfernen] chips checkbox (write-back)
named scenario flags (with_ccr, …) state flag strip above tree read-only mirror in conditional group
view-mode (detail level) display three-way segmented top toggle — (always Gewählt)
trigger_date anchor (linear) / display (tree) linear: result view date input tree: optional per-page input, defaults today linear: top-card date input (canonical)
is_cross_party (derived) display muted style + Gegenseitig badge muted style + Gegenseitig badge

Design principle: dimensions stay in the same chip / control, regardless of which output is showing. The user learns the filter strip once. The output reacts.


§5 Alternative paths spec — four ways to derive at the same outcome

m's "alternative means to derive at what you want" rendered explicitly. All four paths converge on the same underlying rule-set view; only the entry experience differs.

Path 1: PROCEEDING-FIRST (German-lawyer approach)
  "Ich öffne ein UPC-Verletzungsverfahren — wie sieht das aus?"
  1. Page open → "Verfahren wählen" tab (default if no Akte)
  2. Chip-grid: pick `upc.inf.cfi`
  3. Tree renders. User sees full ablauf.
  4. (Optional) Click rule → drill to linear follow-ups of that rule.

Path 2: EVENT-FIRST (UPC-lawyer / paralegal)
  "Das Gericht hat einen Hinweisbeschluss erlassen — was bedeutet das?"
  1. Page open → "Direkt suchen" tab
  2. Filter strip: Forum=UPC + event_kind=order
  3. Search "Hinweis" → 3 hits
  4. Click `upc.inf.cfi.cmo_review` → linear follow-ups (Antrag CMO-Überprüfung etc.)

Path 3: GUIDED (trainee PA)
  "Es ist etwas passiert; ich weiß nicht wie die Frist heißt"
  1. Page open → "Geführt" tab
  2. R1 event_kind: filing
  3. R2 forum: UPC (or skipped if R1 narrowed)
  4. R3 proceeding_type: upc.inf.cfi (auto-skipped if only one)
  5. R4 event chip-strip: pick the relevant event
  6. R5 perspective (only if follow-ups differ)
  7. Linear follow-ups render.

Path 4: AKTE-FIRST (senior partner / paralegal with project context)
  "Auf HL-2024-001 ist heute Klageerwiderung zugegangen — was nun?"
  1. Page open → Akte picker → HL-2024-001
  2. Page auto-derives `proceeding_type` + `our_side` + `scenario_flags`
  3. Default landing: TREE of upc.inf.cfi, scenario flags pre-loaded
  4. Click "Klageerwiderung" card → linear follow-ups, write-back footer enabled
  5. Tick rules → "In Akte speichern" → POST /api/projects/.../deadlines/bulk

All four paths share:

  • the same filter strip (forum / proceeding / event_kind / party — values persist across paths in URL)
  • the same view-mode toggle (when tree is showing)
  • the same scenario_flags (when Akte is loaded)
  • the same per-card vocabulary ([Aufnehmen] / [Entfernen] / [Bedingt] / [Gegenseitig] / )
  • the same cross-pivot affordance ("Im Ablauf zeigen" / "Folge-Fristen anzeigen")

The user can switch paths mid-task: started in Path 4, lost in the Akte's tree, jump to Path 2 (search) to find a specific event, then jump back to the tree via the cross-pivot. Tab state preserved.


§6 Selection state spec

Already locked by atlas's design-deadline-system-revision-2026-05-27.md §2.3 + §2.4a. Briefly, in the unified tool's context:

  • Named flags (with_ccr, with_amend, with_cci, plus catalog extensions) — top "Szenario-Flags" strip when proceeding is locked. Edits write to projects.scenario_flags (Akte) or localStorage (kontextfrei) and dispatch scenario-flag-changed CustomEvent. Both tree and linear views listen and re-render.
  • Per-rule deviations (rule:<uuid> = true|false) — [Aufnehmen] / [Entfernen] chips on each tree card; identical to the result-view checkboxes in linear mode (linear's "checked" state literally is rule:<uuid>=true).
  • Default population: none on project create. The flat-map only stores deviations from priority defaults.

Cross-view sync. When the user toggles "Klageerwiderung" in linear write-back, the tree's corresponding card immediately re-renders with the chip state updated — same CustomEvent. When the user clicks [Aufnehmen] on the tree's "Antrag CMO-Überprüfung", switching to linear shows it pre-checked.

Kontextfrei vs Akte: kontextfrei writes to localStorage["paliad.verfahren.scenario.<proceeding_code>"] (per-proceeding key — different proceedings have different selection sets, matching the existing paliad.verfahrensablauf.scenario.* convention). Akte writes to the DB column.


§7 Sequence visualisation

Three candidate shapes. Issue brief lists "vertical tree, horizontal timeline, collapsible groups, per-priority lanes" as options. Today's surfaces use:

Shape Where today What it does well What it does poorly
3-column swimlane (Unsere / Gericht / Gegenseite) Verfahrensablauf default view Reads side-of-table cleanly; left = our action, right = opponent's Dense at depth; mobile-hostile; cross-party hops zig-zag across columns
Single-column linear timeline Verfahrensablauf alt view Mobile-friendly; chronological Loses parent-chain structure visually
Vertical tree (indented) atlas P3 proposal; ASCII trees in design docs Shows chain depth; clean on desktop + mobile; matches mental model Less easy to read date-order at a glance
Priority groups Mode A/B result view Highlights what's urgent Loses sequence; only works for one anchor

Recommendation: make the tree the canonical desktop shape (atlas P3); the 3-column swimlane becomes an optional view ("Schwimmbahnen") when the user wants side-comparison; mobile defaults to the single-column linear timeline collapsed by depth. Per-priority groups stay as the linear-output sub-shape (only when an event is locked).

This is a strict superset of today's options — no shape is removed.

Concrete rendering rules:

  • Each card carries 4 axes: priority, selection state, conditional gate, cross-party. Visual style composes them: priority = colour stripe; selection = solid vs dotted border; conditional-flag-off = greyed; cross-party = muted + Gegenseitig badge.
  • Spawn rules render as leaf chips with icon. In Akte mode, the chip becomes a CTA: click → create child project of the spawn target's PT, link via parent_project_id. Already wired via /api/projects/{id}/timeline/counterclaim for the CCR case.
  • Court-set rules carry a "vom Gericht bestimmt" badge in place of the computed date. The card is still rendered (it's still part of the ablauf), just without a date column entry.
  • Chain depth is rendered via indentation + connector lines, capped at depth-5 (today's max is 4 for the upc.inf.cfi CCR branch). Beyond depth-3 the lines fold to a "in 3 weiteren Schritten" collapsible hint — keeps long chains from running off the screen.

§8 Context preservation when drilling

m: "when a user drills into a single rule from one entry, how to keep the surrounding sequence visible".

Three options:

  1. Split-pane — left: tree of the proceeding; right: linear follow-ups of the focused rule. Tree highlights the focused node.
  2. Inline drawer — clicking a rule expands an inline drawer beneath it showing follow-ups; tree stays in place; drawer is collapsible.
  3. Breadcrumb pivot — single output shape at a time; pivoting linear→tree shows a breadcrumb chain "upc.inf.cfi > Klageerhebung > Klageerwiderung > [Klageerwiderung is here]"; tree renders with the breadcrumb highlighted.

Inventor pick: option 2 (inline drawer) for desktop, option 3 (breadcrumb) for mobile. Reasons:

  • Split-pane (option 1) is the cleanest visualisation but burns half the screen on context the user might not want. Optional via a "Zwei Spalten" toggle for power users.
  • Inline drawer (option 2) keeps everything in one column with progressive disclosure; the user scrolls through the tree, expands the rule they care about, sees follow-ups, collapses, moves on. Matches how the existing <details> flow already works on /admin pages.
  • Breadcrumb (option 3) is the only sensible mobile pattern — split panes can't, drawers nest awkwardly.

When in the inline drawer, the focused rule's follow-ups render in the same priority-group shape as the linear view; the per-rule [Aufnehmen] / [Entfernen] chips work identically; write-back to Akte works identically. The drawer is the linear view embedded.


§9 Mobile / narrow viewport

Today's Verfahrensablauf 3-column swimlane is desktop-heavy. The tree-output proposal collapses better, but still needs careful narrow-viewport rules.

Layout breakpoints:

  • < 640px (phone): single-column. Filter strip collapses to a sticky "Filter" button → bottom-sheet panel with the same chips. Entry-mode picker collapses to a sticky dropdown ("Verfahren wählen ▾"). Tree renders with no indentation lines; depth-N items get a leading "└ ".indent decoration only. Per-card chips ([Aufnehmen] etc.) move to a "..." menu on each card. View-mode toggle moves to a single icon button cycling Pflicht→Gewählt→Alle.
  • 640-1024px (tablet): filter strip stays at top but wraps; entry-mode picker becomes tabs; tree renders with proper indentation. View-mode toggle and Akte picker stay inline.
  • > 1024px (desktop): full layout per §3.2. Optional "Zwei Spalten" toggle for the split-pane variant (§8.1).

Mobile drill-down (§8 option 3): clicking a card on phone pushes a new route ?focus=<rule_id> and renders the linear follow-up view full-screen with a back-arrow breadcrumb. Back arrow restores the tree at the previous scroll position.

Filter persistence across viewports: URL params survive resize, the bottom-sheet panel reflects the same state as the desktop top-strip — same state machine.


§10 Worked examples — 3 personas

§10.1 Trainee PA — "what's next after Klageerwiderung?"

Persona: Anna, 6-month PA trainee, doesn't know which proceeding "Klageerwiderung" belongs to.

  1. Opens /tools/procedures. No Akte. Lands on "Verfahren wählen" tab (default) but she doesn't want to browse — she wants to find one event.
  2. Clicks "Geführt" tab. R1: was hat sich ereignet → filing. R2: forum → UPC. R3: proceeding_type → upc.inf.cfi (the only filing-forum option that has "Klage" in its events). R4: event chip-strip → Klageerwiderung. R5: perspective — wizard asks because the follow-ups differ → defendant.
  3. Lands on linear follow-ups view. Sees: Pflicht: Replik (claimant, 1 Monat); Empfohlen: Vorl. Einwendungen; Optional: Widerklage; Bedingt: Antrag auf Patentänderung (greyed, with_amend off).
  4. Wants to know: where does Klageerwiderung sit in the bigger picture? Clicks "Im Ablauf zeigen". Tree renders, with Klageerwiderung highlighted; she sees the SoC root above it, the CCR branch beside it, the cascade of Replik/Duplik below.
  5. Anna learns the shape. Back to her task — she copies the Replik date into her notes.

§10.2 Senior partner — brief client on full upc.inf.cfi ablauf

Persona: Dr. Becker, senior litigator, briefing a client on Friday about a new UPC matter that hasn't been filed yet.

  1. Opens /tools/procedures. No Akte (matter not in Paliad yet).
  2. Tab: "Verfahren wählen" → clicks upc.inf.cfi chip.
  3. Tree renders. View-mode at default Gewählt — shows mandatory + recommended. Becker flips to Alle Optionen to brief the client on the full set including conditional branches.
  4. CCR branch greyed (with_ccr off by default in kontextfrei). Becker ticks with_ccr in the flag strip. Tree re-renders; CCR branch lights up.
  5. Becker wants to print this. Cmd-P / "PDF exportieren" (out of scope for this design but flagged). Tree-with-current-state renders cleanly because nothing depends on viewport hover.
  6. After the call, Becker creates the Akte in Paliad. Returns to the page with ?project=HL-2025-031. Same state preserved into the new project — scenario_flags = {with_ccr: true} writes to DB on first PATCH.

§10.3 Paralegal — enter CMS-received Hinweisbeschluss into Akte

Persona: Sandra, paralegal, daily CMS triage. Today: a Hinweisbeschluss arrived on HL-2024-001 (upc.inf.cfi).

  1. Opens /tools/procedures → picks HL-2024-001 from Akte picker.
  2. Page auto-derives proceeding = upc.inf.cfi, our_side = claimant, scenario_flags = {with_ccr: true} (already on this matter).
  3. Default landing: TREE of upc.inf.cfi, scenario state loaded. Sandra sees the full ablauf with the matter's actual selections.
  4. She knows the event is a Hinweisbeschluss → uses the search box (top right corner of the unified page, available in any mode) → types "Hinweis".
  5. Search popover shows 1 result: upc.inf.cfi.cmo_review (Antrag auf CMO-Überprüfung). Sandra clicks → tree scrolls + highlights the rule; drawer expands beneath it showing the follow-up rule upc.inf.cfi.cmo_review_resp with computed date (today + R.333.2 duration).
  6. Drawer footer has "In Akte speichern" button. Sandra ticks the follow-up rule, sets trigger date = today, audit reason = "CMS-Hinweisbeschluss eingegangen", saves.
  7. Deadline inserted into HL-2024-001. Sandra returns to her queue.

Total clicks: 5 (open tool, search, click result, tick, save). No mode-switching, no URL-jumping, no two-tab juggling.


§11 Migration plan

Five-slice train. Each slice ships as one PR. P0 is the model layer atlas already designed; everything below is surface-layer on top.

Slice Mig What ships Reversible?
U0 — Shared filter-strip component Extract Mode A's filter strip + Verfahrensablauf's filter chips into one <FilterStrip> component used by both pages (still two URLs). Standardise chip names, order, colour. Cross-link buttons in both directions. Yes — code-only
U1 — New unified page at /tools/procedures New route + page shell. Carries Akte picker, filter strip, entry-mode tab control. Initially shows TREE view only (lifts from /tools/verfahrensablauf without removing the original). Yes — route addition
U2 — Linear output + drawer + cross-pivot Embed the Mode A/B result-view rendering as an inline drawer in U1. Cross-pivot "Im Ablauf zeigen" / "Folge-Fristen anzeigen" wired. Search box top-right available in all modes. Yes — code-only
U3 — Entry mode tabs (Direkt / Geführt / Verfahren / Aus Akte) Wire Mode A search + Mode B wizard as additional entry tabs on /tools/procedures. All four entry paths converge on either tree or linear output depending on what the user picked. Yes — code-only
U4 — Redirects + deprecation Per m's Q11 (§11.5): hard cut, no dual-shipping. /tools/fristenrechner?… → 301 → /tools/procedures?mode=direkt&… (preserve query params). /tools/verfahrensablauf?… → 301 → /tools/procedures?mode=ablauf&…. Sidebar + cmd-K updated in the same PR. Old *.tsx files deleted. No ?legacy=1 escape. Reversible only by revert PR

Constraint: U0-U3 are independent of atlas P0-P3 and can ship in parallel (different files). U4 should land after atlas P3 (/tools/verfahrensablauf tree) so the redirect target carries the full tree shape from day 1. If atlas P3 slips, U4 stays in the queue.

No DB migration. All state lives in projects.scenario_flags (atlas P0) + localStorage. URL param schema is additive.

Pre-deploy gauntlet: kontextfrei + Akte modes × each entry path × tree + linear output = 16 path/output combinations. Plus mobile narrow viewport for all 4 entry paths. Plus URL deep-link restore for each saved-state shape.


§11.5 m's decisions (2026-05-27)

All 12 questions answered via AskUserQuestion in 3 batches of 4. 9 picks on-recommendation; 3 diverged from the inventor pick. Decisions below; raw question list preserved in §12 as the historical record.

Tier 1 — does the unification happen at all & what does it look like?

  • Q1 (Unify vs Align): Full unification — one URL. [= recommendation] Locks §3.2. The four reader surfaces (Fristenrechner Mode A + Mode B + result + Verfahrensablauf) fold into a single page with entry-mode tabs and two output shapes. Aligned-but-separate (§3.3) is dropped from the plan.
  • Q2 (URL/Name): /tools/procedures — English. [≠ recommendation; m diverged from inventor's /tools/verfahren pick] m's verbatim:

    just one, but english name - call it tools/procedures ... Locks §3.2 + §11 (renames /tools/verfahren/tools/procedures throughout). Rationale: the codebase convention is "English in code, German in UI" (project CLAUDE.md: "All code, table names, Go types, service names, URL paths, API endpoints, file names — English"). /tools/procedures follows that rule; the inventor's /tools/verfahren strawman broke it. The German sidebar entry stays "Verfahren & Fristen" (Q12) — the URL is the developer surface, the label is the user surface.

  • Q3 (Default entry / search shape): All entry modes as tabs + text search combined with dimension filters. [≠ recommendation; m reframed the question] m's verbatim:

    yeah, different tabs, right?! I think we need to have all of the named ones. And we can combine a text search with filters for the dimensions of the event Locks §3.2 + §5 + reshapes §4. All four named entry paths (Verfahren wählen / Direkt suchen / Geführt / Aus Akte) are visible as tabs simultaneously. The search box is part of the filter strip at the top of the page and composes with the chip filters (Forum / Verfahren / event_kind / Partei) at all times. The "Direkt suchen" tab still exists for the explicit search-first workflow, but the search input is also live in tree mode (top-of-page filter strip) — meaning a user browsing a proceeding can refine the tree's rendered set by typing into the same search box that filters Mode A. The default landing question ("which tab is active first") becomes a secondary concern: any of the four tabs is one click away. Default behaviour: first tab in the strip ("Verfahren wählen") is selected on cold open with no Akte, but the URL preserves the user's last-active tab if returning via a deep-link.

  • Q4 (Akte default behaviour): TREE of the Akte's proceeding. [= recommendation] Locks §3.2 + §10.3. Akte picker triggers auto-derivation of proceeding_type + our_side + scenario_flags, lands on the tree view with the matter's state loaded.

Tier 2 — tree mechanics + visual style

  • Q5 (Tree shape): Both vertical tree + 3-column swimlane, with a toggle. [= recommendation] Locks §7. Default desktop = vertical indented tree (clean chain depth, mobile-translatable); "Schwimmbahnen" toggle reveals the 3-column swimlane (Unsere Seite | Gericht | Gegnerseite) for side-comparison. Toggle state in localStorage["procedures:tree_shape"] (per-user, not per-Akte).
  • Q6 (Cross-pivot): Inline drawer beneath the card. [= recommendation] Locks §8. Clicking a rule card expands an inline drawer with the linear follow-up view (priority groups + write-back footer). Tree stays in place above. Multiple drawers can be open. Drawer carries the same per-rule selection chips as the tree, so writes propagate to scenario_flags identically.
  • Q7 (Search position): Always-visible search bar in the filter strip. [= recommendation] Locks §4 + §3.2. Search input lives in the top filter strip next to the chip groups; available in every output mode. Composes with chip filters via AND semantics (chip filters narrow the corpus, search ranks within the narrowed set). This is what m's Q3 reframe asked for.
  • Q8 (Cross-party rows in tree): Show with Gegenseitig badge + muted style. [= recommendation] Locks §7. Tree renders the full graph including opponent rows, muted + badged consistently with the linear view. Identical to atlas's locked treatment for the linear view (design-deadline-system-revision-2026-05-27.md §2.4).

Tier 3 — mobile + migration

  • Q9 (Mobile tree shape): Single-column with indent decorator. [= recommendation] Locks §9. Phone-narrow render keeps depth via leading-marker indentation; SVG connector lines drop; cards stack vertically. Resize back to tablet/desktop restores the full tree with connector lines.
  • Q10 (Mobile drill): Push new route with breadcrumb back. [= recommendation] Locks §9. Clicking a card on phone pushes ?focus=<rule_id> and renders the full-screen linear follow-up view with a back-arrow breadcrumb. Tree scroll position preserved on back. Inline drawer is desktop-only.
  • Q11 (Migration window): Hard cut — no dual-shipping window. [≠ recommendation; m diverged from "2 weeks 302"] m's verbatim:

    not at all Locks §11 (rewrites the U4 slice). When /tools/procedures ships, /tools/fristenrechner and /tools/verfahrensablauf flip directly to redirects (301 permanent, no ?legacy=1 escape hatch). Sidebar entries swap to the new entry in the same release. cmd-K palette swaps to the new entry. No 2-week dual-shipping window. Rationale (interpreted): the audience is internal HLC lawyers (~50 users, all on the same release rhythm). A 2-week dual ship adds complexity for almost no benefit; m would rather flip and fix any broken bookmark via direct comm.

  • Q12 (Sidebar): One entry "Verfahren & Fristen". [= recommendation] Locks §11. Single sidebar item (German label) pointing at /tools/procedures (English URL). cmd-K palette updated to one entry "Verfahren & Fristen" with /tools/procedures as the action.

§11.5.1 Changes triggered by m's divergences

Three picks changed the design beyond ratification. Summarised here so the coder reads the current design, not the pre-grilling strawman.

  1. URL rename /tools/verfahren/tools/procedures (Q2). Replaces every URL reference in §3.2, §4, §5, §10, §11, §14. Page name in the codebase: frontend/src/procedures.tsx. Sidebar label stays German ("Verfahren & Fristen"). Internal Go types stay English (ProceduresPage, etc.).
  2. All-tabs-visible + search-as-filter (Q3). Replaces the strawman's "pick a single default tab" wording in §3.2 + §4. The unified page now renders all four entry-mode tabs at all times (Verfahren wählen / Direkt suchen / Geführt / Aus Akte). The search box is in the filter strip alongside the chip filters and composes with them in every output mode (tree + linear). The "Direkt suchen" tab remains, but its function shifts: it's the search-first cold start tab; once the user has any output (tree or linear), the search box at the top of the page is the canonical re-narrowing affordance. The wizard tab ("Geführt") and the Akte tab still exist as explicit workflows.
  3. Hard cut, no dual-ship (Q11). Slice U4 in §11 is rewritten: 301 redirects on /tools/fristenrechner + /tools/verfahrensablauf to the new page; no ?legacy=1 escape; the old *.tsx files are deleted in the same PR. Bookmarks resolve via the 301; no in-product affordance points at the legacy URL after the merge.

§11.5.2 What stays unchanged

The other 9 picks (Q1, Q4-Q10, Q12) ratified the inventor proposal. The full unification at a single URL with two output shapes (tree + linear drawer), four entry paths, shared selection state via projects.scenario_flags, vertical tree + swimlane toggle, mobile decorator + breadcrumb-back drill-down, single sidebar entry — all locked as drafted in §1-§11.


§12 Open questions for m

Twelve questions, batched 4 + 4 + 4 for AskUserQuestion. The first batch is must-answer (decides the unification's existence + URL shape); the second is shape (tree mechanics + visual style); the third is mobile + migration (operational).

Will be answered via AskUserQuestion per the inventor SKILL; m's picks fold back into a §12.5 m's decisions (2026-05-27) section at the top of this file before the "DESIGN READY FOR REVIEW" signal.

Batch 1 — does the unification happen at all & what does it look like?

  • Q1 (Unify vs Align): Fold the four reader surfaces into /tools/procedures (full unification §3.2), or keep /tools/fristenrechner and /tools/verfahrensablauf as separate URLs and just tighten alignment (§3.3)?
  • Q2 (Naming): If unifying — what's the page name? /tools/verfahren (generic German, my original pick), /tools/fristenrechner (lawyers know this one — repurpose as the supermarket), or /tools/ablauf (closest to what it does)? (m diverged with /tools/procedures — see §11.5.)
  • Q3 (Default entry mode): When the user opens /tools/procedures with no URL params and no Akte, which entry tab is active? "Verfahren wählen" (browse, my pick), "Direkt suchen" (power), "Geführt" (onboarding).
  • Q4 (Akte default behaviour): When user picks an Akte from the picker, default landing — TREE of the Akte's proceeding (my pick) or "remember last view" per-user.

Batch 2 — tree mechanics + visual style

  • Q5 (Tree shape): Desktop tree rendering — vertical indented tree (my pick), 3-column swimlane (current Verfahrensablauf default), or both with a "Schwimmbahnen" toggle.
  • Q6 (Cross-pivot affordance): When clicking a rule card in the tree to see its follow-ups — inline drawer beneath the card (my pick), split-pane (tree left + linear right), or full-page push (replaces tree, breadcrumb back).
  • Q7 (Mode A search location): The free-text "Direkt suchen" entry — only as a top-tab (my pick, with a small search icon always available in tree mode), always-visible search bar at top, or only inside the "Direkt" tab.
  • Q8 (Cross-party rows in linear): Atlas locked "show with Gegenseitig badge, unchecked default, unconditionally excluded from write-back". In tree mode, same treatment (my pick) or hide cross-party rows entirely by default and surface via "Gegenseite einblenden" toggle.

Batch 3 — mobile + migration

  • Q9 (Mobile tree shape): On phones (< 640px) — single-column indented list with leading "└" decorator (my pick), single-column flat list (no indentation), or chronological-timeline view (auto-pivots when narrow).
  • Q10 (Mobile drill-down): Clicking a card on phone — push new route with breadcrumb-back (my pick), inline drawer (cramped on small screens), or modal sheet.
  • Q11 (Migration window): After the unified page ships — 2-week dual-shipping with 302 redirects (my pick, matches t-paliad-322 S5 pattern), 1-week, or 4-week.
  • Q12 (Sidebar entries): Sidebar today has "Fristenrechner" + "Verfahrensablauf" as separate items. Post-merge — one entry "Verfahren & Fristen" (my pick), keep both with both → same URL, or pick one ("Fristenrechner" or "Verfahrensablauf") as the canonical name.

§13 Out of scope

  • Calculator changes (pkg/litigationplanner.CalculateRule). Working.
  • Editorial backfill (curie owns t-paliad-333 in parallel).
  • /admin/procedural-events as a read surface — different audience.
  • /projects/{id} Verlauf — per-Akte actuals; sister tool.
  • SmartTimeline / ProjectionService — per-project read view, downstream consumer.
  • youpc.org/deadlines — cross-repo snapshot consumer.
  • Outlook / Calendar sync UI.
  • PDF export of the tree (mentioned in §10.2 but not designed here).
  • Bulk-write affordances beyond the existing /deadlines/bulk endpoint.
  • Multi-project comparison views (would belong in SmartTimeline at Patent / Litigation / Client level, not in /tools/procedures).
  • Translation between languages of free-text scenario flag names.

  • mBrian: file as [synthesis] linked triggered_by t-paliad-334; related_to athena's assessment + atlas's deadline-system-revision design + cronus's earlier Fristenrechner overhaul design.
  • Cross-refs in this repo: docs/assessment-deadline-system-2026-05-27.md (athena), docs/design-deadline-system-revision-2026-05-27.md (atlas), docs/design-fristenrechner-overhaul-2026-05-26.md (cronus 2026-05-26), docs/design-event-card-choices-2026-05-25.md (existing per-card choice).
  • Gitea: m/paliad#151 (this design), m/paliad#149 (atlas Phase 2), m/paliad#146 (cronus 2026-05-26 Fristenrechner overhaul, S1-S6 shipped).
  • Coder phase (deferred per inventor SKILL): runs after m ratifies via AskUserQuestion. Slice ordering per §11. NOT cronus (parked at "DESIGN READY FOR REVIEW"). A pattern-fluent Sonnet coder picks up U0 first; U1-U3 sequential; U4 gated on atlas P3 landing.