# 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=<id>&per_page=100`, then `GET /tickets/<id>`
  for line-item type/status; `GET /invoices?customer_id=<id>` to map ticket_id → invoice; control chars
  stripped with `tr -d '\000-\037'`.
- Prepaid rule honored: `GET /customers/<id>` (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.
