refactor(planning): remove the original decision trace
CI / policy (push) Successful in 7s
CI / validate (push) Successful in 1m15s
CI / test (push) Successful in 3m18s
CI / benchmark (push) Failing after 5m53s
CI / build (push) Successful in 1m23s
CI / security (push) Successful in 7m6s
CI / policy (pull_request) Successful in 7s
CI / validate (pull_request) Successful in 1m9s
CI / build (pull_request) Successful in 43s
CI / test (pull_request) Successful in 3m19s
CI / images (push) Successful in 3m7s
CI / required (push) Successful in 2s
CI / benchmark (pull_request) Failing after 5m28s
CI / security (pull_request) Successful in 6m37s
CI / images (pull_request) Successful in 3m18s
CI / required (pull_request) Successful in 1s

This commit is contained in:
nessar committed 2026-10-15 20:42:33 +02:00
1 parent ea4256107f
commit d9d9befa12
43 files changed
+729 -8880

No files matched your search

@@ -6,10 +6,9 @@ import {
type PlanOutcome,
type PlanningArtifacts,
type PlanningRequest,
type PlanningTraceUpdate,
} from './leave-planner.core';
import { OPTIMIZATION_PRESETS } from './planning-objectives';
import { applyReplayDeltas, createPlanningCalculation } from './leave-planner.service';
import { createPlanningCalculation } from './leave-planner.service';
const economy: OptimizationPlanningRule = {
id: 'economy',
@@ -415,25 +414,20 @@ describe('supporting placement economy and provenance', () => {
});
it('reclassifies a deferred support addition when an eligible earlier-expiring balance replaces it', () => {
let artifacts: PlanningArtifacts | undefined;
const outcome = calculatePlanningInternal(
{
horizon: { start: '2024-05-06', end: '2024-05-11' },
balances: [
{ id: 'deferred', type: 'cp', quantity: 3, expiryDate: '2025-01-01' },
{
id: 'at-risk',
type: 'rtt',
quantity: 1,
availableFrom: '2024-05-07',
expiryDate: '2024-05-07',
},
],
rules: [bundles[0].rule, economy],
},
undefined,
(value) => (artifacts = value),
);
const outcome = calculatePlanningInternal({
horizon: { start: '2024-05-06', end: '2024-05-11' },
balances: [
{ id: 'deferred', type: 'cp', quantity: 3, expiryDate: '2025-01-01' },
{
id: 'at-risk',
type: 'rtt',
quantity: 1,
availableFrom: '2024-05-07',
expiryDate: '2024-05-07',
},
],
rules: [bundles[0].rule, economy],
});
if (outcome.kind !== 'Plan') throw new Error('Expected a plan');
expect(
outcome.placements.map(({ date, balanceId, supporting }) => ({
@@ -448,20 +442,6 @@ describe('supporting placement economy and provenance', () => {
]);
expect(outcome.metrics.supportingPlacements).toBe(2);
expect(outcome.remainingBalances[0]).toMatchObject({ id: 'deferred', quantity: 1 });
expect(
artifacts?.trace?.phases.flatMap(({ decisions }) =>
decisions.flatMap(({ deltas }) => deltas),
),
).toContainEqual(
expect.objectContaining({
kind: 'placement-updated',
previousPlacement: expect.objectContaining({
balanceId: 'deferred',
supporting: true,
}),
placement: expect.objectContaining({ balanceId: 'at-risk', supporting: false }),
}),
);
});
it('compares new deferred support when at-risk holiday placements relocate into an explicit window', async () => {
@@ -491,13 +471,10 @@ describe('supporting placement economy and provenance', () => {
};
const economyFirst = plan({ ...request, rules: [holiday, economy, early] });
let artifacts: PlanningArtifacts | undefined;
const updates: { update: PlanningTraceUpdate; snapshot: string }[] = [];
const windowFirst = calculatePlanningInternal(
{
...request,
rules: [holiday, early, economy],
traceProgress: (_time: number, update: PlanningTraceUpdate) =>
updates.push({ update, snapshot: JSON.stringify(update) }),
},
(checkpoint, state) => expect(state?.placements).toEqual(checkpoint.placements),
(value) => (artifacts = value),
@@ -547,12 +524,8 @@ describe('supporting placement economy and provenance', () => {
expect(windowFirst.metrics.supportingPlacements).toBe(2);
expect(windowFirst.preferences[0].satisfied).toBe(2);
expect(windowFirst.metrics.holidayWeekValue).toBe(3);
if (
artifacts?.explanation?.kind !== 'PlanExplanation' ||
!artifacts.finalState ||
!artifacts.trace
)
throw new Error('Expected matching explanation and trace artifacts');
if (artifacts?.explanation?.kind !== 'PlanExplanation' || !artifacts.finalState)
throw new Error('Expected matching explanation and state snapshots');
expect(artifacts.finalState.placements).toEqual(windowFirst.placements);
expect(artifacts.explanation.placements.map(({ placement }) => placement)).toEqual(
windowFirst.placements,
@@ -568,33 +541,6 @@ describe('supporting placement economy and provenance', () => {
expect(placement.contributions).not.toContainEqual(contribution);
}
}
const replay = {
balances: artifacts.trace.initialState.balances.map((balance) => ({ ...balance })),
placements: new Map(
artifacts.trace.initialState.placements.map((placement) => [
placement.date,
placement,
]),
),
earnedActivations: [...artifacts.trace.initialState.earnedActivations],
};
for (const decision of artifacts.trace.phases.flatMap(({ decisions }) => decisions))
applyReplayDeltas(replay, decision.deltas, artifacts.finalState);
expect(
[...replay.placements.values()].sort((a, b) => a.date.localeCompare(b.date)),
).toEqual(windowFirst.placements);
expect(
artifacts.trace.phases
.filter(({ name }) => name === 'preference:early')
.flatMap(({ decisions }) => decisions.flatMap(({ candidates }) => candidates)),
).toContainEqual(
expect.objectContaining({
status: 'chosen',
placement: expect.objectContaining({ date: '2026-11-03', ruleIds: ['early'] }),
}),
);
expect(updates.length).toBeGreaterThan(0);
for (const { update, snapshot } of updates) expect(JSON.stringify(update)).toBe(snapshot);
let cancelled = false;
let cancelledArtifacts: PlanningArtifacts | undefined;
let published: PlanOutcome | undefined;
@@ -605,8 +551,6 @@ describe('supporting placement economy and provenance', () => {
progress: (stage: string) => {
if (stage === 'optimization:economy') cancelled = true;
},
traceProgress: (_time: number, update: PlanningTraceUpdate) =>
updates.push({ update, snapshot: JSON.stringify(update) }),
},
(checkpoint, state) => {
expect(state?.placements).toEqual(checkpoint.placements);
@@ -637,7 +581,6 @@ describe('supporting placement economy and provenance', () => {
expect.objectContaining({ kind: 'rule', ruleId: 'early' }),
);
}
for (const { update, snapshot } of updates) expect(JSON.stringify(update)).toBe(snapshot);
});
it('keeps established maximum credit when a later earned period masks its local contribution', () => {
@@ -708,28 +651,6 @@ describe('supporting placement economy and provenance', () => {
});
});
it('records the calendar credit and classification change in the original calendar-rule phase', () => {
let artifacts: PlanningArtifacts | undefined;
calculatePlanningInternal(
{ ...weekend, rules: [gain, economy, requested] },
undefined,
(value) => (artifacts = value),
);
const changes = artifacts?.trace?.phases
.find(({ name }) => name === 'preference:requested')
?.decisions.flatMap(({ deltas }) => deltas);
expect(changes).toContainEqual(
expect.objectContaining({
kind: 'placement-updated',
previousPlacement: expect.objectContaining({ supporting: true }),
placement: expect.objectContaining({
ruleIds: ['gain', 'requested'],
supporting: false,
}),
}),
);
});
it('keeps earned support chronological and preserves the captured economy rule in explanations and counterfactuals', async () => {
vi.stubGlobal('window', undefined);
try {
@@ -792,15 +713,6 @@ describe('supporting placement economy and provenance', () => {
expect(supporting.contributions).toContainEqual(
expect.objectContaining({ kind: 'supporting' }),
);
const trace = await calculation.trace;
expect(trace?.phases.map(({ name }) => name)).toEqual([
'validation',
'obligations',
'optimization:gain',
'optimization:economy',
'expiry',
'dates',
]);
const analysis = await calculation.analyzeCounterfactual(outcome.placements[1]);
if (analysis.kind !== 'Counterfactual') throw new Error('Expected a counterfactual');
expect(analysis.results.find(({ date }) => date === '2024-05-03')).toMatchObject({