wroclove.rb 2026 talk by Nicolò Rebughini (Nebulab). Walks through the evolution of the product-recommendation engine for Cometeer's mixed-roast coffee box — a 'virtual' product represented as five slots (1 light roast, 1 dark roast, 3 medium roasts) that must be filled with concrete SKUs from a large catalog. Version 1: an operator-maintained ordered list scanned with a few nested `if`s (roast level, caffeine level, inventory, customer dislikes); pick the first match. Version 2: add hard constraints (one coffee per roaster, no duplicate product in a box) by looping permutations with and without relaxed constraints — better boxes but poor auditability and lots of coupling. Version 3 (rewrite): split the algorithm into an explicit filtering stage (product pool → roast/caffeine/disliked/etc. filters) followed by a scoring stage using 'amplifiers' — plain Ruby objects, each initialized with a coefficient, that multiply a product's score based on one local question (e.g. 'roaster already in the box?', '1/n decay if product already in box'). ~20–48 amplifiers run per requirement; an audit trail of all multiplications is stored, plus top-three runners-up as metadata. Tweak coefficients, deploy on Fridays (subscription spikes on Sunday), observe, repeat — essentially manual training. Architecture maps onto a neural network: inputs (virtual product, product pool, customer history, box state, customer ratings) → input layer; filters → first hidden layer; amplifiers → second hidden layer; final pick → output layer. Coefficients stand in for weights (no back-propagation or gradient descent); amplification methods stand in for activation functions (different per neuron — 'a snowflake'); arbitrary adjustments stand in for biases. Conclusion: the result looks awfully like a neural network but isn't one. Proper machine learning might have been the canonical tool but would have sacrificed the auditability stakeholders demanded ('why was this coffee picked?'). The system is now being deprecated in favor of proper ML. Q&A covers concerns about user-defined weights, framing as an optimization-with-score-function problem, how manual tweaks were benchmarked (product/operations team vibe-checked resulting boxes), and working without a database — products are pulled in-memory from slow Shopify GraphQL endpoints because building a sync layer would introduce new failure modes.