GC test calls · 19–20 August · read 21 August

The 36 calls

Miss Patty's notes, sorted by what actually caused each one. They are not one problem. They are five, and only two of them are ours to fix in code.

The headline

The most repeated fault is the one nobody had noticed

Every other complaint in the run is “he misheard me.” One is “he never asked.”

⚠️ Seven of thirty-six were booked with no email address. Three with no last name.

#6 “Forgot to ask for my email address” · #9 “He forgot to ask for my email address” · #12 “Did not ask me for the email” · #16 “he closed the call without getting my last name or email” · #18 “it only asked for the client’s name… did not ask for an email” · #23 “Josh did not ask for my email” · #33 “it caused him to forget to ask me my last name and my email”

The cause was the tool, not the prompt. save_contact required firstName and phone and nothing else, so a booking missing both fields was a perfectly valid call. The prompt carries pages on how to read an email back and not one line that makes asking unskippable — and a prompt rule is precisely what had already failed seven times.

✅ Fixed 21 August. The booking tool now refuses once with an instruction to go and ask, then saves on the second attempt whatever happens. Not a hard requirement: the escape hatch — three tries at a difficult address, then “we’ll confirm your email before the agreement goes out”, book, chase it later — has to survive, or we start losing jobs over a name the recogniser cannot hear. One nudge, then out of the way. In both brains. test/ask-before-you-book.test.mjs.

⚠️ It is not live on the phone until bot.py is deployed by hand

cp to /opt/austin-voice/bot.py then pm2 restart austin-voice. The web brain went out with the push.

All 36, by cause

Five different problems wearing one coat

CauseCallsWhoseState
Never asked for the email or the last name #6 #8 #9 #12 #16 #18 #23 #33 — 8 Ours — the tool schema Fixed 21 Aug
Audio cut out / went silent mid-call #1 #3 #5 #7 #8 #14 #19 #23 #35 #36 — 10 Infrastructure Ran on 2GB; now 8GB, and measured
Digits misheard — phone numbers, ZIPs #3 #12 #13 #17 #22 #27 #34 — 7 Recogniser Open — see below
Street names misheard #19 (NASA Road One) #22 #31 — 3 Recogniser · keyterms Open — a keyterm fix exists
Wrong availability — offered a filled slot #30 #31 #32 — 3 Not a code bug — see below Cause established
Quoted where he should have handed off #15 #21 — 2 Chad’s own price table Needs Chad’s ruling
Pool / services gaps #20 #29 #32 — 3 Chad’s onboarding form Ken has asked Chad to fill it
Went well / went as intended #2 #4 #10 #11 #24 #25 #26 #28 — 8 — Good

The three that look like our worst bug and are not

Wrong availability — #30, #31, #32

“He’s still saying we have an availability at 1 o’clock on Tuesday. That may be because I have scheduled 12 to 2:00 already and it is just not seeing a number one slot filled.”

Miss Patty, call #32 — and she is right

She diagnosed it herself and the code agrees with her. Josh reads GC’s GoHighLevel contacts to know what is booked. A job Miss Patty enters directly in ISN never reaches GoHighLevel, so it does not exist as far as availability is concerned. Josh then offers 1pm — correctly, by the only diary he can see, and wrongly by the one she is looking at.

⚠️ And a 12:00 job would not block 1:00 even if we could see it

A clash is defined as the same start time. Overlap is deliberately not modelled — the note in api/ghl/slot-claim.js says so and says why: inventing a duration rule a client never agreed to would refuse bookings they want. But GC’s own form now supplies one — “Typical inspection length: 2.5–3 hours” — so the objection that it would be invented no longer holds. This is a decision for Ken, not a change to slip in.

What already exists and would have prevented all three: the portal’s Block times. A job booked outside our system should be blocked in the calendar, and then Josh cannot sell it. That is a habit, not a build.

Ken answered two of these on the call

The ones that are Chad’s form, not our code

“Some of the errors were caused by his onboarding form wasn’t complete. The $75 pool. Who was doing the inspections when Chad’s no longer doing them and Greg is doing them. That all failed… He’s a source of truth for his own business, and we don’t feel comfortable producing his source of truth.”

Ken, 20 August
CallWhat Patty sawWhat the record actually says
#20 · #32“Josh is still telling me $75” for the pool $75 is correct for the plain Pool/Spa add-on. What he is not offering is the Pool Inspection with Leak Detection at $147, which is in the same record. Josh names the cheaper one and stops.
#29Never asks about well/septic, outbuilding, lawn irrigation All three are in GC’s add-on list with prices ($50 / $25 / $25). He has them and does not offer them.
#15 · #21Quoted $972 on a 6,200 sq ft home instead of handing off ⚠️ $972 is what Chad’s own table says. Standard stops at 5,500 sq ft (“do NOT quote”); the 5-Star table runs to 7,000, and 6,001–6,500 is $972. Josh followed the table. The two tables disagree about where the hand-off starts — that is a question for Chad, not a bug.
#21Quoted $622 first, then corrected He heard “2600” for “6200”. A digit failure, not a pricing one.
#13 · #22Told a caller they were out of the area He misheard the ZIP, then correctly applied the out-of-area rule to the wrong ZIP. #22 hung up. The cost of a digit error is a lost job.
✅ Already true, worth saying because it was raised

“Josh was promising text he couldn’t send.” Fixed 20 August — the web booking line said “an email and text”; it now says an email. We do not text homeowners.

“Whose name owns Queen City?” Done — the demo greets Ray Whitfield.

“It looks pretty thin with $7,000.” Done — the demo now carries 36 jobs and $24,175.

The 10 cut-outs

Silence mid-call — the biggest single group

“I’m sorry, I didn’t get that” · “I’m having problems with the line” · going quiet until the caller asks whether he is still there.

⚠️ Two things were happening on those two days, and both are real
  • Memory. Dil, on the call: “when we have Deepgram, we have PipeCat, we have all these things running the monitoring — it consumes memory.” The server has since been upgraded to 8GB of RAM. Ken: “the RAM is what’s pulling when everything starts up.”
  • We were deploying into their calls. Dil: “there’s a test call here during my time when I was working… it’s a multiple Josh. They’re hitting a moving target, because we’re testing.” Josh’s brain changed several times across those two days, so the 36 notes do not all describe the same Josh.

Neither is proven to be the cause of any specific cut-out, and I am not going to claim it is. What is fair to say: the two conditions that would produce exactly this are both gone or reduced, and the next run is the test. Ask Chad’s team to re-run a handful on a quiet server with nothing deploying, and compare.

🔴 Updated 21 Aug — those calls were made on a two gigabyte server

The RoseHosting invoice paid on 20 August reads “NVMe 2GB ⇒ NVMe 8GB”. So the entire 36-call run happened on two gigabytes, running Pipecat, Deepgram, Silero VAD, Smart Turn, ElevenLabs, the Node app and PM2’s monitoring at once. That is tight enough that the memory explanation stops being one of several and becomes the likeliest one.

It is still not proven, and that is the point. Nobody measured memory during a single one of those calls, so “it ran out of RAM” and “Deepgram dropped the socket” fit the evidence equally well. A plausible cause repeated often enough becomes a fact nobody checked.

✅ So it is now measured. Every call logs available memory at the start and at the end, and shouts when it is tight. After the next run the question is answerable from pm2 logs austin-voice instead of arguable. No new dependency — it reads /proc/meminfo, so the server’s Python environment is untouched.

⚠️ A paid invoice is not a running server — check two things
  • free -h should show 8GB total. A plan change in the billing panel usually needs a reboot before the guest actually sees it.
  • pm2 logs austin-voice should print its Pipecat version on boot — confirm it came back up after any reboot, and that it is still 1.6.0. Never pip install -U: 1.7.0 put a nine-second hole in a ten-digit read-back.

Digits — 7 calls, and one of them hung up

The fix that exists and is switched off

“Josh could never get the phone numbers correct (4 times). I was getting frustrated… I called back. He couldn’t get the numbers correct again… I never finished the call because I was so frustrated.”

Call #22

Keyterms are what make digits and local street names accurate, and they are measured: with them off, “1827 Willow Bend” came back as “187 Willow Bend” and “lockbox 4217” as “four to 21 up and seen”. With them on, both were right.

The phone line runs English only (Ken’s ruling, 13 August), which is the mode where keyterms work best. What is worth checking on the server before the next run is that AUSTIN_MULTILINGUAL_KEYTERMS is not off and that GC’s keyterm list actually carries the street and town names Patty was reading out — NASA Road One is exactly the kind of name that needs to be in it and, on the evidence of #19, is not.

Item 4

Double bookings — where this actually stands

State
Can Josh create a new one? No — slot-claim.js gates all three booking paths (phone Josh, web Josh, portal reschedule) and test/double-booking.test.mjs proves it in 28 checks. That went in 12 August.
So what are the four on Ted’s 3 August? Dated 3 August — nine days before the gate. They are Hamming test bookings from the run Dil reported as “multiple schedules got booked in the same time.” The fix stopped new ones; it did not clean up the old.
Can we see them all in one place? Now yes — the Watch Board lists every clash across GC, Quality and the demo. Each portal only ever showed its own, to its own inspector, which is why four sat there.
Is it one press to fix? Now yes — the work order’s Reschedule bar has a “Next opening” button. It asks the diary for that job’s own inspector and fills the fields. The person still presses “Move it.”
Have they been moved? No — see below.
⚠️ Why I have not moved them for you

Two reasons, and the first one is just a fact: this session has no GoHighLevel credentials, so it cannot write to Chad’s or Ted’s CRM at all.

The second is the rule Ken put on the portal himself — “Nothing has been moved for you.” Moving four of a client’s live bookings without them watching is the one thing every other part of this system refuses to do, because the customer at the old time was never told.

It is now two clicks each: open the job → Reschedule → Next opening → Move it. Under two minutes for all four. If you would rather I did it, give me a token and say so and I will.

⭐ Before the next test run

Block, in the portal, any job that was booked outside our system. That is what stops #30/#31/#32 happening again, and it needs no code.

Item 3 · counter-check

What the 20 August meeting asked for that the launch board does not carry

The board holds 200 items — 192 done, 8 blocked, none open. Everything below was asked for on the call and is on none of the 8.

#What was askedWho
1⭐ Ken gets access to Dil’s Claude Code account. The longest single thread on the call. Ken: “I just cannot be hamstrung… we’re still 12 hours behind, behind, behind, not including the weekends, when we have a product to get on the market by the end of the month.” Dil: “I’ll do research on how to make my account accessible.”Dil
2The onboarding form error that blocked testers. Ken: “they filled in their stuff and tried to go to the next level, and it had an error message that the onboarding form wasn’t available to them… one of the ladies, Gazelle, sent Beth a screenshot.” Cause fixed 20 August; Beth is re-messaging them.Claude
3Text consent taken on the call and recorded. Ken: “is it okay for us to text you the information? And then we record that… there couldn’t be any doubt that the person approved it.” And if they say no, “that needs to be marked, and we cannot do it” — they come out of Engine 1 and 2. He calls it a legal safeguard: “otherwise we can get sued.”Ken → build
4Resend buttons on the work order. If the agreement is unsigned, a button that sends it again; the same for an unpaid payment link. Ken: “that’s really super customer experience” — plus the legal reason, that an inspector who starts without a signed agreement has broken what he warranted to his insurer.Build
5Onboarding form asks: text or email the agreements? Per inspector. “That should be on the onboarding form.”Build
6Email verification tool wired into the import. Ken: “run the list through here via the API code” before anything is sent, to stop the bounces that got the sending domain penalised.Dil
7Import columns fixed: first name, last name, date last inspected (clients) and date last served (agents). “That would tell us what we needed to know to keep us safeguarded.”Beth
8Review page wording — Ken ruled on it. “Send us direct feedback” beside “Leave a Google review”; no single star; five stars each side; the Google button surrounded by real reviews. Plus: pull up two or three live client review pages and check they actually look like that.Beth
9Review responses are a content rule now. Thank the person, name the service, name the town. “If you have just a canned answer, thanks for your kind words, that’s worse than doing nothing at all.” And the reason it matters: most people only read reviews from the last two weeks.Ken
10GHL spam / unsubscribe threshold that alerts us when one client’s list starts misbehaving.Dil + Knox
11Landline check on the number we take. Dil’s point: ISN asks specifically for a mobile. A booking alert to a landline goes nowhere.Build
12Chad fills in his onboarding form. Ken has asked him and James was sitting with him. It is the direct cause of three of the call failures above.Chad
13More Hamming runs through Josh so the demo keeps filling. (The $7,000 complaint is already closed — it is $24,175 now — but the request for runs stands.)Dil
14The rest of Ken’s new homepage. Section 1 is up at /section. Ken: “my goal is to eliminate the original site.”Ken
Item 2 — Beth is handling it. Closed here.

The cause was found and fixed on 20 August: the sign-up page fired its text-message consent and the sign-up at the same moment, both wrote to the same file, the second one lost, and the customer saw an error. The fix does not create the accounts that were never written, so those who were blocked have no account yet.

Dil, 21 August: “do not worry about the early adopters — Beth will message them again.” The sign-up page works now, so a fresh attempt goes through. Nothing is needed from engineering, and this is not on anyone’s open list.

Already closed, so nobody re-raises them

Answered on the call and answered since

RaisedAnswer
“There are two privacy policies” There is one policy, linked twice, and both links are load-bearing. The agreement box must link it because it is one of the three documents that tick accepts; the SMS box must link it because carriers read the opt-in statement itself. Removing either breaks something. Ken had already reached the same place: “these two places may be completely fine.”
Ken: “they need to initial that they know that they can’t upload” Withdrawn by Ken in the same breath — “we took that exposure away because now they can’t upload… so they don’t really need to sign that.” The list tick box that is live says the list is their own past customers.
Slots per day on the calendar Approved — “Yeah, let’s do it” — with the mobile caveat. The calendar was also clipping Friday and Saturday off every desktop; fixed 21 August.
“Whose name owns Queen City?”Ray Whitfield.
Server memoryUpgraded to 8GB. Dil: “this is done.”