Date: 2026-02-16 Status: accepted Phase: Post-POC architecture
ADR 0001 chose Rust as the compilation target. ADR 0008 introduces an IR that decouples contract semantics from any specific backend. This opens the question: should Intent support multiple codegen targets?
The original premise (ADR 0000) is that Intent makes AI-generated code more correct and auditable. That premise applies equally to backend services, CLI tools, web frontends, and edge/serverless functions. Limiting Intent to Rust-only output limits the addressable use cases.
Not everyone writes backend or CLI code. Frontend development (web apps, browser-based tools, interactive UIs) is a massive category where AI coding assistants are heavily used. If Intent can only produce native binaries, it excludes this entire domain.
-
Rust-only. Keep the current single backend. Frontend users would need to compile Rust to WASM separately, which is possible but adds friction and limits the Rust subset that works in browsers.
-
Rust + WASM. Add a WASM backend (possibly via Rust's wasm32 target or direct WASM emission). Covers browser and edge use cases. WASM has a well-defined execution model that maps cleanly to Intent's semantics.
-
Rust + JavaScript/TypeScript. Add a JS/TS backend for direct browser and Node.js targeting. Contracts compile to runtime assertions in JS. Wider reach but weaker type guarantees at the target level.
-
Multi-target via IR. With the IR from ADR 0008, treat code generation as a pluggable backend interface. Ship Rust first, add targets as demand and resources allow. The IR design does not need to change per target -- only the backend implementation.
Multi-target via IR. The IR (ADR 0008) is designed to be target-agnostic. Each codegen backend implements a common interface that consumes the IR and emits target-specific code with appropriate contract enforcement.
Planned target priority:
- Rust (current, production-ready) -- native binaries, CLI, backend
- WASM (next) -- browser, edge, portable. Can leverage Rust's wasm32-unknown-unknown target initially, then move to direct WASM emission if needed
- JavaScript/TypeScript (future) -- frontend, Node.js. Contracts compile to runtime checks. TypeScript output preserves type information
- Z3/SMT-LIB (verification target, not execution) -- contract nodes translated to SMT formulae for static verification
Each target handles contract enforcement in its own idiom:
- Rust:
assert!()macros (current approach) - WASM:
unreachabletraps or imported assertion functions - JS/TS:
throworconsole.assert()with contract metadata - Z3: proof obligations, not runtime checks
- The codegen interface must be defined before building additional backends. This is a design task that should happen during IR implementation (ADR 0008).
- Each new backend is an independent effort that can be developed in parallel once the IR is stable.
- WASM as the second target gives frontend coverage with minimal new
complexity (Rust already compiles to WASM; the initial WASM path can
simply be
intentc build --target wasminvokingcargo build --target wasm32-unknown-unknown). - JS/TS codegen is the most complex additional backend because JavaScript's type system and execution model differ significantly from Intent's. This is why it is lower priority.
- The
intentblockverified_bychecking remains the same regardless of target -- it operates at the IR level before any backend is invoked. - This decision does NOT require all targets to be implemented before shipping. Rust remains the primary and default target. Additional targets are additive.