Epic: single krapper binary + ksrpc service interface to the compiler (Jason's direction, 2026-07-26). This is brick 3 of 3. Depends on #184, #185.
Once krapper is one binary behind a typed ksrpc channel (#184, #185), it can stay alive across a Gradle daemon session instead of being a one-shot batch process, and answer questions on demand.
Query surface (sketch)
Why this matters beyond ergonomics
Two long-standing walls are consequences of the batch, parse-everything-up-front architecture:
Template instantiation manifests (--instantiate pre-declaration) also stop being necessary.
Open (needs-decision)
- Process lifetime + ownership: Gradle daemon-scoped? build-scoped? Idle timeout?
- Determinism and caching: an incremental/lazy binder must still produce byte-identical output for the same inputs (featuregen SYNC is the gate).
- Memory: a persistent Clang instance holding ASTs across a daemon session.
- Whether the FIR compiler plugin becomes a second client of the same service (today it reads
@krapper.CppBinding annotations statically and re-derives the name mangling), or stays annotation-driven.
Epic: single
krapperbinary + ksrpc service interface to the compiler (Jason's direction, 2026-07-26). This is brick 3 of 3. Depends on #184, #185.Once krapper is one binary behind a typed ksrpc channel (#184, #185), it can stay alive across a Gradle daemon session instead of being a one-shot batch process, and answer questions on demand.
Query surface (sketch)
resolve(spec)— what does this C++ type/decl bind to?explainDrop(spec)— why is there no binding for this? (DropLedgeralready has the answer)instantiateNow(spec)— instantiate a template on demand, instead of pre-declaring it in a manifestdiagnostics()— the structured stream from [arch] ksrpc service interface between the compiler and krapper (typed diagnostics, no stdout-scrape) #185Why this matters beyond ergonomics
Two long-standing walls are consequences of the batch, parse-everything-up-front architecture:
clang::Decl) because binding is eager and closed-world. A live service can bind lazily — materialize only what the consuming Kotlin code actually touches. The closure explosion stops being the shape of the problem.docs/design/wellformedness-binding-gate.md). A persistent Clang instance answering queries has Sema — overload resolution, SFINAE, and instantiability become askable rather than guessable.Template instantiation manifests (
--instantiatepre-declaration) also stop being necessary.Open (needs-decision)
@krapper.CppBindingannotations statically and re-derives the name mangling), or stays annotation-driven.