sync: auto-sync from GURU-5070 at 2026-07-23 08:05:57

Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-23 08:05:57
This commit is contained in:
2026-07-23 08:06:39 -07:00
parent 0e13aedb99
commit 61cc7eca5c
9 changed files with 273 additions and 48 deletions

View File

@@ -244,3 +244,4 @@
- [LAB-SVR is current](feedback_labsvr_retired.md) — Len's Auto LAB-SVR is the CURRENT server (replaced old LAB-SERVER); powered back on 2026-07-18
- [Datto AV uses Bitdefender drivers](feedback_datto_av_bitdefender_drivers.md) — rtp1/rtp2/BdNet/BdSentry/netprotection_network_filter* are Datto AV's own drivers (Bitdefender SDK), NOT orphan Avira installs; check infocyte SDK dir before treating as orphans
- [Prospect / call-list vetting criteria](feedback_prospect_list_vetting.md) — dedupe purchased lead lists against Syncro customers AND contacts by email domain; strip competitors, in-house-IT orgs, micro/consumer shops, HIPAA providers, non-AZ; location_type "Remote" = the contact, not the company
- [Syncro hides disabled customers](feedback_syncro_disabled_customers_hidden.md) — GET /customers AND ?query= silently omit disabled (former) customers; 5082 vs 5375 with include_disabled=true; an empty search is NOT proof of absence

View File

@@ -14,10 +14,27 @@ competitor, or a prospect ACG would refuse to onboard is an embarrassment ACG pa
**How to apply:**
1. **Dedupe against Syncro, not the wiki.** `wiki/clients/` holds ~75 articles; Syncro holds
~3000 customers + 768 contacts. Match on **email domain** (customer `.email` AND
5375 customers + 768 contacts. Match on **email domain** (customer `.email` AND
`GET /contacts` — a lead is often a contact under a differently-named customer record),
then normalized business name, then fuzzy. Domain matching found every real hit; name
fuzzing at <0.86 produced only false positives. Exclude free-mail domains from the map.
then normalized business name, then **domain stem ignoring the TLD**, then fuzzy at >=0.86.
Exclude free-mail domains. All four passes are load-bearing:
- Open Enclose matched only on **name + domain stem** — Syncro has `openenclose.com`,
the list had `openenclose.net`.
- Peach Properties matched only on **domain** — filed in Syncro as "Good Rain Appartments".
- AZ Litho is in Syncro twice, as "AZ Litho" and "Arizona Lithography".
- Fuzzing below 0.86 gave only false positives (TMM Family Services -> AMP Facility Services;
NTH Consulting -> SRK Consulting; Stark Electric -> Fiesta Electric).
**`GET /customers` HIDES disabled customers — pass `include_disabled=true` or the entire
former-client population is invisible.** 5082 default vs 5375 with the flag = 293 hidden,
and those 293 ARE the former clients the task is about. `?query=` search hides them too and
returns empty, which reads exactly like "no such customer." Never conclude a company was
never a client from a default list or a query miss. See [[feedback_syncro_disabled_customers_hidden]].
**Compute page count from `meta.total_entries` and assert the pulled count matches.** A
hardcoded page guard silently capped a customer pull at 3000 of 5082 and the dedupe looked
complete while missing 41% of the tenant. `/contacts` also caps ~50/page regardless of
`per_page=100` — verify against `total_entries`, never trust the loop terminator alone.
2. **Active vs former:** a Syncro record alone means nothing — many have zero tickets. Pull
ticket + invoice counts and max dates per matched customer. Recent invoices = ACTIVE
(exclude). Dormant = FORMER (keep on the list, flagged, as a warm re-approach).
@@ -36,13 +53,28 @@ competitor, or a prospect ACG would refuse to onboard is an embarrassment ACG pa
city/state is the contact's location. A Tucson company routinely shows a contact in another
state. Never drop for geography on that column alone — verify HQ (WebFetch the domain).
Flag them `remote_contact` so the setter knows onsite scheduling is harder.
5. **Check whether the file actually contains contact data.** These vendor exports often ship
as previews: `work_email`, `work_phone`, `mobile`, `street1`, `company_revenue`,
`company_employee_count`, `primary_industry` etc. hold the literal strings `Yes`/`No`
(= "we have this field"), not values. Say so before Mike pays a setting firm to work a
list with no phone numbers in it.
5. **The `Yes`/`No` columns are the vendor's data-availability manifest — this is BY DESIGN, not
a broken export.** `work_email`, `work_phone`, `mobile`, `alt_mobile`, `hq_phone`, `street1`,
`company_revenue`, `company_employee_count`, `primary_industry` etc. hold `Yes`/`No` meaning
"we hold this field for this contact." The vendor withholds the actual values until Mike
trims the list and sends it back; then they release the full records for the kept rows.
**Do not report this as a blocker.** Do mine it as a per-row reachability signal
(`phone_channels`) for the setter.
Output shape that worked: two CSVs in `~/Documents` — a tier-ranked `VETTED` call list
(A = priority, B = fits, C = qualify first) and an `EXCLUDED` list with a reason per row so
Mike can audit the cuts. See [[feedback-vault-every-credential]] for the unrelated-but-adjacent
rule on anything credential-shaped that surfaces in these files.
**Deliverables — the send-back file is the one that matters.** Three CSVs in `~/Documents`:
1. `<original name> - TRIMMED.csv` — **the vendor's own file: identical column set, column
order, and row order, kept rows only, rows byte-identical to source.** This is what goes back
to them to unlock the contact data. Verify col-list equality and row-order preservation
before handing it over.
2. `ACG Call List - VETTED.csv` — tier-ranked working list for ACG (A = priority, B = fits,
C = qualify first) plus `setter_note`, `phone_channels`, `remote_contact`, `flag`, `notes`.
**Every FORMER-CLIENT row gets a `setter_note` telling the setter to handle them gently**
(Mike, 2026-07-23) — as the 2nd column so it can't be missed. Pitch depth to what the records
support: substantial multi-year relationship / real but limited work / on file with little or
no work. Overstating a relationship to someone who knows better is its own failure. Assert in
code that every former row has a note and no other row does.
3. `ACG Call List - EXCLUDED.csv` — a reason per row so Mike can audit the cuts.
Keep `matchId` and `domain` on the ACG-side files so the vendor's unlocked data joins back
without redoing the vetting. See [[feedback-vault-every-credential]] for the adjacent rule on
anything credential-shaped that surfaces in these files.

View File

@@ -0,0 +1,47 @@
---
name: Syncro hides disabled customers from list AND search
description: GET /customers and GET /customers?query= both silently omit disabled (former) customers. Pass include_disabled=true, and never treat an empty query result as proof a customer does not exist.
type: reference
---
Verified live on the ACG tenant 2026-07-23:
- `GET /customers?per_page=1` -> `meta.total_entries` = **5082**
- `GET /customers?per_page=1&include_disabled=true` -> `meta.total_entries` = **5375**
**293 customers are hidden by default**, and they are precisely the *former* clients — Syncro
sets `"disabled": true` on the customer object when a relationship ends.
**`GET /customers?query=...` hides them too, and returns an empty result set.** Customer 2549923
has `business_name: "Open Enclose"`, `fullname: "Colt Barrins"`, `email:
openenclose@openenclose.com`, 97 tickets and 122 invoices — and every one of these returned zero
rows: `query=enclose`, `query=Open%20Enclose`, `query=Barrins`, `query=openenclose`. An empty
search result looks identical to "no such customer" and is **not** proof of absence.
`GET /customers/{id}` returns disabled customers fine — the id path is unfiltered.
Probed 2026-07-23: only `include_disabled=true` changes the count. `disabled=true`,
`archived=true`, `filter=disabled`, `status=disabled` are all ignored (still 5082).
`GET /customers/autocomplete?query=` returned nothing useful.
**How to apply:**
- Any task about **former / lapsed / churned clients, win-back, or "have we ever worked with X"**
MUST pass `include_disabled=true`. Without it the answer is structurally wrong, not merely
incomplete.
- **Never conclude "not a client" from a default list or a `?query=` miss.** If a human says a
company was a client and the search disagrees, the search is wrong — re-pull with
`include_disabled=true` and match on name + email-domain + domain-stem before doubting them.
- Watch for **duplicate records** for one company, often one active and one disabled, sometimes
under different names (Open Enclose = 2549923 + 139892; AZ Litho = "AZ Litho" 21215131 disabled
+ "Arizona Lithography" 2377491 active; SunDanzer = 139935 active + 35688623 disabled). Reconcile
by domain before reporting counts or history.
- Email domains drift between the tenant record and the outside world (`openenclose.com` in Syncro
vs `openenclose.net` live), so match the **domain stem ignoring the TLD** as well as the full host.
**Pagination, same session, same failure class:** derive page count from `meta.total_entries` and
assert the pulled row count matches. A hardcoded `[ $P -gt 30 ] && break` guard capped a customer
pull at 3000 of 5082 while the `N < 100` terminator never fired (every page was full), producing a
confident 41%-incomplete result. `GET /contacts` separately caps at ~50/page regardless of
`per_page=100` — 768 entries needs ~16 pages, not 8.
Used by [[feedback_prospect_list_vetting]].

View File

@@ -19,6 +19,12 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure ·
<!-- Append entries below this line -->
2026-07-23 | GURU-5070 | bash/api-pagination | [friction] Hardcoded page guard silently truncated a paginated pull: looped customers with '[ $P -gt 30 ] && break' at 100/page = capped at 3000 of 5082 real records, and the N<100 terminator never fired because every page was full. Produced a confident but 41%-incomplete dedupe. Always compute pages from meta.total_entries and assert the pulled count matches
2026-07-23 | GURU-5070 | syncro/customers-search | GET /customers?query= returned ZERO results for 'enclose', 'Open Enclose', 'Barrins', 'openenclose' despite customer 2549923 having business_name='Open Enclose' / fullname='Colt Barrins'. Search silently excludes disabled customers - do not treat an empty query result as proof a customer does not exist [ctx: endpoint=/customers?query cust=2549923]
2026-07-23 | GURU-5070 | syncro/customers-list | GET /customers omits disabled customers by default - 5082 returned vs 5375 with include_disabled=true (293 hidden). Former/inactive clients are invisible to the default list AND to ?query= search. Always pass include_disabled=true when the task is former-client detection [ctx: endpoint=/customers found=cust-2549923-OpenEnclose]
2026-07-23 | GURU-BEAST-ROG | msp360 | request to https://api.mspbackups.com/api/Provider/Login failed: <urlopen error [Errno 11001] getaddrinfo failed> [ctx: command=monitoring] (x2)
2026-07-22 | GURU-BEAST-ROG | rmm/hitmanpro | HitmanPro_x64 will not execute on Windows-on-ARM (Snapdragon X, LAPTOP-E5EKEJT8): process launches, idles at 0 CPU/1 thread, never scans, no log; 30-min RMM timeout hit. HMP has no ARM64 build - use Defender/EDR scan on ARM devices [ctx: client=bardach agent=d9cd756b cmd=e93474b9]

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -5,6 +5,12 @@
- **Machine:** GURU-5070
- **Role:** admin
> **[WARNING] READ `## Update: 08:03 PT — Corrections` (end of file) BEFORE ACTING ON ANYTHING
> BELOW.** Three findings in the original write-up are wrong: the Yes/No columns are NOT a broken
> export (they are the vendor's data manifest, by design); the Syncro dedupe was incomplete
> (`GET /customers` hides disabled customers AND the pull was truncated at 3000 of 5082); and the
> former-client count is 16, not 9. The Update section is authoritative wherever the two conflict.
---
## Session Summary
@@ -217,3 +223,136 @@ CALL LIST: 168 EXCLUDED: 70
- Tier legend: `A` = priority call (right size/industry, owner-exec contact, local);
`B` = fits, lower priority; `C` = qualify first (geography, size, or unverified)
- Exclusion reasons: `ACTIVE-CLIENT`, `COMPETITOR`, `IN-HOUSE-IT`, `MICRO`, `HEALTHCARE`, `NOT-AZ`
---
## Update: 08:03 PT — Corrections after Mike's feedback
Three corrections to the record above. **Sections written before this Update contain errors that
are corrected here; read this section as authoritative where the two conflict.**
### CORRECTION 1 — the Yes/No columns are NOT a broken export (retracts the "blocker")
The Session Summary and Pending Tasks above describe the `Yes`/`No` availability flags as a
blocker requiring the vendor to release an unlocked file. **Wrong.** Mike: *"They have the
phone/email addresses, they just don't show me those things. This list is what they sent me to
trim."* The flags are the vendor's data-availability manifest, by design — they withhold values
until the list is trimmed and returned, then release full records for the kept rows.
Mined the manifest as a per-row reachability signal instead. All 238 rows have a work email, a
mobile, and a LinkedIn; the differentiator is the rest:
| Channels held | Rows (of 168 kept) |
|---|---|
| mobile + alt-mobile + main line | 83 |
| mobile + main line | 46 |
| mobile + alt-mobile | 14 |
| mobile only | 17 |
| includes a direct work line | 8 |
Only 8 of 168 have a direct desk line; 17 have no main-line fallback. Added as a
`phone_channels` column on the VETTED file.
**New deliverable:** `C:\Users\guru\Documents\Arizona Computer Guru New List - TRIMMED.csv`
the vendor's own file, 168 kept rows, all 56 original columns in original order, original row
order, rows byte-identical to source. This is the file that goes back to them. Verified with an
explicit column-list equality + row-order + row-identity check. No ACG-internal columns added.
### CORRECTION 2 — the Syncro dedupe was materially incomplete (two compounding bugs)
Mike flagged Open Enclose as a previous client. It was not in my match set. Root cause was two
independent failures, both mine:
1. **`GET /customers` silently omits disabled customers.** Default `total_entries` = **5082**;
with `include_disabled=true` = **5375**. The 293 hidden records ARE the former-client
population this task exists to detect. `GET /customers?query=` hides them too and returns an
empty result — I ran `query=enclose`, `Open%20Enclose`, `Barrins`, `openenclose` and got zero
rows for a customer whose `business_name` is literally "Open Enclose". An empty query result
is NOT proof of absence.
2. **My own pagination bug.** The customer pull used a hardcoded `[ $P -gt 30 ] && break` guard
at 100/page = capped at 3000 of 5082, and the real terminator (`N < 100`) never fired because
every page was full. The dedupe ran against 59% of the tenant and was reported as complete.
A third trap on this specific record: Syncro holds `openenclose.com`, the lead list has
`openenclose.net`, so domain matching would have missed it even with a complete pull. Added a
**TLD-agnostic domain-stem pass** to the matcher.
**Corrected pull:** 5375 customers (`include_disabled=true`, page count derived from
`meta.total_entries`, pulled count asserted equal), 768 contacts. Four match passes: domain,
domain-stem, normalized name, fuzzy >= 0.86.
**Six additional former clients found. None active — so list membership did not change (still
168 / 70); only flags and notes changed.** FORMER-CLIENT count 9 -> 16.
| Lead | Company | Syncro | History |
|---|---|---|---|
| 175 | **Open Enclose** | 2549923 (DISABLED) | **97 tickets, 122 invoices thru 2020-11**; prepaid block expired 2025-08-19. Dupe 139892 disabled/no activity |
| 39 | **Geomechanics Southwest** | 7088458 | **47 tickets, 139 invoices thru 2022-07** |
| 75 | Peach Properties | 167909 | 10 tickets + 9 invoices, 2015 — filed as "Good Rain Appartments" |
| 208 | AZ Litho | 2377491 | 4 tickets + 3 invoices thru 2021-01; dupe 21215131 "AZ Litho" disabled/no activity |
| 20 | Finman & Associates | 3472144 | 1 ticket + 2 invoices, 2015 (filed under "Larry Finman") |
| 53 | American Play Systems | 344305 | 2 tickets thru 2016-01, 2 invoices thru 2014-02 (filed under "Debbie Moore") |
| 162 | Lightning Ridge Cellars | 7088554 | record only, zero activity |
Also found: SunDanzer has a second disabled record (35688623, no activity); Marana Chamber has a
second record (1021936, 1 ticket 2014-09).
Each of the four match passes was load-bearing — Open Enclose matched only on name + domain-stem,
Peach Properties only on domain (name is unrelated), AZ Litho exists under two different names.
Logged to `errorlog.md`: `syncro/customers-list` (include_disabled gap),
`syncro/customers-search` (silent empty query result), `bash/api-pagination` (`--friction`,
hardcoded page guard).
### CORRECTION 3 — gentle-handling notes for former clients (Mike's instruction)
Mike: *"They can all stay on the list, but since we used them in the past a note that the setter
should be gentle with them should be added."* Added a `setter_note` column as the **second
column** of the VETTED file (next to tier, so it cannot be missed). Three levels, matched to what
the Syncro records actually support — overstating a relationship to a prospect who knows better
is its own failure mode:
- **`established`** (Open Enclose, Geomechanics) — "Substantial multi-year relationship, ended
around YYYY. Do NOT pitch as a cold prospect... let them lead. No hard close."
- **`served`** (Peach, Earth Savers, Termagon, AZ Litho, Saguaro Solar, Finman, Aviva, American
Play Systems) — "We did work for them (last worked YYYY). Acknowledge the prior relationship up
front rather than introducing ACG cold. Reconnect first, qualify second."
- **`onfile`** (Serrato, Mission Management, Swaim, Marana Chamber, Ironwood Tree, Lightning
Ridge) — "On file with us from around YYYY, little or no work performed. Warm, not cold — don't
overstate the relationship."
Peach Properties was demoted from `established` to `served`: 10 tickets/9 invoices sounds
substantial but all fall inside 2015, so "multi-year" would have been false.
`classify.py` now asserts every FORMER-CLIENT row has a `setter_note` and that no non-former row
carries one, so a later reclassification cannot silently drop a note.
### Final state
```
CALL LIST: 168 EXCLUDED: 70
Tier A: 88 HEALTHCARE 18
Tier B: 57 IN-HOUSE-IT 18
Tier C: 23 MICRO 13
former client: 16 NOT-AZ 10
remote contact: 48 COMPETITOR 7
unverified: 4 ACTIVE-CLIENT 4
```
Deliverables in `C:\Users\guru\Documents\`:
1. `Arizona Computer Guru New List - TRIMMED.csv` — send-back file (vendor's format, 168 rows)
2. `ACG Call List - VETTED.csv` — ACG working list (tier, setter_note, phone_channels,
remote_contact, flag, notes, src_row, matchId)
3. `ACG Call List - EXCLUDED.csv` — 70 cuts with a reason each
### Still open
- **Mike has not reviewed the 168 names for pre-Syncro former clients.** The corrected dedupe
covers everything in Syncro including disabled records, but a client that predates Syncro or
was never entered remains undetectable by any query. An alphabetical scan list was printed for
him; no response yet.
- **Medical device makers/distributors kept** (Wells Johnson #197, NeuroVRD #65, Medfix #29,
Avery Therapeutics #15) as non-covered-entities. Reversible if Mike wants all
healthcare-adjacent gone.
- **4 UNVERIFIED** remain: Third Act/gvfan (#68), Pallet Recyclers (#115), REPICON (#151),
Southwest Solutions (#159). Sites blocked or unreachable.