---
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 <automated> 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 `<worktree_branch_check>` 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 `<verification>` 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*
