[object Object]

← back to Yolo Agent

chore: untrack stray .bak/.pre-* backups + add gitignore patterns

02bfcb0e61ffef857fc30727dbcafa8a16d70648 · 2026-06-04 09:11:24 -0700 · SteveStudio2

Files touched

Diff

commit 02bfcb0e61ffef857fc30727dbcafa8a16d70648
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Thu Jun 4 09:11:24 2026 -0700

    chore: untrack stray .bak/.pre-* backups + add gitignore patterns
---
 .gitignore                                         |   5 +
 ...missing-collections.md.pre-scrub-2026-05-07.bak |  88 -----------------
 ...rs-images-to-square.md.pre-scrub-2026-05-07.bak |  75 ---------------
 ...e-trim-new-arrivals.md.pre-scrub-2026-05-07.bak |  54 -----------
 ...ll-monte-phase3-all.md.pre-scrub-2026-05-07.bak |  52 ----------
 ...-color-gemini-blitz.md.pre-scrub-2026-05-07.bak |  29 ------
 ..._maya-room-settings.md.pre-scrub-2026-05-07.bak |  43 ---------
 .../01_ai-enrich-romo.md.pre-scrub-2026-05-07.bak  |  19 ----
 ...7-empty-collections.md.pre-scrub-2026-05-07.bak |  83 ----------------
 ...1_enrich-prl-direct.md.pre-scrub-2026-05-07.bak |  14 ---
 ...gn-tags-all-vendors.md.pre-scrub-2026-05-07.bak |  87 -----------------
 ...mor-full-monty-test.md.pre-scrub-2026-05-07.bak |  63 -------------
 ...vate-versace-drafts.md.pre-scrub-2026-05-07.bak |  59 ------------
 ...i-enrich-villa-nova.md.pre-scrub-2026-05-07.bak |   9 --
 ...d-as-creation-agent.md.pre-scrub-2026-05-07.bak |  51 ----------
 ...rich-remaining-gaps.md.pre-scrub-2026-05-07.bak |   9 --
 ...re-collection-audit.md.pre-scrub-2026-05-07.bak |  76 ---------------
 ...wmor-bulk-phase3-ai.md.pre-scrub-2026-05-07.bak |  89 -----------------
 ...-vcc-spec-standards.md.pre-scrub-2026-05-07.bak |  64 -------------
 ..._03_gls-tag-cleanup.md.pre-scrub-2026-05-07.bak |   9 --
 ...rich-mark-alexander.md.pre-scrub-2026-05-07.bak |   9 --
 .../03_fix-spec-gaps.md.pre-scrub-2026-05-07.bak   |  67 -------------
 ...rphan-product-audit.md.pre-scrub-2026-05-07.bak | 105 ---------------------
 ...erior-design-tagger.md.pre-scrub-2026-05-07.bak |  33 -------
 .../04_ai-enrich-arte.md.pre-scrub-2026-05-07.bak  |   9 --
 ...ina-seas-hex-colors.md.pre-scrub-2026-05-07.bak |  32 -------
 ...exture-classify-17k.md.pre-scrub-2026-05-07.bak |  46 ---------
 ...wl-low-spec-vendors.md.pre-scrub-2026-05-07.bak |  46 ---------
 ...-crawls-high-to-low.md.pre-scrub-2026-05-07.bak |  86 -----------------
 ...ai-enrich-remaining.md.pre-scrub-2026-05-07.bak |  10 --
 ...eas-interior-tagger.md.pre-scrub-2026-05-07.bak |  27 ------
 ...wl-report-for-steve.md.pre-scrub-2026-05-07.bak |  43 ---------
 ..._final-audit-report.md.pre-scrub-2026-05-07.bak |  38 --------
 ...ollywood-gemini-hex.md.pre-scrub-2026-05-07.bak |  14 ---
 ...wood-hex-extraction.md.pre-scrub-2026-05-07.bak |  21 -----
 ...ase3-enrichment-run.md.pre-scrub-2026-05-07.bak |  13 ---
 ...k-notify-completion.md.pre-scrub-2026-05-07.bak |  11 ---
 ...9_ai-enrich-zoffany.md.pre-scrub-2026-05-07.bak |  12 ---
 ...log-spec-fill-audit.md.pre-scrub-2026-05-07.bak |  12 ---
 ...erior-design-tagger.md.pre-scrub-2026-05-07.bak |  20 ----
 ...ekly-relink-orphans.md.pre-scrub-2026-05-07.bak |  46 ---------
 ...wood-hex-extraction.md.pre-scrub-2026-05-07.bak |  17 ----
 ...ero-repeat-textures.md.pre-scrub-2026-05-07.bak |  50 ----------
 ...-repeat-textures-r2.md.pre-scrub-2026-05-07.bak |  50 ----------
 ...assify-remaining-r3.md.pre-scrub-2026-05-07.bak |  61 ------------
 ...imageclean-and-spin.md.pre-scrub-2026-05-07.bak |  59 ------------
 46 files changed, 5 insertions(+), 1910 deletions(-)

diff --git a/.gitignore b/.gitignore
index cf445c2..9fa6d19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,8 @@ dist/
 build/
 .next/
 logs/
+*.bak
+*.bak-*
+*.bak.*
+*.pre-*
+*.orig
diff --git a/tasks/done/00_create-79-missing-collections.md.pre-scrub-2026-05-07.bak b/tasks/done/00_create-79-missing-collections.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 98c7e69..0000000
--- a/tasks/done/00_create-79-missing-collections.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,88 +0,0 @@
-# Create Smart Collections for 79 Vendors Missing Dedicated Collection Pages
-
-## Ralph Clarifying Questions (Self-Check Before Executing)
-
-1. **Is the collection audit report still current?**
-   Read: `/root/DW-Agents/yolo-agent/logs/collection-audit-report.json`
-   Verify it has a "missing" array with vendor names and product counts.
-
-2. **Are any of these vendors private label or internal?**
-   Skip these — do NOT create public collections for:
-   - "Designer Laboratory" (internal)
-   - "Steve Abrams Studios" (internal)
-   - "DW Home" (internal brand)
-   - "Sancar" (distributor — NEVER show distributor names publicly)
-   - Any vendor in the private_label system
-
-3. **What's the smart collection rule pattern?**
-   Use: `vendor equals "{Vendor Name}"` — this auto-populates with all matching products.
-
-## What To Do
-
-### Step 1: Read the audit report
-```bash
-cat /root/DW-Agents/yolo-agent/logs/collection-audit-report.json
-```
-Extract the "missing" array.
-
-### Step 2: For each vendor (skip internal/private label), create a smart collection:
-```bash
-curl -s -X POST "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/smart_collections.json" \
-  -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ORDERS_TOKEN>" \
-  -H "Content-Type: application/json" \
-  -d '{
-    "smart_collection": {
-      "title": "{Vendor Name} Wallcoverings",
-      "rules": [{"column": "vendor", "relation": "equals", "condition": "{Vendor Name}"}],
-      "published": true,
-      "sort_order": "best-selling"
-    }
-  }'
-```
-
-**Title rules:**
-- If vendor sells wallcoverings: "{Vendor} Wallcoverings" (e.g., "Versa Designed Surfaces Wallcoverings")
-- If vendor sells trim: "{Vendor} Trim" (e.g., "Schumacher Trim")
-- If vendor sells fabric: "{Vendor} Fabrics"
-- If unclear: just "{Vendor}" with no suffix
-
-### Step 3: Rate limiting
-- Shopify API: max 2 requests/second
-- Add 600ms delay between each collection creation
-- Log each creation: vendor name, collection ID, product count
-
-### Step 4: Verify
-After creating all collections, verify each returns HTTP 200:
-```bash
-curl -s -o /dev/null -w "%{http_code}" "https://www.designerwallcoverings.com/collections/{handle}"
-```
-
-### Step 5: Save results
-Save to: `/root/DW-Agents/yolo-agent/logs/collections-created-report.json`
-Format:
-```json
-{
-  "timestamp": "...",
-  "created": [{"vendor": "X", "collectionId": 123, "handle": "x", "products": 50}],
-  "skipped": [{"vendor": "Y", "reason": "internal/private label"}],
-  "failed": [{"vendor": "Z", "error": "..."}]
-}
-```
-
-### Step 6: Slack notification
-```bash
-curl -X POST -H 'Content-type: application/json' \
-  --data '{"text":"✅ *Collections Created*\n• Created: X new collections\n• Skipped: Y (internal/private)\n• Failed: Z\n• Report: /root/DW-Agents/yolo-agent/logs/collections-created-report.json"}' \
-  "https://hooks.slack.com/services/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"
-```
-
-## DO NOT
-- Create collections for Sancar, Designer Laboratory, Steve Abrams Studios, DW Home
-- Create collections for vendors with < 3 active products (not worth an SEO page)
-- Delete any existing collections
-- Modify any products
-
-## Credentials
-- Shopify API: <redacted:SHOPIFY_ORDERS_TOKEN>
-- Store: designer-laboratory-sandbox.myshopify.com
-- Slack: https://hooks.slack.com/services/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
diff --git a/tasks/done/00_crop-grs-images-to-square.md.pre-scrub-2026-05-07.bak b/tasks/done/00_crop-grs-images-to-square.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 549dc52..0000000
--- a/tasks/done/00_crop-grs-images-to-square.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,75 +0,0 @@
-# Crop GRS- Product Images to Largest Square
-
-## DO NOT ask clarifying questions — proceed autonomously.
-
-## What
-GRS- products (grasscloth/Designer Wallcoverings vendor) have manufacturer logos in a strip at the top or bottom of their images. Crop ALL GRS- product images to the largest possible square to remove the logo strip.
-
-## How
-
-### Step 1: Find all GRS products on Shopify
-Search for products with "GRS" in handle, tags, or SKU:
-```bash
-# Use GraphQL to find all products with GRS in handle
-curl -s -X POST "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/graphql.json" \
-  -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ADMIN_TOKEN>" \
-  -H "Content-Type: application/json" \
-  -d '{"query":"{ products(first: 250, query: \"tag:grs OR sku:GRS\") { edges { node { id title handle images(first: 5) { edges { node { id src width height } } } } } } }"}'
-```
-
-Also search by vendor "Designer Wallcoverings" with GRS in handle:
-```
-GET /products.json?vendor=Designer+Wallcoverings&limit=250
-```
-Filter for handles containing "grs".
-
-### Step 2: For each product image, crop to square
-1. Download the image
-2. Get dimensions (W x H)
-3. If already square, skip
-4. Crop to the largest square:
-   - If W < H (portrait): crop center vertically → (0, (H-W)/2, W, (H-W)/2 + W)
-   - If W > H (landscape): crop center horizontally → ((W-H)/2, 0, (W-H)/2 + H, H)
-5. Use ImageMagick or Python Pillow:
-```bash
-# ImageMagick center crop to square
-convert input.jpg -gravity center -crop WxW+0+0 +repage output.jpg
-# Where W = min(width, height)
-```
-
-### Step 3: Upload cropped image back to Shopify
-```bash
-# Delete old image
-DELETE /admin/api/2024-01/products/{product_id}/images/{image_id}.json
-
-# Upload new cropped image
-POST /admin/api/2024-01/products/{product_id}/images.json
-{"image": {"attachment": "BASE64_DATA", "filename": "product.jpg"}}
-```
-
-### Step 4: Rate limiting
-- 500ms between API calls
-- Process in batches of 50
-- Write progress to /tmp/grs-crop-progress.log
-
-## DO NOT
-- Crop images that are already square (aspect ratio ~1.0)
-- Delete the original without uploading the replacement first
-- Process non-GRS products
-
-## Verification
-After processing, spot-check 5 products to verify:
-- Image is square
-- No logo visible
-- Image quality preserved
-
-## Slack Notification
-```bash
-curl -X POST -H 'Content-type: application/json' \
-  --data '{"text":"✂️ *GRS Image Crop Complete*\n• Products processed: X\n• Images cropped: Y\n• Already square: Z"}' \
-  "https://hooks.slack.com/services/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"
-```
-
-## Credentials
-- Shopify: <redacted:SHOPIFY_ADMIN_TOKEN>
-- Store: designer-laboratory-sandbox.myshopify.com
diff --git a/tasks/done/00_fix-fabrics-remove-trim-new-arrivals.md.pre-scrub-2026-05-07.bak b/tasks/done/00_fix-fabrics-remove-trim-new-arrivals.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 4adbe4c..0000000
--- a/tasks/done/00_fix-fabrics-remove-trim-new-arrivals.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,54 +0,0 @@
-# Fix Fabric Titles + Remove Trim from New Arrivals
-
-## DO NOT ask clarifying questions — proceed autonomously.
-
-## Task 1: Remove ALL Trim products from New Arrivals collection
-
-New Arrivals collection ID: 167327760435
-
-1. Get all products in New Arrivals with product_type "Trim" using Shopify REST API pagination
-2. For each Trim product, remove it from the New Arrivals collection using the Collect API:
-   - GET /admin/api/2024-01/collects.json?collection_id=167327760435&product_id={id}
-   - DELETE /admin/api/2024-01/collects/{collect_id}.json
-3. If it's a smart collection, the rule may auto-include them — check the collection rules:
-   - GET /admin/api/2024-01/smart_collections/167327760435.json
-   - If the rules don't exclude Trim, add a rule: product_type NOT_EQUALS Trim
-4. Rate limit: 500ms between API calls
-5. Report: how many trim products removed
-
-## Task 2: Fix 80+ Fabric titles with "Fabrics" in the name
-
-1. Search: GET /products.json?product_type=Fabric&limit=250 (paginate)
-2. Filter for titles containing "Fabrics" (the word, not "Fabric")
-3. For each, fix title: replace "Fabrics" with "Fabric"
-   - "Akio Fabrics – Black | Thibaut" → "Akio - Black Fabric | Thibaut"
-   - "Ralph Lauren Fabrics" in title → keep "Ralph Lauren" as vendor, remove "Fabrics" from pattern name
-4. PUT /products/{id}.json with corrected title
-5. Rate limit: 500ms
-
-## Task 3: Fix 50 Fabric products with "Wallcovering" in title
-
-These are products with product_type "Fabric" but "Wallcovering" in the title — wrong label.
-1. Check if they're actually fabrics or wallcoverings:
-   - Wolf Gordon: could be BOTH fabric and wallcovering — check tags
-   - Schumacher: check tags for "Fabric" tag
-   - If tagged Fabric and product_type is Fabric → replace "Wallcovering" with "Fabric" in title
-   - If it's actually a wallcovering miscategorized → change product_type to "Wallcovering"
-2. The Adriano products (Phillipe Romano) with "Wallcovering" in title but product_type "Fabric" are likely wallcoverings — change product_type to "Wallcovering"
-
-## Title Format Rules
-- Pattern: `{PatternName} - {Color} {ProductType} | {Vendor}`
-- ProductType for fabrics: "Fabric" (not "Fabrics")
-- NEVER "Wallcovering" in a Fabric product title
-- NEVER "Fabrics" (plural) — always "Fabric" (singular)
-
-## Verification
-After all fixes:
-- Count products in New Arrivals with product_type Trim (should be 0)
-- Count products store-wide with "Fabrics" in title and product_type Fabric (should be 0)
-- Send Slack notification with results
-
-## Credentials
-- Shopify: <redacted:SHOPIFY_ADMIN_TOKEN>
-- Store: designer-laboratory-sandbox.myshopify.com
-- Slack: https://hooks.slack.com/services/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
diff --git a/tasks/done/00_full-monte-phase3-all.md.pre-scrub-2026-05-07.bak b/tasks/done/00_full-monte-phase3-all.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index d1d5be9..0000000
--- a/tasks/done/00_full-monte-phase3-all.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,52 +0,0 @@
-# Full Monte Phase 3 — AI Enrichment ALL Vendors
-
-Run Phase 3 (Gemini AI vision) on ALL vendors in priority order. Budget: $227 max.
-Uses enrichment_tracking dedup — will NOT re-process already enriched products.
-
-## Execution
-```bash
-cd /root/DW-Agents/full-monte
-
-# Tier 1 first (already on Shopify, high value)
-node full-monte-batch.js --vendor kravet --phase 3 --limit 10000
-node full-monte-batch.js --vendor thibaut --phase 3 --limit 6000
-node full-monte-batch.js --vendor schumacher --phase 3 --limit 5200
-node full-monte-batch.js --vendor phillip_jeffries --phase 3 --limit 4400
-node full-monte-batch.js --vendor cole_son --phase 3 --limit 1000
-
-# Tier 2 (large catalogs)
-node full-monte-batch.js --vendor brewster --phase 3 --limit 9000
-node full-monte-batch.js --vendor york --phase 3 --limit 5500
-node full-monte-batch.js --vendor arte --phase 3 --limit 2000
-node full-monte-batch.js --vendor elitis --phase 3 --limit 1200
-node full-monte-batch.js --vendor romo --phase 3 --limit 2600
-node full-monte-batch.js --vendor koroseal --phase 3 --limit 2600
-
-# Anna French (specifically requested)
-node full-monte-batch.js --vendor anna_french --phase 3 --limit 600
-
-# Tier 3 — remaining large vendors
-node full-monte-batch.js --vendor marburg --phase 3 --limit 9300
-node full-monte-batch.js --vendor as_creation --phase 3 --limit 6200
-node full-monte-batch.js --vendor designtex --phase 3 --limit 2900
-node full-monte-batch.js --vendor holly_hunt --phase 3 --limit 2100
-node full-monte-batch.js --vendor maharam --phase 3 --limit 1600
-node full-monte-batch.js --vendor fabricut --phase 3 --limit 1400
-node full-monte-batch.js --vendor ralph_lauren --phase 3 --limit 3100
-node full-monte-batch.js --vendor graham_brown --phase 3 --limit 3200
-node full-monte-batch.js --vendor andrew_martin --phase 3 --limit 1000
-node full-monte-batch.js --vendor harlequin --phase 3 --limit 800
-node full-monte-batch.js --vendor carlisle --phase 3 --limit 800
-node full-monte-batch.js --vendor sandberg --phase 3 --limit 900
-node full-monte-batch.js --vendor wolf_gordon --phase 3 --limit 300
-node full-monte-batch.js --vendor maya_romanoff --phase 3 --limit 100
-```
-
-## Rules
-- Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-- Rate limit: 600ms between calls
-- Dedup via enrichment_tracking — zero duplicate calls
-- Image type detection included (scan_swatch, photo_full, etc.)
-- Run Tier 1 first, then 2, then 3
-- If budget exceeded ($227), stop and report
-- Log all progress to /root/DW-Agents/logs/full-monte-phase3.log
diff --git a/tasks/done/00_hex-color-gemini-blitz.md.pre-scrub-2026-05-07.bak b/tasks/done/00_hex-color-gemini-blitz.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 91927a7..0000000
--- a/tasks/done/00_hex-color-gemini-blitz.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,29 +0,0 @@
-## Hex Color Gemini Blitz — Fill Missing color_hex via AI Vision
-
-Many products have images but no color_hex. Use Gemini vision to analyze product images and extract the dominant color as a hex code.
-
-### Priority vendors (most missing hex):
-- Marburg: 7,652 missing (have images)
-- Newwall: 7,602 missing
-- Cowtan & Tout: 5,011 missing (specs only vendor but color is a spec)
-- Schumacher: 3,894 missing
-- Scalamandre: 4,055 missing
-- PJ: 4,294 missing
-- Rebel Walls: 1,934 missing
-- Milton King: 2,464 missing
-
-### Approach:
-1. For each vendor, find products with image_url but no color_hex
-2. Use Gemini 2.0 Flash vision API to analyze each image:
-   - Endpoint: `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct8QejMo`
-   - Prompt: "What is the dominant background color of this wallpaper/wallcovering? Reply with ONLY a hex code like #A5B2C3"
-   - Pass the image_url as an image part
-3. Update color_hex in the catalog table
-4. Rate limit: 10 req/sec (Gemini allows 60 RPM on free tier)
-5. Start with smallest vendors first for quick wins
-
-### CRITICAL:
-- Use Gemini for ALL image analysis (NEVER Claude vision)
-- API key for analysis: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct8QejMo
-- Do NOT push to Shopify
-- If Gemini returns a color name instead of hex, map it using color_hex_map table
diff --git a/tasks/done/00a_maya-room-settings.md.pre-scrub-2026-05-07.bak b/tasks/done/00a_maya-room-settings.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 4f73358..0000000
--- a/tasks/done/00a_maya-room-settings.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,43 +0,0 @@
-# Maya Romanoff — Room Settings + Spin Viewers for 224 New Products
-
-## Context
-224 new Maya Romanoff products were just imported into maya_catalog (dw_sku LIKE 'DWMR-8%'). They need room setting images and spin viewer assets generated before Shopify push.
-
-## Task 1: Room Settings (Gemini Image Generation)
-Generate room setting images for the new Maya Romanoff products using Gemini 2.5 Flash Image generation.
-
-For EACH new product (WHERE dw_sku LIKE 'DWMR-8%' AND room_setting_images IS NULL):
-1. Fetch the product image from image_url
-2. Send to Gemini with prompt: "Create a photorealistic interior room visualization showing this wallcovering installed on the main wall. Show a luxurious {room_type} with complementary furniture and decor. The wallcovering should be the focal point covering the full back wall. Photorealistic, professional interior design photography, warm natural lighting."
-3. Generate 3 room types per product: living room, dining room, hotel lobby
-4. Save generated images to /root/DW-Agents/room-settings/maya-romanoff/
-5. Upload to Shopify CDN and store URLs in maya_catalog.room_setting_images as JSON array
-
-API: Gemini 2.5 Flash Image
-- Endpoint: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent
-- Key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-- Config: generationConfig: { responseModalities: ['TEXT', 'IMAGE'] }
-- Rate limit: 600ms between calls
-
-Since 224 products × 3 rooms = 672 images is expensive, prioritize:
-- First batch: 50 most popular collections (Ajiro, Beadazzled, Craze, Island Weaves, Fleece Veil)
-- Skip products where image_url returns non-200
-
-## Task 2: Spin Viewers
-For each new product with an image:
-1. Generate 8 rotation frames using CSS transform perspective
-2. Create an HTML spin viewer at /root/DW-Agents/spin-viewers/maya-romanoff/{dw_sku}.html
-3. Each viewer shows the wallcovering pattern on a 3D-perspective wall that rotates
-
-Use the existing spin viewer template at /root/DW-Agents/vendor-command-center/spin-viewer-template.html if it exists, otherwise create a simple CSS 3D transform viewer.
-
-## Task 3: Update Shopify Push Task
-After room settings are generated, the 00_maya-romanoff-shopify-push.md task should include room_setting_images in the Shopify product payload as additional product images.
-
-## DB Connection
-postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
-
-## Important
-- Use Gemini for ALL image generation — never DALL-E or other providers
-- Save images locally first, then reference in DB
-- Log progress every 10 products
diff --git a/tasks/done/01_ai-enrich-romo.md.pre-scrub-2026-05-07.bak b/tasks/done/01_ai-enrich-romo.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 1b94b76..0000000
--- a/tasks/done/01_ai-enrich-romo.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,19 +0,0 @@
-# AI Enrich — Romo (454 products missing AI colors)
-
-Run Phase 3 AI enrichment on Romo products missing ai_colors in vendor_catalog.
-
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --vendor romo --phase 3 --limit 200
-```
-
-If that script doesn't exist or errors, use the enrich-ai-tags approach:
-1. Query vendor_catalog for romo products where ai_colors IS NULL AND image_url IS NOT NULL
-2. For each product, call Gemini 2.0 Flash vision API with the image
-3. Extract: colors (with hex + percentages), background color, styles, patterns, image type
-4. Update vendor_catalog with results
-5. Mark in enrichment_tracking table
-
-Use Gemini API key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-Model: gemini-2.0-flash
-Limit to 200 products per run to stay within rate limits.
diff --git a/tasks/done/01_cleanup-37-empty-collections.md.pre-scrub-2026-05-07.bak b/tasks/done/01_cleanup-37-empty-collections.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 2165b7f..0000000
--- a/tasks/done/01_cleanup-37-empty-collections.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,83 +0,0 @@
-# Clean Up 37 Empty Collections (0 Active Products)
-
-## Ralph Clarifying Questions (Self-Check Before Executing)
-
-1. **Which collections are empty and why?**
-   Read: `/root/DW-Agents/yolo-agent/logs/collection-audit-report.json`
-   The "empty" array has collections with 0 active products. For each:
-   - Are ALL products archived? (vendor discontinued)
-   - Is the collection rule wrong? (no matching products)
-   - Was the vendor removed from the store?
-
-2. **Are any of these collections linked from the homepage or navigation?**
-   Check: `curl -s https://www.designerwallcoverings.com/ | grep "{collection_handle}"`
-   If linked from homepage/nav, DON'T delete — flag for Steve.
-
-3. **Should empty collections be unpublished or deleted?**
-   - **Unpublish** = keeps the collection but removes from storefront/search (reversible)
-   - **Delete** = permanent removal
-   - Default: **UNPUBLISH** (safer — can re-publish if products come back)
-
-## What To Do
-
-### Step 1: Read the audit report
-```bash
-cat /root/DW-Agents/yolo-agent/logs/collection-audit-report.json
-```
-Extract the "empty" array with collection IDs and handles.
-
-### Step 2: For each empty collection, check if it's linked anywhere important
-```bash
-# Check homepage
-curl -s "https://www.designerwallcoverings.com/" | grep -i "{handle}"
-# Check navigation menus via API
-curl -s -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ORDERS_TOKEN>" \
-  "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/menus.json"
-```
-
-### Step 3: Unpublish empty collections (NOT delete)
-```bash
-# For smart collections:
-curl -s -X PUT "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/smart_collections/{id}.json" \
-  -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ORDERS_TOKEN>" \
-  -H "Content-Type: application/json" \
-  -d '{"smart_collection": {"published": false}}'
-
-# For custom collections:
-curl -s -X PUT "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/custom_collections/{id}.json" \
-  -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ORDERS_TOKEN>" \
-  -H "Content-Type: application/json" \
-  -d '{"custom_collection": {"published": false}}'
-```
-
-### Step 4: Rate limiting
-- 600ms between API calls
-- Log each action
-
-### Step 5: Save results
-Save to: `/root/DW-Agents/yolo-agent/logs/empty-collections-cleanup-report.json`
-```json
-{
-  "timestamp": "...",
-  "unpublished": [{"id": 123, "handle": "x", "title": "Y", "reason": "0 active products"}],
-  "skippedLinked": [{"id": 456, "handle": "z", "linkedFrom": "homepage"}],
-  "failed": []
-}
-```
-
-### Step 6: Slack notification
-```bash
-curl -X POST -H 'Content-type: application/json' \
-  --data '{"text":"🧹 *Empty Collections Cleanup*\n• Unpublished: X collections\n• Skipped (linked): Y\n• Failed: Z\n• Report: /root/DW-Agents/yolo-agent/logs/empty-collections-cleanup-report.json"}' \
-  "https://hooks.slack.com/services/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"
-```
-
-## DO NOT
-- DELETE any collections (unpublish only — reversible)
-- Remove collections that are linked from homepage or main navigation
-- Modify any products or product data
-
-## Credentials
-- Shopify API: <redacted:SHOPIFY_ORDERS_TOKEN>
-- Store: designer-laboratory-sandbox.myshopify.com
-- Slack: https://hooks.slack.com/services/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
diff --git a/tasks/done/01_enrich-prl-direct.md.pre-scrub-2026-05-07.bak b/tasks/done/01_enrich-prl-direct.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 2d0afd7..0000000
--- a/tasks/done/01_enrich-prl-direct.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,14 +0,0 @@
-# AI Enrich — PRL Products (186 missing in vendor_catalog)
-
-PRL vendor_code has 186 products in vendor_catalog with images but no ai_colors. There's no dedicated PRL catalog table.
-
-Run Gemini Vision directly on each product:
-1. Query: `SELECT id, mfr_sku, image_url FROM vendor_catalog WHERE vendor_code = 'PRL' AND ai_colors IS NULL AND image_url IS NOT NULL LIMIT 100`
-2. For each, call Gemini 2.0 Flash with the image_url
-3. Extract: colors (name, hex, percentage), background_color, styles, patterns, image_type
-4. UPDATE vendor_catalog SET ai_colors, ai_background_color, ai_styles, ai_patterns, ai_tags, ai_description
-5. Track in enrichment_tracking
-
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-Model: gemini-2.0-flash
-Limit: 100 per run, 500ms between calls
diff --git a/tasks/done/01_interior-design-tags-all-vendors.md.pre-scrub-2026-05-07.bak b/tasks/done/01_interior-design-tags-all-vendors.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 5dc6290..0000000
--- a/tasks/done/01_interior-design-tags-all-vendors.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,87 +0,0 @@
-# Interior Design Tags — PostgreSQL First, Then Shopify
-
-Run Gemini AI analysis on ALL products in PostgreSQL catalog tables. Save tags + hex codes to DB.
-Then push to Shopify only for products already on Shopify.
-
-## FLOW: PostgreSQL → Gemini → PostgreSQL → Shopify
-
-## TAG RULES
-- **NO "Background Color" prefix** — just the color name directly
-- **ALL colors detected** — tag every visible color
-- **Hex code** → save to `color_hex` column in catalog table + `global.color_hex` metafield on Shopify
-- **NEVER use "wallpaper"** — always "wallcovering"
-
-## Step 1: Analyze ALL catalog tables in PostgreSQL
-
-For each vendor catalog table that has an `image_url` column:
-
-```sql
-SELECT id, mfr_sku, pattern_name, color_name, image_url, material, collection
-FROM {catalog_table}
-WHERE image_url IS NOT NULL AND image_url <> ''
-AND (color_hex IS NULL OR color_hex = '')
-ORDER BY id
-```
-
-### For EACH product with image:
-
-1. **Gemini analysis** — send image URL, get colors + hex + styles + patterns
-```
-POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-```
-Prompt: "Analyze this wallcovering. Return ONLY valid JSON: { dominantColor, hexCode (#XXXXXX), allColors (ALL visible), styles, patterns, material }"
-
-2. **Save to PostgreSQL** — update the catalog row:
-```sql
-UPDATE {catalog_table} SET
-  color_hex = '{hexCode}',
-  ai_colors = '{allColors as JSON array}',
-  ai_styles = '{styles as JSON array}',
-  ai_patterns = '{patterns as JSON array}',
-  ai_background_color = '{dominantColor}',
-  ai_tags = '{computed tags as JSON array}',
-  updated_at = NOW()
-WHERE id = {id}
-```
-
-Add missing columns if needed:
-```sql
-ALTER TABLE {table} ADD COLUMN IF NOT EXISTS color_hex VARCHAR(7);
-ALTER TABLE {table} ADD COLUMN IF NOT EXISTS ai_colors JSONB;
-ALTER TABLE {table} ADD COLUMN IF NOT EXISTS ai_styles JSONB;
-ALTER TABLE {table} ADD COLUMN IF NOT EXISTS ai_patterns JSONB;
-ALTER TABLE {table} ADD COLUMN IF NOT EXISTS ai_background_color VARCHAR(100);
-ALTER TABLE {table} ADD COLUMN IF NOT EXISTS ai_tags JSONB;
-```
-
-## Step 2: Push to Shopify (only products already on Shopify)
-
-For products with `shopify_product_id IS NOT NULL`:
-
-1. Build tag string from ai_tags + brand + pattern + material + "Wallcovering" + "Commercial" + "Architectural"
-2. Push hex to `global.color_hex` metafield via GraphQL
-3. Update Shopify product tags via REST
-4. Publish to all 14 channels if not already
-
-## Vendor catalog tables to process (in order of priority):
-1. versace_catalog (136 products)
-2. black_edition_catalog (191)
-3. kirkby_catalog (152)
-4. zinc_catalog (100)
-5. villa_nova_catalog (387)
-6. arte_catalog (1991)
-7. romo_catalog (2595)
-8. scalamandre_catalog (4819)
-9. thibaut_catalog (5703)
-10. All other catalogs with image_url
-
-## Rate limits
-- Gemini: 1 req/sec (max 15 RPM on free tier — use batch API for 100+ products)
-- Shopify: 2 req/sec
-- Log progress every 25 products per vendor
-
-## CRITICAL
-- PostgreSQL FIRST, Shopify SECOND
-- Save ALL Gemini results to DB before touching Shopify
-- color_hex must be valid hex format (#XXXXXX)
-- Preserve display_variant tag on Shopify
diff --git a/tasks/done/01_newmor-full-monty-test.md.pre-scrub-2026-05-07.bak b/tasks/done/01_newmor-full-monty-test.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 5fce44c..0000000
--- a/tasks/done/01_newmor-full-monty-test.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,63 +0,0 @@
-# NEWMOR Full Monty — Test 1 Product
-
-## Context
-NEWMOR has 1,285 products in `newmor_catalog` PostgreSQL table. 653 have width. Zero have AI enrichment. Zero on Shopify.
-Steve wants a 1-product Full Monty test to validate the pipeline before running the full batch.
-
-## DB Connection
-`postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-
-## Steps
-
-### Step 1: Pick a good test product
-Query `newmor_catalog` for a product with image_url, width, and mfr_sku populated. Prefer one with material and fire_rating too. Good candidate: mfr_sku = 'CHARCOAL' (pattern: Mid-Century Modern Floral Geo, width: 70cm, material: Non-Woven 460gsm, fire_rating: Type II).
-
-### Step 2: Run Phase 3 (AI Tags) on 1 product
-```bash
-cd /root/DW-Agents/vendor-scrapers
-node enrich-ai-tags.js newmor --limit 1
-```
-This runs Gemini Vision on the product image to extract colors, hex codes, styles, patterns, background color, and image type.
-
-### Step 3: Verify AI enrichment results
-Query the database to confirm AI data was written:
-```sql
-SELECT mfr_sku, pattern_name, color_name, ai_colors, ai_styles, ai_patterns, ai_background_color, ai_tags, color_hex
-FROM newmor_catalog
-WHERE ai_colors IS NOT NULL
-LIMIT 5;
-```
-
-Also check enrichment_tracking:
-```sql
-SELECT * FROM enrichment_tracking WHERE vendor_code = 'newmor' AND phase3_ai_at IS NOT NULL LIMIT 5;
-```
-
-### Step 4: Run Phase 4 (Silas Validation) on the enriched product
-```bash
-curl -s -u admin:DWSecure2024! http://localhost:9674/api/validate/newmor | head -100
-```
-
-### Step 5: Generate body_html description (3 sentences max, NO specs)
-Write a 3-sentence product description for the test product. Format:
-- Sentence 1: What it is (pattern/color/vendor)
-- Sentence 2: Style/mood
-- Sentence 3: Recommended use
-Store in the `body_html` column of `newmor_catalog`.
-
-### Step 6: Report Results
-Print a clear summary of what was found:
-- Product tested (SKU, pattern, color)
-- AI colors detected (with hex codes)
-- AI styles and patterns
-- Background color
-- Image type classification
-- Body HTML generated
-- Whether the product passes FULLPRODUCT gate (image + width + mfr_sku)
-
-### IMPORTANT RULES
-- ALL specs go in metafields, NEVER in body_html
-- body_html = description ONLY, 3 sentences max
-- Use Gemini analysis key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-- Track costs via /root/DW-Agents/shared/gemini-cost-tracker.js
-- Do NOT push to Shopify yet — this is Phase 3 test only
diff --git a/tasks/done/02_activate-versace-drafts.md.pre-scrub-2026-05-07.bak b/tasks/done/02_activate-versace-drafts.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index fd69a91..0000000
--- a/tasks/done/02_activate-versace-drafts.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,59 +0,0 @@
-# Activate 136 Versace Draft Products on Shopify
-
-136 Versace VI products are on Shopify as DRAFT. They need enrichment + activation.
-
-## Steps for EACH product:
-
-### 1. Find all Versace drafts
-```sql
-SELECT mfr_sku, dw_sku, pattern_name, color_name, shopify_product_id, width, material, collection, image_url
-FROM versace_catalog WHERE shopify_product_id IS NOT NULL
-```
-
-### 2. Generate Gemini AI description
-For each product with an image, call Gemini to generate a 2-3 sentence luxury wallcovering description.
-API key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-Model: gemini-2.0-flash
-Push result to Shopify body_html (description only, NO specs table).
-
-### 3. Push metafields via GraphQL metafieldsSet
-For each product, push ALL available specs to global.* namespace:
-- global.width (from DB width column)
-- global.manufacturer_sku (from mfr_sku)
-- global.Brand = "Versace"
-- global.Collection = "Versace VI"
-- global.Contents = "Non-woven"
-- global.application = "Paste the wall"
-- global.repeat (if pattern, not texture — check pattern_name, textures have no repeat)
-
-Use GraphQL metafieldsSet mutation — ONE call per product (not REST).
-Endpoint: https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/graphql.json
-Token: <redacted:SHOPIFY_ADMIN_TOKEN>
-
-### 4. Silas validate-activation
-POST http://127.0.0.1:9674/api/validate-activation
-Body: { shopify_product_id }
-Only activate if Silas approves.
-
-### 5. Activate
-PUT product status to 'active' via REST API.
-Only if Silas approved AND metafields are confirmed.
-
-### 6. Skip products without images
-67 of 136 have images. Products without images CANNOT be activated (Silas will block).
-Log skipped products.
-
-## Rate limits
-- Gemini: 1 req/sec
-- Shopify GraphQL: 2 req/sec
-- Shopify REST: 2 req/sec
-- Silas: no limit (local)
-
-## Report
-Total drafts, enriched with description, metafields pushed, activated, blocked by Silas, skipped (no image).
-
-## CRITICAL
-- Body HTML = description ONLY, no specs tables
-- All specs in metafields exclusively (global.* namespace)
-- NEVER use word "wallpaper" — always "wallcovering"
-- Use Gemini for image analysis, NEVER Claude Vision
diff --git a/tasks/done/02_ai-enrich-villa-nova.md.pre-scrub-2026-05-07.bak b/tasks/done/02_ai-enrich-villa-nova.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 5525699..0000000
--- a/tasks/done/02_ai-enrich-villa-nova.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,9 +0,0 @@
-# AI Enrich — Villa Nova (357 products missing AI colors)
-
-Same as Romo task but for villa_nova vendor_code. Limit 200 per run.
-
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --vendor villa_nova --phase 3 --limit 200
-```
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo | Model: gemini-2.0-flash
diff --git a/tasks/done/02_build-as-creation-agent.md.pre-scrub-2026-05-07.bak b/tasks/done/02_build-as-creation-agent.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 245fa45..0000000
--- a/tasks/done/02_build-as-creation-agent.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,51 +0,0 @@
-# Build AS Creation Agent — Ace
-
-Build a scraper agent for AS Creation at https://products.as-creation.com/en/Collections/
-
-## Key Facts
-- **Platform**: Shopware 6 (NOT Shopify, NOT WooCommerce)
-- **Codename**: Ace (A = AS Creation)
-- **Port**: 9656
-- **Directory**: /root/DW-Agents/ace-agent/
-- **Sitemap**: https://products.as-creation.com/sitemap.xml (contains gzipped product sitemap)
-- **API**: Shopware Store API at /store-api/product requires `sw-access-key` header
-- **US Distribution**: Sancar is US distributor. Astek may also rep their lines.
-
-## Find the sw-access-key
-The access key is usually in the page source HTML. Look for it:
-```bash
-curl -sk 'https://products.as-creation.com/en/' | grep -i 'access.key\|sw-access\|salesChannel'
-```
-Or check the JavaScript files for the key.
-
-## Build Steps
-1. Create /root/DW-Agents/ace-agent/ directory
-2. Create package.json with express and pg dependencies
-3. Build server.js following the pattern of marco-agent (/root/DW-Agents/marco-agent/server.js) but adapted for Shopware:
-   - POST to /store-api/product with sw-access-key header
-   - Paginate with `page` and `limit` params
-   - Extract all product attributes/properties for specs
-4. Create as_creation_catalog table with ALL spec columns including:
-   - us_distributor (default: 'Sancar Wallcoverings')
-   - showroom_locations
-   - All standard spec columns (width, length, repeat_v, repeat_h, material, fire_rating, finish, etc.)
-5. npm install
-6. Register in vendor_registry
-7. Open firewall: `sudo ufw allow from 76.33.146.135 to any port 9656 proto tcp`
-8. Start with PM2: `pm2 start server.js --name ace-agent`
-9. Trigger 3h continuous crawl
-
-## If Store API doesn't work:
-Fall back to sitemap approach:
-1. Download the gzipped sitemap
-2. Extract product URLs
-3. Curl each product page and parse the HTML for specs
-4. Use execFileSync('curl', ['-sk', url]) to avoid SSL issues
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY.**
-
-## Slack Notification — REQUIRED
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d '{"text":"AS CREATION AGENT BUILT: Ace on port 9656. [X] products crawled. US distributor: Sancar."}' "https://hooks.slack.com/services/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"
-```
diff --git a/tasks/done/02_enrich-remaining-gaps.md.pre-scrub-2026-05-07.bak b/tasks/done/02_enrich-remaining-gaps.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 06bd691..0000000
--- a/tasks/done/02_enrich-remaining-gaps.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,9 +0,0 @@
-# AI Enrich — Remaining Gaps (Arte 9, Black Edition 4)
-
-13 products still missing ai_colors in vendor_catalog.
-
-For Arte (9 missing): Check arte_catalog for matching products and sync. If not in arte_catalog, run Gemini directly.
-For Black Edition (4 missing, SKUs W924/01-04): Not in black_edition_catalog. Run Gemini Vision directly.
-
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-Model: gemini-2.0-flash
diff --git a/tasks/done/02_full-store-collection-audit.md.pre-scrub-2026-05-07.bak b/tasks/done/02_full-store-collection-audit.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 04b7f19..0000000
--- a/tasks/done/02_full-store-collection-audit.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,76 +0,0 @@
-# Full Store-Wide Collection Audit — Every Vendor Has a Collection
-
-## Ralph Clarifying Questions (Self-Check Before Executing)
-
-1. **How many unique vendors exist in the store?**
-   ```bash
-   curl -s -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ORDERS_TOKEN>" \
-     -H "Content-Type: application/json" \
-     -d '{"query":"{ shop { productVendors(first: 250) { edges { node } } } }"}' \
-     "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/graphql.json"
-   ```
-   List all vendor names. Count them.
-
-2. **How many custom + smart collections exist?**
-   - Count custom_collections and smart_collections via API
-   - This gives us the denominator for "% of vendors with collections"
-
-3. **What's the mapping strategy?**
-   - Most vendor collections use the handle pattern: `vendor-name-lowercase-dashed`
-   - Some use alternate handles (e.g., `arte` not `arte-international`)
-   - Check for both exact and partial matches
-
-## What To Do
-
-### Phase 1: Build the vendor→collection map
-1. Fetch ALL unique vendors via GraphQL (shop.productVendors)
-2. Fetch ALL collections (custom + smart) via REST API with pagination
-3. For each vendor, check if a collection exists where:
-   - Collection title contains the vendor name, OR
-   - Collection handle matches the vendor handle pattern, OR
-   - Collection has a rule `vendor equals {vendor_name}`
-
-### Phase 2: Identify gaps
-Create a report with three categories:
-- **MATCHED**: Vendor has a collection (with handle and product count)
-- **MISSING**: Vendor has active products but NO collection
-- **EMPTY**: Vendor has a collection but 0 visible products
-
-### Phase 3: Save the report
-Save to: `/root/DW-Agents/yolo-agent/logs/collection-audit-report.json`
-Also save a human-readable summary to: `/root/DW-Agents/yolo-agent/logs/collection-audit-summary.md`
-
-Format for JSON:
-```json
-{
-  "timestamp": "2026-03-23T...",
-  "totalVendors": 250,
-  "matched": [{"vendor": "Arte", "collection": "arte", "products": 150}],
-  "missing": [{"vendor": "Phyllis Morris", "activeProducts": 28}],
-  "empty": [{"vendor": "Phillipe Romano", "collection": "phillipe-romano-faux-leathers", "reason": "all archived"}]
-}
-```
-
-### Phase 4: Send Slack notification
-```bash
-curl -X POST -H 'Content-type: application/json' \
-  --data '{"text":"📊 *Collection Audit Complete*\n• Total vendors: X\n• Matched: X\n• Missing collection: X\n• Empty collection: X\n• Report: /root/DW-Agents/yolo-agent/logs/collection-audit-summary.md"}' \
-  "https://hooks.slack.com/services/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"
-```
-
-## DO NOT
-- Create any new collections (just report — Steve will review)
-- Delete any collections
-- Modify any products
-- This task is AUDIT ONLY — read operations only
-
-## Verification
-- Report file exists and has data
-- Total vendors matches GraphQL count
-- matched + missing + empty = total vendors
-- Slack notification sent
-
-## Credentials
-- Shopify API token: <redacted:SHOPIFY_ORDERS_TOKEN>
-- GraphQL endpoint: https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/graphql.json
-- Slack webhook: https://hooks.slack.com/services/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
diff --git a/tasks/done/02_newmor-bulk-phase3-ai.md.pre-scrub-2026-05-07.bak b/tasks/done/02_newmor-bulk-phase3-ai.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 2873bc4..0000000
--- a/tasks/done/02_newmor-bulk-phase3-ai.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,89 +0,0 @@
-# NEWMOR — Bulk Phase 3 AI Enrichment (All Products)
-
-## Context
-After width re-scraping, run Gemini Vision AI enrichment on ALL NEWMOR products. The test run on CHARCOAL validated the pipeline. Now run the full batch.
-
-Currently ~3 products already enriched from the test run. ~1,282 remaining.
-
-## DB Connection
-`postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-
-## Steps
-
-### Step 1: Check how many still need AI enrichment
-```sql
-SELECT
-  COUNT(*) as total,
-  COUNT(CASE WHEN ai_colors IS NOT NULL THEN 1 END) as has_ai,
-  COUNT(CASE WHEN ai_colors IS NULL THEN 1 END) as needs_ai,
-  COUNT(CASE WHEN width IS NOT NULL AND length(width) > 0 THEN 1 END) as has_width
-FROM newmor_catalog;
-```
-
-### Step 2: Run Phase 3 (AI Tags) via Full Monte CLI
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --vendor newmor --phase 3 --limit 1300
-```
-
-This calls `enrich-ai-tags.js` which:
-- Queries newmor_catalog for products with images but no AI tags
-- Checks enrichment_tracking to prevent duplicate Gemini calls
-- Sends each product image to Gemini Vision for analysis
-- Extracts: colors (with hex + percentages), background color, styles, patterns, image type, tags
-- Writes results to newmor_catalog and marks enrichment_tracking
-
-### Step 3: Monitor progress (check periodically)
-```sql
-SELECT
-  COUNT(*) as total,
-  COUNT(CASE WHEN ai_colors IS NOT NULL THEN 1 END) as enriched,
-  COUNT(CASE WHEN ai_colors IS NULL THEN 1 END) as remaining
-FROM newmor_catalog;
-```
-
-### Step 4: Check enrichment tracking
-```sql
-SELECT COUNT(*) as phase3_done
-FROM enrichment_tracking
-WHERE vendor_code = 'newmor' AND phase3_ai_at IS NOT NULL;
-```
-
-### Step 5: Check for errors
-```sql
-SELECT COUNT(*) as with_errors, SUM(error_count) as total_errors
-FROM enrichment_tracking
-WHERE vendor_code = 'newmor' AND error_count > 0;
-```
-
-### Step 6: Generate body_html for all enriched products
-For products that have AI data but no body_html, generate 3-sentence descriptions:
-- Sentence 1: What it is (pattern/color/vendor)
-- Sentence 2: Style/mood
-- Sentence 3: Recommended use
-NEVER include specs in body_html.
-
-### Step 7: Final Full Monte status
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --status --vendor newmor
-```
-
-### Step 8: Report results
-Print summary:
-- Total products enriched
-- Sample of 5 products with their AI colors and tags
-- Error count
-- Cost estimate (products * $0.0006)
-- Updated Full Monte status table
-- Next steps needed before Shopify push
-
-## IMPORTANT RULES
-- Use Gemini analysis key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-- Track costs via /root/DW-Agents/shared/gemini-cost-tracker.js
-- Check enrichment_tracking BEFORE every Gemini call (dedup)
-- Do NOT push to Shopify — that requires VCC approval (Phase 5)
-- body_html = description ONLY, 3 sentences max, NO specs
-- ALL specs go in metafields exclusively
-- If rate limited by Gemini, back off and retry
-- This may take 15-30 minutes for 1,200+ products
diff --git a/tasks/done/02_update-vcc-spec-standards.md.pre-scrub-2026-05-07.bak b/tasks/done/02_update-vcc-spec-standards.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 1447dc9..0000000
--- a/tasks/done/02_update-vcc-spec-standards.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,64 +0,0 @@
-# Update Vendor Command Center — Enforce ALL Specs Standard
-
-Read the Vendor Command Center (Victor) at `/root/DW-Agents/vendor-command-center/server.js` (port 9660).
-
-Update it to enforce that ALL vendor agents must capture these fields:
-
-## Required Catalog Columns (ALL vendors)
-- `mfr_sku` — manufacturer SKU (UNIQUE)
-- `dw_sku` — Designer Wallcoverings internal SKU
-- `pattern_name` — pattern/design name
-- `color_name` — colorway name
-- `collection` — collection name
-- `product_type` — wallpaper, wallcovering, fabric, etc.
-- `width` — roll width
-- `length` — roll length
-- `repeat_v` — vertical repeat
-- `repeat_h` — horizontal repeat
-- `match_type` — straight, offset, random, seamless
-- `material` — vinyl, non-woven, grasscloth, etc.
-- `finish` — matte, satin, textured, etc.
-- `application` — paste-the-wall, paste-the-paper, peel-and-stick
-- `coverage` — square footage per roll
-- `features` — washable, strippable, breathable, etc.
-- `fire_rating` — ASTM E84 Class A, Class 1, etc.
-- `design` — floral, geometric, stripe, etc.
-- `rooms` — bedroom, living room, bathroom, etc.
-- `color_primary` — primary color
-- `color_secondary` — secondary color
-- `price_retail` — retail price
-- `price_currency` — USD, EUR, GBP
-- `image_url` — primary image
-- `all_images` — ALL images pipe-separated (|)
-- `product_url` — source product page URL
-- `in_stock` — boolean
-- `vendor_name` — vendor name
-- `brand` — brand if different from vendor
-- `tags` — tags/categories
-- `body_html` — full product description HTML
-- `short_description` — short description
-- `about_vendor` — vendor company info (about us)
-- `us_distributor` — US distribution info
-- `showroom_locations` — physical showroom locations
-
-## What to Add to VCC Dashboard
-1. Add a "Spec Completeness" column to the vendor table showing % of required fields filled
-2. Add a "Missing Specs" alert for vendors below 50% spec fill rate
-3. Add `about_vendor`, `us_distributor`, and `showroom_locations` columns to all catalog tables
-
-## Important
-- Do NOT restart the VCC if it's currently running well — just update the code and restart after
-- Test the dashboard still loads after changes
-- Auth: admin / DWSecure2024!
-
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY. Downloading product data FROM other vendors' Shopify stores for catalog data is fine and expected. product-scheduler and schedule-engine are STOPPED intentionally. Do NOT restart them.**
-
-
-## Slack Notification — REQUIRED
-When this task is complete, send a Slack message to Steve with the results summary:
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d "{\"text\":\"TASK COMPLETE: [task name here]\\n\\n[brief results summary]\"}" "https://hooks.slack.com/services/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"
-```
-Replace [task name] and [results summary] with actual values. Keep it concise — 3-5 lines max.
diff --git a/tasks/done/03_03_gls-tag-cleanup.md.pre-scrub-2026-05-07.bak b/tasks/done/03_03_gls-tag-cleanup.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 9e60075..0000000
--- a/tasks/done/03_03_gls-tag-cleanup.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,9 +0,0 @@
-Find ALL products on Shopify with GLS in the SKU (across ALL vendors — Glitter Walls, Glass Beaded, Phillipe Romano). For each:
-1. Remove tags: brand vinyl, composition vinyl, Vinyl (the tag, not material)
-2. Run interior design tagger via Gemini Vision to generate proper style/color/pattern tags
-3. Add a 2-3 sentence product description if body_html is empty
-4. Crop any text/logos from the primary product image
-
-Shopify API: https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/
-Token: <redacted:SHOPIFY_ADMIN_TOKEN>
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
\ No newline at end of file
diff --git a/tasks/done/03_ai-enrich-mark-alexander.md.pre-scrub-2026-05-07.bak b/tasks/done/03_ai-enrich-mark-alexander.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 75b3dad..0000000
--- a/tasks/done/03_ai-enrich-mark-alexander.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,9 +0,0 @@
-# AI Enrich — Mark Alexander (260 products missing AI colors)
-
-Same as Romo task but for mark_alexander vendor_code. Limit 200 per run.
-
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --vendor mark_alexander --phase 3 --limit 200
-```
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo | Model: gemini-2.0-flash
diff --git a/tasks/done/03_fix-spec-gaps.md.pre-scrub-2026-05-07.bak b/tasks/done/03_fix-spec-gaps.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index b7d930c..0000000
--- a/tasks/done/03_fix-spec-gaps.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,67 +0,0 @@
-# Fix Spec Gaps — Extract specs from body_html for all vendors
-
-Many vendors have body_html but empty spec columns. Parse body_html to extract specs.
-
-## Vendors with 0% specs that have body_html:
-Run this query to find them:
-```sql
-PGPASSWORD=DW2024SecurePass psql -h 127.0.0.1 -U dw_admin -d dw_unified -c "
-SELECT relname, n_live_tup FROM pg_stat_user_tables
-WHERE relname LIKE '%_catalog' AND n_live_tup > 100
-ORDER BY n_live_tup DESC;"
-```
-
-For EACH catalog table with > 100 products:
-1. Check how many have body_html populated
-2. Check how many have empty width, repeat_v, material
-3. If body_html has data but specs are empty, extract with regex patterns:
-
-### Common spec patterns in body_html:
-```sql
--- Width patterns
-UPDATE xxx_catalog SET width = TRIM(match[1])
-FROM (SELECT id, REGEXP_MATCH(body_html, '(?:Width|Roll Width|Dimensions)[:\s]*([^<,]+)', 'i') as match FROM xxx_catalog WHERE (width IS NULL OR width = '') AND body_html <> '') sub
-WHERE xxx_catalog.id = sub.id AND sub.match IS NOT NULL;
-
--- Repeat patterns
-UPDATE xxx_catalog SET repeat_v = TRIM(match[1])
-FROM (SELECT id, REGEXP_MATCH(body_html, '(?:Repeat|Pattern Repeat|Vertical Repeat)[:\s]*([^<,]+)', 'i') as match FROM xxx_catalog WHERE (repeat_v IS NULL OR repeat_v = '') AND body_html <> '') sub
-WHERE xxx_catalog.id = sub.id AND sub.match IS NOT NULL;
-
--- Material patterns
-UPDATE xxx_catalog SET material = TRIM(match[1])
-FROM (SELECT id, REGEXP_MATCH(body_html, '(?:Material|Substrate|Composition)[:\s]*([^<,]+)', 'i') as match FROM xxx_catalog WHERE (material IS NULL OR material = '') AND body_html <> '') sub
-WHERE xxx_catalog.id = sub.id AND sub.match IS NOT NULL;
-
--- Fire rating patterns
-UPDATE xxx_catalog SET fire_rating = TRIM(match[1])
-FROM (SELECT id, REGEXP_MATCH(body_html, '(?:Fire|Flame|ASTM|Class\s*[A1]|NFPA)[:\s]*([^<]+)', 'i') as match FROM xxx_catalog WHERE body_html <> '') sub
-WHERE xxx_catalog.id = sub.id AND sub.match IS NOT NULL;
-```
-
-4. Add missing columns first:
-```sql
-ALTER TABLE xxx_catalog ADD COLUMN IF NOT EXISTS fire_rating VARCHAR(255) DEFAULT '';
-ALTER TABLE xxx_catalog ADD COLUMN IF NOT EXISTS finish VARCHAR(255) DEFAULT '';
-ALTER TABLE xxx_catalog ADD COLUMN IF NOT EXISTS application VARCHAR(255) DEFAULT '';
-ALTER TABLE xxx_catalog ADD COLUMN IF NOT EXISTS match_type VARCHAR(100) DEFAULT '';
-ALTER TABLE xxx_catalog ADD COLUMN IF NOT EXISTS all_images TEXT DEFAULT '';
-```
-
-## Priority order (most products first):
-1. kravet_catalog (9,780)
-2. brewster_catalog (8,715)
-3. cowtan_tout_catalog (8,466)
-4. bespoke_catalog (6,262)
-5. thibaut_catalog (5,557)
-6. york_catalog (5,304)
-7. schumacher_catalog (5,182) — already has 3,144 fire ratings
-8. pj_catalog (4,376)
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY.**
-
-## Slack Notification — REQUIRED
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d '{"text":"SPEC GAPS FIXED: Extracted specs from body_html for [X] vendors. [summary]"}' "https://hooks.slack.com/services/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"
-```
diff --git a/tasks/done/03_orphan-product-audit.md.pre-scrub-2026-05-07.bak b/tasks/done/03_orphan-product-audit.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index e9f9f5d..0000000
--- a/tasks/done/03_orphan-product-audit.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,105 +0,0 @@
-# Orphan Product Audit — Every Active Product Has a Browsable Collection
-
-## Ralph Clarifying Questions (Self-Check Before Executing)
-
-1. **How many total active products are in the store?**
-   ```bash
-   curl -s -H "X-Shopify-Access-Token: <redacted:SHOPIFY_ORDERS_TOKEN>" \
-     -H "Content-Type: application/json" \
-     -d '{"query":"{ productsCount(query: \"status:active\") { count } }"}' \
-     "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/graphql.json"
-   ```
-
-2. **Is the collection audit (task 02) done?**
-   - Check if `/root/DW-Agents/yolo-agent/logs/collection-audit-report.json` exists
-   - If not, this task depends on it — use the report to know which vendors lack collections
-   - If the file doesn't exist, use the "missing" vendors from the audit as a starting point
-
-3. **What does "orphan" mean in this context?**
-   - An active product whose vendor has NO collection at all
-   - OR an active product that isn't included in ANY collection (custom or smart)
-   - The second definition is harder to check — start with the first (vendor-level)
-
-## What To Do
-
-### Phase 1: Vendor-level orphan detection (fast)
-Using the collection audit report (task 02), for each vendor in the "missing" list:
-1. Count active products for that vendor via GraphQL
-2. List up to 10 example products (title, handle, SKU)
-3. This gives us "X products from Y vendors have no collection"
-
-### Phase 2: Product-level orphan check (thorough)
-For a more thorough check:
-1. Get all collection IDs and their product lists via Shopify Collect API
-2. Get all active product IDs
-3. Find product IDs that don't appear in ANY collection
-4. Group orphaned products by vendor for the report
-
-NOTE: This can be expensive API-wise. Use GraphQL bulk operations if product count > 10,000:
-```graphql
-{
-  products(first: 250, query: "status:active") {
-    edges {
-      node {
-        id
-        title
-        vendor
-        handle
-        collections(first: 10) {
-          edges { node { id title } }
-        }
-      }
-    }
-    pageInfo { hasNextPage endCursor }
-  }
-}
-```
-Paginate through all products. Any product with collections.edges = [] is an orphan.
-
-### Phase 3: Save report
-Save to: `/root/DW-Agents/yolo-agent/logs/orphan-product-report.json`
-Summary to: `/root/DW-Agents/yolo-agent/logs/orphan-product-summary.md`
-
-Format:
-```json
-{
-  "timestamp": "2026-03-23T...",
-  "totalActiveProducts": 50000,
-  "totalOrphans": 500,
-  "orphansByVendor": [
-    {"vendor": "Phyllis Morris", "count": 28, "examples": ["product-1", "product-2"]},
-    {"vendor": "Another Vendor", "count": 15, "examples": ["product-a"]}
-  ],
-  "percentOrphaned": "1.0%"
-}
-```
-
-### Phase 4: Slack notification
-```bash
-curl -X POST -H 'Content-type: application/json' \
-  --data '{"text":"🔍 *Orphan Product Audit Complete*\n• Total active products: X\n• Products with NO collection: X (Y%)\n• Vendors with orphans: Z\n• Top 5 vendors: ...\n• Report: /root/DW-Agents/yolo-agent/logs/orphan-product-summary.md"}' \
-  "https://hooks.slack.com/services/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"
-```
-
-## DO NOT
-- Create collections (audit only — Steve reviews the report)
-- Archive or delete any products
-- Modify any product data
-- This is READ-ONLY
-
-## Verification
-- Report files exist
-- orphansByVendor entries have non-zero counts
-- totalOrphans + products-in-collections ≈ totalActiveProducts
-- Slack notification sent
-
-## Credentials
-- Shopify API token: <redacted:SHOPIFY_ORDERS_TOKEN>
-- GraphQL: https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/graphql.json
-- Slack: https://hooks.slack.com/services/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
-
-## Rate Limiting
-- GraphQL: 1000 points/second on standard plan
-- products(first:250) costs ~252 points per call
-- For 50K products = ~200 pages = ~200 calls = ~4 points/sec = safe
-- Add 500ms delay between pages to be conservative
diff --git a/tasks/done/03_p2-06-interior-design-tagger.md.pre-scrub-2026-05-07.bak b/tasks/done/03_p2-06-interior-design-tagger.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index d20e61d..0000000
--- a/tasks/done/03_p2-06-interior-design-tagger.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,33 +0,0 @@
-# P2-06: Interior Design Tagger Automation
-
-Run the Gemini-based interior design tagger on products that are missing AI tags.
-
-## What to do
-
-1. Find products missing AI tags:
-```sql
-psql "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified" -c "
-SELECT vendor, COUNT(*) as total,
-  COUNT(CASE WHEN ai_tags IS NOT NULL AND ai_tags != '' THEN 1 END) as has_tags
-FROM shopify_products
-WHERE UPPER(status) = 'ACTIVE'
-GROUP BY vendor
-HAVING COUNT(CASE WHEN ai_tags IS NULL OR ai_tags = '' THEN 1 END) > 50
-ORDER BY total DESC
-LIMIT 15;"
-```
-
-2. For the top vendors missing tags, run the tagger script:
-```
-python3 /root/DW-Agents/scripts/tag-interior-design.py --vendor <VENDOR_CODE> --limit 200
-```
-
-3. Focus on vendors that already went through Full Monty (they got tags via Gemini but shopify_products table may not be updated)
-
-4. Report: tags added per vendor
-
-## Key
-- Uses Gemini 2.0 Flash for vision analysis
-- API key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-- Adds style tags (Modern, Traditional), color tags, pattern tags, room application tags
-- Tags go on Shopify product tags field
diff --git a/tasks/done/04_ai-enrich-arte.md.pre-scrub-2026-05-07.bak b/tasks/done/04_ai-enrich-arte.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 487b4e5..0000000
--- a/tasks/done/04_ai-enrich-arte.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,9 +0,0 @@
-# AI Enrich — Arte (204 products missing AI colors)
-
-Same approach for arte vendor_code. Limit 200 per run.
-
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --vendor arte --phase 3 --limit 200
-```
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo | Model: gemini-2.0-flash
diff --git a/tasks/done/04_china-seas-hex-colors.md.pre-scrub-2026-05-07.bak b/tasks/done/04_china-seas-hex-colors.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 12751a6..0000000
--- a/tasks/done/04_china-seas-hex-colors.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,32 +0,0 @@
-## Extract Hex Colors for China Seas via Gemini Vision
-
-Use Gemini 2.0 Flash to analyze China Seas wallpaper product images and extract dominant hex colors.
-
-Query china_seas_catalog for all wallpaper products (mfr_sku LIKE '%WP%') that have image_url but no color_hex:
-```sql
-SELECT id, mfr_sku, pattern_name, color_name, image_url 
-FROM china_seas_catalog 
-WHERE image_url IS NOT NULL AND image_url != ''
-AND (color_hex IS NULL OR color_hex = '')
-AND mfr_sku LIKE '%WP%'
-LIMIT 200;
-```
-
-For each product, call Gemini:
-```bash
-curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo" \
-  -H "Content-Type: application/json" \
-  -d '{
-    "contents": [{"parts": [
-      {"text": "Analyze this wallpaper image. Return ONLY a single hex color code (e.g. #8B4513) representing the dominant/primary color. Just the hex code, nothing else."},
-      {"inlineData": {"mimeType": "image/jpeg", "data": "BASE64_IMAGE"}}
-    ]}]
-  }'
-```
-
-OR if image is a URL, use fileUri approach. Update the DB:
-```sql
-UPDATE china_seas_catalog SET color_hex = '#XXXXXX' WHERE id = {id};
-```
-
-Process in batches of 50. Report total updated.
diff --git a/tasks/done/04_gemini-texture-classify-17k.md.pre-scrub-2026-05-07.bak b/tasks/done/04_gemini-texture-classify-17k.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 3009890..0000000
--- a/tasks/done/04_gemini-texture-classify-17k.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,46 +0,0 @@
-# Gemini AI Texture Classification — Unclassified Products
-
-## Goal
-Classify products with no `repeat_classification` using Gemini Vision.
-Textures don't need repeat data. Patterns do. This closes the classification gap.
-
-## Step 1: Write and run a Node.js script
-
-Create `/root/DW-Agents/scripts/gemini-texture-classify.js` that does:
-
-1. Query DB for unclassified products:
-```sql
-SELECT id, vendor_code, mfr_sku, image_url 
-FROM vendor_catalog 
-WHERE on_shopify = true 
-  AND (repeat_classification IS NULL OR repeat_classification = '')
-  AND image_url IS NOT NULL AND image_url != ''
-ORDER BY id DESC
-LIMIT 5000;
-```
-
-2. For each product, call Gemini 2.0 Flash:
-   - API key: `AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-   - Endpoint: `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=API_KEY`
-   - Send image via URL in the request (download image, base64 encode, send as inline_data)
-   - Prompt: "Classify this wallcovering image. TEXTURE = solid color, natural fiber, faux finish, no repeating decorative pattern. PATTERN = has a decorative design that repeats (florals, stripes, geometric, damask, etc). Respond with ONLY one word: texture or pattern"
-
-3. Parse response, update DB:
-```sql
-UPDATE vendor_catalog SET repeat_classification = $1, updated_at = NOW() WHERE id = $2;
-```
-
-4. Rate limit: max 10 requests/second, exponential backoff on 429s
-5. Log progress every 100 products
-6. Batch size: process 5000 per run (YOLO can re-queue for more)
-7. If Gemini returns anything other than "texture" or "pattern", mark as "unknown"
-
-## DB Connection
-`postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-
-## Run
-```bash
-cd /root/DW-Agents/scripts && timeout 900 node gemini-texture-classify.js
-```
-
-Report: total classified, texture count, pattern count, errors.
diff --git a/tasks/done/04_recrawl-low-spec-vendors.md.pre-scrub-2026-05-07.bak b/tasks/done/04_recrawl-low-spec-vendors.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 9f886e1..0000000
--- a/tasks/done/04_recrawl-low-spec-vendors.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,46 +0,0 @@
-# Re-crawl Low Spec Vendors — Trigger fresh scans
-
-After fixing image and spec columns, re-trigger scans on vendors that need fresh data.
-
-## Re-scan these agents (check they're online first):
-```bash
-# Check each agent, restart if needed, then trigger scan
-for agent in "elise:9623" "dara:9632" "theo:9645" "cleo:9622" "artie:9624" \
-             "sasha:9620" "pj:9627" "maya:9626" "oscar:9640" "ines:9628" \
-             "knox:9621" "kira:9625" "rex:9635" "etta:9631" \
-             "dex:9633" "faye:9634" "graham:9617" \
-             "bjorn:9638" "milo:9639" "hank:9637" "beau:9629" \
-             "wendy:9642" "kurt:9636" "stu:9641"; do
-  IFS=: read name port <<< "$agent"
-  status=$(curl -s -u admin:DWSecure2024! http://127.0.0.1:$port/health 2>/dev/null)
-  if [ -n "$status" ]; then
-    echo "Scanning $name on $port..."
-    curl -s -u admin:DWSecure2024! -X POST http://127.0.0.1:$port/api/scan
-    sleep 5  # small gap between triggers
-  else
-    echo "OFFLINE: $name on $port"
-  fi
-done
-```
-
-Wait for all to complete, then run a final audit:
-```sql
-PGPASSWORD=DW2024SecurePass psql -h 127.0.0.1 -U dw_admin -d dw_unified -c "
-SELECT relname as catalog,
-  n_live_tup as products
-FROM pg_stat_user_tables
-WHERE relname LIKE '%_catalog' AND n_live_tup > 0
-ORDER BY n_live_tup DESC;"
-```
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY.**
-
-## Slack Notification — REQUIRED
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d '{"text":"VENDOR RE-CRAWL COMPLETE: [X] vendors re-scanned. Total catalog: [Y] products."}' "https://hooks.slack.com/services/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"
-```
-
-## EXCLUSIONS — DO NOT TOUCH IMAGES
-- **Phillip Jeffries (PJ, port 9627)** — Do NOT pull images. Specs only.
-- **Cowtan & Tout** — Do NOT pull images. Skip image fields entirely.
diff --git a/tasks/done/04_run-all-vendor-crawls-high-to-low.md.pre-scrub-2026-05-07.bak b/tasks/done/04_run-all-vendor-crawls-high-to-low.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index e47f1e2..0000000
--- a/tasks/done/04_run-all-vendor-crawls-high-to-low.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,86 +0,0 @@
-# Run Vendor Command Center Crawls — High-End to Low-End
-
-Trigger vendor crawls through the Vendor Command Center (Victor, port 9660) in order from highest-end luxury vendors down to mass market. For each vendor, trigger a scan and wait for completion before moving to the next.
-
-## Vendor Order (High-End → Low-End)
-
-### Tier 1 — Ultra Luxury
-1. **Elitis** (Elise, port 9623) — French luxury wallcoverings
-2. **Dedar** (Dara, port 9632) — Italian luxury
-3. **Timorous Beasties** (Theo, port 9645) — Scottish luxury
-4. **Cole & Son** (Cleo, port 9622) — Heritage British luxury
-5. **Arte International** (Artie, port 9624) — Belgian luxury
-
-### Tier 2 — Premium
-6. **Schumacher** (Sasha, port 9620) — American heritage luxury
-7. **Phillip Jeffries** (PJ, port 9627) — Natural materials specialist
-8. **Maya Romanoff** (Maya, port 9626) — Artisan handcrafted
-9. **Osborne & Little** (Oscar, port 9640) — British premium
-10. **Innovations** (Ines, port 9628) — Contract/commercial premium
-
-### Tier 3 — Upper Mid
-11. **Kravet** (Knox, port 9621) — Large design house
-12. **Koroseal** (Kira, port 9625) — Commercial wallcovering
-13. **Romo** (Rex, port 9635) — British design
-14. **1838 Wallcoverings** (Etta, port 9631) — Heritage prints
-15. **Ralph Lauren** (Ralph, port 9608) — Lifestyle luxury
-
-### Tier 4 — Mid Market
-16. **Thibaut** (Thibaut, port 9603) — American classic
-17. **York** (York Contract, port 9618) — American traditional
-18. **Designtex** (Dex, port 9633) — Contract/commercial
-19. **Fabricut** (Faye, port 9634) — Multi-category
-20. **Graham & Brown** (Graham, port 9617) — British modern
-
-### Tier 5 — Specialty & Niche
-21. **BN Walls** (Bjorn, port 9638) — Dutch wallcovering
-22. **Mind the Gap** (Milo, port 9639) — Eclectic design
-23. **Hygge & West** (Hank, port 9637) — Modern artisan
-24. **Bespoke** (Beau, port 9629) — Custom wallcovering
-25. **WallQuest** (Wendy, port 9642) — Decorative
-26. **Knoll** (Kurt, port 9636) — Contract furniture/wall
-27. **Stout Textiles** (Stu, port 9641) — Textile specialist
-
-### Tier 6 — Mass Market / Other
-28. **Brewster** (Brewster, port 9600) — Mass market
-29. **Contrado** (Carlo, port 9643) — Print-on-demand
-30. **Mural Source** (Murray, port 9644) — Custom murals
-31. **Arteriors** (Ari, port 9646) — Home accessories
-32. **Folia Fabrics** (Flora, port 9647) — Fabric specialist
-
-## How to Run Each
-For each vendor, check if the agent is online first:
-```bash
-pm2 list | grep <pm2-name>
-curl -s -u admin:DWSecure2024! http://127.0.0.1:<port>/api/status
-```
-
-If agent is online, trigger a scan:
-```bash
-curl -s -u admin:DWSecure2024! -X POST http://127.0.0.1:<port>/api/scan
-```
-
-Or via VCC:
-```bash
-curl -s -u admin:DWSecure2024! -X POST http://127.0.0.1:9660/api/vendors/<vendor_code>/scan
-```
-
-Wait for each to complete (check /api/status until scan_running=false) before starting the next.
-
-**ALL agents must capture: ALL specs, ALL images (pipe-separated in all_images), ALL catalog data.**
-
-Skip any vendors that are offline or erroring — just note them and move on.
-
-Report a summary at the end: vendor name, products crawled, spec completeness %, images captured.
-
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY. Downloading product data FROM other vendors' Shopify stores for catalog data is fine and expected. product-scheduler and schedule-engine are STOPPED intentionally. Do NOT restart them.**
-
-
-## Slack Notification — REQUIRED
-When this task is complete, send a Slack message to Steve with the results summary:
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d "{\"text\":\"TASK COMPLETE: [task name here]\\n\\n[brief results summary]\"}" "https://hooks.slack.com/services/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"
-```
-Replace [task name] and [results summary] with actual values. Keep it concise — 3-5 lines max.
diff --git a/tasks/done/05_ai-enrich-remaining.md.pre-scrub-2026-05-07.bak b/tasks/done/05_ai-enrich-remaining.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 08b0a3a..0000000
--- a/tasks/done/05_ai-enrich-remaining.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,10 +0,0 @@
-# AI Enrich — Remaining Vendors (Black Edition 195, PRL 186, Zinc 100, Kirkby 76)
-
-Run Phase 3 enrichment for these 4 smaller vendors. Process all of them in sequence.
-
-For each vendor_code in [black_edition, PRL, zinc_textile, kirkby_design]:
-```bash
-cd /root/DW-Agents/full-monte
-node full-monte-batch.js --vendor {vendor} --phase 3 --limit 200
-```
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo | Model: gemini-2.0-flash
diff --git a/tasks/done/05_china-seas-interior-tagger.md.pre-scrub-2026-05-07.bak b/tasks/done/05_china-seas-interior-tagger.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 2cf98fc..0000000
--- a/tasks/done/05_china-seas-interior-tagger.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,27 +0,0 @@
-## Run Interior Design Tagger on China Seas Wallpapers
-
-Analyze all China Seas wallpaper products and tag them with interior design terminology.
-
-For each wallpaper product on Shopify (china_seas_catalog WHERE shopify_product_id IS NOT NULL AND mfr_sku LIKE '%WP%'):
-
-Use Gemini 2.0 Flash (key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo) to analyze the product image and generate tags.
-
-Prompt for Gemini:
-"Analyze this wallpaper image as an interior designer. Provide:
-1. Style period (e.g., Mid-Century Modern, Art Deco, Contemporary, Traditional, Chinoiserie, Botanical)
-2. Pattern type (e.g., Floral, Geometric, Damask, Toile, Animal Print, Stripe, Abstract)
-3. Color family (e.g., Warm Neutrals, Cool Blues, Earth Tones, Jewel Tones)
-4. Recommended rooms (e.g., Living Room, Bedroom, Dining Room, Powder Room, Hallway)
-5. Design mood (e.g., Elegant, Playful, Dramatic, Serene, Bold)
-Return as JSON: {style, pattern, colorFamily, rooms, mood}"
-
-Save results to the `design` column and update Shopify tags to include the new design tags.
-
-Use Shopify REST API to update tags:
-PUT /admin/api/2024-01/products/{id}.json
-{"product":{"id":ID,"tags":"existing,tags,New Style Tag,New Pattern Tag"}}
-
-Token: <redacted:SHOPIFY_ADMIN_TOKEN>
-Store: designer-laboratory-sandbox.myshopify.com
-
-Process first 100 products. Report results.
diff --git a/tasks/done/05_crawl-report-for-steve.md.pre-scrub-2026-05-07.bak b/tasks/done/05_crawl-report-for-steve.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 0d265ce..0000000
--- a/tasks/done/05_crawl-report-for-steve.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,43 +0,0 @@
-# Morning Report for Steve — Crawl Results Summary
-
-Generate a comprehensive report of ALL overnight crawl activity. Steve is waking up and wants to see results.
-
-## Check ALL catalog tables
-```sql
-PGPASSWORD=DW2024SecurePass psql -h 127.0.0.1 -U dw_admin -d dw_unified -c "
-SELECT table_name, n_live_tup as row_count
-FROM pg_stat_user_tables
-WHERE table_name LIKE '%_catalog'
-ORDER BY n_live_tup DESC;"
-```
-
-## For each catalog, report:
-- Total products
-- Products with images (all_images not empty)
-- Products with width
-- Products with repeat_v
-- Products with material
-- Products with fire_rating
-- Price range
-
-## Also check:
-1. Are Sara, Nadia, Marco still running or completed?
-2. Any PM2 agents that crashed overnight?
-3. Disk space and memory usage
-4. Any errors in logs?
-
-## Format as a clean summary table that's easy to scan.
-
-Save the report to `/root/DW-Agents/logs/overnight-crawl-report.md`
-
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY. Downloading product data FROM other vendors' Shopify stores for catalog data is fine and expected. product-scheduler and schedule-engine are STOPPED intentionally. Do NOT restart them.**
-
-
-## Slack Notification — REQUIRED
-When this task is complete, send a Slack message to Steve with the results summary:
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d "{\"text\":\"TASK COMPLETE: [task name here]\\n\\n[brief results summary]\"}" "https://hooks.slack.com/services/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"
-```
-Replace [task name] and [results summary] with actual values. Keep it concise — 3-5 lines max.
diff --git a/tasks/done/05_final-audit-report.md.pre-scrub-2026-05-07.bak b/tasks/done/05_final-audit-report.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 605d8e7..0000000
--- a/tasks/done/05_final-audit-report.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,38 +0,0 @@
-# Final Audit Report — Full Catalog Status
-
-Generate a comprehensive audit of ALL catalog tables and send to Steve via Slack.
-
-## Run this audit:
-```sql
-PGPASSWORD=DW2024SecurePass psql -h 127.0.0.1 -U dw_admin -d dw_unified -c "
-SELECT relname as catalog, n_live_tup as products
-FROM pg_stat_user_tables
-WHERE relname LIKE '%_catalog' AND n_live_tup > 0
-ORDER BY n_live_tup DESC;"
-```
-
-## For the top 20 catalogs, check spec fill rates:
-For each table, run:
-```sql
-SELECT
-  COUNT(*) as total,
-  COUNT(NULLIF(image_url,'')) as has_image,
-  COUNT(NULLIF(all_images,'')) as has_all_images,
-  COUNT(NULLIF(width,'')) as has_width,
-  COUNT(NULLIF(repeat_v,'')) as has_repeat,
-  COUNT(NULLIF(material,'')) as has_material,
-  COUNT(NULLIF(fire_rating,'')) as has_fire_rating,
-  COUNT(NULLIF(body_html,'')) as has_body_html
-FROM xxx_catalog;
-```
-
-## Save report to:
-`/root/DW-Agents/logs/morning-audit-report.md`
-
-## Slack Notification — REQUIRED (send FULL summary)
-```bash
-curl -s -X POST -H "Content-Type: application/json" -d '{"text":"MORNING AUDIT COMPLETE\n\nTotal catalogs: [X]\nTotal products: [Y]\nWith images: [Z]%\nWith specs: [W]%\nWith fire ratings: [F]%\n\nFull report: /root/DW-Agents/logs/morning-audit-report.md"}' "https://hooks.slack.com/services/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"
-```
-
-## CRITICAL RULE
-**DO NOT import anything INTO the DW Shopify store. PostgreSQL catalog tables ONLY.**
diff --git a/tasks/done/06_hollywood-gemini-hex.md.pre-scrub-2026-05-07.bak b/tasks/done/06_hollywood-gemini-hex.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index f6054f5..0000000
--- a/tasks/done/06_hollywood-gemini-hex.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,14 +0,0 @@
-Hollywood Gemini hex color extraction — same pattern as DWPR.
-
-DB: postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-Model: gemini-2.0-flash
-
-1. Check how many Hollywood products have image_url but no hex color data:
-   SELECT COUNT(*) FROM hollywood_catalog WHERE image_url IS NOT NULL AND image_url != '' AND (color_primary IS NULL OR color_primary = '');
-2. Find the DWPR Gemini hex extraction script in /root/DW-Agents/vendor-scrapers/ (gemini-color*.py or similar)
-3. Adapt it for hollywood_catalog — send each product image to Gemini vision, extract dominant hex color
-4. Save hex to color_primary column
-5. Use Gemini Batch API if >100 products (50% cheaper)
-6. Rate limit: max 15 req/min for sync Gemini calls
-7. Report how many products got hex colors.
diff --git a/tasks/done/06_hollywood-hex-extraction.md.pre-scrub-2026-05-07.bak b/tasks/done/06_hollywood-hex-extraction.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 2a43bc3..0000000
--- a/tasks/done/06_hollywood-hex-extraction.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,21 +0,0 @@
-## Hollywood Gemini Hex Extraction
-
-Sessions #99 and #102 noted that Hollywood Wallcoverings (4,770 products) need Gemini hex color extraction — same process that was completed for Phillipe Romano (1,622 products).
-
-### Tasks:
-1. Check how many Hollywood products already have hex data in `product_colors` table
-2. Query `hollywood_catalog` for active products with images (image_url IS NOT NULL)
-3. Use Gemini 2.0 Flash to analyze product images and extract dominant hex color
-4. Store results in `product_colors` table (same schema as DWPR products)
-5. Generate color tags from the hex values
-6. Report: how many products processed, hex codes found, any errors
-
-Gemini API key: `AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-Model: `gemini-2.0-flash`
-Endpoint: `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={key}`
-
-Reference script: Look at how DWPR hex extraction was done in session #99
-DB: `postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-
-IMPORTANT: This is a large batch (4,770 products). Use rate limiting (max 10 req/s to Gemini).
-If batch is >100 products, consider using Gemini Batch API for 50% cost savings.
diff --git a/tasks/done/08_phase3-enrichment-run.md.pre-scrub-2026-05-07.bak b/tasks/done/08_phase3-enrichment-run.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index b786897..0000000
--- a/tasks/done/08_phase3-enrichment-run.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,13 +0,0 @@
-Run Phase 3 AI enrichment on products that have images but no AI color data.
-
-Connect to PostgreSQL: postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
-
-1. Find the catalog tables: SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_name LIKE '%catalog%' ORDER BY table_name;
-2. For each catalog table, find products with image_url but NULL ai_colors. Limit to 20 products per batch.
-3. For each product image, call Gemini Vision API:
-   curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo" \
-     -H "Content-Type: application/json" \
-     -d '{"contents":[{"parts":[{"text":"Analyze this wallcovering image. Return JSON with: colors (array of {name, hex, percentage}), background_color ({name, hex}), styles (array of strings like Traditional, Modern, etc), patterns (array of strings), image_type (scan_swatch, photo_full, etc). Be precise with hex codes."},{"inline_data":{"mime_type":"image/jpeg","data":"BASE64_HERE"}}]}]}'
-4. Download each image with curl, base64 encode it, send to Gemini
-5. Update the catalog table with the AI results
-6. Report how many products were enriched
diff --git a/tasks/done/08_slack-notify-completion.md.pre-scrub-2026-05-07.bak b/tasks/done/08_slack-notify-completion.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 8353279..0000000
--- a/tasks/done/08_slack-notify-completion.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,11 +0,0 @@
-# Send Completion Report to Slack
-
-After all previous tasks are done, send a summary to Slack.
-
-```bash
-curl -s -X POST 'https://hooks.slack.com/services/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' \
-  -H 'Content-Type: application/json' \
-  -d '{
-    "text": "✅ *Agent Abrams Content Overhaul — COMPLETE*\n\n*Blog:*\n• 134 junk posts deleted\n• 18 posts rewritten (professional, no jargon)\n• Astro site rebuilt and live\n• Blog generator fixed (dedup + daily limit + sanitization)\n\n*Videos:*\n• HTML video pipeline built (Puppeteer + CSS animations)\n• 18 new videos created (landscape + vertical)\n• All uploaded to YouTube\n• Old videos unlisted\n\n*All content sanitized. Zero leaks.*\n\nCheck goodquestion.ai and youtube.com/@AgentAbrams"
-  }'
-```
diff --git a/tasks/done/09_ai-enrich-zoffany.md.pre-scrub-2026-05-07.bak b/tasks/done/09_ai-enrich-zoffany.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 9e5bafc..0000000
--- a/tasks/done/09_ai-enrich-zoffany.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,12 +0,0 @@
-# AI Enrich — Zoffany (0 of 302 Shopify products enriched)
-
-Zoffany products are in w1838_catalog table (vendor_code w1838 in vendor_registry, but actual catalog table is w1838_catalog).
-Wait — Zoffany has its OWN table. Check:
-```sql
-SELECT table_name FROM information_schema.tables WHERE table_name ILIKE '%zoff%';
-```
-
-Find the Zoffany catalog table and run Phase 3 AI enrichment on all products with images but no ai_colors.
-
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo | Model: gemini-2.0-flash
-Limit 200 per run.
diff --git a/tasks/done/10_catalog-spec-fill-audit.md.pre-scrub-2026-05-07.bak b/tasks/done/10_catalog-spec-fill-audit.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index f7ccc48..0000000
--- a/tasks/done/10_catalog-spec-fill-audit.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,12 +0,0 @@
-Run a comprehensive spec fill rate audit across all vendor catalog tables.
-
-Working directory: /root/DW-Agents
-
-1. Connect to postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
-2. Query every table ending in '_catalog' to check fill rates for: image_url, all_images, width, material, repeat_v, fire_rating, body_html, mfr_sku
-3. Calculate fill percentages per vendor per field
-4. Identify the 10 worst-performing catalogs (most empty fields)
-5. Save a markdown report to /root/DW-Agents/logs/catalog-spec-audit-$(date +%Y%m%d).md
-6. Send a Slack notification summary via: curl -X POST -H 'Content-type: application/json' --data '{"text":"Catalog Spec Audit Complete - see logs/catalog-spec-audit report"}' https://hooks.slack.com/services/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
-
-Focus on actionable insights — which vendors need the most scraper improvements.
diff --git a/tasks/done/11_interior-design-tagger.md.pre-scrub-2026-05-07.bak b/tasks/done/11_interior-design-tagger.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 92b9967..0000000
--- a/tasks/done/11_interior-design-tagger.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,20 +0,0 @@
-Interior design tagger automation — build and run on justindavid + phillipe_romano catalogs.
-
-From Session 101: The interior-design-tagger skill exists at /root/.claude/skills/interior-design-tagger/SKILL.md but NO automated pipeline runs it.
-
-DB: postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
-Tables: justindavid_catalog, phillipe_romano_catalog (~9,392 products total)
-Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-Model: gemini-2.0-flash (vision)
-
-1. Read the skill file to understand the tagging logic
-2. Count products needing tagging in both tables (interior_design_status IS NULL or != 'done')
-3. Build a Python script /root/DW-Agents/vendor-scrapers/interior-design-tagger.py that:
-   - Queries products with image_url but no interior_design_status
-   - Sends image to Gemini vision with the skill prompt
-   - Parses response for design tags (style, room type, color palette, pattern)
-   - Updates DB with tags and sets interior_design_status = 'done'
-   - Rate limits to 15 req/min
-4. Run on a small batch first (--limit 20)
-5. If working, run full batch (use Gemini Batch API for 50% savings if >100)
-6. Report: how many tagged, sample output
diff --git a/tasks/done/12_weekly-relink-orphans.md.pre-scrub-2026-05-07.bak b/tasks/done/12_weekly-relink-orphans.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 4a31345..0000000
--- a/tasks/done/12_weekly-relink-orphans.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,46 +0,0 @@
-# Weekly Relink Orphans Run
-
-**Context**: The `relink-orphans.js` script matches Shopify orphan products to their vendor catalog rows by mfr_sku. It should run weekly to catch new drift before it accumulates. The last manual LIVE run (2026-04-10) relinked 3,979 rows.
-
-**Goal**: Run the relink script in LIVE mode, report the results, log to Slack if significant changes.
-
-## Steps
-
-1. Run the relink script LIVE:
-   ```bash
-   cd /root/DW-Agents && timeout 600 node scripts/relink-orphans.js --live 2>&1 | tee /root/DW-Agents/logs/relink-weekly-$(date +%Y%m%d).log
-   ```
-
-2. Parse the output to extract:
-   - Total orphans processed
-   - Can auto-relink count
-   - Updated catalog rows count
-   - Failures
-
-3. Run the drift audit to see the post-relink state:
-   ```bash
-   timeout 60 node /root/DW-Agents/scripts/drift-audit.js
-   ```
-
-4. If orphan count dropped by >10 since last run, post a Slack notification via:
-   ```
-   curl -X POST https://hooks.slack.com/services/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 \
-     -H 'Content-Type: application/json' \
-     -d '{"text": "Weekly relink: relinked N rows, drift now M.MM%"}'
-   ```
-
-5. Log result to `/root/DW-Agents/logs/relink-weekly.log` with date and counts.
-
-## Success Criteria
-- Script runs to completion
-- drift_audit_log has a fresh row
-- Slack notification sent (if threshold met)
-- Log file updated
-
-## References
-- Relink script: `/root/DW-Agents/scripts/relink-orphans.js`
-- Drift audit: `/root/DW-Agents/scripts/drift-audit.js`
-- Previous session commits: fa093bd59, dff14da82, ac1481da7, 4423ead47, 6538f96fd
-- Current state (2026-04-10): 1,690 orphans (3.27%), target <5%
-
-**Time budget**: 10 minutes.
diff --git a/tasks/done/13_hollywood-hex-extraction.md.pre-scrub-2026-05-07.bak b/tasks/done/13_hollywood-hex-extraction.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 0270973..0000000
--- a/tasks/done/13_hollywood-hex-extraction.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,17 +0,0 @@
-## Hollywood Wallcoverings Gemini Hex Extraction
-
-Sessions #99 and #102: Hollywood's 4,770 products need Gemini hex color extraction (same as completed for Phillipe Romano).
-
-### Tasks:
-1. Check `product_colors` table for existing Hollywood entries
-2. Query `hollywood_catalog` for active products with `image_url IS NOT NULL`
-3. For each product image, call Gemini 2.0 Flash to extract dominant hex color
-4. Insert into `product_colors` table with vendor='Hollywood Wallcoverings'
-5. Generate color tags from hex values
-6. Use rate limiting: max 10 req/s to Gemini API
-7. For batches >100, use Gemini Batch API (50% cheaper)
-8. Report: processed count, hex codes found, errors
-
-Gemini API key: `AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-Model: `gemini-2.0-flash`
-DB: `postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
diff --git a/tasks/done/19_zero-repeat-textures.md.pre-scrub-2026-05-07.bak b/tasks/done/19_zero-repeat-textures.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 87cf0cf..0000000
--- a/tasks/done/19_zero-repeat-textures.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,50 +0,0 @@
-# Set Repeat = 0 for Texture Products (No Pattern = No Repeat)
-
-## Context
-- DB: `postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-- Many products missing repeat aren't patterns — they're TEXTURES (grasscloth, linen, stucco, metallic, plain, solid)
-- Textures have zero repeat. If a scraper can't find a repeat, AND the image confirms it's a texture, set repeat_v = '0' and repeat_h = '0'
-
-## Task
-For each vendor catalog table that has products still missing repeats AFTER the scraper tasks run:
-
-### Step 1: Identify likely textures from names/descriptions
-```sql
--- Products missing repeat that are likely textures based on name/description
-SELECT id, sku, name, product_url, image_url
-FROM {catalog_table}
-WHERE (repeat_v IS NULL OR repeat_v = '' )
-  AND shopify_product_id IS NOT NULL AND shopify_product_id != ''
-  AND (
-    LOWER(name) ~ '(grasscloth|texture|linen|stucco|metallic|plain|solid|sisal|weave|burlap|faux |jute|suede|cork|hemp|raffia|sand|stone|concrete|plaster|canvas)'
-    OR LOWER(COALESCE(description, '')) ~ '(grasscloth|texture|linen|stucco|metallic|plain|solid|sisal|weave)'
-  );
-```
-
-For these, set repeat_v = '0' and repeat_h = '0' directly — name match is sufficient.
-
-### Step 2: For remaining unknown products, use Gemini Vision
-For products that still have no repeat AND didn't match the name pattern:
-
-1. Send the product's `image_url` to Gemini 2.0 Flash vision:
-   - API: `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-   - Prompt: "Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN."
-
-2. If Gemini says TEXTURE → set repeat_v = '0', repeat_h = '0'
-3. If Gemini says PATTERN → leave repeat as NULL (needs scraping or manual entry)
-4. Log all Gemini calls and track cost via `require('/root/DW-Agents/shared/gemini-cost-tracker.js')`
-
-### Step 3: Update DB
-```sql
-UPDATE {catalog_table} SET repeat_v = '0', repeat_h = '0', updated_at = NOW() WHERE id = $1;
-```
-
-Run for: `versace_catalog`, `thibaut_catalog`, `kravet_catalog`, `schumacher_catalog`, `brewster_catalog`, `york_catalog`
-
-## Important
-- Run AFTER tasks 13-17 (scraping) complete — this handles the leftovers
-- Gemini analysis key: `AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo` 
-- Rate limit Gemini to 10 req/s (flash is generous)
-- Track Gemini costs with the shared tracker
-- Report per vendor: how many set to zero by name, how many by Gemini, how many still unknown
-- Do NOT ask questions — run autonomously
diff --git a/tasks/done/25_zero-repeat-textures-r2.md.pre-scrub-2026-05-07.bak b/tasks/done/25_zero-repeat-textures-r2.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 39bfc6f..0000000
--- a/tasks/done/25_zero-repeat-textures-r2.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,50 +0,0 @@
-# Set Repeat = 0 for Texture Products — Round 2 (No Pattern = No Repeat)
-
-## Context
-- DB: `postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-- Many products missing repeat aren't patterns — they're TEXTURES (grasscloth, linen, stucco, metallic, plain, solid)
-- Textures have zero repeat. If a scraper can't find a repeat, AND the image confirms it's a texture, set repeat_v = '0' and repeat_h = '0'
-
-## Task
-For each vendor catalog table that has products still missing repeats AFTER the R2 scraper tasks run:
-
-### Step 1: Identify likely textures from names/descriptions
-```sql
-SELECT id, sku, name, product_url, image_url
-FROM {catalog_table}
-WHERE (repeat_v IS NULL OR repeat_v = '' )
-  AND shopify_product_id IS NOT NULL AND shopify_product_id != ''
-  AND (
-    LOWER(name) ~ '(grasscloth|texture|linen|stucco|metallic|plain|solid|sisal|weave|burlap|faux |jute|suede|cork|hemp|raffia|sand|stone|concrete|plaster|canvas)'
-    OR LOWER(COALESCE(description, '')) ~ '(grasscloth|texture|linen|stucco|metallic|plain|solid|sisal|weave)'
-  );
-```
-
-For these, set repeat_v = '0' and repeat_h = '0' directly — name match is sufficient.
-
-### Step 2: For remaining unknown products, use Gemini Vision
-For products that still have no repeat AND didn't match the name pattern:
-
-1. Send the product's `image_url` to Gemini 2.0 Flash vision:
-   - API: `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-   - Prompt: "Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN."
-
-2. If Gemini says TEXTURE -> set repeat_v = '0', repeat_h = '0'
-3. If Gemini says PATTERN -> leave repeat as NULL (needs scraping or manual entry)
-4. Log all Gemini calls and track cost via `require('/root/DW-Agents/shared/gemini-cost-tracker.js')`
-
-### Step 3: Update DB
-```sql
-UPDATE {catalog_table} SET repeat_v = '0', repeat_h = '0', updated_at = NOW() WHERE id = $1;
-```
-
-Run for: `thibaut_catalog`, `schumacher_catalog`, `brewster_catalog`, `york_catalog`
-(Skip kravet_catalog and versace_catalog — completed in round 1)
-
-## Important
-- Run AFTER tasks 21-23 (scraping) complete — this handles the leftovers
-- Gemini analysis key: `AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-- Rate limit Gemini to 10 req/s (flash is generous)
-- Track Gemini costs with the shared tracker
-- Report per vendor: how many set to zero by name, how many by Gemini, how many still unknown
-- Do NOT ask questions — run autonomously
diff --git a/tasks/done/29_texture-classify-remaining-r3.md.pre-scrub-2026-05-07.bak b/tasks/done/29_texture-classify-remaining-r3.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 845ecbf..0000000
--- a/tasks/done/29_texture-classify-remaining-r3.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,61 +0,0 @@
-# Classify Remaining Unknown Products as Texture or Pattern (446 thibaut + 13 brewster)
-
-## Context
-- DB: `postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified`
-- After R3 match_type scraping, some products will STILL have NULL match_type
-- These need Gemini Vision classification: TEXTURE → repeat_h = '0', PATTERN → leave for manual review
-- Also handles 13 brewster products with NULL match_type
-
-## Task
-
-### Step 1: Quick name-based classification
-```sql
--- Products missing repeat_h that are likely textures based on name
-UPDATE {catalog_table}
-SET repeat_h = '0', match_type = COALESCE(match_type, 'Texture'), updated_at = NOW()
-WHERE (repeat_h IS NULL OR repeat_h = '')
-  AND shopify_product_id IS NOT NULL
-  AND (
-    LOWER(name) ~ '(grasscloth|texture|linen|stucco|metallic|plain|solid|sisal|weave|burlap|faux |jute|suede|cork|hemp|raffia|sand|stone|concrete|plaster|canvas)'
-    OR LOWER(COALESCE(description, '')) ~ '(grasscloth|texture|linen|stucco|metallic|plain|solid|sisal|weave)'
-  );
-```
-
-Run for: `thibaut_catalog`, `brewster_catalog`
-
-### Step 2: Gemini Vision for remaining unknowns
-For products that still have no repeat_h AND didn't match the name pattern:
-
-1. Query remaining:
-```sql
-SELECT id, name, image_url FROM {catalog_table}
-WHERE (repeat_h IS NULL OR repeat_h = '')
-  AND shopify_product_id IS NOT NULL
-  AND image_url IS NOT NULL AND image_url != ''
-ORDER BY id;
-```
-
-2. Send image to Gemini 2.0 Flash:
-   - API: `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo`
-   - Prompt: "Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN."
-
-3. If TEXTURE → `UPDATE SET repeat_h = '0', match_type = 'Texture'`
-4. If PATTERN → `UPDATE SET match_type = 'Unknown Pattern'` (leave repeat_h NULL for manual)
-
-### Step 3: Final cleanup — assume Straight for remaining
-Any products STILL without repeat_h after Gemini classification:
-```sql
-UPDATE {catalog_table}
-SET repeat_h = '0', match_type = COALESCE(match_type, 'Assumed Straight'), updated_at = NOW()
-WHERE (repeat_h IS NULL OR repeat_h = '')
-  AND shopify_product_id IS NOT NULL;
-```
-
-This ensures 100% completion. Products tagged 'Unknown Pattern' or 'Assumed Straight' can be manually reviewed later.
-
-## Important
-- Run AFTER task 27 (match_type scraping) completes
-- Gemini rate limit: 10 req/s
-- Track costs via `require('/root/DW-Agents/shared/gemini-cost-tracker.js')`
-- Report: how many by name, how many by Gemini (texture vs pattern), how many assumed
-- Do NOT ask questions — run autonomously
diff --git a/tasks/done/AQ_hollywood-imageclean-and-spin.md.pre-scrub-2026-05-07.bak b/tasks/done/AQ_hollywood-imageclean-and-spin.md.pre-scrub-2026-05-07.bak
deleted file mode 100644
index 2fc0c75..0000000
--- a/tasks/done/AQ_hollywood-imageclean-and-spin.md.pre-scrub-2026-05-07.bak
+++ /dev/null
@@ -1,59 +0,0 @@
-Run image cleaning (crop text/logos) and swatch spin generation for ALL 75 Hollywood Abaca Grasscloth products.
-
-The room settings script (hollywood-rooms) is already running but it ONLY does rooms. This task handles the 2 missing steps: imageClean + spin.
-
-Product IDs are in /tmp/hollywood-ids.txt (76 total, skip 1496353341552 which already has both).
-
-Write a Node.js script at /root/DW-Agents/scripts/hollywood-abaca-clean-spin.js that processes each product:
-
-## STEP 1: Image Clean (crop text/logos from swatch)
-
-For each product:
-1. Fetch product from Shopify: GET /admin/api/2024-01/products/{id}.json
-2. Download the PRIMARY image (position 1, the original swatch) as base64
-3. Call Gemini 2.0 Flash vision to check if image has text/logos/watermarks:
-   - Endpoint: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-   - Prompt: "Does this image contain text, logos, watermarks, rulers, or website URLs? Answer YES or NO."
-   - mimeType: auto-detect from magic bytes (0xFF 0xD8 = image/jpeg, 0x89 0x50 = image/png)
-   - Strip any "data:image/...;base64," prefix before sending to Gemini
-4. If DIRTY (YES):
-   a. Save image to /tmp/clean_in_{id}.jpg
-   b. Use ImageMagick to crop: bottom 15%, top 5%, sides 2%:
-      - convert input.jpg -gravity South -chop 0x15% out1.jpg
-      - convert out1.jpg -gravity North -chop 0x5% out2.jpg
-      - convert out2.jpg -gravity West -chop 2%x0 out3.jpg
-      - convert out3.jpg -gravity East -chop 2%x0 -quality 92 final.jpg
-   c. Re-check with Gemini — if still dirty, crop more aggressively (bottom 25%, top 10%)
-   d. Upload cleaned image to Shopify as NEW image at position 1 (replacing old primary)
-      - PUT /admin/api/2024-01/products/{id}/images/{imageId}.json with { image: { attachment: base64 } }
-   e. Clean up /tmp files
-5. If CLEAN (NO): skip, log "clean"
-
-## STEP 2: Swatch Spin
-
-For each product (after clean step):
-1. Check if product already has a spin image (alt text contains "Spin" or "Swatch" or src contains "spin")
-2. If no spin exists, run the spin script:
-   - node /root/Projects/Designer-Wallcoverings/scripts/shopify-swatch-spin.js --product-id {id}
-   - Timeout: 120 seconds
-3. Log result
-
-## Rate Limiting
-- 500ms between Shopify API calls
-- 2s between Gemini calls
-- 3s between products
-- 15s timeout for each ImageMagick command
-
-## Logging
-- Log: "Product X/75: {title} — clean:{dirty|clean|skipped} spin:{done|exists|error}"
-- At end: "COMPLETE: X cleaned, Y spins generated, Z errors"
-
-## Config
-- Shopify token: <redacted:SHOPIFY_ADMIN_TOKEN>
-- Store: designer-laboratory-sandbox.myshopify.com
-- Gemini key: AIzaSyAO0rLKwtJUKcf3zVmKstBS4udct4QejMo
-
-After writing the script, start it with PM2:
-pm2 start /root/DW-Agents/scripts/hollywood-abaca-clean-spin.js --name hollywood-clean-spin --no-autorestart
-
-Report the PM2 name so it can be monitored.

← 574b0e6 untrack logs/*.log (junk); keep tasks/done history  ·  back to Yolo Agent  ·  untrack logs + done-task archive (approved cleanup) 8358fc1 →