AI Coding Agents on Spring Projects: Live Pipelines, Verifiable Loops, and Context Governance#
Abstract: For engineers already shipping services on the JVM and web stacks, this article starts from a typical Spring Boot + Kotlin real-time interactive application, traces the data path from database signals through reactive SSE to the browser, and breaks human–agent collaboration into three verifiable layers: compile-and-test closure, versioned project memory (CLAUDE.md / rules / Skills), and Hooks and MCP on the tool-call path. The second half covers gaps in tests and state machines caused by spec-less iteration, how structured clarification (Interview) writes navigation and security decisions into the specification, and how cross-cutting steps can be silently dropped in long conversations—with ideas for segmented execution. The concrete demo project named in the article refers to an example shown in public slide materials; line-by-line correspondence with third-party repositories is not verified here.
1. Case context: projector real-time interaction and common stack combinations#
(1) Rationale and motivation
Such scenarios usually combine a large display, mobile participation, and time-bound interaction: an administrator starts a round, participants join via QR code, consume a “reaction budget” while viewing projected content under a timer, and rankings are revealed across categories. Implementation goals often include low-latency signal fan-out (many clients subscribing to one event source) and server rendering or progressive enhancement (e.g., HTMX) to limit front-end complexity.
(2) Implementation levers
Public materials repeatedly anchor on: Spring Boot, Kotlin, jOOQ, HTMX. Kotlin entry points typically use runApplication<Application>(*args); under Boot, jOOQ connects the SQL generation layer via auto-configured DSLContext and datasource dialect properties (see Spring Boot reference — Using jOOQ); on the browser side, HTMX’s SSE extension can connect to the push endpoint using EventSource semantics (see htmx SSE extension).
(3) How to use it
@SpringBootApplication
class DemoApplication
fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}
Kotlin and Spring Boot integration constraints (plugins, runApplication, etc.) follow the official chapter (Spring Boot — Kotlin support).

Caption: The slide title area shows English text—“A photo reaction game on a beamer. The manager starts a round, quests join via QR code.”—with German UI wording (e.g., Ergebnisse), illustrating the interaction shape of the demo product rather than a fixed open-source repo version.
2. Conventions, compile feedback, and tests: the agent collaboration “closed loop”#
(1) Rationale and motivation
Clear layering (Controller / Service / Repository) and widespread annotation usage help automated assistants find extension points in unfamiliar repos; more importantly, a single Gradle compile or test run surfaces type and integration errors, turning guesses into machine-checkable signals—consistent with headless CLI, Hooks, and CI narratives below.
(2) Implementation levers
The Kotlin Gradle plugin exposes standard task names compileKotlin / compileTestKotlin (see Kotlin Gradle compiler options). The web layer can combine @SpringBootTest (Spring Boot testing), MockMvc (MockMvc overview), and Testcontainers (Spring Boot and Testcontainers; project home at Testcontainers for Java).
(3) How to use it
./gradlew compileKotlin compileTestKotlin test
3. PostgreSQL NOTIFY, WebFlux, and browser SSE#
(1) Rationale and motivation
Database NOTIFY delivers payloads on a given channel to sessions that have executed LISTEN, suitable as a lightweight internal event bus (PostgreSQL NOTIFY). Spring WebFlux can expose Flux<ServerSentEvent> as text/event-stream, consumed by the browser’s EventSource (ServerSentEvent JavaDoc; MediaType.TEXT_EVENT_STREAM constant; MDN — EventSource). The slide case sketches listener threads, Reactor sinks, and polling intervals together; those wiring details are illustrative architecture, not the only canonical pattern for Postgres or Spring.
(2) Implementation levers
The main chain (matching slide English): pg_notify → notification service → Reactor sink → Flux<ServerSentEvent> → HTTP SSE; the browser side is labeled EventSource / HTMX. Implementations may swap JDBC polling for R2DBC, etc., but produces = TEXT_EVENT_STREAM_VALUE and the reactive return type remain the core WebFlux SSE API surface.
(3) How to use it
@GetMapping(path = ["/api/sse/slideshow"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun slideshow(): Flux<ServerSentEvent<String>> = slideshowEvents()
const es = new EventSource("/api/sse/slideshow");
es.onmessage = (ev) => console.log(ev.data);


Caption: The terminal summary states The project uses PostgreSQL LISTEN/NOTIFY as the event transport, with Spring WebFlux Flux streams delivering events to browsers. and lists steps “Guest uploads photo > pg_notify > SlideshowNotificationService > Reactor Sink > SSE stream.”

Caption: The same overview shows “Guest uploads photo » pg_notify » SlideshowNotificationService » Reactor Sink > SSE stream” and the architecture line “Spring Controller (Flux
4. Subagents, summary backflow, and headless snapshot retrieval#
(1) Rationale and motivation
Heavy code exploration burns tokens; moving study work into a separate subagent context and letting only structured summaries return to the main session reduces the risk of crowding out early information in the main window. Documentation covers subagents, model routing, and hook interactions (custom subagents). Meanwhile, print mode (-p) and --model and other CLI flags suit scripted read-only Q&A (Claude Code CLI reference).
(2) Implementation levers
Conceptual split: the main session keeps decisions and edits; subtasks do broad file reads and retrieval; downstream consumption is summaries or structured lists only. The “server side” for databases here means schema contracts: list tables, columns, and unique constraints via migrations or information_schema for low-cost alignment with the domain model.
(3) How to use it
claude -p --model haiku "List tables, unique constraints, and status enum columns in ranking-game-related migrations"
5. Database modeling example: ranking session, participants, and reactions#
(1) Rationale and motivation
Real-time multiplayer play needs a session-scoped state machine (e.g., LOBBY / ACTIVE / FINISHED / REVEAL), participant sets, and per-person reactions to each piece of content; unique constraints prevent duplicate joins or duplicate votes—business rules pushed into storage.
(2) Implementation levers
Slides list tables ranking_game_session, ranking_game_participant, ranking_game_reaction, with semantics such as Unique constraint: one participant per guest per session and one reaction per participant per photo per session (English on screen is authoritative). Exact column names and CHECK constraints follow actual migrations.
(3) How to use it
CREATE UNIQUE INDEX ux_participant_per_guest
ON ranking_game_participant (session_id, event_guest_id);
CREATE UNIQUE INDEX ux_one_reaction_per_submission
ON ranking_game_reaction (participant_id, submission_id);

Caption: The slide states in uppercase “The ranking game feature uses three main database tables:” and lists “ranking_game_session”, “ranking_game_participant”, “ranking_game_reaction”, and English bullets such as “Unique constraint: one participant per guest per session”.
6. “Vibe coding” baseline: missing tests and terminal states silently skipped#
(1) Rationale and motivation
Without a spec and layered memory, stacking code quickly from natural-language prompts alone tends to produce no automated tests, defects only found manually, and incomplete state-machine branches—for example an enum with a REVEAL phase but no migration path into it. Root causes are often framed as requirements drifting across long context, not a single syntax slip.
(2) Implementation levers
Reliable stack: JUnit / Spring Boot Test for regression; state transitions can be table-driven in unit tests enumerating when(event); key terminal states should be asserted reachable in tests.
(3) How to use it
enum class Phase { LOBBY, ACTIVE, FINISHED, REVEAL }
fun next(p: Phase, timerEnded: Boolean): Phase = when (p) {
Phase.ACTIVE -> if (timerEnded) Phase.FINISHED else p
Phase.FINISHED -> Phase.REVEAL
else -> p
}

Caption: The slide title is “THE VIBE CODING BASELINE”; body text includes “Iteration 1: no config, no skills, no plan”, “No tests written.”, “The whole REVEAL state skipped.”
7. In-session checkpoint and /rewind: try ideas without losing conversational meaning#
(1) Rationale and motivation
The agent records edits by checkpoint; when a refactor goes wrong, you can interrupt and, under Rewind / checkpoint semantics, roll back workspace changes while keeping chat history, then continue with corrected instructions. Official docs summarize tracking, rollback, and summarizing edits (Checkpointing).
(2) Implementation levers
The product provides session state and checkpoint selection; the focal file edited in demo materials is **RankingGameService.kt. Specific gestures such as rapid Escape follow current client documentation.
(3) How to use it
Human flow: interrupt the running tool call → invoke rewind → pick the target checkpoint → confirm restore → continue editing the same service class with tighter incremental prompts.

Caption: The UI lists repeated summaries like “Update (../rankinggame/RankingGameService.kt) Added 19 lines” and shows the prompt “Interrupted - What should Claude do instead?”
8. Division of labor among CLAUDE.md, path rules, and Skills#
(1) Rationale and motivationCLAUDE.md loads at session start—fit for “always true” compile and acceptance discipline; finer rules live under .claude/rules, injected only when matching paths are read, saving tokens (project memory and CLAUDE.md; path-scoped rules in path-specific rules—front matter uses a paths list for globs, not a separate globs key). Skills body text loads only when invoked, refreshing procedural guidance at action time (Skills).
(2) Implementation levers
The Hooks doc’s InstructionsLoaded event fires when CLAUDE.md or .claude/rules/*.md enters context (Hooks reference). The /context command shows the live breakdown of what fills the window (Context window).
(3) How to use it
# CLAUDE.md (illustrative)
- Compile after .kt changes: `./gradlew compileKotlin compileTestKotlin`
- Verify before done: run tests or demonstrate correctness
---
paths:
- "**/src/test/**"
---
Prefer Spring Boot Test + Testcontainers for integration scenarios...

Caption: The slide segment title is “INSIDE MY CLAUDE.MD”; visible bullets include “Compile after .kt changes:”, “./gradlew compileKotlin compileTestKotlin”, and “Verify before done: never mark a task complete without proving it works”.
9. Interview workflow: Explore first, then pin the spec with structured questions#
(1) Rationale and motivation
Writing entry paths, boundary states, and security assumptions into a reviewable document before coding cuts rework. Demo materials show a trajectory: auto-run “Explore codebase architecture”, then multi-select Q&A to clarify product choices such as where the admin enters the Ranking Game; Skill text requires the spec to end with User Stories with navigation-style stories first. The tool name AskUserQuestion appears in Hooks and subagent docs (Hooks — AskUserQuestion; Create custom subagents). Whether an “Interview Skill” fixed template and line count is a first-party built-in is not confirmed under that name in public docs; treat it as a reusable Markdown skill scaffold.
(2) Implementation levers
Mandatory topics cover Entry points, User journey, Edge cases, State transitions, Terminal states & dead ends, etc.; output constraints: Write the spec to a file, Spec MUST end with User Stories.
(3) How to use it
Clarifications map to routes and page structure—for example a dedicated section under /admin or on the event detail page.
@Controller
class RankingGameAdminController {
@GetMapping("/admin/events/{id}/ranking-game")
fun rankingGamePage(@PathVariable id: UUID): String = "admin/ranking-game"
}

Caption: The UI shows “Let me explore the codebase first to understand the existing architecture before interviewing you.” and a status line starting “Explore(Explore codebase architecture) Done (53 tool uses”.

Caption: The Q&A panel title includes “Where does the manager find the Ranking Game?..”; option rows show phrases such as “Manager dashboard (/admin)”, “Add a ‘Start Ranking Game’ button”.

Caption: The draft shows contiguous English such as “Interview me relentlessly ## Mandatory interview topics about every aspect…”, “Use AskUserQuestion tool to”, and “Write the spec to a file.”
10. Reaction budget and tamper resistance: server-side enforcement in an HTTP demo#
(1) Rationale and motivation
If budget lives only in browser cookies or front-end state, clients can tamper with counts; the server must treat an authenticated guest principal (e.g., event_guest) and database aggregates as authoritative. Slide options enumerate Server-side budget enforcement, pure client, cookie mixes, etc. (English labels as on screen).
(2) Implementation levers
Spring MVC commonly uses @PostMapping, @PathVariable, @RequestBody, ResponseEntity (annotation-driven controllers). The demo uses custom header X-Demo-Guest only in the sketch below; production systems should use sessions, JWT, or other mature mechanisms.
(3) How to use it
POST /api/events/550e8400-e29b-41d4-a716-446655440000/reactions HTTP/1.1
Content-Type: application/json
X-Demo-Guest: guest-token-demo
{"submissionId": 99, "type": "HEART"}
@RestController
@RequestMapping("/api/events/{eventId}/reactions")
class ReactionController(
private val reactions: ReactionService,
) {
@PostMapping
fun react(
@PathVariable eventId: UUID,
@RequestBody body: ReactionBody,
@RequestHeader("X-Demo-Guest") guestToken: String,
): ResponseEntity<Void> {
reactions.react(eventId, guestToken, body.submissionId, body.type)
return ResponseEntity.accepted().build()
}
}
data class ReactionBody(val submissionId: Long, val type: String)

Caption: The option list shows “Security: should we prevent reaction manipulation?..”, “1. Server-side budget enforcement”, “DB tracks reactions per guest…”, etc.

Caption: The same “Storage model” branch shows “Clarifying: reactions stored in the DB, but budget tracked client-side via a cookie?..” and numbered lines “1. DB reactions, cookie budget”, “Each reaction is a DB row. Budget is client-side.”
11. Domain validation: reuse existing exception hierarchy and bilingual messages#
(1) Rationale and motivation
When adding business validation (e.g., legal timer duration ranges), mirroring existing PhotoQuestException subclasses in the repo avoids one-off error models; a slide shows InvalidTimerDurationException carrying German user copy and English system copy. OCR misread “30” as “3@”; the correct interval follows project source or product requirements—here interpreted conventionally as 1–30 minutes.
(2) Implementation levers
Kotlin can use require for illegal arguments (require in stdlib); combined with Spring HTTP mapping, exceptions should map to 400/422 via @ControllerAdvice (Spring MVC exception handling).
(3) How to use it
class InvalidTimerDurationException : PhotoQuestException(
userDe = "Die Timer-Dauer muss zwischen 1 und 30 Minuten liegen.",
systemEn = "Timer duration must be between 1 and 30 minutes",
)
fun createSession(timerMinutes: Long) {
if (timerMinutes !in 1..30) throw InvalidTimerDurationException()
}

Caption: The diff summary includes “class InvalidTimerDurationException : PhotoQuestException(” and the English line “Timer duration must be between 1 and 3@ minutes” (the “@” is OCR noise; source wins).
12. Hooks, static analysis, and the Jackson 3 migration narrative#
(1) Rationale and motivation
Rule text may be ignored by the model; Hooks run scripts on PreToolUse / PostToolUse / SessionEnd, etc., to block dangerous commands or run formatter / linter after writes (Hooks reference). The demo mentions Detekt custom rules flagging Jackson 2 ObjectMapper references to steer toward Jackson 3 JsonMapper; the Spring Boot 4 migration guide documents com.fasterxml.jackson → tools.jackson (Spring Boot 4.0 Migration Guide — Jackson). Detekt rule DSL details were not verified against an official page in this article.
(2) Implementation levers
Hook configuration follows the product JSON schema; matchers can filter tool names such as Bash, Edit|Write.
(3) How to use it
{
"hooks": {
"PreToolUse": [{ "matcher": "Bash", "command": "./hooks/git-guard.sh" }],
"PostToolUse": [{ "matcher": "Edit|Write", "command": "./hooks/detekt-on-write.sh" }]
}
}
13. MCP: expose IDE capabilities as agent-callable interfaces#
(1) Rationale and motivation
Model Context Protocol exposes external systems (IDEs, issue trackers, observability backends) through a standard tool surface to clients; without MCP, agents often rely on shell and raw file I/O. Spring AI ships multiple MCP Server Boot Starters (Spring AI — MCP overview). Protocol docs live at modelcontextprotocol.io; repo README at modelcontextprotocol/modelcontextprotocol README.
(2) Implementation levers
Slides contrast “Without MCP / With IntelliJ MCP”, listing reformat_file, execute_run_configuration, auto-import, and the line “The IDE becomes an API that the agent calls.”; JetBrains MCP Steroid’s README claims broader IntelliJ Platform API exposure (MCP Steroid README). Exact tool identifiers follow the implementing repo.
(3) How to use it
On the CLI, configure servers with claude mcp (CLI reference); in the IDE, install the matching MCP plugin and grant the agent a minimal permission set.

Caption: The table contrasts “Without MCP” and “With IntelliJ MCP”, includes “The IDE becomes an API that the agent calls.”, and “github.com/JetBrains/mcp-steroid”.
14. Long-plan drift and segmented headless execution (Ralph-style thinking)#
(1) Rationale and motivation
In one very long session, the model may have a plan but not execute step by step: slides mark /frontend-design, agent-browser, /simplify, etc., as “dropped after early Phase” or “Never used”, with the title “Plans work — until the context window doesn’t.” and the conclusion “The agent isn’t a deterministic machine.” That aligns with putting each phase in a separate claude -p session and a shell loop consuming plan files in order; whether “Ralph” is a community nickname must be checked against each tool’s docs—vendor pages do not mandate that name.
(2) Implementation levers
Segmented execution needs: machine-readable plan artifacts, phase boundaries, cold-start sessions; Skills docs bundle the /simplify command (Skills); whether it was invoked in a given run is an observational matter.
(3) How to use it
while read -r phase; do
claude -p -- "$(cat docs/plan.md)" --phase "$phase"
done < docs/phases.txt
The --phase flag name is illustrative; real flags follow the CLI reference.


Caption: The slide main title is “LEVEL 4: THE DRIFT PROBLEM”, subtitle “Plans work — until the context window doesn’t.”, bottom line “The agent isn’t a deterministic machine”, with English status labels such as “Dropped after Phase 1” and “Never used”.
References and further reading#
- Spring Boot — Kotlin language support
- Spring Boot — Using jOOQ and DSLContext
- htmx extension — Server-Sent Events (sse-connect, etc.)
- PostgreSQL manual — NOTIFY
- Spring Framework JavaDoc — ServerSentEvent
- MDN — EventSource API
- Kotlin docs — compileKotlin task in Gradle
- Spring Boot reference — SpringBootTest
- Spring Framework reference — MockMvc
- Testcontainers for Java project home
- Claude Code docs — Subagents
- Claude Code docs — CLI reference (includes
-p,--model) - Claude Code docs — Checkpointing (rollback edits)
- Claude Code docs — Project memory and CLAUDE.md
- Claude Code docs — Path-scoped rules (paths glob)
- Claude Code docs — Skills
- Claude Code docs — Hooks (includes AskUserQuestion)
- Claude Code docs — Context window and /context
- Anthropic docs — Prompt caching
- Kotlin stdlib — require
- Spring Framework reference — Controller advice exception handling
- Spring Boot 4.0 Migration Guide — Jackson 3 / tools.jackson
- modelcontextprotocol repository README (protocol entry)
- Spring AI reference — Model Context Protocol overview and Boot Starters
- JetBrains — MCP Steroid project README



