glm-5.3-flash ee4053e3e2 docs(release): rewrite README on the shipped framing; CHANGELOG 0.1.0; package exclude fix
- README: the engine contract (strict mode, set-per-registry,
  consumer-supplied text, typed errors, determinism, two sinks,
  per-set escaping), the three integration postures (emit.md A/B/C),
  an explicit what-0.1.0-does-not-ship section, no stale codegen/alktype
  references
- CHANGELOG: Keep a Changelog 0.1.0 entry itemized against the actual
  surface, with the error-evolution policy recorded
- Cargo.toml: exclude docs/plans/ and tasks/ from the package
2026-11-07 06:07:28 +00:00

alkgen

The text-generation engine of the alk* stack: handlebars-rust templates rendered over serde-serializable contexts with strict, deterministic output. One crate, one purpose: register a template set, render its templates, get the same bytes every time.

Status: 0.1.0 publishes the core, proven fit for its first consumer, alkforge's server-side HTML rendering. The engine is consumer-blind: it owns no template sets and no assumptions about what the rendered text is. HTML, Rust, and WGSL are all the same shape to it.

The engine's contract

  • Strict mode is always on. A missing context variable is a typed error, never silently empty output. A silent gap in generated text becomes a bug in the consumer's build, far from its cause; the engine refuses to produce one.
  • One registry per template set. A TemplateSet is the unit: strict mode, the set's escaper, and its namespace for templates, partials, and helpers all live there. A partial's name is never a render target; the set tracks the difference and rejects a partial-as-target as a typed error.
  • Consumer-supplied templates register through the same machinery the engine would use. Template text arrives as &str (inline literals, include_str!, caller-built strings); there is no filesystem path anywhere in the API, so the core is wasm-clean by construction.
  • Typed errors, no panics. Malformed template text fails at registration; render failures (missing variable, unknown template, unknown helper) fail at render. Every failure maps to exactly one variant of the public Error enum (non-exhaustive; the substrate's detail stays reachable through the error's source chain). Template sets may add helpers, which must be pure: no time, no environment, no randomness, no I/O.
  • Deterministic, byte-identical output. Repeated renders and rebuilt registries produce the same bytes, and there is no hash-map iteration order that can leak into them. This is what makes consumer-side caching and checked-in generated artifacts safe.
  • Two sinks. render returns a String; render_to_write streams to any io::Write target. Both produce byte-identical output. The write sink is not atomic: a render that fails partway may leave earlier bytes in the target, and consumers that need atomicity buffer first.
  • Escaping is a per-set choice. EscapePolicy::Html keeps the substrate's HTML entity escaping on (with {{& }} as the deliberate per-expression opt-out); EscapePolicy::NoOp passes interpolations through verbatim for code generation, where output should be escaped at the source, not mangled by entity escaping.

Usage

use alkgen::{EscapePolicy, TemplateSet};
use serde_json::json;

let mut set = TemplateSet::new(EscapePolicy::Html);
set.register_template("page", "<h1>{{title}}</h1>{{> footer}}")?;
set.register_partial("footer", "<p>{{year}}</p>")?;

let ctx = json!({ "title": "Hello", "year": "2026" });
assert_eq!(set.render("page", &ctx)?, "<h1>Hello</h1><p>2026</p>");
# Ok::<(), alkgen::Error>(())

Integration patterns

How rendered text reaches its consumer; the render machinery is identical in every posture (see docs/architecture/emit.md, which ships in the package):

  • In-process SSR (the first real consumer: alkforge): link the crate, register your page templates and fragment partials, render on demand or behind your own cache. Determinism is what makes caching safe to add later. Render failure is a typed error your error-page mapping owns.
  • Build-time code generation: call the API from a build.rs script (there is no CLI in v1, by design), render each document, and write the files yourself: the engine returns text and owns nothing about file placement. For artifacts that get checked in, the family's hygiene convention applies at the emit layer: generated files start with an "Auto-generated by alkgen. DO NOT EDIT." banner and regeneration is diff-quiet because rendering is deterministic.
  • Render-to-compile (future): render shader or other target text and feed it to a downstream compiler, the alkminer-v1 ShaderBuilder shape. No new surface is required from the engine for this.

What 0.1.0 does not ship

Engine-owned template sets: the BAST codec set (binary readers/writers/validators for alkcall channels), protocol handler sets, and the WGSL set are future activations, each behind its own review; the bast-codegen cargo feature is declared but gates nothing. The ssr-html target is proven in-crate through consumer-shaped fixture sets that register through the same public API a real consumer uses. Your template sets are yours: register them from your crate through this API.

Design record

docs/architecture/ ships in the package: the component spec (core.md, emit.md), the activation queue (targets.md), and the decision records (ADR-001 through 010) this README summarizes.

License

Dual-licensed under MIT or Apache-2.0, at your option.

S
Description
No description provided
Readme
527 KiB
0 Stars 6 Watchers 0 Forks
Languages
Rust 100%