sync: auto-sync from HOWARD-HOME at 2026-05-06 15:10:59
Author: Howard Enos Machine: HOWARD-HOME Timestamp: 2026-05-06 15:10:59
This commit is contained in:
@@ -622,13 +622,15 @@ JSON
|
||||
|---|---|---|---|
|
||||
| `1190473` | Labor - Remote Business | `150.00` | Standard remote work |
|
||||
| `26118` | Labor - Onsite Business | `175.00` | Base onsite rate |
|
||||
| `573881` | Labor - In Shop Business | `150.00` | Hardware brought into ACG's shop |
|
||||
| `26184` | Labor - Emergency or After Hours Business | `262.50` | **1.5× onsite; time-and-a-half baked into the rate.** Non-prepaid customers only. Do NOT stack with `26118` for the same hours. |
|
||||
| `9269129` | Labor - Prepaid Project Labor | `0.00` | Debits from customer `prepay_hours` bank |
|
||||
| `9269124` | Labor - Internal Labor | `0.00` | Non-billable internal time |
|
||||
| `1049360` | **Labor- Warranty work** | `0.00` | **Use this for ANY warranty / no-charge work.** Do NOT use a billable labor product + `billable: false` or a patched price. See `feedback_syncro_warranty_product.md`. |
|
||||
| `9269129` | Labor - Prepaid Project Labor | `0.00` | Debits from customer `prepay_hours` bank. Per `feedback_syncro_labor_type.md`: do NOT use as a default — only when explicitly directed. |
|
||||
| `9269124` | Labor - Internal Labor | `0.00` | Non-billable internal ACG time (not customer-facing). |
|
||||
| `26117` | Fee - Travel Time | `40.00` | Per travel event (not hourly) |
|
||||
| `68055` | Labor - Website Labor | `150.00` | Website-related work |
|
||||
|
||||
`price_retail` is the per-unit rate. Line item total = `price_retail × quantity`.
|
||||
`price_retail` is the per-unit rate. Line item total = `price_retail × quantity`. **Rates are determined by the product selected** — never patch `price_retail` on a line item to convert one product into another (e.g. don't take Remote Labor at $150 and patch to $0 to mimic warranty). If a line's dollar amount is wrong, the wrong `product_id` was picked — undo, pick the correct product, redo. The only legitimate `update_line_item price_retail` use is the Syncro auto-gen-zero recovery (when an auto-generated line came in at $0 instead of the product's intended rate).
|
||||
|
||||
**Emergency / after-hours billing branches by whether customer has prepaid labor:**
|
||||
|
||||
@@ -704,7 +706,7 @@ When `/syncro bill <number>` is called:
|
||||
4. Decide product + quantity using the emergency-branching table above:
|
||||
- Non-prepaid + emergency → product `26184`, qty = actual hours
|
||||
- Prepaid + emergency → product `26118`, qty = actual hours × 1.5
|
||||
- Warranty / no-charge → use the closest labor product (e.g. `1190473` remote, `26118` onsite) with `billable: false` on the timer; qty = actual hours
|
||||
- Warranty / no-charge → product **`1049360` (Labor- Warranty work)**, `billable: true`, qty = actual hours. Do NOT pick a regular labor product with `billable: false` — Syncro silently overrides the flag and generates a billable line. (Verified 2026-05-06 on #32225 — see `feedback_syncro_warranty_product.md`.)
|
||||
- Otherwise → per `--labor` mapping below, qty = actual hours
|
||||
5. Look up `price_retail` from the local rate table (do NOT fetch live — rates are baked in)
|
||||
6. Compute `start_at` and `end_at` for the timer (use ISO8601; the `end_at − start_at` interval should equal `quantity` hours so Syncro's reporting math matches what you bill)
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
- [Syncro — use a billable labor type, never "Prepaid project labor"](feedback_syncro_labor_type.md) — Time entries must use in-shop / onsite / remote / web labor. "Prepaid project labor" is exempt and won't decrement prepay blocks. Default is Remote labor for typical support tickets. Winter caught this 2026-05-04.
|
||||
- [Syncro — log time entries first, never bare add_line_item](feedback_syncro_timer_first.md) — All Syncro work-time billing MUST go through `timer_entry → charge_timer_entry`. Bare `add_line_item` leaves Syncro time tracking at 00:00:00 and breaks reporting. Mike caught this on 2026-04-30 across 31 tickets; I repeated the bug on 2026-05-01 across 3 more.
|
||||
- [Syncro — timer_entry response is FLAT](feedback_syncro_timer_response_shape.md) — POST /tickets/{id}/timer_entry returns `{"id": N, ...}` directly, NOT `{"timer": {...}}`. Parse as `.id`. The skill doc's `.timer.id // .timer_entry.id` fallback always resolves to null and causes duplicate-timer retries. Hit on #32253 2026-05-05.
|
||||
- [Syncro — warranty has its own product, never patch dollar amounts](feedback_syncro_warranty_product.md) — Warranty/no-charge work uses product `1049360` (Labor- Warranty work, $0). Do NOT use Remote/Onsite + `billable: false` — Syncro silently overrides the flag. Do NOT patch `price_retail` to convert one labor product into another; pick the correct product and re-run. Hit on #32225 2026-05-06.
|
||||
- [SQL instance role — verify by connections, not name](feedback_sql_instance_role_by_connection.md) — Standard installed under default `SQLEXPRESS` instance name is real. Prove role with `sys.dm_exec_sessions` + `Get-NetTCPConnection -OwningProcess` before recommending stop/uninstall. IMC1 2026-05-05/06 near-miss.
|
||||
|
||||
## Machine
|
||||
|
||||
22
.claude/memory/feedback_syncro_warranty_product.md
Normal file
22
.claude/memory/feedback_syncro_warranty_product.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Syncro — warranty work uses the "Labor- Warranty work" product, never patch a billable product to $0
|
||||
description: For warranty/no-charge labor on Syncro tickets, use product_id 1049360 (Labor- Warranty work, $0/hr). Do NOT use a regular labor product with billable=false or a patched price_retail=0. Prices are determined by the product selected; never override the dollar amount to make one product behave like another.
|
||||
type: feedback
|
||||
---
|
||||
|
||||
**Rule (two parts):**
|
||||
|
||||
1. **Warranty / no-charge labor uses product `1049360` "Labor- Warranty work" ($0/hr, non-taxable).** Don't pick a regular Remote/Onsite/etc. labor product and try to neutralize it.
|
||||
|
||||
2. **Prices are set by selecting the correct product. Never change `price_retail` on a line item to make a different labor product behave like a warranty (or any other) product.** If you find yourself reaching for `update_line_item` to drop a price, that's the signal to back up and pick a different `product_id` instead.
|
||||
|
||||
**Why:** On 2026-05-06 (ticket #32225 Sombra Residential), I chose product `1190473` (Labor - Remote Business, $150/hr) for a follow-up warranty cleanup, set `billable: false` on the timer, and assumed the timer flag would zero the line. Syncro silently overrode `billable: false` and the resulting line came in at $75. I patched `price_retail` to $0 to "fix" it. Howard caught it: warranty work has a dedicated product in the dropdown, and patching dollar amounts is never how this is solved. The earlier guidance in `.claude/commands/syncro.md` (the "Warranty / no-charge → use closest labor product with billable=false" rule) was wrong; warranty has its own product just like Onsite, Remote, Emergency, etc., and that product is what should be used.
|
||||
|
||||
**How to apply:**
|
||||
|
||||
- **For any warranty / no-charge work:** `product_id = 1049360`, qty = actual hours, no need to patch the line — it generates at $0 because the product's `price_retail` is $0.
|
||||
- **Set `billable` based on the product, not the situation.** For the warranty product, leave `billable: true` — Syncro decides line economics from `price_retail` × `quantity`, and warranty product is $0 by design. (Anecdotally, Syncro's `timer_entry` endpoint silently overrode `billable: false` to `true` on 2026-05-06, so don't rely on it as a price gate anyway.)
|
||||
- **Never reach for `update_line_item` to drop a price as a workaround.** If the dollar amount on a line is wrong, the wrong product was selected — undo, pick the correct product, redo. The only legitimate use of `update_line_item price_retail` is the Syncro auto-gen-zero recovery case (when the auto-line came in at $0 instead of the product's actual rate), and even that is a Syncro bug we're patching around, not a price-management tool.
|
||||
- **For the dropdown of available labor products,** see the rate table in `.claude/commands/syncro.md`. If the situation doesn't match any of those, ask before improvising.
|
||||
|
||||
**Where this lands in skill code:** `.claude/commands/syncro.md` — added `1049360` to the labor product table, fixed the warranty branch in the billing workflow, and added an explicit "never patch price_retail to convert products" rule.
|
||||
@@ -91,3 +91,17 @@ Two FYIs from today:
|
||||
|
||||
- Remediation tool: Security Investigator app (`bfbc12a4-...`), Graph + EXO read scopes only. Token cached at `/tmp/remediation-tool/207fa277-e9d8-4eb7-ada1-1064d2221498/`.
|
||||
- No write actions taken on any tenant.
|
||||
|
||||
## 4. Cascades 4-UPS install billing -- ticket #32101 (later same day)
|
||||
|
||||
Closed out the long-running "Estimate - UPS/battery back ups" ticket #32101. Hardware (4x CyberPower 500v/300w UPS @ $399.99 + 1x APC UPS 1500 @ $889.99) had already been invoiced on 2026-04-03 (invoice #67341). Howard had performed the four mechanical-room installs (1st through 4th floor, each protecting that floor's UniFi switch; 1st floor also protects the phone switches); installed the larger Memory Care unit several days earlier separately.
|
||||
|
||||
Billed onsite labor only -- 4 installs x 0.5 hr = 2.0 hrs at product `26118` Labor - Onsite Business ($175/hr) -- against Cascades' prepay block. No emergency multiplier (regular onsite work).
|
||||
|
||||
- Comment posted (customer-visible)
|
||||
- Timer 39053175, charged -> line item 42328604 (1.0 line, 2.0 qty, $350 total)
|
||||
- Invoice #67569 created at $0 (fully covered by prepay)
|
||||
- Cascades prepay: 48.5 -> **46.5 hrs** (2.0 debited)
|
||||
- Ticket status: Waiting for Parts -> Invoiced
|
||||
|
||||
Memory Care install was excluded from this billing per Howard's direction (confirmed: 4 installs, not 5).
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Horseshoe Management -- APC Smart-UPS bypass relay fault -- 2026-05-06
|
||||
|
||||
## User
|
||||
- **User:** Howard Enos (howard)
|
||||
- **Machine:** Howard-Home
|
||||
- **Role:** tech
|
||||
|
||||
## Summary
|
||||
|
||||
Onsite emergency response for Horseshoe Management (Bill Young). APC Smart-UPS 1350 was throwing a "P.17" / Event 17 error -- this is the APC code for **Bypass Relay Weld fault**, where the internal transfer relay has stuck and the unit can no longer switch between line power and battery power.
|
||||
|
||||
Cleared the error via a full power-cycle: disconnected all loads, unplugged the UPS from the wall, removed the batteries, held the power button for 10 seconds to discharge residual capacitance, reinstalled the batteries, plugged back in, reconnected loads, powered everything up. Error code cleared and the UPS is now operating normally.
|
||||
|
||||
**Underlying concern:** This site has now gone through several batteries and two complete UPS units, all reporting battery-related errors. That pattern doesn't fit normal battery wear -- it points to a likely **electrical issue at the wall outlet or branch circuit** feeding this equipment (voltage irregularities, poor grounding, or a shared circuit with a high-draw load). Recommended (in the customer-visible resolution comment on the ticket) that they have a licensed electrician verify the wiring before purchasing more batteries / replacement units.
|
||||
|
||||
## Ticket + billing
|
||||
|
||||
- **Ticket:** Syncro #32256 -- "Emergency onsite - Server making strange noise" (the ticket subject was set when the call came in; actual issue was the UPS, not the server)
|
||||
- **Customer:** Horseshoe Management (Bill Young, Syncro 625269), 2325 E Grant Rd, Tucson
|
||||
- **Time:** 1.0 hr emergency onsite
|
||||
- **Customer has prepay block:** 33.25 hrs at start of session
|
||||
|
||||
Per the Syncro emergency-billing branch for prepay customers: bill Onsite Business (`26118`, $175/hr) at `qty = actual_hours x 1.5`, NOT the Emergency product `26184`. Stacking would double-count the time-and-a-half. So:
|
||||
|
||||
- Product: `26118` Labor - Onsite Business
|
||||
- Qty: 1.5 hrs (1.0 actual x 1.5 emergency multiplier)
|
||||
- Rate: $175/hr
|
||||
- Line total: $262.50 (debits 1.5 hrs from prepay block; customer owes $0)
|
||||
- Invoice: #67568, total $0.00 (fully covered by prepay)
|
||||
- Prepay balance after: 33.25 -> **31.75 hrs**
|
||||
- Ticket status: New -> Invoiced
|
||||
|
||||
## Findings to flag
|
||||
|
||||
1. **Repeat battery / UPS failures point to electrical issue.** Recommended electrician evaluation in the customer-visible resolution comment on ticket #32256. Worth following up with Bill in a few days to confirm whether they've engaged an electrician.
|
||||
|
||||
2. **Stale plaintext credentials in customer notes.** While billing this ticket, noticed the Syncro customer record's free-text notes field contains plaintext passwords for Donna, Bill, Randy, Frank, Sam, "Bill Server", and -- most concerning -- the M365 admin password (`Bill@horseshoemgt.com / Passw0rd!`). These should be migrated to the SOPS vault under `clients/horseshoe-management/` and stripped from Syncro. Not urgent for today's ticket but a real exposure.
|
||||
|
||||
## Files / state changes
|
||||
|
||||
- Syncro ticket #32256 closed out (comment, timer, line item, invoice, status -> Invoiced).
|
||||
- No file changes in this repo.
|
||||
- No on-site config changes beyond the UPS power-cycle.
|
||||
|
||||
## Tools used
|
||||
|
||||
- Onsite physical work: UPS power-cycle.
|
||||
- Syncro REST API: comment + timer_entry + charge_timer_entry + invoice (1.5 hr emergency-on-prepay billing pattern).
|
||||
@@ -0,0 +1,84 @@
|
||||
# Sombra Residential -- Bryan sombrahomes ghost account cleanup -- 2026-05-06
|
||||
|
||||
## User
|
||||
- **User:** Howard Enos (howard)
|
||||
- **Machine:** Howard-Home
|
||||
- **Role:** tech
|
||||
|
||||
## Summary
|
||||
|
||||
Amy at Sombra Residential called reporting that Word would not close on Bryan's PC (DESKTOP-UQRN4K3, one of the two new computers we set up the week prior). The error stated "Word could not close because it had an open dialog box" but no dialog was visible. Howard force-closed Word via Task Manager, reopened it, and saw a credential prompt asking for `bryan@sombrahomes.com` -- the company's old email domain from before the rebrand to `sombraresidential.com`. Same prompt appeared on opening Excel. New Outlook app worked fine.
|
||||
|
||||
Investigation traced the prompts to stale Microsoft 365 identity references that Transwiz had carried over from Bryan's old machine during the new-PC setup, all bound to the pre-rebrand `bryan@sombrahomes.com` account. Removed the stale data in stages, with full backups + auto-generated revert scripts at each step. After the final cleanup pass (classic MAPI Outlook profiles, both 15.0 and 16.0 trees), the prompts stopped. Verified by Howard with all Office apps + reboot + retest.
|
||||
|
||||
Total time on the issue: ~30 min remote diagnostic + cleanup. Billed against ticket #32225 (the original new-PC setup ticket) as **warranty / no-charge** -- the issue is a direct side effect of the data transfer we performed during that ticket. New invoice #67572 generated at $0 against the warranty product.
|
||||
|
||||
## Customer + machine context
|
||||
|
||||
- **Customer:** Sombra Residential LLC (Syncro customer 32971820)
|
||||
- **Caller:** Amy
|
||||
- **Affected user:** Bryan Menie -- accounts now `bryan@sombraresidential.com`, formerly `bryan@sombrahomes.com`
|
||||
- **Machine:** DESKTOP-UQRN4K3
|
||||
- **Bryan's SID:** `S-1-5-21-2758790109-566389284-3601084329-1002`
|
||||
- **GuruRMM agent ID:** `6dc0fb03-d6c4-4e3e-a58c-d9d015ff588a` (site `787d497a-eb1d-4468-a8ac-51d3c23954cb` "main office")
|
||||
- **Office product:** OneNote Free + O365 Business Retail, Click-to-Run, version 16.0.19929.20106
|
||||
|
||||
## Diagnostic findings
|
||||
|
||||
The ghost prompts came from data Transwiz had carried over wholesale from Bryan's old machine. Key root cause: company rebranded `sombrahomes.com` -> `sombraresidential.com` at some point post-2022, but Bryan's classic Office identity store still had the old `bryan@sombrahomes.com` LiveId entries persisted (`ErrorState=6` -- stuck token, can't refresh). Office apps walk that store on startup and try to refresh the dead tokens, which is what surfaced as a credential prompt.
|
||||
|
||||
Notable diagnostic data points (from probe runs via GuruRMM):
|
||||
|
||||
| Probe pass | Key finding |
|
||||
|---|---|
|
||||
| v1 (HKCU as SYSTEM) | Empty -- agent runs as `nt authority\system`, so HKCU was the SYSTEM hive, not Bryan's. Confirmed HKLM was clean (413 MB dump, 0 matches). |
|
||||
| v3 (HKU\<bryan-sid>) | Found stale `8a2ca986c32435e4_LiveId` in `Office\15.0\Common\Identity\` with `EmailAddress=bryan@sombrahomes.com`. Plus AutoDiscover XMLs and PB4S config files. |
|
||||
| v4b (HKU full grep) | Word/Excel kept prompting after first cleanup; full hive grep found additional refs in `Office\15.0\Common\ServicesManagerCache\Identities\8a2ca986c32435e4_LiveId\` (the splash-screen "connected accounts" cache) and in classic MAPI Outlook profiles `Outlook` + `Outlook20221013` under both 15.0 and 16.0 trees, all bound to the old account. |
|
||||
|
||||
The new Outlook app uses WAM tokens (separate from classic config) and was correctly authenticated with `bryan@sombraresidential.com` (19 valid `.tbacct` files). That's why only Word and Excel showed the ghost prompt and the new Outlook app did not.
|
||||
|
||||
## Cleanup performed
|
||||
|
||||
Three cleanup passes, each with snapshot-first backup + auto-generated `revert.ps1` + manifest.json under `C:\ProgramData\ACG\sombrahomes-cleanup-<timestamp>\`. Office processes confirmed closed before each pass (script refused to run otherwise).
|
||||
|
||||
| Pass | Backup folder | Targets removed |
|
||||
|---|---|---|
|
||||
| v2 | `sombrahomes-cleanup-20260506-135723` | 3 reg keys (`Office\15.0\Common\Identity\Identities\8a2ca986c32435e4_LiveId`, `Profiles\8a2ca986c32435e4_LiveId`, `DocToIdMapping\8a2ca986c32435e4_LiveId`) + 2 files (`AutoD.bryan@sombrahomes.com.xml`, `PB4S-Configuration-bryan@sombrahomes.com.xml`) |
|
||||
| v3 | `sombrahomes-cleanup-20260506-142613` | `ServicesManagerCache\Identities\8a2ca986c32435e4_LiveId` + `MSOIdentityCRL\UserExtendedProperties\microsoftonline.com::customerservice@sombrahomes.com` + OneAuth `Bryan@SombraHomes.com_identity_provider` blob |
|
||||
| v4 | `sombrahomes-cleanup-20260506-143518` | 4 classic MAPI Outlook profiles (`Outlook` + `Outlook20221013` in both 15.0 and 16.0 trees, total ~245 KB of registry data) |
|
||||
|
||||
After v3 the prompt persisted in Word/Excel only; v4 cleared it. Howard verified after v4: opened Word, Excel, all other Office apps, rebooted, retested -- no prompts. New Outlook app continues working with `bryan@sombraresidential.com`.
|
||||
|
||||
Each backup folder contains a self-contained `revert.ps1` that re-imports all registry exports and copies files back. Reverting any single pass is one command.
|
||||
|
||||
## Billing
|
||||
|
||||
| Ticket | Comment | Time | Product | Invoice | Total |
|
||||
|---|---|---|---|---|---|
|
||||
| #32225 | Customer-visible follow-up describing issue + cleanup | 0.5 hr | `1049360` Labor- Warranty work | #67572 | $0.00 (warranty) |
|
||||
|
||||
Initial billing attempt (now corrected) had used product `1190473` Labor - Remote Business with `billable: false` and patched the price to $0. Howard caught it -- warranty has its own dedicated product (`1049360` Labor- Warranty work) and that's what should be selected. Patching `price_retail` to convert one labor product into another is wrong. Fixed: removed wrong line + timer, regenerated against the correct warranty product. Documented as `feedback_syncro_warranty_product.md`; updated `.claude/commands/syncro.md` rate table + workflow.
|
||||
|
||||
## Files / state changes
|
||||
|
||||
- `C:\ProgramData\ACG\sombrahomes-cleanup-20260506-*` -- 3 backup folders on Bryan's PC. All three include manifest.json + revert.ps1.
|
||||
- Local cleanup scripts staged at `C:\claudetools\.claude\tmp\sombra-cleanup-v2.ps1` / `v3.ps1` / `v4.ps1` (and probes v1-v4b). Not committed -- one-off diagnostic.
|
||||
- New feedback memory: `.claude/memory/feedback_syncro_warranty_product.md`
|
||||
- Updated: `.claude/commands/syncro.md` (rate table + warranty workflow + never-patch-price rule)
|
||||
- Updated: `.claude/memory/MEMORY.md` (index entry)
|
||||
|
||||
## Note for Mike + Winter
|
||||
|
||||
Couple of observations from this session that may be relevant elsewhere:
|
||||
|
||||
1. **Transwiz drag-along:** Whenever we use Transwiz on a domain-rebranded shop, expect this exact ghost-account symptom on the destination machine. Quickest indicator: classic Office MAPI profile name, `HKU\<sid>\Software\Microsoft\Office\16.0\Outlook\DefaultProfile`, and the ServicesManagerCache LiveId entries. Worth adding a "post-Transwiz Office identity sweep" step to our new-PC checklist.
|
||||
|
||||
2. **GuruRMM SYSTEM context:** The agent runs as `nt authority\system`. Probes that read `HKCU` or `$env:USERPROFILE` will hit SYSTEM's hive/profile, not the actual user's. For per-user investigations, resolve the target user's SID via `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList` and read from `HKU:\<sid>\` and `C:\Users\<user>\` directly.
|
||||
|
||||
3. **Syncro `billable: false` on `timer_entry` is silently ignored.** Setting `billable: false` does NOT prevent Syncro from generating a $-charged line item. The skill memory has been updated to reflect this -- always pick the correct product (warranty for warranty, etc.) rather than trying to neutralize a billable product with a flag or a patched price.
|
||||
|
||||
## Tools used
|
||||
|
||||
- GuruRMM: agent command POST + result polling. Read-only probes + targeted cleanup commands. SYSTEM context.
|
||||
- Syncro REST API: ticket comment, timer_entry, charge_timer_entry, invoice CRUD.
|
||||
- No write actions on any M365 tenant.
|
||||
Reference in New Issue
Block a user