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

+3 -3
View File
@@ -32,7 +32,7 @@ describe('Application Settings', () => {
localStorage.clear();
localStorage.setItem('app.language', JSON.stringify('en'));
localStorage.setItem('leaveBalances', savedBalances);
localStorage.setItem('vacationRules', '[]');
localStorage.setItem('vacationRules', '{"version":1,"rules":[]}');
localStorage.setItem('unrelated.entry', 'keep this value');
mediaQuery = Object.assign(new EventTarget(), {
matches: true,
@@ -461,7 +461,7 @@ describe('Application Settings', () => {
await (await dialog.getHarness(MatSlideToggleHarness)).check();
expect(localStorage.getItem('calendarSettings.showWeekNumbers')).toBe('true');
expect(localStorage.getItem('leaveBalances')).toBe(savedBalances);
expect(localStorage.getItem('vacationRules')).toBe('[]');
expect(localStorage.getItem('vacationRules')).toBe('{"version":1,"rules":[]}');
expect(localStorage.getItem('unrelated.entry')).toBe('keep this value');
expect(fixture.nativeElement.querySelectorAll('.week-number').length).toBeGreaterThan(
0,
@@ -490,7 +490,7 @@ describe('Application Settings', () => {
TestBed.resetTestingModule();
await createApp();
expect(localStorage.getItem('leaveBalances')).toBe(savedBalances);
expect(localStorage.getItem('vacationRules')).toBe('[]');
expect(localStorage.getItem('vacationRules')).toBe('{"version":1,"rules":[]}');
expect(localStorage.getItem('unrelated.entry')).toBe('keep this value');
expect(document.body.classList.contains('dark-mode')).toBe(true);
expect(