Kida 0.7.0
strict-by-default release — strict_undefined flips to True, parser error hints for Jinja2 traps, jinja2_compat_warnings on by default, and render-surface hardening
Released 2026-04-20.
Kida 0.7.0 finishes the "strict by default" transition announced in 0.6.0.strict_undefined=True is now the default, parser errors for Jinja2-only keywords include targeted migration hints, and the {% set %} scoping trap now emits a MigrationWarningout of the box. Also: RenderCapture for block-level capture and search indexing, render-surface parity corpus, and leaf-node hardening.
Breaking
strict_undefined=Trueis the default — Missing variables and missing attribute access now raiseUndefinedErrorwith a descriptive message distinguishing variable / attribute / key lookups. Previously missing attributes silently rendered as"", contradicting the documented stance. Escape hatch: passstrict_undefined=Falseon theEnvironmentto restore the prior lenient behavior as a transitional shim. (#107)
Added
- Parser error hints for Jinja2 traps —
K-PAR-001now prepends a targeted migration suggestion before the generic keyword list. Coversmacro→{% def %},endmacro/endset→ unified{% end %},namespace→{% let %}/{% export %}, andfill/endfill→{% slot %}inside{% call %}. The trap table inkida.parser.errors.JINJA2_TRAPSis data-only — trivial to extend. (#106) - RenderCapture — Block-level capture, search indexing, and freeze cache. (#99)
- Reject non-top-level
{% def %}/{% region %}— Definitions nested inside other blocks fail fast at parse time with a retargeted Undefined hint. (#100) - Python 3.14+ idioms —
TypedDict,match/case, and__slots__adopted across the codebase. (#98) - Render-surface parity corpus & sandbox fuzz — HTML / terminal / markdown parity corpus, fragment scaffolding, and sandbox fuzz harness. (#103)
AGENTS.md— Contributor safety/values guide for agents working in this repo. (#104)
Fixed
- Docs:
{% macro %}false claim corrected acrossCLAUDE.md, migration docs, and release notes.{% macro %}is not a valid Kida keyword — rename to{% def %}. (#106) CoercionWarningcoverage — Now extends to collection / number filters; lint gates added. (#97)PrecedenceWarning— parenthesized nullish fallback — Warning no longer fires when the nullish fallback is explicitly parenthesized. (#96)- GitHub Action default Python version — Bumped from 3.12 to 3.14 to match project support. (#94)
- Leaf-node hardening — Bug fixes, dead-code removal, test-gap closure across parser / compiler leaf nodes. (#105)
Changed
jinja2_compat_warningsdefaults toTrue—MigrationWarning(K-WARN-002) fires out of the box on the canonical{% set %}scoping trap (nested{% set x %}shadowing an outer{% let x %}or{% export x %}). The trigger is narrowly scoped — fresh names used for legitimate block-scoped work do not warn. Suppress viaEnvironment(jinja2_compat_warnings=False)orwarnings.filterwarnings("ignore", category=MigrationWarning). (#106)
Upgrade Notes
- Audit templates for implicit
None/ missing attribute access. Anywhere you relied on{{ user.nickname }}silently rendering""whennicknameis missing, switch to one of:{% if user.nickname is defined and user.nickname %}{{ user.nickname }}{% end %}{{ user.nickname ?? "" }}{{ user.nickname | default("") }}
- Temporary escape hatch:
Environment(strict_undefined=False)restores prior lenient behavior. Plan to remove this before the next release. - Expect new
MigrationWarningoutput if your templates hit the{% set %}scoping trap. Fix the trap (usually: switch to{% let %}or{% export %}) or filter the warning. - GitHub Action version tag updated to
@v0.7.0.