focus-flow/Codex Documentation/Completed Plans/V1_BLOCK_11_Backend_Baseline_Domain_Contracts.md

12 KiB
Raw Permalink Blame History

V1 Block 11 — Backend Baseline and Domain Contracts

Status: Complete on 2026-06-24.

Purpose: Re-establish a trustworthy executable baseline after the archived Blocks 0110, resolve remaining V1 specification ambiguities, and harden the core domain/time contracts before adding more scheduling, persistence, or UI surface area.

Chunk 11.1 — Fresh verification and V1 traceability baseline

Recommended Codex level: medium

Status: Complete on 2026-06-24.

Baseline:

  • Starting commit: 775c2ed406f03a73a9b0ca621dea5b4482468616
  • Dart SDK: 3.12.2
  • Current test count: 143 passing tests

Verification commands:

  • dart pub get: passed
  • dart format lib test: passed, 0 files changed
  • dart analyze: passed, no issues found
  • dart test: passed, 143 tests
  • git diff --check: passed

Documentation outputs:

  • Updated Codex Documentation/Archived plans/V1_TEST_COVERAGE_MATRIX.md to remove a stale reference to missing test/quick_capture_test.dart and record the fresh verification result.
  • Added V1_REQUIREMENTS_TRACEABILITY_MATRIX.md.
  • Added V1_PUBLIC_API_BASELINE.md.
  • Updated V1_BACKEND_COMPLETION_GAP_MATRIX.md so it no longer describes the 143-test result as only historical.

Tasks:

  • Install or select a Dart SDK compatible with pubspec.yaml.
  • Run and record:
dart pub get
dart format lib test
dart analyze
dart test
git diff --check
  • Record the starting commit and actual current test count.
  • Repair stale or incorrect entries in V1_TEST_COVERAGE_MATRIX.md, including references to test files that do not exist.
  • Add a V1 requirements traceability matrix that maps each human-document MVP acceptance criterion to production APIs, tests, and one of: complete, incomplete, intentionally deferred, or contradictory.
  • Capture a public API baseline so later chunks can distinguish intentional breaking changes from accidental ones.
  • Turn every verified gap into either an active-plan reference or a narrowly scoped issue/TODO; do not leave vague “future” claims in the completion matrix.

Rules:

  • This chunk is verification and documentation only unless a minimal formatting or test-reference correction is required.
  • Do not claim the archived 143-test result is current until the suite is rerun.
  • If a command cannot run, document the exact environment blocker and keep this chunk incomplete.
  • Do not edit archived plan completion notes to hide a newly discovered gap.
  • Do not begin feature implementation in this chunk.

Acceptance criteria:

  • All standard verification commands pass in the active environment.
  • The current test count and starting commit are recorded.
  • Every V1 acceptance criterion has a traceable implementation/test status.
  • Stale coverage references are corrected.
  • The gap matrix agrees with the active Block 1118 plan index.

BREAKPOINT: Stop here. Confirm high mode before resolving domain semantics.

Chunk 11.2 — Resolve V1 lifecycle and metadata semantics

Recommended Codex level: high

Status: Complete on 2026-06-24.

Documentation outputs:

  • Added V1_ADR_001_Lifecycle_Metadata_Reminder_Semantics.md to define durable V1 lifecycle statuses, movement/activity semantics, task-type behavior, planned versus actual time fields, project default precedence, and reminder policy boundaries.
  • Updated Human Documentation/Starter Architecture Notes.md to resolve the human-spec pushed/skipped status ambiguity without changing product intent.

Test outputs:

  • Added test/domain_contracts_test.dart to lock the durable status list, assert push remains movement metadata, keep burnout skip as stats-only compatibility, and cover critical versus inflexible missed semantics.

Tasks:

  • Add an architecture decision record that defines the durable task lifecycle states used by V1.
  • Keep movement such as manual push, automatic push, move to backlog, and restore from backlog as activity/stat events rather than durable lifecycle statuses.
  • Keep skipped during burnout compatible as a future activity/stat concept, but do not add V2 shield or catch-up transitions.
  • Define exact behavior for each task type in each relevant lifecycle state, including flexible, critical, inflexible, locked, surprise, and free slot.
  • Define which fields represent planned placement, actual work time, completion time, backlog-entry time, and last modification time.
  • Define critical-missed behavior as missed plus backlog placement, and inflexible-missed behavior as missed history that retains its original scheduled interval.
  • Define how configured project defaults, learned suggestions, and task-level overrides differ.
  • Define the reminder-profile inheritance order and the boundary between backend policy decisions and platform notification delivery.
  • Update human-facing architecture notes only where needed to resolve a real contradiction; preserve the original product intent.

Rules:

  • Do not introduce V2 behavior to make the status table symmetrical.
  • Do not turn every activity into a task status.
  • Preserve calm, non-punitive terminology.
  • The decision record must be specific enough to drive model, mapping, and test changes in later chunks.
  • Prefer one durable meaning per field; do not overload updatedAt as a proxy for backlog age, completion, or actual work time.

Acceptance criteria:

  • The status/event distinction is documented and covered by focused tests or compile-time model expectations.
  • Critical and inflexible missed semantics are unambiguous.
  • Planned versus actual time semantics are unambiguous.
  • Project defaults, learned suggestions, and task overrides have a defined precedence model.
  • No V2-only workflow has been added.

Chunk 11.3 — Domain invariants and explicit patch semantics

Recommended Codex level: high

Status: Complete on 2026-06-24.

Implementation outputs:

  • Added typed domain validation codes and DomainValidationException.
  • Enforced non-blank task/project/locked-time identifiers and labels at domain model boundaries.
  • Enforced positive optional durations and valid scheduled, actual, TimeInterval, SchedulingWindow, locked block, recurrence, and override intervals.
  • Added explicit nullable clear semantics for task priority, duration, schedule interval, actual interval, parent ownership, reminder override, and project default duration.
  • Added task actualStart, actualEnd, and reminderOverride fields with document mapping support.
  • Rejected self-parenting and preserved direct-child-only ownership.
  • Defensively copied public domain/read-model collections into unmodifiable snapshots.

Test outputs:

  • Added test/domain_invariants_test.dart for validation codes, clear paths, immutable collection boundaries, and locked-time invariants.
  • Updated persistence and scheduler tests for the new document fields and immutable result snapshots.

Tasks:

  • Enforce non-blank stable IDs, titles, and project IDs at model boundaries.
  • Enforce positive durations when a duration is present.
  • Enforce that scheduled start/end values are either both absent or both present and that end is after start.
  • Enforce valid TimeInterval, scheduling-window, recurrence, and override intervals.
  • Reject self-parenting and define the direct-child-only ownership boundary.
  • Add explicit patch/clear semantics for nullable fields that must be removable, including duration, priority, parent ownership, schedule placement, actual interval, and reminder override.
  • Prevent mutable input collections from leaking into immutable domain objects.
  • Introduce typed validation failures/codes that application and persistence layers can map without parsing English strings.
  • Add regression tests for every invariant and every intentional clear path.

Rules:

  • Keep constructors/factories consistent; do not leave a public constructor that bypasses all invariants without a documented internal-only reason.
  • Do not use magic sentinel enum values to mean “clear this field.”
  • Validation must remain UI- and database-independent.
  • Existing valid fixtures must continue to construct or be migrated explicitly in Block 15.
  • Error codes are stable contracts; explanatory text may change later.

Acceptance criteria:

  • Invalid partial/negative/empty model states are rejected deterministically.
  • Every nullable field that the product can remove has an explicit tested clear path.
  • All domain collections exposed publicly are immutable views or immutable values.
  • Application callers can distinguish validation categories without matching message text.
  • Existing scheduling behavior still passes its regression suite.

BREAKPOINT: Stop here. Confirm extra high mode before changing civil-time and clock contracts.

Chunk 11.4 — Deterministic clock, IDs, and civil-time semantics

Recommended Codex level: extra high

Status: Complete on 2026-06-24.

Implementation outputs:

  • Added clock, ID, civil-date, wall-time, timezone resolver, DST policy, and fixed-offset resolver contracts in lib/src/time_contracts.dart.
  • Exported the time contracts from the public scheduler_core.dart entry point.
  • Replaced hidden DateTime.now() fallbacks in scheduling, action, surprise logging, and child-completion services with injected Clock boundaries.
  • Added optional ID-generator convenience wrappers for quick capture and surprise logging while preserving explicit request APIs.
  • Migrated locked block dates and override dates to CivilDate; kept ClockTime as a backwards-compatible alias of WallTime.
  • Required locked-time expansion and override interval conversion to receive an explicit timeZoneId and TimeZoneResolver.
  • Documented and tested safe overnight locked-rule behavior: reject non-positive and overnight wall-time intervals instead of splitting silently.
  • Added civil-date and wall-time persistence conventions that store date-only and wall-time strings without timezone conversion.
  • Updated architecture notes and the public API baseline for the intentional time-contract changes.

Test outputs:

  • Added test/time_contracts_test.dart for civil-date/wall-time parsing, midnight/month/year/leap-day boundaries, fixed offset conversion, injected clocks/IDs, DST gap/repeat policy, reject policy codes, and overnight rejection.
  • Updated locked-time, scheduling, persistence, repository, and invariant tests to use explicit civil dates and timezone resolver boundaries.
  • Current verification result: dart test passed with 174 tests.

Tasks:

  • Introduce injectable clock and ID-generation contracts for application/domain operations that currently fall back to DateTime.now() or caller-created IDs.
  • Remove hidden wall-clock reads from deterministic core methods; convenience wrappers may delegate to injected services at an outer boundary.
  • Introduce explicit civil-date and wall-clock value types for recurring locked rules and date-only overrides.
  • Introduce a time-zone identifier/resolver boundary that converts a local day and wall time into instants used by the scheduling engine.
  • Define and test daylight-saving behavior for nonexistent and repeated local times.
  • Persist date-only values as date-only values and wall times as wall times; do not convert them to UTC timestamps that can change the calendar day.
  • Define whether overnight locked rules are rejected or normalized into explicit split occurrences; implement the selected safe behavior.
  • Update locked-block expansion, scheduling windows, and tests to use the new deterministic time contracts.
  • Add boundary tests for midnight, month/year transitions, leap day, DST gaps, DST repeats, and non-UTC time zones.

Rules:

  • Keep IANA/platform time-zone implementation behind an interface so the core does not import Flutter or platform APIs.
  • Do not use the machines implicit local zone as persistent business data.
  • Do not silently reinterpret legacy UTC timestamps; migration belongs in Block 15 and must be fixture-tested.
  • Every scheduling operation must receive an explicit operation time and owner time-zone context through the application boundary.
  • Locked and inflexible time must remain immovable through this refactor.

Acceptance criteria:

  • Core tests no longer depend on the machine clock or default local time zone.
  • Recurring locked blocks expand to the intended local calendar dates across DST transitions.
  • Date-only overrides round-trip without a day shift.
  • Invalid/ambiguous time input follows a documented deterministic policy.
  • The full verification suite passes after the time-model migration.

Commit suggestion:

feat(domain): harden v1 contracts and time semantics