Files
recipe/.planning/phases/01-project-infrastructure-module-wiring/01-VALIDATION.md
2026-04-29 20:54:01 +02:00

7.9 KiB
Raw Blame History

phase, slug, status, nyquist_compliant, wave_0_complete, created
phase slug status nyquist_compliant wave_0_complete created
1 project-infrastructure-module-wiring draft false false 2026-04-24

Phase 1 — Validation Strategy

Per-phase validation contract derived from 01-RESEARCH.md § Validation Architecture. Phase 1 is predominantly build-level verification (Gradle tasks, file structure, grep invariants) rather than unit tests. The existing ApplicationTest.kt is the one test file extended (adds /health coverage).


Test Infrastructure

Property Value
Framework kotlin.test (commonTest) + ktor-server-test-host (JUnit 4 runner for server) + existing KMP template test stubs
Config file composeApp/src/commonTest/kotlin/ComposeAppCommonTest.kt, shared/src/commonTest/kotlin/SharedCommonTest.kt, server/src/test/kotlin/dev/ulfrx/recipe/ApplicationTest.kt (all present from template)
Quick run command ./gradlew :server:test :composeApp:jvmTest :shared:jvmTest (JVM-only, <30s)
Full suite command ./gradlew check (runs spotlessCheck + every *Test task across all targets)
Estimated runtime ~30s quick / ~35 min full (cold)

Sampling Rate

  • After every task commit: ./gradlew spotlessCheck :server:test :shared:jvmTest (fast subset, <30s)
  • After every plan wave: ./gradlew build (includes iOS framework link + Android APK)
  • Before /gsd-verify-work (phase gate): ./gradlew check + manual server /health curl + iOS simulator boot check
  • Max feedback latency: 30s (quick subset) / 5 min (full)

Per-Task Verification Map

Note: Task IDs are populated by gsd-planner when PLAN.md files are written. Each row below is the per-requirement contract the planner MUST map to at least one task's <automated> block. Rows marked "Wave 0" require a helper file to be created before task execution can verify it.

Behavior Requirement Test Type Automated Command File Exists Status
No version literals in any build.gradle.kts INFRA-01 shell grep tools/verify-no-version-literals.sh Wave 0 pending
gradle/libs.versions.toml is the single source of truth INFRA-01 grep grep -rE "libs\\.(versions|plugins|bundles)" build-logic/src/main/kotlin/ returns all version lookups catalog exists pending
Convention plugins apply without duplication INFRA-02 Gradle ./gradlew :composeApp:help :server:help :shared:help shows recipe.* in applied plugins Wave 0 (plugins don't exist yet) pending
Adding a new KMP module only needs id("recipe.kotlin.multiplatform") INFRA-02 visual refactored shared/build.gradle.kts ≤15 LOC Target Wave 2 pending
gradle.properties contains both iOS K/N flags INFRA-03 grep tools/verify-ios-flags.sh Wave 0 pending
iOS simulator build has no legacy memory-manager warnings INFRA-03 build-log ./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64 --info 2>&1 | grep -iE 'legacy|freeze|SharedImmutable' is empty Wave 2 (iOS) pending
shared/commonMain has no Ktor/Compose/SQLDelight imports INFRA-06 grep tools/verify-shared-pure.sh Wave 0 pending
shared/ package scaffold exists INFRA-06 file test -d shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared Wave 2 pending
SC1: ./gradlew build succeeds + produces iOS framework + APK ROADMAP SC1 Gradle ./gradlew build && test -f composeApp/build/outputs/apk/debug/composeApp-debug.apk && test -d composeApp/build/bin/iosSimulatorArm64/debugFramework/ComposeApp.framework Phase gate pending
SC4: each module's help shows its convention plugins ROADMAP SC4 Gradle ./gradlew :composeApp:help -q | grep 'recipe.kotlin.multiplatform' etc. Phase gate pending
Server /health returns 200 JSON {"status":"ok"} D-16 integration ./gradlew :server:test --tests "*HealthRoute*" (added to ApplicationTest.kt) Wave 0 (test update) pending
Server fails loudly if Postgres unreachable D-16 manual docker compose down; ./gradlew :server:run exits non-zero with "Database unreachable" in logs Phase gate pending
Spotless formatting clean D-10 Gradle ./gradlew spotlessCheck Per-commit pending
Koin starts without double-init D-14 Gradle test ./gradlew :composeApp:jvmTest (template test exercises App() composition path; no KoinApplicationAlreadyStartedException) Per-wave pending

Status: pending · green · red · ⚠️ flaky


Wave 0 Requirements

These assets MUST exist before any verification task can run green. The planner should place them in Wave 0 (or inside the plan that creates the infrastructure they verify).

  • tools/verify-no-version-literals.sh — greps every build.gradle.kts + build-logic/**/*.gradle.kts for a non-test numeric version literal; exits non-zero on match
  • tools/verify-shared-pure.sh — greps shared/src/commonMain/ for forbidden imports (io.ktor, androidx.compose, org.jetbrains.compose, app.cash.sqldelight); exits non-zero on match
  • tools/verify-ios-flags.sh — greps gradle.properties for kotlin.native.binary.objcDisposeOnMain=false AND kotlin.native.binary.gc=cms; exits non-zero if either is missing
  • build-logic/ scaffold — settings.gradle.kts, build.gradle.kts, and 5 src/main/kotlin/recipe.*.gradle.kts stubs
  • server/src/main/resources/application.conf — HOCON with ktor.deployment, database.url/user/password using ${?X} env overrides
  • server/src/main/resources/db/migration/.gitkeep — directory placeholder for Flyway
  • docker-compose.ymlpostgres:16 service with named volume + healthcheck
  • server/src/test/kotlin/dev/ulfrx/recipe/ApplicationTest.kt — extended with /health endpoint assertion
  • composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/di/Koin.kt + AppModule.ktinitKoin() helper + empty module
  • composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/logging/Logging.kt — Kermit setTag("recipe")
  • composeApp/src/androidMain/kotlin/dev/ulfrx/recipe/MainApplication.kt + AndroidManifest.xml registration — calls initKoin { androidContext(this) }
  • composeApp/src/iosMain/kotlin/dev/ulfrx/recipe/di/KoinIos.ktfun doInitKoin() exported for Swift
  • iosApp/iosApp/iOSApp.swift — modified to call KoinIosKt.doInitKoin() in init()

Manual-Only Verifications

Behavior Requirement Why Manual Test Instructions
iOS simulator debug launch has no legacy K/N memory-manager warnings INFRA-03 / SC3 Requires Xcode simulator boot; not scriptable from Gradle reliably on CI Run ./gradlew :composeApp:iosSimulatorArm64Test OR open iosApp.xcworkspace in Xcode, run on iPhone 15 simulator, inspect console for legacy/freeze/SharedImmutable — expect none
Hot-reload dev loop on Desktop still works post-refactor (regression check for commit c50d747) Interactive ./gradlew :composeApp:jvmRun --mainClass MainKt --auto-reload; edit App.kt, observe reload without rebuild
Server /health reachable via curl when Postgres up D-16 Requires running Postgres + server process docker compose up -d postgres, ./gradlew :server:run &, sleep 5, curl -sf http://localhost:8080/health returns {"status":"ok"}

Validation Sign-Off

  • All tasks have <automated> verify or Wave 0 dependencies
  • Sampling continuity: no 3 consecutive tasks without automated verify
  • Wave 0 covers all MISSING references (13 items listed above)
  • No watch-mode flags in any verification command
  • Feedback latency < 30s (quick) / 5min (full)
  • nyquist_compliant: true set in frontmatter after planner maps every task to a row above

Approval: pending