This commit is contained in:
nessar committed 2026-10-07 00:28:29 +02:00
1 parent 03841c6e3d
commit 036a8c0e1e
32 files changed
+1805 -89

No files matched your search

@@ -0,0 +1,22 @@
# 01 — Open plan statistics for calculated leave usage
**What to build:** The user opens a statistics popup from the calendar and sees how many new leave days the displayed valid plan uses, including a valid plan retained after cancellation. This establishes a usable first slice that later tickets extend with the other statistics.
**Blocked by:** None — can start immediately.
**Status:** ready-for-agent
**GitLab:** [#65](https://gitlab.nessar.fr/nessar/vac-optimizer/-/work_items/65)
Source: the agreed Plan Statistics Popup spec for [#3](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/3) and [#29](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/29), in milestone %3: V1 stats. Follow the domain glossary and ADRs 0002, 0004, 0006, and 0007.
- [ ] A labelled calendar control opens one statistics popup for the latest calculated valid plan. Opening it runs no optimization and changes no planning data.
- [ ] The popup shows the number of leave placement dates with an explicit leave-day label. Declared non-working days consume no balance and are excluded from this count. A valid plan with no placements displays 0 and still permits opening the popup.
- [ ] A retained valid plan from an incomplete calculation exposes the same popup with a prominent "Partial plan" label. Invalid input, a planning conflict, or an incomplete calculation without a retained valid plan exposes no statistics.
- [ ] Statistics refer to the producing calculation and its submitted inputs. Editing balances, rules, declarations, or the horizon, inspecting historical trace steps, and exploring hypothetical dates do not change the displayed count.
- [ ] A new valid outcome replaces the statistics. A new outcome without a valid plan clears them, including any already open popup. Late replies from an older calculation cannot restore or overwrite them.
- [ ] Popup access is available with the valid outcome while trace delivery is pending or has failed. Reuse the existing result lifecycle and dialog patterns without introducing another calculation or trace-dependent summary.
- [ ] The control and popup work with the existing language settings, keyboard opening and dismissal, visible focus, focus containment and restoration, meaningful accessible labels, and a readable mobile layout.
- [ ] Existing behavior tests verify complete and retained partial plans, zero placements, declared-day exclusion, pending input edits, delayed or failed trace delivery, stale replies, and replacement by an outcome without a valid plan. Verify keyboard behavior and run the repository's existing tests, lint, formatting, type checks, and production build.
This ticket is independently demonstrable by calculating a plan and opening its leave-usage summary. It does not depend on declared-day period aggregation or earned-leave acquisition changes.
@@ -0,0 +1,28 @@
# 02 — Show work-sequence and time-off-period lengths
**What to build:** The statistics popup shows average and longest working stretches, average and longest complete breaks, and non-working-day gain, using the calculated plan's shared calendar semantics.
**Blocked by:**
- 01 — Open plan statistics for calculated leave usage.
- [#62 — Optimiser les périodes de repos autour des jours déclarés](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/62), which establishes time-off periods and work sequences that include declared non-working days.
**Status:** ready-for-agent
**GitLab:** [#66](https://gitlab.nessar.fr/nessar/vac-optimizer/-/work_items/66)
Source: the agreed Plan Statistics Popup spec for [#3](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/3) and [#29](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/29), including [#7](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/7). The existing longest work-sequence metric from #28 is reused. Follow the domain glossary and ADRs 0004, 0006, and 0007.
- [ ] Add five labelled metrics: non-working-day gain, average work-sequence length, longest work-sequence length, average time-off period length, and longest time-off period length. Work lengths use working days; break lengths use calendar days.
- [ ] The work-sequence average includes every non-empty sequence inside the submitted horizon, including both edges. Weekends and French public holidays neither count nor split a sequence; leave placements and declared non-working days interrupt it. Consecutive days off introduce no zero-length samples.
- [ ] Sequences of 10, 5, and 15 working days produce an average of 10 and a longest length of 15. Fractional averages remain representable and calculations do not prematurely round the underlying values.
- [ ] Break statistics use full canonical time-off periods, including merged declarations and placements and contiguous non-working dates immediately outside the horizon. Friday and Monday off around a holiday-free weekend produce one 4-calendar-day period. A declared Friday with no new placements produces a 3-day Friday–Sunday period.
- [ ] Non-working-day gain counts distinct weekend and public-holiday dates in these periods. A weekend public holiday contributes once; a declared day does not itself become additional weekend or holiday gain.
- [ ] Saved declarations outside the horizon do not inflate in-horizon work counts or create isolated out-of-horizon periods. Adjacent declarations may extend a period anchored inside the horizon under the shared calendar contract.
- [ ] Empty samples remain distinguishable from measured zero. A valid plan without work sequences retains a longest work-sequence length of 0; missing average samples and a missing longest time-off period retain an explicit empty data state.
- [ ] All five figures inherit the popup's snapshot, trace independence, and partial-plan behavior. Any new outcome facts survive direct planning, worker transport, and retained-plan checkpoints and describe the actual displayed plan.
- [ ] Behavior tests cover fractional means, both horizon edges, contiguous days off, intervening weekends and holidays, declarations without new placements, merged periods, adjacent context dates, and empty samples. Check rendered units and values, complete and retained partial outcomes, and the repository's existing tests, lint, formatting, type checks, and production build.
Reuse #62's calendar and period definitions rather than adding a conflicting calendar model. These descriptive metrics do not change the planning objective order.
Proposed presentation default, not explicitly confirmed: show "—" for an average without samples and for the longest time-off period when none exists. Decimal precision follows existing presentation conventions; it does not change the underlying metric.
@@ -0,0 +1,26 @@
# 03 — Show gross earned leave by generating rule
**What to build:** The statistics popup shows all leave earned by the calculated plan before consumption, with a breakdown by the rules that generated it, including entitlements that were fully used.
**Blocked by:**
- 01 — Open plan statistics for calculated leave usage.
- [#64 — Appliquer les motifs IF_THEN et les droits acquis aux jours déclarés](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/64), which establishes finalized earned entitlements and the fixed Europe/Paris calculation-date cutoff.
**Status:** ready-for-agent
**GitLab:** [#67](https://gitlab.nessar.fr/nessar/vac-optimizer/-/work_items/67)
Source: the agreed Plan Statistics Popup spec for [#3](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/3) and [#29](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/29), including [#8](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/8). Follow the domain glossary and ADRs 0004, 0006, and 0007.
- [ ] Display gross earned leave from every applicable generating rule, including Samedi Malin, with a per-rule breakdown whose quantities sum to the total.
- [ ] A plan earning 3 days and consuming 2 reports 3 earned days. Fully consumed earned entitlements remain included even when absent from remaining balances; generating a future entitlement does not require consuming it inside the horizon.
- [ ] Repeated satisfied occurrences contribute their generated quantities once per generating rule and occurrence. Distinct rules retain separate attribution even when their names match or they share contributing dates. Occurrences satisfied by declarations, placements, or both use the finalized entitlement semantics from #64.
- [ ] Include only entitlements becoming available strictly after the producing calculation's captured Europe/Paris calendar date. Availability before or on that date is excluded; availability after the planning horizon is included. Use the finalized availability after the complete generating time-off period, including later period extensions.
- [ ] Only entitlements generated by the final or retained valid plan contribute. Rejected candidates, abandoned branches, provisional earnings, and hypothetical alternatives cannot inflate the total.
- [ ] Rule labels come from the producing calculation's immutable rule names and attribution. Renaming or deleting pending rules, changing balances, or crossing a calendar-date boundary after calculation does not change this result.
- [ ] Carry reliable gross quantities and generating-rule attribution with complete outcomes and retained partial plans through direct planning, worker delivery, and cancellation checkpoints. Reuse #64's captured calculation date; do not recapture it on opening the popup, reconstruct earnings from remaining balances or trace history, or infer attribution by parsing balance identifiers.
- [ ] A valid plan with no qualifying earnings shows a total of 0. Trace readiness and failure do not gate the total or breakdown, and partial plans retain their prominent label.
- [ ] Fixed-clock behavior tests verify partial and full consumption, multiple rules and repeated occurrences, shared contributing dates, availability before/on/after the reference date and beyond the horizon, period extensions, original rule names, and cancellation retaining a different state from the latest candidate. Assert the rendered total and breakdown through the direct and worker paths and run the repository's existing tests, lint, formatting, type checks, and production build.
Presentation proposal, not an agreed requirement: show contributing rules only, omitting zero-earning rows. The total and all positive contributions are required regardless of that display choice.
@@ -0,0 +1,24 @@
# 04 — Count public holidays connected to a weekend
**What to build:** The statistics popup counts weekday public holidays joined to a weekend by the calculated plan's time-off periods, including connections through leave and adjacent holidays beyond the horizon.
**Blocked by:**
- 01 — Open plan statistics for calculated leave usage.
- [#62 — Optimiser les périodes de repos autour des jours déclarés](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/62), which provides shared time-off periods including declared non-working days and adjacent context dates.
**Status:** ready-for-agent
**GitLab:** [#68](https://gitlab.nessar.fr/nessar/vac-optimizer/-/work_items/68)
Source: the agreed Plan Statistics Popup spec for [#3](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/3) and [#29](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/29), including [#9](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/9). Follow the domain glossary and ADRs 0004, 0006, and 0007.
- [ ] Show the number of distinct Monday-to-Friday French public-holiday dates in planned time-off periods containing at least one Saturday or Sunday. Each qualifying period contains at least one leave placement or declared non-working day.
- [ ] Count direct Monday/Friday connections and connections through leave, such as a Tuesday holiday joined to a weekend by Monday off. Declared non-working days can provide the same connection without consuming a balance.
- [ ] Exclude Saturday and Sunday public holidays, naturally long weekends without placed or declared leave, and weekday-only time-off periods that do not reach a weekend. A declaration never becomes a public holiday.
- [ ] Include a qualifying holiday immediately outside the submitted horizon when it belongs to the period's full contiguous span. Friday leave followed by a weekend and a Monday holiday outside the horizon includes that Monday holiday.
- [ ] Each holiday date contributes once. This is a date count, independent of the weighted public-holiday week value used in optimization; a qualifying Wednesday holiday contributes 1, not 3.
- [ ] A valid plan with no qualifying dates displays 0. Complete and retained partial plans use their own producing outcomes and calendar facts, independently of trace delivery or pending input edits.
- [ ] Behavior tests verify direct and bridged connections, declaration-only connections, weekend-holiday exclusion, natural long weekends, breaks reaching no weekend, adjacent out-of-horizon holidays, and duplicate dates. Assert the visible count, direct/worker consistency, and retained-plan behavior; run the repository's existing tests, lint, formatting, type checks, and production build.
This slice uses the canonical periods supplied by #62 and can proceed independently of ticket 02's descriptive length statistics. It does not change optimization weights or placement decisions.
@@ -0,0 +1,26 @@
# 05 — Warn about weeks with one workday
**What to build:** The statistics popup identifies undesirable full weeks with exactly one day remaining to work, showing both how many such weeks exist and the exact date of each lone workday.
**Blocked by:**
- 01 — Open plan statistics for calculated leave usage.
- [#61 — Saisir, sauvegarder et figer les jours déjà posés](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/61), which carries fixed declared non-working days with the producing calculation and its outcomes.
**Status:** ready-for-agent
**GitLab:** [#69](https://gitlab.nessar.fr/nessar/vac-optimizer/-/work_items/69)
Source: the agreed Plan Statistics Popup spec for [#3](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/3) and [#29](https://gitlab.nessar.fr/nessar/vac-optimizer/-/issues/29), including the clarification that working only one day in a full week is undesirable. Follow the domain glossary and ADRs 0004, 0006, and 0007.
- [ ] Count Monday-to-Sunday calendar weeks whose five Monday-to-Friday dates all lie inside the submitted half-open horizon and that contain exactly one remaining working day after excluding French public holidays, leave placements, and declared non-working days.
- [ ] Four weekdays off and one remaining workday qualify. Weeks with zero or two remaining workdays do not qualify, including two-workday weeks containing separate one-day work sequences.
- [ ] Exclude clipped workweeks at both horizon edges, even if only one workday happens to be visible. A week whose five weekdays are all inside the horizon still qualifies when its Saturday or Sunday lies outside it.
- [ ] When the count is positive, show a clear warning and one chronological entry per affected week, identifying its Monday-to-Sunday date range and the exact date of its lone workday. Localized dates include enough year context to disambiguate multi-year horizons and weeks spanning year boundaries.
- [ ] A valid plan with no matching weeks displays a count of 0 and no matching-week warning entries. The warning remains understandable without relying solely on color and is readable with keyboard, assistive technology, and mobile layout.
- [ ] Declarations alone can create a qualifying week without new placements. Saved declarations outside the horizon do not create extra warnings. Use the shared working-day calendar and the producing plan's fixed declarations rather than its count of short work sequences.
- [ ] The count and dated entries inherit snapshot stability, replacement and clearing behavior, trace independence, and the partial-plan label. They describe the actual retained plan on cancellation, not a later candidate or a historical or hypothetical view.
- [ ] The feature only reports the pattern; it does not move leave, change planning objectives, trigger recalculation, or present a valid plan as a planning conflict.
- [ ] Behavior tests cover one/zero/two workdays, separated one-day sequences, declaration-only weeks, holiday exclusions, clipped horizon edges, all weekdays inside with the weekend outside, month/year boundaries, and complete versus retained partial outcomes. Assert both counts and displayed week/workday dates through existing planning and calendar tests, including worker/cancellation behavior; run the repository's existing tests, lint, formatting, type checks, and production build.
This diagnostic depends on fixed declarations from #61, but does not require time-off-period aggregation from #62 or the other statistics tickets.