Files
paliad/docs/design-procedures-workflow-tracker-2026-05-27.md
mAi c8f310c62c
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(procedures-tracker): fold m's 7 picks — §11 decisions + §6.5 multi-tl anchor + §9 direct-replace migration (t-paliad-337)
5 picks on-recommendation, 2 diverged:

Q3 (multi-proceeding anchor scope): m picked 'other timelines auto-collapse to header-only' over the recommended 'stay expanded'. Added §6.5 with the header-card render rule.

Q7 (migration cadence): m picked 'direct replace at T1, no flag' over the recommended flag-gated dev. §9 rewritten end-to-end: T1 ships the minimum-viable tracker visibly to users, replacing the catalog UI in the same PR. T2-T4 layer zoom + Akte + polish. T5 is cleanup-only.

The 5 on-rec picks: inline checkbox forks (Q1), sibling-collapse zoom (Q2), 6 curated defaults on cold open (Q4), latest-done-deadline Akte anchor (Q5), global Stichtag (Q6) — all locked as drafted in §1-§8.

Ready for review. Coder gate held; head decides T1 hire.
2026-05-27 21:13:35 +02:00

39 KiB

Design — /tools/procedures workflow tracker (m/paliad#152)

Task: t-paliad-337 Gitea: m/paliad#152 Inventor: atlas (shift-1, fresh — name-recycle, not the atlas from earlier today) Date: 2026-05-27 Branch: mai/atlas/inventor-extend-tools Status: Draft — coder gate held; m to ratify the remaining open questions via AskUserQuestion before any coder shift.

Builds on:

  • docs/design-unified-procedural-events-tool-2026-05-27.md (cronus's U0-U4 design, shipped today as /tools/procedures)
  • docs/design-deadline-system-revision-2026-05-27.md §3.3 + §3.3a (atlas Phase 2 model layer + view-mode toggle)
  • docs/design-fristenrechner-overhaul-2026-05-26.md (cronus 2026-05-26 Mode A+B+result, shipped via t-paliad-322)

Reframe note (2026-05-27 21:01): the first draft of this doc overengineered the surface — three-view toggle, separate compound drawer, separate Konstellationen drawer. m re-anchored: "clean display of timelines that have potential forks the user can select. UX should be key. It should be easy to find your thing." This rewrite collapses to a single canonical shape and folds the zoom / constellation / cross-cut concepts into it. The pre-grilling §13 + the 11-Q batch in §14 of the first draft are gone — superseded by m's 4 answers in §0.2 and the smaller open-question set in §10.


§0 Premises

§0.1 What shipped today and what m hit

/tools/procedures (U0-U4, knuth, m/paliad#151) is a catalog browser:

  • 4 always-visible tabs (Verfahren wählen / Direkt suchen / Geführt / Aus Akte).
  • Shared filter strip + search box at the top (markup-only in U0).
  • Two output shapes — TREE (Verfahrensablauf) and LINEAR (Mode A/B result view) — bound to specific entry tabs.

m's bugs (2026-05-27 20:43 / 20:46):

  1. 4 tabs visible → pre-form leaks across them, page feels like 4 disjoint workflows.
  2. Result view fires too many rules incl. conditional-flag-off + curie's 7 compound rules.
  3. Proaktiv/Gericht/Reaktiv columns are a stance grouping, not a sequence anchor.
  4. No "you are here" marker.
  5. Sequence isn't visualised as a sequence — flat priority groups, not chained.

m's reframe (verbatim, 20:43): "view proceedings with all possible constellations and the sequences and determine where we are in that sequence and what steps are coming next for any given procedural event."

Tightened by m on 21:01:

"clean display of timelines that have potential forks the user can select. procedural_events that act as triggers for mandatory or optional events. And there is a limited type of proceedings — a sequence of the events builds the proceeding. Some aux proceedings, some main… but a lot is connected. UX should be key. It should be easy to find your thing."

§0.2 The four m-answers that lock the architecture

Asked back during the grilling round at 20:57, answered 21:01:

inventor's grilling question m's answer what it locks
1 One canonical shape or still 3 views? "I still want zoomability for one event and all events it triggers. But that can be from within the full timeline/tree as well." One canonical view (full timeline/tree); zoom is an interaction on it, not a separate view. The Anchor / Verfahren / Konstellationen toggle is dropped.
2 What's a "fork" — scenario flags only / +optionals / everything? "c" (everything: flags + optionals + appeal-target + court-set picks) Every choice point in the data is a fork. Optionals (priority='optional') + conditional flags + appeal-target + perspective + court-set scheduling. Inline pickers.
3 "Easy to find" — timeline-as-index / search box / proceeding picker first? "all of these — text search, filter pills, a display of the resulting proceedings timelines" Find = combined affordance. Text search + filter pills + the displayed result is the matched proceeding timelines. The page never has chrome that isn't either the find affordance or the timelines themselves.
4 Aux proceedings inline or drillable? "inline" Aux proceedings draw inline as expandable child timelines hanging off the spawn point in the parent timeline. The full connected graph is one visible thing.

§0.3 Live data the tracker has to work against

Verified 2026-05-27 against paliad.sequencing_rules (231 published / 242 total):

  • 110 chained (parent_id not null) — most rules in a chain.
  • 78 trigger-rooted, 4 spawns (cross-PT), 47 court-set, 18 conditional (6 with_ccr / 4 with_amend / 4 with_cci / 4 compound with_ccr AND with_amend).
  • Biggest single proceeding: upc.inf.cfi (50 rules).
  • ~46 proceeding types total (UPC 35 / DE 5 / EPA 3 / DPMA 3).
  • paliad.deadlines carries both procedural_event_id and sequencing_rule_id → Akte actuals overlay is a direct join.

§0.4 Scope

In: redesign the /tools/procedures surface as a single timeline-tree view with inline forks + a combined find affordance.

Out:

  • Calculator changes.
  • Editorial backfill (curie's t-paliad-333 owns the 7 compound rules + R.109 chain). This design is independent of curie's column-shape work; compound rules surface inline via parent_id like any other rule, with whatever annotation curie ships.
  • /admin/procedural-events write surface.
  • /projects/{id} Verlauf / SmartTimeline — cross-link only.
  • youpc.org cross-repo / Outlook sync / PDF export.

§1 The single canonical shape

One page. One view. Top section = find affordance. Below = matched proceeding timelines, each as an inline-forked tree, vertically stacked.

┌────────────────────────────────────────────────────────────────────┐
│  [🔍 Suche: Klageerwiderung_____________________]                   │
│  Forum:   [● UPC] [DE] [EPA] [DPMA]                                  │
│  Verfahren: [● Verletzung] [● Widerklage] [Berufung] [Nichtigkeit] … │
│  Partei:  [Klägerseite] [● Beklagtenseite]                           │
│  Akte:    HL-2024-001 ▼     Stichtag: 2026-04-01                     │
│                                                                       │
│  2 Verfahren passen — Anker: Klageerwiderung (HL-2024-001)            │
└────────────────────────────────────────────────────────────────────┘

┌─ upc.inf.cfi · Verletzungsverfahren UPC ─────────────────────────┐
│                                                                    │
│  ● Klageerhebung (R.13)                       2026-01-15 · Klg · M │
│  │                                                                  │
│  ▼ ● Klageerwiderung (R.23.1)                 2026-04-01 · Bekl · M │
│      │                                       ━━━━ DU BIST HIER ━━━━ │
│      │  Optionen für dieses Ereignis:                                │
│      │   ☑ Widerklage auf Nichtigkeit                                │
│      │   ☐ Antrag Patentänderung (R.30)                              │
│      │   ☐ Vorläufige Einwendungen                                   │
│      │                                                                │
│      ├─● Replik (R.29.a/b)                    2026-06-01 · Klg · M  │
│      │  ├─● Duplik (R.29.c)                   2026-07-01 · Bekl · M │
│      │  └─● Replik auf Defence to CCR (R.29.d) 2026-08-01 · Klg · M │
│      │     └─● Rejoinder (R.29.e)             2026-09-01 · Bekl · M │
│      │                                                                │
│      ├─● Widerklage auf Nichtigkeit  ✓                              │
│      │   └─▼ Tochterverfahren upc.rev.cfi ▾                          │
│      │       │                                                        │
│      │       ├─● Antrag Patentänderung (R.50)  optional ☐            │
│      │       ├─● Hauptverhandlung [Gericht]                          │
│      │       └─● Entscheidung [Gericht]                              │
│      │                                                                │
│      └─● Vorläufige Einwendungen ☐ (optional, ausgewählt: nein)     │
│                                                                       │
│  ● Mündliche Verhandlung [Gericht bestimmt]                         │
│  │                                                                    │
│  └─● Urteil [Gericht]                                                │
│     └─▼ Berufungsverfahren upc.apl ▸ (auf Endentscheidung)            │
│                                                                       │
└────────────────────────────────────────────────────────────────────┘

┌─ upc.ccr.cfi · Widerklage auf Nichtigkeit (Tochter, oben verlinkt) ┐
│  …                                                                   │
└────────────────────────────────────────────────────────────────────┘

No tabs. No view toggle. The output reacts to the find affordance, the anchor pin, and per-node fork selections.

§1.1 The shape's components

  1. Find header (sticky at top): search input + filter pills + Akte/date row + a one-line result summary. §2.
  2. Timeline-trees (the page body): one block per matched proceeding, full chain + inline forks + inline aux branches. §3-§5.
  3. Anchor pin (when set): the "DU BIST HIER" band on a specific node, optionally with zoom mode collapsing everything else. §6.

That's the entire UI surface. No drawers, no separate drillable panes, no constellation viewer. Forks are inline checkboxes; aux proceedings are inline expandable subtrees; zoom is an interaction on the existing rendering.


§2 The find affordance

m's #3 answer makes this load-bearing: text + pills + result-timelines are all the same affordance. As the user narrows, the timelines below filter; as the timelines change, the result-count summary updates; clicking a node in a timeline auto-narrows the filter pills to that proceeding (optional sugar).

§2.1 Composition

Control Source Composes via Persists in
Free-text search input box, debounced 200ms OR-against (procedural_event.name DE/EN, rule_code, aliases) ?q=<text>
Forum pill row static enum (UPC/DE/EPA/DPMA), single-select AND ?forum=<id>
Verfahren pill row proceeding_type chips, multi-select (deduped from active forum) AND (any-of) ?procs=<csv>
Partei pill row claimant / defendant / both / — (or auto from Akte) AND ?party=<x>
Akte picker dropdown of user's projects seeds Verfahren + Partei + scenario_flags + anchor ?project=<uuid>
Stichtag (date) date input, defaults today feeds computed dates throughout the timelines ?trigger_date=<iso>

All controls live in one sticky header. The header keeps its height stable so the timelines below don't reflow on every keystroke.

§2.2 Cold open behaviour

No URL params, no Akte:

  • Search box empty, all forums neutral, all proceeding pills neutral. Show a curated default of the most-common proceedings: upc.inf.cfi, upc.rev.cfi, upc.apl.merits, de.inf.lg, epa.opp.opd, dpma.opp.dpma. (See Q4 below.)
  • A hint above the timelines: "Suche oder filtere, um andere Verfahren einzublenden."

With a ?project= param: filters pre-fill from the Akte, anchor pins to the latest completed deadline.

With a ?q= or ?event= param: filters pre-fill to match, single matched proceeding renders pinned.

§2.3 What the search matches

Free-text search hits the same corpus the existing /api/tools/fristenrechner/search?kind=events endpoint covers — procedural_events by name + code + aliases. Spawn-only events stay filtered out (per atlas P0 §2.2). Hits surface in two ways simultaneously:

  • The matched proceeding(s) render expanded with the hit event(s) anchor-pinned.
  • A small "Treffer: 3 Ereignisse in 2 Verfahren" summary above the timelines.

If the user types something narrow enough to match a single event, the page auto-pins that event (auto-anchor). If multiple events match, the user picks via a small dropdown under the search input — picking sets the anchor.

§2.4 Why pills, not chips-with-sub-modes

The shipped 4-tab UI tried to express "what kind of question are you asking" via tabs. m's answer #3 collapses that — the find affordance doesn't care which "kind" of question; it cares about the active filter set. A user with a search + a forum + an Akte set gets the right timelines regardless of which tab they "came from". The mental model is: narrow the set; the timelines arrive.


§3 Timelines and forks

Each matched proceeding renders as one card. Inside the card: the proceeding's name + jurisdiction badge in a thin header strip, then the chain.

§3.1 The chain

Vertical, top-to-bottom = chronological. Each node = one procedural_event (the rule that fires it lives inside). Edges = parent_id. Per node:

  • Bullet style by priority: solid filled (mandatory), solid outline (recommended), dotted (optional), dashed (conditional-flag-off and hidden).
  • Bullet colour: priority band — black/grey/blue/light depending on the scale we end up picking. Lime accent (#c6f41c) reserved for the anchor pin.
  • Inline metadata: name, rule code, computed date, party badge, priority badge. Stripped to one line.
  • Court-set events: render with [Gericht bestimmt] in date column.
  • Spawn nodes: terminate the bullet with ▼ Tochterverfahren <code> ▾ — expandable inline; collapsed by default unless the spawn flag is on. §5.

§3.2 Forks — every choice point is one

A "fork" is anywhere the user can flip the proceeding's shape:

  1. Scenario flags (with_ccr, with_amend, with_cci) — currently 3, extensible via curie's scenario_flag_catalog.
  2. Optional rules (priority='optional') — each is a "do I do this?" pick.
  3. Appeal-target picksapplies_to_target array on appeal proceedings (endentscheidung / kostenentscheidung / anordnung / schadensbemessung / bucheinsicht). Per-card chip group at the appeal root.
  4. Perspective — claimant / defendant per proceeding (mostly comes from Akte's our_side, picker overrides).
  5. Court-set timing choiceschoices_offered JSON on sequencing_rules (appellant / include_ccr / skip shapes from einstein). Per-card chip set.

Where forks render. Inline, on the node where the fork's effect begins. Not in a top-of-page flag strip (m's bug #5 — sequences should be visualised as sequences; flags above the tree decouple cause from effect).

Concretely: the with_ccr fork renders as a checkbox on the Klageerwiderung node, because that's where the user decides "we are filing a Widerklage with our KEW". Toggling it lights up the CCR child branches below. Similarly:

  • with_amend renders on the KEW node and on the Antrag-Patentänderung node it gates.
  • with_cci renders on the Defence-to-Revocation node.
  • Optional rules render as a checkbox on their own card.
  • Appeal-target picks render on the appeal root.

If multiple forks share a node, they cluster as a small "Optionen für dieses Ereignis" mini-strip below the node header:

▼ ● Klageerwiderung (R.23.1)             2026-04-01 · Bekl · M
   │ Optionen:
   │  ☑ Widerklage auf Nichtigkeit
   │  ☐ Antrag Patentänderung (R.30)
   │  ☐ Vorläufige Einwendungen einlegen

§3.3 Default rendering ("Gewählt" semantics)

Each node renders iff:

  • It's mandatory (priority='mandatory'), OR
  • It's selected per current scenario state (priority='recommended' unless explicitly deselected; priority='optional' iff explicitly selected; conditional iff flag is on).
  • Same as atlas P3's "Gewählt" view-mode.

Conditional rules whose flag is off do not render at all by default. The fork checkbox to turn the flag on still appears on the gating node — turning it on causes the dependent branch to render.

This is m's bug #2 fix: no more dump of every-rule including flag-off conditional. The forks themselves are the affordance that brings hidden branches into view.

§3.4 Optional reveal — "Alle Optionen"

A single toggle at the top of each proceeding card (NOT page-wide):

[· Gewählt ·] [ Alle Optionen ]

"Alle Optionen" renders every rule including flag-off conditionals (greyed with their flag hint) and unselected optionals (dotted with [Aufnehmen] chip). Useful when the user wants to see the whole shape. Per-proceeding so a page with 3 proceedings can have one in "Alle Optionen" mode without affecting the others. State persists in localStorage per proceeding code.

§3.5 Why dropping "Nur Pflicht"

Atlas P3's three-way toggle had Nur Pflicht / Gewählt / Alle Optionen. With forks made inline + per-node, "Nur Pflicht" loses load-bearing — it was useful when the page had no fork interactivity (you wanted to dial down clutter). Now the user can just leave all forks off and see the mandatory-only chain in Gewählt mode. The two-way Gewählt ↔ Alle Optionen is enough.

§3.6 Cross-party rows

Per atlas §2.4 / m's lock: every rule for the proceeding renders, with rows where the user is not the primary_party muted + carrying a "Gegenseitig" badge. Same treatment in this tracker. Not hidden by perspective; just visually deemphasised.


§4 Court-set events & date rendering

is_court_set=true rules don't compute a date — the court picks it on the day. Two display options that interact:

  • Render with [Gericht bestimmt] in the date column, no date. Standard.
  • When the user has scheduled the actual date (an appointments row on the project or a manual override), the actual date replaces the badge. Akte-only.

If the date is "vom Gericht" and matters as a trigger for downstream events, downstream events render [abhängig von Verhandlung] instead of a date, and recompute live once the court date is known.

choices_offered per-rule (the 3 known shapes today: appellant, include_ccr, skip) — also inline per-node, treated as forks (§3.2 #5).


§5 Aux proceedings inline

Per m's #4 answer: spawned proceedings draw inline as expandable subtrees, not as drillable separate pages.

§5.1 Render

A spawn node renders as a leaf chip terminating the parent's chain segment:

●─● Widerklage auf Nichtigkeit ✓
    └─▼ Tochterverfahren upc.rev.cfi ▾
        │
        ├─● Antrag Patentänderung (R.50) optional ☐
        ├─● Hauptverhandlung [Gericht]
        └─● Entscheidung [Gericht]
            └─▼ Berufungsverfahren upc.apl ▸
  • Collapsed by default unless the gating fork is on (e.g. with_ccr ticked → CCR's spawn into upc.rev.cfi auto-expands).
  • Expanding writes nothing — pure UI state in sessionStorage["procedures:expanded_spawns"].
  • The aux subtree renders with the same node vocabulary as the parent; forks inside the aux are independently editable.
  • Aux subtrees can themselves have aux subtrees (e.g. CCR → Berufung). Depth is bounded by the data — today 2 levels deep at most.

§5.2 Cross-references

When two paths converge on the same aux proceeding (e.g. CCR triggers from a couple of places), the aux renders inline at the first path's spawn point and renders as a back-reference at subsequent spawn points: ▸ (siehe oben: Tochterverfahren upc.rev.cfi). Single source of truth in the rendered tree, even when the graph has multiple edges.

§5.3 Akte mode

In Akte mode, if the spawn was actualised (a child project exists linked via parent_project_id), the aux subtree shows the child project's badge: 📁 HL-2024-001-CCR · Tochterakte. Clicking the badge navigates to that child project. The subtree itself still renders inline.


§6 Anchor pin & zoom

m's #1 answer: "zoomability for one event and all events it triggers, from within the full timeline".

§6.1 The anchor pin

Any node can be pinned as the anchor. Pinning sources:

  • URL ?event=<sequencing_rule_id> (deep link).
  • Search box auto-pin when the search narrows to a single hit.
  • Click-to-pin on any node (small pin icon in the node's metadata row).
  • Akte landing: auto-pin to latest completed deadline.

The pinned node renders with a 4px lime-coloured left band + a ━━ DU BIST HIER ━━ divider above its successors. The pin is also reflected in the find-header's result summary: "Anker: Klageerwiderung (HL-2024-001)".

§6.2 Zoom mode

A small [ 🔍 Fokus ] chip on the anchored node toggles zoom mode for that anchor. When zoom is on:

  • The anchored node's ancestors collapse to a single breadcrumb at the top of the proceeding card:
    upc.inf.cfi ▸ Klageerhebung ▸ ━ Klageerwiderung ━
    
  • The anchored node renders full.
  • Successors render fully (the forward subtree under the anchor).
  • Sibling branches at every ancestor depth collapse to a single-line summary card: … 4 weitere Schritte verborgen — [zeigen].

This is what m means by "zoom into one event from within the timeline" — the same view, just with non-relevant siblings collapsed. Toggle off → full timeline restored, anchor still pinned.

Zoom is page-scoped (one anchor per page, one zoom state). State in URL: ?event=<id>&zoom=1.

§6.5 Multi-proceeding anchor scope (m's Q3 divergence)

When the page shows >1 matched proceeding and an anchor is pinned, the non-anchored proceedings auto-collapse to a header-only one-line card:

┌─ upc.inf.cfi · Verletzungsverfahren UPC ─────┐
│ … full timeline …                            │
│ ━━ DU BIST HIER: Klageerwiderung ━━          │
└──────────────────────────────────────────────┘

┌─ upc.rev.cfi ▸ ausblenden — [zeigen] ────────┐
└──────────────────────────────────────────────┘

┌─ upc.apl.merits ▸ — [zeigen] ────────────────┐
└──────────────────────────────────────────────┘

Clicking a header card's [zeigen] link restores that proceeding's full timeline (the header stays as a per-card affordance for re-collapse). The collapsed state persists in sessionStorage["procedures:collapsed_proceedings"]. Un-pinning the anchor restores all visible proceedings to full-render automatically.

The rule applies regardless of how the anchor was pinned (URL, search-auto, click-to-pin, Akte landing). The find-header result count still shows N proceedings matched — header cards are present, just collapsed.

§6.3 The "where I came from" question

m's brief asked for backward-walk visualisation. Without zoom: the chain above the anchor is the backward walk — it's the same tree. With zoom: the breadcrumb at the top of the proceeding card is the backward walk in compact form. No separate concept; backward walk = upward in the tree.

§6.4 Akte mode: actuals overlay

When ?project=<uuid> is set, each node in the chain queries paliad.deadlines WHERE project_id = $p AND sequencing_rule_id = $r and overlays:

  • status='done' → ✓ in the node bullet area + actual completed date in the date column. Greyed slightly to read as "past".
  • status='open' and due_date < today → ⚠ overdue.
  • status='open' and due_date >= today📅 actual due date if differs from computed; ◇ marker.
  • No deadline row → render as template (current behaviour).

The anchor auto-pins to the latest status='done' deadline by default — the natural reading is "we just finished this".


§7 What lives where: the find header vs the timelines

A short table to make the responsibility boundary explicit:

Concern Find header Timeline body
Pick proceeding(s) Filter pill row (auto-rendered after)
Pick anchor Search-narrow → auto-pin / URL ?event= Click pin icon on any node
Pick perspective Pill (or auto from Akte) (read-only — feeds rendering)
Pick scenario flags (no) Inline fork checkboxes on gating nodes
Pick optional rules (no) Inline fork checkboxes on each optional node
Pick appeal target (no) Inline chip group on appeal root
Pick date Stichtag input (read-only — feeds computed dates)
Toggle Alle Optionen / Gewählt (no) Per-proceeding 2-way toggle
Zoom on anchor (no) [Fokus] chip on anchored node
Akte select Akte picker (read-only — feeds actuals overlay)

Find header = "narrow the set + global context". Timelines = "everything per-event". No drawers, no overlays.


§8 Cold open + empty state

Cold open with no Akte, no URL params (Q4 below): show a curated default of 6 most-common proceedings (upc.inf.cfi, upc.rev.cfi, upc.apl.merits, de.inf.lg, epa.opp.opd, dpma.opp.dpma), each rendered with default Gewählt + no forks selected + no anchor. Hint text above: "Suche oder filtere, um andere Verfahren zu sehen."

Empty filter result (e.g. user types nonsense): zero timelines render, with a helper card: "Keine Treffer. Filter zurücksetzen ▸"


§9 Migration (direct replace per m's Q7)

4 slices + 1 cleanup, all surface, no DB mig, no ?tracker=1 flag. Each slice ships visibly to users at /tools/procedures. T1 must be at least as functional as today's catalog browser — so the find header + multi-proceeding render + inline forks + aux inline all front-load there. T2-T4 layer the remaining behaviour.

All independent of curie's editorial work — compound rules render inline via parent_id like any other rule; if curie ships a compound_predecessors uuid[] column later, those rules can render at multiple positions (one inline per predecessor) without tracker code changes beyond the join.

Slice What ships Notes
T1 — Tracker shell replaces the catalog page /tools/procedures now renders: sticky find header (search + Forum/Verfahren/Partei pills + Akte picker + global Stichtag), N-proceeding render (one card per matched proceeding), inline forks (scenario flags + optionals visible as checkboxes on the gating node), aux proceedings inline-expandable at spawn points, cold-open with 6 curated defaults (Q4), default = Gewählt. The 4 entry-mode tabs are deleted in the same PR; URL params ?mode=proceeding|search|wizard|akte 301-redirect or drop. URL anchor ?event=<rule_id> scroll-highlights the matching node (no zoom yet). Replaces catalog UI; users see the new tracker immediately.
T2 — Anchor pin + zoom + multi-proceeding scope Anchor pin (lime band + DU BIST HIER divider), [Fokus] chip on anchored node toggles zoom (§6.2), URL state ?event=…&zoom=1. Multi-proceeding auto-collapse rule (§6.5) kicks in when an anchor is set. Click-to-pin on any node. Layered on T1's existing render.
T3 — Akte landing + actuals overlay ?project=<uuid> derives anchor from latest status='done' deadline (Q5), backward walk overlays paliad.deadlines actuals as status badges (§6.4), scenario_flags load from project, fork write-back via existing PATCH /api/projects/{id}/scenario-flags + POST /api/projects/{id}/deadlines/bulk. The first slice that exercises the project hookup end-to-end.
T4 — Appeal-target + court-set choices + polish Wire applies_to_target array forks on appeal proceedings, choices_offered shapes (appellant, include_ccr, skip), court-set date override from appointments table, cross-party muted treatment per §3.6. Per-proceeding "Alle Optionen" toggle (§3.4). Polish + the edge-case fork shapes.
T5 — Cleanup Dead-code removal: legacy procedures.ts tab toggling, fristenrechner-mode-a.ts / fristenrechner-wizard.ts / fristenrechner-result.ts / verfahrensablauf.ts if no longer referenced (verify with grep before deletion). Sidebar/cmd-K unchanged (URL same). No user-visible change.

§9.1 Constraint: T1 is the new floor

Because there's no flag, T1 must not regress from today's catalog UI in any non-trivial way. The catalog today serves four user workflows:

  1. Pick a proceeding, see its full Verfahrensablauf → T1 covers via "Verfahren" pill click → that proceeding renders alone.
  2. Search for an event → T1 covers via search input + auto-pin.
  3. Wizard from R1-R5 → T1 covers via Forum/Verfahren/Partei pills + search (the wizard's narrowing is just a sequence of filter applications).
  4. Enter via Akte → T1 covers via the Akte picker; full actuals overlay arrives in T3 (open/done badges may render partial in T1, but the Akte's scenario_flags + proceeding pre-load works).

If T1 reviewing exposes a regression, T1 holds (the issue blocks merge) — m's PR review gates the slice landing.

§9.2 What stays unchanged

  • URL: /tools/procedures keeps it.
  • Sidebar entry "Verfahren & Fristen" keeps it.
  • cmd-K palette keeps it.
  • All other tools, calendar, projects, deadlines surfaces — untouched.
  • Calculator (pkg/litigationplanner.CalculateRule) — untouched.

§9.3 Out-of-band dependencies

  • The compound-predecessors editorial column is owned by curie's t-paliad-333. Tracker reads whatever lands. If it slips past T4, compound rules render via their primary parent_id only (today's shape) — degraded but still correct on that path. No tracker re-render needed when curie ships.
  • The Akte actuals overlay (T3) reads paliad.deadlines.sequencing_rule_id — column exists, nothing new.

§9.4 Test surface per slice

  • T1: cold-open 6 curated defaults render; search narrows to single proceeding; pill toggles change render; ?project= loads Akte filters (no actuals yet); URL deep-link ?event= highlights matching node; legacy ?mode= redirects.
  • T2: click-to-pin sets anchor with lime band; [Fokus] zoom collapses siblings; un-zoom restores; multi-proceeding auto-collapse when anchor active; URL state survives reload.
  • T3: Akte landing auto-pins latest done deadline; status badges render on each node from paliad.deadlines; fork tick writes to scenario_flags; "In Akte speichern" persists.
  • T4: appeal-target chips switch the rule set rendered on appeal proceedings; choices_offered per-node chip groups visible + functional; "Alle Optionen" reveals hidden conditional rules with greyed state.
  • T5: production deploy unchanged surface; no live regression; deleted files don't break build.

§10 Open questions for m

Seven questions in 2 batches (4 + 3) for AskUserQuestion. Tier 1 = how the per-node fork UI feels + how zoom interacts with multi-proceeding pages. Tier 2 = cold-open content + Akte default + Stichtag scope + migration cadence.

m's picks fold back into §11 below before the "TRACKER DESIGN READY FOR REVIEW" signal.

Batch 1 — fork UI + zoom + cross-party

  • Q1 (Fork-cluster shape on a node) — when a node has 2-4 forks (e.g. Klageerwiderung: with_ccr + with_amend + Vorl. Einwend.) — (a) inline checkbox list below the node header (current sketch), (b) collapsed "Optionen (3) ▾" affordance that expands on hover/click, (c) chip strip on the same line as the node header.
  • Q2 (Zoom interaction)[Fokus] chip on the anchored node — (a) collapses siblings to one-line summaries (current sketch), (b) outright hides siblings, breadcrumb-only, (c) split-view (zoomed pane below original full tree).
  • Q3 (Anchor scope on a multi-proceeding page) — when 3 timelines are visible and the user pins an anchor in one — (a) the other 2 timelines stay expanded normally (no zoom effect on them), (b) the other 2 timelines auto-collapse to header-only ("upc.rev.cfi ▸ ausblenden — [zeigen]"), (c) the other 2 timelines reorder to bottom of page (anchored proceeding floats to top).
  • Q4 (Cold-open default content) — opening /tools/procedures with no URL params and no Akte — (a) the 6-curated-default-proceedings sketch (Verletzung UPC + DE LG, Nichtigkeit UPC, Berufung UPC, EPA-Einspruch, DPMA-Einspruch), (b) all ~46 proceedings rendered with all forks off (lots of scrolling), (c) empty state with a "Filter wählen, um Verfahren einzublenden" prompt.

Batch 2 — Akte semantics + Stichtag + migration

  • Q5 (Akte landing — default anchor)?project=<uuid> — (a) auto-pin to latest status='done' deadline (current sketch), (b) auto-pin to next-open deadline (forward-looking), (c) no auto-pin, just pre-fill filters + actuals overlay, user picks anchor.
  • Q6 (Stichtag scope) — date input in the find header — (a) global, feeds all visible proceedings' computed dates (current sketch — useful for browsing "if today were the trigger"), (b) per-proceeding (each timeline carries its own date input), (c) only valid in single-proceeding mode (hidden when the page shows >1 proceeding).
  • Q7 (Migration cadence) — (a) flag-gated dev under ?tracker=1, T1-T4 ship, T5 hard-cut (current sketch, cronus precedent), (b) direct replace at T1 (no flag — every slice ships visibly to users), (c) parallel URL /tools/procedures-v2 until hard-cut.

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

All 7 questions answered via AskUserQuestion in 2 batches (4 + 3) at 21:0?. 5 picks on-recommendation, 2 diverged. Decisions below; the underlying question list lives in §10 above as the historical record.

Tier 1 — fork UI + zoom + cross-party

  • Q1 (Fork cluster on a node): Inline checkbox list below node header. [= REC] Locks §3.2. Every fork on a given node renders as a checkbox in an "Optionen:" cluster line below the node header. Always visible, no hover, no extra click. Vertical real estate per node is acceptable because the default Gewählt mode keeps the tree compact (most events have zero forks).
  • Q2 (Zoom interaction): Collapse siblings to one-line summaries. [= REC] Locks §6.2. [Fokus] chip on the anchored node folds sibling branches at each ancestor depth to a … 4 weitere Schritte verborgen — [zeigen] line. The anchored node's subtree renders full. Breadcrumb at the top of the proceeding card. Toggle off restores everything.
  • Q3 (Multi-proceeding anchor scope): Other timelines auto-collapse to header-only. [≠ REC; m diverged from "stay expanded"] Locks new §6.5. When an anchor is pinned on a multi-proceeding page, the non-anchored proceedings fold to a one-line header card (upc.rev.cfi ▸ ausblenden — [zeigen]). Clicking the header line restores that proceeding's full timeline. Rationale (interpreted): with an anchor pinned, the page is about that anchor — having other proceedings full-render in parallel competes for attention without earning it. The header card preserves the find-header result count and offers a one-click escape if the user wants to compare.
  • Q4 (Cold open content): 6 curated default proceedings. [= REC] Locks §8. No URL params + no Akte → render upc.inf.cfi, upc.rev.cfi, upc.apl.merits, de.inf.lg, epa.opp.opd, dpma.opp.dpma stacked vertically, all forks off, no anchor. Hint: "Suche oder filtere, um andere Verfahren zu sehen."

Tier 2 — Akte + Stichtag + migration

  • Q5 (Akte default anchor): Latest status='done' deadline. [= REC] Locks §6.4 + §9. ?project=<uuid> → derive anchor by SELECT … FROM paliad.deadlines WHERE project_id=$p AND sequencing_rule_id IS NOT NULL ORDER BY completed_at DESC NULLS LAST LIMIT 1. Fallback: next open deadline → proceeding root. The backward chain reads as Akte history; the anchor itself is the most recently completed work; forward is upcoming.
  • Q6 (Stichtag scope): Global, feeds all visible proceedings. [= REC] Locks §2.1 + §7. One date input in the find header. All visible proceedings compute dates against it. When the user has an Akte loaded, the Stichtag pre-fills from the project's latest trigger date but is overrideable. When the anchor is pinned to a status='done' deadline, the date input shows that deadline's completed_at but can still be overridden for "what-if" exploration.
  • Q7 (Migration cadence): Direct replace at T1 — no flag. [≠ REC; m diverged from flag-gated dev] Rewrites §9. Every slice ships visibly to users at /tools/procedures. T1 must be at minimum equivalent to today's catalog browser (so the slicing has to front-load find header + multi-proceeding render + forks inline + aux inline). The flag-gated dev plan is dropped. cronus's Q11 hard-cut precedent extends here: m would rather ship per-slice visibly than carry a parallel surface during dev. Rationale (interpreted): partial-tracker > no-tracker, and ~50 internal lawyers absorb the per-slice deltas through release comms.

§11.1 Changes triggered by m's divergences

Q3 divergence — multi-proceeding anchor scope. New §6.5 added below. The header-card-only render for non-anchored proceedings preserves filter compose (you can still see "upc.rev.cfi matched the filter") while clearing the page's vertical real estate for the anchor's full context.

Q7 divergence — direct replace. §9 rewritten end-to-end. T1 now ships the minimum-viable tracker (find header + multi-proceeding render + forks inline + aux subtrees inline + URL-anchor highlight), replacing the catalog UI at /tools/procedures from the moment it merges. T2-T4 layer zoom, Akte semantics, polish. T5 ("cleanup only") is now just dead-code removal.

§11.2 What stays unchanged

The other 5 picks (Q1, Q2, Q4, Q5, Q6) ratified the inventor proposal. Inline checkbox forks per node, breadcrumb-collapse zoom, 6-curated cold open, latest-done-deadline Akte anchor, global Stichtag — all locked as drafted in §1-§8.


§12 Out of scope

  • Calculator changes.
  • Editorial backfill (curie's t-paliad-333). Compound rules render inline as parent_id-chained rules with curie's annotation; no special tracker treatment.
  • /admin/procedural-events, /projects/{id} Verlauf / SmartTimeline.
  • youpc.org / Outlook / PDF export.
  • Multi-project anchor comparison.
  • Free-text scenario flag i18n.

  • mBrian (after m's ratification): file as [synthesis] linked triggered_by t-paliad-337; related_to cronus's unified-procedural-events-tool design + atlas's deadline-system-revision + cronus's earlier Fristenrechner overhaul.
  • Cross-refs in this repo: docs/design-unified-procedural-events-tool-2026-05-27.md (cronus, U0-U4 shipped today), docs/design-deadline-system-revision-2026-05-27.md (atlas Phase 2), docs/design-fristenrechner-overhaul-2026-05-26.md (cronus 2026-05-26).
  • Gitea: m/paliad#152 (this design), m/paliad#151 (cronus U0-U4), m/paliad#149 (atlas Phase 2).
  • Coder phase (deferred per inventor SKILL): runs after m ratifies §10 + §11. Slice ordering per §9. NOT atlas (parked at "TRACKER DESIGN READY FOR REVIEW"). Pattern-fluent Sonnet coder picks up T1 first.