Verfahrensablauf: sort post-trigger optional events by duration ascending (14d → 1mo → 2mo …) #128
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
m's report (2026-05-26 11:11)
In the post-decision optional-events section, the four R.118.4 / R.151 / R.353 / R.220.1 rows render in catalog order, not by duration. m's expectation:
Expected order (post-Entscheidung, ascending duration):
Currently they're interleaved (Folgeentscheidungen first even though 2-month).
What to do
internal/services/projection_service.go(or the rendering path infrontend/src/client/views/verfahrensablauf-core.ts), sort the rules WITHIN the same trigger-event group by:duration_unitweight: days < weeks < monthsduration_valueascending within same unitsubmission_codeASC as a stable secondary sortparent_id/trigger_event_id. Don't reorder across different trigger groups.Files most likely touched
internal/services/fristenrechner.go(orprojection_service.go) — sorting in the projection resultinternal/services/fristenrechner_test.go— regression test with the post-decision groupfrontend/src/client/views/verfahrensablauf-core.tsif sorting happens client-sideHard rules
go build ./... && go test ./internal/... && cd frontend && bun run buildclean.mai/<worker>/sort-rules-by-duration.Out of scope
Reporting
mai report completedwith branch + SHAs + UX path: open the example UPC inf project with a decision date → confirm the post-decision optional events render 1-month rules (R.151, R.353) before 2-month rules (R.118.4, R.220.1).ritchie shift-1 progress (2026-05-26)
Branch:
mai/ritchie/coder-sort-post-triggerCommit:
49ddaa4What landed
internal/services/fristenrechner.go— newsortDeadlinesByDurationWithinTriggerGroupstep inCalculate()right after the rule-evaluation loop. Walks consecutive runs of deadlines whose underlying rule shares the same(parent_id, trigger_event_id)and reorders each run in place by duration ASC.internal/services/fristenrechner_sort_test.go— 5 pure-function tests:PostDecision— canonical four-rule scenario from m's report: cost_app + rectification (1mo) before appeal_spawn + cons_orders (2mo).UnitWeight— days < weeks < months < years tier ordering.NoCrossGroupReorder— interleaved groups stay interleaved.ConditionalLast—IsConditional/IsCourtSetrows pinned to the bottom of their group.RootsNotMerged— top-level rules never sort against each other.Verification
go build ./...clean.go test ./internal/...all green (180+ tests).bun test181/181 pass.bun run buildproduces dist/ without errors.Note on within-tier tiebreak
The spec called for
submission_codeASC as the secondary sort, which putsappeal_spawnbeforecons_orderswithin the 2-month tier (a < c). m's expected listing in the issue body has them in rule-code order (R.118 before R.220). Tier-level intent (1-month tier before 2-month tier) is met either way; flagged here in case m wants rule_code ordering instead — would be a one-line tiebreak swap.UX path to confirm in browser
Open any UPC inf project with a decision date set, scroll to the post-decision optional-events block, verify 1-month rules (R.151 Antrag auf Kostenentscheidung, R.353 Antrag auf Berichtigung) render before 2-month rules (R.118.4 Folgeentscheidungen, R.220.1 Berufung gegen Endentscheidung).
Commit:
49ddaa4eb8Sweep verdict, corrected (2026-07-29): ALREADY DONE.
An earlier version of my sweep recorded this as STILL TRUE. That was wrong; corrected in
docs/findings-issue-sweep-2026-07-29.md(commitf4fe5bb).pkg/litigationplanner/sort.goimplementssortDeadlinesByDurationWithinTriggerGroupand names this issue in its doc comment (t-paliad-296). The sort key is exactly what m asked for:duration_unitweight ascending — days / working_days < weeks < months < yearsduration_valueascendingDifferent trigger groups keep their proceeding-sequence position; the walk only permutes adjacent same-group rows, and root rules are deliberately excluded so anchors (SoC, oral hearing, decision) are never reordered against each other.
It runs in the production path —
Calculate()calls it atpkg/litigationplanner/engine.go:835, right after the sequence sort — and five tests pin it ininternal/services/fristenrechner_sort_test.go: post-decision order, unit weight, no cross-group reorder, conditional last, roots not merged. All pass.Where my wrong verdict came from, since it is the same trap as #126: I grepped the frontend core for
duration/sort, found onlyverfahrensablauf-core.ts:1058sorting keys lexically, and concluded no duration sort existed anywhere. That line buckets group keys into dated and unscheduled — a different operation. The frontend receives rows the Go engine has already ordered.Not closing — only m closes issues.