| Principle | Kotlin Implementation | Tooling |
|---|---|---|
| Intent–Structure–Implementation Separation | Interface (specification) + data class (data) + concrete class (implementation) | Kotlin compiler |
| Generative Conformance | Code generation from OpenAPI / JSON Schema / annotations | KSP + KotlinPoet, OpenAPI Generator |
| Skeleton–Tissue Architecture | public interfaces (skeleton) + internal implementations (tissue) |
Access modifiers, sealed classes |
| Recursive Refinement with Fixed Premises | Module boundaries + Git tags + incremental builds | Gradle, KSP incremental processing |
| Validation Gates | Compiler checks + static analysis + architecture tests | Kotlin compiler, Detekt, ArchUnit |
| Scope | Format | Generation Target |
|---|---|---|
| API boundaries (REST) | OpenAPI 3.0+ YAML | Ktor/Spring server stubs, client libraries |
| Data models | JSON Schema or Kotlin data classes | POJOs / data classes, JSON schema |
| Service contracts | gRPC + Protocol Buffers | Kotlin gRPC stubs (grpc-kt) |
| Domain constraints | Custom annotations + KSP | Validation code, state machines |
Selection rule: OpenAPI for external APIs, JSON Schema for shared data, gRPC for internal services, custom annotations for domain‑specific rules.
KSP processes annotations at compile time. KotlinPoet generates .kt files programmatically.
// Custom processor skeleton
class DeepCodingProcessor : SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> {
val symbols = resolver.getSymbolsWithAnnotation("GenerateTissue")
symbols.forEach { symbol ->
val fileSpec = buildTissueClass(symbol)
fileSpec.writeTo(codeGenerator)
}
return emptyList()
}
}
Gradle plugin configuration:
openApiGenerate {
generatorName.set("ktor") // or "spring"
inputSpec.set("$projectDir/src/main/resources/api.yaml")
outputDir.set("$buildDir/generated")
apiPackage.set("com.example.api")
modelPackage.set("com.example.model")
}
Generates JSON Schema from @Schema annotated data classes at compile time.
@Schema
data class Product(
val id: Long,
val name: String,
val price: Double
)
// Schema accessible via Product::class.jsonSchemaString
public)// skeleton/ServiceSkeleton.kt
interface ServiceSkeleton {
fun execute(input: Input): Output
}
fun ServiceSkeleton.executeWithLogging(input: Input): Output {
println("Executing: $input")
return execute(input)
}
sealed interface ResultState
data class Success(val data: Output) : ResultState
data class Failure(val error: String) : ResultState
internal)internal visibility.src/main/kotlin/tissue/generated/.// tissue/generated/ServiceTissue.kt (generated by KSP)
internal class ServiceTissue : ServiceSkeleton {
override fun execute(input: Input): Output {
// Generated business logic
return Output("Processed: ${input.value}")
}
}
byclass ServiceCoordinator(
private val tissue: ServiceTissue
) : ServiceSkeleton by tissue
| Layer | Tool | Enforced Property |
|---|---|---|
| Compiler | Kotlin compiler | Null safety, type safety, when exhaustiveness for sealed classes |
| Access control | internal + Gradle modules |
Tissue implementations not visible outside module |
| Static analysis | Detekt custom rules | Package naming, dependency direction (tissue → skeleton only) |
| Architecture tests | ArchUnit | Layer dependencies, no circular dependencies |
| Generation-time | KSP processor | Structural specification conformance |
Detekt custom rule example (tissue not depending on other tissue):
class TissueDependencyRule : Rule() {
override fun visitClass(klass: KtClass) {
// Check import statements and supertypes
}
}
ArchUnit test:
@Test
fun `tissue depends only on skeleton`() {
val rule = noClasses()
.that().resideInPackage("..tissue..")
.should().dependOnClassesThat()
.resideInPackage("..tissue..")
rule.check(importedClasses)
}
Phase N complete
│
├── Git tag: phase-N-complete
├── Save structural specification snapshot
│
▼
Modify specification (OpenAPI YAML, annotations, .proto)
│
├── KSP incremental processing detects changes
├── Regenerate affected tissue code only
│
▼
Validation gates (compiler → Detekt → ArchUnit → tests)
│
├── On failure: reject change, rollback to tag
├── On success: commit new specification and generated code
│
▼
Phase N+1 complete
│
└── Git tag: phase-N+1-complete
Gradle incremental build configuration:
tasks.named("compileKotlin") {
dependsOn("generateCode")
}
tasks.named("generateCode") {
inputs.dir("src/main/resources/specification")
outputs.dir("$buildDir/generated")
}
openapi plugin can generate OpenAPI from code (reverse direction).| Clean Architecture Layer | Deep Coding Layer | Implementation |
|---|---|---|
| Domain (interfaces) | Skeleton | public interfaces, sealed states |
| Data (repositories) | Tissue | internal implementations, KSP generated |
| Presentation | Framework layer | Deep Coding not applied |
expect/actual declarations align with skeleton‑tissue separation.| Phase | Scope | Deliverable | Duration |
|---|---|---|---|
| 0 | Infrastructure | Gradle setup, KSP module, KotlinPoet dependency | 1 week |
| 1 | Skeleton design | Core interfaces, sealed state definitions | 1-2 weeks |
| 2 | Structural specification | OpenAPI YAML, custom annotations, JSON Schema | 1 week |
| 3 | Generation pipeline | KSP processors, OpenAPI Generator integration | 2 weeks |
| 4 | Validation gates | Detekt custom rules, ArchUnit tests, CI integration | 1 week |
| 5 | Pilot module | Apply to one module, measure build time and conformance | 1-2 weeks |
| Constraint | Mitigation |
|---|---|
| KSP learning curve | Start with small annotation processors; use existing examples |
| kotlinx-schema experimental status | Use OpenAPI Generator for production; monitor kotlinx-schema maturity |
| Existing Java codebase | Apply Deep Coding to new Kotlin modules only; use facade pattern for legacy integration |
| Build time in large projects | Incremental KSP processing + Gradle build cache |
| Reflection‑heavy frameworks (Spring, Hibernate) | Limit Deep Coding to contract and DTO layers; use traditional implementation for persistence |
Kotlin provides all necessary language features and tooling for a specification‑driven, AI‑assisted development workflow:
public/internal visibility and module boundariesThe plan is ready for production use in Ktor server applications, Android projects, and Kotlin Multiplatform environments. New modules can adopt the full pipeline; existing codebases can integrate gradually.