# Wishdeal Factory buyer-path - iteration 149 ship log

**Date:** 2026-05-15 (push mode, 60 min cadence, MASSIVE drift sweep iter)

## What shipped (3 substantive ships - the biggest drift recovery of the campaign)

Iter 148 revealed a class of bug: source-generator cron runs revert surface-fix injectors. Iter 149 ran the full 50-audit sweep and found **5 major regressions** affecting **>1500 page-modifications worth of prior work**. Restored everything + patched 1 more source generator + fixed 1 corrupted regex.

## Ship 1: Restored 5 regressed accessibility fixes (>1500 page-modifications)

Ran all 50 audits to find current state vs expected. Major regressions detected:

| Audit | Pre-149 state | Post-149 fix |
|---|---|---|
| audit-heading-hierarchy | 0/248 FAIL (was 247/247 OK iter 139) | 248/248 OK |
| audit-aria-hidden-decorative | 0/248 FAIL (was 247/247 OK iter 140) | 248/248 OK |
| audit-form-labels | 3/747 FAIL (was 744/744 OK iter 133) | 747/747 OK |
| audit-favicon-coverage | 247/248 WARN (was 247/247 OK iter 132) | 248/248 OK |
| audit-cross-surface-name | 0/29 FAIL (was 29/29 OK iter 126) | 29/29 OK |

Re-ran every injector: h1-aria-fix, heading-hierarchy-fix, aria-hidden-svg-injector, aria-label-injector, skip-link-injector, landmarks-fix, favicon-injector. Plus force-regenerated fallback-subpages to fix how-it-works brand-rename drift. Plus manual title swap for brief-ai/skeptic-memos.

**Total surface re-fixes: ~2,100 page modifications** (496 SVGs + 744 forms + 248 headings + 248 H1s + 248 skip-links + 248 favicons + 28 brand-renamed how-it-works + 1 manual brief-ai).

## Ship 2: Patched trust-signal-injector source (iter-148 footer fix made durable)

Iter 148 added `role="contentinfo"` to 2 pages' wd-trust sections (competitor-tracker, immigration-law-ai). Iter-149 sweep showed both were REVERTED. Same iter-148 lesson at smaller scale.

Located source generator: `trust-signal-injector.py` rewrites the wd-trust section block. Patched line 56 to include `role="contentinfo"` in the section open tag.

**Result: audit-section-landmarks 246/248 → 248/248 OK. Fix is now durable across cron cycles.**

## Ship 3: Fixed corrupted brand-name regex in audit-case-studies-quality.py

The audit's `brand_brief_name(slug)` had `r"^name:\\s+(.+?)\\s*$"` (DOUBLE backslash in raw-string) instead of `r"^name:\s+(.+?)\s*$"`. The double-backslash made the regex match LITERAL `\s` characters, which no brand brief contains. So brand_brief_name returned None for all slugs, and the audit flagged all 24 brand-renamed products as "title-no-product" false positives.

Audit jumped from 215/249 FAIL to 241/249 WARN after the regex fix.

This is the third audit-precision-fix in the campaign (after apostrophe regex iter 129, DECORATIVE_ICON_v1 iter 146).

## /quality-report/ status

Pre-iter-149 (during drift):
- 1 FAIL (case-studies 215/249)
- 6 WARN (incl. heading-hierarchy + aria-hidden + form-labels + cross-surface-name + favicon as regressions, plus chronic 6)
- 35 OK

Post-iter-149 (after sweep + fixes):
- **0 FAIL** (restored from FAIL → WARN/OK)
- **7 WARN** (case-studies + meta-tags + paragraph + semantic-CTA + placeholder + back-link + emoji)
- **45 OK**

**0 FAIL state restored. 13 consecutive iters (148-149) but with 0-FAIL recovery this iter.**

## Source-generator drift register (cumulative)

Generators that own buyer-touching surfaces and would revert surface-fix injectors. Sorted by patch status:

| Generator | Patched (source-fix applied)? |
|---|---|
| brand_name_helper.py (used by 9 generators) | n/a - helper module |
| faq-template-gen.py | ✓ iter 125 |
| regen-unlock-pages.py | ✓ iter 125 |
| regen-adopt-pages.py | ✓ iter 125 |
| regen-feedback-page.py | ✓ iter 125 |
| regen-fallback-pricing.py | ✓ iter 125 + FORCE_REGEN |
| regen-vs-pages.py | ✓ iter 125 |
| regen-fallback-subpages.py | ✓ iter 125 + FORCE_REGEN + WD_PRESERVE_CUSTOM_SUBPAGE_v1 |
| case-studies-gen.py | ✓ iter 125 |
| jsonld-injector.py | ✓ iter 126 |
| og-meta-injector.py | ✓ iter 127 (brand + canonical) |
| top-utility-bar-injector.py | ✓ iter 148 (role=navigation + aria-label) |
| trust-signal-injector.py | ✓ iter 149 (role=contentinfo) |
| meta-description-injector.py | one-shot, idempotent |
| favicon-injector.py | one-shot, idempotent |
| skip-link-injector.py | one-shot, idempotent |
| h1-aria-fix-injector.py | one-shot, idempotent |
| heading-hierarchy-fix.py | one-shot, idempotent |
| aria-hidden-svg-injector.py | one-shot, idempotent |
| aria-label-injector.py | one-shot, idempotent |
| landmarks-fix-injector.py | one-shot, idempotent |

**Discovered durability gap**: the one-shot injectors (h1-aria, heading-hierarchy, aria-hidden-svg, aria-label, skip-link, landmarks-fix) need their effects to be IDEMPOTENT on cron, which they are - BUT none of them are SCHEDULED to re-run. So when a source generator overwrites a page (e.g., page rebuilds for any reason), the fix is lost.

Fix going forward: either (a) schedule the injectors to run periodically as guard-rails, OR (b) patch the source generators to include those attributes by default.

Did the latter for trust-signal-injector + top-utility-bar-injector. The other one-shots (h1-aria, heading-hierarchy, aria-hidden-svg, aria-label, skip-link, landmarks-fix) still need scheduling.

## Status snapshot

- 246 scored products + 2 partial builds
- 50 audit systems
- 0 fake-proof findings; ~120 in warn (estimate: 26 placeholder-CTA + 58 paragraph + 8 case-studies + 15 back-link + 3 emoji + 5 meta-tags + 1 fake-button + a few footer)
- 247 brand briefs with valid archetype
- 58 content invariants defended
- /quality-report/ surfaces 52 live-check cards (**0 FAIL**, 7 warn, 45 ok)
- 77/77 health endpoints, 182+ cron jobs
- 60 min cadence active

## Iter 149 throughput note

3 substantive ships at 60-min cadence. Largest drift-recovery iter in the campaign:
- 5 major audits restored from FAIL/WARN to OK
- 2 source generators patched
- 1 corrupted regex fixed
- ~2,100 page modifications applied

The "drift sweep" is now a valuable iter pattern: every N iters, run all audits + check vs expectations to catch source-generator regressions early. Consider scheduling as recurring sanity-check.

## Running queue (top 5 for iter 150)

1. **MILESTONE iter 150 - retrospective + cadence-validate refresh**
2. **Schedule one-shot injectors as cron guard-rails** (h1-aria, heading-hierarchy, aria-hidden-svg, aria-label, skip-link, landmarks-fix should run every ~hour to keep state)
3. **Patch source generators for the still-vulnerable one-shots** where feasible
4. **Wes-task: 120 warn items**
5. **Pivot to non-audit work** (essays, editorial)

## Cumulative iter 1-149

- **Catalog**: 246 scored + 2 partial
- **Content library**: 12 essays + Read-next + 273 OG PNGs + 149 styled ship-log pages + cadence-validate
- **Audit infrastructure**: 50 audit systems
- **Source durability**: 32+ generators + 13 patched for a11y/brand fix preservation + 47 JSON snapshots + 182+ cron jobs
- **Content invariants**: 58 defended
- **Source-generator regressions caught + fixed iter 149**: 5 (~2,100 page-mods restored)

Pattern at iter 149: the audit suite + drift-sweep cadence catches its own regressions. Iter 150 candidate: schedule a regular drift-sweep job to make this self-healing instead of manual.
