Executive Summary Tech Issues (10) Workflow Issues (7) Context & Session Issues (3) What Worked Recommendations
Executive Summary
20
Total Friction Points
10
Tech Issues
7
Workflow Issues
3
Session Issues
4
Still Open
10
Patterns That Worked

The Q1/Q2 2026 Sperry Tree Care campaign build covered a full-stack marketing system: 11 Kit nurture emails to ~1,400 Club members, 3 Meta paid social campaigns, WS4 Jobber-to-Kit Zapier automation, WordPress landing pages via REST API, Cloudflare Workers for all report/asset delivery, and a referral share precapture flow.

The single largest time drain was Kit API write operations being completely broken. V3 and V4 silently ignore subject and body writes, returning 200/201 while changing nothing. Multiple hours were lost diagnosing this before confirming no automation path exists. Every email body must be manually pasted via Kit UI.

The second largest issue was the Jobber to Kit automation gap: zero automation flows out of Jobber. Referred neighbors and estimate requests receive no automated follow-up. WS4 was designed to close this gap but was overdue at time of this report. This is the highest-ROI build remaining in the engagement.

On the workflow side, Meta TOS acceptance and client photo library requirements were launch blockers that should have been handled at contract signing. Approval delays cost prime spring pruning window time. These are process failures, not technology failures, and are fully preventable with updated onboarding checklists.

The patterns that emerged from this build — CF Worker as primary delivery, wrangler via Desktop Commander, navigator.share API detection, V3→V4→V3 Kit segmentation sequence, and Dispatch for unattended communication — are now locked into memory and reusable across all future client builds.

Tech Issues
🔴 Critical
1. Kit API write operations completely broken — V3 and V4 POST/PUT/PATCH silently ignore subject and body

Kit V3 and V4 API POST/PUT/PATCH calls for broadcast subject, body, and from-name all return 200/201 with no error — but nothing is written. The API reports success while silently discarding the content. Only DELETE and send_at schedule writes reliably work.

Time wasted: Multiple hours across several sessions — building API calls, testing V3 vs V4 endpoints, verifying authenticated payloads, comparing request/response pairs, and ultimately confirming no automation path exists.

Fix That Worked
Manual paste by Jason. Open the Kit draft URL → switch template to "Custom HTML" → paste HTML body → save. Attempting browser automation causes CSS artifacts (style blocks render as visible text in the email body).
Recommendation
Monitor Kit API status monthly. If write ops are restored, automate broadcast creation immediately. For new client engagements, evaluate ESPs with working write APIs: Loops (API-first), Resend, or Postmark + custom list management.
🟢 Resolved
2. Kit segmentation requires a 3-step API sequence — V3 and V4 each wipe what the other sets

Setting both content and subscriber filter on a Kit broadcast requires three sequential API calls. V3 PUT sets content/from/send_at but does not preserve subscriber_filter. V4 PATCH sets subscriber_filter but wipes email_address and send_at. Correct sequence: V3 PUT → V4 PATCH → V3 PUT again to restore what V4 wiped.

Fix That Worked
The exact 3-step sequence is documented in Kit API memory. Works reliably when followed in order.
Recommendation
Build a wrapper script that executes the 3-step pattern automatically: accepts broadcast_id, subscriber_filter, from_email, send_at as params and handles the V3→V4→V3 sequence internally.
🟢 Resolved
3. Cloudflare MCP is read-only — cannot deploy workers via MCP, must use wrangler CLI

The CF MCP can list workers and read configs but cannot deploy. Every CF Worker deployment requires wrangler CLI via Desktop Commander on the Mac.

Fix That Worked
cd /Users/Jason && /usr/local/bin/wrangler deploy [file] --name [name] --compatibility-date 2024-01-01 — run via Desktop Commander start_process. Reliable and fast once the pattern is known.
Recommendation
Treat wrangler as a first-class tool in all CF-related skills. Add deploy+verify cycle as a standard wrapper: deploy → wait 3s → fetch URL → confirm 200 response.
🟡 Medium
4. Elementor nonce blocks WordPress App Password for cache flush — requires browser tab

REST API writes to _elementor_data work correctly with the BT_admin app password. But Elementor cache flush requires its own AJAX nonce — not the WP REST nonce — so app password authentication is rejected for the flush call. Every content update via headless REST requires a separate manual browser step to flush cache before changes go live.

Fix That Worked
Use REST API for all content writes. Flush cache manually via browser tab on the Elementor Tools page at /wp-admin/admin.php?page=elementor-tools.
Recommendation
Build a dedicated cache-flush bookmarklet that auto-clicks "Clear Files & Data" when opened while logged in. Long-term: migrate LP delivery to pure CF Workers to eliminate the Elementor dependency entirely.
🟡 Medium
5. Wordfence WAF blocks large JSON REST API payloads — Elementor data updates fail silently

When updating Elementor widget data via REST API with large JSON payloads (full _elementor_data structures), Wordfence WAF blocks the request. The block can appear as a 403, a timeout, or an empty response. Not immediately obvious as a WAF block vs. an API auth issue.

Fix That Worked
Chunked updates, or temporarily disabling Wordfence WAF for trusted IPs during build sessions. Per authorized precedent in session memory, temporary WAF disable during builds is permitted — must re-enable immediately after.
Recommendation
Permanently whitelist the BOSSTORQUE build IP in Wordfence for the REST API endpoint pattern (/wp-json/wp/v2/*). Eliminates the need to toggle WAF during every build session.
🟢 Resolved
6. Jobber iframe src race condition — iframe loads before JS sets the ?ref= parameter

Initial LP implementation set the Jobber iframe src attribute via JavaScript after page load. The iframe began loading before the script executed, causing the first load to miss the ?ref= referral parameter. Referral attribution was silently lost on a meaningful percentage of form submissions.

Fix That Worked
Set src="" (empty string) in HTML markup. Set the real src via JS synchronously before the browser initiates any load. Referral parameter captured correctly on every load.
Recommendation
Always use the empty-src pattern for any Jobber iframe embed with dynamic URL parameters. Document in the Sperry LP design standard as a mandatory pattern.
🟢 Resolved
7. Mobile UA sniffing unreliable for share button — wrong device detection on edge cases

Initial referral share page used User-Agent string to detect mobile vs. desktop and conditionally show native share vs. Gmail/mailto fallback links. UA sniffing fails on desktop Chrome on Android, iOS Safari with desktop mode enabled, and other edge cases.

Fix That Worked
Replaced UA sniffing with navigator.share API detection. If navigator.share exists → native share. If not → Gmail + mailto fallback. Works correctly across all devices and browser configurations.
Recommendation
Rule: never use UA sniffing for feature detection. Always use API capability detection. Add to LP design standard as a global JS pattern requirement.
🟢 Resolved
8. present_files tool frequently fails — files in workspace reported as not accessible

The Cowork present_files tool frequently returns "not accessible on user's computer" when attempting to deliver files from the workspace folder. No clear pattern for when it works vs. fails — appears tied to file path mapping between the Cowork sandbox mount and the Mac filesystem.

Fix That Worked
Deploy to a Cloudflare Worker instead. Persistent, shareable URL that never expires and works on any device. Faster and more reliable than a local file link.
Recommendation
CF Worker deployment is now the default delivery method for all Sperry HTML deliverables. present_files is a backup-only option for non-HTML file types. Update all skill templates to reflect this default.
🟢 Resolved
9. iMessage MCP self-routing loop — messages to Jason's own number do not deliver to iPhone

The iMessage MCP configured with Jason's number (541-514-2521) creates a routing loop — the message routes back to the Mac iMessage app, not to the iPhone. Confirmed non-functional for all self-messaging use cases.

Fix That Worked
Dispatch only: surface the message directly in the Cowork session chat. Cowork auto-routes to the Dispatch thread in Jason's Claude mobile app with a push notification to iPhone. Zero additional tooling required.
Recommendation
Remove iMessage MCP from consideration for all self-notification use cases. The CLAUDE.md global rules already document this — reinforce in memory so no future session attempts iMessage for Dispatch-style alerts.
🟡 Medium
10. Meta Marketing API MCP token expiry — user tokens expire, no refresh token flow

The Meta Marketing API MCP uses a user access token that expires (typically 60 days for long-lived tokens). No refresh token flow exists — renewal requires manually generating a new token via Meta's Graph API Explorer. Expiry is not surfaced proactively; discovered only when a call fails.

Fix That Worked
Renew token manually when calls fail. Navigate to Graph API Explorer, generate a new long-lived token, update MCP configuration. Documented in the Meta MCP memory file.
Recommendation
Two paths: (1) Monthly calendar reminder to proactively renew the token. (2) Migrate to a Meta Business System User token — non-expiring, generated via Meta Business Settings → System Users. Priority: do this before the next Meta campaign build.
Workflow Issues
🔴 Critical
1. Zero automation flows out of Jobber — estimate leads get one confirmation email and nothing else

All 4 Zapier zaps in the current stack flow into Jobber (from Facebook Lead Ads and CF7 contact forms). Zero automation flows out. Every neighbor who requests an estimate after receiving a referral share gets a single Jobber confirmation email and then nothing. No follow-up sequence, no nurture, no re-engagement. WS4 was scoped to fix this but was overdue by 8+ days at the time of this report.

Fix / WS4 Scope
Build Zapier zap: Jobber "Estimate Created" trigger → Kit tag → enroll in Estimate Lead Warmup sequence.
Recommendation
This is the single highest-ROI automation gap in the entire stack. Estimate leads with zero follow-up is real revenue leaking. Include outbound Jobber zap in the SOW scope definition for all future field service clients — it should be a default deliverable, not an add-on.
🔴 Critical
2. Manual Kit paste is the only viable email content path — 5 minutes per email, 11 emails

Because Kit API writes are broken, every broadcast email requires a full manual workflow: write HTML locally → open Kit draft URL → switch to "Custom HTML" → paste → save → verify. Attempting browser automation causes CSS artifacts. 5 min × 11 emails = ~55 minutes of manual work that should be zero-touch.

Recommendation
Build a pre-paste workflow tool: validate HTML locally (promo check, style block position, link validity) → generate a Kit-ready paste guide CF Worker → open in browser → Jason pastes. Also: evaluate switching ESPs for the next engagement to one with working write APIs.
🟡 Medium
3. Meta Lead Ads TOS acceptance required separately — was a launch blocker requiring client chase

Before any Lead Gen campaign can run, the Facebook Page admin (Michele) must separately accept the Lead Ads Terms of Service at facebook.com/ads/leadgen/tos. This is a one-time step per ad account, completely independent of campaign creation — campaigns can be built and published, but they simply won't run until TOS is accepted. The dependency wasn't anticipated, causing a launch delay during peak spring season.

Recommendation
Add Meta Lead Ads TOS acceptance as a Day 1 client onboarding checklist item — before any Meta campaign work begins. Include the exact URL and a screenshot of what to click. This 2-minute step, if missed, can block campaigns for days.
🟡 Medium
4. Meta campaign creative blocked on real photos — AI images rejected, client photo library required

Initial Meta ad creative used AI-generated (Imagen 3) images as placeholders. Rob Miron rejected these and required real photos of Sperry's work before approving the campaigns. Kelly Lyons' photo library was the resolution, but sourcing the photos required additional coordination that delayed the approval cycle.

Recommendation
Client photo library delivery is a required contract signing deliverable — same day as SOW. No AI image should be used in a final Meta deliverable without explicit client sign-off. AI images are a placeholder only, never a deliverable.
🟢 Resolved
5. Promo policy violations in email content — prohibited promo language found pre-send

email_ws2_03.html contained two SOW violations: "priority scheduling" (prohibited per Sperry promo rules — not available and not offered) and "15% discount" (unapproved percentage discount). Caught during manual review before scheduling. Had the email been scheduled without review, two policy violations would have gone to 1,400 subscribers.

Fix That Worked
Manual review before each email was scheduled. Both violations corrected before any send.
Recommendation
Build a promo compliance check into the email review workflow. The check must scan for: "priority scheduling", specific discount percentages, unapproved offer language. Must run before every Kit paste operation, not after.
🟡 Medium
6. Kit broadcast stubs deleted between sessions — all 9 stubs had to be recreated

Kit broadcast stub IDs created in an earlier session (23674286–23674298) were deleted or expired by the time they were needed for scheduling. All 9 stubs had to be recreated with new IDs, and the memory file had to be updated. Cause unclear — Kit may auto-clean old unscheduled drafts, or they may have been explicitly deleted in the UI.

Recommendation
Never delete Kit broadcast stubs. Create all stubs at campaign start, log all IDs immediately to the Kit API memory file, and treat them as permanent until confirmed sent.
🔴 Critical
7. Campaign approval sent at build completion, not build start — 7+ days lost during peak spring season

The Meta campaign approval page wasn't sent to Rob until April 28 — weeks after the campaigns were built. Rob held approval for 7+ days during peak spring pruning season. The campaigns were ready; the delay was a process failure in when the approval was requested, not a build problem.

Recommendation
Send client approval requests on Day 1 of campaign build, not at completion. Use a CF Worker preview URL as the approval vehicle — it can be updated in place as the build evolves. Include a hard deadline tied to campaign timing and an escalation path if the deadline passes without response.
Context & Session Issues
🟡 Medium
1. Context loss through compaction — pre-compaction work not captured in _SESSION.md, caused re-work

Multiple compaction events occurred during long sessions. In each case, compaction triggered before _SESSION.md was updated with current state. Recovery required re-reading memory files, fetching live CF Worker pages to reconstruct the task list, and in some cases re-doing work that had already been completed but wasn't documented.

Fix That Worked
Manually updating _SESSION.md after the fact, then fetching live CF Worker status pages to reconstruct actual current state. Live pages are more reliable than memory files for capturing what's done vs. pending.
Recommendation
_SESSION.md update must be a mandatory step at every milestone — after each completed task, before any complex multi-step operation. Treat it like a git commit: small, frequent, immediately after meaningful work is done.
🟡 Medium
2. Wrong post-compaction recap — focused on email build work instead of Jason's actual SOW priority question

After a compaction event, the session recap prioritized recent email build work instead of addressing Jason's actual question about SOW priorities and what was still open. Required multiple corrections to re-orient. The error came from recapping what was most recent in context rather than fetching live state and answering the actual question.

Recommendation
Mandatory post-compaction restart protocol: (1) Read _SESSION.md → (2) Fetch live CF Worker status pages → (3) Confirm Jason's current priority before any work → (4) Proceed. Never recap from memory alone after a compaction event.
🟢 Resolved
3. Session transcript files inaccessible from bash sandbox — wrong session content returned

Session transcript JSONL files are stored at a path that doesn't map correctly to the bash sandbox mount. An attempt to read a May 4 transcript via bash returned content from an April 25 session — same filename pattern, wrong mount point.

Fix That Worked
Fetch live CF Worker pages instead. The status report and punchlist Workers reflect actual current state and are always accessible. No transcript reading needed.
Recommendation
Never rely on transcript files for state reconstruction. CF Worker pages are the canonical source of truth. For future client engagements, establish a "project state Worker" from Day 1 — updated in place as the project progresses.
What Worked — Patterns to Carry Forward
Empty src iframe + JS set pattern
Solves iframe race condition for Jobber embeds with dynamic URL params. Set src="" in HTML, set via JS before first load. Reliable across all browsers.
navigator.share API detection
Correct way to detect native share capability. If navigator.share exists → native share sheet. If not → Gmail + mailto fallback. No UA sniffing, ever.
CF Worker as primary file delivery
Persistent URL, works on any device, never expires, updates in place. Replaces unreliable present_files. Default delivery method for all HTML deliverables.
V3 → V4 → V3 Kit API sequence
Only reliable way to set both subscriber_filter AND email_address + send_at on a Kit broadcast. Three sequential API calls, in order. Documented in Kit API memory.
wrangler CLI via Desktop Commander
cd /Users/Jason && wrangler deploy [file] --name [name] --compatibility-date 2024-01-01. Handles ES modules and service workers. CF MCP is read-only — wrangler is the only deploy path.
Live CF Worker pages for state reconstruction
Fetching live status report and punchlist Workers mid-session reliably reconstructs project state after compaction. More accurate than memory files or transcripts.
_SESSION.md for context continuity
When updated proactively at each milestone, eliminates re-work after compaction. Must be a frequent commit pattern — not session-end-only.
WebFetch for live status mid-session
Fetching live CF Worker URLs mid-session to verify deploys and confirm state. Fast, no tool switching, gives ground truth on what's actually live.
Parallel subagent spawning
For independent research and build tasks, launching simultaneous subagents cuts wall-clock time significantly vs. sequential execution.
Dispatch (Cowork chat → mobile push)
The only reliable unattended communication channel. Cowork session chat auto-routes to Dispatch thread on Claude mobile with iPhone push notification. No special tool needed.
Recommendations

Automation — Build These Now

  • 1
    Jobber → Kit Zapier zap (WS4 — overdue, highest priority). Trigger: Jobber "Estimate Created." Action: Kit tag + enroll in Estimate Lead Warmup sequence. Every day this is missing is estimate leads with zero follow-up.
  • 2
    Kit email prep + promo compliance script. Validates HTML, checks for prohibited promo language (priority scheduling, unapproved discounts), verifies link validity, generates Kit-ready paste guide URL. Must run before every Kit paste operation.
  • 3
    wrangler deploy wrapper script. Handles the full deploy+verify cycle: write file → wrangler deploy → wait 3s → fetch URL → assert 200 → report deployed URL.
  • 4
    Meta system user token migration. Replace expiring user access token with a non-expiring system user token via Meta Business Settings → System Users. Priority: before the next Meta campaign build.
  • 5
    V3→V4→V3 Kit segmentation wrapper script. Accepts broadcast_id, subscriber_filter, from_email, send_at — executes the 3-step API sequence internally. Prevents re-learning this quirk on every campaign.

Build Workflow — Process Changes

  • 1
    Client photo library required at contract signing, Day 1. No Meta creative work begins without a Dropbox/Drive folder of approved client photos. AI images are placeholders only, never final deliverables without explicit client sign-off.
  • 2
    Meta Lead Ads TOS acceptance — Day 1 onboarding checklist item. Include exact URL (facebook.com/ads/leadgen/tos) and a screenshot of what to click. 2-minute task that blocks campaign launch if missed.
  • 3
    Campaign approval on Day 1 of build, not Day Last. Send CF Worker approval preview URL the same day the first draft is ready. Include a hard deadline tied to campaign timing and an escalation path for non-response.
  • 4
    Kit broadcast stubs — create all at campaign start, never delete. Create all stubs on Day 1, log all IDs to Kit API memory immediately. No deletion without explicit campaign cancellation confirmation.
  • 5
    Promo compliance check — mandatory before every Kit paste. Check for: priority scheduling, specific discount percentages, unapproved offer language. Non-negotiable pre-send step, formalized in the Sperry skill.

MCP / API Connections to Add or Fix

  • 1
    Jobber webhooks outbound. Critical gap. Jobber → Zapier → Kit is the only path for estimate follow-up sequences. No native Jobber outbound MCP currently exists.
  • 2
    Kit API write ops — monitor monthly. When Kit restores working POST/PUT/PATCH for broadcast body/subject, automate all broadcast creation immediately. Check Kit API changelog on the first of each month.
  • 3
    WP headless cache flush endpoint. Bookmarklet or lightweight endpoint that flushes Elementor cache without manual browser navigation. Eliminates the one remaining manual step in headless WP updates.
  • 4
    Wordfence IP allowlist for BOSSTORQUE build IP. Permanently whitelist for the REST API endpoint pattern. Eliminates WAF toggling during every WP build session.

Session & Context Management

  • 1
    _SESSION.md — mandatory milestone commits, not session-end-only. Update after every completed task. Treat like a git commit: small, frequent, immediately after meaningful work is done.
  • 2
    Formalize post-compaction restart protocol. Mandatory sequence: read _SESSION.md → fetch live CF Worker status pages → confirm Jason's priority → proceed. Never recap from memory alone after compaction.
  • 3
    Project state CF Worker — establish from Day 1 on all new engagements. A dedicated CF Worker URL reflecting what's done, pending, and blocked. The canonical source of truth — not memory files, not transcripts.