fire-planner/tests
Viktor Barzin 64eb90c3dc
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fire-planner: Wave 2 chart-first — flex spending, categorised life
events, interactive Visx Gantt + spending-profile chart

Charts are now the primary editor for life events. The Plan-tab body
re-orders to make charts ~80% of viewport real-estate; legacy form
sections are collapsed into a drawer.

Backend:
- alembic 0004: life_event.category enum (essential / discretionary /
  not_spending). Defaults to essential so existing rows keep their
  full spending impact.
- Simulator gains discretionary_outflows + flex_rules params. Tracks
  per-path running ATH, applies the deepest applicable cut to
  discretionary outflows when portfolio drops vs ATH (PLab-style flex
  spending). Cut amount stays in the portfolio (refund pattern).
- New flex_spending module with FlexRule + applicable_cut +
  cuts_per_year (vectorised). Sortable rules; "deepest cut wins" so
  users specify cumulative cuts at each tier.
- New /scenarios/{id}/spending-profile endpoint returning per-year
  base / essential / discretionary / flex_cut / total breakdown.
- SimulateRequest gains flex_rules + life_event.category roundtrip.
- 8 new tests; 246 total pytest pass; mypy + ruff clean.

Frontend (Visx + ECharts):
- Installed @visx/{scale,shape,group,axis,event,responsive,tooltip}
  for native SVG drag interactions.
- New <SpendingProfileChart> — Visx stacked-area of base/essential/
  discretionary with red flex-cut overlay, hover tooltip, click-to-
  scrub-year.
- New <EventGantt> — interactive Visx Gantt:
    * Click empty space → popover create at that year (default
      essential spending event)
    * Click a bar → inline edit popover (name, kind, range, £/y,
      category) with delete button
    * Drag bar middle → moves the whole event (year-resolution snap)
    * Drag bar edges → resizes year_start / year_end
    * All gestures persist via PATCH /life-events/{id}
- New <FlexRulesEditor> — list of {from_ath_pct, cut} tiers, save-on-
  change to scenario.config_json.flex_rules.
- Plan-tab redesign: NW fan dominant top with floating stat badges
  (Year/Age/NW/Δ NW/Spending/Eff. tax) over the chart; spending-
  profile chart middle; Gantt bottom; flex-rules editor; legacy form
  sections in a collapsed <details> drawer.
- Frontend typecheck + 7 vitest tests + production build all clean.
2026-05-10 16:49:04 +00:00
..
__init__.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
conftest.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_actualbudget.py whatif: live data refresh, inflation-adjusted spending, legend fix 2026-05-10 11:27:22 +00:00
test_api_cashflow.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
test_api_life_events_goals.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
test_api_networth.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
test_api_progress.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
test_api_scenarios.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
test_api_simulate.py engine+api: plumb life events into the simulator 2026-05-09 22:30:33 +00:00
test_api_spending.py whatif: live data refresh, inflation-adjusted spending, legend fix 2026-05-10 11:27:22 +00:00
test_api_spending_profile.py fire-planner: Wave 2 chart-first — flex spending, categorised life 2026-05-10 16:49:04 +00:00
test_api_year_stats.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
test_cli.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_db_schema.py schema: add life_event, retirement_goal; extend scenario with kind/parent 2026-05-09 21:36:58 +00:00
test_e2e.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_flex_spending.py fire-planner: Wave 2 chart-first — flex spending, categorised life 2026-05-10 16:49:04 +00:00
test_goals_eval.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
test_income_streams.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
test_ingest_wealthfolio_pg.py ingest: switch wealthfolio to pg-sync mirror reads 2026-05-09 21:33:48 +00:00
test_life_events.py engine+api: plumb life events into the simulator 2026-05-09 22:30:33 +00:00
test_reporters_pg.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_returns.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_returns_wealthfolio.py returns: 3 models — Shiller bootstrap (default), manual %, Wealthfolio history 2026-05-10 01:04:25 +00:00
test_scenarios.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_simulator.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_simulator_events.py engine+api: plumb life events into the simulator 2026-05-09 22:30:33 +00:00
test_simulator_fixed_rates.py fire-planner: ProjectionLab parity Wave 1 — tabbed shell, year stats, goals, 2026-05-10 12:49:44 +00:00
test_simulator_flex.py fire-planner: Wave 2 chart-first — flex spending, categorised life 2026-05-10 16:49:04 +00:00
test_spending_plan.py strategies: spending input is honoured + new "Custom" preset with guardrails 2026-05-10 01:21:55 +00:00
test_strategies.py strategies: spending input is honoured + new "Custom" preset with guardrails 2026-05-10 01:21:55 +00:00
test_tax_base.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_tax_other_regimes.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_tax_uk.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00