Skip to content

Dive planner Phase 2: persisted plans, sync, and the PlanEngine#485

Merged
ericgriffin merged 11 commits into
mainfrom
worktree-dive-planner-phase2-domain
Jul 6, 2026
Merged

Dive planner Phase 2: persisted plans, sync, and the PlanEngine#485
ericgriffin merged 11 commits into
mainfrom
worktree-dive-planner-phase2-domain

Conversation

@ericgriffin

@ericgriffin ericgriffin commented Jul 5, 2026

Copy link
Copy Markdown
Member

Summary

Phase 2 of the dive planner redesign (spec, plan). Builds directly on #484 (Phase 1 engine, now merged).

Persistence + sync

  • Schema v100: dive_plans / dive_plan_tanks / dive_plan_segments with HLC columns, idempotent migration, and a beforeOpen re-assert backstop against parallel-branch version collisions. The plan row carries CCR/contingency/repetitive config columns now (Phases 4-6 fill them) plus denormalized summary columns so the saved-plans list never runs the engine per row.
  • Full sync registration (all 18 sites: serializer, merge order, entityHasUpdatedAt, parentRefs, _hlcTargets) — verified by the structural safety-net tests plus a new FK-ON export/JSON/upsert round-trip test.
  • DivePlanRepository: save/get/list/delete/duplicate with markRecordPending + fresh HLC on every write and per-row tombstones for removed children (the parent-surviving-child-delete lesson from multi-computer consolidation).

Domain + engine

  • domain.DivePlan aggregate: the persisted superset of the legacy planner state — mode (OC/CCR), water type, descent/ascent rates, last stop, air breaks, three SAC rates (bottom / deco / stressed with 0.8x / 2.5x derived defaults), deviation deltas, turn-pressure rule, setpoints, tissue-seeding and plan-vs-actual dive links.
  • PlanEngine: DivePlan -> PlanOutcome built entirely on the Phase 1 seams (BuhlmannGf/SchedulePolicy/BreathingConfig/DiveEnvironment). Produces the stop schedule with per-stop gas/tank/arrival, per-segment NDL/ceiling/TTS/CNS/OTU, a tissue timeline for the Phase 3 canvas, environment-aware three-SAC consumption with compressibility-corrected remaining pressure, and a severity-sorted PlanIssue list: ppO2, hypoxic gas, END, gas density 5.2/6.2 g/L (new shared gas_density.dart helper, also deduplicating the dive-details density curve), CNS/OTU, reserve/gas-out, and deco-without-deco-gas.
  • A parity test pins PlanEngine against the legacy PlanCalculatorService: identical stops, TTS, and NDL on the default path.

User-visible

  • The planner's save button now actually persists (with list summary numbers), and /planning/dive-planner/:planId loads a saved plan back into the editor. Everything else about the old planner is unchanged — the new UI is Phase 3.

Verification

790 tests green across the sweep (4 migration, 304 deco, 82 planner, 400 sync); flutter analyze clean.

@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements Phase 2 of the dive-planner redesign by introducing a persisted/synced dive-plan aggregate plus a new PlanEngine that computes schedules, consumption, and issues using the Phase 1 deco-engine seams. This keeps the legacy planner UI largely intact while making “Save”/deep-link “Load” operate against real stored plans.

Changes:

  • Adds schema v100 plan tables (dive_plans, dive_plan_tanks, dive_plan_segments) with migration/backstop and full sync registration + FK-on round-trip coverage.
  • Introduces the planner/ feature module: domain.DivePlan + DivePlanRepository + PlanEngine + Riverpod providers.
  • Wires legacy planner save/load to persisted plans via a state↔aggregate mapper and adds end-to-end tests for save/reset/load.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/features/planner/plan_engine_schedule_test.dart Validates PlanEngine schedule generation and parity with legacy planner results.
test/features/planner/plan_engine_issues_test.dart Covers PlanEngine issue detection, sorting, and consumption math.
test/features/planner/dive_plan_state_mapper_test.dart Ensures legacy UI state round-trips through the persisted aggregate.
test/features/planner/dive_plan_repository_test.dart Exercises plan persistence, summaries, tombstones, duplication, and pending sync markers.
test/features/planner/dive_plan_entity_test.dart Verifies DivePlan derived defaults, max-depth logic, and copyWith clear-flags.
test/features/dive_planner/save_load_round_trip_test.dart End-to-end test for save → reset → load through Riverpod + repository.
test/core/services/sync/dive_plan_sync_round_trip_test.dart Sync export/JSON/apply round-trip validation with FK ON.
test/core/deco/gas_density_test.dart Pins density computation vectors and thresholds.
test/core/database/migration_v100_dive_plans_test.dart Asserts v100 tables/indexes exist and beforeOpen backstop heals collisions.
lib/features/planner/presentation/providers/plan_repository_providers.dart Provides repository + live-updating summaries list providers.
lib/features/planner/domain/services/plan_engine.dart New PlanEngine orchestration: schedule, segments, consumption, and issue computation.
lib/features/planner/domain/services/dive_plan_state_mapper.dart Maps between legacy planner state and the new persisted domain.DivePlan.
lib/features/planner/domain/entities/plan_outcome.dart Defines PlanEngine output model (stops, tank usage, issues, tissue timeline).
lib/features/planner/domain/entities/dive_plan.dart Defines persisted dive-plan aggregate + summary row type.
lib/features/planner/data/repositories/dive_plan_repository.dart Implements persistence, child tombstones, sync pending markers, and duplication.
lib/features/dive_planner/presentation/providers/dive_planner_providers.dart Wires notifier to repository-backed save/load while preserving legacy flows.
lib/features/dive_planner/presentation/pages/dive_planner_page.dart Loads persisted plan by route id and replaces save TODO with real persistence.
lib/features/dive_log/data/services/profile_analysis_service.dart Deduplicates density math via shared helper.
lib/core/services/sync/sync_service.dart Registers plan entities in merge order, updatedAt map, and parent refs.
lib/core/services/sync/sync_data_serializer.dart Adds plan entities to SyncData + export/upsert/delete/record-id plumbing.
lib/core/deco/gas_density.dart New shared gas-density helper + thresholds.
lib/core/database/database.dart Adds Drift table definitions, schema bump to v100, migration + beforeOpen re-assert.
lib/core/data/repositories/sync_repository.dart Registers plan tables as HLC targets for pending marking.
docs/superpowers/plans/2026-07-05-dive-planner-phase2-domain.md Implementation plan/spec for Phase 2 work items and constraints.

Comment thread lib/features/planner/domain/services/plan_engine.dart
Comment thread lib/features/planner/domain/services/plan_engine.dart
Comment thread lib/features/planner/data/repositories/dive_plan_repository.dart
Comment thread lib/features/planner/data/repositories/dive_plan_repository.dart
- PlanEngine: reject non-Buhlmann start states up front; accumulate CNS/OTU
  over decompression stops (primary + air-break gas)
- DivePlanRepository: preserve child tank/segment createdAt across edits
- Add entity, engine, repository, and sync round-trip coverage
@ericgriffin ericgriffin self-assigned this Jul 6, 2026
@ericgriffin ericgriffin moved this from Backlog to In review in Submersion Release Tracker Jul 6, 2026
@ericgriffin ericgriffin merged commit d418aeb into main Jul 6, 2026
19 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in Submersion Release Tracker Jul 6, 2026
@ericgriffin ericgriffin deleted the worktree-dive-planner-phase2-domain branch July 6, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants