Files
alkgen/docs/architecture/decisions/001-one-core-template-set-targets.md
glm-5.3-flash a91ea2ec89 docs(architecture): phase 1 base: text-generation core specs, ADRs 001-010, OQ tracker
- overview.md, core.md, emit.md, targets.md: modular spec set for the
  generalized engine (contexts + templates + partials -> text), with
  the three targets (ssr-html, bast-rust-codecs, call-handlers,
  wgsl-jit) as template sets plus emit postures
- ADRs 001-010: one core/template-set split, handlebars 6.4 strict
  substrate, sync/wasm/deterministic posture, typed contexts with
  builders, per-registry escaper, SSR library posture, typed direct
  codecs output contract, template-set ownership, feature gating,
  library-only v1
- open-questions.md: OQ-01..OQ-08 centralized tracker carrying phase-0
  residue (GN-01/02/07/09) with three deferred(scope) entries plus a
  resolved disposition for phase-0 OQ-GN-04
- tasks/architecture/: external-trigger tracker tasks paired with the
  deferred OQs (taskgraph validate passes)
- phase-0.md checklist dispositioned for OQ-GN-04; AGENTS.md lifecycle
  updated to phase 1

Verification: taskgraph validate (4 tasks OK), cargo fmt --check,
cargo test, em-dash grep clean; architecture-reviewer pass returned
zero critical issues
2026-11-06 08:18:43 +00:00

2.5 KiB

ADR-001: One text-generation core; targets are template sets plus emit layers

Status

Accepted

Context

Phase 0 scoped the crate as "codegen over BAST documents" with static file emission into downstream projects as the product. Two things dissolved that framing:

  1. The 2026-11-06 unpause arrived because alkforge (family ADR-002) needs server-side HTML generation, a runtime rendering use with no schema, no plans, and no file emission.
  2. WGSL generation for alkjs (alkminer-v1's ShaderBuilder precedent) and Rust codec generation (reader POC) are provably the same machinery: contexts plus templates plus partials produce text.

Three data points, one shape. Treating SSR as a special case baked into a codegen-shaped core would either fork the machinery or deform it.

Decision

alkgen's core is a text-generation engine: it owns registry construction (strict mode, first-class partials, per-registry escape policy), context conventions, a deterministic synchronous render entry point, and typed errors. A target is a template set plus a context shape plus an emit posture. Shared core types encode none of the targets: no reader/writer assumptions, no HTML assumptions, no WGSL assumptions.

Validity pinning is per template set: render tests for each set pin what "valid output" means for it (Rust compilability, HTML well-formedness, WGSL syntax are set-level property tests, never core concepts).

The dev-tool identity is demoted from "the product" to "posture A of the emit layer" (emit.md).

Consequences

  • Positive: three consumers, one maintenance surface; the SSR branch acts as a standing overfitting test; the WGSL path needs no core work beyond template sets when it arrives.
  • Positive: the demotion is cheap because it changes nothing required by branches 1 and 2; their needs are now a posture, not the crate's definition.
  • Negative: generalization can hide real per-target needs until late. Mitigation: the first consumer is SSR (the least codegen-like), so the core is exercised against the differentiator immediately.
  • Negative: core APIs must stay small enough to remain "everything-for-nothing" (no target vocabulary), which constrains helpers and conveniences that would drift toward one target.

References

  • targets.md (the instance table)
  • emit.md (the posture layer)
  • Phase 0, section "Core generalization steer" and the framing correction (docs/research/phase-0.md)
  • ADR-006 (SSR posture), ADR-007 (codec contract)