toga-ai 1.0.55 → 1.0.56

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.
@@ -9,7 +9,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
9
9
 
10
10
  ## 2.0 framework
11
11
 
12
- - **_underscore** (_Underscore) _(framework core)_ — 4 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
12
+ - **_underscore** (_Underscore) _(framework core)_ — 5 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
13
13
  - **worker2** (Worker) — 5 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
14
14
  - **api2** (API) — 1 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
15
15
  - **dbchanges2** (Database Changes) _(framework core)_ — 1 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
@@ -4,4 +4,5 @@
4
4
  |-----|-----------|---------|-------|
5
5
  | [Compass ASN → ItemFulfillment Auto-Creation](features/asn-to-item-fulfillment.md) | 2.0 | For Compass USA, posting an AdvanceShippingNotice (ASN) auto-creates the ItemFulfillment (IF) on the upstream SalesOrder. | _underscore/Model/Compass/AdvanceShippingNotice.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client_Compass/2026-06-11 - AsnItemTrackingNumberAcl.sql |
6
6
  | [Compass: Item Fulfillments for Sales Order Items TableView (tracking via bridge)](features/item-fulfillment-tracking-tableview.md) | 2.0 | The Compass TableView `item-fulfillments-for-sales-order-items` (`TableViews.id = 13` in Client_Compass) was rebuilt as part of the tracking-number bridge migra | dbchanges2/Client_Compass/2026-06-10 - ItemFulfillmentsForSalesOrderItemsTableView.sql |
7
+ | [Compass MITS PO → SO Item Linking](features/mits-po-to-so-item-linking.md) | 2.0 | MITS sends Compass inbound Purchase Orders (`POST /v2/purchase-orders`) against a Sales Order (`mitsSalesOrder`). | _underscore/Model/Compass/PurchaseOrder.php |
7
8
  | [Compass USA](profile.md) | 2.0 | Compass USA is a TOGA client running a multi-tier supply-chain commerce operation. | |
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: Compass MITS PO → SO Item Linking
3
+ framework: "2.0"
4
+ repo: _underscore
5
+ project: _Underscore
6
+ client: compass-usa
7
+ type: client-feature
8
+ status: active
9
+ updated: 2026-06-11
10
+ owners: ["jcardinal"]
11
+ files:
12
+ - _underscore/Model/Compass/PurchaseOrder.php
13
+ related:
14
+ - asn-to-item-fulfillment.md
15
+ ---
16
+
17
+ ## Summary
18
+ MITS sends Compass inbound Purchase Orders (`POST /v2/purchase-orders`) against a Sales Order
19
+ (`mitsSalesOrder`). `_Model_Compass_PurchaseOrder` links each `PurchaseOrderItem` to the
20
+ `SalesOrderItem` it fulfills via the `SalesOrderItems_PurchaseOrderItems` bridge. There are
21
+ **two distinct linking paths** depending on order type, and conflating them caused a
22
+ production data-integrity bug.
23
+
24
+ ## Key files / entry points
25
+ - `_underscore/Model/Compass/PurchaseOrder.php` — `prePost` (SA path + MR via `handleMrOrder`)
26
+ and `postPost` (link creation).
27
+ - USA/Canada subclasses (`Model/Compass/Usa|Canada/PurchaseOrder.php`) are empty and inherit
28
+ this behavior — edit the parent.
29
+
30
+ ## How it works
31
+ - **SA orders (normal):** each inbound PO item carries `createdFromSalesOrderItem.lineNumber`
32
+ (the MITS line, which includes configuration-line offsets). `prePost` remaps it to the real
33
+ SO `lineNumber` via `$mapIncomingLineNumbersToOriginalLineNumbers` and builds
34
+ `salesOrderItemPurchaseOrderItems` on the payload, so the **correct** bridge rows are created
35
+ by the normal nested API write. This is the authoritative SA linkage.
36
+ - **MR orders (`mitsSalesOrder` starts with `MR`):** `prePost` calls `handleMrOrder` and
37
+ returns early. `handleMrOrder` creates/appends the SO from the PO items, **strips**
38
+ `createdFromSalesOrderItem`, and deliberately **aligns** SO and PO `lineNumber`s. It does
39
+ NOT build the item bridge — so the `postPost` lineNumber-match pass is the **only** (and
40
+ correct) MR linking mechanism.
41
+
42
+ ## Data model
43
+ - `SalesOrderItems_PurchaseOrderItems` (`Client_Compass`): `uuid`, `salesOrderItemId`,
44
+ `purchaseOrderItemId`. One row per (SO item, PO item) the PO fulfills.
45
+ - A PO item's `lineNumber` is **PO-local (1..N per PO)** — NOT the SO line number.
46
+
47
+ ## Client variations
48
+ USA and Canada share the parent handler unchanged.
49
+
50
+ ## Gotchas / known issues
51
+ - **Spurious cross-part links from the `postPost` lineNumber join (fixed 2026-06-11).** The
52
+ `postPost` link pass matched `SalesOrderItems.lineNumber = PurchaseOrderItems.lineNumber`
53
+ for *all* orders. For SA orders that is wrong: PO line numbers are PO-local, so whenever an
54
+ SO is split across multiple POs, or carries non-PO lines (freight/tax/warranty) that shift
55
+ the SO line numbers, the join created extra links pointing PO items at the **wrong** SO line
56
+ (different part). The correct SA links already existed from `prePost`; the `postPost` pass
57
+ only added bogus duplicates. Detection: ~40% of recent SA orders had ≥1 link where the PO
58
+ item's part ≠ the SO item's part. **Fix:** guard the `postPost` link block with
59
+ `if (static::isMrOrder($api->httpPayload))` so it runs for MR only. A link whose PO-item
60
+ part ≠ SO-item part is always invalid (a PO line can only fulfill the same part) — that is
61
+ the safe cleanup predicate for remediating historical rows.
62
+ - **Downstream tracking-number misattribution (NOT yet fixed as of 2026-06-11).** Because
63
+ tracking propagation followed the (scrambled) SO↔PO linkage, tracking numbers landed on the
64
+ wrong IF granularity for affected SA orders. Tracking for Compass lives at
65
+ `ItemFulfillmentItemUnits_TrackingNumbers` and `ItemFulfillments_TrackingNumbers` (header),
66
+ NOT `ItemFulfillmentItems_TrackingNumbers`. Source of truth for "which tracking shipped which
67
+ part" is the ASN side: `AdvanceShippingNoticeItemUnits_TrackingNumbers` →
68
+ `AdvanceShippingNoticeItems.purchaseOrderItemId` → PO item → part. A correct remediation
69
+ re-derives every tracking→IF-unit attachment from that ASN truth rather than doing per-line
70
+ swaps (the scramble spans multiple lines, so a single swap just moves a different wrong
71
+ number onto the line). Example seen on SA132739: UPS `1Z8696XA0193326215` actually shipped
72
+ `C40QYUC-1` (SO line 4) but was attached to SO line 1 (`1000555`).
73
+
74
+ ## Change history
75
+ - 2026-06-11 — Guarded `postPost` SO↔PO item linking to MR orders only; SA links come solely
76
+ from `prePost`'s `createdFromSalesOrderItem` remap. Fixes spurious cross-part links. (jcardinal)
77
+
78
+ ## Related docs
79
+ - [Compass ASN → ItemFulfillment Auto-Creation](asn-to-item-fulfillment.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.55",
3
+ "version": "1.0.56",
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",