The calculation overlay shows a circular percentage indicator, but its fixed stage mapping is out of date. Since rule stages are named after their rules (optimization:<id>, preference:<id>), every preference rule shows 50%. Six mapped stage names are never reported, and preparation stays at 0%. Progress can appear stalled while planning continues, and the overlay does not say what work is underway.
Since #302, the time per stage also varies by configuration in ways the form does not reveal. These figures are shares of each scenario's planning time on the development machine:
in multi-year horizons, loss prevention takes 58–65%;
in typed obligations, public-holiday weeks take 65%;
in the loaded year, non-working-day gain takes 77%;
the obligation stage takes at most 3%.
Since #302, an earned-entitlement retry can also re-run the rule stages after dates, which would move today's mapping backwards.
Solution
Keep the circular indicator, but make the percentage follow the indicative wait rather than the stages completed. Beneath the indicator, add a short line naming the current planning stage and, for preference stages, the rule being applied. Below that, add an approximate remaining time for longer waits. Show 100% only when the planner completes.
User Stories and Acceptance Criteria
As a user waiting for a plan, I can see what the calculation is doing, how far through the expected wait it is, and roughly how long remains.
Percentage
The percentage is the share of the expected wait e. e is the indicative-wait estimate for the submitted configuration, including the device's local refinement, captured once at Calculate. Elapsed time counts from the same Calculate timestamp the duration calibration uses.
Progress rises linearly to 95% at e, then holds at 95% until the planner reports completion, then shows 100%.
Progress never moves backwards, including when the planner repeats stages. Editing the form during a calculation does not change it.
Cancellation, interruption and errors never force 100%.
Stage line
One line beneath the indicator names the current planning stage:
Planner stage
English text
preparation
Preparing the calendar
validation
Checking your inputs
obligations
Satisfying obligations
optimization:<id> / preference:<id>
Applying "rule name" (no optimization summary)
expiry
Using balances that expire first
dates
Settling the final dates
Obligations are satisfied jointly, so that stage names no single rule.
Remaining time
When e is at least 3 seconds, a second line reads "About N s left". N is rounded to whole seconds under 10 s, then to 5-second steps, then to whole minutes.
Once the elapsed time reaches e, that line reads "Taking longer than expected". This also applies to calculations whose e was under 3 seconds.
Cancellation and accessibility
After Cancel, the percentage freezes, the stage and remaining-time lines are hidden, and the existing status reads "Cancelling…".
The stage and remaining-time lines are visible text, not live regions.
The existing status keeps "Loading…" / "Cancelling…" and announces "Taking longer than expected" once when the overrun starts.
The Cancel control stays available.
Localization
All new text is localized in every supported language (EN, FR, ES, DE).
Implementation Decisions
PlanningDurationService owns the wait progress: the percentage, remaining time and overrun state. It already owns the estimate and its calibration, and it already depends on PlanningCalculationService. While a calculation is pending, it reads the pending calculation's Calculate timestamp and submitted configuration, freezes e, and updates on a 250 ms tick.
PlanningCalculationService reports the current stage and the submitted configuration in its pending state. It no longer computes percentages; stageProgress and its obsolete stage names are removed.
CalendarYear binds the new state. Planning, optimization, worker and cancellation behaviour are unchanged.
Progress is deliberately time-based. Per-stage weights are not guessed, because the costly stage depends on the configuration (see the problem statement).
Testing Decisions
Use a controlled clock to test:
the linear climb to 95% at e and the hold at 95%;
the switch to "Taking longer than expected" and its single announcement;
the 3-second threshold for the remaining-time line;
the remaining-time rounding;
that e stays frozen when the form changes mid-calculation;
monotonic progress when stages repeat;
100% only on completion, and none on cancellation, incomplete outcomes or errors.
Do not assert exact timings against hardware speed.
Verify the visible stage text for each stage, including the rule name, and the localized text in each supported language.
Follow the existing calendar planning tests and duration-estimate tests.
Out of Scope
Changes to planning, optimization, worker search or cancellation semantics.
Replacing the circular indicator or redesigning other loading states.
Remote timing collection, or a standing accuracy caveat beyond the overrun line above.
Further Notes
ADR 0006: this is UI behaviour under its existing cancellable-calculation contract.
First runs on a slow device: before the device has any local sample, a phone will often overrun its first estimate, which was fitted on a desktop. It then shows 95% with "Taking longer than expected" until the plan arrives. Later calculations use the device's own refinement.
Origin: the decisions above came from a design review after #302 and PR #303. "Planning stage" and "indicative wait" are defined in CONTEXT.md.
## Problem Statement
The calculation overlay shows a circular percentage indicator, but its fixed stage mapping is out of date. Since rule stages are named after their rules (`optimization:<id>`, `preference:<id>`), every preference rule shows 50%. Six mapped stage names are never reported, and `preparation` stays at 0%. Progress can appear stalled while planning continues, and the overlay does not say what work is underway.
Since #302, the time per stage also varies by configuration in ways the form does not reveal. These figures are shares of each scenario's planning time on the development machine:
- in multi-year horizons, loss prevention takes 58–65%;
- in typed obligations, public-holiday weeks take 65%;
- in the loaded year, non-working-day gain takes 77%;
- the obligation stage takes at most 3%.
Since #302, an earned-entitlement retry can also re-run the rule stages after `dates`, which would move today's mapping backwards.
## Solution
Keep the circular indicator, but make the percentage follow the **indicative wait** rather than the stages completed. Beneath the indicator, add a short line naming the current **planning stage** and, for preference stages, the rule being applied. Below that, add an approximate remaining time for longer waits. Show 100% only when the planner completes.
## User Stories and Acceptance Criteria
- As a user waiting for a plan, I can see what the calculation is doing, how far through the expected wait it is, and roughly how long remains.
**Percentage**
- [ ] The percentage is the share of the expected wait `e`. `e` is the indicative-wait estimate for the submitted configuration, including the device's local refinement, captured once at Calculate. Elapsed time counts from the same Calculate timestamp the duration calibration uses.
- [ ] Progress rises linearly to 95% at `e`, then holds at 95% until the planner reports completion, then shows 100%.
- [ ] Progress never moves backwards, including when the planner repeats stages. Editing the form during a calculation does not change it.
- [ ] Cancellation, interruption and errors never force 100%.
**Stage line**
- [ ] One line beneath the indicator names the current planning stage:
| Planner stage | English text |
|---|---|
| `preparation` | Preparing the calendar |
| `validation` | Checking your inputs |
| `obligations` | Satisfying obligations |
| `optimization:<id>` / `preference:<id>` | Applying "*rule name*" (no optimization summary) |
| `expiry` | Using balances that expire first |
| `dates` | Settling the final dates |
- [ ] Obligations are satisfied jointly, so that stage names no single rule.
**Remaining time**
- [ ] When `e` is at least 3 seconds, a second line reads "About N s left". N is rounded to whole seconds under 10 s, then to 5-second steps, then to whole minutes.
- [ ] Once the elapsed time reaches `e`, that line reads "Taking longer than expected". This also applies to calculations whose `e` was under 3 seconds.
**Cancellation and accessibility**
- [ ] After Cancel, the percentage freezes, the stage and remaining-time lines are hidden, and the existing status reads "Cancelling…".
- [ ] The stage and remaining-time lines are visible text, not live regions.
- [ ] The existing status keeps "Loading…" / "Cancelling…" and announces "Taking longer than expected" once when the overrun starts.
- [ ] The Cancel control stays available.
**Localization**
- [ ] All new text is localized in every supported language (EN, FR, ES, DE).
## Implementation Decisions
- `PlanningDurationService` owns the wait progress: the percentage, remaining time and overrun state. It already owns the estimate and its calibration, and it already depends on `PlanningCalculationService`. While a calculation is pending, it reads the pending calculation's Calculate timestamp and submitted configuration, freezes `e`, and updates on a 250 ms tick.
- `PlanningCalculationService` reports the current stage and the submitted configuration in its pending state. It no longer computes percentages; `stageProgress` and its obsolete stage names are removed.
- `CalendarYear` binds the new state. Planning, optimization, worker and cancellation behaviour are unchanged.
- Progress is deliberately time-based. Per-stage weights are not guessed, because the costly stage depends on the configuration (see the problem statement).
## Testing Decisions
- Use a controlled clock to test:
- the linear climb to 95% at `e` and the hold at 95%;
- the switch to "Taking longer than expected" and its single announcement;
- the 3-second threshold for the remaining-time line;
- the remaining-time rounding;
- that `e` stays frozen when the form changes mid-calculation;
- monotonic progress when stages repeat;
- 100% only on completion, and none on cancellation, incomplete outcomes or errors.
- Do not assert exact timings against hardware speed.
- Verify the visible stage text for each stage, including the rule name, and the localized text in each supported language.
- Follow the existing calendar planning tests and duration-estimate tests.
## Out of Scope
- Changes to planning, optimization, worker search or cancellation semantics.
- Replacing the circular indicator or redesigning other loading states.
- Remote timing collection, or a standing accuracy caveat beyond the overrun line above.
## Further Notes
- **ADR 0006:** this is UI behaviour under its existing cancellable-calculation contract.
- **First runs on a slow device:** before the device has any local sample, a phone will often overrun its first estimate, which was fitted on a desktop. It then shows 95% with "Taking longer than expected" until the plan arrives. Later calculations use the device's own refinement.
- **Origin:** the decisions above came from a design review after #302 and PR #303. "Planning stage" and "indicative wait" are defined in `CONTEXT.md`.
Design decision during implementation (PR #304), confirmed by the owner. It replaces this acceptance criterion: "Once the elapsed time reaches e, that line reads 'Taking longer than expected'."
e is the centre of the range shown before Calculate, which runs from e/2 to 3e. Once calibrated, e is a median, so about half of all runs would pass it. The overrun now starts at the top of that displayed range. Between e and that top, the percentage holds at 95% and the remaining-time line is hidden. Past the top, for any e, the line reads "Taking longer than expected" and is announced once.
Also confirmed:
Remaining time is rounded up under 10 s, so it never reads "0 s". From 10 s it goes to the nearest 5 s, and a value that rounds to 60 s or more is shown in whole minutes.
The stage and remaining-time lines sit below the "Calculating..." status.
Design decision during implementation (PR #304), confirmed by the owner. It replaces this acceptance criterion: "Once the elapsed time reaches e, that line reads 'Taking longer than expected'."
e is the centre of the range shown before Calculate, which runs from e/2 to 3e. Once calibrated, e is a median, so about half of all runs would pass it. The overrun now starts at the top of that displayed range. Between e and that top, the percentage holds at 95% and the remaining-time line is hidden. Past the top, for any e, the line reads "Taking longer than expected" and is announced once.
Also confirmed:
- Remaining time is rounded up under 10 s, so it never reads "0 s". From 10 s it goes to the nearest 5 s, and a value that rounds to 60 s or more is shown in whole minutes.
- The stage and remaining-time lines sit below the "Calculating..." status.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem Statement
The calculation overlay shows a circular percentage indicator, but its fixed stage mapping is out of date. Since rule stages are named after their rules (
optimization:<id>,preference:<id>), every preference rule shows 50%. Six mapped stage names are never reported, andpreparationstays at 0%. Progress can appear stalled while planning continues, and the overlay does not say what work is underway.Since #302, the time per stage also varies by configuration in ways the form does not reveal. These figures are shares of each scenario's planning time on the development machine:
Since #302, an earned-entitlement retry can also re-run the rule stages after
dates, which would move today's mapping backwards.Solution
Keep the circular indicator, but make the percentage follow the indicative wait rather than the stages completed. Beneath the indicator, add a short line naming the current planning stage and, for preference stages, the rule being applied. Below that, add an approximate remaining time for longer waits. Show 100% only when the planner completes.
User Stories and Acceptance Criteria
Percentage
e.eis the indicative-wait estimate for the submitted configuration, including the device's local refinement, captured once at Calculate. Elapsed time counts from the same Calculate timestamp the duration calibration uses.e, then holds at 95% until the planner reports completion, then shows 100%.Stage line
One line beneath the indicator names the current planning stage:
preparationvalidationobligationsoptimization:<id>/preference:<id>expirydatesObligations are satisfied jointly, so that stage names no single rule.
Remaining time
eis at least 3 seconds, a second line reads "About N s left". N is rounded to whole seconds under 10 s, then to 5-second steps, then to whole minutes.e, that line reads "Taking longer than expected". This also applies to calculations whoseewas under 3 seconds.Cancellation and accessibility
Localization
Implementation Decisions
PlanningDurationServiceowns the wait progress: the percentage, remaining time and overrun state. It already owns the estimate and its calibration, and it already depends onPlanningCalculationService. While a calculation is pending, it reads the pending calculation's Calculate timestamp and submitted configuration, freezese, and updates on a 250 ms tick.PlanningCalculationServicereports the current stage and the submitted configuration in its pending state. It no longer computes percentages;stageProgressand its obsolete stage names are removed.CalendarYearbinds the new state. Planning, optimization, worker and cancellation behaviour are unchanged.Testing Decisions
eand the hold at 95%;estays frozen when the form changes mid-calculation;Out of Scope
Further Notes
CONTEXT.md.Design decision during implementation (PR #304), confirmed by the owner. It replaces this acceptance criterion: "Once the elapsed time reaches e, that line reads 'Taking longer than expected'."
e is the centre of the range shown before Calculate, which runs from e/2 to 3e. Once calibrated, e is a median, so about half of all runs would pass it. The overrun now starts at the top of that displayed range. Between e and that top, the percentage holds at 95% and the remaining-time line is hidden. Past the top, for any e, the line reads "Taking longer than expected" and is announced once.
Also confirmed: