Files
vac-optimizer/docs/adr/0010-rank-obligation-solutions-before-preferences.md
T
nessarandClaude Opus 5.5 8168137cd5 perf(planning): plan from the best-ranked obligation solution
With several obligation solutions, the planner ran the whole preference
chain on candidate solutions as previews: every solution after a
complete enumeration, or the eight best-ranked after a truncated window
search. It now orders all solutions by the existing pre-preference
ranking (active objectives, then tie-breaks, of each obligation-only
plan; equal ranks keep enumeration order) and runs the preference
stages once, on the first. If that run ends with earned leave available
only after its final merged time-off period, the stages restart on the
next solution, so a request that planned before never becomes a
conflict.

The loaded year drops from 43 to 5.5 seconds and typed obligations from
3.3 to 0.1 seconds, with byte-identical benchmark plans. Over the 5,000
seeded requests, 23 plans become worse (9 on a real objective) and 1
better; over 50 loaded-year-sized requests, 4 become worse on a real
objective. ADR 0010 records the decision; docs/benchmark/issue-302.md
records the comparison and the opt-in runner that reproduces it.

The frozen-engine check fails until the frozen engine is rebuilt from
this commit in the next one.

Part of #302.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:18:06 +02:00

2.3 KiB

Rank Obligation Solutions Before Preferences

Accepted for issue #302, after the analysis in issue #288.

A search change may change planning outcomes when it is deliberate, isolated in one reviewed commit and recorded. The frozen engine of the frozen-engine differential check is rebuilt from that commit, in its own commit, and the benchmark documentation records a reproducible before/after comparison over the check's seeded requests, including every request that became worse on a real objective. Exact optimizations still keep every outcome, stable explanation and final-state snapshot identical to the frozen engine.

When obligation rules can be satisfied jointly in several ways, the planner orders the obligation solutions by its pre-preference ranking: the active objectives, then the tie-breaks, evaluated on the obligation-only plan. Equal ranks keep enumeration order. The planner runs the preference stages once, on the first solution, instead of previewing the preference stages on every candidate solution. This removes a cost that grew with the number of solutions, and trades away the cases where a lower-ranked solution ends better after the preferences: over the 5,000 seeded requests, 23 plans became worse, 9 of them on a real objective, and 1 became better; over 50 loaded-year-sized requests, 4 became worse on a real objective (comparison record). If the run on the chosen solution ends in an earned-entitlement chronology conflict, the planner tries the next solution in that order, and reports a conflict only when every solution fails.

The Bun benchmark targets, measured with the benchmark protocol on the development machine, are 10 seconds for the loaded year, 5 seconds for multi-year horizons and 3 seconds for every other scenario. They are development targets, not reference-phone limits. This revisits the five-second target of ADR 0003; ADR 0006 already removed its automatic cutoff and sets no validated limit for multi-year horizons.