diff --git a/.planning/phases/01-project-infrastructure-module-wiring/01-01-SUMMARY.md b/.planning/phases/01-project-infrastructure-module-wiring/01-01-SUMMARY.md new file mode 100644 index 0000000..9861801 --- /dev/null +++ b/.planning/phases/01-project-infrastructure-module-wiring/01-01-SUMMARY.md @@ -0,0 +1,154 @@ +--- +phase: 01-project-infrastructure-module-wiring +plan: 01 +subsystem: infra +tags: [gradle, version-catalog, kotlin-native, ios-binary-flags, bash, invariants, koin, kermit, flyway, postgresql, spotless, ktor] + +# Dependency graph +requires: [] +provides: + - Gradle version catalog extended with Koin (BOM + core/compose/composeViewmodel/android), Kermit, Spotless, Flyway (core + postgresql), Postgres JDBC, Ktor content-negotiation + kotlinx-json serializer + - kotlinx-serialization = 1.7.3 version alias (kept even though no library wires it in Plan 01 — Phase 2+ wire Ktor plugins using this pin) + - iOS K/N binary flags kotlin.native.binary.gc=cms + kotlin.native.binary.objcDisposeOnMain=false in gradle.properties + - tools/verify-no-version-literals.sh (D-09 invariant check) + - tools/verify-shared-pure.sh (INFRA-06 / D-19 invariant check — tolerant of pre-scaffold shared/commonMain) + - tools/verify-ios-flags.sh (INFRA-03 / D-18 invariant check) +affects: [01-02-build-logic, 01-03-module-wiring, 01-04-compose-app, 01-05-server, 01-06-shared, 01-07-validation, 02-auth, 10-ui-chrome, 11-localization-deployment] + +# Tech tracking +tech-stack: + added: + - Koin 4.2.1 (BOM + 4 consumed modules) + - Kermit 2.1.0 + - Spotless 8.4.0 (plugin) + - Flyway 12.4.0 (core + database-postgresql module + Gradle plugin) + - PostgreSQL JDBC 42.7.10 + - Ktor server content-negotiation + kotlinx-json serializer (version.ref = existing ktor 3.4.1) + - kotlinx-serialization = 1.7.3 version alias (no library entry yet — pre-wire for ktor serializer which derives its version from ktor) + patterns: + - "Catalog-only versioning: no numeric version literals in *.gradle.kts outside build-logic/ (D-09 / INFRA-01 SC#2)" + - "BOM-managed Koin libs omit version.ref (koin-core/koin-compose/koin-composeViewmodel/koin-android pinned via koin-bom)" + - "Fail-loud shell invariants under tools/ — every Phase 1 plan's block calls one of these three scripts" + +key-files: + created: + - tools/verify-no-version-literals.sh + - tools/verify-shared-pure.sh + - tools/verify-ios-flags.sh + modified: + - gradle/libs.versions.toml + - gradle.properties + +key-decisions: + - "Refined verify-no-version-literals.sh to exclude top-level project-version assignments (^version = \"x.y.z\") — these are Gradle artifact metadata, not library-version pins. D-09 guards dependencies, not project identity. server/build.gradle.kts:8 keeps its project version." + +patterns-established: + - "Pattern 1: All Phase 1+ library/plugin versions declared ONLY in gradle/libs.versions.toml; build scripts reference via libs.* accessors" + - "Pattern 2: iOS Kotlin/Native binary flags live in gradle.properties — single file, compiler reads verbatim at link time" + - "Pattern 3: Invariant checks as bash scripts under tools/; shebang #!/usr/bin/env bash; set -euo pipefail; fail-loud on violation, silent-pass on clean" + - "Pattern 4: Pre-scaffold tolerance — verify-shared-pure.sh exits 0 if shared/src/commonMain doesn't exist (lets invariant scripts run before Plan 07 scaffolds)" + +requirements-completed: [INFRA-01, INFRA-03] + +# Metrics +duration: 4min +completed: 2026-04-24 +--- + +# Phase 01 Plan 01: Foundations Summary + +**Gradle version catalog extended with 6 versions / 11 libraries / 2 plugins (Koin + Kermit + Spotless + Flyway + Postgres + Ktor content-negotiation), iOS K/N binary flags (gc=cms + objcDisposeOnMain=false) added to gradle.properties, and three tools/verify-*.sh invariant scripts shipped — the foundation every remaining Phase 1 plan leans on.** + +## Performance + +- **Duration:** 4 min +- **Started:** 2026-04-24T16:12:45Z +- **Completed:** 2026-04-24T16:16:53Z +- **Tasks:** 3 +- **Files modified:** 2 (catalog + gradle.properties) +- **Files created:** 3 (tools/verify-*.sh) + +## Accomplishments + +- **Version catalog now covers every Phase 1+ library and plugin**, including BOM-managed Koin modules (omitting `version.ref` by design) and fine-grained Ktor server-side JSON plumbing. No existing version ref was bumped; additive-only per D-09. +- **iOS K/N binary flags wired on day 1** (gc=cms + objcDisposeOnMain=false), closing PITFALL #1 before any iOS framework is linked. +- **Three invariant scripts ship green** — `verify-ios-flags.sh`, `verify-shared-pure.sh`, `verify-no-version-literals.sh` — exit 0 against current repo state, ready to gate every subsequent plan's automated checks. + +## Task Commits + +Each task committed atomically on this worktree branch: + +1. **Task 1: Extend gradle/libs.versions.toml with Phase 1 aliases** — `b609cb6` (feat) +2. **Task 2: Append iOS K/N binary flags to gradle.properties** — `d873c31` (feat) +3. **Task 3: Create verify-*.sh invariant scripts under tools/** — `aaa8042` (feat) + +_No TDD for this plan — all tasks are config/scaffold, not behavior._ + +## Files Created/Modified + +### Created +- `tools/verify-no-version-literals.sh` — Grep `*.gradle.kts` for `version = "[0-9]..."`; skip `build-logic/build.gradle.kts` (legitimate plugin-dep literals) and top-level project-version assignments (artifact metadata, not library pins). +- `tools/verify-shared-pure.sh` — Grep `shared/src/commonMain/` for imports from `io.ktor`, `androidx.compose`, `org.jetbrains.compose`, `app.cash.sqldelight`. Exits 0 if the directory doesn't exist yet (Plan 07 hasn't scaffolded it). +- `tools/verify-ios-flags.sh` — Grep `gradle.properties` for both K/N flags; fail with a clear MISSING: line if either absent. + +### Modified +- `gradle/libs.versions.toml` — +6 versions (flyway, kermit, koin, kotlinx-serialization, postgresql, spotless); +11 libraries (5 koin-*, kermit, 2 ktor-server-*, 2 flyway-*, postgresql); +2 plugins (spotless, flywayPlugin). 24 / 33 / 10 totals after edit. +- `gradle.properties` — +5 lines (blank separator + comment + comment + 2 K/N flags) appended after existing Android block. Original 10 lines unchanged. + +## Decisions Made + +- **Refined verify-no-version-literals.sh script semantics** — The plan's canonical script (from 01-RESEARCH.md lines 1174–1218 and 01-PATTERNS.md lines 446–490) excluded only `build-logic/build.gradle.kts`. Running it against the current repo tripped on `server/build.gradle.kts:8: version = "1.0.0"` — the Ktor template's project-version property. Per D-09, the invariant targets **library/plugin** version literals, not project/artifact metadata. I added a second, narrow exclusion: lines where the matched `version = "..."` begins at column 0 (unindented project-version assignments). Library and plugin version literals always appear inside a `dependencies { }` or `plugins { }` block and are therefore indented, so they remain caught. Sanity-check: the script still flags a synthetic `dependencies { implementation("x:y") { version = "9.9.9" } }` as a violation. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] Refined verify-no-version-literals.sh to not fire on project-version metadata** +- **Found during:** Task 3 (running the script for the first time) +- **Issue:** The canonical script in the plan (quoted verbatim from 01-RESEARCH.md) exit-1'd on `server/build.gradle.kts:8: version = "1.0.0"`. That line is the Gradle project-version property (artifact name metadata), not a library-version pin. The plan's acceptance criterion ("`bash tools/verify-no-version-literals.sh` exits 0 today") cannot be satisfied without either removing the project version or refining the script. D-09 (CONTEXT.md line 32) says the rule is "no library versions outside catalog" — project version is out of scope for D-09. +- **Fix:** Added a second `grep -v` to exclude lines matching `:[0-9]+:version[[:space:]]*=[[:space:]]*"[0-9]` (unindented top-level project-version). Library/plugin version literals in Gradle DSL are always indented inside a block, so they remain caught. Updated the script's header comment to document the refinement rationale. +- **Files modified:** `tools/verify-no-version-literals.sh` +- **Verification:** Script exits 0 against current repo state; synthetic indented `version = "9.9.9"` test case still trips the script with exit 1. Both conditions tested. +- **Committed in:** `aaa8042` (Task 3 commit — the refined script is the only shipped version; no redundant fix-up commit). + +--- + +**Total deviations:** 1 auto-fixed (Rule 3 — blocking) +**Impact on plan:** Minimal. The refinement strengthens the script's semantic correctness (targets library/plugin pins, not project identity). Success criteria and all acceptance criteria still pass. No additional tasks; no scope creep. + +## Issues Encountered + +- **Initial worktree base mismatch** — Worktree branch HEAD was `0ca22f9e` (a later commit in the worktree's own history), not the expected `875055a` base. The `` guard caught it and reset to `875055a` before any work. All three task commits therefore sit cleanly on the required base. +- **Planner arithmetic off-by-one** — Plan success criteria say "10 new [libraries] entries"; the plan's own enumeration lists 11 (5 koin + kermit + 2 ktor + 2 flyway + postgresql). I shipped all 11 explicitly named entries. This is a planner-side typo, not a deviation. + +## User Setup Required + +None. This plan is pure build configuration — no secrets, no external services, no dashboard config. + +## Next Phase Readiness + +- **Plan 02 (build-logic/) unblocked** — `VersionCatalogsExtension.named("libs").findLibrary("koin-core")` etc. will resolve in precompiled plugins; every alias the downstream plans need is now present. +- **Plan 03+ module build files unblocked** — modules can reference `libs.koin.core`, `libs.kermit`, `libs.ktor.serverContentNegotiation`, `libs.flyway.core`, `libs.flyway.database.postgresql`, `libs.postgresql` via type-safe accessors. +- **Plan 07 (validation) unblocked** — the three `tools/verify-*.sh` scripts are the Wave 0 gate it enumerates. +- **No blockers.** `./gradlew build` is NOT expected to pass until Plan 02 wires up `build-logic/` and Plan 03 refactors module build scripts — that's by design and stated in this plan's `` block. + +## Self-Check: PASSED + +Verification of claims in this summary: + +**Created files exist:** +- `tools/verify-no-version-literals.sh` — FOUND + executable +- `tools/verify-shared-pure.sh` — FOUND + executable +- `tools/verify-ios-flags.sh` — FOUND + executable + +**Commits exist in branch history:** +- `b609cb6` — FOUND (feat(01-01): extend version catalog with Phase 1 aliases) +- `d873c31` — FOUND (feat(01-01): add iOS Kotlin/Native binary flags to gradle.properties) +- `aaa8042` — FOUND (feat(01-01): add Phase 1 invariant verification scripts) + +**All three invariant scripts exit 0 against the current repo state.** All success criteria from the plan pass. + +--- + +*Phase: 01-project-infrastructure-module-wiring* +*Completed: 2026-04-24*