Commit Graph

88 Commits

Author SHA1 Message Date
59d069591b test(01-05): rewrite ApplicationTest to assert GET /health without Postgres
- Replace testRoot template assertion with 'health endpoint returns 200 with status ok'
- Compose only configureRouting() in testApplication — NOT Application.module()
- This keeps the test independent of Database.migrate / running Postgres (D-11 test invariant)
- Install ContentNegotiation { json() } inside application { } — production module() does it,
  but the test composes routing directly and must install the plugin itself
- All imports explicit (D-11 allWarningsAsErrors); no wildcards
- Body checked via substring for "status" + "ok" — robust to JSON field ordering

Note: ./gradlew :server:test runtime verification deferred to Plan 07 (integration build)
since build-logic/recipe.jvm.server plugin is being authored in parallel Plan 02 worktree.
2026-04-24 18:23:14 +02:00
60221f66a2 feat(01-02): wire build-logic into root settings + add spotless/flyway classloader hints
- settings.gradle.kts: includeBuild("build-logic") placed inside pluginManagement { } (PITFALL #9)
- build.gradle.kts: 2 new alias(...) apply false entries (spotless, flywayPlugin)
- Existing repositories, module includes, and 8 original apply-false entries preserved verbatim
2026-04-24 18:22:56 +02:00
37f6191523 feat(01-04): wire JVM + Wasm main + Swift iOSApp to bootstrap Koin + Kermit
- Desktop main() calls configureLogging() → initKoin() before application { Window { App() } }
- Wasm main() calls configureLogging() → initKoin() before ComposeViewport { App() } (PITFALL #8 future-proof)
- iOSApp.swift imports ComposeApp and calls KoinIosKt.doInitKoin() in init() — single iOS call site (PITFALL #4)
- MainViewController.kt and App.kt unmodified (anti-pattern guards)
2026-04-24 18:22:47 +02:00
f691400f2b docs(01-06): add Local development section and drop js target
- New "Local development" section documents docker compose + gradlew dev loop
- Covers /health smoke test, env-var overrides (DATABASE_* and PORT)
- Adds spotlessApply + check + down -v reference commands
- Removes legacy js target docs (D-01); wasmJs target preserved
2026-04-24 18:22:41 +02:00
daefe6c26d refactor(01-05): rewrite Application.kt with ContentNegotiation, Flyway boot, /health
- Remove wildcard Ktor imports (D-11 allWarningsAsErrors safety) — all imports explicit
- Install ContentNegotiation { json() } for @Serializable response bodies
- Call Database.migrate(this) at boot — fails loudly if Postgres unreachable
- Extract configureRouting() extension so tests can compose routing without DB
- Replace template root greeting with GET /health → {"status":"ok"} (D-16)
- main() shape unchanged: embeddedServer(Netty, SERVER_PORT, "0.0.0.0", ...)
2026-04-24 18:22:37 +02:00
d316a4805e refactor(01-03): apply recipe.jvm.server + recipe.quality to server module
- Replaces alias(kotlinJvm) + alias(ktor) + application with id("recipe.jvm.server") + id("recipe.quality") — application plugin now applied by the convention
- Removes per-module dep lines (logback, ktor-serverCore, ktor-serverNetty, ktor-serverTestHost, kotlin-testJunit) — all bundled in recipe.jvm.server
- Keeps module-only config: group/version coordinates, application { mainClass.set } + applicationDefaultJvmArgs, implementation(projects.shared)
- File shrinks 23 -> 18 lines; no version literals leak
2026-04-24 18:22:09 +02:00
24018efe67 feat(01-05): add HOCON config, Flyway migration dir, fail-loud Database.migrate
- application.conf: HOCON with ktor.deployment.port (8080 + ${?PORT}) and
  database.url/user/password (localhost defaults + ${?DATABASE_URL/USER/PASSWORD})
- db/migration/.gitkeep: placeholder so classpath:db/migration resolves
- Database.kt: object Database.migrate(app) reads HOCON config, runs Flyway
  with baselineOnMigrate + validateOnMigrate + cleanDisabled, throws
  IllegalStateException on any failure (D-16 fail-loud contract)
- SLF4J (not Kermit); server logs url+user only, never password
2026-04-24 18:22:08 +02:00
4e6192293f feat(01-04): add Android MainApplication + manifest registration
- Create MainApplication : Application() running configureLogging() then initKoin { androidContext(this@MainApplication) } in onCreate
- Register android:name=".MainApplication" on <application> element (MainActivity entry preserved)
- Establishes the canonical init order for Android process boot
2026-04-24 18:22:03 +02:00
6a69910aa7 feat(01-02): scaffold build-logic included build with 5 precompiled plugins
- build-logic/settings.gradle.kts resolves parent catalog via files("../gradle/libs.versions.toml")
- build-logic/build.gradle.kts declares kotlin-dsl + 9 compileOnly asDependency entries
- recipe.quality: Spotless + ktlint + D-11 allWarningsAsErrors safety net (plugins.withId guard)
- recipe.kotlin.multiplatform: D-05 target matrix (androidTarget, iosArm64, iosSimulatorArm64, jvm, wasmJs) + JVM 11/21 split + baseName "ComposeApp" + Koin/Kermit/kotlin-test deps
- recipe.compose.multiplatform: layers on recipe.kotlin.multiplatform (PITFALL #2 avoided) + hot-reload + Compose deps
- recipe.android.application: namespace dev.ulfrx.recipe + findVersion catalog accessor (PITFALL #1)
- recipe.jvm.server: Ktor + Flyway + Postgres with quoted "implementation" configs + cleanDisabled guard
2026-04-24 18:22:02 +02:00
af4428fd8a feat(01-06): add docker-compose.yml with postgres:16 for local dev
- Single postgres service pinned to postgres:16
- Credentials recipe/recipe/recipe match application.conf HOCON defaults
- Named volume recipe-pgdata for persistence across restarts
- Healthcheck via pg_isready enables docker compose up --wait usage
- No version key (modern compose v2); Authentik stays on homelab (D-17)
2026-04-24 18:21:40 +02:00
7d750af710 feat(01-04): add Koin + Kermit bootstrap commonMain + iOS bridge
- Add initKoin(config) helper wrapping startKoin { modules(appModule) } (PITFALL #4 single entry)
- Add empty appModule placeholder (D-14) — Phase 2+ extends
- Add configureLogging() setting Kermit tag "recipe" (D-15)
- Add iosMain doInitKoin() bridge — Swift-accessible as KoinIosKt.doInitKoin()
- configureLogging() always runs before initKoin() so module loading can log
2026-04-24 18:21:36 +02:00
d76dcea18d refactor(01-03): apply recipe.* conventions to composeApp + shared, drop js
- composeApp/build.gradle.kts now applies 4 recipe.* IDs (kotlin.multiplatform, compose.multiplatform, android.application, quality); removes all structural target/android/nativeDistributions blocks (114 -> 28 lines)
- shared/build.gradle.kts applies recipe.kotlin.multiplatform + recipe.quality + androidLibrary; adds explicitApi() (D-12) and KotlinNativeTarget/Framework baseName = "Shared" override (D-07 / PITFALL #10); keeps android { } block per Open Question #1
- Adds libs.koin.android to androidMain dependencies (for Plan 04's MainApplication androidContext)
- Drops js target per D-01: removes js { browser() } from both modules and deletes shared/src/jsMain/Platform.js.kt
- iosX64 remains absent per D-02
- No version literals leak; tools/verify-no-version-literals.sh + verify-shared-pure.sh both pass
2026-04-24 18:21:35 +02:00
4d9aefd4c2 docs(01-01): complete foundations plan — catalog + iOS flags + invariants
Summarizes Plan 01-01 execution:
- 3 task commits (b609cb6, d873c31, aaa8042)
- 1 Rule 3 auto-fix (refined verify-no-version-literals.sh to
  exclude top-level project-version metadata while still
  catching indented library/plugin version literals)
- Self-check PASSED (all files + commits verified)

Requirements: INFRA-01, INFRA-03
2026-04-24 18:18:20 +02:00
aaa8042aee feat(01-01): add Phase 1 invariant verification scripts
Three executable bash scripts under tools/ that Wave 0 and every
subsequent Phase 1 plan's <automated> block rely on:

- verify-no-version-literals.sh (INFRA-01 SC#2 / D-09): no literal
  library/plugin version strings in any *.gradle.kts. Excludes
  build-logic/build.gradle.kts (needs asDependency() literals) and
  top-level project-version assignments ("^version = \"x.y.z\"")
  which are artifact metadata, not library pins.
- verify-shared-pure.sh (INFRA-06 / D-19): shared/commonMain must
  not import Ktor/Compose/SQLDelight. Returns OK if the directory
  does not exist yet (pre-scaffold tolerance for Plan 07).
- verify-ios-flags.sh (INFRA-03 / D-18): both K/N iOS binary flags
  present in gradle.properties.

All three use bash (#!/usr/bin/env bash + set -euo pipefail) and
are marked chmod +x. Scripts exit 0 against the current repo state.
2026-04-24 18:16:29 +02:00
d873c31e19 feat(01-01): add iOS Kotlin/Native binary flags to gradle.properties
- kotlin.native.binary.gc=cms (concurrent mark-sweep collector)
- kotlin.native.binary.objcDisposeOnMain=false (off-main-thread
  Obj-C deinit) — avoids UI-thread pause spikes in CMP on iOS
- Enforces INFRA-03 / D-18 / CLAUDE.md convention #7 /
  PITFALLS.md #1 on day 1 before any iOS code is compiled
2026-04-24 18:14:12 +02:00
b609cb6362 feat(01-01): extend version catalog with Phase 1 aliases
- Add versions: flyway=12.4.0, kermit=2.1.0, koin=4.2.1,
  kotlinx-serialization=1.7.3, postgresql=42.7.10, spotless=8.4.0
- Add libraries: 5 koin-* (BOM-managed for -core/-compose/-
  composeViewmodel/-android), kermit, 2 ktor server-side
  (content-negotiation + kotlinx-json), 2 flyway (core + postgres
  database module), postgresql JDBC driver
- Add plugins: spotless (Diffplug) + flywayPlugin
- No existing version refs modified; additive only (D-09)
2026-04-24 18:13:49 +02:00
875055a5ef docs(state): begin Phase 1 execution
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 18:11:29 +02:00
8ef2dbfae4 chore: clear auto-chain flag before phase 1 execution
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 18:11:14 +02:00
0ca22f9e36 Plan phase 1 2026-04-24 18:08:36 +02:00
d104d3da87 refactor(01): address plan-checker revisions (1 blocker, 5 warnings)
- 01-02: wave 1→2, depends_on [01]; drop unused androidLibrary classpath
  entry; guard Kotlin compilerOptions with plugins.withId listeners
- 01-05: remove misleading 'gradle exit' echo from verify block
- 01-06: harden credential check on docker-compose.yml alone
- 01-07: drop hardcoded /Users/rwilk/dev/repo/recipe cd prefix
- 01-RESEARCH: rename Open Questions → (RESOLVED); replace
  'Recommendation:' with 'RESOLVED:' per gsd Dimension 11 convention
2026-04-24 16:40:32 +02:00
d6cec3fe07 Plan phase 1 2026-04-24 16:21:25 +02:00
7ac1555a4c docs(01): add validation strategy 2026-04-24 15:46:08 +02:00
6f9d7d7ee5 docs(01): research phase infrastructure domain
Capture Phase 1 research covering build-logic convention plugin mechanics,
Koin/Kermit bootstrap for CMP+iOS, Ktor /health + Flyway wiring, version
catalog access from precompiled plugins, iOS K/N binary flags, and
validation commands mapped to all 5 roadmap success criteria + INFRA-01/02/03/06.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 15:43:29 +02:00
9738621f77 docs(state): record phase 1 context session 2026-04-24 15:27:17 +02:00
68e4a5637a docs(01): capture phase context 2026-04-24 15:27:13 +02:00
c50d747cf6 Fix hot reload for desktop target 2026-04-24 14:11:23 +02:00
761958208e docs: update out of scope plans 2026-04-24 13:48:55 +02:00
f5a650040e docs: update household information 2026-04-24 13:37:36 +02:00
7aef40ca14 docs: add CLAUDE.md with project guidance 2026-04-24 13:14:30 +02:00
30dfb0b4e4 docs: create roadmap (11 phases) 2026-04-24 13:02:44 +02:00
2115d89ba3 docs: define v1 requirements 2026-04-24 12:58:05 +02:00
fe96b26019 docs: research summary 2026-04-24 12:56:13 +02:00
4d964d933d docs: pitfalls research 2026-04-24 12:54:05 +02:00
d8819e02f0 docs: architecture research 2026-04-24 12:48:12 +02:00
4919f9f866 chore: add project config 2026-04-24 11:47:24 +02:00
2e595705fe docs: record locked tech-stack decisions 2026-04-24 11:47:24 +02:00
0c87978547 docs: initialize project 2026-04-23 23:33:33 +02:00
bf8b46bff2 Initial commit 2026-04-23 22:50:48 +02:00