18 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, requirements_addressed, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | requirements_addressed | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-project-infrastructure-module-wiring | 07 | execute | 3 |
|
|
true |
|
|
|
Purpose: Phase 1 success is defined by 5 ROADMAP success criteria (SC1-SC5) and 4 phase requirements (INFRA-01/02/03/06). Plans 01-06 delivered the files and refactors; this plan PROVES they integrate cleanly. Any regression here is a phase-completion blocker.
Output: 1 .gitkeep placeholder + verification artifacts (APK + iOS framework) + proof of all 5 SCs + green ./gradlew check.
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-project-infrastructure-module-wiring/01-CONTEXT.md @.planning/phases/01-project-infrastructure-module-wiring/01-RESEARCH.md @.planning/phases/01-project-infrastructure-module-wiring/01-PATTERNS.md @.planning/phases/01-project-infrastructure-module-wiring/01-VALIDATION.md @tools/verify-no-version-literals.sh @tools/verify-shared-pure.sh @tools/verify-ios-flags.sh @CLAUDE.mdFrom Plan 01:
- tools/verify-no-version-literals.sh — greps every *.gradle.kts for version literals (exits 0 if none except build-logic/build.gradle.kts)
- tools/verify-shared-pure.sh — greps shared/src/commonMain/ for forbidden imports (exits 0 if none OR if directory absent)
- tools/verify-ios-flags.sh — greps gradle.properties for the two iOS K/N flags (exits 0 if both present)
From Plan 02:
- build-logic/ with 5 precompiled plugins applied via settings.gradle.kts pluginManagement.includeBuild
From Plan 03:
- composeApp/, shared/, server/ build.gradle.kts applying recipe.* convention plugins
From Plan 04:
- composeApp common/iOS/Android/Desktop/Wasm entry points calling initKoin() + configureLogging()
- iosApp/iosApp/iOSApp.swift calling KoinIosKt.doInitKoin()
From Plan 05:
- server Application.kt with /health + Database.migrate + ContentNegotiation + extracted configureRouting()
- server ApplicationTest.kt passing without Postgres
From Plan 06:
- docker-compose.yml with postgres:16 + matching credentials
- README.md with Local development section
Phase gate commands (from 01-VALIDATION.md § Sampling Rate):
- Quick:
./gradlew spotlessCheck :server:test :shared:jvmTest(<30s) - Per-wave:
./gradlew build(full — iOS framework link + Android APK + server JAR) - Phase gate:
./gradlew check+ manual curl + iOS simulator boot (simulator boot is a manual-only verification, 01-VALIDATION.md § Manual-Only)
The file content is zero bytes (empty). Its purpose is purely to make dev.ulfrx.recipe.shared package discoverable in git and in the IDE, ready for Phase 2+ DTO additions.
DO NOT:
- Touch or delete
shared/src/commonMain/kotlin/dev/ulfrx/recipe/Greeting.kt— template class, stays - Touch
Platform.ktorConstants.kt— template classes, stay - Add any other file under the new
shared/package - Add
expect/actualdeclarations anywhere in shared/ (Phase 2+ scope)
Note the namespace layering: shared/src/commonMain/kotlin/dev/ulfrx/recipe/ is the ROOT package (dev.ulfrx.recipe — where Constants.kt lives), and shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared/ is a SUB-package (dev.ulfrx.recipe.shared — where Phase 2+ DTOs will live). Both are valid; Phase 1 keeps the root-package template files and adds the sub-package placeholder.
test -f shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared/.gitkeep && test -d shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared && test -f shared/src/commonMain/kotlin/dev/ulfrx/recipe/Greeting.kt && test -f shared/src/commonMain/kotlin/dev/ulfrx/recipe/Constants.kt && bash tools/verify-shared-pure.sh
<acceptance_criteria>
- shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared/.gitkeep exists (file test: test -f)
- Parent directory shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared exists (directory test: test -d)
- Existing template files are preserved: shared/src/commonMain/kotlin/dev/ulfrx/recipe/Greeting.kt, Platform.kt, Constants.kt all still exist
- tools/verify-shared-pure.sh exits 0 — the .gitkeep file is not a .kt file so the grep skips it; the existing Greeting/Platform/Constants files still contain no forbidden imports
</acceptance_criteria>
Empty package scaffold created; shared/ is ready for Phase 2+ DTOs.
Execute these commands IN ORDER. Each must exit 0 before proceeding to the next.
-
Spotless apply — auto-formats Kotlin + Gradle + Markdown files across all modules using
recipe.quality's ktlint rules:./gradlew spotlessApplyExpected: exit 0. If formatting changes any file, the change is benign (whitespace/indentation normalization); the subsequent
buildstill passes. -
Invariant script: no version literals — enforces INFRA-01 SC#2:
bash tools/verify-no-version-literals.shExpected: exit 0 +
OK: no version literals outside catalog. -
Invariant script: shared/ is pure — enforces INFRA-06 SC#5:
bash tools/verify-shared-pure.shExpected: exit 0 +
OK: shared/commonMain is pure. -
Invariant script: iOS K/N flags present — enforces INFRA-03 SC#3:
bash tools/verify-ios-flags.shExpected: exit 0 +
OK: iOS binary flags present. -
Full Gradle build — enforces SC1: produces Android APK + iOS framework + server JAR:
./gradlew buildExpected: exit 0. This compiles every target (androidTarget, iosArm64, iosSimulatorArm64, jvm, wasmJs), links the iOS framework, packages the Android APK, and builds the server fat JAR.
After success, verify the two proof artifacts exist:
test -f composeApp/build/outputs/apk/debug/composeApp-debug.apk test -d composeApp/build/bin/iosSimulatorArm64/debugFramework/ComposeApp.framework -
Convention plugin applied — enforces SC4 / INFRA-02:
./gradlew :composeApp:help -q 2>&1 | grep -q 'recipe.kotlin.multiplatform' || ./gradlew :composeApp:tasks --all -q 2>&1 | grep -q 'recipe' || trueKtlint/help output verification: the
helptask for a module does not always enumerate plugins in recent Gradle versions. An alternative proof: the./gradlew buildsuccess in step 5 IS the proof thatrecipe.kotlin.multiplatformwas applied — if the plugin hadn't applied, compilation would have failed at configuration time. Record the./gradlew buildsuccess as SC4 satisfaction ifhelpoutput is ambiguous. -
Full check — enforces full-suite green (spotlessCheck + all tests):
./gradlew checkExpected: exit 0. This includes:
spotlessCheck(Spotless verification):server:test(runs the /health test from Plan 05 — no Postgres needed):composeApp:jvmTest(template test, if present):shared:jvmTest(template test, if present)- Other platform tests as declared
If any of steps 1-7 fails, report exactly which step failed, the full error output, and STOP. The failure indicates a regression in one of Plans 01-06 that needs a /gsd-plan-phase --gaps cycle.
IMPORTANT:
- Do NOT add a
docker compose up postgresstep here. The/healthtest in Plan 05 composesconfigureRouting()directly WITHOUTDatabase.migrate()— no Postgres required. The only manual-only verification in Phase 1 is iOS simulator boot (01-VALIDATION.md § Manual-Only) which is deferred to a later human review. - Do NOT run
./gradlew :server:runhere — it would callDatabase.migrate()which requires a running Postgres. That's a manual smoke check (documented in README Local development) not a CI/phase-gate check. ./gradlew spotlessApply -q && bash tools/verify-no-version-literals.sh && bash tools/verify-shared-pure.sh && bash tools/verify-ios-flags.sh && ./gradlew build -q && test -f composeApp/build/outputs/apk/debug/composeApp-debug.apk && test -d composeApp/build/bin/iosSimulatorArm64/debugFramework/ComposeApp.framework && ./gradlew check -q <acceptance_criteria>./gradlew spotlessApplyexits 0tools/verify-no-version-literals.shexits 0 (SC2)tools/verify-shared-pure.shexits 0 (SC5)tools/verify-ios-flags.shexits 0 (SC3)./gradlew buildexits 0 (SC1)composeApp/build/outputs/apk/debug/composeApp-debug.apkexists (SC1 Android artifact)composeApp/build/bin/iosSimulatorArm64/debugFramework/ComposeApp.frameworkdirectory exists (SC1 iOS artifact)./gradlew checkexits 0 (full-suite verification — includes spotlessCheck + all tests including /health)- The
./gradlew buildsuccess implicitly proves SC4 (convention plugins applied) — ifrecipe.kotlin.multiplatformhadn't applied, the build would have failed during module configuration - No
BUILD FAILEDstring appears in the transcript </acceptance_criteria> Phase 1 green — all 5 SCs and all 4 phase requirements (INFRA-01/02/03/06) verified by automated commands.
<threat_model>
Trust Boundaries
| Boundary | Description |
|---|---|
| Developer host → Gradle daemon | Same process; Gradle executes precompiled plugin code from build-logic/ with full project access by design. |
| Gradle build → Maven Central + Gradle Plugin Portal + Google | First ./gradlew build downloads new artifacts (Koin, Kermit, Spotless, Flyway, Postgres JDBC, ktor content-negotiation, kotlinx-serialization). All versions pinned via catalog (Plan 01). |
| iOS framework link → K/N compiler | Uses the two binary flags from gradle.properties (gc=cms, objcDisposeOnMain=false). Verified by tools/verify-ios-flags.sh (infrastructure check) + deferred iOS simulator boot check (manual). |
STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|---|---|---|---|---|
| T-01-07-01 | Denial of Service | ./gradlew build downloading fresh deps, causing slow first-build |
accept | First build may take 2-5 minutes as Koin/Kermit/Flyway/Postgres JDBC artifacts download (~80 MB per 01-RESEARCH.md § Runtime State Inventory). Subsequent builds use Gradle cache. Not a threat — just an expectation. |
| T-01-07-02 | Tampering (supply chain) | Malicious transitive dep snuck in via new library | mitigate | Every new dep is pinned via catalog (Plan 01). Gradle verification metadata (gradle/verification-metadata.xml) is NOT enabled in Phase 1 — it's a future enhancement (Phase 11 CI setup). Risk accepted for Phase 1 single-dev local-build scope. |
| T-01-07-03 | Destruction | Stale build/ cache from template's js target outputs |
mitigate | 01-RESEARCH.md § Runtime State Inventory notes developers should ./gradlew clean once after Phase 1 to flush stale js target outputs. Task 2's ./gradlew build will still succeed (Gradle ignores orphaned outputs), but developers may see bloated build/ until a clean. README Local development section's ./gradlew check implicitly clears enough; full clean is a nice-to-have. |
| T-01-07-04 | Information Disclosure | ./gradlew build log leaking env variables to console |
accept | Server-side env vars (DATABASE_URL etc.) are only read at server boot, not during ./gradlew build. The /health test composes routing without the DB. No secrets logged during build. |
| </threat_model> |
Hard gate commands (all must exit 0):
./gradlew spotlessApply— auto-formattools/verify-no-version-literals.sh— SC2 / INFRA-01tools/verify-shared-pure.sh— SC5 / INFRA-06tools/verify-ios-flags.sh— SC3 / INFRA-03./gradlew build— SC1, implicitly SC4 / INFRA-02./gradlew check— full-suite (spotlessCheck + all tests)
Manual-only verifications (deferred per 01-VALIDATION.md § Manual-Only — NOT in Task 2 <automated>):
- iOS simulator debug launch without legacy memory-manager warnings (requires Xcode + simulator)
- Hot-reload dev loop on Desktop (interactive)
- Server
/healthreachable via curl when Postgres is up (requiresdocker compose up -d postgres+./gradlew :server:run)
These manual checks are recommended for the developer to run once; they are NOT gate-blocking for automated Phase 1 completion.
<success_criteria>
shared/src/commonMain/kotlin/dev/ulfrx/recipe/shared/.gitkeepcreated./gradlew spotlessApplygreen- All 3
tools/verify-*.shscripts green ./gradlew buildgreen + Android APK + iOS framework artifacts exist./gradlew checkgreen- No manual step required to pass this plan </success_criteria>
Include in the summary a brief "Manual smoke checks to run later" list pointing at 01-VALIDATION.md § Manual-Only:
- iOS simulator boot without legacy-MM warnings
- Desktop hot-reload regression check
- docker compose up postgres + server /health curl smoke test