# Wishdeal Factory buyer-path - iteration 104 ship log

**Date:** 2026-05-14 (push mode, 60 min cadence, periodic-verification iter)

## What shipped (2 substantive ships + 1 audit-discovery)

This iter built a periodic verification audit for hero-polish drift, then wired the result into /quality-report/ as invariant #13. **First-run result: 177/177 polishes intact, 0 drift.** The hand-polished work from iters 5-15 has been preserved across all subsequent regen cycles.

## Audit-discovery: hero-polish state at iter 104

**Polish library state:**
- 178 polish JSONs in /home/ubuntu/factory/director/hero-polish/
- 177 actually applied (1 is AUTO.json, a template placeholder with no real /builds/AUTO/ directory)
- 177/177 = 100% applied to products that have them

**Verification check (after HTML-entity-decode fix):**
- 177/177 polish blocks match the source JSON h1
- 0 drift
- 0 missing markers
- 0 missing pages

**Initial false-positive run:** First run reported 10 drifts. Inspection showed they were all HTML-entity encoding differences (apostrophes encoded as `&#x27;`, ampersands as `&amp;` on the page). The polish-applicator uses `html.escape()` correctly; my audit needed to `html.unescape()` before comparison. Fixed inline.

**The 26 hand-polished claim was stale.** Memory file said "26 hand-polished products." Actual current count: 177 (the polish library grew from iter 5 onwards). Iter 104 brings the catalog state into agreement with reality.

## Ship 1: audit-hero-polish-drift.py + JSON snapshot

Built audit-hero-polish-drift.py (~120 lines):
- Scans /home/ubuntu/factory/director/hero-polish/*.json
- For each, opens /srv/sites/factory/builds/<slug>/index.html
- Extracts the h1 inside the WD_HERO_POLISH_v1 block
- HTML-unescapes both sides + compares
- Categorizes: match / drift / no-marker / no-h1 / missing-page / missing-polish-h1
- Writes JSON snapshot at /srv/sites/factory/hero-polish-drift.json

**Cron:** every 30 min at :04, :34. Audit fast (~1 second for 177 scans).

## Ship 2: /quality-report/ surfaces hero-polish drift + invariant #13

Patched regen-quality-report.py with:
- New helper `latest_hero_polish_drift()` reads the JSON snapshot
- New "Hero polish sync" card: "177/177 - all polishes intact"
- New row in "What we audit" table: describes the audit + cadence + what it catches
- New content invariant #13: "No hero-polish drift between polish JSON and rendered page"

**Total live-check cards on /quality-report/ now: 7** (Health, Fake-proof, Adoptability sync, Em-dash, Broken-taglines, Page identity, Hero polish sync).

## Health hygiene (Op rule 5)

- **Em-dash sweep**: pending
- **audit-fakeproof**: 0 hard / 0 soft (CLEAN)
- **audit-adoptability-drift**: 245 matched, 0 drift, 2 partial-build
- **audit-page-identity**: 1714/1718 ok / 4 weak / 0 mismatch
- **audit-hero-polish-drift**: 177/177 match, 0 drift (NEW iter 104)
- **Health-check**: 77/77 passing

## Status snapshot

- 245 scored products + 2 partial builds
- 246 build pages with index.html
- 0 fake-proof findings, 0 score drift, 0 page-identity fall-throughs, 0 hero-polish drift
- **177 hero-polish blocks intact** (corrected from stale "26 hand-polished" memory)
- 247 brand briefs with valid archetype
- 12 essays + Read-next + JSON-LD
- 8 high-trust pages with JSON-LD durable
- /factory/catalog/ with CollectionPage
- 244 /builds/ pages with PNG OG + Product schema
- 271 OG PNG images
- 5 transparency surfaces + 104 styled ship-log detail pages
- /quality-report/ surfaces **7 live-check cards** (added Hero polish sync iter 104)
- **13 content invariants defended** (NEW iter 104: hero-polish drift)
- 77/77 health endpoints, 135+ cron jobs
- 60 min cadence active

## Iter 104 throughput note

2 substantive ships at 60-min cadence. The verification was the primary ask; building it as a durable audit (not a one-time check) plus surfacing the result on /quality-report/ converted "spot-check" into "ongoing-monitored-invariant."

## The 5 audit suites now operational

| Audit | Cadence | What | Iter shipped |
|---|---|---|---|
| audit-fakeproof.py | daily 4:30am | Fake-proof claims | 69 |
| audit-adoptability-drift.py | every 15 min | Score sync | 93 |
| audit-page-identity.py | every 30 min | Page-identity fall-through (7 surfaces) | 97 |
| **audit-hero-polish-drift.py** | every 30 min | **Polish JSON vs rendered page** | **104** |
| em-dash-sweep.py | every 15 min | Em-dash invariant | 1 (always-running) |

Each audit writes a JSON snapshot at /srv/sites/factory/<audit>.json that /quality-report/ reads. All four content-invariant audits return clean.

## Running queue (top 5 for iter 105)

1. **Audit on /factory/own/ pages** - parallel buyer-path surface not yet covered (244 pages)
2. **Audit on /factory/feedback/<slug>/ pages** - already in page-identity (7-surface) but no content-quality audit
3. **OG conversion completeness check** - 271 PNGs vs 247 brand briefs; possibly some still missing PNGs
4. **Cadence-validate 60 min** - iter 101-104 each 1-2 ships. Holding well.
5. **13th essay** - skip until queue has fresh candidate.

## Cumulative iter 1-104

- **Catalog**: 245 scored + 2 partial, 246 with index.html
- **Content library**: 12 essays + Read-next + 271 OG PNGs + 104 styled ship-log pages
- **High-trust pages**: 8 foundational + 5 transparency surfaces
- **Audit infrastructure**: **5 audit systems** + 7-surface coverage + self-healing INDEX_HTML_GUARD + improved name-matching + hero-polish drift detection
- **Source durability**: 24+ generators (added audit-hero-polish-drift iter 104) + 6 regen scripts auto-call injectors + 5 JSON snapshots + 135+ cron jobs
- **Content invariants**: **13 defended** at surface+source AND publicly surfaced

The hero-polish state is now self-verifying. The 177 polishes will get caught within 30 min if any regen drifts them. Time-to-detect on drift = at most one audit cycle.
