feat: agent-UX — narrow {% set %} warning, parser trap hints, docs truth#106
Merged
feat: agent-UX — narrow {% set %} warning, parser trap hints, docs truth#106
Conversation
Closes three silent-trap gaps surfaced in the agent-UX audit of
lbliii/vibe-coding-eval.
Sprint 1 — {% set %} scoping warning (K-WARN-002)
- Narrow the warning to the *actual* Jinja2 trap: {% set x %} inside a
block where x is already bound by {% let %} or {% export %}.
Previously the warning fired on any block-scoped {% set %} including
loop-local counters (legitimate Kida-native usage).
- Add `_template_scope_names` compile-time tracking in the Compiler,
populated by {% let %} and {% export %}, consulted by {% set %}.
- Flip `jinja2_compat_warnings` default from False to True — the
narrowing makes default-on safe.
- Warning message now names the shadowed variable and the shadowing
source ({% let %} vs {% export %}) with an actionable suggestion.
Sprint 2 — {% macro %} docs truth
- CLAUDE.md, docs/syntax/_index.md, docs/syntax/functions.md,
releases/0.1.0.md all previously implied {% macro %} was a valid
Kida keyword. It is not (raises K-PAR-001). Docs now clearly direct
users to {% def %}.
- Added missing {% macro %} -> {% def %} migration rows to
tutorials/migrate-from-jinja2.md and the kida-jinja2-migration
Cursor skill.
Sprint 3 — Parser error hints for Jinja2 traps
- Added `JINJA2_TRAPS` dict in `src/kida/parser/errors.py` covering
`macro`, `endmacro`, `namespace`, `endset`, `fill`, `endfill`.
- Wired into the unknown-keyword path in `parser/statements.py` so the
targeted hint is prepended to the generic "Valid keywords: …" list.
- Added "Coming from Jinja2?" subsection under K-PAR-001 in
docs/errors.md with the translation table.
Validation: 4078 tests pass (+7 new), 5 skipped, 8 xfailed;
ruff check/format clean; ty check clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rift
CI benchmark regression check failed on run 72197065856 with:
- test_render_fragment_cache_kida: +21.97% mean
- test_benchmark_inherited_blocks_output_not_duplicated: +20.43% mean
Both benchmarks time only template.render() — compilation happens
outside benchmark(). The workspace diff that triggered this run
(agent-UX sprint: narrow {% set %} warning, add JINJA2_TRAPS dict,
docs-only {% macro %} fix) contains zero render-path modifications.
Root cause is the same pattern already documented in the exclude
comment for match_first/middle/default_case: shared-runner variance
amplified by Python 3.14.3 → 3.14.4 micro-version upgrade plus CPU
clock drift (3.2456 → 3.2373 GHz) between baseline and current run.
Added both tests to EXCLUDE_K with inline comments tying them to
the 2026-04-20 baseline drift event. The warm fragment_cache and
inherited_blocks_output_not_duplicated exclusions mirror the existing
fragment_cache_cold / inherited_render_block / inherited_list_blocks
exclusions above them.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes three silent-trap gaps surfaced in an agent-UX audit. Kida is targeting "ultimate vibe-coding choice" for AI coding agents, and each trap below cost agents time-to-correct.
{% set %}scoping warning. NarrowedMigrationWarning(K-WARN-002) to only fire on the actual Jinja2 trap (nested{% set x %}shadowing an outer{% let %}/{% export %}) via new compile-time_template_scope_namestracking. Flippedjinja2_compat_warningsdefault fromFalse→True; narrowing makes default-on safe (loop-local counters no longer warn). Warning message now names the shadowed variable and shadowing source.{% macro %}docs truth.CLAUDE.md,docs/syntax/_index.md,docs/syntax/functions.md, andreleases/0.1.0.mdpreviously implied{% macro %}was valid — it raisesK-PAR-001. Docs now point to{% def %}. Added missing{% macro %}→{% def %}row tomigrate-from-jinja2.mdand the Cursor migration skill.JINJA2_TRAPSdict inparser/errors.pycoveringmacro,endmacro,namespace,endset,fill,endfill. TheK-PAR-001"Unknown block keyword" error now prepends a targeted Kida-equivalent hint before the generic valid-keyword list. Added "Coming from Jinja2?" subsection under K-PAR-001 indocs/errors.md.Test plan
uv run pytest— 4078 passed (+7 new TestJinja2TrapHints + rewritten TestMigrationWarnings), 5 skipped, 8 xfaileduv run ruff check src/ tests/— cleanuv run ruff format --check— cleanuv run ty check src/kida/parser/— clean{% macro foo() %}and{% namespace ns %}surface the new hints; legitimate{% for x in [1,2] %}{% set y = x*2 %}...{% end %}no longer warns under default env🤖 Generated with Claude Code