feat(planning): make optimization rules composable

Evaluate explicit, ordered optimization configurations through one shared
planner model. Add six editable presets, durable one-time legacy migration,
and consistent completed and cancelled plan provenance.

Include functional regressions and the agreed trace-removal and benchmark
follow-up specs. Performance acceptance remains in #78 under unchanged gates.

Refs: #70, #71, #72, #73, #74, #75, #76, #77, #78
This commit is contained in:
nessar committed 2026-10-10 16:07:34 +02:00
1 parent 209bf05f36
commit 6811142299
45 files changed
+8795 -3075

No files matched your search

+38 -13
View File
@@ -1,5 +1,30 @@
# Mobile leave-planner benchmark
## Composable optimization rules: current verification status
The #70–#75 implementation uses explicit active optimization configurations in
the benchmark fixtures. The latest full functional coverage run passes 652 tests
across 34 files under the 2 GB Node heap limit, excluding the separate benchmark.
This does not establish a passing performance protocol.
The most recent seven-scenario protocol attempt timed out at its unchanged
300-second limit without an out-of-memory failure. The loaded-year warm-up took
184.36 seconds; its first measured repetition began about 251.78 seconds into
the protocol. These measurements precede the final period-projection cache and
the planned original-decision-trace removal, and are not a result for either.
At the user's request, #75 finishes on saved-rule migration and functional
verification. #78 owns benchmark verification and implementation of further
optimizations when needed, after #76 removes tracing and #77 verifies the retained
behavior. All seven scenarios, one warm-up and two measured repetitions per
scenario, the 2 GB heap limit and the 300-second timeout remain required. No
automatic elapsed-time planning cutoff or weaker CI gate is introduced.
The results below document earlier implementations and protocols. They are
historical measurements rather than the performance result for composable rules.
## Reference-phone protocol
Open the deployed application at `/benchmark` on the reference phone. Tap
**Run benchmark**, wait for the seven scenarios to finish, then tap **Copy
report** and save the tab-separated output with the date and build identifier.
@@ -90,10 +115,10 @@ and each flow sent exactly one planning request. All 1,949 and 3,956 trace
packets respectively were acknowledged, carrying 122,621 and 249,234 candidate
records without truncation. Heartbeats continued during the producing runs.
| Horizon | Calendar usable | Later trace delivery | Placements | Maximum UI timer delay before calendar / during trace | Peak page heap before calendar / during trace | Peak Chrome process-tree RSS before calendar / during trace |
| --- | --- | --- | --- | --- | --- | --- |
| Two years | 5.08 s | 2.55 s | 60 | 1.47 s / 0.70 s | 22.7 / 314.6 MiB | 1,143.2 / 1,606.8 MiB |
| Three years | 10.86 s | 4.14 s | 90 | 2.11 s / 1.48 s | 22.9 / 597.6 MiB | 1,386.8 / 2,217.8 MiB |
| Horizon | Calendar usable | Later trace delivery | Placements | Maximum UI timer delay before calendar / during trace | Peak page heap before calendar / during trace | Peak Chrome process-tree RSS before calendar / during trace |
| ----------- | --------------- | -------------------- | ---------- | ----------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------- |
| Two years | 5.08 s | 2.55 s | 60 | 1.47 s / 0.70 s | 22.7 / 314.6 MiB | 1,143.2 / 1,606.8 MiB |
| Three years | 10.86 s | 4.14 s | 90 | 2.11 s / 1.48 s | 22.9 / 597.6 MiB | 1,386.8 / 2,217.8 MiB |
A 50 ms page timer measured extra event-loop delay and sampled available
main-thread JS heap. RSS was sampled every 500 ms across that isolated Chrome
@@ -111,10 +136,10 @@ completed stage. An editable input accepted focus while the worker remained
active. Both flows kept a 44 px Cancel control, fit the viewport without
horizontal overflow, and delivered the original trace after their outcome.
| Cancellation point | Request to outcome | Request to complete artifacts | Retained placements |
| --- | --- | --- | --- |
| Calendar preparation | 21.9 ms | 874.8 ms | 0 |
| Active holiday-week optimization, keyboard | 21.5 ms | 1,431.7 ms | 90 |
| Cancellation point | Request to outcome | Request to complete artifacts | Retained placements |
| ------------------------------------------ | ------------------ | ----------------------------- | ------------------- |
| Calendar preparation | 21.9 ms | 874.8 ms | 0 |
| Active holiday-week optimization, keyboard | 21.5 ms | 1,431.7 ms | 90 |
No browser errors occurred. Cancellation issued one cancel request and no
additional calculation. Separate tests cover late artifact errors and stale
@@ -151,11 +176,11 @@ at the worker's terminal artifact delivery. The application's own calibration
uses its request timestamp and `afterNextRender` endpoint as described in
[planning-duration.md](../planning-duration.md).
| Horizon | Range before Calculate (with one local sample) | Observed calendar wait | Additional trace delivery | Range after completion | Placements |
| --- | --- | --- | --- | --- | --- |
| One year | 1–4 s | 1.74 s | 1.23 s | 1–5 s | 30 |
| Two years | 2–16 s | 5.08 s | 2.88 s | 2–16 s | 60 |
| Three years | 7–44 s | 11.03 s | 5.60 s | 6–39 s | 90 |
| Horizon | Range before Calculate (with one local sample) | Observed calendar wait | Additional trace delivery | Range after completion | Placements |
| ----------- | ---------------------------------------------- | ---------------------- | ------------------------- | ---------------------- | ---------- |
| One year | 1–4 s | 1.74 s | 1.23 s | 1–5 s | 30 |
| Two years | 2–16 s | 5.08 s | 2.88 s | 2–16 s | 60 |
| Three years | 7–44 s | 11.03 s | 5.60 s | 6–39 s | 90 |
All three outcomes completed through `dates`, with no intermediate placements,
implicit deadline, extra request or date movement. The three-year result