Skip to content

Commit 27a0a57

Browse files
committed
Release version 0.1.0
1 parent f0401ce commit 27a0a57

File tree

5 files changed

+426
-4
lines changed

5 files changed

+426
-4
lines changed

CLAUDE.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
**Semantic AI Validator** is a Kotlin library for AI-powered semantic validation of form fields using Large Language Models (LLMs). The project enables validation by describing requirements in plain English rather than writing complex regex patterns.
8+
9+
- **Owner**: SoftwareMill
10+
- **License**: Apache 2.0
11+
- **Target**: Spring Boot 3.5+ applications, Java 21+
12+
- **Language**: Kotlin 2.1.0 with explicit API mode in core library
13+
- **Key Framework**: Koog AI Framework (0.5.0) for LLM integration
14+
15+
## Module Structure
16+
17+
This is a multi-module Gradle project with three modules:
18+
19+
1. **semantic-ai-validator-core**: Core validation library (publishable to Maven Central)
20+
- Standalone, framework-agnostic validation logic
21+
- Annotations: `@AIVerify`, `@AIVerifyContext`
22+
- LLM client integration via Koog framework (OpenAI, Anthropic, Google, Ollama)
23+
- Reflection-based field discovery and validation orchestration
24+
- Coroutine-based async validation
25+
26+
2. **semantic-ai-validator-spring-boot-starter**: Spring Boot integration (publishable to Maven Central)
27+
- Auto-configuration for Spring Boot 3.5+
28+
- Type-safe configuration properties (`AIValidatorProperties`)
29+
- Integration with Spring Validation framework (`@Valid`)
30+
- `@ValidateWithAI` constraint annotation
31+
- Controller advice for error handling
32+
33+
3. **semantic-ai-validator-demo**: Demo application (not published)
34+
- Full-featured Spring Boot application showcasing library capabilities
35+
- Web UI with Thymeleaf templates
36+
- Example forms: project validation, invoice PDF validation, product reviews
37+
- Unit tests, integration tests, and Playwright E2E tests
38+
39+
## Common Development Commands
40+
41+
### Building and Testing
42+
43+
```bash
44+
# Build entire project
45+
./gradlew build
46+
47+
# Build without tests (faster)
48+
./gradlew build -x test
49+
50+
# Run all tests
51+
./gradlew test
52+
53+
# Run tests for specific module
54+
./gradlew :semantic-ai-validator-core:test
55+
./gradlew :semantic-ai-validator-spring-boot-starter:test
56+
./gradlew :semantic-ai-validator-demo:test
57+
58+
# Run specific test class
59+
./gradlew test --tests 'AIFieldValidatorTest'
60+
61+
# Run specific test method
62+
./gradlew test --tests 'AIFieldValidatorTest.should validate field successfully'
63+
64+
# Generate code coverage report
65+
./gradlew test koverHtmlReport
66+
# Report: build/reports/kover/html/index.html
67+
```
68+
69+
### Running the Demo Application
70+
71+
```bash
72+
# Set API key first (required)
73+
export OPENAI_API_KEY=sk-...
74+
75+
# Run demo application
76+
./gradlew :semantic-ai-validator-demo:bootRun
77+
78+
# Alternative: run with Gradle wrapper and skip tests
79+
OPENAI_API_KEY="$OPENAI_API_KEY" ./gradlew :semantic-ai-validator-demo:bootRun -x test
80+
81+
# Demo will be available at http://localhost:8080
82+
```
83+
84+
### Publishing
85+
86+
```bash
87+
# Publish to local Maven repository for testing
88+
./gradlew publishToMavenLocal
89+
90+
# Check publication configuration
91+
./gradlew :semantic-ai-validator-core:publishMavenPublicationToMavenLocal
92+
./gradlew :semantic-ai-validator-spring-boot-starter:publishMavenPublicationToMavenLocal
93+
```
94+
95+
## Architecture Notes
96+
97+
### LLM Client Architecture
98+
99+
- **Koog Framework**: All LLM interactions use the Koog AI Framework (ai.koog:koog-agents:0.5.0)
100+
- **Multiple Providers**: Single unified API (`LLMClient` interface) wraps Koog executors for OpenAI, Anthropic, Google, Ollama
101+
- **Factory Pattern**: `LLMClientFactory` creates appropriate client based on provider configuration
102+
- **Async by Default**: All validation is coroutine-based using `suspend` functions
103+
- **Context7 Integration**: When working with Koog framework features, use Context7 to fetch latest docs
104+
105+
### Validation Flow
106+
107+
1. **Annotation Scanning** (`ReflectionUtils`): Discover `@AIVerify` fields using Kotlin reflection
108+
2. **Context Extraction**: Gather values from fields marked with `@AIVerifyContext` or listed in `contextFields`
109+
3. **Prompt Building** (`PromptBuilder`): Construct validation prompts with field values and context
110+
4. **Parallel Execution**: Validate multiple fields concurrently using coroutines
111+
5. **Response Parsing**: Parse LLM responses to extract validation results (VALID/INVALID + error messages)
112+
6. **Result Aggregation** (`AIObjectValidator`): Combine field-level results into object-level validation
113+
114+
### Spring Integration
115+
116+
- **Auto-Configuration** (`AIValidatorAutoConfiguration`): Conditionally creates beans based on API keys
117+
- **Constraint Validator** (`AIValidatorConstraintValidator`): Bridges to Spring's `@Valid` mechanism
118+
- **Controller Advice** (`AIValidationControllerAdvice`): Handles validation exceptions and formats error responses
119+
- **Configuration Properties** (`AIValidatorProperties`): Type-safe binding from `application.yml`
120+
121+
### Dependency Version Management
122+
123+
**IMPORTANT**: Koog 0.5.0 was compiled with kotlinx-serialization 1.8.1 and is **incompatible** with 1.9.0+. All modules enforce version 1.8.1 through:
124+
- `resolutionStrategy.force()` in root build.gradle.kts
125+
- Version constraints in core module
126+
- Dependency management overrides in demo module
127+
128+
## Testing Strategy
129+
130+
### Coverage Requirements
131+
- **Minimum**: 80% for all modules
132+
- **Target**: 90%+ for core library
133+
- **Critical paths**: 100% for validation logic
134+
135+
### Test Types
136+
137+
1. **Unit Tests** (Kotest + MockK):
138+
- Test individual components in isolation
139+
- Mock LLM clients and external dependencies
140+
- Fast, no Spring context
141+
142+
2. **Integration Tests** (Spring Boot Test):
143+
- Load full Spring context
144+
- Test auto-configuration and bean wiring
145+
- Validate end-to-end Spring integration
146+
147+
3. **E2E Tests** (Playwright):
148+
- Browser-based tests of demo application
149+
- Test complete user flows with real UI interaction
150+
- Located in `semantic-ai-validator-demo/src/test`
151+
152+
### Running E2E Tests
153+
154+
E2E tests use Playwright and require the demo application to be running:
155+
156+
```bash
157+
# Terminal 1: Start demo app
158+
export OPENAI_API_KEY=sk-...
159+
./gradlew :semantic-ai-validator-demo:bootRun
160+
161+
# Terminal 2: Run E2E tests
162+
./gradlew :semantic-ai-validator-demo:test --tests '*E2E*'
163+
```
164+
165+
## Code Style and Conventions
166+
167+
### Kotlin Style
168+
- **Indentation**: 4 spaces (no tabs)
169+
- **Line length**: 120 characters max
170+
- **API visibility**: Core module uses `kotlin { explicitApi() }` - all public APIs require explicit visibility modifiers
171+
- **Immutability**: Prefer `val` over `var`
172+
- **Null safety**: Avoid nullable types unless necessary
173+
174+
### Testing Conventions
175+
- Use **backtick test names** for readability: `` `should validate field when LLM returns VALID` ``
176+
- Follow **AAA pattern**: Arrange, Act, Assert
177+
- Use **Kotest matchers**: `shouldBe`, `shouldContain`, `shouldBeEmpty()`
178+
179+
### Documentation
180+
- **KDoc required** for all public APIs in core and starter modules
181+
- Include **usage examples** in KDoc
182+
- Document **exceptions** and edge cases
183+
- Add **`@since` tags** for version tracking
184+
185+
## Environment Variables
186+
187+
```bash
188+
# LLM Provider API Keys
189+
OPENAI_API_KEY=sk-...
190+
ANTHROPIC_API_KEY=sk-ant-...
191+
GOOGLE_API_KEY=...
192+
193+
# Ollama (for local models) - default is http://localhost:11434
194+
OLLAMA_BASE_URL=http://localhost:11434
195+
```
196+
197+
## Common Issues and Solutions
198+
199+
### kotlinx-serialization Version Conflicts
200+
201+
**Problem**: Build fails with `NoSuchMethodError` or serialization errors.
202+
203+
**Solution**: Koog 0.5.0 requires kotlinx-serialization 1.8.1. The build is already configured to enforce this, but if you add new dependencies that transitively pull in 1.9.0+, add force resolution in root build.gradle.kts.
204+
205+
### Demo App Won't Start
206+
207+
**Problem**: Application fails to start with bean creation errors.
208+
209+
**Solution**: Ensure at least one LLM provider API key is configured. The auto-configuration conditionally creates beans based on API key presence.
210+
211+
### Tests Requiring Real LLM API Calls
212+
213+
**Problem**: Some tests need actual LLM responses to validate behavior.
214+
215+
**Solution**: Mock the `LLMClient` interface using MockK. For integration tests that need real calls, use `@TestInstance` and tag tests appropriately so they can be skipped in CI.
216+
217+
## Contributing Workflow
218+
219+
1. **Branch naming**: `feature/my-feature`, `fix/bug-description`
220+
2. **Commit messages**: Follow [Conventional Commits](https://www.conventionalcommits.org/) (feat:, fix:, docs:, test:, refactor:, chore:)
221+
3. **Before submitting PR**:
222+
- Run `./gradlew clean build test`
223+
- Ensure 90%+ test coverage for new code
224+
- Update relevant README files
225+
- Add KDoc to public APIs
226+
4. **Testing requirements**: All new code must have tests (unit + integration where applicable)
227+
228+
## Useful Gradle Properties
229+
230+
Location: `gradle.properties`
231+
232+
```properties
233+
koogVersion=0.5.0 # Koog AI Framework version
234+
kotlinVersion=2.1.0 # Kotlin compiler version
235+
springBootVersion=3.5.3 # Spring Boot version
236+
kotestVersion=5.9.1 # Kotest testing framework
237+
playwrightVersion=1.49.0 # Playwright for E2E tests
238+
```
239+
240+
## Related Documentation
241+
242+
- Main README: `/README.md` - User-facing documentation, quick start
243+
- Contributing Guide: `/CONTRIBUTING.md` - Detailed contribution guidelines
244+
- Core Module: `/semantic-ai-validator-core/README.md` - Standalone usage, API reference
245+
- Spring Starter: `/semantic-ai-validator-spring-boot-starter/README.md` - Spring Boot configuration
246+
- Demo App: `/semantic-ai-validator-demo/README.md` - Demo endpoints and examples
247+
- whenever you try to mutate a list in kotlin consider using map operation
248+
- whenever return keyword is not necessary in kotlin functions don't use it

build.gradle.kts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ plugins {
1616

1717
// Kover for code coverage
1818
id("org.jetbrains.kotlinx.kover") version "0.9.1"
19+
20+
// Maven Central publishing
21+
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
1922
}
2023

2124
allprojects {
22-
group = "com.softwaremill"
23-
version = "0.1.0-SNAPSHOT"
25+
group = "com.softwaremill.aivalidator"
26+
version = "0.1.0"
2427

2528
repositories {
2629
mavenCentral()
@@ -73,3 +76,16 @@ kover {
7376
}
7477
}
7578
}
79+
80+
// Configure publishing for Maven Central Portal
81+
// https://central.sonatype.com/
82+
nexusPublishing {
83+
repositories {
84+
sonatype {
85+
nexusUrl.set(uri("https://central.sonatype.com/api/v1/publisher/"))
86+
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/api/v1/publisher/"))
87+
username.set(project.findProperty("mavenCentralUsername") as String? ?: System.getenv("MAVEN_CENTRAL_USERNAME"))
88+
password.set(project.findProperty("mavenCentralPassword") as String? ?: System.getenv("MAVEN_CENTRAL_PASSWORD"))
89+
}
90+
}
91+
}

0 commit comments

Comments
 (0)