Files
claudetools/session-logs/2026-06/2026-06-30-howard-syncro-category-skill-fix.md
Howard Enos bc6dde5b89 sync: auto-sync from HOWARD-HOME at 2026-06-30 11:54:16
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-30 11:54:16
2026-06-30 11:54:48 -07:00

5.1 KiB

User

  • User: Howard Enos (howard)
  • Machine: Howard-Home
  • Role: tech

Session Summary

Howard flagged a Syncro billing defect on his invoice list (invoice 1650806091 view): "Windows Pro Upgrade" line items on Cascades of Tucson tickets #32466 and #32474 (invoices 67887 and 67890) went out with a blank CATEGORY column, while labor lines correctly showed "Labor". The directive was explicit — do NOT fix the ticket (Winter already corrected the records); fix the skill so I stop making this mistake, since categories are a fixed set in Syncro and must not be invented or left blank.

Investigated the root cause read-only via the Syncro REST API. Located the product "Windows Pro Upgrade" (id 23571919) and confirmed both category and product_category are null on the product itself — that null propagates to every line item billed from it, producing the blank CATEGORY column. Confirmed product_category is the operative field (the field that shows "Labor" on labor products like 1190473). Enumerated the controlled vocabulary by paging all ~960 products: real categories in the tenant are Labor, Default, Subscriptions, Product, Service/Services, Other, Contract, Discount, Exempt Labor, Prepay Hours, Deposit, Hardware (plus Software per Howard's set selections). The /product_categories API endpoint returned empty, so the live set must be derived by enumerating distinct product_category across GET /products.

Fixed the skill rules only (no ticket/product writes). Added a controlled-vocabulary rule and a pre-flight check to .claude/commands/syncro.md, created a feedback memory with an index line, and logged the correction to errorlog.md. The net behavioral change: before invoicing, the /syncro flow must GET /products/<id>, verify product_category is a real non-null value, halt on a blank one, and never substitute an invented category.

Key Decisions

  • Fixed the skill at two layers: the bolded rules block (next to the taxable rule) AND the add_line_item required-fields procedure, so the check sits in the workflow, not just the header.
  • Did not hardcode the category list as authoritative — instructed the skill to enumerate the live set from GET /products (it changes), with known-good values listed only as a reference and "ASK if none fits."
  • Targeted the line-item/invoicing path (where I act) rather than product creation — the skill does not create products, and the product-level fix is Winter's record correction.
  • Wrote a feedback-type memory (shapes future behavior fleet-wide) in addition to the errorlog correction (pattern-linting), per the complementary-logging rule.

Problems Encountered

  • /product_categories API endpoint returned empty — resolved by enumerating distinct product_category across all paged GET /products to recover the controlled vocabulary.
  • Product exposes several category-ish fields (category, product_category, category_id, category_path) — confirmed product_category/category_path are the populated ones (both "Labor" on a labor product) and product_category is the canonical field to check.

Configuration Changes

  • Modified: .claude/commands/syncro.md — added controlled-vocabulary + no-blank-category rule (after the taxable rule); added category pre-flight to the add_line_item required-fields list.
  • Created: .claude/memory/feedback_syncro_line_item_category.md — feedback memory for the rule.
  • Modified: .claude/memory/MEMORY.md — added index line for the new memory.
  • Modified: errorlog.md — logged the correction (--correction).

Credentials & Secrets

None created or discovered. Used the per-user Syncro API key already baked into .claude/commands/syncro.md (howard token) for read-only GETs.

Infrastructure & Servers

  • Syncro PSA: https://computerguru.syncromsp.com/api/v1 — query-param auth (?api_key=).

Commands & Outputs

  • GET /products?query=Windows%20Pro%20Upgrade → product id 23571919, product_category: null, price_retail: 99.0, taxable: true.
  • GET /products/1190473 (Labor - Remote Business) → product_category: "Labor" (confirms the field that renders the CATEGORY column).
  • Paged enumeration of all products → distinct product_category: Labor, Default, Subscriptions, Product, Service(s), Other, Contract, Discount, Exempt Labor, Prepay Hours, Deposit, Hardware (+ Software per Syncro admin set).
  • bash .claude/scripts/log-skill-error.sh "/syncro" "..." --correction[OK] logged skill error to errorlog.md.

Pending / Incomplete Tasks

  • None for the skill fix. (Ticket/product record correction is Winter's, already done — invoices 67887/67890, product 23571919.)
  • Optional future: the product 23571919 product_category should be set to "Software" at the product level so future bills inherit it — outside this session's scope (Winter handling records).

Reference Information

  • Tickets: Cascades of Tucson #32466, #32474. Invoices: 67887, 67890. Invoice list view: invoice 1650806091.
  • Product: "Windows Pro Upgrade" id 23571919.
  • Files: .claude/commands/syncro.md, .claude/memory/feedback_syncro_line_item_category.md, .claude/memory/MEMORY.md, errorlog.md.