Ship log · iter #135

Iteration 135 ship log

2026-05-15 · push mode, 60 min cadence, placeholder-CTA cleanup iter

On this pageWhat shipped (3 substantive ships) Ship 1: Survey + placeholder-cta-injector.py - 447 CTAs fixed Ship 2: audit-published-date.py - 35th audit class Ship 3: /quality-report/ wired - 1 new card + invariant #43 The 35 audit suites at iter 135 Health hygiene Status snapshot Iter 135 throughput note Running queue (top 5 for iter 136) Cumulative iter 1-135

Date: 2026-05-15 (push mode, 60 min cadence, placeholder-CTA cleanup iter)

What shipped (3 substantive ships)

Surveyed iter-134's 778 placeholder CTAs to find safe-match patterns. Built placeholder-cta-injector with high-confidence text-to-target mapping. Two injector runs fixed 447 of 778 CTAs (57% reduction). Plus built audit-published-date.py.

Ship 1: Survey + placeholder-cta-injector.py - 447 CTAs fixed

Surveyed all 778 empty-hash CTAs by visible text. Top patterns formed clear intent groups:

Intent groupSample textTargetFrequency
Trial / get-started"Start free trial", "Get Started Free", "Read the dossier"/factory/unlock/<slug>/~210
Demo / sales"Book a demo", "Talk to sales", "Watch Demo"/factory/operator-partnership/~80
Legal"Terms", "Privacy Policy"/factory/terms/~50
Pricing"See pricing"/factory/builds/<slug>/pricing/~10
FAQ"FAQ"/factory/builds/<slug>/faq/~5
How-it-works"See How It Works"/factory/builds/<slug>/how-it-works/~5

Built placeholder-cta-injector.py (~110 lines) with a safe-match table. Only replaces href="#" where the visible link text matches a high-confidence pattern. Ambiguous nav-style placeholders ("Platform", "Solutions", "Resources", "Customers", "Sign in") left untouched (Wes-task).

Run 1: 402 CTAs fixed across 161 pages. Extended pattern table for "Begin Free Trial", "Start the pilot", "Generate sequence/roadmap", "Watch Demo", etc.

Run 2: 45 more CTAs fixed across 25 pages.

Net result: 447 CTAs fixed. audit-anchor-jump-noise card: 52/247 -> 90/247. Empty-hash links: 778 -> 331 (57% reduction).

Remaining 331 are mostly hand-written nav stubs ("Platform", "Solutions", "Resources" x10 each, "Sign in" x10) that came from B2B SaaS template starters. These should probably be removed entirely since the factory doesn't have a /platform/, /solutions/, or /resources/ page. Wes-task.

Ship 2: audit-published-date.py - 35th audit class

Built audit-published-date.py (~95 lines). For each ship-log iter detail page (/factory/log/ship-logs/iter-N/) and each playbook essay (/factory/playbooks/<slug>/), verifies a published date is declared via:

Result: 139/146 clean. All 134 ship-log details are dated (the regen-ship-log-details.py generator does this correctly). 7 of 12 playbook essays missing dates: 5k-budget, agency-productization, counsel-anatomy, distribution-channels-2026, five-patterns, operator-partnership-math, vertical-ai-2026.

Cron: every hour at :55

Ship 3: /quality-report/ wired - 1 new card + invariant #43

Patched regen-quality-report.py:

Live-check card count: 36 -> 37. Total content invariants: 42 -> 43.

The 35 audit suites at iter 135

Class breakdown:

Health hygiene

Status snapshot

Iter 135 throughput note

3 substantive ships at 60-min cadence. Demonstrated the "audit finds drift -> survey -> safe-match table -> inject" loop on a real systemic issue (778 placeholder CTAs). 57% fix rate without editorial risk. Remaining 43% need human judgment (nav stubs, ambiguous CTAs).

Running queue (top 5 for iter 136)

  1. Wes-task: 157 build pages with remaining placeholder CTAs (331 links, mostly nav stubs)
  2. Wes-task: 7 playbook essays need published dates
  3. Optional: extend safe-match table further; nav-stub removal is high-leverage if Wes can confirm
  4. audit-script-coverage - verify expected analytics scripts loaded
  5. audit-csp-headers (server-level check)

Cumulative iter 1-135

The audit-survey-inject loop works at any drift scale: 778 broken CTAs -> 447 fixed in one iter. The safe-match table is the leverage point - it turns "fix one by one" into "fix N matching pattern X". Future audit findings can use the same pattern.

← PreviousIter #134 Next →Iter #136