Files
Dumitru Picalau 26df88216f feat(ai): chat round, node negatives, pack builder quality fixes (#69)
Chat round (explain on selection, page starters, reactions, streamed notes, thinking), negatives on node fixed values and combines, Pack builder quality fixes from 31 real-model eval rounds, and small-model support (scoped tools, checked tool arguments on local servers, two-phase steps, fixed prefix shown in Test connection).
2026-10-17 01:23:58 +02:00

812 lines
34 KiB
Python

"""Simulation of user's reported chain — verifies constraints actually
fire end-to-end through the engine.
Chain order (matches screenshot 2026-05-26):
1. hair_style wildcard (source for hair_x_mood)
2. shirt wildcard (source for shirt_x_color_compat)
3. hair_x_mood constraint #1 (source=hair_style, target=mood)
4. shirt_x_color_compat constraint #1 (source=shirt, target=color)
5. backdrop wildcard — options carry `@{color}` AND `@{mood}` refs
6. (final framing bundle)
6a. hair_x_mood constraint #2 (second instance of same constraint)
6b. mood wildcard (top-level instance)
6c. outfit wildcard
Expected behaviour (SP3 reach selector, default `all`):
- hair_x_mood #1 (registered first) covers BOTH the backdrop nested
`@{mood}` AND the top-level `mood` → hit count 2
- shirt_x_color_compat covers backdrop's nested `@{color}` → hit count 1
- hair_x_mood #2 (registered after backdrop) covers only the
top-level `mood` → hit count 1
- every constraint has a non-zero hit count in `__wp_constraint_hits__`
- zero `constraint_never_applied` warnings
Pre-SP3 this chain rode the one-shot consumed-set (each constraint
fired exactly once); SP3 retired that for the reach selector, so the
default `all` constraints now re-weight every downstream occurrence.
If any of those expectations fail the constraint runtime is broken in
some subtle way — useful diagnostic for the "never_applied" warnings
the user saw on iteration 1.
"""
from __future__ import annotations
from engine.pipeline import PipelineEngine
# UUIDs — 8 hex chars, matching the runtime regex `[0-9a-f]{8}`.
HAIR_STYLE = "a1a1a1a1"
SHIRT = "b2b2b2b2"
MOOD = "c3c3c3c3"
COLOR = "d4d4d4d4"
BACKDROP = "e5e5e5e5"
OUTFIT = "f6f6f6f6"
CN_HAIR_X_MOOD_1 = "cc111111"
CN_SHIRT_X_COLOR = "cc222222"
CN_HAIR_X_MOOD_2 = "cc333333"
def _wildcard(uuid: str, var: str, options, sub_categories=None):
"""Match the shape `WildcardHandler` expects post-coerce."""
return {
"id": uuid,
"type": "wildcard",
"enabled": True,
"payload": {
"var_binding": var,
"options": options,
"sub_categories": list(sub_categories or []),
},
}
def _constraint(module_id: str, source_uuid: str, target_uuid: str, matrix=None, uid=None):
out = {
"id": module_id,
"type": "constraint",
"enabled": True,
"payload": {
"source_wildcard_id": source_uuid,
"target_wildcard_id": target_uuid,
"matrix": matrix or {},
"exceptions": [],
},
}
# Per-instance uid — distinct from the library `id`. Two sibling
# instances of one library constraint entry share `id` but get their
# own `_uid`; the engine keys the SP3 hit counter on `_uid` so they
# count independently.
if uid is not None:
out["_uid"] = uid
return out
def _build_catalog():
"""Catalog seen by `_resolve_ref` for nested `@{uuid}` lookups.
Includes mood + color because backdrop references them, plus every
other wildcard so the constraint sources are findable."""
return {
HAIR_STYLE: _wildcard(HAIR_STYLE, "hair_style", [
{"id": "h1", "value": "long", "weight": 1, "sub_categories": ["long"]},
{"id": "h2", "value": "short", "weight": 1, "sub_categories": ["short"]},
]),
SHIRT: _wildcard(SHIRT, "shirt", [
{"id": "s1", "value": "tee", "weight": 1, "sub_categories": ["casual"]},
{"id": "s2", "value": "blouse", "weight": 1, "sub_categories": ["formal"]},
]),
MOOD: _wildcard(MOOD, "mood", [
{"id": "m1", "value": "BAD_warm", "weight": 1, "sub_categories": ["warm"]},
{"id": "m2", "value": "ok_cool", "weight": 1, "sub_categories": ["cool"]},
]),
COLOR: _wildcard(COLOR, "color", [
{"id": "c1", "value": "BAD_red", "weight": 1, "sub_categories": ["warm"]},
{"id": "c2", "value": "ok_blue", "weight": 1, "sub_categories": ["cool"]},
]),
BACKDROP: _wildcard(BACKDROP, "backdrop", [
# Carrier option — references BOTH nested wildcards in one
# option value so a single backdrop roll exercises both
# constraints on the nested-ref path.
{"id": "bd1", "value": f"under @{{{COLOR}}} sky with @{{{MOOD}}} air", "weight": 1},
]),
OUTFIT: _wildcard(OUTFIT, "outfit", [
{"id": "o1", "value": "jacket", "weight": 1},
]),
}
def _build_modules():
"""Flat module list — same order as user's WP_Context view."""
return [
_wildcard(HAIR_STYLE, "hair_style", [
{"id": "h1", "value": "long", "weight": 1, "sub_categories": ["long"]},
]),
_wildcard(SHIRT, "shirt", [
{"id": "s1", "value": "tee", "weight": 1, "sub_categories": ["casual"]},
]),
_constraint(
CN_HAIR_X_MOOD_1, HAIR_STYLE, MOOD,
# Matrix: source sub_category "long" excludes target sub_category "warm".
# That kills the BAD_warm mood option, leaving only ok_cool.
matrix={"long": {"warm": {"mode": "exclude", "factor": 1}}},
),
_constraint(
CN_SHIRT_X_COLOR, SHIRT, COLOR,
# Source "casual" excludes color "warm" — kills BAD_red.
matrix={"casual": {"warm": {"mode": "exclude", "factor": 1}}},
),
_wildcard(BACKDROP, "backdrop", [
{"id": "bd1", "value": f"under @{{{COLOR}}} sky with @{{{MOOD}}} air", "weight": 1},
]),
# Final framing bundle contents (engine sees them flat).
_constraint(
CN_HAIR_X_MOOD_2, HAIR_STYLE, MOOD,
matrix={"long": {"warm": {"mode": "exclude", "factor": 1}}},
),
_wildcard(MOOD, "mood", [
{"id": "m1", "value": "BAD_warm", "weight": 1, "sub_categories": ["warm"]},
{"id": "m2", "value": "ok_cool", "weight": 1, "sub_categories": ["cool"]},
]),
_wildcard(OUTFIT, "outfit", [
{"id": "o1", "value": "jacket", "weight": 1},
]),
]
def _run(seed: int = 7) -> dict:
"""Drive the real `PipelineEngine` with a seeded ctx that has the
library catalog pre-populated — same shape `WP_Context.execute`
builds via `deserialize_node_input` + `_expand_catalog_via_live_db`."""
ctx = {"__wp_catalog__": _build_catalog()}
engine = PipelineEngine()
return engine.run(_build_modules(), ctx=ctx, seed=seed)
# ─────────────────────────────────────────────────────────────────────
# Tests
def test_chain_runs_without_engine_exception():
ctx = _run()
assert "__wp_trace__" in ctx
def test_backdrop_resolves_with_both_nested_refs():
"""Backdrop's only option carries `@{color}` and `@{mood}`. After
resolve the `backdrop` ctx var should hold the rolled color + mood
inline — proves both nested refs actually fired."""
ctx = _run()
val = ctx.get("backdrop") or ""
assert "sky with" in val, f"backdrop didn't resolve: {val!r}"
# Both nested wildcards rolled — their resolved values should be
# substituted into the carrier text.
assert "@{" not in val, f"unresolved ref token in backdrop: {val!r}"
def test_constraint_hair_x_mood_1_covers_both_mood_occurrences():
"""hair_x_mood #1 (registered first) covers BOTH the backdrop nested
@{mood} and the top-level mood under default `all` → hit count 2."""
ctx = _run()
hits = ctx.get("__wp_constraint_hits__", {})
assert hits.get(CN_HAIR_X_MOOD_1) == 2, (
f"hair_x_mood #1 expected to cover both mood occurrences. hits={hits}, "
f"warnings={[w.get('detail') for w in ctx.get('__wp_warnings__', [])]}"
)
def test_constraint_shirt_x_color_fires():
"""shirt_x_color_compat covers backdrop's nested @{color} → hit count 1
(the only color occurrence downstream of it)."""
ctx = _run()
hits = ctx.get("__wp_constraint_hits__", {})
assert hits.get(CN_SHIRT_X_COLOR) == 1, (
f"shirt_x_color_compat never fired. hits={hits}, "
f"warnings={[w.get('detail') for w in ctx.get('__wp_warnings__', [])]}"
)
def test_constraint_hair_x_mood_2_fires_on_top_level_only():
"""hair_x_mood #2 registers AFTER backdrop, so it misses backdrop's
nested mood (resolved earlier) and covers only the top-level mood in
final framing → hit count 1."""
ctx = _run()
hits = ctx.get("__wp_constraint_hits__", {})
assert hits.get(CN_HAIR_X_MOOD_2) == 1, (
f"hair_x_mood #2 never fired. hits={hits}, "
f"warnings={[w.get('detail') for w in ctx.get('__wp_warnings__', [])]}"
)
def test_no_constraint_never_applied_warnings():
"""End-of-run check should emit zero never_applied warnings — all
three constraints fired (two on backdrop's nested refs + one on
top-level mood)."""
ctx = _run()
never_applied = [
w for w in ctx.get("__wp_warnings__", [])
if w.get("type") == "constraint_never_applied"
]
detail = [w.get("detail") for w in never_applied]
assert never_applied == [], (
f"expected zero never_applied warnings, got {len(never_applied)}: {detail}"
)
def test_top_level_mood_respects_constraint():
"""hair_style rolled 'long' → matrix excludes 'warm' sub_category →
top-level mood must pick `ok_cool`, never `BAD_warm`."""
ctx = _run()
mood_val = ctx.get("mood") or ""
assert mood_val == "ok_cool", (
f"mood ignored constraint: rolled {mood_val!r} but matrix "
f"should have excluded the 'warm' option"
)
def test_backdrop_nested_color_respects_constraint():
"""Backdrop's `@{color}` resolution should also be constrained by
shirt_x_color_compat — rolled color sub_category must NOT be 'warm'
(shirt rolled 'casual' → matrix excludes 'warm')."""
ctx = _run()
val = ctx.get("backdrop") or ""
# The carrier text is `under <color> sky with <mood> air`.
# `BAD_red` is the warm color option — must not appear.
assert "BAD_red" not in val, (
f"backdrop nested @{{color}} ignored constraint: {val!r}"
)
def test_multiple_seeds_consistent_constraint_firing():
"""Sanity check across seeds — every seed should fire all three
constraints (the only roll that varies is which option within a
given sub-category wins, not whether the constraint fires)."""
for seed in (0, 1, 7, 42, 99, 1234):
ctx = {"__wp_catalog__": _build_catalog()}
engine = PipelineEngine()
ctx = engine.run(_build_modules(), ctx=ctx, seed=seed)
hits = ctx.get("__wp_constraint_hits__", {})
for cid in (CN_HAIR_X_MOOD_1, CN_SHIRT_X_COLOR, CN_HAIR_X_MOOD_2):
assert hits.get(cid, 0) >= 1, (
f"seed {seed}: constraint {cid} never fired, hits={hits}"
)
# ─────────────────────────────────────────────────────────────────────
# Carrier that doesn't resolve the ref (SP3: no claim, no spill — the
# constraint simply applies on the next ACTUAL target resolution).
def test_carrier_without_ref_does_not_block_later_target():
"""SP3 retired the carrier-claim failsafe. A carrier (backdrop) that
rolls an option WITHOUT the @{target} ref does NOT count as a target
occurrence — the constraint just applies on the next ACTUAL target
resolution (the top-level color after backdrop), which is now
constrained. (Pre-SP3 the carrier "claimed" the one-shot so the
later target rolled free — that consumed-set model is gone.)
Chain: shirt → shirt_x_color constraint → backdrop (rolls a no-ref
option) → color (top-level AFTER backdrop). The top-level color must
be CONSTRAINED (warm excluded → never warm_red)."""
SHIRT = "b2b2b2b2"
COLOR = "a361dbdc"
BACKDROP = "b0b0b0b0"
CN = "cc222222"
modules = [
_wildcard(SHIRT, "shirt", [
{"id": "s1", "value": "tee", "weight": 1, "sub_categories": ["casual"]},
]),
_constraint(
CN, SHIRT, COLOR,
matrix={"casual": {"warm": {"mode": "exclude", "factor": 1}}},
),
# Backdrop's only reachable option has no ref (the weight-0
# ref option never wins) — so backdrop resolves no @{color}.
_wildcard(BACKDROP, "backdrop", [
{"id": "bd1", "value": "plain studio", "weight": 1},
{"id": "bd2", "value": f"with @{{{COLOR}}}", "weight": 0},
]),
# Top-level color AFTER backdrop — IS constrained now.
_wildcard(COLOR, "color", [
{"id": "c1", "value": "warm_red", "weight": 1, "sub_categories": ["warm"]},
{"id": "c2", "value": "cool_blue", "weight": 1, "sub_categories": ["cool"]},
]),
]
catalog = {
COLOR: _wildcard(COLOR, "color", [
{"id": "c1", "value": "warm_red", "weight": 1, "sub_categories": ["warm"]},
{"id": "c2", "value": "cool_blue", "weight": 1, "sub_categories": ["cool"]},
]),
}
for seed in range(20):
ctx = {"__wp_catalog__": dict(catalog)}
ctx = PipelineEngine().run(modules, ctx=ctx, seed=seed)
hits = ctx.get("__wp_constraint_hits__", {})
# The top-level color is the single actual occurrence → fired once.
assert hits.get(CN) == 1, f"seed {seed}: expected one firing, hits={hits}"
# Constrained → warm excluded → never warm_red.
assert "warm_red" not in (ctx.get("color") or ""), (
f"seed {seed}: top-level color ignored constraint (rolled warm)"
)
def test_carrier_null_pick_does_not_count_as_occurrence():
"""A carrier (backdrop) whose winning option is empty/null resolves
no @{color}, so it does NOT count as a target occurrence — no
never_applied warning is emitted on its account (the constraint
legitimately found no downstream color this run). Under SP3 there's
nothing to "claim"; hits stays 0 and the never_applied warning is
the correct signal.
Chain: shirt → shirt_x_color → backdrop (winning option empty,
weight-0 option carries @{color}). No actual color resolution
anywhere → constraint never fires → exactly one never_applied."""
SHIRT = "b2b2b2b2"
COLOR = "a361dbdc"
BACKDROP = "b0b0b0b0"
CN = "cc222222"
modules = [
_wildcard(SHIRT, "shirt", [
{"id": "s1", "value": "tee", "weight": 1, "sub_categories": ["casual"]},
]),
_constraint(
CN, SHIRT, COLOR,
matrix={"casual": {"warm": {"mode": "exclude", "factor": 1}}},
),
# Backdrop: the winning option is empty (null); the weight-0
# option carries @{color} but never wins → no color resolves.
_wildcard(BACKDROP, "backdrop", [
{"id": "bd_null", "value": "", "weight": 1},
{"id": "bd_color", "value": f"@{{{COLOR}}}", "weight": 0},
]),
]
catalog = {
COLOR: _wildcard(COLOR, "color", [
{"id": "c1", "value": "warm_red", "weight": 1, "sub_categories": ["warm"]},
{"id": "c2", "value": "cool_blue", "weight": 1, "sub_categories": ["cool"]},
]),
}
for seed in (0, 1, 7, 42, 99):
ctx = {"__wp_catalog__": dict(catalog)}
ctx = PipelineEngine().run(modules, ctx=ctx, seed=seed)
hits = ctx.get("__wp_constraint_hits__", {})
warns = [
w for w in ctx.get("__wp_warnings__", [])
if w.get("type") == "constraint_never_applied"
]
# No actual color resolution → constraint never fired.
assert hits.get(CN, 0) == 0, f"seed {seed}: unexpected firing, hits={hits}"
# The target IS present in the chain (carrier + top-level absent;
# only the weight-0 carrier ref) → one never_applied warning.
assert len(warns) == 1, f"seed {seed}: expected one never_applied, got {warns}"
def test_sibling_constraints_same_library_uuid_are_independent_oneshots():
"""User's real case (2026-05-26): TWO hair_x_mood instances share
the SAME library uuid (id) but have distinct `_uid`. The pair badge
shows #1 → backdrop (carrier), #2 → mood (direct top-level). The
engine must honour that: backdrop claims instance #1, the top-level
mood claims instance #2 → mood IS constrained. Pre-fix both keyed on
the shared library uuid, so backdrop's claim spent BOTH and mood
rolled unconstrained.
Chain: hair_style → hair_x_mood#1 (uid A) → hair_x_mood#2 (uid B) →
backdrop (carries @{mood}, rolls null) → mood (top-level)."""
HAIR = "aaaa0001"
MOOD = "c14e7527"
BACKDROP = "b0b0b0b0"
LIB_CID = "e41f5bc4" # shared library uuid for both hair_x_mood
modules = [
_wildcard(HAIR, "hair_style", [
{"id": "h1", "value": "long", "weight": 1, "sub_categories": ["long"]},
]),
# Two instances, SAME library id, distinct _uid → independently
# keyed in the hit counter (cid = `_uid`).
_constraint(
LIB_CID, HAIR, MOOD,
matrix={"long": {"warm": {"mode": "exclude", "factor": 1}}},
uid="uidA",
),
_constraint(
LIB_CID, HAIR, MOOD,
matrix={"long": {"warm": {"mode": "exclude", "factor": 1}}},
uid="uidB",
),
# Backdrop carries @{mood} (weight-0 ref option) but rolls null —
# resolves no nested mood.
_wildcard(BACKDROP, "backdrop", [
{"id": "bd_null", "value": "", "weight": 1},
{"id": "bd_mood", "value": f"@{{{MOOD}}}", "weight": 0},
]),
# Top-level mood AFTER backdrop — the single actual occurrence.
_wildcard(MOOD, "mood", [
{"id": "m1", "value": "warm_bad", "weight": 1, "sub_categories": ["warm"]},
{"id": "m2", "value": "cool_ok", "weight": 1, "sub_categories": ["cool"]},
]),
]
catalog = {
MOOD: _wildcard(MOOD, "mood", [
{"id": "m1", "value": "warm_bad", "weight": 1, "sub_categories": ["warm"]},
{"id": "m2", "value": "cool_ok", "weight": 1, "sub_categories": ["cool"]},
]),
}
for seed in range(15):
ctx = {"__wp_catalog__": dict(catalog)}
ctx = PipelineEngine().run(modules, ctx=ctx, seed=seed)
hits = ctx.get("__wp_constraint_hits__", {})
# Both instances register before the top-level mood, so under the
# default `all` reach BOTH cover it independently → each fired once.
# (The per-`_uid` keying keeps siblings distinct — pre-SP3 both
# keyed on the shared library uuid and a single fire spent both.)
assert hits.get("uidA") == 1 and hits.get("uidB") == 1, (
f"seed {seed}: both sibling instances should fire independently "
f"(hits={hits})"
)
# mood was constrained → never the warm option.
assert ctx.get("mood") == "cool_ok", (
f"seed {seed}: top-level mood rolled {ctx.get('mood')!r} — it "
f"wasn't constrained"
)
# No leftover warnings.
warns = [
w for w in ctx.get("__wp_warnings__", [])
if w.get("type") == "constraint_never_applied"
]
assert warns == [], f"seed {seed}: unexpected warnings {warns}"
def test_constraint_skipped_when_source_not_picked_yet():
"""A constraint whose source rolls AFTER it (so the source pick
isn't recorded when the target would be reached) does not apply —
it's skipped with an unknown_constraint_source signal rather than
firing on stale/absent source data. (Pre-SP3 this was framed as the
carrier-claim deferring; SP3 has no claim — the apply path itself
skips + warns when the source pick is missing.)
Chain: constraint(src=shirt) → backdrop (no-ref roll) → shirt. The
constraint never reaches an actual color target AND its source rolls
last, so it never fires."""
SHIRT = "b2b2b2b2"
COLOR = "a361dbdc"
BACKDROP = "b0b0b0b0"
CN = "cc222222"
modules = [
_constraint(
CN, SHIRT, COLOR,
matrix={"casual": {"warm": {"mode": "exclude", "factor": 1}}},
),
_wildcard(BACKDROP, "backdrop", [
{"id": "bd1", "value": "plain studio", "weight": 1},
{"id": "bd2", "value": f"with @{{{COLOR}}}", "weight": 0},
]),
_wildcard(SHIRT, "shirt", [
{"id": "s1", "value": "tee", "weight": 1, "sub_categories": ["casual"]},
]),
]
ctx = {"__wp_catalog__": {}}
ctx = PipelineEngine().run(modules, ctx=ctx, seed=0)
hits = ctx.get("__wp_constraint_hits__", {})
assert hits.get(CN, 0) == 0, (
f"constraint fired despite no actual target resolution + source "
f"picked last (hits={hits})"
)
def test_never_applied_message_distinguishes_present_vs_absent():
"""The end-of-run warning wording differs by cause: target present
in chain (ordering issue) vs target uuid absent (typo)."""
# Absent target — no instance, no carrier anywhere.
GHOST = "deadbeef"
modules_absent = [
_wildcard("11111111", "src", [
{"id": "s1", "value": "a", "weight": 1, "sub_categories": ["x"]},
]),
_constraint("22222222", "11111111", GHOST),
]
ctx = PipelineEngine().run(modules_absent, ctx={"__wp_catalog__": {}}, seed=0)
w = next(
x for x in ctx["__wp_warnings__"]
if x.get("type") == "constraint_never_applied"
)
assert w["detail"]["target_present"] is False
assert "no @{deadbeef}" in w["message"]
# Present target — instance exists but rolled BEFORE the constraint.
TGT = "33333333"
modules_present = [
_wildcard(TGT, "tgt", [
{"id": "t1", "value": "early", "weight": 1, "sub_categories": ["warm"]},
]),
_wildcard("11111111", "src", [
{"id": "s1", "value": "a", "weight": 1, "sub_categories": ["x"]},
]),
_constraint("22222222", "11111111", TGT),
]
ctx = PipelineEngine().run(modules_present, ctx={"__wp_catalog__": {}}, seed=0)
w = next(
x for x in ctx["__wp_warnings__"]
if x.get("type") == "constraint_never_applied"
)
assert w["detail"]["target_present"] is True
assert w["detail"]["ref_only"] is False
assert w["severity"] == "warn"
assert "is in the chain" in w["message"]
# Target reached only through a ref in an option this run didn't draw
# (a recipe wildcard): info, and it says so.
carrier = _wildcard("44444444", "outfit", [
{"id": "r1", "value": "plain", "weight": 1},
{"id": "r2", "value": "@{33333333}", "weight": 0},
])
modules_ref = [
_wildcard("11111111", "src", [
{"id": "s1", "value": "a", "weight": 1, "sub_categories": ["x"]},
]),
_constraint("22222222", "11111111", TGT),
carrier,
]
ctx = PipelineEngine().run(modules_ref, ctx={"__wp_catalog__": {}}, seed=0)
w = next(
x for x in ctx["__wp_warnings__"]
if x.get("type") == "constraint_never_applied"
)
assert w["detail"]["ref_only"] is True
assert w["severity"] == "info"
assert "none of them was drawn" in w["message"]
# ─────────────────────────────────────────────────────────────────────
# Cross-node propagation regression (2026-05-26)
#
# Before the original fix, two sequential WP_Context nodes downstream
# of each other duplicated `constraint_never_applied` warnings: Context
# A ran the never_applied check at end of run + emitted warnings, then
# Context B inherited `__wp_constraints__` (which IS cross-node) but NOT
# the constraint bookkeeping (which used to NOT propagate), so B re-ran
# the same check with fresh state and re-warned for every constraint A
# already applied. The user saw 4 warnings for a 3-constraint chain.
# SP3 swapped the consumed-set for `__wp_constraint_hits__`, which
# stays in the cross-node key set for the same reason.
#
# Repro: build A's bucket + hits via PipelineEngine, copy the same
# pattern the cross-node copy in `WP_Context.execute` does, run a
# second pipeline on a different module set, then count warnings after
# the `build_payload` merge.
def test_end_of_run_dedupes_warnings_by_cid():
"""Two sibling constraint instances with the same library uuid
register two entries in the bucket. End-of-run check used to emit
a warning per entry — now emits one per distinct cid."""
# Use a target uuid that NEVER rolls so neither constraint can
# fire. Two siblings, same library uuid, registered twice.
GHOST_TGT = "00000000"
modules = [
# Source for both — needs to roll so source_pick exists.
_wildcard("11111111", "src", [
{"id": "s1", "value": "a", "weight": 1, "sub_categories": ["x"]},
]),
# Two sibling constraints, same library uuid → same
# `__constraint_module_id__`.
_constraint("22222222", "11111111", GHOST_TGT),
_constraint("22222222", "11111111", GHOST_TGT),
]
ctx = {"__wp_catalog__": {}}
ctx = PipelineEngine().run(modules, ctx=ctx, seed=0)
never_applied = [
w for w in ctx.get("__wp_warnings__", [])
if w.get("type") == "constraint_never_applied"
]
assert len(never_applied) == 1, (
f"expected 1 deduped warning, got {len(never_applied)}: "
f"{[w.get('module_id') for w in never_applied]}"
)
def test_constraint_hits_propagate_cross_node():
"""`__wp_constraint_hits__` must be in cross-node-internals so a
downstream Context shares the SP3 reach-selector counters (first/next
coverage spans nodes) and doesn't re-warn constraints already applied
upstream. Simulates the WP_Context.execute cross-node copy step + the
build_payload warning dedup."""
from wp_nodes.types import _CROSS_NODE_INTERNAL_KEYS, build_payload
assert "__wp_constraint_hits__" in _CROSS_NODE_INTERNAL_KEYS, (
"constraint hit counter must propagate cross-node — otherwise "
"downstream Contexts reset first/next counters and re-warn every "
"constraint upstream already applied"
)
# Sanity: build_payload writes the hit counter into internals
# (verifies _CROSS_NODE_INTERNAL_KEYS is actually consulted).
ctx = {
"__wp_constraint_hits__": {"abc12345": 2},
"__wp_constraints__": [],
"__wp_picks__": {},
"__wp_trace__": [],
"__wp_warnings__": [],
}
payload = build_payload(ctx, upstream_debug={}, seed=0)
assert payload.internals.get("__wp_constraint_hits__") == {"abc12345": 2}
def test_constraint_targets_next_color_not_source_nested():
"""User's mental model (2026-05-26), still true under SP3's
downstream-relative reach: when the SOURCE wildcard's own option
carries a nested `@{target}` ref AND the constraint sits after the
source, the constraint does NOT reach the source's own nested roll
(it resolved before the constraint registered). It reaches the NEXT
target occurrence downstream — e.g. a `@{color}` inside a backdrop
wildcard placed after the constraint.
Chain: shirt (option = `@{color} t-shirt`) → shirt_x_color
constraint → backdrop (option = `studio with @{color} accents`).
Expected: shirt's nested color rolls FREE (no constraint yet),
backdrop's nested color is CONSTRAINED (warm excluded → ok_blue),
constraint fires once, zero warnings."""
SHIRT = "b2b2b2b2"
COLOR = "a361dbdc"
BACKDROP = "b0219910"
CN = "cc222222"
modules = [
_wildcard(SHIRT, "shirt", [
{
"id": "s1", "value": f"@{{{COLOR}}} t-shirt", "weight": 1,
"sub_categories": ["casual"],
},
]),
_constraint(
CN, SHIRT, COLOR,
matrix={"casual": {"warm": {"mode": "exclude", "factor": 1}}},
),
_wildcard(BACKDROP, "backdrop", [
{"id": "bd1", "value": f"studio with @{{{COLOR}}} accents", "weight": 1},
]),
]
catalog = {
COLOR: _wildcard(COLOR, "color", [
{"id": "c1", "value": "BAD_red", "weight": 1, "sub_categories": ["warm"]},
{"id": "c2", "value": "ok_blue", "weight": 1, "sub_categories": ["cool"]},
]),
}
for seed in (0, 1, 7, 42, 99):
ctx = {"__wp_catalog__": dict(catalog)}
ctx = PipelineEngine().run(modules, ctx=ctx, seed=seed)
hits = ctx.get("__wp_constraint_hits__", {})
warns = [
w for w in ctx.get("__wp_warnings__", [])
if w.get("type") == "constraint_never_applied"
]
backdrop_val = ctx.get("backdrop") or ""
# Backdrop's color is the only occurrence AFTER the constraint
# (shirt's nested color resolved before it) → fired once.
assert hits.get(CN) == 1, (
f"seed {seed}: constraint didn't fire on backdrop's color, hits={hits}"
)
assert warns == [], f"seed {seed}: unexpected warnings {warns}"
# Backdrop's nested color must respect the constraint → ok_blue.
assert "BAD_red" not in backdrop_val, (
f"seed {seed}: backdrop color ignored constraint: {backdrop_val!r}"
)
def test_build_payload_dedupes_constraint_never_applied():
"""`build_payload` merges upstream + this-run warnings. Without
dedup, the same constraint_never_applied row from A's end-of-run
appears AGAIN in B's end-of-run (because B inherited the constraint
bucket + ran the check again). Dedup key is (type, module_id)."""
from wp_nodes.types import build_payload
upstream_debug = {
"__wp_warnings__": [
{
"type": "constraint_never_applied",
"severity": "warn",
"module_id": "ghost001",
"detail": {"constraint_id": "ghost001"},
"message": "...",
},
],
}
ctx = {
"__wp_warnings__": [
# Same constraint id — should be deduped against upstream.
{
"type": "constraint_never_applied",
"severity": "warn",
"module_id": "ghost001",
"detail": {"constraint_id": "ghost001"},
"message": "...",
},
# Different cid — should survive.
{
"type": "constraint_never_applied",
"severity": "warn",
"module_id": "ghost002",
"detail": {"constraint_id": "ghost002"},
"message": "...",
},
# Unrelated warning type — not deduped.
{
"type": "unknown_wildcard_ref",
"severity": "warn",
"module_id": "x",
"message": "...",
},
],
"__wp_trace__": [],
"__wp_constraints__": [],
"__wp_picks__": {},
"__wp_constraint_hits__": {},
}
payload = build_payload(ctx, upstream_debug=upstream_debug, seed=0)
out_warnings = payload.debug["__wp_warnings__"]
cids = [
w.get("module_id") for w in out_warnings
if w.get("type") == "constraint_never_applied"
]
# One ghost001 (the duplicate dropped), one ghost002.
assert cids == ["ghost001", "ghost002"], f"unexpected dedup result: {cids}"
# Non-constraint warning survived unchanged.
assert any(w.get("type") == "unknown_wildcard_ref" for w in out_warnings)
def test_build_payload_propagates_loop_internals():
"""Loop bookkeeping must survive the socket boundary so a SECOND
chained WP_Context (the one the user wired rgthree Seed into) still
varies its seed per iteration + honours override. Pre-fix only the
first ContextLoop child saw these; downstream defaulted loop_index=0
+ seed_override=None, so its seed was identical every iteration and
override was ignored (2026-05-26)."""
from wp_nodes.types import build_payload
ctx = {
"__wp_loop_index__": 3,
"__wp_seed_override__": 12345,
"__wp_loop_seeds__": [100, 200, 300, 400],
"__wp_trace__": [],
"__wp_warnings__": [],
"__wp_constraints__": [],
"__wp_picks__": {},
"__wp_constraint_hits__": {},
}
payload = build_payload(ctx, upstream_debug={}, seed=0)
assert payload.internals.get("__wp_loop_index__") == 3
assert payload.internals.get("__wp_seed_override__") == 12345
assert payload.internals.get("__wp_loop_seeds__") == [100, 200, 300, 400]
def test_effective_chain_seed_varies_per_iteration_with_external_seed():
"""End-to-end seed-variation proof for an external (link-driven)
seed: even when widget_seed is a FIXED value (simulating rgthree
Seed driving the input), each iteration's loop_index produces a
distinct chain seed. This is what a downstream chained context now
gets once the loop internals propagate."""
from engine.seed_derive import effective_chain_seed
fixed_external = 303816870871154 # a rgthree-style fixed seed
# No override — pure widget_seed + loop_index variation.
seeds = [
effective_chain_seed(
widget_seed=fixed_external, seed_override=None, loop_index=i,
)
for i in range(4)
]
assert len(set(seeds)) == 4, f"iterations didn't vary: {seeds}"
# iteration 0 is the unshifted base (backwards-compat).
assert seeds[0] == fixed_external & 0xFFFFFFFFFFFFFFFF
# With override ON, the derived series replaces the external seed.
overridden = [
effective_chain_seed(
widget_seed=fixed_external, seed_override=900 + i, loop_index=i,
)
for i in range(4)
]
# iteration 0 base is the override, not the external seed.
assert overridden[0] == 900
assert all(s != fixed_external for s in overridden[1:]), (
"override didn't replace the external seed"
)