# June Billing Reconciliation — Cascades, Rednour + ACG Internal (6-13 to 6-26) ## User - **User:** Howard Enos (howard) - **Machine:** Howard-Home - **Role:** tech ## Session Summary Ran a comprehensive Syncro billing reconciliation for Howard's work since June 6, routed entirely through the `/syncro` skill. Started by indexing every Howard-authored session log since 06-06, filtering out Mike/Winter and internal-only sessions, then worked client-by-client. The headline finding for Cascades was that **most of the large June work was already invoiced** (voice VLAN + WiFi/RF on #32444 = 7h; Home→Pro round 1 #32466; SSD/UPS hardware tickets; shared mailboxes; Karen ALDOCS; Executive share; Chris Knight). Reconciliation was done against live Syncro (tickets + invoices + line items), not the logs alone, to avoid double-billing — and to catch the inverse: two hardware-only invoices (#32439 Memcare UPS, #32443 Front Desk UPS) that had **no install labor**. Billed the genuine Cascades gaps as several small tickets (per Howard's preference for multiple smaller invoices over one large one), all drawn from the prepaid block (which auto-nets $0 and debits hours): UPS install labor on #32439/#32443 (0.5h onsite each); a new Home→Pro round 2 ticket #32474 (2× $99 keys + 1.0h remote = the only real-dollar Cascades invoice, $215.23); a combined EDR-rollout + accounting-scan ticket #32475 (1.5h + 1.0h remote); an emergency power-outage recovery ticket #32476 (1.5h emergency onsite → prepaid ×1.5 = 2.25 qty); a Synology→CS-Server migration + SMB diagnosis ticket #32478 (2.0h remote, single combined line dated 06-18); and an Alma Montt offboarding ticket #32479 (0.5h remote). The Cascades block ran 46.75 → 37.50 (9.25h). Resolved a date/attribution discrepancy on the "power outage" via a raw-transcript dig (sub-agent over `~/.claude/projects/C--claudetools/*.jsonl` for 06-16 and 06-19): the 06-16 record was entirely remote (the "I was there" quote was Vertical's VoIP tech, not Howard); 06-19 onsite phone re-keying was already billed in #32444; and the outage was the unplanned 06-16-into-06-17 event (both Howard and Mike onsite for the pfSense recovery). Howard confirmed the outage as one billable item = 1.5h emergency onsite; billed to Howard, comment credits both techs. For non-Cascades: skipped Lens Auto Brokerage (a transient self-resolving Deskman triage explicitly logged as "not a ticket") and Dataforth (Howard's call). Confirmed Universal Minerals (#32397, $175) and Wolkin (#32465, $225) were already billed. Billed the one open item — Rednour Nick Pafford share setup on #32343 (1.0h onsite, $175 real-dollar; no block), attributed to Howard with ticket owner left as Mike; skipped the 06-26 Mac RMM diagnosis as an internal GuruRMM product bug. Finally built ACG internal time-tracking ticket #32480 ("Howard - Internal work 6-13-26 to 6-26-26") on the internal account (15353550) — 13 lines of Internal Labor (product 9269124, $0/hr time-tracking), 16.0h total: the three Howard-specified items (radio show 2h, Bitdefender skill 2h, EDR skill 2h) plus a bucket-A split of 10h across the other claudetools/GuruRMM dev work (Security Assessment, GuruRMM fixes, SPEC-030 uninstall, UniFi/pfSense verbs, AMPIPIT, ScreenConnect, GuruScan, Win11 KB, skill-first governance, sync/harness). Period total billed 6-13→6-26: ~31.5h (15.5h client + 16.0h internal). ## Key Decisions - **Reconciled against live Syncro before billing anything** — pulled tickets/invoices/line items per customer to establish already-billed vs gaps, rather than billing off session logs (which record work done, not billing state). This caught both double-bill risks and the labor-missing hardware tickets. - **Hours are the tech's call, not derived from logs** — every line's hours came from Howard explicitly; the logs only supplied the work scope and delivery channel. - **Several small tickets over one big invoice** (Howard's stated billing preference) — each Cascades gap got its own ticket/invoice; B (EDR) + C (scan) deliberately combined into one ticket per Howard. - **Prepaid mechanics:** all Cascades labor billed against the block (auto-nets $0, debits by quantity); emergency on a prepaid customer billed on 26184 at qty = actual ×1.5 (2.25 for 1.5h), not a separate regular+emergency line. Keys (product 23571919) are taxable and bill real dollars; block labor on the same invoice nets $0 via "- Applied N Prepay Hours." - **Attribution:** new labor attributed to the API-key owner (Howard, 1750); on Rednour #32343 (owner Mike) the line was set `user_id:1750` so Howard gets the commission without changing ticket ownership. - **Emergency outage billed as one event to Howard** (mentions Mike in the comment) per Howard, after the transcript dig showed 06-16 was remote and the real onsite emergency was the 06-16→17 pfSense recovery. - **Lens skipped** — transient updater-lock crash that self-resolved; the log explicitly recorded it as "not a ticket," so nothing to bill. - **Internal labor is $0 time-tracking** (product 9269124 price_retail 0.0) — #32480 records hours for utilization, not revenue; Bitdefender/EDR skill work was billed under the internal ticket, not double- counted in the dev-bucket split. - **Bucket-A split of the 10 internal items** weighted by scope (SPEC-030 + Security Assessment + GuruRMM fixes heaviest), summing to exactly the 10h Howard set. ## Problems Encountered - **#32439/#32443 looked billed but were hardware-only** — initial pass checked for *any* line item; Howard flagged the install labor was missing. Re-validated by line *type* and billed 0.5h onsite each. - **"Power outage on the 16th, onsite" did not match the record** — session logs had 06-16 as remote planning and the outage recovery as 06-17 (Mike onsite, Howard remote). Resolved with a raw-transcript sub-agent dig that surfaced the true picture; Howard then clarified it was one 06-16→17 event with both techs onsite. Billed per Howard's direct knowledge, flagged the discrepancy before posting. - **Universal Minerals / Wolkin assumed unbilled** — both were already invoiced (#32397 $175, #32465 $225); verified live before proposing anything, so nothing was double-billed. - **Multiple invoices per ticket on already-Invoiced tickets** — confirmed Syncro pulls only uninvoiced lines into a new invoice (matches the existing #32330/#32303 multi-invoice pattern), so adding labor + a new invoice to #32439/#32443/#32343 did not re-bill the prior hardware/remote lines. ## Configuration Changes No repo code/config changes. Syncro records created (all via the `/syncro` skill, heredoc/jq payloads): - **#32439** (id 112780453): +0.5h Labor-Onsite (line 43041905), invoice 1650816983 ($0), Resolution comment 420976000. - **#32443** (id 112827387): +0.5h Labor-Onsite (line 43041908), invoice 1650816984 ($0), comment 420976008. - **#32474** (NEW, id 113124973) "Windows Home -> Pro edition upgrades (round 2) - NurseAssist + DESKTOP-MD6UQI3": 2× Windows Pro Upgrade ($99 taxable) + 1.0h Labor-Remote (block); invoice 1650816992 ($215.23); status Invoiced. - **#32475** (NEW, id 113124984) "Datto EDR rollout + Accounting scan-to-folder setup": 1.5h + 1.0h Labor-Remote (block); invoice 1650816999 ($0); Invoiced. - **#32476** (NEW, id 113124998) "Emergency Onsite - Building power outage / pfSense recovery (06-16 overnight)": 2.25 qty Labor-Emergency (26184, 1.5h ×1.5, block); invoice 1650817007 ($0); priority 4 Urgent; Invoiced. - **#32478** (NEW, id 113125316) "Synology -> CS-SERVER file migration + SMB diagnosis": 2.0h Labor-Remote (block), single combined line dated 06-18; invoice 1650817187 ($0); Invoiced. - **#32479** (NEW, id 113125318) "Alma Montt - user offboarding (M365 + AD)": 0.5h Labor-Remote (block); invoice 1650817191 ($0); Invoiced. - **#32343** (id 111409967, Rednour, owner Mike): +1.0h Labor-Onsite ($175, user_id 1750=Howard), invoice 1650817586 ($175.00), no-block upsell note; comment 420978674. - **#32480** (NEW, id 113125980, ACG internal 15353550) "Howard - Internal work 6-13-26 to 6-26-26": 13 Internal-Labor lines ($0), 16.0h total; invoice 1650817773 ($0); Invoiced; comment 420981118. This session log created at `session-logs/2026-06/2026-06-26-howard-june-billing-reconciliation.md`. ## Credentials & Secrets None discovered, created, or rotated this session. Syncro auth via the per-user Howard API key baked into the `/syncro` skill (attribution user_id 1750). ## Infrastructure & Servers - **Syncro:** base `https://computerguru.syncromsp.com/api/v1`, query-param auth, Howard key (user_id 1750). - **Customers:** Cascades of Tucson 20149445 (prepaid block 46.75 → **37.50** after this run); Rednour Law 1224246 (prepay 0.0, no block); Arizona Computer Guru internal 15353550 (prepay 0.0); Universal Minerals 34844920; Wolkin/Robert 796910; Len's Auto Brokerage 3289131. - **Labor products:** 26118 Onsite $175; 1190473 Remote $150; 26184 Emergency $262.50 (onsite ×1.5); 23571919 Windows Pro Upgrade $99 taxable; 9269124 Internal Labor **$0** (time-tracking). - **Raw transcripts** mined for the 16th/19th: `C:\Users\Howard\.claude\projects\C--claudetools\*.jsonl`. ## Commands & Outputs - Per-customer reconciliation: `GET /tickets?customer_id=&per_page=100`, then `GET /tickets/` for line-item type/status; `GET /invoices?customer_id=` to map ticket_id → invoice; control chars stripped with `tr -d '\000-\037'`. - Prepaid rule honored: `GET /customers/` (full, authoritative) for `prepay_hours` before every preview — never from the search/list endpoint. - Billing sequence per ticket (heredoc/jq, `--data-binary`): comment → add_line_item(s) → invoices → PUT invoice note → PUT status Invoiced → post-bot-alert; each step guarded (STOP + echo response if any id came back null), no retries on ambiguous results. - Emergency prepaid mechanic verified on #32476: `Labor - Emergency or After Hours Business` qty 2.25, invoice line "- Applied 2.25 Prepay Hours," block 42.25 → 40.00. - Internal #32480: 13 lines via a bash array loop (product 9269124, price 0, user_id 1750); invoice hours-sum verified = 16.0. ## Pending / Incomplete Tasks - **Rednour 2-desktop fixes** — Howard still needs to fix Nick's two desktops; bill onto #32343 (multi- invoice) or a new ticket when done. - **GuruRMM macOS enrollment bug** — install script writes the site *code* where `/api/enroll` wants a UUID (HTTP 422); onsite paste-block delivered to Howard's Discord, fix pending onsite verify; product fix is Mike's (coord todo 6f2d22be). Not client-billable. - **Deferred per Howard (not billed):** Cascades CARF technology plan (06-24), Lupe Sanchez/Trcieja perf diag (06-18), KPI dashboard scoping (06-17); Dataforth 06-23/06-25 sessions; Lens (not-a-ticket). - **Invoice-date note:** #32478 references work date 06-18 in the line/comment; the Syncro invoice itself carries today's creation date (no API backdate). ## Reference Information - New tickets: #32474, #32475, #32476, #32478, #32479 (Cascades), #32480 (ACG internal). - Real-dollar invoices this run: #32474 $215.23, #32343 $175.00 (total $390.23). All other invoices $0 (prepaid block or internal labor). - Cascades block: 46.75 → 37.50 (9.25h drawn). Period total billed 6-13→6-26 ≈ 31.5h (15.5 client + 16 internal). - Already-billed verified: Cascades #32444 (7h voice/RF, inv 67856), #32466 (inv 67887 $215.23), #32440 (67850), #32439/#32443 hardware (67850/67851/67854), #32417 (67825), #32403 (67811), #32230 (67876), #32193 (67873); Universal Minerals #32397 (inv 67810 $175); Wolkin #32465 (inv 67885 $225). - 9 #bot-alerts posted (message_ids in the run output). - Syncro skill billing rules applied: `.claude/skills/` (syncro); prepaid emergency ×1.5; per-user attribution. ## Update: 17:19 PT — session close; 06-01→06-12 hours query abandoned (rate limit) Attempted to total Howard's billed labor hours across all clients for 2026-06-01 to 2026-06-12. The calc requires fetching each in-range invoice individually (tech attribution `user_id` lives only on invoice/ticket line items, not the `/invoices` list endpoint) — 46 ticket-bearing invoices in the window. The bulk per-invoice GET repeatedly failed: Syncro's **180 req/min per-IP limit is shared** (Discord bot + other sessions also hit it), so any burst beyond a handful was throttled to empty responses; paced foreground (perl micro-delay) and patient background runs (90s pre-wait + 1.5s pacing + retries) were also starved, returning OK=0/failed=46 even though single and ~5-at-a-time GETs work fine. **No billing changes were made — entirely read-only.** To finish later: trickle the fetch in bursts of <=6 spaced ~18s apart during a low-contention window (the `.trickle.sh` logic), summing `quantity` on line items where `item` matches /labor/i and `user_id==1750`, over invoices with `date` in range. Session closed at user request; no new tickets/invoices created since the prior content above (#32480 internal already captured). ## Update: 17:24 PT — .gitignore hardened against root scratch sweep Root cause of the earlier stray commits (`.lab.txt`, `.invcfg`, `.fail.txt`, `.hours_calc.sh`): the billing/invoice-calc scratch files were written to the repo root and were not gitignored, so the sync `git add -A` catch-all committed them. Added a targeted block to `.gitignore` — `.*.txt`, `.*.sh`, `.invcfg`, `.inv/`, `.one.json` — which ignores dot-prefixed scratch (legit scripts are `scripts/*.sh`, not dot-prefixed) without catching tracked root dotfiles (`.hosts.json`, `.devs.json`, `.mcp.json.example`, etc., verified via `git check-ignore`). Future session scratch in repo root won't be swept into commits.