# 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 01–10, 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:

```bash
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 11–18 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 machine’s 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:

```text
feat(domain): harden v1 contracts and time semantics
```
