Merge: t-paliad-337 — workflow-tracker design for /tools/procedures (m/paliad#152)
atlas shipped the workflow-tracker design after m's 21:01 grilling-round reframe (single timeline-with-forks, find=search+pills+result-timelines, aux inline, zoom from within full tree). 510-line doc, 2 rewrite iterations. 7 Qs answered in 2 batches (4+3). 5 on-recommendation, 2 divergent: - Q3 (divergent): multi-proceeding anchor scope — auto-collapse other proceedings to header-only (new §6.5) - Q7 (divergent): migration strategy — direct replace at T1, no feature flag (§9) 4-slice + cleanup train. T1 ships minimum-viable tracker visibly at /tools/procedures, replacing the catalog UI knuth shipped today. Inventor parks. Head dispatches Sonnet coder (NOT atlas per project memory directive).
This commit is contained in:
510
docs/design-procedures-workflow-tracker-2026-05-27.md
Normal file
510
docs/design-procedures-workflow-tracker-2026-05-27.md
Normal file
@@ -0,0 +1,510 @@
|
||||
# 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 picks** — `applies_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 choices** — `choices_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.
|
||||
|
||||
---
|
||||
|
||||
## §13 Synthesis links
|
||||
|
||||
- **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.
|
||||
Reference in New Issue
Block a user