toga-ai 1.0.227 → 1.0.228

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.
@@ -5,7 +5,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
5
5
  ## 1.0 framework
6
6
 
7
7
  - **library** (Library) _(framework core)_ — 10 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
8
- - **worker** (Worker) — 10 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
8
+ - **worker** (Worker) — 11 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
9
9
  - **togadesk** (TOGa Desk) — 8 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
10
10
  - **togaview** (TOGa View) — 6 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
11
11
  - **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
@@ -2,5 +2,6 @@
2
2
 
3
3
  | Doc | Framework | Summary | Files |
4
4
  |-----|-----------|---------|-------|
5
+ | [NYCDOE Ticket Hold-Status Sync (ServiceNow ⇄ TOGaDesk)](features/hold-status-sync.md) | 1.0 | DOE ticket **hold** status must round-trip between ServiceNow (SNOW) and TOGaDesk and **stay held** — holds are SLA-bearing in both systems. | worker/crons/sync/nycdoe/send_ticket_updates.php, worker/crons/sync/nycdoe/process_tickets.php, worker/crons/sync/nycdoe/send_request_item_updates.php, library/app/model/togadesk/repairorder.php, library/app/api/nycdoev2.php |
5
6
  | [NYCDOE ServiceNow / ASN Integration](features/servicenow-integration.md) | 1.0 | The NYCDOE/ServiceNow integration mirrors DOE's ServiceNow tickets (Incidents + RITMs) into local tables, turns vendor shipment notices into NetSuite Sales Orde | worker/crons/sync/nycdoe/import_asn.php, worker/crons/sync/nycdoe/import_inc.php, worker/crons/sync/nycdoe/legacy_import_asn.php, worker/crons/sync/nycdoe/legacy_process_asn_queue.php, worker/crons/sync/nycdoe/process_tickets.php, worker/crons/sync/nycdoe/1_send_asn_to_netsuite.php, worker/crons/sync/nycdoe/2_send_serials_to_netsuite.php, worker/crons/sync/nycdoe/3_create_installation_ticket.php, worker/crons/sync/nycdoe/send_ticket_updates.php, worker/crons/sync/nycdoe/send_request_item_updates.php, worker/crons/sync/nycdoe/send_nycdoe_proof_of_delivery.php, worker/crons/sync/nycdoe/sync_nycdoe_locations.php, worker/crons/sync/nycdoe/receive_edi_purchase_orders.php, worker/crons/sync/nycdoe/send_edi_open_invoices.php, worker/crons/notifications/nycdoe/, worker/schedules/cron.worker.sync.json, worker/schedules/cron.worker.notification.json, library/app/api/nycdoe.php, library/app/api/nycdoev2.php, library/app/asnprocessor/manufacturer.php, library/app/asnprocessor/apple.php, library/app/asnprocessor/lenovo.php, library/app/asnprocessor/lexmark.php, library/app/asnprocessor/acer.php, library/app/edi.php |
6
7
  | [New York City Department of Education](profile.md) | 1.0 | NYC DOE (New York City Department of Education) is a TOGA client whose entire integration runs in the **1.0 worker tier** (~30 cron scripts under `worker/crons/ | |
@@ -0,0 +1,127 @@
1
+ ---
2
+ title: NYCDOE Ticket Hold-Status Sync (ServiceNow ⇄ TOGaDesk)
3
+ framework: "1.0"
4
+ repo: worker
5
+ project: Worker
6
+ client: nycdoe
7
+ type: client-feature
8
+ status: active
9
+ updated: 2026-06-29
10
+ owners: [mhammontree]
11
+ files:
12
+ - worker/crons/sync/nycdoe/send_ticket_updates.php
13
+ - worker/crons/sync/nycdoe/process_tickets.php
14
+ - worker/crons/sync/nycdoe/send_request_item_updates.php
15
+ - library/app/model/togadesk/repairorder.php
16
+ - library/app/api/nycdoev2.php
17
+ related:
18
+ - servicenow-integration.md
19
+ - ../profile.md
20
+ - ../../../1.0/apps/worker/architecture.md
21
+ ---
22
+
23
+ ## Summary
24
+
25
+ DOE ticket **hold** status must round-trip between ServiceNow (SNOW) and TOGaDesk and
26
+ **stay held** — holds are SLA-bearing in both systems. This doc covers the bidirectional
27
+ hold-status sync for DOE Incidents (INC) and Request Items (RITM), the authoritative
28
+ business rule that governs it, and the TRUE-79922 fix that made hold persist. It is the
29
+ status-sync companion to the broader [ServiceNow / ASN integration](servicenow-integration.md)
30
+ doc; the underlying crons and `App_Api_NYCDOEV2` plumbing are documented there.
31
+
32
+ > DOE "tickets" are **`repair_orders`** rows (`App_Model_TogaDesk_RepairOrder`,
33
+ > `db_togadesk` / legacy `TOGaDeskSupport`, **clientid = 16**) — NOT the generic `tickets`
34
+ > table / `class.ticket.php`. All four DOE crons filter to client 16 / `NYCDOETickets`, so
35
+ > hold behavior here is **NYCDOE-only**; no other client is affected.
36
+
37
+ ## The authoritative business rule (SME-confirmed — contact-center)
38
+
39
+ 1. **A DOE hold persists until MANUALLY set to a new status.** Nothing auto-reverts a hold.
40
+ 2. **TOGaDesk is the AUTHORITATIVE system for releasing a hold.** A manual change *in
41
+ ServiceNow* does NOT release a TOGaDesk hold — the outbound cron **re-asserts On Hold**
42
+ onto SNOW every run until the hold is cleared in TOGaDesk.
43
+ 3. Scheduling metadata (ETA / assigned technician) is **separate from the hold STATE** — an
44
+ on-site visit can be scheduled weeks out (e.g. summer break) **without releasing the
45
+ hold**. ETA syncs *inside* the hold payload.
46
+
47
+ ## How it works
48
+
49
+ ### Status model (TOGaDesk side)
50
+ - There are **six `HOLD_*` status constants** on `App_Model_TogaDesk_RepairOrder`. All bucket
51
+ to main status **`Hold`** via `App_Model_TogaDesk_RepairOrder::statusDisplayMain()`.
52
+ - `Hold` has **statusRank 6**, beating `Work in Progress` (rank 5) in the downgrade-guard
53
+ added by TRUE-76812 — so a downstream sync cannot silently demote a held order.
54
+
55
+ ### Status field (ServiceNow side)
56
+ - The SNOW **native `state` field** (human-readable: `On Hold`, `In Progress`, `Assigned`,
57
+ `Resolved`, …) is the **SLA-bearing, authoritative status**. Read/write this for hold.
58
+ - The custom **`u_status_task`** field is a *separate concept* with a different vocabulary;
59
+ it can lag/disagree with `state` (observed: native `state="In Progress"` while
60
+ `u_status_task="Open"`). **Never use `u_status_task` for hold detection.**
61
+ - Numeric `state` codes seen on the wire: INC `On Hold` = **3**, `In Progress` = **2**;
62
+ RITM `On Hold` = **8**, the scheduled-update state = **"-14"**.
63
+
64
+ ### Outbound (TOGaDesk → ServiceNow)
65
+ - `send_ticket_updates.php` (INC) pushes the hold as `state:3`. The "Assigned → In Progress"
66
+ auto-start block is **guarded** so it never pushes `state:2` when the local repair order is
67
+ in any `HOLD_*` status (this is what caused the self-clobber — see Change history).
68
+ - `send_request_item_updates.php` (RITM) pushes `state:"8"` (On Hold) and carries a
69
+ defensive `HOLD_*` guard on the scheduled-update path so it can't push `state:"-14"` while
70
+ held.
71
+
72
+ ### Inbound (ServiceNow → TOGaDesk)
73
+ - `process_tickets.php` determines local status from the native **`$data->state`** field
74
+ (NOT `u_status_task`): after the `u_status_task` switch — before the completion-preserve
75
+ step and the `statusRank` downgrade-guard — if native `state` is `On Hold`
76
+ (case-insensitive) it sets `$newStatus = STATUS_HOLD`. Both inbound "Assigned-force"
77
+ `patchINC(state:2)` blocks are guarded against a local hold.
78
+
79
+ ### RITM "ETA-in-hold"
80
+ - `send_request_item_updates.php` syncs `scheduled_date` (ETA) to ServiceNow **inside the
81
+ hold block, in the same payload as `state:"8"`**, when a held order has an ETA + assigned
82
+ technician. This mirrors the INC cron, which already sends `u_eta` while holding — keeping
83
+ scheduling metadata flowing while the hold STATE stays asserted.
84
+
85
+ ## Reference facts (DOE sync debugging)
86
+
87
+ - **SNOW request/response logs:** logged to the legacy `Logs` schema, **`API` table**
88
+ (`App_Model_Logs_API`, `db_logs`, `_databaseNameOverride 'Logs'`). `requestPayload` /
89
+ `responsePayload` are queryable CHAR columns — the primary debugging avenue. Filter
90
+ `endpoint LIKE '%nycd3%'`; the custom DOE endpoint base is **`/api/nycd3/`**. The
91
+ state:3↔state:2 oscillation in TRUE-79922 was proven from this table (INC2074899,
92
+ INC2185183 showed `state:3` then `state:2` pushed seconds apart in one run).
93
+ - **`NYCDOETickets` (`App_Model_Common_NYCDOETicket`, `db_common` / legacy `Common`)** stores
94
+ the inbound SNOW record in `rawData`, a **`FIELDTYPE_BLOBSTORAGE`** field (S3 bucket
95
+ `asifiles`, key `prod/Common/NYCDOETickets/rawData/{id}`) — **NOT a queryable DB column.**
96
+ - **Worker prod code cannot run on a Windows dev box.** The DB/S3 data layer fetches EC2
97
+ instance-metadata (IMDSv2) credentials and fails off-EC2. Investigate with the toga DB MCP
98
+ and the `Logs.API` table instead of running the crons locally.
99
+
100
+ ## Gotchas / known issues
101
+
102
+ - **The self-clobber (root cause #1 of TRUE-79922):** an unguarded "Assigned → In Progress"
103
+ auto-start fought the hold push — `state:3` then `state:2` pushed seconds apart, every run,
104
+ so SNOW never stayed On Hold. Any future auto-start/auto-status block on these crons MUST
105
+ short-circuit when the local RO is in a `HOLD_*` status.
106
+ - **The wrong-field read (root cause #2 of TRUE-79922):** reading `u_status_task` instead of
107
+ native `state` meant a hold set on the SNOW side never reached TOGaDesk. Hold detection is
108
+ on native `state` only.
109
+ - Holds are **never auto-released** — if a SNOW user manually changes status, the outbound
110
+ cron correctly re-asserts On Hold; that is intended, not a bug. Clear the hold in TOGaDesk.
111
+
112
+ ## Change history
113
+ - 2026-06-29 — TRUE-79922: fixed DOE holds never persisting (reverted to In Progress, broke
114
+ SLA reporting both sides). Two coupled defects: outbound self-clobber (`send_ticket_updates.php`
115
+ unguarded Assigned→In-Progress pushing `state:2` over a held `state:3`) and inbound
116
+ wrong-field read (`process_tickets.php` read `u_status_task` instead of native `state`).
117
+ Guarded all Assigned-force blocks (INC outbound + both inbound) against local `HOLD_*`,
118
+ added native-`state`="On Hold"→`STATUS_HOLD` inbound mapping, and a RITM scheduled-update
119
+ `HOLD_*` guard. Built RITM ETA-in-hold sync (`scheduled_date` in the same `state:"8"`
120
+ payload). Recorded the SME business rule (hold persists until manual; TOGaDesk authoritative
121
+ for release). (mhammontree)
122
+
123
+ ## Related docs
124
+ - [NYCDOE ServiceNow / ASN Integration](servicenow-integration.md) — full integration map,
125
+ crons, schedules, and `App_Api_NYCDOEV2` plumbing.
126
+ - [NYC DOE client profile](../profile.md)
127
+ - [Worker (1.0) architecture](../../../1.0/apps/worker/architecture.md)
@@ -36,6 +36,7 @@ files:
36
36
  - library/app/edi.php
37
37
  related:
38
38
  - ../profile.md
39
+ - hold-status-sync.md
39
40
  - ../../../1.0/apps/worker/architecture.md
40
41
  ---
41
42
 
@@ -230,6 +231,11 @@ Vendor SFTP ───(legacy_import_asn.php, ser+non-ser)─┘ [UNIQUE ded
230
231
  of the consumer query; `php -l` every touched file.
231
232
 
232
233
  ## Change history
234
+ - 2026-06-29 — Outbound status sync now keeps DOE holds authoritative (TRUE-79922). Hold
235
+ detection moved to the SNOW native `state` field (not `u_status_task`); Assigned-force
236
+ blocks guarded against local `HOLD_*` to stop the `state:3`↔`state:2` self-clobber; RITM
237
+ now syncs ETA inside the On-Hold payload. Split into dedicated
238
+ [hold-status-sync.md](hold-status-sync.md). (mhammontree)
233
239
  - 2026-06-19 — Investigated (read-only) the replacement-PO-suffix duplicate-fulfillment bug: PO-scoped serial dedupe defeated by per-manufacturer suffix-format variance (`-RPL`/`-REPL`/`-RPLE`/`-N`/`_N`); confirmed live case WR260150152/V60095WK (ROs 772308+801064) and ~14 systemic pairs across Lenovo+Lexmark. Refined business rule #6; added OPEN-BUG gotcha + adjacent anomalies (numeric-PO↔WR cluster, "NA"/integer serials). No code changes. (mhammontree)
234
240
  - 2026-06-10 — Documented the NYC DOE ServiceNow/ASN integration (ticket mirror, dual ASN ingestion, NetSuite freeze pipeline, EDI surface, dedupeKey gotchas). (mhammontree)
235
241
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.227",
3
+ "version": "1.0.228",
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",