design(procedures-tracker): fold m's 7 picks — §11 decisions + §6.5 multi-tl anchor + §9 direct-replace migration (t-paliad-337)
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

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.
This commit is contained in:
mAi
2026-05-27 21:13:35 +02:00
parent 7554e86673
commit c8f310c62c

View File

@@ -328,6 +328,27 @@ This is what m means by "zoom into one event from within the timeline" — the *
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.
@@ -374,19 +395,51 @@ Empty filter result (e.g. user types nonsense): zero timelines render, with a he
---
## §9 Migration
## §9 Migration (direct replace per m's Q7)
5 slices, all surface, no DB mig. 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.
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.
| Slice | What ships | Reversible? |
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 page behind `?tracker=1`** | New `procedures-tracker.ts` mounts under a `?tracker=1` URL flag on `/tools/procedures`. Existing 4-tab UI stays default. | Yes — flag-gated |
| **T2 — Find header + multi-proceeding render** | Sticky header (search + pill rows + Akte + Stichtag) + render N matched proceedings as inline-forked trees (no aux expansion yet, no zoom). Forks: scenario flags + optionals. Default = Gewählt. | Yes — code-only |
| **T3 — Aux proceedings inline + appeal-target + court-set choices** | Spawn nodes expand inline (§5), appeal-target chip group on appeal root, `choices_offered` shapes wired. | Yes — code-only |
| **T4 — Anchor pin + zoom + Akte actuals overlay** | URL `?event=` pin, click-to-pin, `[Fokus]` chip per anchor, Akte deadlines join for status badges6.4). | Yes — code-only |
| **T5 — Hard-cut: tracker becomes the page** | `procedures.tsx` rewritten — tracker shell only. Legacy entry-tab logic in `procedures.ts` deleted. `/tools/procedures?mode=…` URL params 301-mapped to the new tracker URLs. Sidebar/cmd-K unchanged. | Reversible only by revert PR |
| **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" toggle3.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. |
The flag-gated dev period (T1-T4) gives m + 2 PAs a chance to sanity-check before T5. m's cronus-Q11 precedent (hard cut, no dual-ship) applies — the audience is ~50 internal lawyers.
### §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.
---
@@ -411,7 +464,30 @@ m's picks fold back into §11 below before the "TRACKER DESIGN READY FOR REVIEW"
## §11 m's decisions (2026-05-27)
To be populated after AskUserQuestion returns. Until then, the inventor picks above govern.
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.
---