Karou's pick after U19: "start" for the larger batch. U20 is the final wave — closes the last two punt items from the V0.3 → U17 stack. Exclude For (Odoo's per-combo exclusion model) finally functional on the U17 Configure page; mixed-mode warning banner on the product detail page when Instant + Never lines coexist. With this slice the entire accumulated punt list is empty.
setLineValueExclusions({templateId, valueId, excludedValueIds}) tx-wraps a REPLACE — drops both directions anchored on valueId (forward + reverse), then re-inserts both directions for each new pair. A single (value_id) lookup at picker / generator time returns the full forbidden partner set without a UNION./cafe/products/[id]/attributes/[lineId]: <details>/<summary> multi-select grouped by sibling attribute. Auto-saves on draft change via useEffect guarded by ref + draft-equals-saved short-circuit. Summary chips below the picker show AttrName: Value.ShellProductAttributeValue.excludes? populated from attribute-pairs.ts (new SELECT joining the exclusion table). Chips render disabled (line-through + cursor-not-allowed + title="Not available with the current selection.") when forbidden. Auto-deselect useEffect sweeps prior selections that become forbidden when the user picks a sibling.regenerateVariantsForTemplate filters Cartesian combos before INSERT (drops any combo containing an excluded pair). Zero-allowed safeguard preserves the H4-X invariant: if exclusions wipe every combo, fall back to a single default variant./cafe/products/[id] inside the Attributes & Variants section, above the line editor.Set<"instant" | "never"> from draft.map(ln => attributesLibrary.find(a => a.id === ln.attributeId)?.createVariant). Banner appears when the set contains BOTH modes.product-mixed-mode-warning. Informational, not blocking — admins can save mixed-mode templates.| ✓ | Pre-flight: seed template with 2 attributes (Color × Size) via raw SQL |
| ✓ | Load-bearing UI: open Red's exclusion picker, tick Large, wait for auto-save → summary chip renders + DB has BOTH directions (forward + reverse); reload page → checkbox still ticked |
| ✓ | Generator probe: Cartesian = 4 combos, allowed = 3 after exclusion (Red+Large dropped) |
| ✓ | Add a Never attribute + line to the template via SQL → reload /cafe/products/[id] → product-mixed-mode-warning visible mentioning both Instant + Never |
| ✓ | No HTTP 5xx during the flow |
| ✓ | Cleanup: delete seeded data |
wrangler deployments list showed the deploy at 00:22 UTC, but the warm Worker on lumiere may have been mid-restart when the test fired <20s later. Solo retry without code changes: 6/6 clean. Doesn't quite match the existing feedback_phase2_cafe_multishop_solo_retry (that's specifically about POS-master suite racing the narongix chain) — this is a different shape (immediately after a fresh deploy). Not worth a new memo for one occurrence.vRed.id / vLarge.id in ${...} interpolations expecting OUTER JS scope, but those variables are defined INSIDE the probe body. Fix: compute the forbidden check inside the probe + report a boolean.inArray not in generator probe imports — added.(value_id) → excluded_value_id[] lookup returns the full forbidden partner set. Cost: 2 rows per save instead of 1; reads: 1 query instead of 1 UNION. Net win for the read-heavy POS path.| test-phase1-prod.mjs | 11/11 |
| test-phase2-sso-outdoor-prod.mjs | 6/6 |
| test-m1-prod.mjs | 10/10 |
| test-r7-prod.mjs | 14/14 |
| test-r8-prod.mjs | 4/4 |
| test-phase2-cafe-multishop-prod.mjs | 6/6 |
feedback_phase2_cafe_multishop_solo_retry.