Commit Graph
9 Commits
Author SHA1 Message Date
DumiFlex f68d2ece81 feat(engine): per-pick recording + apply constraints via combine_constraint_factor 2026-06-11 05:41:40 +03:00
DumiFlex 33b3600bf8 feat(engine): independent (allow-repeats) multi-pick for the wildcard pool
The pool multi-pick (PICK min-max) now honors instance.pick_independent: when true it draws WITH replacement (repeats allowed) and the count is NOT clamped to the pool size, mirroring the inline ~ flag. Default (unique, pick_k_unique) path is byte-unchanged, so existing locked seeds reproduce. Foundation for the 'Allow repeats' pool toggle; schema (instance + library default) + TS parity + UI follow.
2026-06-09 23:44:25 +03:00
DumiFlex ace0486f9d fix(engine): guard junk pick counts + warn on multi-pick constraint source 2026-06-08 21:06:35 +03:00
DumiFlex 443db49546 feat(engine): multi-select wildcard binds a list variable 2026-06-08 14:31:26 +03:00
DumiFlex 13de622c6b feat(engine): multi-tag options + boolean sub-category filters (v2)
Option sub_category -> sub_categories[] (default []). Both pool filters (instance category_filter, nested @{} ref) become boolean expressions (and/or/not/parens; comma=or) matched against an option's tag set via the shared engine/syntax/subcat_filter matcher, applied BEFORE constraints. Exclude-null is a separate flag: instance exclude_null + the trailing !null ref marker, replacing the old 'null' keyword.

4-segment ref grammar @{uuid#name:expr!null} single-sourced across tokenize.py/scan.py/pipeline.py/_constraints.py (! excluded from name/expr captures); tokenizer REF meta now carries filter_expr + exclude_null instead of a comma-split list. scan.py findall unpack sites updated for the 4th group.

validate_payload: per-option sub_categories[] must be in the registry; optional tag_groups (UI-only axes, members in-registry, <=1 group); registry names validated via subcat_filter.validate_subcat_name (rejects whitespace, boolean/ref chars, reserved words incl. null). wp_api/_validators delegates to the same function.

Constraints stay alive via a primary-tag stopgap: _apply_constraint_to_options + _record_pick use sub_categories[0] as the matrix key; true multi-tag matrix matching is SP3. Cascade fix_subcat_delete/rename + orchestrator scrub the per-option list; instance_schemas category_filter -> string. Existing engine tests migrated to the v2 shape; added tests for the ref regex, payload validation, and multi-tag pool filtering.
2026-06-07 00:43:55 +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 6921606570 feat(context): module picker + lock/internal + card indicators (#8)
Phase 5.5.4 (SPA library picker for ContextWidget) plus QA-driven polish.

* New ModulePickerModal with search, kind tabs, single + multi-pick, and
  compact filter UX (favorites/hide-added inline; category + tag chips
  behind popover with active-count badge).
* ModuleEditModal kind-aware body — wildcard option editor with
  enable/disable, weight overrides, mode picker (random/subset/pinned),
  sub-category multi-select.
* Lock + internal per-instance overrides ported and adapted: locked_seed
  derives a per-wildcard rng via sha256(seed:binding); internal hides
  bindings from the public PIPELINE_CONTEXT payload.
* Card indicators: modified dot (option-pool overrides), missing-from-
  library dot (polled hash check), in-card lock + internal toggles.
* RNG-faithful assembler preview via new /wp/api/preview/resolve; header
  shows "PREVIEW · 42". UNRESOLVED chips clickable to strip $var.
* Bulk collapse/expand toggle, focus toast w/ pulsing border overlay
  that tracks node bounds, friendly @name substitution in modal.
* Backend: new /wp/api/modules/import-from-workflow endpoint preserves
  uuid; engine emits per-module effective seeds via WP_Context UI
  payload for authoritative lock-toggle defaults.
2026-04-30 00:53:13 +03:00
DumiFlex 657fe57890 refactor(engine): wildcard handler delegates to resolve_text 2026-04-28 06:39:39 +03:00
DumiFlex 30bf13efc0 feat(engine): wildcardhandler with weighted rng and @{ref} resolution 2026-04-26 16:24:54 +03:00