sync: auto-sync from GURU-5070 at 2026-05-28 10:18:36

Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-05-28 10:18:36
This commit is contained in:
2026-05-28 10:18:39 -07:00
parent 79ce10917f
commit 96ed34de4b
3 changed files with 95 additions and 3 deletions

View File

@@ -275,7 +275,7 @@ Whether the draft came from Ollama or Claude wrote it directly:
2. `quantity` = minutes ÷ 60 — verify the arithmetic (e.g. 45 min = 0.75, not 0.77)
3. Computed total = `price_retail × quantity` — matches what was communicated to user
4. If labor_type is `emergency` and `prepay_hours > 0`: product must be `26184` (emergency item), qty must be actual_hours × 1.5 (premium in the quantity)
5. `comment_body` uses `<br>`, not `<ul>/<li>`
5. `comment_body` uses `<br>` — scan the string for `\n` (literal backslash-n) or bare newlines and replace with `<br>`. No `<ul>`/`<li>`.
6. No internal notes or credential data in a customer-visible comment body
If a check fails: correct it and note the fix in the preview so the user can see what changed.
@@ -575,6 +575,13 @@ Every endpoint's response shape, verified against the live API. Parse exactly as
#### Comments
**Dead-end paths (all return 404 — do not probe):**
- `POST /ticket_comments` — top-level; GET works for listing but POST does not exist
- `POST /tickets/{id}/comments` (plural) — does not exist
- `POST /ticket_comments` with `ticket_id` in body — 404 regardless of payload
**Correct path:** `POST /tickets/{id}/comment` (singular, nested under ticket). Verified 2026-05-28.
```bash
# POST comment — response: {"comment": {...}}
COMMENT_RESP=$(curl -s -X POST "${BASE}/tickets/${ID}/comment?api_key=${API_KEY}" \
@@ -594,6 +601,7 @@ COMMENT_ID=$(echo "$COMMENT_RESP" | jq -r '.comment.id')
- `hidden: true` = internal only (customer can't see)
- `do_not_email: true` = suppress email to customer
- Body is HTML; use `<br>` for line breaks. `<ul>`/`<li>` do not render in Syncro.
- **`\n` does NOT render as a line break in Syncro** — it shows as a space or is ignored. Every line break in the body MUST be a literal `<br>` tag. This applies whether the body was drafted by Ollama, Claude, or built from a shell variable. When using `jq --arg body "$VAR"`, a variable containing `\n` characters passes them as literal backslash-n, not HTML breaks. Write body strings with `<br>` inline, or use the heredoc form below to write proper HTML. Incident: ticket #32339 Birth Biologic 2026-05-28 — tech notes posted with `\n` separators, rendered as one unreadable block.
- Do NOT wrap the payload in `{"comment": {...}}` — returns 422.
- **If `COMMENT_ID` is null:** GET `/tickets/{id}` and check `.ticket.comments[]` by subject before doing anything else. Comments cannot be deleted via API — duplicates require manual GUI removal.
@@ -608,7 +616,15 @@ curl -s "${BASE}/customers/${CUST_ID}?api_key=${API_KEY}" | jq '{id: .customer.i
#### Line Items
All billing uses `add_line_item` directly. Do not use `timer_entry → charge_timer_entry`.
All billing uses `add_line_item` directly. Do not use `timer_entry → charge_timer_entry`. Do not use timers.
**Dead-end paths (all return 404 — do not probe):**
- `POST /ticket_line_items` — does not exist
- `POST /tickets/{id}/line_item` (singular) — does not exist
- `POST /tickets/{id}/line_items` (plural) — does not exist
- `PUT /tickets/{id}` with `line_items_attributes` in body — silently no-ops (returns ticket with empty line_items)
**Correct path:** `POST /tickets/{id}/add_line_item` using the **internal ticket ID** (e.g. 111387456, from `.ticket.id`), not the ticket number. Verified 2026-05-25 and 2026-05-28.
```bash
# Add line item — response is FLAT: {"id": N, "ticket_id": N, "product_id": N, "price_retail": N, ...}

Submodule .claude/worktrees/agent-ad3a8120cb99cdb4a deleted from b0695ab3a0