66 lines
3.4 KiB
Markdown
66 lines
3.4 KiB
Markdown
# PR #278: reject impossible mandatory moves before copying
|
|
|
|
Measured on 2026-10-16 against `433a8b0`, which includes the
|
|
[immutable date-count optimization](pr-278-immutable-date-counts.md).
|
|
|
|
A loaded-year CPU profile attributed 5.09 seconds to candidate assignment and
|
|
6.53 seconds to final validation out of 58.24 seconds. Generic moves and swaps
|
|
copied the candidate state before discovering that a mandatory placement's new
|
|
date or leave type could never satisfy its rule.
|
|
|
|
The shared assignment function now calls the existing `mandatoryRelocationDate`
|
|
check before copying. It checks only necessary date and type conditions. Complete
|
|
multi-day patterns and earned-entitlement chronology are still validated after
|
|
the candidate is assembled. Preferences remain movable, and valid alternatives,
|
|
objective order and deterministic tie breaks remain unchanged.
|
|
|
|
## Before and after
|
|
|
|
Both protocol runs use Node 24.18.0, Bun 1.3.14 and Vitest 5.0.3 on the same local
|
|
machine. This comparison uses a fresh baseline from this session. No other test,
|
|
build or profiling workload runs alongside either protocol measurement.
|
|
|
|
```sh
|
|
NODE_OPTIONS=--max-old-space-size=2048 timeout 300s bunx vitest run src/app/benchmark/leave-planner-benchmark.spec.ts --maxWorkers=1
|
|
```
|
|
|
|
All seven warm-ups, fourteen measured calculations, the typed-obligation precheck,
|
|
fixtures, assertions and resource limits remain unchanged.
|
|
|
|
| Measurement | Before | After |
|
|
| ---------------------------------------------------- | --------: | --------: |
|
|
| Vitest duration | 232.630 s | 228.130 s |
|
|
| Benchmark test | 231.483 s | 227.011 s |
|
|
| Loaded year, mean of two measured calculations | 59.255 s | 57.850 s |
|
|
| Typed obligations, mean of two measured calculations | 4.552 s | 4.368 s |
|
|
| Headroom before timeout (Vitest duration) | 67.370 s | 71.870 s |
|
|
|
|
The Vitest duration was 1.9% shorter in this pair. External wall time was not
|
|
recorded for these runs. Both runs completed successfully, and every repeated
|
|
scenario remained deterministic. The baseline is faster than the one recorded
|
|
for the preceding optimization, so only same-session pairs are comparable.
|
|
Live CI performance still needs confirmation.
|
|
|
|
## Correctness checks
|
|
|
|
Complete outcomes, stable explanations and final-state snapshots match the
|
|
baseline for all seven scenarios. Baseline snapshots come from the preceding
|
|
optimization's saved run, whose bundle matches a fresh build of `433a8b0` byte for
|
|
byte; the loaded-year snapshot was also regenerated in this session. Diagnostic
|
|
comparisons ran alongside functional checks, so their timings are not used for
|
|
the protocol comparison.
|
|
|
|
The functional coverage suite passes all 640 tests across 33 files. Two additional
|
|
regression cases cover obligations and lower-priority preferences when a calendar
|
|
objective competes for the same leave balance. Both cases pass before and after
|
|
the optimization. Existing tests also exercise typed reassignments, complete
|
|
multi-day patterns, earned entitlements and counterfactual explanations.
|
|
Application and spec type checks, lint, source formatting and `git diff --check`
|
|
pass.
|
|
|
|
No browser timing run or live CI rerun was performed for this change.
|
|
|
|
Diagnostic sources, profiles, bundles and full logs are retained in
|
|
`/tmp/vac-opt278-step3`. The original core diagnostic runner is documented in
|
|
[issue-78.md](issue-78.md#reproduction).
|