feat: MPS-24 — auto-hydrate products into existing tags on create/edit

Operator: new products / edited descriptions should auto-file into the
shop's existing categories without manual tagging.

- lib/tag_suggest.py:auto_hydrate_tags(dbsession, product) — stem-match
  title+description against the shop's EXISTING tag names (reuses
  tokenize/simple_stem; every stem of the tag name must be in the
  product stem set, so unigram 'Holiday' and phrase 'First Grade' both
  work). ADDITIVE (never removes), IDEMPOTENT, never CREATES tags
  (inventing categories stays suggest-then-approve).
- views/product.py:_auto_hydrate_and_flash wired into product_new
  (create), product_edit_description (markup desc editor), and
  product_edit (when title/desc changed, AFTER the explicit comma-tag
  sync so it's purely additive).
- Tests: TestAutoHydrateTags (3, integration) +
  test_new_product_auto_hydrates_existing_tag /
  test_edit_description_auto_hydrates_existing_tag (functional).
  1145 passed.
- Docs: CLAUDE.md (auto-apply-existing vs never-auto-CREATE
  distinction), mps-24.md Phase 2.8n.
This commit is contained in:
russell@unturf.com 2026-05-17 11:13:36 -04:00
parent 60a93de763
commit 2bc1e20958
No known key found for this signature in database
6 changed files with 253 additions and 2 deletions

View file

@ -363,6 +363,25 @@ Tests (`test_functional.py::TestProductTagsSpa`):
Deferred (occasional click, not the hot path): AJAX-ifying the
"Suggest categories" link — still a full navigation by design.
**Phase 2.8n — auto-hydrate products into existing tags** (shipped
2026-05-17): operator wants new/edited products auto-filed into
existing categories without manual tagging.
`lib/tag_suggest.py:auto_hydrate_tags` stem-matches a product's
title+description against the shop's EXISTING tag names (reuses
`tokenize`/`simple_stem`; every stem of the tag name must appear in
the product stem set — unigram + phrase tags both work). Wired via
`views/product.py:_auto_hydrate_and_flash` into `product_new`
(create), `product_edit_description` (markup desc editor) and
`product_edit` (when title/desc changed, AFTER the explicit comma-tag
sync so it's additive). Contract: additive (never removes),
idempotent, never CREATES tags — inventing categories stays
suggest-then-approve; this only files into operator-defined ones.
Tests: `TestAutoHydrateTags` (3, test_integration) +
`test_new_product_auto_hydrates_existing_tag` /
`test_edit_description_auto_hydrates_existing_tag` (test_functional).
Note: shares the suggest engine's stemmer, so its known traits apply
(e.g. "studies"→"stud" ≠ "study"→"study"); consistent by design.
**Phase 2.8m — supersession keeps umbrella unigrams** (shipped
2026-05-17): operator saw "December Holiday" but not "Holiday" on its
own. Bigram supersession dropped a unigram when the *union* of all