Migrate project artifacts to spec-kit format

- Move cross-cutting docs (personas, design system, implementation phases,
  Ideen.md) to .specify/memory/
- Move cross-cutting research and plans to .specify/memory/research/ and
  .specify/memory/plans/
- Extract 5 setup tasks from spec/setup-tasks.md into individual
  specs/001-005/spec.md files with spec-kit template format
- Extract 20 user stories from spec/userstories.md into individual
  specs/006-026/spec.md files with spec-kit template format
- Relocate feature-specific research and plan docs into specs/[feature]/
- Add spec-kit constitution, templates, scripts, and slash commands
- Slim down CLAUDE.md to Claude-Code-specific config, delegate principles
  to .specify/memory/constitution.md
- Update ralph.sh with stream-json output and per-iteration logging
- Delete old spec/ and docs/agents/ directories
- Gitignore Ralph iteration JSONL logs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 20:19:41 +01:00
parent 0b2b84dafc
commit 6aeb4b8bca
83 changed files with 6486 additions and 660 deletions

View File

@@ -0,0 +1,477 @@
---
date: 2026-03-04T00:19:03+01:00
git_commit: 7b460dd322359dc1fa3ca0dc950a91c607163977
branch: master
topic: "T-1: Initialize monorepo structure — Tech stack research"
tags: [research, codebase, t-1, scaffolding, spring-boot, vue, maven, vite, hexagonal-architecture]
status: complete
---
# Research: T-1 — Initialize Monorepo Structure
## Research Question
What are the current versions, scaffolding approaches, and architectural patterns needed to implement T-1 (Initialize monorepo structure) with the specified tech stack: Java (latest LTS), Spring Boot, Maven, hexagonal/onion architecture backend + Svelte with Vite frontend?
## Summary
This research covers all technical aspects needed for T-1. The spec requires a monorepo with `backend/` and `frontend/` directories, both building successfully as empty scaffolds. The key findings and open decisions are:
1. **Java 25** is the current LTS (Sep 2025). Spring Boot **4.0.3** is the latest stable — but **3.5.x** is more battle-tested. This is an architectural decision.
2. **Svelte 5** is stable (since Oct 2024). The SPA router ecosystem for plain Svelte 5 is weak — **SvelteKit in SPA mode** is the pragmatic alternative.
3. **Hexagonal architecture**: Single Maven module with package-level separation + ArchUnit enforcement. Base package `com.fete`.
4. **TypeScript** for the frontend is recommended but is a decision point.
## Detailed Findings
### 1. Java Version
**Java 25 (LTS)** — released September 16, 2025.
- Premier support through Sep 2030, extended support through Sep 2033.
- Supersedes Java 21 (Sep 2023) as the current LTS.
- Java 21 is still supported but free updates end Sep 2026.
- Next LTS: Java 29 (Sep 2027).
**Recommendation:** Java 25. Longest support runway, both Spring Boot 3.5 and 4.0 support it.
### 2. Spring Boot Version
Two actively supported lines as of March 2026:
| Version | Latest Patch | OSS Support Ends | Java Baseline | Key Dependencies |
|---------|-------------|-------------------|---------------|-----------------|
| **4.0.x** | 4.0.3 | Dec 2026 | Java 17+ (up to 25) | Spring Framework 7.0, Jakarta EE 11, Hibernate 7.1, Jackson 3.0, Tomcat 11.0 |
| **3.5.x** | 3.5.11 | Jun 2026 | Java 17+ (up to 25) | Spring Framework 6.x, Jakarta EE 10, Hibernate 6.x, Jackson 2.x, Tomcat 10.x |
**Trade-offs:**
| Factor | Spring Boot 4.0 | Spring Boot 3.5 |
|--------|----------------|-----------------|
| Support runway | Dec 2026 (longer) | Jun 2026 (shorter) |
| Ecosystem maturity | Jackson 3.0 + Hibernate 7.1 are new major versions; fewer community examples | Battle-tested, large ecosystem of examples |
| Migration burden | None (greenfield) | None (greenfield) |
| Forward-looking | Yes | Will need migration to 4.x eventually |
**Decision needed:** Spring Boot 4.0 (forward-looking) vs. 3.5 (more battle-tested). Both support Java 25.
### 3. Maven
- **Maven version:** 3.9.12 (latest stable; Maven 4.0.0 is still RC).
- **Maven Wrapper:** Yes, include it. Modern "only-script" distribution — no binary JAR in repo. Scripts `mvnw`/`mvnw.cmd` + `.mvn/wrapper/maven-wrapper.properties` are committed.
- Benefits: deterministic builds in Docker, no Maven pre-install requirement for contributors or CI.
**Minimal dependencies for Spring Boot + PostgreSQL:**
```xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.3</version> <!-- or 3.5.11 -->
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
```
Note: For the empty scaffold (T-1), JPA autoconfig must be excluded or deferred since there's no DB yet. Either omit `spring-boot-starter-data-jpa` until T-4, or add `spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration` to `application.properties`.
### 4. Svelte + Vite Frontend
**Current versions:**
- Svelte: **5.53.6** (stable since Oct 2024, runes-based reactivity)
- Vite: **7.3.1** (stable; Vite 8 is in beta)
**Svelte 5 key changes from Svelte 4:**
- Reactive state: `let count = $state(0)` (explicit rune) instead of implicit `let count = 0`
- Derived values: `$derived()` replaces `$:` blocks
- Props: `$props()` replaces `export let`
- Reactivity works in `.svelte.ts` files too (not just components)
### 5. SvelteKit vs. Plain Svelte — Decision Point
The spec says "Svelte with Vite as bundler" for an SPA with a separate REST backend.
**Option A: Plain Svelte + Vite + third-party router**
| Pro | Con |
|-----|-----|
| Simpler mental model | Router ecosystem broken for Svelte 5: `svelte-spa-router` has no Svelte 5 support (issue #318) |
| Literal spec wording | Only unmaintained/low-adoption alternatives exist |
| No unused SSR concepts | Violates dependency statute ("actively maintained") |
**Option B: SvelteKit in SPA mode (adapter-static + `ssr: false`)**
| Pro | Con |
|-----|-----|
| Built-in file-based routing (maintained by Svelte team) | Has SSR concepts that exist but are unused |
| First-class Vitest integration (T-4 requirement) | Slightly larger framework footprint |
| SPA config is 3 lines of code | SEO concerns (irrelevant for this app) |
| Output is static HTML/JS/CSS — no Node.js runtime needed | |
| `npx sv create` scaffolds TS/ESLint/Vitest in one step | |
**SPA configuration (total effort):**
1. `npm i -D @sveltejs/adapter-static`
2. `svelte.config.js`: `adapter: adapter({ fallback: '200.html' })`
3. `src/routes/+layout.js`: `export const ssr = false;`
**Decision needed:** SvelteKit in SPA mode (pragmatic, solves the router problem) vs. plain Svelte + Vite (minimalist, but router ecosystem is a real problem).
### 6. TypeScript vs. JavaScript — Decision Point
**Arguments for TypeScript:**
- Java backend is strongly typed; TS catches API contract drift at compile time.
- Svelte 5 has first-class TS support, including TS in markup.
- The API client layer (T-4) benefits most from type safety.
- Zero-config in both SvelteKit and the `svelte-ts` Vite template.
- Rich Harris: "TypeScript for apps, JSDoc for libraries." This is an app.
**Arguments against:**
- KISS/grugbrain principle — TS adds cognitive overhead.
- Svelte's compiler already catches many errors.
**Verdict from research:** TS overhead in Svelte 5 is minimal (`let count: number = $state(0)` vs. `let count = $state(0)`). The real value is in the API client layer and shared types.
### 7. Node.js Version
| Version | Status | End of Life |
|---------|--------|-------------|
| Node.js 24 | Active LTS | ~April 2028 |
| Node.js 22 | Active LTS | April 2027 |
| Node.js 20 | Maintenance LTS | April 2026 (EOL imminent) |
**Recommendation:** Target Node.js 22 LTS as minimum. Docker image should use `node:22-alpine`.
### 8. Hexagonal Architecture — Package Structure
**Approach:** Single Maven module with package-level separation. Multi-module Maven is overkill for a small app. ArchUnit test enforces dependency rules.
**Package structure:**
```
com.fete
├── FeteApplication.java # @SpringBootApplication
├── domain/
│ ├── model/ # Entities, value objects (plain Java, no framework annotations)
│ └── port/
│ ├── in/ # Driving port interfaces (use cases)
│ └── out/ # Driven port interfaces (repositories)
├── application/
│ └── service/ # Use case implementations (@Service)
├── adapter/
│ ├── in/
│ │ └── web/ # REST controllers, DTOs, mappers
│ └── out/
│ └── persistence/ # JPA entities, Spring Data repos, mappers
└── config/ # @Configuration classes
```
**Dependency flow (strict):**
```
domain → nothing
application → domain only
adapter → application + domain
config → everything (wiring)
```
**Spring annotations by layer:**
| Layer | Annotations | Rationale |
|-------|-------------|-----------|
| `domain.model` | None | Plain Java — no framework coupling |
| `domain.port` | None | Plain Java interfaces |
| `application.service` | `@Service` only | Pragmatic compromise for component scanning |
| `adapter.in.web` | `@RestController`, `@GetMapping`, etc. | Framework adapter layer |
| `adapter.out.persistence` | `@Entity`, `@Repository`, `@Table`, etc. | Framework adapter layer |
| `config` | `@Configuration`, `@Bean` | Wiring layer |
**Domain purity:** Persistence has its own JPA entity classes (e.g., `EventJpaEntity`) separate from domain model classes. Mappers convert between them.
**Empty directory markers:** Use `package-info.java` in each leaf package. Documents package purpose, allows Git to track the directory, and aids component scanning.
**Base package:** `com.fete` (Maven convention, clean, short).
### 9. .gitignore
The existing `.gitignore` covers IDE files (`.idea/`, `.vscode/`, `*.iml`), OS files (`.DS_Store`, `Thumbs.db`), and Claude settings. The following sections need to be added:
**Java/Maven:**
- `*.class`, `*.jar`, `*.war`, `*.ear`, `*.nar` — compiled artifacts
- `target/` — Maven build output
- Maven release plugin files (`pom.xml.tag`, `pom.xml.releaseBackup`, etc.)
- `.mvn/wrapper/maven-wrapper.jar` — downloaded automatically
- Eclipse files (`.classpath`, `.project`, `.settings/`, `.factorypath`)
- Spring Boot (`.springBeans`, `.sts4-cache`)
- Java crash logs (`hs_err_pid*`, `replay_pid*`)
- `*.log`
**Node.js/Svelte/Vite:**
- `node_modules/`
- `dist/`, `build/` — build output
- `.svelte-kit/` — SvelteKit generated files
- `vite.config.js.timestamp-*`, `vite.config.ts.timestamp-*` — Vite temp files
- `.env`, `.env.*` (but NOT `.env.example`)
- `npm-debug.log*`
**Editor files:**
- `*.swp`, `*.swo`, `*~` — Vim/editor backup files
- `\#*\#`, `.#*` — Emacs
**Committed (NOT ignored):**
- `mvnw`, `mvnw.cmd`, `.mvn/wrapper/maven-wrapper.properties`
- `package-lock.json`
### 10. Existing Repository State
The repository currently contains:
- `CLAUDE.md` — Project statutes
- `README.md` — With tech stack docs and docker-compose example
- `LICENSE` — GPL
- `.gitignore` — Partial (IDE + OS only)
- `Ideen.md` — German idea document
- `spec/` — User stories, personas, setup tasks, implementation phases
- `.ralph/` — Ralph loop infrastructure
- `ralph.sh` — Ralph loop runner
- `review-findings.md` — Review notes
No `backend/` or `frontend/` directories exist yet. No `Dockerfile` exists yet (listed in README project structure, but deferred to T-2).
## Decisions Required Before Implementation
These are architectural decisions that require approval per CLAUDE.md governance statutes:
| # | Decision | Options | Recommendation |
|---|----------|---------|----------------|
| 1 | Spring Boot version | 4.0.3 (latest, longer support) vs. 3.5.11 (battle-tested, shorter support) | 4.0.3 — greenfield project, no migration burden, longer support |
| 2 | SvelteKit vs. plain Svelte | SvelteKit SPA mode vs. plain Svelte + third-party router | SvelteKit SPA mode — router ecosystem for plain Svelte 5 is broken |
| 3 | TypeScript vs. JavaScript | TypeScript (type safety on API boundary) vs. JavaScript (simpler) | TypeScript — minimal overhead in Svelte 5, catches API contract drift |
| 4 | Spring Boot JPA in T-1? | Include `spring-boot-starter-data-jpa` now (exclude autoconfig) vs. add it in T-4 | Defer to T-4 — T-1 is "empty scaffold", JPA needs a datasource |
## Code References
- `spec/setup-tasks.md` — T-1 acceptance criteria
- `spec/implementation-phases.md:9-14` — Phase 0 task order
- `CLAUDE.md:36-43` — Dependency statutes
- `Ideen.md:76-78` — Tech stack decisions (already made)
- `.gitignore` — Current state (needs extension)
- `README.md:112-119` — Documented project structure (target)
## Architecture Documentation
### Target Repository Layout (after T-1)
```
fete/
├── backend/
│ ├── pom.xml
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── .mvn/wrapper/maven-wrapper.properties
│ └── src/
│ ├── main/
│ │ ├── java/com/fete/
│ │ │ ├── FeteApplication.java
│ │ │ ├── domain/model/ (package-info.java)
│ │ │ ├── domain/port/in/ (package-info.java)
│ │ │ ├── domain/port/out/ (package-info.java)
│ │ │ ├── application/service/ (package-info.java)
│ │ │ ├── adapter/in/web/ (package-info.java)
│ │ │ ├── adapter/out/persistence/(package-info.java)
│ │ │ └── config/ (package-info.java)
│ │ └── resources/
│ │ └── application.properties
│ └── test/java/com/fete/
│ └── FeteApplicationTest.java
├── frontend/
│ ├── package.json
│ ├── package-lock.json
│ ├── svelte.config.js
│ ├── vite.config.ts
│ ├── tsconfig.json
│ ├── src/
│ │ ├── app.html
│ │ ├── routes/
│ │ │ ├── +layout.js (ssr = false)
│ │ │ └── +page.svelte
│ │ └── lib/
│ └── static/
├── spec/
├── .gitignore (extended)
├── CLAUDE.md
├── README.md
├── LICENSE
└── Ideen.md
```
### Build Commands (Target State)
| What | Command |
|------|---------|
| Backend build | `cd backend && ./mvnw package` |
| Backend test | `cd backend && ./mvnw test` |
| Frontend install | `cd frontend && npm install` |
| Frontend build | `cd frontend && npm run build` |
| Frontend test | `cd frontend && npm test` |
| Frontend dev | `cd frontend && npm run dev` |
## Open Questions
All resolved — see Follow-up Research below.
## Follow-up Research: Frontend Pivot to Vue 3 (2026-03-04)
### Context
During decision review, the developer raised concerns about the Svelte 5 ecosystem maturity (specifically the broken third-party router situation signaling a smaller, less mature ecosystem). After comparing Svelte 5 vs Vue 3 on ecosystem size, community support, team size, and stability, the decision was made to pivot from Svelte to **Vue 3**.
### Rationale
- Vue 3 has a significantly larger ecosystem and community
- Official, battle-tested packages for all needs (Vue Router, Pinia, Vitest)
- Vite was created by Evan You (Vue's creator) — first-class integration
- Vue 3 Composition API is modern and elegant while being mature (stable since 2020)
- Larger team, broader funding, more StackOverflow answers and tutorials
### Vue 3 Stack — Research Findings
**Current versions (March 2026):**
| Package | Version | Notes |
|---------|---------|-------|
| Vue | 3.5.29 | Stable. Vue 3.6 (Vapor Mode) is in beta |
| Vue Router | 5.0.3 | Includes file-based routing from unplugin-vue-router. Drop-in from v4 for manual routes |
| Vite | 7.3.1 | Stable. Vite 8 (Rolldown) is in beta |
| Vitest | 4.0.18 | Stable. Browser Mode graduated from experimental |
| @vue/test-utils | 2.4.6 | Official component testing utilities |
| create-vue | 3.22.0 | Official scaffolding tool |
| Node.js | 24 LTS | Latest LTS, support through ~April 2028 |
**Scaffolding:** `npm create vue@latest` (official Vue CLI scaffolding). Interactive prompts offer TypeScript, Vue Router, Pinia, Vitest, ESLint, Prettier out of the box.
**Selected options for fete:**
- TypeScript: **Yes**
- Vue Router: **Yes**
- Pinia: **No** — Composition API (`ref`/`reactive`) + localStorage is sufficient for this app's simple state
- Vitest: **Yes**
- ESLint: **Yes**
- Prettier: **Yes**
- E2E testing: **No** (not needed for T-1)
**Project structure (scaffolded by create-vue):**
```
frontend/
├── public/
│ └── favicon.ico
├── src/
│ ├── assets/ # Static assets (CSS, images)
│ ├── components/ # Reusable components
│ ├── composables/ # Composition API composables (added manually)
│ ├── router/ # Vue Router config (index.ts)
│ ├── views/ # Route-level page components
│ ├── App.vue # Root component
│ └── main.ts # Entry point
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.node.json
├── vite.config.ts
├── eslint.config.js
├── .prettierrc.json
├── env.d.ts
└── README.md
```
**Key conventions:**
- `src/views/` for route page components (not `src/pages/` — that's Nuxt)
- `src/components/` for reusable components
- `src/composables/` for Composition API composables (e.g., `useStorage.ts`)
- `src/router/index.ts` for route definitions
### Resolved Decisions
| # | Decision | Resolution |
|---|----------|------------|
| 1 | Spring Boot version | ~~**4.0.3**~~**3.5.11** — see addendum below |
| 2 | Frontend framework | **Vue 3** — pivot from Svelte due to ecosystem maturity concerns |
| 3 | TypeScript | **Yes** — confirmed by developer |
| 4 | Node.js version | **24 LTS** (latest LTS) |
| 5 | Base package | **`de.fete`** (not `com.fete`) |
| 6 | JPA in T-1 | **Defer to T-4** — T-1 is empty scaffold, JPA needs a datasource |
| 7 | State management | **No Pinia** — Composition API + localStorage sufficient |
### Addendum: Spring Boot 4.0 → 3.5 Pivot (2026-03-04)
During T-1 implementation, Spring Boot 4.0.3 proved unworkable for the scaffold phase. The 4.0 release massively reorganized internal packages — test infrastructure classes (`TestRestTemplate`, `AutoConfigureMockMvc`, etc.) were moved into new modules with different package paths. The Spring Boot 4.0 Migration Guide did not cover these changes adequately, and resolving the issues required extensive trial-and-error with undocumented class locations and missing transitive dependencies.
**Decision:** Pivot to **Spring Boot 3.5.11** (latest 3.5.x patch). This is the battle-tested line with OSS support through June 2026. Since this is a greenfield project, migrating to 4.x later (once the ecosystem and documentation have matured) is straightforward.
**Impact:** None on architecture or feature scope. The hexagonal package structure, dependency choices, and all other decisions remain unchanged. Only the Spring Boot parent version in `pom.xml` changed.
### Updated Target Repository Layout
```
fete/
├── backend/
│ ├── pom.xml
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── .mvn/wrapper/maven-wrapper.properties
│ └── src/
│ ├── main/
│ │ ├── java/de/fete/
│ │ │ ├── FeteApplication.java
│ │ │ ├── domain/model/ (package-info.java)
│ │ │ ├── domain/port/in/ (package-info.java)
│ │ │ ├── domain/port/out/ (package-info.java)
│ │ │ ├── application/service/ (package-info.java)
│ │ │ ├── adapter/in/web/ (package-info.java)
│ │ │ ├── adapter/out/persistence/(package-info.java)
│ │ │ └── config/ (package-info.java)
│ │ └── resources/
│ │ └── application.properties
│ └── test/java/de/fete/
│ └── FeteApplicationTest.java
├── frontend/
│ ├── public/
│ ├── src/
│ │ ├── assets/
│ │ ├── components/
│ │ ├── composables/
│ │ ├── router/index.ts
│ │ ├── views/
│ │ ├── App.vue
│ │ └── main.ts
│ ├── index.html
│ ├── package.json
│ ├── package-lock.json
│ ├── tsconfig.json
│ ├── vite.config.ts
│ └── eslint.config.js
├── spec/
├── .gitignore (extended)
├── CLAUDE.md
├── README.md
├── LICENSE
└── Ideen.md
```