toga-ai 1.0.300 → 1.0.301

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.
@@ -6,6 +6,6 @@
6
6
  | [Compass MA Sales Order Exception Report](features/compass-ma-sales-order-exception-report.md) | A worker cron that emails operations the "Compass Refresh Exception Report" — Compass `MA%` sales orders whose corresponding Office Depot (ODP) sales order has | worker/crons/toga2/compass/workflow/7_generate_ma_sales_order_exception_report.php |
7
7
  | [Compass Partial In-Transit & Delivered Emails (per package)](features/compass-partial-in-transit-delivered-emails.md) | Compass USA and Compass Canada send a **per-package** in-transit email (and a matching delivered email) instead of one email listing the whole order. | worker/crons/toga2/compass/update_salesorder_status_from_odp.php, worker/crons/toga2/compasscanada/workflow/3_update_salesorder_status_from_grand_and_toy.php |
8
8
  | [Forecast2 ↔ NetSuite Reconciliation & Trueup Tooling](features/forecast2-netsuite-reconciliation.md) | CLI tools to **audit** and **repair** drift between the production `Forecast` DB (core2) and NetSuite. | test/@dave/checker.php, _underscore/Component/Forecast/SaleImport/SaleImport.php, test/@dave/looper.php, test/@dave/reconcile_netsuite_totals.php, test/@dave/fixer.php, test/@dave/analyze_netsuite_forecast_diff.php, test/@dave/trueup_sales.php, test/@dave/trueup_open_orders.php, test/@dave/loop_trueup_open_orders.php, test/@dave/trueup_opportunities.php, test/@dave/probe_sales_gap_direct.php, test/@dave/probe_missing_oo_timing.php, test/@dave/probe_missing_oo_createdby.php, test/@dave/probe_drift_so_dates.php, test/@dave/probe_profit_invoices.php, test/@dave/probe_profit_gap.php, worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php, worker/crons/toga2/forecast2/periodic_forecast_discrepancy_fix_open_orders.php, worker/crons/toga2/forecast2/import_open_orders.php, worker/schedules/cron.worker.infrastructure.json |
9
- | [NetSuite → TOGa Supply Per-Client Sync (thin wrappers)](features/netsuite-togasupply-per-client-sync.md) | Syncs NetSuite transactions (sales orders, purchase orders, invoices, item receipts, item fulfillments, inventory adjustments) into each TOGa Supply (2.0) clien | worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/crons/toga2/netsuite/sync_togasupply_canon.php, worker/schedules/cron.worker.sync.json, dbchanges2/_modules/netsuite/2026-04-01 - Parameters.sql |
9
+ | [NetSuite → TOGa Supply Per-Client Sync (thin wrappers)](features/netsuite-togasupply-per-client-sync.md) | Syncs NetSuite transactions (sales orders, purchase orders, invoices, item receipts, item fulfillments, inventory adjustments) into each TOGa Supply (2.0) clien | worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/crons/toga2/netsuite/sync_togasupply_canon.php, worker/schedules/cron.worker.sync.json, dbchanges2/_modules/netsuite/2026-04-01 - Parameters.sql, library/app/api/netsuite/rest.php, library/app/systemmonitor/netsuiteintegration.php |
10
10
  | [Prudential: Send Shipments for the Day report (daily cron)](features/send-shipments-for-the-day.md) | Daily cron (9:00 PM) that emails Prudential and Dell stakeholders an Excel report of all devices shipped that day, including tracking number, serial number, emp | worker/crons/notifications/reports/send_shipments_for_the_day.php |
11
11
  | [Onboarding a Client to the NetSuite TOGa Supply Sync](workflows/onboarding-client-to-netsuite-togasupply-sync.md) | How to add a new TOGa 2 client to the per-client NetSuite → TOGa Supply importer (`worker/crons/toga2/netsuite/`). | worker/crons/toga2/netsuite/sync_togasupply.php, worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/schedules/cron.worker.sync.json, dbchanges2/_modules/netsuite/2026-04-01 - Parameters.sql |
@@ -6,13 +6,15 @@ project: Worker
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-30
9
+ updated: 2026-07-09
10
10
  owners: ["dfranks", "bala"]
11
11
  files:
12
12
  - worker/crons/toga2/netsuite/common_sync_togasupply.php
13
13
  - worker/crons/toga2/netsuite/sync_togasupply_canon.php
14
14
  - worker/schedules/cron.worker.sync.json
15
15
  - dbchanges2/_modules/netsuite/2026-04-01 - Parameters.sql
16
+ - library/app/api/netsuite/rest.php
17
+ - library/app/systemmonitor/netsuiteintegration.php
16
18
  related:
17
19
  - ../architecture.md
18
20
  - forecast2-netsuite-reconciliation.md
@@ -128,9 +130,34 @@ Parameters are stored **per client DB** but accessed **through the TOGa2 API**,
128
130
  older** integration (`syncWithToga`/`syncWithTogadesk`) with its own legacy parameter keys
129
131
  (`NETSUITE_LAST_*_INTEGRATION_DATETIME`) — NOT the supply sync. The supply wrapper for AIG
130
132
  lives in the `netsuite/` folder. Both key sets coexist harmlessly.
131
- - **Invoices lag ~24h by design:** the invoice section caps its upper bound at `now − 86400s`
132
- (invoices may still be attaching), so `LAST_SYNC_DATETIME_INVOICES` always trails the others
133
- by a day. Not a fault.
133
+ - **Invoices lag ~24h by design + are keyed on `lastmodifieddate`:** the invoice section caps its
134
+ upper bound at `now − 86400s` (invoices may still be attaching), so `LAST_SYNC_DATETIME_INVOICES`
135
+ always trails the others by a day. Not a fault. Invoices are also pulled by
136
+ **`lastmodifieddate`, NOT `trandate`** — `App_Api_Netsuite_Rest::listSales()` defaults
137
+ `$dateField='lastmodifieddate'` and the engine calls it without the 4th arg. So a backdated
138
+ `trandate` is irrelevant to whether an invoice imports, and a just-modified invoice still won't
139
+ import until it is >24h old (the upper-bound cap).
140
+ - **A parse error in the shared `library/app/api/netsuite/rest.php` takes down EVERY client at
141
+ once (tier-wide outage).** All wrappers autoload `App_Api_Netsuite_Rest` in the pre-section
142
+ LOOKUPS/setup phase of `common_sync_togasupply.php` (~line 433). Because PHP parses the whole
143
+ file before executing, any fatal parse error in `rest.php` prevents the class from loading and
144
+ crashes **all** clients' sync at the same instant — before any record section runs.
145
+ **Localizing the crash from `Parameters`:** `NETSUITE_EXECUTION_MODE_*` is `<seconds>-IDLE` vs
146
+ `<seconds>-RUNNING`; `startModeIteration()` writes RUNNING at the *start* of a section. If a
147
+ frozen client's mode is stuck **IDLE** (not RUNNING), the script is dying **before** any section
148
+ — i.e. in the LOOKUPS/setup phase (autoload/parse error, or a lookup 403/exception). Stuck
149
+ **RUNNING** means it crashed *inside* that section. And because `SALES_ORDERS` advances its
150
+ watermark to ~now on every completed run (no 24h cap), a SALES_ORDERS watermark frozen for days
151
+ means no run has *completed*, even if the cron is firing. To confirm tier-wide vs per-client:
152
+ compare several clients' watermarks — **all frozen at the same timestamp = shared/upstream cause**
153
+ (e.g. this parse error), not per-client data. When the fix deploys, MODE flips to RUNNING and the
154
+ watermark jumps to ~now on completion (a positive live signal); the sync self-recovers and
155
+ backfills the gap.
156
+ - **Monitoring blind spot — not every client is in the NetSuite sync monitor.**
157
+ `App_SystemMonitor_NetSuiteIntegration` (`library/app/systemmonitor/netsuiteintegration.php`)
158
+ alerts ClickUp when any client's checkpoint is >48h stale, but its `CLIENT_CONFIGURATIONS` list
159
+ (~line 16) **omits Quad, AIG, and Growrk**. Their stalls raise no alert (Quad's 3-day July-2026
160
+ outage went unflagged for that reason). Follow-up: add Quad/AIG/Growrk to `CLIENT_CONFIGURATIONS`.
134
161
  - **Seeded-but-stale = stalled sync.** Verify health by reading `LAST_SYNC_DATETIME_*` in each
135
162
  `Client_<Id>.Parameters`: a healthy client advances to ~now every 5 min. As of 2026-06-17,
136
163
  Quad was seeded but frozen at 2025-04/05 (not advancing) while the other 12 deployed clients
@@ -151,6 +178,19 @@ Parameters are stored **per client DB** but accessed **through the TOGa2 API**,
151
178
 
152
179
  ## Change history
153
180
 
181
+ - 2026-07-09 — **Tier-wide outage (2026-07-06 → 07-09): a dropped brace in shared `rest.php`
182
+ killed every client's sync for 3 days.** A bad merge (`c3caa11a`, "Merge branch '_production'
183
+ into TRUE-79078", 2026-06-24) silently dropped two tokens at the `listLocations()` /
184
+ `listPurchaseOrders()` boundary in `library/app/api/netsuite/rest.php` (~line 1119) during
185
+ conflict resolution — the closing `}` of `listLocations()` and the `/**` opening the
186
+ `listPurchaseOrders()` docblock — leaving `return $out;` immediately followed by a bare
187
+ ` * Returns purchase orders...`, a fatal `syntax error, unexpected '*'`. `App_Api_Netsuite_Rest`
188
+ then failed to load entirely, so every client's autoload in the LOOKUPS phase crashed. Shipped to
189
+ prod via automated merge `c85e39e5` at 2026-07-06 16:17 UTC — the exact minute all clients' last
190
+ successful sync ran. Fix: restored the missing `}` and `/**`; verified `php -l` clean. Sync
191
+ self-recovered and backfilled the July 6–9 gap (Quad invoice 313319 / order 281251 / $2,356.22
192
+ imported, all watermarks current). See the new tier-wide-parse-error and monitor-blind-spot
193
+ gotchas above. (bala)
154
194
  - 2026-06-30 — The IF section's `syncItemFulfillmentFromNetsuite` (`library/app/api/toga2.php`) now
155
195
  imports **all** fulfillment statuses (`['_picked','_packed','_shipped']`, not just shipped),
156
196
  stamping/advancing the IF stage from `c_netsuiteInternalItemFulfillmentStatus`. Full mechanics
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.300",
3
+ "version": "1.0.301",
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",