toga-ai 1.0.327 → 1.0.329

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.
@@ -21,7 +21,7 @@
21
21
  | [Per-Client Database Connections & the Local Logs Trap](features/per-client-database-connections.md) | When `_underscore` serves a request for a client it opens **three distinct per-client database connections**, not one. | _underscore/Database.php, _underscore/ApiRequest.php, _underscore/Model/Client/Logs/Api.php |
22
22
  | [Recursive Item Fulfillments (upstream mirroring)](features/recursive-item-fulfillments.md) | In a multi-tier supply chain a sales order (SO) spawns a purchase order (PO) that becomes another SO downstream, and so on. | _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Client/ItemFulfillmentItem.php, _underscore/Model/Client/ItemFulfillmentItemUnit.php, _underscore/Model/Client/ItemFulfillmentPackage.php, _underscore/Model/Compass/AdvanceShippingNotice.php, dbchanges2/Core/2026-02-13 - 75601 - RecursiveItemFulfillmentCreation.sql, dbchanges2/Core/2026-06-04 - RecursiveItemFulfillmentPut.sql, dbchanges2/Client_Compass/2026-07-02a - FixSA133377TrackingSerialAndDuplicateIF.sql |
23
23
  | [Surface Resolver (_Model_Core_Surface::resolve — replaces Page::meta)](features/surface-resolver.md) | The runtime for the platform-wide **Surface** UI presentation layer: 9 `_underscore` models plus a cached resolver, `_Model_Core_Surface::resolve(&$api, string | _underscore/Model/Core/Surface.php, _underscore/Model/Client/AclRecordScript.php, _underscore/Model/Core/RecordScript.php, dbchanges2/Core/2026-06-30a - SurfaceMetaGroupAndSalesOrderSections.sql, dbchanges2/Client/2026-06-30a - SurfaceMetaGroupAcl.sql, dbchanges2/Client_Quad/2026-07-01a - GrantSurfacesMetaGroupScriptAcl.sql, dbchanges2/Client_CompassCanada/2026-07-01a - GrantSurfacesMetaGroupScriptAcl.sql, dbchanges2/Core/2026-06-29b - SurfaceMetaPublicReadAcl.sql, dbchanges2/Client/2026-06-29c - SurfaceRecordScriptAcl.sql, dbchanges2/Core/2026-06-29c - SurfaceDebugPhpMethodFix.sql, _underscore/Model/Core/SurfaceElement.php, _underscore/Model/Core/Action.php, _underscore/Model/Core/Vocabulary.php, _underscore/Model/Core/VocabularyTerm.php, _underscore/Model/Core/Message.php, _underscore/Model/Client/SurfaceOverride.php, _underscore/Model/Client/MessageTranslation.php, _underscore/Model/Client/ThemeToken.php, _underscore/Model/Core/Page.php |
24
- | [Tracking-Number Bridge Migration (ASN / Item Fulfillment / Item Receipt)](features/tracking-number-bridges.md) | Shipment tracking numbers used to live as **scalar FK columns** (`trackingNumberId`, `returnTrackingNumberId`) directly on the lowest-level "unit"/"item" tables | api2/Component/Api/V2/V2.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnit.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillmentItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Prudential/AdvanceShippingNotice.php, _underscore/Model/Compass/AdvanceShippingNotice.php, _underscore/Trait/Netsuite/ItemFulfillment.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Core/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql, dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql |
24
+ | [Tracking-Number Bridge Migration (ASN / Item Fulfillment / Item Receipt)](features/tracking-number-bridges.md) | Shipment tracking numbers used to live as **scalar FK columns** (`trackingNumberId`, `returnTrackingNumberId`) directly on the lowest-level "unit"/"item" tables | api2/Component/Api/V2/V2.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnit.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillmentItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Prudential/AdvanceShippingNotice.php, _underscore/Model/Compass/AdvanceShippingNotice.php, _underscore/Trait/Netsuite/ItemFulfillment.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Core/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Growrk/2026-07-13a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql, dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql |
25
25
  | [Units for Items for Purchase Orders — Data Structure](features/units-for-items-for-purchase-orders.md) | Describes how unit (serialized inventory) data is linked to sales-order and purchase-order line items behind the `units-for-items-for-purchase-orders` TableView | |
26
26
  | [Refreshing a Local Dev Database from Beta (dev-sandbox)](workflows/local-db-refresh-from-beta.md) | How to reset a local 2.0 dev database from the **beta / dev-sandbox** environment: dump each schema (`Core`, `Client_<Id>`, `Logs_<Id>`, …) from the beta host, | api2/Config/, _underscore/Loader.php, _underscore/Model/Client/BundleTranslation.php, api2/Component/Api/V2/V2.php, toga25-supply/sync_compasscanada_schema.sql |
27
27
  | [Running a 2.0 App Locally (browser, end-to-end via api2)](workflows/running-a-2.0-app-locally.md) | The full dependency chain required to run a 2.0 client app **through the browser**, end-to-end, against a **local `api2`** (e.g. | _underscore/Environment.php, _underscore/Config.php, _underscore/Database.php, _underscore/Route.php, api2/Component/Api/V2/V2.php, api2/index.php, api2/.htaccess |
@@ -6,7 +6,7 @@ project: _Underscore
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-07-02
9
+ updated: 2026-07-14
10
10
  owners: [mhammontree]
11
11
  files:
12
12
  - _underscore/Model/Client/ItemFulfillment.php
@@ -63,12 +63,17 @@ record instead of a hardcoded constant.
63
63
  record by UUID, reads its stored raw PNG (`labelPdfFile`), and returns a **combined base64 PDF**
64
64
  via `buildFromPngLabels`. Replaced the frontend `pdf-lib` merge (which broke once labels became
65
65
  PNG — it expected a base64 PDF). Requires a Client-DB `AclRecordScripts` dispatch grant or it
66
- 403s — see the ACL permission-chain doc's record-script dispatch section.
66
+ 403s — see the ACL permission-chain doc's record-script dispatch section. **`$caption` accepts a
67
+ position-aligned CSV** (one caption per uuid, in order) so a combined outbound+return PDF can
68
+ caption only the return page "Return Label".
67
69
  - `_Model_Client_ItemFulfillment::generateReturnLabel(&$api, $uuid)`
68
- (`Model/Client/ItemFulfillment.php`): builds a per-carrier **return** shipment request
69
- (ship-from = customer, ship-to = warehouse return address; Ground service; FedEx uses drop-off
70
- pickup), creates a **second** `TrackingNumbers` record, stores its raw PNG, and links it as
71
- `returnTrackingNumberId` on the `ItemFulfillments_TrackingNumbers` header bridge.
70
+ (`Model/Client/ItemFulfillment.php`): builds a per-carrier **return** shipment request, creates a
71
+ **second** `TrackingNumbers` record, stores its raw PNG, links it as `returnTrackingNumberId` on
72
+ the `ItemFulfillments_TrackingNumbers` header bridge, and returns `returnTrackingNumberUuid`. The
73
+ **return address is now per-fulfillment**: it joins `returnAddressId` → `Addresses`/`States` and
74
+ ships **from** that saved return address, falling back to the `RETURN_ADDRESS_*` config constants
75
+ when `returnAddressId` is unset (superseding the earlier fixed `RETURN_ADDRESSES` set). The return
76
+ leg **reuses the outbound** weight/carrier/method/account (see the return-leg semantic below).
72
77
  - `getLabelFormat()` (client UPS config helper): now **defaults to `PNG`** (was ZPL) and validates
73
78
  against a supported-format allowlist, so a carrier label reliably comes back as an embeddable PNG.
74
79
  - `_Component_Library_Carriers_Ups::submitShipmentRequest`
@@ -117,11 +122,28 @@ reprint combine moved to the backend `reprintLabelsApi` scripted API and return-
117
122
  **Return labels.** When `ShipmentRequest->isReturn` is set, the carrier request injects the
118
123
  return-service flags: UPS `Shipment.ReturnService.Code = '9'` (Print Return Label); FedEx
119
124
  `shipmentSpecialServices.returnShipmentDetail` (`returnType = PRINT_RETURN_LABEL`, RMA reason
120
- "Customer Return"). `generateReturnLabel` builds the return request with **ship-from = customer,
121
- ship-to = warehouse**, at **Ground / customer-drops-off** service level (decision), creates a 2nd
122
- `TrackingNumbers` record, stores its raw PNG, and links `returnTrackingNumberId` on the
123
- `ItemFulfillments_TrackingNumbers` bridge. Warehouse return addresses come from a `RETURN_ADDRESSES`
124
- set (two verified addresses: Naperville default + Plainview).
125
+ "Customer Return"). `generateReturnLabel` builds the return request, creates a 2nd
126
+ `TrackingNumbers` record, stores its raw PNG, links `returnTrackingNumberId` on the
127
+ `ItemFulfillments_TrackingNumbers` bridge, and returns `returnTrackingNumberUuid`.
128
+
129
+ **Return address is now per-fulfillment (2026-07).** `generateReturnLabel` joins
130
+ `ItemFulfillments.returnAddressId` → `Addresses`/`States` and ships **from** that saved return
131
+ address; it falls back to the `RETURN_ADDRESS_*` config constants when `returnAddressId` is unset.
132
+ This supersedes the earlier fixed `RETURN_ADDRESSES` set (Naperville/Plainview).
133
+
134
+ **Return-leg semantic (important — only the address is independent).** The return leg **reuses the
135
+ outbound shipment's weight/carrier/method/account**: `packageWeightPounds` = the outbound tracking
136
+ weight, and the return `TrackingNumber`'s carrier/method/account = the outbound's. **Only the
137
+ return ADDRESS is persisted** (`returnAddressId`). The TOGa Supply return modal's
138
+ weight/dims/carrier fields are prefilled from outbound **for display only** and are not persisted
139
+ or independently used — see the fulfill-and-ship doc's edit-trap gotcha.
140
+
141
+ **NetSuite tracking now includes both legs (fixed 2026-07).** `Trait/Netsuite/ItemFulfillment.php::createNetsuiteItemFulfillment`
142
+ read the **retired `itemFulfillmentPackages`** (absent post-bridge), so **no tracking reached
143
+ NetSuite** at all. It now iterates the `itemFulfillmentTrackingNumbers` bridge and pushes the
144
+ **outbound** tracking plus, when present, the **return** tracking as a **second package**
145
+ (`packageDescr = 'Return Label'`). (The 2026-06-16 bridge repoint fixed the four queries in
146
+ `Model/Client/ItemFulfillment.php`; this trait method was a separate straggler on the same table.)
125
147
 
126
148
  ## `FIELD_STORAGE` mechanics (reference)
127
149
 
@@ -222,11 +244,22 @@ still discards the unsaved in-memory value.
222
244
  on the tracking record itself must be CIE-enabled.
223
245
  - **FedEx credentials are hardcoded in `Fedex.php` and were intentionally retained** (Mark's
224
246
  decision) — do not "fix" them into config as part of unrelated work.
247
+ - **Local live-UPS carrier testing setup (local-only).** With `debug_mode=1` the `_underscore` UPS
248
+ carrier hits the UPS **CIE test** endpoint (`wwwcie.ups.com`). To fulfill locally you need three
249
+ things or the call fails in confusing ways: (a) `ShippingMethods.code` populated (UPS service
250
+ codes: Ground=`03`, Next Day Air=`01` — passed straight through as the UPS service `Code`); (b) a
251
+ **`[ups]` config group with OAuth creds** (`oauth_client_id`/`oauth_client_secret`) **in the dev
252
+ INI** — without it, it falls back to blank legacy creds and UPS returns **"Invalid Access License
253
+ number"** (document *where* the creds live, never the values); (c) a **CIE-valid shipper number** —
254
+ the client's production UPS account (`8696XA`) is rejected by CIE with "Missing or invalid shipper
255
+ number". The UPS account-location map lives at the developer's local
256
+ `shipping_carrier_ups_account_location.md`.
225
257
  - **Ship guards (2026-07).** Shipping now **fails fast** if the selected carrier account is empty,
226
258
  and **errors if an Item Fulfillment has >1 tracking number** (can't determine which account to
227
259
  bill) — expect a hard error rather than a silently-wrong bill in those cases.
228
260
 
229
261
  ## Change history
262
+ - 2026-07-14 — TRUE-79191 return-label increment: `generateReturnLabel` ships from the **per-fulfillment** return address (`returnAddressId` → Addresses/States, falling back to `RETURN_ADDRESS_*`; supersedes the fixed `RETURN_ADDRESSES` set) and returns `returnTrackingNumberUuid`; documented the return-leg reuse semantic (return reuses outbound weight/carrier/method/account — only the address is independent). Fixed `Trait/Netsuite/ItemFulfillment.php::createNetsuiteItemFulfillment`, which read the retired `itemFulfillmentPackages` so no tracking reached NetSuite — now iterates the `itemFulfillmentTrackingNumbers` bridge and pushes outbound + return (2nd package, `packageDescr='Return Label'`). `reprintLabelsApi` `$caption` now accepts a position-aligned CSV for per-page captions. Added the local live-UPS testing setup gotcha (`[ups]` OAuth config, CIE endpoint/shipper, `ShippingMethods.code`). (mhammontree)
230
263
  - 2026-07-02 — Reprint combine moved to the backend: new `_Model_Client_TrackingNumber::reprintLabelsApi` scripted API (RecordScript `GET /v2/tracking-numbers/reprint`) returns a combined base64 PDF from the stored PNGs (frontend `pdf-lib` merge removed). Added return-label generation (`generateReturnLabel`; UPS ReturnService `9` / FedEx `PRINT_RETURN_LABEL`; Ground/customer-drops-off; `RETURN_ADDRESSES`; links `returnTrackingNumberId`). Carrier billing account threaded from the tracking record (`shippingCarrierAccountNumber`) — removed `SHIPPER_NUMBER`/`ACCOUNT_NUMBER` constants, fail-fast on empty account, error on >1 tracking number per IF. Ship-to now `COALESCE(IF, SO)` address. `getLabelFormat()` defaults PNG + allowlist. Fixed two SQL injections (`postPost` `$payload->uuid`, `fulfill` NetSuite `$internalId`) and removed leftover debug `echo`/`print_r` from `fulfill()`. Found + fixed the framework-core root cause of storage writes silently vanishing (two `Model.php` `FIELD_STORAGE` bugs — see FIELD_STORAGE mechanics). (mhammontree)
231
264
  - 2026-06-18 — Implemented the label-storage rework: request PNG from UPS/FedEx, store the raw PNG, generate the printable PDF on demand via the new `_Component_Library_LabelPdf` (FPDF); dropped Labelary. Added the FedEx tracking-cred config-fallback fix and the `_Loader`→Composer FPDF autoloader toggle. Open: the `labelPdfFile` S3 write still skips on a lazy-model save. (mhammontree)
232
265
  - 2026-06-16 — Repointed the carrier-label/NS-IF tracking-number queries (`upsShipmentApi`, `fedexShipmentApi`, `fulfill`, `createNetsuiteItemFulfillment`) from the dropped `ItemFulfillmentPackages` table to the `ItemFulfillments_TrackingNumbers` bridge — they had been saving the label/`number` to the wrong/null record (reprint `labelPdfFile` null; NS IF missing tracking). Confirmed working on beta. (mhammontree)
@@ -6,7 +6,7 @@ project: _Underscore
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-07-09
9
+ updated: 2026-07-14
10
10
  owners: ["jcardinal", "mhammontree", "dfranks", "apeterson"]
11
11
  files:
12
12
  - api2/Component/Api/V2/V2.php
@@ -23,6 +23,7 @@ files:
23
23
  - dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql
24
24
  - dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql
25
25
  - dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql
26
+ - dbchanges2/Client_Growrk/2026-07-13a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql
26
27
  - dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql
27
28
  - dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql
28
29
  related:
@@ -153,8 +154,13 @@ returnTrackingNumber: {...} }]`, and an IFIU's as `itemFulfillmentItemUnitTracki
153
154
  integrations enabled 403s (EZ-1) on the bridge records the moment the sync exercises them. Fixed one-off
154
155
  per client as each starts failing: **Prudential** (`Client_Prudential/2026-06-15 - ...`, recs 317/319) and
155
156
  **Quad** (`Client_Quad/2026-06-18a - ...`, all of 317-322) and **NYCHH**
156
- (`Client_Nychh/2026-06-19b - ...`, all of 317-322) so far. Each new client is whack-a-mole until
157
- the chain is folded back into the base migration + blank-client template.
157
+ (`Client_Nychh/2026-06-19b - ...`, all of 317-322) and **GroWrk**
158
+ (`Client_Growrk/2026-07-13a - ...`, all of 317-322) so far. Each new client is whack-a-mole until
159
+ the chain is folded back into the base migration + blank-client template. **Decision (Mark,
160
+ TRUE-79191):** the GroWrk fix is kept **Client_Growrk-scoped** for now — GroWrk is (as far as
161
+ told) the only client on Fulfill & Ship and the team pattern is per-client anyway. A shared
162
+ `Client/` migration would fix all clients at once if the feature broadens — that remains the
163
+ preferred long-term fix (fold into the base migration + blank-client template).
158
164
 
159
165
  - **`Client_CompassCanada` is missing these bridge tables on *beta* (local drift).** Beta's
160
166
  `Client_CompassCanada` lacks 17 tables that prod has — including the `*_TrackingNumbers`
@@ -167,6 +173,7 @@ returnTrackingNumber: {...} }]`, and an IFIU's as `itemFulfillmentItemUnitTracki
167
173
  - **Porting the item-fulfillment TableView fix to another client is two independent decisions, not a copy-paste.** The **re-root** (Units 31 → ItemFulfillmentItems 29 + OUTER unit chain) is universally portable and fixes the "0 records" bug everywhere. The **tracking source is client-specific**: Compass writes one tracking number per item fulfillment at the **item level (318)**, so its views read 318. Other clients populate different bridge levels — verify with `SELECT COUNT(*)` per bridge before choosing. As of 2026-06-19, **record 318 is empty in `Client_Nychh` and `Client_Quad`**; their tracking lives at the **IF/shipment level (317)** (covers IFIs: NYCHH 7955/10049 ≈ 79%, Quad 4878/4967 ≈ 98%) and the **unit level (319)** (≈ 7–9% — serialized only). Copying Compass's 318 join into a client that doesn't write 318 yields a structurally-correct view with permanently blank tracking until 318 is backfilled. (NYCHH's pre-fix view pointed at the now-deleted record 41 = old IF-level/package bridge, i.e. it originally intended IF-level 317.)
168
174
 
169
175
  ## Change history
176
+ - 2026-07-14 — **GroWrk** hit the bridge ACL gap (TRUE-79191): 403 EZ-1 on `item-fulfillment-tracking-numbers` made TOGa Supply's Pending Shipments list come back `isSuccess:false` (frontend showed the empty "Create your first shipment" state). GroWrk never got the fix that Prudential (2026-06-15) and Quad (2026-06-18a) already had. Added `Client_Growrk/2026-07-13a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql` (all 6 bridges 317-322, idempotent NOT-EXISTS guards, `slug='all'`/`sqlExpression='1'`, root logic group operator AND). Decision: kept Growrk-scoped for now (only client on Fulfill & Ship); shared `Client/` migration remains the long-term fix. (mhammontree)
170
177
  - 2026-07-09 — Noted that `Client_CompassCanada` is missing these bridge tables on **beta**, so a local
171
178
  reset from beta reintroduces the 17-table drift (1146 on SalesOrders load); fix locally with
172
179
  `sync_compasscanada_schema.sql`. Cross-linked the new local-DB-refresh-from-beta workflow. (apeterson)
@@ -6,7 +6,7 @@ project: API
6
6
  client: shared
7
7
  type: workflow
8
8
  status: active
9
- updated: 2026-06-18
9
+ updated: 2026-07-14
10
10
  owners: ["jcardinal", "mhammontree"]
11
11
  files: []
12
12
  related: []
@@ -20,6 +20,16 @@ the `agilantsolutions` org. A single pipeline can have multiple Source actions s
20
20
  connection (e.g. `agilantsolutions/api2` and `agilantsolutions/_underscore` on the same
21
21
  connection ARN). Deployment target is Elastic Beanstalk.
22
22
 
23
+ ## Branch model (which branch deploys where)
24
+ The application repos (`_underscore`, `api2`, `toga2-supply`) deploy from **long-lived per-env
25
+ branches** — `_beta`, `_production` (and `_stage`, etc.) — not from `_main`. **api2 pulls
26
+ `_underscore`'s matching `_<env>` branch at EB build time**, so promoting a shared `_underscore`
27
+ change to an env means merging it into that `_underscore` `_<env>` branch (the api2 build then
28
+ picks it up). **`dbchanges2` has only `_main`** — its migrations are applied **per-environment by
29
+ the team's process**, decoupled from the app branches; a code deploy does not run migrations. So a
30
+ full feature promotion to an env = apply the `dbchanges2` migrations to that env **and** deploy the
31
+ app-repo `_<env>` branches.
32
+
23
33
  ## Steps
24
34
  1. A push to the watched branch (e.g. `_stage`) triggers the pipeline.
25
35
  2. The Source stage uses `CodeStarSourceConnection` actions, each referencing:
@@ -103,6 +113,7 @@ aws codeconnections get-connection --connection-arn "<CONN_ARN>" --region "$REGI
103
113
  ```
104
114
 
105
115
  ## Change history
116
+ - 2026-07-14 — Documented the branch model: app repos (`_underscore`/`api2`/`toga2-supply`) deploy from long-lived `_beta`/`_production` branches (not `_main`); api2 pulls `_underscore`'s `_<env>` branch at EB build; `dbchanges2` has only `_main` and its migrations are applied per-env by the team process (not by a code deploy). (mhammontree)
106
117
  - 2026-06-18 — Added two EB-instance gotchas surfaced during the TOGa Supply beta/prod label deploys: (1) terminated instances must be **manually re-registered** as LB targets (we don't pay for auto-registration) — until then the new code never serves traffic and looks like deploy-lag; (2) on-instance `composer require` stopgap syntax (no space after the colon, fix root cause by committing `composer.lock`). (mhammontree)
107
118
  - 2026-06-16 — Documented after a pipeline (API-QC-Security, account 975050298201) failed every
108
119
  run at Source with "[GitHub] GitHub returned an Internal Error"; connection was AVAILABLE and
@@ -3,5 +3,5 @@
3
3
  | Doc | Summary | Files |
4
4
  |-----|---------|-------|
5
5
  | [TOGa Supply (toga2-supply) Architecture](architecture.md) | `toga2-supply` is the **React + Vite frontend** for TOGa Supply — warehouse fulfillment tooling (shipment selection, fulfill & ship against carrier APIs, NetSui | toga2-supply/src/api/toga.ts, toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx |
6
- | [Fulfill & Ship](features/fulfill-and-ship.md) | Fulfill & Ship lets a warehouse user select sales-order line items, enter serials, pick a carrier/method, and in one action: create the Item Fulfillment records | toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx, toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts, toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx, _underscore/Model/Client/ItemFulfillment.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php |
6
+ | [Fulfill & Ship](features/fulfill-and-ship.md) | Fulfill & Ship lets a warehouse user select sales-order line items, enter serials, pick a carrier/method, and in one action: create the Item Fulfillment records | toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx, toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx, toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/EditShipment/types.ts, toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx, toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts, toga2-supply/src/pages/Shipments/types.ts, toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx, toga2-supply/src/components/ui/CardTable/CardTable.tsx, toga2-supply/src/components/ui/CardTable/types.ts, toga2-supply/src/assets/pen-line.svg, _underscore/Model/Client/ItemFulfillment.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php |
7
7
  | [AWS Amplify Build & Deploy (non-prod environments)](workflows/amplify-build-and-deploy.md) | How `toga2-supply` (React + Vite) builds and deploys on **AWS Amplify**. | toga2-supply/amplify.yml, toga2-supply/.gitattributes, toga2-supply/.github/workflows/sync-stage-environments.yml, toga2-supply/.env.qc-security |
@@ -6,17 +6,24 @@ project: TOGa Supply
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-07-02
9
+ updated: 2026-07-14
10
10
  owners: [mhammontree]
11
11
  files:
12
12
  - toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx
13
13
  - toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx
14
14
  - toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx
15
+ - toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx
16
+ - toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx
15
17
  - toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts
18
+ - toga2-supply/src/pages/EditShipment/types.ts
16
19
  - toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx
17
20
  - toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx
18
21
  - toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts
22
+ - toga2-supply/src/pages/Shipments/types.ts
19
23
  - toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx
24
+ - toga2-supply/src/components/ui/CardTable/CardTable.tsx
25
+ - toga2-supply/src/components/ui/CardTable/types.ts
26
+ - toga2-supply/src/assets/pen-line.svg
20
27
  - _underscore/Model/Client/ItemFulfillment.php
21
28
  - _underscore/Trait/Netsuite/ItemFulfillment.php
22
29
  - _underscore/Component/Library/Carriers/Ups/Ups.php
@@ -59,6 +66,27 @@ GroWrk, June 2026); FedEx + UPS both need verification before prod.
59
66
  `saveShipmentToNetsuite` → `createNetsuiteItemFulfillment`, which attaches the label
60
67
  to the IF **after** creating it (the IF doesn't exist yet when the label is bought).
61
68
 
69
+ ## Edit a saved (unfulfilled) pending shipment in place (2026-07)
70
+
71
+ A saved-but-not-yet-fulfilled shipment can now be **edited in place** rather than only
72
+ re-created. Pending Shipments (`ShipmentsCardTableForm`, non-fulfilled view) shows an edit
73
+ pencil (`src/assets/pen-line.svg`, tinted `supply-blue-400` to match the trash icon) **only**
74
+ on rows where `dtSubmitted == null` (i.e. not yet pushed to NetSuite). Clicking it opens the
75
+ Edit Shipment form at `/edit-shipment?internalId=<so>&itemFulfillmentUuid=<uuid>`, rehydrated
76
+ from the saved fulfillment; **Save UPDATES the existing records** instead of POSTing a new draft.
77
+
78
+ - `getShipmentForEdit(uuid)` (`UpdateShipmentApi.ts`) loads the tracking fields + uuid,
79
+ ship-to + return addresses + their uuids, and item lines with unit serials.
80
+ - `updateShipment()` PUTs `/tracking-numbers/{uuid}`, PUTs `/addresses/{shipToUuid}`, and PUTs
81
+ the existing return address (or creates + links one). It returns the **same shape** as
82
+ `saveShipment`, so the downstream fulfill/label/print flow is unchanged.
83
+ - **v1 scope (decision, Mark):** shipment details + ship-to address + return label/address are
84
+ editable; **item lines & serial numbers are READ-ONLY**. `SelectedShipmentItemsTable` gained a
85
+ `readOnly` prop that renders serials as text, and the "all serials provided" button-enable gate
86
+ is auto-satisfied in edit mode.
87
+ - `CardTable` was made reusable for this: optional `editIcon` + `isEditButtonDisabled` props
88
+ (defaults preserve prior behavior; the shipments card is the only consumer today).
89
+
62
90
  ## Reprint (backend-combined, 2026-07)
63
91
 
64
92
  Fulfilled-shipments view (`FulfilledShipmentsPage` → `ShipmentsCardTableForm` with
@@ -126,6 +154,19 @@ the call 403s and returns no label.
126
154
  `item-fulfillment-tracking-numbers` bridge requires the bridge record's ACL logic-group
127
155
  chain to exist for the user's role, or it 403s and `itemFulfillmentTrackingNumbers` returns
128
156
  `null` (so reprint has no label). See the tracking-number-bridges doc's ACL gotcha + fix.
157
+ - **Return modal's non-address fields are an edit-trap (not persisted, not used).** On the
158
+ backend the return leg **reuses the outbound shipment's weight/carrier/method/account**
159
+ (`generateReturnLabel`: `packageWeightPounds` = outbound tracking weight; the return
160
+ `TrackingNumber`'s carrier/method/account = outbound). **Only the return ADDRESS is persisted**
161
+ (`returnAddressId`). The return modal's weight/dims/carrier fields are prefilled from the
162
+ outbound shipment **for display only** — editing them changes nothing. Follow-up: make those
163
+ fields read-only OR persist independent return dimensions.
164
+ - **Declared Cost column showed a constant "$ -" on Pending Shipments (fixed 2026-07).** The
165
+ column + formatter existed, but `getShipments` (`ShipmentsApi.ts`) never *requested*
166
+ `trackingNumber.declaredCost` and the card row-builder (`ShipmentsCardTableForm.tsx`) never
167
+ mapped it into `flattenedData`. Added the field to the query and the row map (+ `declaredCost`
168
+ on the `FlattenedData` type). A missing column that always renders empty is usually a
169
+ not-requested / not-mapped field, not a formatter bug.
129
170
  - **Two separate page components + a scroll/clip trap.** `/shipments` renders `ShipmentsPage`;
130
171
  `/fulfilled-shipments` renders `FulfilledShipmentsPage` — **separate components** (a fix to one
131
172
  does NOT touch the other; the shared list is `ShipmentsCardTableForm`). Both pages used
@@ -143,14 +184,42 @@ the call 403s and returns no label.
143
184
 
144
185
  - ~~Reprint rewire~~ — done (backend `reprintLabelsApi` combine; see Reprint section).
145
186
  - ~~Address-source decision~~ — done (`COALESCE(IF, SO)`).
146
- - Return-label flow: backend generation is done (`generateReturnLabel`; UPS ReturnService `9` /
147
- FedEx `PRINT_RETURN_LABEL`; 2nd tracking number linked via `returnTrackingNumberId` on the
148
- bridge; Ground/customer-drops-off). Remaining **frontend** polish: "needs return label" control,
149
- a return-address editable combo ("Rolodex pattern" of client locations, overridable, validated),
150
- and "return label" text on return pages of the combined PDF.
187
+ - ~~Return-label flow (Increment 3)~~ — **done end-to-end (2026-07).** Backend `generateReturnLabel`
188
+ now ships FROM the per-fulfillment return address (`returnAddressId` → Addresses/States, falling
189
+ back to the `RETURN_ADDRESS_*` config), and the frontend fulfill flow (`UpdateShipmentApi.ts`
190
+ `fulfillShipment(needsReturnLabel)` + `EditShipmentForm.tsx`) prints one **combined outbound +
191
+ return PDF**, with the return page captioned "Return Label" (`ShipmentsApi.ts` passes a
192
+ position-aligned `captions` CSV to `reprintLabelsApi`). See the carrier-shipping-labels doc.
193
+ - **Edit-mode follow-ups (v1 punts):** (a) serial-number editing in edit mode — would need
194
+ unit add/remove diffing against the API (the edit route already carries the fulfillment uuid);
195
+ (b) the return modal's weight/dims/carrier fields are an **edit-trap** — see the gotcha below.
151
196
  - UPS 35-char hardening, location-scoped inventory lookup, carrier/method on the NS IF,
152
197
  responsiveness per Figma, FedEx + UPS end-to-end verification before prod.
153
198
 
199
+ ## Deploy / provisioning requirements (per environment)
200
+
201
+ The return-label feature (TRUE-79191) needs **four** things present in a given environment or it
202
+ silently mis-behaves; treat these as the release checklist when promoting to a new env:
203
+ 1. **`ItemFulfillments.returnAddressId` column** (Client DB) — the persisted return address FK.
204
+ 2. **RecordField 2434** (Core) — the record field backing `returnAddressId`.
205
+ 3. **`generateReturnLabel` RecordScript** (Client DB) — the scripted-API dispatch grant.
206
+ 4. **Bridge ACL logic groups for records 317–322** (Client DB) — or reads 403 EZ-1; see the
207
+ tracking-number-bridges doc.
208
+
209
+ **Environment status snapshot (2026-07, TRUE-79191):** GroWrk is **not** in the beta cluster; it
210
+ exists non-prod only in **dev-sandbox** (closest to ready: has the bridge, bridge ACL logic
211
+ groups, and the `generateReturnLabel` RecordScript, but is **missing** the `returnAddressId`
212
+ column and RecordField 2434) and **client-sandbox** (far behind — no bridge at all), plus prod.
213
+ **Prod is not migrated for this feature** (missing `returnAddressId`, RecordField 2434, the
214
+ `generateReturnLabel` RecordScript, and all six bridge ACL logic groups — the 403 gap is live in
215
+ prod now).
216
+
217
+ **"Testing in prod" (PMO Aaron's call, since no client uses the feature yet) is a FULL prod
218
+ release, not a sandbox run.** It means applying all TRUE-79191 `dbchanges2` migrations to prod +
219
+ deploying code to `_production`; a live run then buys a **REAL** UPS label on Agilant account
220
+ `8696XA` (prod endpoint) and creates a **REAL** NetSuite Item Fulfillment. Plan to **void the
221
+ labels and reverse the fulfillment** afterward.
222
+
154
223
  ## Client variations
155
224
 
156
225
  None in the flow itself — but the NetSuite trait is composed into **client-specific**
@@ -159,6 +228,7 @@ not the base `_Model_Client_ItemFulfillment`. Tested with GroWrk; UPS support wa
159
228
  for Compass and is not yet in prod.
160
229
 
161
230
  ## Change history
231
+ - 2026-07-14 — TRUE-79191: added **edit-a-saved-pending-shipment-in-place** (pencil on `dtSubmitted==null` rows → `/edit-shipment`, `getShipmentForEdit`/`updateShipment` PUT existing records; item lines/serials read-only in v1; `CardTable` made reusable with `editIcon`/`isEditButtonDisabled`). Completed the Increment-3 **return-label** frontend (combined outbound+return PDF, return page captioned "Return Label" via a position-aligned `captions` CSV to `reprintLabelsApi`). Fixed the Declared Cost "$ -" column (field was never requested/mapped). Documented the return-modal edit-trap (only the return ADDRESS persists — weight/carrier/dims reuse outbound) and the per-env deploy/provisioning checklist + the "testing in prod = full prod release (real labels/NS IF)" decision. (mhammontree)
162
232
  - 2026-07-02 — Reprint rewired to the backend: `ShipmentsApi.ts` now calls `GET /v2/tracking-numbers/reprint` (`reprintLabelsApi`) for a combined base64 PDF built from the stored PNGs; removed the stale client-side `pdf-lib` merge. Return-label backend generation landed (`generateReturnLabel`, `returnTrackingNumberId` on the bridge). Ship-to address source resolved to `COALESCE(IF, SO)`. (mhammontree)
163
233
  - 2026-06-18 — PNG label-storage rework reflected on the frontend: labels now store as PNG and the PDF is built on the backend (`LabelPdf`), so the client-side `pdf-lib` reprint is stale and must be rewired to a backend generate endpoint. Fixed the Fulfilled Shipments responsiveness/clip bug (Reprint button unreachable at 100% zoom) — `overflow-scroll` → `overflow-auto` and gave `FulfilledShipmentsPage`'s outer its own scroll; documented the `/shipments` vs `/fulfilled-shipments` two-component trap and the `AuthLayout overflow-hidden` clip. (mhammontree)
164
234
  - 2026-06-16 — Drove the full beta flow green for UPS/GroWrk. Updated the save step to the `/item-fulfillment-tracking-numbers` bridge (FE commit `b5c16592d`, key `itemFulfillmentTrackingNumbers`). Added gotchas: local-FE↔deployed-beta-BE skew, `dtSubmitted` fulfilled/pending gating, `createNetsuiteItemFulfillment` orderLine fragility on partial/already-fulfilled orders, and the bridge-ACL 403 that nulls tracking/labels (reprint). (mhammontree)
@@ -5,13 +5,14 @@ apps:
5
5
  - _underscore
6
6
  - api2
7
7
  - worker2
8
+ - toga2-supply
8
9
  - dbchanges2
9
10
  project: _Underscore
10
11
  client: growrk
11
12
  type: profile
12
13
  status: active
13
- updated: 2026-06-19
14
- owners: ["rgirish"]
14
+ updated: 2026-07-14
15
+ owners: ["rgirish", "mhammontree"]
15
16
  files: []
16
17
  related:
17
18
  - clients/growrk/features/transfer-order-flow.md
@@ -20,3 +21,9 @@ related:
20
21
  ## Summary
21
22
 
22
23
  GroWrk is a 2.0 client using TOGA for inventory and order management. Their primary integration involves inventory movements between locations (warehouses, distribution points). NetSuite is the ERP. The key engineering challenge is that GroWrk historically used zero-dollar SalesOrders with holdInvoice=true in NetSuite as a workaround to represent internal inventory transfers — work is underway to replace this with a dedicated TransferOrders record type in the TOGA DB while keeping NetSuite unchanged.
24
+
25
+ GroWrk is (as far as told) the **only client on TOGa Supply's Fulfill & Ship** flow — it is the client used to drive that feature and its return-label increment (TRUE-79191) green. See the [Fulfill & Ship feature](../../2.0/apps/toga2-supply/features/fulfill-and-ship.md) and [tracking-number bridges](../../2.0/apps/_underscore/features/tracking-number-bridges.md).
26
+
27
+ ## Local dev gotchas
28
+
29
+ - **`_Model_Growrk_Unit` declares runtime custom-field columns that must physically exist on `Client_Growrk.Units`.** The model declares `c_` fields (`c_itemDescription`, `c_chargingBrick`, `c_deviceStatus`, `c_chargingCable`, `c_grade`); these are runtime custom-field columns, so a locally-drifted `Client_Growrk` DB missing them **1054s (unknown column) on any Unit load**. Add the columns to bring a local DB current.
@@ -0,0 +1,78 @@
1
+ ---
2
+ type: session
3
+ slug: bdr-build
4
+ title: BDR web funnel built through Phase 5 (scaffold to real backend)
5
+ author: tcox
6
+ repos: [bdr, ai-bdr]
7
+ framework: "2.0"
8
+ client: shared
9
+ status: active
10
+ created: 2026-07-14
11
+ updated: 2026-07-14
12
+ ---
13
+
14
+ # Session: bdr-build
15
+ **Date:** 2026-07-14
16
+ **Project/Repo:** bdr (2.0) — local `C:\WWW\BDR`, GitHub `agilantsolutions/BDR`, branch `BDR-Development`
17
+ **Task:** Execute PLAN.md Phases 0-5 of the BDR web funnel: get the repo onto GitHub, scaffold the Next.js app, and build the content layer, component library, all screens/flow, and the real HubSpot/Toga backend.
18
+
19
+ ---
20
+
21
+ ## What WORKED
22
+ - **Repo now on GitHub.** `C:\WWW\BDR` git-initialized, branched off remote `_main` (README preserved), pushed to `agilantsolutions/BDR` branch **`BDR-Development`** (developer renamed it from feature/initial-plan-and-mockup). 8 commits: `3a1db6b` plan+mockup import (323 files, `.claude/` gitignored), `08eaf65` PLAN.md path/registry fixes, then Phases 0-5.
23
+ - **CLI git auth PERMANENTLY FIXED on this machine.** `git config --global credential.helper manager` + one interactive `git fetch` popped the GCM browser sign-in; credentials stored. Push/fetch now work from CLI for ALL repos incl. the knowledge repo (`/capture` pushes work). The old "push via GitHub Desktop" memory was deleted as obsolete.
24
+ - **Phase 0** (`dcc3e30`): Next.js 16.2.3 + React 19.2.4 + TS scaffold mirroring `info`'s config. Mockup `styles.css` ported as `src/app/studio.css`. `resolveCampaignId` (?campaign= -> hsCampaignId map -> `default`, slug regex `^[a-z0-9][a-z0-9-]{0,63}$`). ESLint flat-config no-em-dash rule (Literal/TemplateElement/JSXText selectors) — proven to fire. amplify.yml + .env.example.
25
+ - **Phase 1** (`960fe34`): `src/content/` schema.ts (CampaignBundle contract), provider.ts (`resolveCampaign` never throws; unknown slug serves DEFAULT content with requested id), hubspotProvider.ts stub (throws, gated on §9.10), useCampaign.tsx context hook, default.ts = mockup copy verbatim extracted by subagent. Vitest wired (server-only shimmed via alias).
26
+ - **Phase 2** (`90fd7ed`): components.jsx ported to 16+ typed client modules (Ico 27-icon registry + iconFor, AgentArt/SmoothImg/TalkingPreview, VoiceDial+VoiceAudio, ColorSelector, SwapFade with settle guards verbatim, Particles, StepRail, SynapseButton...). `src/lib/agentData.ts` (only home for accent hexes) + `assetPath.ts` (replaces ASSET()/window.__resources, preloadAgentAssets). Assets pruned per §5.8 to 6.2MB (Alex slot-1 art+talk video, walkthrough, brand SVGs).
27
+ - **Phase 3** (`64553b1`): Capabilities.tsx fully config-driven (Q&A pill rotation with mockup fade phases + same-tick click guard), thin AgentFlowRoot (accent -> :root, --mx/--my hover, scroll tint), RichText.tsx `agentize()` replaces `<agent>` token with bundle.agent.name. Schema calibrations: `chrome`, eyebrows, `qbank`, connectNote -> {label,value}.
28
+ - **Phase 4** (`85a4772`): useAgentFlow state machine (go()/back map, stepFor, modal gates, aibdr.v2 localStorage — only voice survives refresh), AutoBuild (verbatim ms timeline, lands on CAMPAIGN agent not hardcoded Alex), CallNow, Schedule (12-month, 30-min slots), Success (calling simulation + summaries + AmbientQuestions), Welcome/WelcomeStep2/EarlyAccess modals, leadActions seam stubs. Creator + TweaksPanel deliberately NOT ported (parked, §9.3/§9.7).
29
+ - **Phase 5** (`34a3910`): `src/server/` toga.ts + hubspot.ts ported from `info` with ALL PII logging stripped (identifier-only logs), validation.ts (16KB body cap, phone/uuid/ISO checks), leadSink.ts + callbackService.ts adapters, /api/call-now + /api/call-later + /api/contact route handlers (always envelope-shaped), page.tsx primes lead from ?hsContactId server-side and NEVER fails rendering, leadActions POST for real. info's dead 501 `visit` route dropped deliberately.
30
+ - **Verification discipline held every phase:** tsc + eslint + vitest + next build + live SSR curl checks before each commit. Final: **67 tests / 7 files green**. Live checks: `?campaign=healthcare` -> data-campaign="healthcare"; POST /api/call-now `{}` -> 400 envelope (not 500); missing env -> 500 envelope, funnel still renders.
31
+ - **Subagent pipeline worked well:** 4 background implementer agents (content extraction, component port, Capabilities, Phase 4 flow, Phase 5 backend) each verified before returning; main thread stayed conductor.
32
+
33
+ ## What did NOT work — DO NOT RETRY THESE
34
+ - **`sed`/`perl` in-place replacement of literal `\n` escapes through the Bash tool failed silently** (file unchanged; the `\"` expression in the same sed call DID apply — escaping is mangled through the Windows Git Bash wrapper). Fix that worked: the **Edit tool** with exact old/new strings. The mockup's styles.css lines 759 + 840 contain literal `\n` / `\"` sequences (JS-string generation artifacts) that break the CSS parser — already fixed in `src/app/studio.css`; `mockup/styles.css` left pristine (still broken) on purpose.
35
+ - **`pkill` does not kill Windows processes from Git Bash** — it exits quietly and the old `next start` keeps holding port 3000, serving a STALE build (looks like your new code didn't build). Kill via PowerShell `Get-NetTCPConnection -LocalPort 3000 | Stop-Process` or `taskkill //PID <pid> //F` (netstat to find PID).
36
+ - **The Bash tool's cwd resets to `c:\WWW` between some calls** — `npm run <script>` then fails with "Missing script" because c:\WWW has no package.json. Always `cd /c/WWW/BDR &&` first.
37
+ - **Pre-commit path scan regex missed `c:\WWW\...` single-backslash absolute paths** (pattern only matched escaped/forward-slash forms) — PLAN.md was pushed with machine paths in it (git-workflow violation), fixed in follow-up `08eaf65`. Scan for `[A-Za-z]:[\\/]` case-insensitively next time.
38
+ - **ESLint linted `mockup/**` (110 errors)** until `mockup/**` was added to globalIgnores — the prototype is reference material, not shipped code.
39
+ - **CLI push/fetch without GCM sign-in**: `fatal: could not read Username` — resolved permanently (see What WORKED); do not fall back to GitHub Desktop workflows.
40
+
41
+ ## Not tried yet (candidates for next session)
42
+ - **§9.10 decision (gates Phase 6):** how campaign content is modeled in HubSpot (HubDB likely vs custom object; nested Q&A pool/sets/callSummaries are the hard part). Needs the HubSpot instance owner. Then: implement hubspotProvider (fetch by slug + map + revalidation cache + no-em-dash normalization), seed campaign 1 from default.ts, slim DEFAULT to engineering fallback.
43
+ - **Phase 6:** second campaign (healthcare proof points already in the Q pool) proving zero-code campaign adds.
44
+ - **Phase 7:** pixel-parity pass vs mockup screens/screenshots, GA4 (react-ga4 installed, not wired), accessibility.
45
+ - **Phase 8:** Amplify SSR app creation + env vars (values from info's deployment), `togatech` integration mechanism (§9.6), PR + merge strategy for `BDR-Development` -> `_main`.
46
+ - **Local run QA:** developer was about to `npm run dev` and walk the funnel; feedback may yield fidelity fixes.
47
+ - Success screen consuming `submitOk` (currently exposed by useAgentFlow, not yet surfaced in UI).
48
+
49
+ ## Current file state
50
+ | File | Status | Notes |
51
+ |------|--------|-------|
52
+ | `C:\WWW\BDR` (whole repo) | 8 commits pushed to `BDR-Development` | Working tree clean at `34a3910`. No PR opened (developer said "no PR to do yet"). |
53
+ | `src/app/` | layout + page (server: resolve slug -> bundle -> lead prime) + studio.css (fixed) + api/{call-now,call-later,contact} | |
54
+ | `src/content/` | schema.ts, default.ts (mockup copy interim), provider.ts, hubspotProvider.ts (throwing stub), useCampaign.tsx | |
55
+ | `src/components/`, `src/flow/`, `src/server/`, `src/lib/` | Complete per phases 2-5 | Creator/TweaksPanel not ported (parked). |
56
+ | `test/` (7 files, 67 tests) | All green | Includes route validation, CST formatting, slots, phone. |
57
+ | `knowledge/2.0/apps/ai-bdr/*` (team repo) | NOT yet re-synced with Phase 3/4 schema calibrations or build progress | `/capture` pending — run it next session start or after QA. |
58
+
59
+ ## Decisions made
60
+ - **No Tailwind** (deviation from mirroring info): Tailwind 4's preflight reset would fight the mockup's hand-authored CSS and threaten pixel parity; PLAN §5.1 makes it optional. Rejected: including it for config parity.
61
+ - **DEFAULT bundle carries the mockup's copy verbatim as interim dev content** (documented in default.ts header) until HubSpot is seeded post-§9.10, then slim to engineering fallback. Rejected: building screens against lorem-ipsum minimal DEFAULT (no parity possible).
62
+ - **Schema calibrated by building, not upfront:** Phase 3/4 added chrome, qbank, eyebrows, earlyAccess/phone/recap groups, connectNote {label,value}, template tokens `<agent>/<date>/<tz>/<time>/<detail>`. The §6 sketch was a starting point; the code schema is now the contract.
63
+ - **AutoBuild lands on `bundle.agent`**, not hardcoded Alex — agent identity is campaign config (PLAN §2.2 design implication).
64
+ - **info's `visit` route dropped** (permanent 501 stub, no caller): dead attack surface. Recorded in contact route header.
65
+ - **PII logging stripped at port time** (info debt): identifier-only logs everywhere; Toga error paths strip query strings (contact lookup carries email in query).
66
+ - **`.claude/` harness gitignored** in the BDR repo (machine-local, installed via npx toga-ai; committing snapshots the whole KB stale).
67
+ - **GCM one-time sign-in** chosen over GitHub Desktop-only pushes: fixes CLI push machine-wide, permanently.
68
+
69
+ ## Blockers
70
+ - **§9.10 HubSpot content mechanism undecided** — gates hubspotProvider + campaign seeding (Phase 6). Owner: whoever runs the HubSpot instance.
71
+ - **First-campaign direction/copy from leadership** still pending (fills bundle 1, doesn't block engine work).
72
+ - **Real-call testing needs env values** (HUBSPOT_ACCESS_TOKEN + 4 TOGA_* vars) from info's deployment — deliberate action, hits live Toga and can trigger an actual callback.
73
+
74
+ ## Exact next step
75
+ > `cd C:\WWW\BDR && npm run dev`, open http://localhost:3000, walk the full funnel (Welcome -> Build my agent -> AutoBuild -> Capabilities -> Call Now/Schedule -> Success) side-by-side with `mockup/AI BDR (standalone).html`, and note fidelity gaps for the Phase 7 parity pass. Then run `/capture` to re-sync the ai-bdr knowledge docs (schema calibrations + build progress).
76
+
77
+ ---
78
+ _Saved by /session-save on 2026-07-14_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.327",
3
+ "version": "1.0.329",
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",