The Distance Between Shipped and Changing Behavior.
Bright Side Plumbing has 300+ Python scripts, 95+ HTML playbooks, 30+ timers and 350 API endpoints.
Most of it stops halfway up the ladder. This document maps every system between "built" and "actually moving revenue."
80% of BSP systems stop at Step 2 or 3. Only 7 reach Step 6.
The 6-Step Weaponization Ladder
True weaponization is not deployment. It is the moment behavior or revenue actually changes.
1
Built
Code written, file exists. Most things live here forever.
2
Deployed
On VM or WP. Reachable. Not necessarily running.
3
Timer Running
Systemd/cron active. Process exits 0. Zero verification of output.
4
Producing Output
JSON/DB writes confirmed. Data flows. No one reads it yet.
5
Output Consumed
A human or downstream system reads and acts on the output.
6
Changing Behavior
TRUE WEAPONIZATION. Revenue or decisions move because of it.
Red-to-green: where BSP systems actually sit. Most mass is red/orange.
02The Ecosystem by the Numbers
Massive surface area. Tiny weaponized core. The problem is not "we do not have enough." The problem is "we do not finish the last mile."
300+
Python files built across Nexus / Titan / Zeus / Morpheus
Built
95+
HTML playbooks deployed to /documents/playbooks/
Deployed
30+
Systemd timers actively running on VM 34.55.179.122
Timers active
350
Morpheus/Titan API endpoints (201 confirmed live)
Surface area
48
Items built but NOT fully weaponized (step 1-4)
The gap
7
Items that reached Step 6 and changed behavior
Weaponized
03Scripts Written. Never Verified Executed.
Apr 2 marathon produced multiple Google Ads fix scripts. Files exist. Nobody has shown proof that the API actually applied the changes to the live account. Classic step 1-to-2 ghost.
Execution verification rate
0%
Unverified
fix_conversion_actions.py
Demotes 11 junk PRIMARY Google Ads conversions so Smart Bidding stops optimizing on noise.
Written Apr 2, file lives in BrightSide_Nexus_Package_v3
No log entry showing the Google Ads API mutation response
Current conversion state in Ads UI has not been re-audited
Smart Bidding still potentially poisoned
Step 1 of 6
Unverified
fix_negative_keywords.py
Pushes 43 negative keywords to campaigns to block wasted spend on irrelevant queries.
Produced in the Apr 2 session
No proof the negatives appear in the live shared set
Search terms report not re-sampled post-push
Waste may still be flowing
Step 1 of 6
Unverified
push_sewer_keywords.py
Inserts 39 sewer-specific keywords into the Mar 2026 sewer ad group to capture 576K monthly search volume.
Script authored, not logged, not diffed against live account
Ad group keyword count not reconciled
No click/impression delta reported in the 11 days since
Core revenue hypothesis untested
Step 1 of 6
Pattern
Pattern: Write-and-Forget
Every Apr 2 marathon produced scripts. None have a companion verifier. We produce artifacts, not outcomes.
No post-run grep against Google Ads snapshot
No Slack WIN when the mutation actually took
No "before / after" receipt archived
Systemic, not per-script
04Data Collected. Never Used.
Weeks of keyword and field-note research sitting in JSON files. No page, no blog, no ad copy, no Daniel prompt actually consumes it. The data was built. The weaponization was not.
Data-to-asset conversion
5%
Zero output
42,003 keywords researched
Full KC plumbing keyword universe inventoried with volume, CPC, intent. Zero pages published using the insights.
SEMRush pull + Ahrefs validation + GSC overlay
Clustered into 180+ service/intent buckets
Page build count attributable to this dataset: 0
Step 2 of 6
Invisible
576K monthly searches invisible
Sewer camera, sewer cleanout, sewer smell, sewer roots. The big search pools that BSP could dominate.
No dedicated landing pages for sub-intents
Sewer Camera Inspection page is the only one deployed
Estimated monthly lost impressions: 400K+
Step 2 of 6
Zero output
1,179 field notes analyzed
Real tech notes from real jobs, mined for blog opportunities. 50 blog ideas extracted. Zero blogs actually built from the list.
Topic extraction ran, JSON saved
Audrey never briefed on the 50
No blog calendar entry pulls from this source
Step 2 of 6
Not used
50 language bank phrases
Actual customer phrases pulled from Daniel transcripts and 3CX calls. Not injected into Daniel's Vapi prompt, ad copy, or landing page headlines.
Language bank sits in memory file
Daniel still uses generic script
Ad RSAs still generic
Step 2 of 6
Dormant
25,414 keywords inventoried
Total keyword universe across all KC plumbing variants. 13.7M monthly search volume. Staged but not mapped to content calendar.
Master JSON exists
No page-to-keyword map
No monthly priority sort feeding Audrey's queue
Step 2 of 6
Partial
Competitor SERP snapshots
Plumbing Express / Santa Fe Plumbing / others pulled. Gap analyses generated. Almost none of the gaps filled.
Snapshot JSONs dated Apr 2-10
Blog calendar has not pulled from gap list
Paid strategy has not adjusted to competitor ad creatives
Step 3 of 6
05Pages Built. Never Deployed.
Web pages written, reviewed, and left in draft. Content asset produced. Revenue asset absent.
Draft-to-live publish rate
15%
Draft
3 WordPress pages sitting in Draft
Emergency Plumbing, Gas Line, Sewer Line Replacement. All three have copy, schema, hero blocks. None are published.
WP status: draft
No Google crawl possible
No internal links pointing to them
Estimated monthly traffic lost: ~8K sessions
Step 2 of 6
Shells
11 Bricks staging pages
Template shells built on staging subdomain. Only 1 (sewer camera inspection) has actual content and is live on production.
10 of 11 are empty shells
No content production queue feeding them
No publish deadline
Audrey waiting on keyword brief that was never delivered
Step 1 of 6
Unpublished
Kalen's 3,713-word sewer blog
Kalen personally wrote a long-form sewer guide. It was reviewed, praised, never published.
Word count: 3,713
Master plumber voice, hard to replicate
In drafts folder, not in WP
Weeks of ranking potential lost
Step 1 of 6
VM only
Sewer Camera Inspection blog (VM)
Full blog with widgets built on the VM. Never pushed to WordPress production.
HTML lives in /opt/nexus/nexus/scripts/output/playbooks/
Not crawlable at callbrightside.com/blog/
Oxygen/Bricks page not created for it
Zero indexed, zero traffic
Step 2 of 6
06Features Built. Never Activated.
The biggest category. Fifteen-plus major features engineered to completion, then stalled behind a single activation step: a credential, an approval, a campaign submission, a checkbox.
Feature activation rate (15 tracked)
10%
Not authorized
Plaid Bank Integration
Approved, endpoints built, OAuth flow coded. Stephanie has not completed bank authorization. No live transaction feed.
BSP bank connection: not linked
Transaction pull: 0 rows
Blocks real-time profitability view
Step 2 of 6
Pending
10DLC Campaign Registration
Telnyx SMS infrastructure ready. 10DLC brand + campaign pending because BSP EIN has not been provided by Stephanie.
Blocks Daniel SMS follow-up
Blocks review request SMS
Blocks booking confirmation SMS
14+ days pending
Step 2 of 6
Voice not switched
Daniel Female Voice
Voice option identified, A/B script designed. Voice has not been switched in Vapi. Current voice remains unchanged.
No A/B test data
No call-outcome comparison
Stephanie has not approved final voice
Step 1 of 6
Collecting, not searchable
Daniel Transcript Repository
Transcripts are being captured. The searchable repo / tagging UI is not built. Robert cannot query "how many times did Daniel fumble this objection?"
Raw text files exist
No UI, no classification
No feedback loop into Vapi prompt
Step 3 of 6
Not deployed
Daniel Job Type Filter
Logic to route only high-intent job types into Daniel's flow. Designed, not deployed to Vapi.
Still answering all calls equally
Cheap-intent calls consume expensive AI minutes
Step 1 of 6
Not deployed
Daniel ETA Relay
When dispatch updates ETA, Daniel was supposed to surface the update to the caller. Feature designed. Not live.
Dispatch > Daniel webhook: not connected
Callers still get generic "on the way"
Step 1 of 6
$54K outstanding
Collections Bot
Follow-up bot for aging AR. $54K in outstanding invoices. Whether the bot is actively sending is uncertain. No report has come back showing a recovery dollar figure.
No weekly "dollars recovered" metric
No per-invoice status log
$54K still on the books
Step 3 of 6
Shells
Facebook EPA + $199 Checkup
Enhanced Performance Ads campaign shells created. $199 Checkup offer designed. Ad creatives absent. Campaigns never launched.
Campaign status: paused/unpublished
No audience targeting configured
No creative assets from Audrey
Zero spend, zero impressions
Step 2 of 6
Self-reverts
Weather Bidding Engine
Auto-adjusts Google Ads bids by local weather (freeze warning = sewer demand spike). Whenever the engine pushes a bid change, something auto-reverts it. Not weaponized.
Mutation log shows writes
Bid state reverts within hours
Root cause: automated rule conflict
Step 4 of 6
Tabled
Membership Engine
614 customers eligible for the FREE spend-based membership tier. Engine built. Tabled pending Brenda conversation.
Eligibility list: 614 names
No enrollment emails sent
No tier badges in ST
Step 2 of 6
Usage unclear
Sewer Hotspot Engine
337 historical sewer jobs clustered geographically. Heatmap built. Kalen / Ashton usage unclear: does the sales team route leads to the hotspots?
Hotspot JSON regenerates weekly
No dispatch-board integration
No ad geo-layer tied to hotspots
Step 4 of 6
$3.1M dormant
Estimate Recovery Pipeline
ST shows $3.1M in unsold estimates. Recovery engine designed. No systematic follow-up cadence is actively firing.
Pipeline: $3.1M
No "day 3 / day 7 / day 14" follow-up sequence executing
No recovered-dollar metric reported
Step 2 of 6
Not started
Auto-Review Engine (Stephanie #2)
Stephanie's priority #2. Automated post-job review solicitation flow. Not started.
No trigger logic built
Blocked by 10DLC anyway
Currently: manual review asks, inconsistent
Step 0 of 6
Not started
Customer Portal (Stephanie #3)
Stephanie's priority #3. Customer self-service portal for invoices, appointments, membership. Not started.
No wireframe
No auth strategy picked
Scoped only in verbal conversation
Step 0 of 6
Not started
100 Year LSA Campaign
Kalen approved the "100 Year KC Plumber" LSA angle. Campaign has not been created, creative not produced, geo-tier not applied.
Kalen approval: yes
LSA profile update: no
Creative brief to Audrey: no
Step 1 of 6
07Partners Engaged. Never Activated.
Conversations opened, commitments voiced, agreements half-signed. The work to turn goodwill into a working integration is the missing piece.
Partner activation rate
20%
Status unclear
Nick Welty (inspectornick.com)
Promised 8 client referrals / cross-promo opportunities. No cadence, no CRM tag, no inbound tracking.
Last touch date unclear
Not to be confused with Nick Chernioglo (BSP tech)
No co-branded landing page
No referral attribution mechanism
Step 2 of 6
Follow-up unclear
Audacy
Radio/streaming partnership conversation opened. No signed proposal, no follow-up loop, no decision owner.
No scheduled next call
No spend allocated
No creative concept produced
Step 1 of 6
No contract 24d
HubSpot
Demo done 24 days ago. No signed contract. Decision: no HubSpot (per memory) but status is limbo, not closed.
Memory says "no HubSpot"
No formal "we are not moving forward" sent
Rep likely still chasing
Closed-loop missing
Waiting on us
KSHB Media Partnership
Accepted terms ($10K or $5.5K test, free weather sponsorship, free 3K CRM records). Blocked on BSP data cleanup.
Launch target: July 2026
Data cleanup is the blocker
3K CRM records: not imported
Weather sponsorship: live but under-used
Step 3 of 6
Not scheduled
Kassidy Onboarding
ServiceTitan framework and training curriculum designed. No scheduled training session, no login provisioned, no first task assigned.
Framework docs exist
ST seat: not provisioned
Week 1 plan: not approved by Stephanie
Step 2 of 6
08Integrations: Partial.
Connected and handshaking, but not actually doing the job end to end. The classic "green dot lying to us" pattern.
Integration completeness
45%
Ramp 422
QuickBooks API
QB connected, P&L pulls cleanly. Ramp COGS sync returning 422 errors on the feed into QB categorization.
QB auth: live
P&L SSoT: working ($611K / 3mo)
Ramp 932+ transactions: 422 error on post
COGS attribution partially broken
Step 4 of 6
Usage unclear
Monday.com
Connected via API. Audrey does not use Monday.com (per memory). Actual usage inside BSP unclear.
Board ingestion works
No active workflow depends on it
No sync target
Step 3 of 6
Audience stale
Facebook CAPI
Conversion API verified, pixel firing. Custom audience not refreshed in weeks.
CAPI events: flowing
Custom audience last updated: stale
Lookalike seed not rebuilt post-Nick/Russ cleanup
Step 4 of 6
Actionability ?
Gmail Intel
100 messages analyzed, classified, summarized. No one is acting on the output. No drafts pushed, no tasks created, no alerts firing.
Analyzer timer active
Output JSON exists
No downstream consumer
Step 4 of 6
Engagement ?
GBP Auto-Post
Google Business Profile posts are scheduled and running. Engagement metric not tracked or correlated to calls.
Posts: firing weekly
GBP insights: not ingested
No A/B test on post format
Step 4 of 6
Blocked
Telnyx SMS
Templates built, sender verified, test traffic flowed. 10DLC not registered = carrier throttling / blocking production messages.
Templates: ready
10DLC: pending
Production SMS delivery: unreliable to blocked
Step 3 of 6
09Monitoring Gaps.
The systems that are supposed to tell us when other systems break are themselves silent. We find out by accident.
Monitor-to-alert coverage
30%
1 of 3 up
GCLID Bridge
Three GCLID capture processes intended. Only the one on port 8509 is confirmed running. Other two: status unknown.
Port 8509: active, captures verified Apr 13
Port 8503: historical, status unclear
Secondary capture process: not confirmed
Step 5 of 6
Unmonitored
Offline Conversion Upload
Fixed Apr 10 to post to the correct conversion action ($762 primary, not $0 secondary). Success-rate monitor not added.
Fix deployed: yes
Success-rate dashboard: no
Failure alert: no
Step 4 of 6
Warmup
Smart Bidding
Clean conversion data only just started flowing. The Google Smart Bidding 14-day learning window has not elapsed. Performance claims premature.
Clean data start: Apr 10
14-day window ends: Apr 24
Any performance read before then is noise
Step 3 of 6
Silent?
Self-Healer
Last successful run: 11 hours ago. Could be silently failing. No Slack alert on skipped runs.
Timer: active
Last log: 11h old
Expected cadence: hourly
Likely failing silently
Step 3 of 6
Not ingesting
RAG Ingestion (Incidents)
Incident postmortems are supposed to flow into Zeus RAG for future retrieval. Incidents are not being ingested.
Zeus has 2,808 chunks
Incidents category: 0 chunks
Each session repeats the same mistake
Step 2 of 6
Empty
Session Logger
nexus_session_logger.py exists. Across recent sessions it's been called rarely. Learnings do not persist. Each session reinvents the same lessons.
Lists made. Commitments spoken. The carryover rate is brutal. We accumulate queues faster than we close them.
Action-item close rate (rolling 30d)
25%
74 queued
Action Center Backlog
74 action items currently queued in the Action Center. No owner assignment discipline, no due-date sweep, no stale-item archive.
74 open
Oldest items: 30+ days
No "last touched" sort
Most incomplete
Apr 13 Standup (today)
24 items captured in the Apr 13 standup. Most incomplete even day-of. Pattern repeats weekly.
24 items raised
Completed by EOD: typically <8
Rollover to tomorrow: 16+
Partial
Apr 6 Standup
30+ items from the Apr 6 meeting. Partial completion, no closeout audit done 7 days later.
30+ raised
No completion report circulated
Items silently migrated without status
Weeks old
Mar 27 / 28 Overnight
Multiple items from the Mar 27/28 overnight push still open. Two+ weeks outdated. No archive, no active work.
Age: 2+ weeks
Original context lost
Should be archived or re-scoped
11The 3 Five-Minute Blockers.
The three items that cost BSP the most, take the least time to fix, and have not been done. The contradiction is the point.
Each of these is a single checkbox or console setting. Each has been outstanding for 2+ weeks. Each is silently costing measurable revenue and trust every day.
14+ days
DKIM in Google Admin
Google Admin console. Add DKIM record. 5-minute task. Blocks ALL outbound email deliverability.
Blast radius: every transactional email
Likely impact: review requests not arriving, invoices to spam
Root cause of churn on review flow
Who owns: Robert (auth to Google Admin)
18 days
GA4 MCC Conversion Import
GA4 events must be imported at MCC level, not individual account. Flagged Apr 7 Dhina meeting. Not done.
Impact: Google Ads Smart Bidding blind to GA4 conversions
Impact: reports show gap between GA4 vs Ads
Fix: toggle at MCC > Conversions > Import
Ongoing
GSC Indexing
Most pages marked "Discovered currently not indexed" or "Unknown to Google." Indexing requests not batched, sitemap not re-submitted post-deploys.
Impact: organic impressions collapse
Sewer Camera page: indexed
Most others: unknown
Fix: sitemap refresh + request indexing batch
12The Wins. Actually Weaponized.
Small and proud. These cleared all 6 rungs. Each changed a real number on a real dashboard.
Step-6 weaponization (out of 55+ tracked systems)
7 / 55
Weaponized
Aggregator Cancellations
Goodzer, Voolt, and Networx canceled. Clean, measurable, recurring win. $143K/yr returned to BSP.
Annual savings: ~$143,000
Confirmed in P&L trajectory
Zero regression risk
Step 6 of 6
Weaponized
ST Killer / Morpheus Infrastructure
Shadow-system Phase 1 live. 14 tables, 201 confirmed endpoints (of 350 target). Replaces ST queries across dashboards.
201 endpoints live
Queries faster than ST native
ST contract leverage before May/June renewal
Step 6 of 6
Weaponized
GTM v41/v42
Conversion tag fixed. Book-appointment event reliably fires across service pages.
GTM container v41 > v42
Book-appointment event verified
Feeds clean conversion data to Ads + GA4
Step 6 of 6
Weaponized
GCLID Bridge
Captures verified Apr 13. Click IDs now flow from paid click > form > ST > offline conversion upload.
Port 8509 process stable
GCLID rows increasing daily
Enables offline conversion attribution end-to-end
Step 6 of 6
Weaponized
Big Sale Tracker
Exposes $64K/week of real revenue that ST alone miscounts. Used in Stephanie reporting.
The repeatable motion of "identify, evaluate, cancel, replace with owned funnel." Beyond the individual cancellations, the motion itself is a weaponized capability.
Replaces dependency on rented leads
Recovers margin on every closed job
Repeatable on any future partner
Step 6 of 6
13Where Every System Actually Sits.
Below: every major BSP system placed at the rung it truly occupies. Not the rung we wish it occupied.
STEP 1 Built
fix_conversion_actions.py · fix_negative_keywords.py · push_sewer_keywords.py · Daniel Female Voice · Daniel Job Type Filter · Daniel ETA Relay · 100 Year LSA · Kalen's 3,713-word sewer blog · 3 WP draft pages
12
STEP 2 Deployed
42,003 keywords JSON · 576K invisible sewer searches · 1,179 field notes analysis · 50 language bank phrases · 25,414 keyword inventory · 11 Bricks shell pages · Sewer Camera VM blog · Plaid Bank integration · 10DLC pending · FB EPA/$199 Checkup shells · Membership Engine (614 eligible) · Estimate Recovery pipeline · Nick Welty partnership · Kassidy onboarding framework
GCLID Bridge port 8509 · Zeus RAG (2,808 chunks, used in session) · Sacred HTML data_weapons_plan (read by team) · Graph Brain (used during sessions)
4
STEP 6 Weaponized
Aggregator Cancellations ($143K/yr) · ST Killer / Morpheus (201 endpoints) · GTM v41/v42 · GCLID end-to-end · Big Sale Tracker ($64K/wk) · Pre-Write Gate · Aggregator Audit Motion
7
The mass sits at Steps 1-3. The revenue sits at Step 6. The gap between them is the entire thesis of this document.
14The Fix. How to Close the Gap.
Not more tools. Not more builds. The fix is a verification layer plus a hard kill-switch.
Layer 1
Output Verifier
Already designed. Checks step 4: did the process actually write output? Produces a nightly diff showing which timers fired vs which produced new rows.
Catches "timer active, output empty"
Scheduled nightly
Slack WIN only when outputs are healthy
Currently the Missing Third Agent
Layer 2 (new)
Behavior Verifier
NEW layer. Checks step 5-6: did any human or system consume the output and did a downstream number actually move?
Ties output rows to downstream KPI deltas
Example: GBP posts > GBP insights Δ > calls Δ
If no downstream motion after N days: flag
Builds the first feedback loop that detects weaponization, not just deployment
Layer 3
Weekly "What Actually Changed?" Report
One Slack message per Monday, to Robert only. Lists the systems where a real number moved, and the systems where nothing did.
Exactly one page
Pulls from Behavior Verifier
Reviewed in Monday planning
Forces the team to stop celebrating deploys
Layer 4 (kill switch)
14-Day Activation Deadline
After any system has been at Step 3 for 14 days without reaching Step 4, force a decision: activate or archive. No third option.
Archive is honorable. Drift is not.
Kills zombie timers
Frees cognitive load
Creates a real forcing function
The one-line thesis: BSP does not have a building problem. BSP has a finishing problem.
The fix is three small instruments that stop rewarding deployment and start rewarding behavior change.
A1Appendix: The Recurring Failure Patterns.
Every gap above is an instance of one of these patterns. Naming them is the first step to stopping them.
Pattern
The Green-Dot Lie
Timer active, script exits 0, API returns 200. We call it "working." We never check the output.
Auto-tagger ran in dry-run for weeks with zero writes
Offline conversions "ran" but timed out
Revenue returned data but it was phantom $128K
Fix: Output Verifier enforces "writes happened"
Pattern
The Half-Deployed Draft
Page, blog, campaign, or email composed. Sits in draft. No publish ritual, no publish accountability.
3 WP pages in draft
Kalen 3,713-word blog in folder
11 Bricks shells on staging
Fix: weekly publish review with a named owner
Pattern
The Handshake Without Follow-Through
Partner conversation produces warm intent. No CRM task, no next-meeting, no decision owner. The relationship rots.
Nick Welty: promised 8, no tracking
Audacy: conversation, no proposal
HubSpot: demo done, no formal close
Fix: every partner conversation = CRM record + next-step + due-date
Pattern
The Dataset That Never Hit the Page
Rich JSON produced. No template, no calendar, no campaign consumes it. Research becomes archaeology.
42,003 keywords unused
1,179 field notes unused
50 language bank phrases unused
Fix: every dataset gets a downstream consumer named before it ships
Pattern
The Self-Reverting Automation
Automation writes a change. Another automation overwrites it. Silent conflict. Neither system owns the final state.
Weather Bidding getting auto-reverted
GCLID bridge port conflicts
Fix: single writer per resource, conflict-detection rule in the graph
Pattern
The Learning That Never Persisted
Session ends, learnings dissolve. Next session repeats the same mistakes. Zeus RAG is the fix; it goes unused.
Session logger near-empty
Incident postmortems not ingested
Fix: mandatory --log and --learn calls per session, briefing at start
If you read the appendix and felt like each pattern fit three different sections above — that is the proof. The gap is systemic, not per-feature.