toga-ai 1.0.1114 → 1.0.1116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,5 +15,6 @@
15
15
  | [Staff SSO Login (Sso class via saml.togahub.com)](features/staff-sso-login.md) | TOGa Desk staff "Sign in with SSO" via saml.togahub.com (TRUE-78064, `Sso` class, Tools pattern); open before touching SSO login, the `?saml=` return, the `[sam |
16
16
  | [Ticket "Assign To" Lists (who can be assigned a ticket)](features/ticket-assign-to-lists.md) | How the ticket "Assign To" pickers are built (new/edit/merge modals, ticket page) and the hardcoded client exclusion list (`ASSIGN_TO_EXCLUDED_CLIENTS`, IM Hous |
17
17
  | [Ticket Lifecycle (class.ticket.php)](features/ticket-lifecycle.md) | TOGa Desk ticket creation + reply handling via `Ticket` (class.ticket.php): the four creation/reply doors, `deriveCustomerId()`, and the `addReply()` status swi |
18
+ | [Old Ticket Data Requests (TOGaDeskSupport + TOGaDeskSupportArchive)](workflows/old-ticket-data-requests.md) | How to answer "get details for archived/old Desk tickets" requests from ops: query live `TOGaDeskSupport` AND `TOGaDeskSupportArchive`, dedupe archive replies, |
18
19
  | [Reverting a TOGa Desk _production Deploy (revert-forward)](workflows/production-revert-forward.md) | How to cleanly roll back one ticket's changes from the togadesk `_production` branch via `git revert -m 1` of its two-parent merge, verified with `git patch-id` |
19
20
  | [Standalone PHP Test Script Bootstrap (TOGa Desk)](workflows/standalone-test-scripts.md) | How to bootstrap the TOGa Desk 1.0 framework in a standalone CLI PHP script for read-only testing of desk classes (e.g. |
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Old Ticket Data Requests (TOGaDeskSupport + TOGaDeskSupportArchive)
3
+ framework: "1.0"
4
+ repo: togadesk
5
+ project: TOGa Desk
6
+ client: shared
7
+ type: workflow
8
+ status: active
9
+ updated: 2026-10-21
10
+ owners: ["bala"]
11
+ files: []
12
+ related:
13
+ - 1.0/apps/togadesk/architecture.md
14
+ - 1.0/apps/togadesk/features/ticket-lifecycle.md
15
+ - standalone/apps/claude/workflows/mcp-tool-usage.md
16
+ ---
17
+
18
+ How to answer "get details for archived/old Desk tickets" requests from ops: query live `TOGaDeskSupport` AND `TOGaDeskSupportArchive`, dedupe archive replies, deliver one Excel row per ticket; includes the HPE service-task data map.
19
+
20
+ ## Summary
21
+ Ops (e.g. Maggie Swietkowski) send a list of old Desk tickets and ask for dates, engineers, or notes. Precedents: TRUE-76720 (NYC DoE install dates), TRUE-3401 (OD depot tech notes), TRUE-82979 (HPE GCSN cases). No code change; data only, via `toga-db` environment `legacy`.
22
+
23
+ **Critical rules:** Always check BOTH `TOGaDeskSupport` and `TOGaDeskSupportArchive`. A ticket can keep its live `tickets` row (status Closed, `notes` intact) while ALL its replies and history exist only in the archive. Missing replies in live never means "no data".
24
+
25
+ ## Steps
26
+ 1. Resolve each requested ticket number to `TOGaDeskSupport.tickets.id`.
27
+ 2. Pull replies/history from live, then from `TOGaDeskSupportArchive` by the same id. The archive has the same tables (`tickets`, `tickets_replies`, `tickets_history`, `tickets_cfvalues`, `tickets_contacts`, `tickets_assets`, `tickets_agents`, `tickets_rules`, `ticket_files`) and keeps the original ids (`tickets_replies.ticketid` = live `tickets.id`).
28
+ 3. Received date = `tickets.timestamp`. Closure date = the `tickets_replies` row with `newStatus='Closed'`, or the `tickets_history` "Status changed … to Closed" row (no closed-date column, see [ticket lifecycle](../features/ticket-lifecycle.md#gotchas)).
29
+ 4. Follow merges: child tickets point at the master via `tickets.mergedWithTicketId`; the master often has no replies, so read the children.
30
+ 5. Custom fields are in `tickets_cfvalues` (by custom field id).
31
+ 6. Deliver an Excel (or CSV): one row per requested ticket, keep the requester's columns, add the asked-for columns, and a reason column when nothing is found.
32
+ 7. Claude cannot attach files to ClickUp (`start-gate` blocks `clickup_attach_task_file`). The developer attaches the file by hand.
33
+
34
+ ## HPE service tasks (TOGaDeskSupport clientid 9)
35
+ Department "HPE- Support Contact Center".
36
+ - HPE emails from `sfdc.hpesupport@hpe.com` open a ticket titled `HPE Service Task : <task no>-531, RESPONSE_TIME, 4HR|NBD has been assigned to Asi System Integration Inc [100451]`. Received date = that ticket's `timestamp`.
37
+ - Staff create a Master Ticket and a Customer Ticket; the HPE ticket and the customer ticket are merged into the master (step 4).
38
+ - HPE GCSN event / part order number (`XC########`) = custom field id 43 "HPE Order ID" in `tickets_cfvalues`.
39
+ - The lead Rapid Response Engineer replies "Assign to <engineer>". The engineer who did the onsite work = `tickets.adminid`.
40
+ - Closing summary arrives as an email reply "Please close this case in TOGA and HPE CSN. Below is the closing summary…" and is also in `tickets.notes` (HTML-entity encoded: `&lt;` `&gt;` `&quot;`; decode before export).
41
+ - Cases rejected / "sent back to HPE" (no technician in the area) never get field 43. Find them by serial number in `tickets_replies.message` (e.g. GCSN XC27745229 = tickets 9004848 / 9004883, no repair).
42
+
43
+ ## Gotchas
44
+ - **Archive replies can be duplicated.** Ticket 9004290 (`tickets.id` 161855) had 0 replies/history live but 6 replies + 9 history rows in the archive, each reply copied twice with different ids. De-duplicate by timestamp (+ message).
45
+ - Archive `tickets_history.userid` is NULL; archive `tickets_replies.peopleid` still joins to live `TOGaDeskSupport.people`.
46
+ - Resolved WJE tickets are moved to the archive after 120 days (TRUE-56700). Other clients' old tickets land there too; never assume a cutoff.
47
+ - `toga_query` rejects the `REPLACE()` string function; see [MCP tool usage](../../../../standalone/apps/claude/workflows/mcp-tool-usage.md#gotchas).
48
+
49
+ ## Change history
50
+ - 2026-10-21 — Created from TRUE-82979 (HPE GCSN case details): archive schema, data-request output format, HPE data map. (bala)
51
+
52
+ ## Related
53
+ - [TOGa Desk architecture](../architecture.md)
54
+ - [Ticket lifecycle](../features/ticket-lifecycle.md)
55
+ - [MCP tool usage](../../../../standalone/apps/claude/workflows/mcp-tool-usage.md)
@@ -110,7 +110,8 @@ The 1.0 error handler **terminates** on a PHP deprecation notice (`App_Error::ha
110
110
  - When porting or running 1.0 code on PHP 8.x, **audit for deprecated-in-8.x calls** in every reachable path before deploy.
111
111
  - Known offender: **`curl_close()`** — deprecated as of PHP 8.5, a no-op since PHP 8.0. Remove all `curl_close()` calls; the cURL handle closes automatically. (Design Demo Admin incident — see framework-rules-cases.md.)
112
112
  - In `library`, guard deprecated calls by version (`PHP_VERSION_ID`) and use 7.1-valid syntax (`?string $x = null`) — other 1.0 apps still run PHP 7.2. Fixed/open list: [PHP 8.5 compatibility](../apps/library/features/php-8-5-runtime-compatibility.md).
113
- - Never pass `null` to internal string functions (`trim`, `base64_decode`, `stripos` — deprecated 8.1). Cast `(string)` first; DB/JSON fields can be null.
113
+ - Main 8.x break classes in 1.0 apps: `null` into internal string functions (`trim`, `base64_decode`, `stripos` — deprecated 8.1) and reading keys of an empty `fetchRow` / `fetchOne` result (warning since 8.0). Cast `(string)` / default the array at the call site; DB/JSON fields can be null.
114
+ - When the root cause is a library helper (e.g. `App_Date`, `App_Database`), fix it in library, keeping it PHP 7.2 safe — see [PHP 8.5 compatibility](../apps/library/features/php-8-5-runtime-compatibility.md).
114
115
  - Do not suppress the deprecation with `@` (see coding-style rules) — remove/replace the deprecated call.
115
116
 
116
117
  ## Error handling in controllers
@@ -6,7 +6,7 @@ project: Worker
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-10-16
9
+ updated: 2026-10-22
10
10
  owners: ["jcardinal", "mhammontree", "bala", "rgirish"]
11
11
  files:
12
12
  - worker2/Worker/Monitor/Compass.php
@@ -37,6 +37,7 @@ related:
37
37
  - ../../../clients/compass-usa/features/oneuptime-netsuite-duplicate-sales-orders-monitor.md
38
38
  - ../../../../clients/wje/features/oneuptime-monitors.md
39
39
  - ../../../clients/compass-canada/features/oneuptime-po-transmissions-to-vendors-monitor.md
40
+ - ../../../clients/compass-canada/features/oneuptime-sales-order-transmission-monitor.md
40
41
  - ../../../../clients/nychh/features/oneuptime-asset-tag-backfill-monitor.md
41
42
  - ../../../../clients/compass-usa/features/oneuptime-office-depot-inbound-files-monitor.md
42
43
  - ../../../clients/nychh/features/oneuptime-transfer-order-emails-owed-monitor.md
@@ -51,7 +52,7 @@ A second, **OneUptime-reporting** monitoring pattern for the 2.0 worker2 tier, p
51
52
  `App_SystemMonitor_Compass` monitors. A worker2 cron action runs a self-contained check, decides
52
53
  pass/fail itself, and POSTs a JSON metric body to a OneUptime "Incoming Request" monitor — replacing
53
54
  the 1.0 tier's email alerts. The class is `abstract class _Worker_Monitor_Compass` and now carries a
54
- **suite of 14 monitors** covering the Compass USA / Office Depot integration (plus one Compass Canada monitor) (S3, DB, mailbox, and
55
+ **suite of 14 monitors** covering the Compass USA / Office Depot integration (plus two Compass Canada monitors) (S3, DB, mailbox, and
55
56
  NetSuite SuiteQL checks). Designed to be **client-agnostic** — a reusable template for future monitors and clients.
56
57
 
57
58
  Distinct from the DB-driven email-orchestrator [Monitoring Framework](./monitoring-framework.md)
@@ -152,6 +153,11 @@ Each measures one Compass/Office Depot (or Compass Canada) integration metric an
152
153
  `Core.CronJobs` id 87, `*/5`. First monitor in this class on a **second client DB** (registers
153
154
  `Client_CompassCanada` in-method). DEGRADED >10 waiting / >15 min oldest, HIGH >20 / >30 min. Details:
154
155
  [Compass Canada: PO-to-vendor monitor](../../../clients/compass-canada/features/oneuptime-po-transmissions-to-vendors-monitor.md).
156
+ - **CompassCanadaSalesOrderTransmission** (DB, added 2026-10-22) — Canada clone of
157
+ `CompassSalesOrderTransmission`: approved `Client_CompassCanada` SOs not yet sent to MITS. `Core.CronJobs`
158
+ id 98, `*/5`. Does **not** exclude cancelled (stage 8), because the Canada cron does not. DEGRADED >6 /
159
+ >30 min, HIGH >12 / >60 min. Details:
160
+ [Compass Canada: SO-to-MITS monitor](../../../clients/compass-canada/features/oneuptime-sales-order-transmission-monitor.md).
155
161
 
156
162
  ### Payload contract & OneUptime criteria (critical — OneUptime cannot compare numbers)
157
163
 
@@ -617,6 +623,7 @@ production deploy.**
617
623
  - [OneUptime 1.0 worker uptime monitoring](../../../1.0/apps/worker/features/oneuptime-worker-uptime-monitoring.md) — the 1.0 push-heartbeat predecessor
618
624
 
619
625
  ## Change history
626
+ - 2026-10-22 — Added `CompassCanadaSalesOrderTransmission` (cron 98); its first two prod runs hit the undefined-method gotcha (row inserted before deploy). (bala)
620
627
  - 2026-10-16 — Added same-class merge-conflict gotcha; linked NYCHH `TransferOrderEmailsOwed` (TRUE-82758). (mhammontree)
621
628
  - 2026-10-15 — Absence rule must exceed the longest gap between pushes for non-`*/5` monitors; linked NYCHH `AssetTagBackfill` (twice daily, 960 min). (mhammontree)
622
629
  - 2026-10-13 — Added `OfficeDepotInboundFiles` (cron 93, CloudWatch + S3) after `OfficeDepotEdiImportQueue` stayed green through the 2026-10-10 AS2 outage; import JSONs are never committed to worker2. (bala)
@@ -8,7 +8,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
8
8
  - **worker** (Worker) — 43 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
9
9
  - **dbchanges** (Database Changes) _(framework core)_ — 1 doc(s) → [1.0/apps/dbchanges/INDEX.md](1.0/apps/dbchanges/INDEX.md)
10
10
  - **worker1.5** (Worker 1.5) — 0 doc(s) → [1.0/apps/worker1.5/INDEX.md](1.0/apps/worker1.5/INDEX.md)
11
- - **togadesk** (TOGa Desk) — 16 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
11
+ - **togadesk** (TOGa Desk) — 17 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
12
12
  - **togaview** (TOGa View) — 8 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
13
13
  - **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
14
14
  - **walmarttechservices** (Walmart Tech Services) — 1 doc(s) → [1.0/apps/walmarttechservices/INDEX.md](1.0/apps/walmarttechservices/INDEX.md)
@@ -23,7 +23,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
23
23
  ## 2.0 framework
24
24
 
25
25
  - **_underscore** (_Underscore) _(framework core)_ — 114 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
26
- - **worker2** (Worker) — 93 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
26
+ - **worker2** (Worker) — 94 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
27
27
  - **api2** (API) — 27 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
28
28
  - **dbchanges2** (Database Changes) _(framework core)_ — 23 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
29
29
  - **toga2-supply** (TOGa Supply) — 9 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
@@ -7,6 +7,7 @@
7
7
  | [Grand & Toy ASN Import (Compass Canada)](features/grand-and-toy-asn-import.md) | 2.0 | Imports Grand & Toy ASNs for Compass Canada (CSV cron + cXML gateway) and auto-builds the ItemFulfillment chain + bilingual in-transit email; open for G&T ASN f |
8
8
  | [Compass Canada — Item-Fulfillment TableViews (dead-Core-id 500, rebuilt onto the USA shape)](features/item-fulfillment-tableviews.md) | 2.0 | Why Compass Canada's item-fulfillment TableViews 500'd on dead Core ids and how they were rebuilt onto the USA shape; open when a Canada TableView 500s on /meta |
9
9
  | [Compass Canada: PO-to-vendor transmission monitor (Monitor/Compass/CompassCanadaPurchaseOrderTransmissionsToVendors)](features/oneuptime-po-transmissions-to-vendors-monitor.md) | 2.0 | worker2 OneUptime push monitor for Compass Canada POs the 1.0 cron has not yet sent to the vendor (Grand & Toy), plus how the Canada PO transmit cron differs fr |
10
+ | [Compass Canada: sales-order-to-MITS transmission monitor (Monitor/Compass/CompassCanadaSalesOrderTransmission)](features/oneuptime-sales-order-transmission-monitor.md) | 2.0 | worker2 OneUptime push monitor for approved Compass Canada sales orders the 1.0 cron has not yet sent to MITS, plus Canada MITS send-cron timing facts; open whe |
10
11
  | [Compass Canada — order fulfillment status (standard base rule, no Canada override)](features/order-fulfillment-status-per-line.md) | 2.0 | Canada-specific facts for the shared Compass order fulfillment status (standard base rule since TRUE-79669); open before touching Canada order status or Canada |
11
12
  | [Compass Canada Persona Model (sector-granted vs hand-assigned)](features/persona-model.md) | 2.0 | Where each `Client_CompassCanada` persona comes from: PEOPLE cron (only "All"), sector `Locations_Personas`, or hand-assigned with nothing keeping it in step. |
12
13
  | [Compass Canada](profile.md) | 2.0 | Compass Canada is the Canadian arm of the Compass account — a separate TOGA tenant, related to but distinct from Compass USA. |
@@ -0,0 +1,54 @@
1
+ ---
2
+ title: "Compass Canada: sales-order-to-MITS transmission monitor (Monitor/Compass/CompassCanadaSalesOrderTransmission)"
3
+ framework: "2.0"
4
+ repo: worker2
5
+ project: Worker
6
+ client: compass-canada
7
+ type: client-feature
8
+ status: active
9
+ updated: 2026-10-22
10
+ owners: ["bala"]
11
+ files:
12
+ - worker2/Worker/Monitor/Compass.php
13
+ - worker/crons/toga2/compasscanada/workflow/1_transmit_compassCanada_sales_orders_to_mits.php
14
+ - worker/schedules/cron.worker.sync.json
15
+ related:
16
+ - ../../../2.0/apps/worker2/features/oneuptime-worker2-monitoring.md
17
+ - ../../compass-usa/features/mits-sales-order-transmission-alerting.md
18
+ - ./oneuptime-po-transmissions-to-vendors-monitor.md
19
+ - ../profile.md
20
+ ---
21
+ worker2 OneUptime push monitor for approved Compass Canada sales orders the 1.0 cron has not yet sent to MITS, plus Canada MITS send-cron timing facts; open when Canada orders are not reaching MITS or when tuning this monitor.
22
+
23
+ ## Summary
24
+ `_Worker_Monitor_Compass::CompassCanadaSalesOrderTransmission()` counts approved, untransmitted Canada SOs and the age of the oldest, and pushes to OneUptime monitor "Compass Canada Sales Order Transmissions". Canada clone of the USA `CompassSalesOrderTransmission` (cron 28). Shared pattern (payload contract, provisioning, criteria): [OneUptime push-metric monitors](../../../2.0/apps/worker2/features/oneuptime-worker2-monitoring.md).
25
+
26
+ - Prod `Core.CronJobs` **id 98**, `*/5 * * * *`, `maxExecutionTime` 120. Live 2026-10-22 (worker2 `_production` `8e3fcc8`); first runs 0 waiting, alarm=OK.
27
+ - Push URL = in-method `$ONEUPTIME_URL` local (credential; never record the value).
28
+ - Import JSON: `test/@Bala/monitors/monitor-import-compass-canada-sales-order-transmission.json` (never in worker2).
29
+ - Body: `status, alarm, reason, pendingCount, oldestPendingMinutes, oldestPendingOrderNumber, thresholds, checkedAtUtc`.
30
+
31
+ ## How it works
32
+
33
+ ### Producer being watched (1.0)
34
+ `worker/crons/toga2/compasscanada/workflow/1_transmit_compassCanada_sales_orders_to_mits.php`, `*/3 * * * *` in `worker/schedules/cron.worker.sync.json` ("Send TOGaSupply sales orders to CompassCanada"), runs 24/7. Sleeps 30s per order (about 6 orders per run). Picks orders `ORDER BY RAND()`. Throws on any MITS failure (No Items Found / more than 15 items / non-200), which aborts the run.
35
+
36
+ ### Query (mirrors the cron exactly)
37
+ - `Approvals.recordId = 14`, INNER JOIN `ApprovalDecisions` stage 1 **and** stage 2 both `isApproved = 1`, `SalesOrders.c_dtTransmittedToCompass IS NULL`, `customerId = 5`.
38
+ - **Does NOT exclude `salesOrderStageId = 8` (cancelled)**, unlike USA, because the Canada cron does not skip them. Add the filter to both together or neither.
39
+ - Age = minutes since the **later** of the two approval decisions (same `COALESCE`/`GREATEST` NULL guard as USA; reason in the shared doc).
40
+
41
+ ### Thresholds (prod, last 60 days: 175 of 177 sent within 10 min of final approval, busiest day 12 orders)
42
+ | Signal | DEGRADED | HIGH |
43
+ |---|---|---|
44
+ | `pendingCount` | > 6 | > 12 |
45
+ | `oldestPendingMinutes` | > 30 | > 60 |
46
+
47
+ ## Gotchas
48
+ - **Send minutes are always divisible by 3.** All 177 sends in 60 days landed on a `*/3` minute, between 03:00 and 21:00. Use this to tell a cron send from a manual one.
49
+ - **A bad order stalls alone, forever.** `ORDER BY RAND()` means one failing order does not block the others for long, but it never sends. Only the age alarm catches it. Two past stalls: SAC100749 (704 min, 2026-08-31), SAC100651 (1067 min, 2026-09-24).
50
+ - **Untransmitted is not the same as stuck.** Prod 2026-10-22: 55 untransmitted Canada orders, all `salesOrderStageId` NULL. 47 are rejected (correct, never sent). 8 (SAC100694 to SAC100706, 2026-07-31 to 2026-08-06) have only a stage-2 decision with `isApproved` NULL and no stage-1 row, so they are stuck in approval. The monitor cannot see them (INNER JOINs). Open, not fixed.
51
+ - Canada stage ids: `ApprovalTemplateStages` 1 "Pending Initial Approval", 2 "Pending Approval" (template 1). Every Canada order has an `Approvals` row (182 in 60 days, 0 missing).
52
+
53
+ ## Change history
54
+ - 2026-10-22 — Created and deployed to prod (cron 98, `*/5`); first runs 0 waiting, alarm=OK. 14:25/14:30 runs failed "Call to undefined method" because the cron row went in before the deploy. (bala)
@@ -42,6 +42,7 @@ related:
42
42
  - features/item-fulfillment-tableviews.md
43
43
  - ../../2.0/apps/worker2/features/compass-vip-support-importer.md
44
44
  - features/oneuptime-po-transmissions-to-vendors-monitor.md
45
+ - features/oneuptime-sales-order-transmission-monitor.md
45
46
  - ../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
46
47
  - ../../2.0/apps/toga2-commerce/features/sso-redirect-and-session-gating.md
47
48
  - ../compass-usa/features/saml-sso.md
@@ -137,6 +138,8 @@ to but distinct from Compass USA. Like Compass USA it spans the **2.0** commerce
137
138
  email also `print_r`s the full payload (ship-to PII) into the body and has no dedupe. Recipients
138
139
  are currently `devteam@togatech.com` + `vburks@togatech.com`. See
139
140
  [MITS Sales-Order Transmit Alerting](../compass-usa/features/mits-sales-order-transmission-alerting.md).
141
+ Approved orders not yet sent to MITS are watched by the OneUptime monitor (cron 98, 2026-10-22):
142
+ [SO-to-MITS monitor](features/oneuptime-sales-order-transmission-monitor.md).
140
143
 
141
144
  ## Storefront notes (toga2-commerce)
142
145
  - Runs the same `toga2-commerce` storefront (2.0, consumes api2), with English + French cart
@@ -5,7 +5,7 @@ project: _Underscore
5
5
  client: compass-usa
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-10-06
8
+ updated: 2026-10-22
9
9
  owners: ["dfranks", "bala", "jcardinal"]
10
10
  files:
11
11
  - worker/crons/toga2/compass/workflow/1_transmit_compass_sales_orders_to_mits.php
@@ -20,6 +20,7 @@ related:
20
20
  - item-catalogs-and-duplicate-items.md
21
21
  - ../workflows/catalog-fold-reversal.md
22
22
  - ../../compass-canada/profile.md
23
+ - ../../compass-canada/features/oneuptime-sales-order-transmission-monitor.md
23
24
  - ../../../2.0/apps/worker2/features/error-escalation-cron.md
24
25
  - ../../../2.0/apps/_underscore/features/error-reporting-issue-event.md
25
26
  - ../../../1.0/apps/library/features/error-capture-1-0.md
@@ -83,7 +84,7 @@ The alert almost never fires on **volume**. It fires because one bad order **abo
83
84
 
84
85
  **Recommended code hardening (NOT yet implemented):** wrap each order's transmit in `try/catch` so one MITS rejection raises the business issue but **continues to the next order** instead of aborting the batch. This removes the starvation entirely.
85
86
 
86
- The worker2 OneUptime monitor now catches this starvation directly: `CompassSalesOrderTransmission` alarms on `pendingCount > 10` **OR** `oldestAgeMinutes > 180`, so a single order stuck too long pages even when the count is under threshold. See [OneUptime push-metric monitors for 2.0 workers](../../../2.0/apps/worker2/features/oneuptime-worker2-monitoring.md).
87
+ The worker2 OneUptime monitor now catches this starvation directly: `CompassSalesOrderTransmission` alarms on `pendingCount > 10` **OR** `oldestAgeMinutes > 180`, so a single order stuck too long pages even when the count is under threshold. See [OneUptime push-metric monitors for 2.0 workers](../../../2.0/apps/worker2/features/oneuptime-worker2-monitoring.md). Canada has its own clone (cron 98): [Canada SO-to-MITS monitor](../../compass-canada/features/oneuptime-sales-order-transmission-monitor.md).
87
88
 
88
89
  ## Gotchas
89
90
  - **Canada is the pre-2026-08-03 design, and it still carries the two problems that migration fixed.** Its "Invalid response from MITS API" email `print_r`s the **whole transmission payload** into the body — which includes ship-to addressee, attention line, street address and phone number — and there is no issue dedupe, so a bad run emails once per order. Treat bringing Canada onto `App_Exception_Business` as known outstanding work, not a new idea; the USA block is the reference implementation.
@@ -6,8 +6,8 @@ project: Claude Harness
6
6
  client: shared
7
7
  type: workflow
8
8
  status: active
9
- updated: 2026-10-01
10
- owners: ["jcardinal", "tcox", "ajean", "mhammontree"]
9
+ updated: 2026-10-21
10
+ owners: ["jcardinal", "tcox", "ajean", "mhammontree", "bala"]
11
11
  files:
12
12
  - claude/skills/start/SKILL.md
13
13
  - claude/skills/finish/SKILL.md
@@ -104,7 +104,7 @@ SELECT name, clientIdentifier FROM Clients WHERE name LIKE '%<keyword>%';
104
104
  - **Reverse-engineering the `talos` project because someone said "ask Talos" is a real failure mode** — it burns a session answering the wrong question. Default to the MCP.
105
105
  - **KB client names differ from `registry.json`.** The KB uses `compass-group` (not `compass-usa`/`compass-canada`), `health-and-hospitals` (not `nychh`), `nyc-doe` (not `nycdoe`), and carries buckets with no registry entry at all — `northwell`, `endeavor-health`, `casl`, `lenovo`, `adyen`, `speedcast`, `rumc`, `uma`, `craftex`, `dunn`, `interfaith-ministries`, `ford-foundation`, `alpha-omega-plastics`, `american-campus-communities`, `ninja-rmm`, plus non-client buckets `general`, `ai`, `power-bi`, `warehouse`, `toga-desk`, `toga-technology`. Always pick the `client` value from the `available_clients` list the tool returns.
106
106
  - **⚠ "Beta" is `dev-sandbox`, NOT `client-beta`.** For the beta API tier (`api.beta.togahub.com`), `Core.DatabaseHosts` maps environment `beta` for `Client_*` schemas to the **dev-sandbox** cluster — so "the beta database" and "the dev-sandbox database" are the same host. The MCP's `client-beta` environment exposes **no schemas** and querying it looks like the data is missing. Query **`dev-sandbox`** whenever someone says "beta". Any frontend pointed at `VITE_API=https://api.beta.togahub.com/v2` is therefore reading/writing dev-sandbox data. (2024-era onboarding SQL shows beta on a us-west-2 `client-cluster`; that has since been consolidated — trust `Core.DatabaseHosts`, not old migrations.)
107
- - **⚠ The write-blocker is a naive string scan — it rejects `UPDATE`/`REPLACE` even inside a string literal.** `toga_query` refuses the whole statement if those words appear anywhere in it, so a read-only query like `… WHERE output LIKE '%skipped update%'` fails validation. **A column alias trips it too** — `… AS updateDisabled` is rejected on the same scan, so the alias has to be renamed (`skippedDisabled`), not just the predicate. Work around it by matching on a fragment that avoids the keyword (`LIKE '%disabled%'`, `LIKE '%skipped%'`), or by pulling the rows and filtering client-side — don't conclude the data isn't there.
107
+ - **⚠ The write-blocker is a naive string scan — it rejects `UPDATE`/`REPLACE` even inside a string literal.** `toga_query` refuses the whole statement if those words appear anywhere in it, so a read-only query like `… WHERE output LIKE '%skipped update%'` fails validation. **A column alias trips it too** — `… AS updateDisabled` is rejected on the same scan, so the alias has to be renamed (`skippedDisabled`), not just the predicate. **The `REPLACE()` string function is rejected too** — use `REGEXP_REPLACE()` (works on the `legacy` MySQL 8 cluster). Work around it by matching on a fragment that avoids the keyword (`LIKE '%disabled%'`, `LIKE '%skipped%'`), or by pulling the rows and filtering client-side — don't conclude the data isn't there.
108
108
  - **Production sessions render in US/Central (UTC−5); most other timestamps you're comparing are UTC.** GitHub/API/webhook timestamps are UTC, so a naive `dtStamp` vs. commit-time comparison is off by five hours — enough to make a healthy worker fleet look dead. Anchor both sides to UTC (or `CONVERT_TZ`) before drawing a conclusion about "when did this last run".
109
109
  - **⚠ Talos auto-generated "KB investigation" text on a ClickUp ticket can be fabricated.** TRUE-80523's description called WJE "Write Job Entry" and cited a CloudWatch/Datadog ADR, a DLQ, and a Migration Sprint retro — none exist. Treat such write-ups as unverified; check every name and source against the code, this KB, and the data before acting on it.
110
110
  - **`local` is not this MCP.** If someone means their own machine's database, use the `mysql` CLI via shell, not `toga-db`.
@@ -124,6 +124,7 @@ SELECT name, clientIdentifier FROM Clients WHERE name LIKE '%<keyword>%';
124
124
  Schema names are **case-sensitive** — copy the exact value from `toga_list_schemas` or `Core.Clients`. `Client_Aig` works; `Client_AIG` and `client_aig` do not.
125
125
 
126
126
  ## Change history
127
+ - 2026-10-21 — Write-blocker gotcha: `REPLACE()` function also rejected; use `REGEXP_REPLACE()` (TRUE-82979). (bala)
127
128
  - 2026-10-01 — Added gotcha: Talos auto-generated ClickUp ticket write-ups can invent sources (TRUE-80523). (mhammontree)
128
129
  - 2026-09-25 — corrected the "TOGa IQ" row: it now names the separate `toga25-iq` app, not the `talos` codebase (rebrand) (jcardinal)
129
130
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.1114",
3
+ "version": "1.0.1116",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",