Commit Graph
4 Commits
Author SHA1 Message Date
DumiFlex d41be86fae fix(engine): fold list-valued vars in derivation + converter reads 2026-06-08 20:58:59 +03:00
DumiFlex 8eeb0a8032 feat(engine): list-backed variables + var.K accessor 2026-06-08 14:21:40 +03:00
DumiFlex a8b8a6dfbd feat(engine): gate VAR token by surface — combine/derivation/assembler only
Wildcard + fixed_values surfaces are binding PRODUCERS, not consumers
— they don't read upstream \$var. Combine + derivation + assembler do
(template interpolation is their reason to exist).

Adds VarOutOfSurfaceError to engine.syntax.types + extends SurfaceKind
literal with "fixed_values". _resolve_var checks surface membership
in _VAR_SURFACES_ALLOWED frozenset; out-of-surface refs warn + render
literal \$name in lenient mode (existing default), raise in strict
mode (used by tests + dev mode).

Lenient strategy means workflows saved before this cycle keep
resolving — the warning surfaces in toast / conflict scanner without
crashing the queue.

Test fixture adjustments document the new contract:
- tests/syntax/test_resolve.py default surface flips wildcard -> combine
  (these tests cover VAR resolution mechanics, not surface gating)
- tests/syntax/test_determinism.py corpus single_var + var_in_text
  cases use surface=combine
- tests/engine/modules/test_wildcard_handler.py:
    * test_resolve_var_substitution_in_option renamed to
      test_resolve_var_in_option_renders_literal_warns + asserts new
      lenient path
    * test_resolve_pinned_mode_resolves_inline_syntax swaps \$color for
      a {red|red} alternation that DOES resolve on wildcard surface

Surface gating tests live in tests/engine/syntax/test_resolve_var_surface.py
covering all 5 surfaces + lenient vs strict modes + internal-key skip.
2026-05-08 18:22:48 +03:00
DumiFlex 227c647e86 feat(syntax): foundation types, error classes, ResolveContext Protocol 2026-04-28 03:10:27 +03:00