sync: auto-sync from HOWARD-HOME at 2026-05-05 16:44:25

Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-05-05 16:44:25
This commit is contained in:
2026-05-05 16:44:26 -07:00
parent fd8361d0a6
commit bc39d75304
4 changed files with 126 additions and 0 deletions

View File

@@ -34,6 +34,7 @@
- [Syncro — never set contact on Cascades tickets](feedback_syncro_cascades_contact.md) — Cascades-specific instance of the blank-contact rule above. Kept for the Meredith-defaulting incident detail.
- [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.
## Machine
- [ACG-5070 Workstation Setup](reference_workstation_setup.md) - Windows 11 Pro clean install 2026-03-30, replaced CachyOS. All tools installed.

View File

@@ -0,0 +1,48 @@
---
name: Syncro — timer_entry response is FLAT, not wrapped
description: POST /tickets/{id}/timer_entry returns a flat object {"id": N, "ticket_id": ..., "product_id": ..., ...}, NOT wrapped in {"timer": {...}} or {"timer_entry": {...}}. Parse as `.id`, never `.timer.id` — using the wrapped pattern silently returns null and creates duplicate timers when the script "retries".
type: feedback
---
**Rule:** When parsing the response from `POST /tickets/{id}/timer_entry`, use `.id` directly — the response is a FLAT object. Do NOT use `.timer.id // .timer_entry.id`.
**Verified response shape (2026-05-05, ticket #32253):**
```json
{
"id": 39031258,
"ticket_id": 109895882,
"user_id": 1750,
"start_time": "2026-05-05T09:00:00.000-07:00",
"end_time": "2026-05-05T09:30:00.000-07:00",
"recorded": false,
"billable": true,
"notes": "...",
"product_id": 26118,
"comment_id": null,
"ticket_line_item_id": null,
"active_duration": 1800,
"billable_time": 1800
...
}
```
**Why:** The skill doc at `.claude/commands/syncro.md` shows
```bash
TIMER_ID=$(echo "$TIMER_RESP" | jq -r '.timer.id // .timer_entry.id')
```
That fallback resolves to `null` because neither key exists on the flat response. A `null` TIMER_ID then breaks `charge_timer_entry` ("Not found"). If the script retries the timer_entry POST after the perceived failure, it creates a duplicate — Syncro has no idempotency. Hit this on ticket #32253 (Cascades) on 2026-05-05; created two duplicate 0.5hr timers and had to delete one via `delete_timer_entry` before charging.
**How to apply:**
- **Parsing:** Always `jq -r '.id'` on the timer_entry response.
- **After ANY ambiguous timer_entry response** (null `.id`, jq error, network blip): GET the ticket and inspect `.ticket.ticket_timers[]` BEFORE retrying. Filter for `recorded: false` entries with the start/end times you just sent.
- **Cleanup if duplicates exist:** `POST /tickets/{id}/delete_timer_entry` with `{"timer_entry_id": N}` for the older duplicate(s). Returns `{"success": true}`.
- **Verifying the timer is on the ticket:** `GET /tickets/{id}``.ticket.ticket_timers` is the authoritative list. The standalone `/ticket_timers?ticket_id=N` query parameter does NOT filter by ticket — returns the entire global timer history.
**Charge timer response is also flat:**
```json
{"id": 39031258, "recorded": true, "ticket_line_item_id": 42313052, ...}
```
Parse as `.ticket_line_item_id` to get the auto-generated line. Do not look for a wrapper.
**Where this lands in skill code:** `.claude/commands/syncro.md` example block needs `.id` not `.timer.id // .timer_entry.id`. Until the skill is patched, override the example pattern when running.

View File

@@ -168,3 +168,57 @@ Datto AEMAgent 290 s Datto RMM
### Note for Mike
**Fleet-wide MSP cleanup decision needed.** Every Cascades workstation we onboarded into GuruRMM since 2026-04-18 still has the previous MSP's Datto RMM, Datto AV, Datto EDR (Infocyte), Syncro RMM, and Splashtop running concurrently with our agent. CHEF-PC is the visible symptom — five RMM/EDR stacks plus three remote-access tools running simultaneously, with `SyncroLive.Agent.Runner` alone consuming 35+ minutes of CPU time and `WmiPrvSE` saturated. Before I scrip a fleet uninstall, need confirmation: (1) is GuruRMM the canonical RMM going forward? (2) Datto AV out, Defender in? (3) Are we still under contract on any of the Datto/Syncro tooling we'd be ripping out? Will scope this onsite workstation by workstation, but the fix is fleet-wide, not just CHEF-PC.
---
## Update: 16:42 PT — Syncro tickets created (#32253 invoiced, #32254 opened)
### What landed
Two Syncro tickets created via API on 2026-05-05 for Cascades of Tucson (customer 20149445). Ticket #32253 covers earlier today's onsite RAM install on MDIRECTOR-PC and is fully billed + invoiced. Ticket #32254 documents the Chef-PC slow-performance issue and stages the upcoming Windows reinstall — no billing applied yet. Both created with `contact_id: null` per the Cascades blank-contact rule. Initial-issue comments posted with `do_not_email: true`.
### Ticket #32253 — Shelby Trozzi 4GB RAM upgrade (Invoiced)
- **Subject:** Shelby Trozzi - 4GB RAM upgrade for slowness
- **Issue type:** Hardware. Priority: 2 Normal. Status: Invoiced.
- **Initial issue comment summary:** Per audit, Shelby's machine ran slow due to programs/photos left open for extended periods. Installed one 4GB DDR4 RAM stick to alleviate slowness. Advised user to reboot regularly and close unused programs. Recommended replacing the machine — current hardware is at end of useful life.
- **Billing:**
- Onsite labor (product 26118): 0.5 hr @ $175/hr — applied to Cascades prepay block (auto-generated line via `charge_timer_entry`)
- Hardware (product 32252): 1 × 4GB DDR4 RAM stick @ $25.00, taxable
- **Invoice:** #67564 — total **$27.18** ($25.00 hardware + $2.18 tax). Labor line shows "Applied 0.5 Prepay Hours" — block decremented as expected.
> Note vs. the earlier plan in this log: the original recommendation was a matched 2× 4GB DDR4-2400 SODIMM pair for dual-channel. Mike's instruction at billing time was a single 4GB stick (asymmetric with whatever was already there). The dual-channel rebalance remains a follow-up if performance is still poor after RAM + reboot discipline.
### Ticket #32254 — Chef JD / Chef-PC Windows reinstall (open)
- **Subject:** Chef JD - Chef-PC running slow / Windows reinstall
- **Issue type:** Software. Priority: 2 Normal. Status: New.
- **Asset linked:** CHEF-PC (Syncro asset 9794584).
- **Initial issue comment summary:** Chef-PC running slow. Built-in Windows repairs are getting stuck on the backend. Plan: full Windows reinstall.
- **No billing applied** — ticket scopes the upcoming reinstall.
- **Scope note:** This ticket frames the reinstall as the resolution, but the parent log's "Note for Mike" still stands — the underlying cause on this fleet is the previous-MSP agent stack (Datto RMM/AV/EDR + Syncro + Splashtop running concurrently with GuruRMM). A clean Windows install on CHEF-PC will fix the symptom on this one machine without addressing the fleet-wide stack-removal decision Mike still owes.
### Skill bug encountered (Syncro `timer_entry` response shape)
The Syncro skill (`.claude/commands/syncro.md`) example for `POST /tickets/{id}/timer_entry` parses the response as `.timer.id // .timer_entry.id`. The actual API response is a **flat** object — `{"id": N, "ticket_id": ..., ...}` — and that fallback always resolves to `null`.
What happened on Ticket #32253:
1. First `timer_entry` POST succeeded and created timer 39031253. My jq returned null because of the `.timer.id` pattern.
2. Subsequent `charge_timer_entry` with `null` ID returned `{"message":"Not found"}`.
3. Reading the response shape, I retried the POST. Syncro has no idempotency, so it created a SECOND timer (39031258).
4. Verified two unrecorded timers on the ticket via `GET /tickets/{id}``.ticket.ticket_timers`.
5. Deleted the older duplicate via `POST /tickets/{id}/delete_timer_entry` (returned `{"success": true}`).
6. Charged the survivor — generated one labor line item at the correct $175 rate.
**No double-billing landed.** Only one labor line item exists on the ticket and the invoice. Net Cascades prepay debit is the intended 0.5 hr.
**Documentation:**
- Saved feedback memory: `.claude/memory/feedback_syncro_timer_response_shape.md`
- Indexed under Feedback in `.claude/memory/MEMORY.md`
- The skill file `.claude/commands/syncro.md` example block still has the bad pattern — flagged for fix in the Pending section below.
### Cascades prepay block (post-billing)
- Before this session: 50.0 hours
- After Tickets #32253 (0.5 hr) + #32255 (1.0 hr): **48.5 hours**
- Verified via `GET /customers/20149445``.customer.prepay_hours == "48.5"`
### Pending (added)
- [ ] Patch `.claude/commands/syncro.md` `timer_entry` example: change `jq -r '.timer.id // .timer_entry.id'` to `jq -r '.id'`. Same fix applies to the `charge_timer_entry` response (also flat — `.ticket_line_item_id` directly on the root).
- [ ] Decide on the dual-channel rebalance for MDIRECTOR-PC if a 0.5-hr session of "reboot + close apps + reseat single 4GB stick" doesn't resolve user complaints within ~2 weeks.
- [ ] Schedule Chef-PC Windows reinstall (ticket #32254). Reinstall on its own will not remove the previous-MSP agents on the rest of the fleet — track that as the parent fleet-cleanup decision (still on Mike).

View File

@@ -100,3 +100,26 @@ Two separate one-time passwords delivered to Mike in chat:
- AD domain account password
Neither committed to repo. Both forced to change at first sign-in.
---
## Update: 16:42 PT — Syncro ticket #32255 invoiced
### Ticket #32255 — Zachary Nelson onboarding (Invoiced)
- **Customer:** Cascades of Tucson (Syncro 20149445)
- **Subject:** Zachary Nelson - New user / email / desktop setup
- **Issue type:** New User / Workstation Deployment. Priority: 2 Normal. Status: Invoiced.
- **Contact:** null (Cascades blank-contact rule).
- **Initial issue comment summary:** Set up new M365 email and user account for Zachary Nelson; configured account on his desktop; added Zachary to share folders on cascadesDS — ALdocs, Business Office, Business AL.
- **Billing:** Onsite labor (product 26118): 1.0 hr @ $175/hr — applied to Cascades prepay block.
- **Invoice:** #67565 — total **$0.00** (1.0 hr applied to prepay; no taxable items). Labor line shows "Applied 1.0 Prepay Hours".
### Coverage note
This ticket bills only the desktop / share-folder portion of today's Zachary work. The M365 cloud account creation, on-prem AD account creation on CS-SERVER, license assignment (SPB), and password handoff to Mike are documented earlier in this log and folded into the same 1.0-hr onsite block. If this scope ends up needing a second pass (manager assignment, group memberships, or the broader O365_BUSINESS_PREMIUM → SPB migration sweep tracked in "Not done"), open a follow-up ticket rather than appending to #32255.
### Cascades prepay block (post-billing)
- Block at 50.0 hours before today's billing session.
- Decremented 1.5 hours total today (0.5 on #32253 + 1.0 on #32255) → **48.5 hours remaining**.
### Cross-reference
Skill bug hit on Ticket #32253 (Syncro `timer_entry` response shape) is documented in the parallel chef-pc-slow log (`2026-05-05-howard-chef-pc-slow-and-mdirector-ram.md`, "Update: 16:42 PT" section). Ticket #32255 was created cleanly after the workaround was understood.