Wire project infrastructure

This commit is contained in:
2026-04-24 15:27:17 +02:00
parent 68e4a5637a
commit 015d8d51d0
66 changed files with 7276 additions and 211 deletions

View File

@@ -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 <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 11741218 and 01-PATTERNS.md lines 446490) 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*