Skip to content

E1-07: Add Android Vehicle UI - #37

Merged
davidru85 merged 28 commits into
mainfrom
story/E1-07-android-vehicle-ui
Aug 31, 2026
Merged

E1-07: Add Android Vehicle UI#37
davidru85 merged 28 commits into
mainfrom
story/E1-07-android-vehicle-ui

Conversation

@davidru85

@davidru85 davidru85 commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • Delivers E1-07 Android Vehicle list, create/edit form and detail UI with shared KMP presentation state holders and executable D-28 package rules.
  • Applies all owner code-review corrections in four RED/GREEN/REFACTOR triplets: safe cached creation, bounded Swift holder caches, explicit enum ABI names, Android configuration-change retention and raw odometer validation.
  • Keeps D-84 through D-89 unchanged and records the two gated corrections as D-90 / ADR-0091 and D-91 / ADR-0092.
  • Applies second-round N-1/N-2 corrections for restored-draft command parity and one shared initial-odometer range without a new decision, ADR or Swift ABI change.

Story

E1-07 - Android UI: Vehicles - M

Ready Check

  • Backlog story and acceptance criteria are explicit
  • Dependencies and normative sections were reviewed
  • Every required decision is Accepted
  • Verification and human-review gates are identified
  • Owner conversation stayed in Spanish and repository artifacts are technical English

Scope Completed

  • Implemented the localized Compose Vehicle list, create/edit form and detail shell with typed loading, empty and error states.
  • Added shared Vehicle presentation state holders, reactive edit facts, Kotlin/Swift graph separation and graph-owned database lifetime.
  • Added D-28 domain/data/presentation rules with an independently firing fixture for each rule.
  • Made successful creation reset its inputs while preserving create-route identity; completion is reported through savedVehicleId.
  • Added keyed release for cached Vehicle forms, Fuel Entry lists and Fuel Entry forms on SwiftAppGraph.
  • Pinned Confirmation, AuthProvider and SyncTrigger to exact Kotlin-matching Swift and Shared... Objective-C names.
  • Retained Android form drafts across activity recreation while still releasing the holder after navigation exit.
  • Preserved empty, non-numeric, overflowing and out-of-range odometer text and mapped it to a localized visible error that blocks save.
  • Republishes restored saveable drafts into fresh holders and preserves pre-facts edits while keeping odometer editability facts-owned.
  • Uses the Kotlin-only domain initial-odometer range in the Android adapter, removing the duplicated host range.

TDD Evidence

Correction RED GREEN REFACTOR
C-1 / C-4 cached creation and Swift cache lifetime bbbec4a f5eafcf 4e23654
C-2 explicit common-enum ABI names 3d10013 ca54bcb bcf0345
C-3 Android configuration retention 9829fe8 100d107 5e2cf35
C-5 raw odometer input 0c708c5 67b252f 0f0e170
N-1 restored-draft command parity 4d101d0 8628e9f 71ec3dd
N-2 shared odometer range 9aba1db e205991 ca7324b

Acceptance Evidence

  • Two saves through one creation holder issue two distinct create commands, never an update, and the second form starts empty.
  • Swift keyed release closes the selected holder, cancels its child scope and returns a fresh instance on the next request.
  • The API 36 instrumented suite proves creation, Fuel Type control absence, detail routing, draft retention across recreation, release after back-stack exit and visible invalid-odometer feedback.
  • Android display copy comes from English and Spanish resources; UiState still contains codes and data only.
  • The production list requests includeDeleted = false; tests prove tombstones do not enter the emitted list.
  • D-28 real-tree checks and all firing fixtures pass.
  • State restoration with a fresh holder produces CreateVehicleCommand(name = "Restored draft", initialOdometerKm = 321), and edits made before first facts appear in the captured UpdateVehicleCommand.
  • The API 36 range test binds both accepted boundaries and adjacent rejected values to the domain declaration.

Swift ABI and Golden Header

  • The PR intentionally changes the Swift-facing ABI; it does not claim byte-for-byte preservation relative to main.
  • D-90 adds releaseVehicleFormStateHolder, releaseFuelEntryListStateHolder, releaseFuelEntryFormStateHolder and VehicleFormUiState.savedVehicleId.
  • D-91 pins the reviewed enum names Confirmation, AuthProvider and SyncTrigger with matching SharedConfirmation, SharedAuthProvider and SharedSyncTrigger Objective-C names. C-2 creates no additional golden diff from the preceding D-90 state because those Kotlin-matching names were already generated; the annotations make them contractual rather than export-configuration artifacts.
  • The linked final Shared.framework header exactly matches the committed golden and exposes no forbidden provider, repository, command or use-case declarations.
  • N-1 and N-2 do not change that header; INITIAL_ODOMETER_RANGE_KM is hidden from Objective-C.

Decisions Made

  • D-90 / ADR-0091: retain keyed Swift holder caches, add explicit single-holder release and separate creation completion from route identity.
  • D-91 / ADR-0092: use exact Kotlin-matching common-enum export names because no current Swift source consumes the pre-E1-07 module-derived names.
  • Android saveable draft text and raw odometer parsing remain host-private and do not expand the shared ABI.
  • D-84 through D-89 and ADR-0085 through ADR-0090 remain ratified and unchanged.
  • N-1 and N-2 add no decision or ADR; D-84 through D-91 remain ratified and unchanged.

Verification Run

  • ./gradlew :feature:vehicle:testAndroidHostTest :shared:testAndroidHostTest :core:common:testAndroidHostTest — 81 actionable tasks, successful.
  • ./gradlew :androidApp:compileDebugKotlin :androidApp:compileDebugAndroidTestKotlin — 113 actionable tasks, successful.
  • ./gradlew :androidApp:connectedDebugAndroidTest — five tests passed on E1_07_API_36.
  • ./gradlew :composition:ios:linkDebugFrameworkIosSimulatorArm64 — 69 actionable tasks, successful.
  • Exact generated-header/golden diff -u — no output.
  • Final repository verification completed after two behavior-neutral formatting corrections exposed by Detekt and KtLint; all aggregate components pass, including 16 architecture rules over 23 modules and 92 decision/ADR mirrors with none unresolved.
  • git diff --check — no output.
  • All 10 protected checks green on the final pushed commit.

Contract Impact

  • No contract changes
  • D-90 updates docs/CONTRACTS.md for savedVehicleId and keyed Swift holder release.
  • D-91 lists the exact common-enum Swift and Objective-C names.

Decision Board Impact

  • No decision changes
  • Added D-90 / ADR-0091 and D-91 / ADR-0092 with identical required mirrors.
  • N-1/N-2 add no decision or ADR.

Shared-Write Modules Touched

  • :core:database — D-89 graph-owned lifetime correction; no schema or migration change.
  • :core:common, :feature:vehicle, :shared, :composition:ios — reviewed presentation and ABI corrections.

Project Log Entry

  • Entry appended to docs/PROJECT_LOG.md.

Human Review Gate

  • Gated documentation paths
  • Module boundaries and Swift-facing API surface
  • Final owner review required

This pull request was not merged and MUST NOT be merged by the agent.

Risks or Follow-ups

  • E3-03: DefaultAppGraph.syncController() remains staged and throws if called; E3-03 must supply the final controller.
  • Unassigned: VehicleFormStateHolder.loadedInitialOdometerKm is not refreshed after a successful edit, so a later save can still report the initial odometer as changed.
  • Unassigned: VehicleCreationTest uses the device database and accumulates Vehicles across runs instead of using hermetic storage.
  • E3-03: staged VehicleSliceRuntime.refresh() reports success even when an individual applyRemoteVehicle call fails; the final synchronization path must propagate per-item failure correctly.
  • Unassigned architecture hardening: D-28 FeaturePackageRules inspects imports only, so fully qualified forbidden usages can bypass it.
  • Unassigned presentation coverage: dedicated tests are still missing for requestDelete / confirmDelete and the restoration error branch.
  • E3-08 still owns completion of the staged Fuel, Session and Sync graph factories.
  • N-3: replace the hand-written navigation-entry lifetime observer in a future scoped correction.
  • N-4: replace the literal English invalid-odometer assertion with R.string.error_out_of_range in a future correction.

@davidru85
davidru85 deployed to cloud-runtime-verification August 30, 2026 14:57 — with GitHub Actions Active
@davidru85
davidru85 deployed to cloud-runtime-verification August 30, 2026 20:40 — with GitHub Actions Active
@davidru85

Copy link
Copy Markdown
Owner Author

Owner-review correction completed in the required TDD sequence:

  • RED ca2e225: added observable release tests for direct AppGraph.close() and transitive SwiftAppGraph.close().
  • GREEN 315751f: introduced D-89 / ADR-0090 and a :core:database-owned DatabaseHandle; all production and test factories now preserve driver ownership, and both graphs release the handle idempotently.
  • REFACTOR 352f18f: normalized the affected code, closed the graph in the construction contract test, and finalized the handoff and project log.

Owner-ratified D-84 through D-88 and ADR-0085 through ADR-0089 were not reopened or amended. The linked Shared framework header remains byte-exact with the unchanged golden.

Local final evidence:

  • Full repository verification passed: 607 actionable tasks.
  • contractCheck: 90 accepted decision/ADR mirrors, no pending assertion.
  • architectureCheck: 16 rules over 23 modules.
  • iOS framework link passed: 69 actionable tasks.
  • Exact generated-header/golden comparison and git diff --check passed.

The pull request remains human-gated and must not be merged by the agent.

@davidru85
davidru85 deployed to cloud-runtime-verification August 31, 2026 08:22 — with GitHub Actions Active
@davidru85
davidru85 deployed to cloud-runtime-verification August 31, 2026 09:16 — with GitHub Actions Active
@davidru85
davidru85 merged commit 6d4e4a6 into main Aug 31, 2026
10 checks passed
@davidru85
davidru85 deleted the story/E1-07-android-vehicle-ui branch August 31, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant