toga-ai 1.0.288 → 1.0.290

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.
@@ -8,6 +8,7 @@
8
8
  | [Assortment Name Translation (AssortmentTranslations sidecar)](features/assortment-name-translation.md) | Serves Assortment (product-grouping) **names** in multiple languages by adding a per-language **sidecar** table `AssortmentTranslations`, reusing the platform's | _underscore/Model/Client/AssortmentTranslation.php, dbchanges2/Client/2026-06-26a - AssortmentTranslations.sql, dbchanges2/Core/2026-06-26a - AssortmentTranslationsRecord.sql, dbchanges2/Client/2026-06-26b - AssortmentTranslationsAcl.sql |
9
9
  | [Asynchronous Query Execution (writes-only, via Worker)](features/async-query-execution.md) | `_Query` can run a **write** query asynchronously so a long/slow write does not hold a request-scoped DB connection open long enough to hit **"MySQL server has | _underscore/Query.php, worker2/Worker/Infrastructure/Database.php, worker2/Worker/Team/Transcripts.php |
10
10
  | [Carrier Shipping Labels (UPS/FedEx) & NetSuite Item Fulfillment](features/carrier-shipping-labels.md) | Backend mechanics behind TOGa Supply's Fulfill & Ship: buying a carrier label (UPS/FedEx), persisting it, and creating the NetSuite Item Fulfillment with tracki | _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Client/TrackingNumber.php, _underscore/Model/Client/ItemFulfillments/TrackingNumber.php, _underscore/Component/Library/LabelPdf/LabelPdf.php, _underscore/Component/Library/Carriers/ShipmentRequest/ShipmentRequest.php, _underscore/Component/Library/Carriers/Ups/Ups.php, _underscore/Component/Library/Carriers/Fedex/Fedex.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Trait/Netsuite/SalesOrder.php, _underscore/Component/Library/NetSuite/NetSuite.php, _underscore/Model/Client/TrackingNumber.php, _underscore/Model/Client/ShippingMethod.php, _underscore/Model.php, _underscore/Cloud.php |
11
+ | [_Component_*/_Model_* project-namespace registration (autoloader) & backslash-qualify traps](features/component-model-namespace-registration.md) | Every **project-local** `_Component_*` and `_Model_*` class in a 2.0 app **must declare the project namespace** at the top of the file: ```php namespace <NAMESP | _underscore/Loader.php, worker2/_.php, api2/_.php, worker2/Component/Forecast/Db/Db.php, worker2/Component/Forecast/SaleImport/SaleImport.php, api2/Component/Api/Netsuite/Netsuite.php |
11
12
  | [Client Email Template Sending](features/email-template-sending.md) | `_Model_Client_EmailTemplate` sends a stored, client-defined email template by UUID. | _underscore/Model/Client/EmailTemplate.php, _underscore/Model/Client/EmailTemplateOutgoingEmailAddress.php, _underscore/Email.php |
12
13
  | [Error Reporting — Issue/Event Aggregation (exceptionHandler)](features/error-reporting-issue-event.md) | `_underscore`'s global exception handler persists every uncaught exception into a two-table **Issue / Event** model in the **shared Core Logs DB** (`_underscore | _underscore/Error.php, _underscore/Model/Core/Logs/Issue.php, _underscore/Model/Core/Logs/Event.php, dbchanges2/Logs/2026-07-06 - Issue and Event tables.sql |
13
14
  | [Record-Changed Event Publishing (_Event::publish to SQS)](features/event-publish-sqs.md) | `_Event::publish()` (in `_underscore/Event.php`) is the PHP side of the real-time event pipeline. | _underscore/Event.php |
@@ -0,0 +1,102 @@
1
+ ---
2
+ title: "_Component_*/_Model_* project-namespace registration (autoloader) & backslash-qualify traps"
3
+ framework: "2.0"
4
+ repo: _underscore
5
+ project: _Underscore
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-07-08
10
+ owners: [dfranks]
11
+ files:
12
+ - _underscore/Loader.php
13
+ - worker2/_.php
14
+ - api2/_.php
15
+ - worker2/Component/Forecast/Db/Db.php
16
+ - worker2/Component/Forecast/SaleImport/SaleImport.php
17
+ - api2/Component/Api/Netsuite/Netsuite.php
18
+ related:
19
+ - ../architecture.md
20
+ - ./forecast-sale-import.md
21
+ ---
22
+
23
+ ## Summary
24
+ Every **project-local** `_Component_*` and `_Model_*` class in a 2.0 app **must declare the
25
+ project namespace** at the top of the file:
26
+
27
+ ```php
28
+ namespace <NAMESPACE>; // worker2 → 'worker', api2 → 'api'
29
+ ```
30
+
31
+ where `<NAMESPACE>` is the value of that project's `_.php` `const NAMESPACE` (worker2 =
32
+ `'worker'`, api2 = `'api'`). The `namespace` declaration **IS the "registration"** — there
33
+ is no config toggle. If the class is declared in the **global** namespace instead, the
34
+ `_underscore` autoloader throws at **class-load (runtime)**:
35
+
36
+ > The namespace for '`<Class>`' located in '`<path>`' has not been defined which is
37
+ > prohibited for all _Model and _Component classes. Define the namespace for this class and
38
+ > try again.
39
+
40
+ **This is NOT caught by `php -l`** (parse-only) — it only surfaces at autoload/runtime, so
41
+ lint-clean code can still fatally throw on the first request that touches the class.
42
+
43
+ ## How it works — `_underscore/Loader.php` (lines ~71-83)
44
+ For a project-local `_Component_*` / `_Model_*` class the autoloader:
45
+ 1. `require`s the local file.
46
+ 2. Checks whether the class **also** exists under the project namespace
47
+ (`<NAMESPACE>\<Class>`).
48
+ 3. **If yes** → `eval`s a bridge class in the global namespace
49
+ (`class <Class> extends <NAMESPACE>\<Class> {}`, Loader.php:79-80) so callers can use the
50
+ bare `_Component_Foo` name.
51
+ 4. **If no** (class was declared globally, so `<NAMESPACE>\<Class>` doesn't exist) → **throws**
52
+ the "namespace … has not been defined" error above.
53
+
54
+ **Correct precedent to copy:** `api2/Component/Api/Netsuite/Netsuite.php` —
55
+ `namespace api;` + `class _Component_Api_Netsuite extends \_Component` + `\_Config::netsuite(...)`,
56
+ `new \_ApiRequest(...)`.
57
+
58
+ ### Framework references inside a namespaced file — what resolves vs. what must be backslash-qualified
59
+ Once the file is in `namespace <NAMESPACE>;`, **static calls and constants** to framework
60
+ classes resolve transparently via the autoloader's namespace fallback (Loader.php ~94-120),
61
+ bridged as `<NAMESPACE>\_X` → the framework class — e.g. `_Time::convert(...)`,
62
+ `_underscore::DB_FORECAST`, `_Component_Api_Netsuite::send(...)`, `new _Query(...)` all work
63
+ unqualified.
64
+
65
+ **Three constructs do NOT get that treatment and MUST be backslash-qualified:**
66
+ - `catch (\Exception $e)` / `catch (\RuntimeException $e)` — unqualified `catch (Exception $e)`
67
+ resolves to the non-existent `<NAMESPACE>\Exception` and silently no-matches (or fatals).
68
+ **This silent-swallow `catch` is the most dangerous / easiest-to-miss line** — the block
69
+ never catches, so error handling quietly does nothing.
70
+ - `new \Exception(...)` / `throw new \RuntimeException(...)` — same reason.
71
+ - `extends \_Component` (and `extends \_Model` etc.) — the base class in the class declaration
72
+ must be backslash-qualified.
73
+
74
+ ## Why this matters — the Forecast SALES drift root cause
75
+ This mechanism was the root cause of the Forecast **SALES** drift observed after a worker2
76
+ push: `_Component_Forecast_SaleImport` and `_Component_Forecast_Db` had been declared in the
77
+ **global** namespace, so every NetSuite sales/invoice/opportunity webhook **fatally threw at
78
+ autoload before writing to `Forecast.Sales`**. Because NetSuite replays edits across old
79
+ transactions, the symptom **presented as ~7 months of historical drift** rather than as a
80
+ "new code broken" failure — a misleading symptom that this mechanism explains.
81
+
82
+ (The engine ultimately lives under `_underscore` — see the
83
+ [Forecast.Sales import engine doc](./forecast-sale-import.md) — precisely because a
84
+ `_Component_*` class loaded from a project path is rejected; but even a legitimately
85
+ project-local `_Component_*`/`_Model_*` must still declare the project namespace.)
86
+
87
+ ## Gotchas / known issues
88
+ - `php -l` will **not** catch a missing/global namespace or an unqualified `catch`/`throw`/
89
+ `extends` — boot the class (autoload it) to verify. A wrong autoload path is likewise a
90
+ runtime-only failure.
91
+ - A global-namespace `_Component_*`/`_Model_*` fails **loudly** (the throw above). An
92
+ unqualified `catch (Exception $e)` fails **silently** — the more insidious of the two.
93
+
94
+ ## Change history
95
+ - 2026-07-08 — Documented the `_Component_*`/`_Model_*` project-namespace registration
96
+ requirement (Loader.php eval-bridge mechanism, ~71-83), the runtime-only failure mode (not
97
+ caught by `php -l`), and the three constructs that must be backslash-qualified inside a
98
+ namespaced file (`catch`/`throw`/`new \Exception`, `extends \_Component`). Root-caused the
99
+ Forecast SALES drift to `_Component_Forecast_SaleImport`/`_Component_Forecast_Db` declared
100
+ in the global namespace (webhooks threw at autoload before writing; presented as 7-month
101
+ historical drift because NetSuite replays edits). Correct precedent:
102
+ `api2/Component/Api/Netsuite/Netsuite.php`. (dfranks)
@@ -38,6 +38,7 @@ related:
38
38
  - ../../worker2/features/netsuite-salesorder-open-orders-sync.md
39
39
  - ../../worker2/features/netsuite-supporting-record-webhook-importer.md
40
40
  - ./netsuite-rest-client.md
41
+ - ./component-model-namespace-registration.md
41
42
  ---
42
43
 
43
44
  ## Summary
@@ -135,7 +136,14 @@ This is the **opposite of the legacy cron**, which reads the pre-signed listSale
135
136
  (already `-foreignamount`) and so applies the factor **only** to the synthetic shipping
136
137
  line. **Do not copy the cron's sign handling into the webhook** — it reintroduces the
137
138
  ~$470K credit-memo sign bug (credits stored positive). The cron is not authoritative for
138
- the raw-REST path. Confirmed end-to-end against the local Forecast mirror (creditMemo
139
+ the raw-REST path.
140
+
141
+ > **Do not confuse this line-amount/revenue sign with the `amountDue` "store raw positive"
142
+ > decision (TRUE-78923).** The "store raw positive / don't sign-flip credit memos & refunds"
143
+ > guidance applies **only to `amountDue`** (which this importer does not write) — it does
144
+ > **NOT** apply to the line `amount`/revenue sign. For revenue, credit memos + cash refunds
145
+ > **must** land NEGATIVE and invoices + cash sales POSITIVE in `Forecast.Sales`; that is the
146
+ > stored contract. Mis-carrying the amountDue rule onto revenue would store credits positive. Confirmed end-to-end against the local Forecast mirror (creditMemo
139
147
  revenue stored -350..-600; cashRefund revenue -885 / profit -78; invoice positive).
140
148
 
141
149
  > A reviewer may flag "profit double-signs the factor" — false positive:
@@ -481,10 +489,25 @@ record is deleted in NetSuite.)
481
489
  (e.g. `./` under worker2) with "namespace … has not been defined" — at **class-load
482
490
  (runtime), not `php -l`**. So this engine lives in `_underscore` next to
483
491
  `_Component_Forecast_Db` even though only worker2 uses it; it references the worker2 class
484
- `_Worker_Netsuite_Item`, resolved lazily at runtime in the worker2 context.
492
+ `_Worker_Netsuite_Item`, resolved lazily at runtime in the worker2 context. **A
493
+ legitimately project-local `_Component_*`/`_Model_*` (e.g. the worker2 copies of these
494
+ classes) must still declare `namespace worker;` or it throws the same error at autoload —
495
+ and this exact global-namespace mistake caused the SALES drift (webhooks fatally threw
496
+ before writing, presenting as 7-month historical drift). See the
497
+ [namespace-registration doc](./component-model-namespace-registration.md) for the
498
+ eval-bridge mechanism and the `catch`/`throw`/`extends` backslash-qualify traps.**
485
499
  - The cron's sign handling is not portable here — see Sign convention.
486
500
 
487
501
  ## Change history
502
+ - 2026-07-08 — **Clarified the revenue sign convention is NOT the `amountDue` "store raw
503
+ positive" rule.** The TRUE-78923 "don't sign-flip credit memos/refunds" guidance applies
504
+ only to `amountDue` (which this importer does not write); the line `amount`/revenue sign
505
+ contract is unchanged — credit memos + cash refunds NEGATIVE, invoices + cash sales
506
+ POSITIVE. Also cross-linked the new
507
+ [`_Component_*`/`_Model_*` namespace-registration doc](./component-model-namespace-registration.md):
508
+ a global-namespace declaration of `_Component_Forecast_SaleImport`/`_Component_Forecast_Db`
509
+ was the root cause of the SALES drift (webhooks threw at autoload before writing; presented
510
+ as 7-month historical drift because NetSuite replays edits). (dfranks)
488
511
  - 2026-07-07 — **Documented the AMQ enqueuer's line-field inline-edit blind spot** (Forecast2 SALES
489
512
  profit-drift forensics; invoice 6715127 / 2026-02-20 / $3,392.70). Editing a **sublist LINE
490
513
  field** (e.g. cost `TRANLINE.MCOSTESTIMATE`) inline in the NetSuite UI raises **no** record UE
@@ -5,9 +5,12 @@ project: _Underscore
5
5
  client: shared
6
6
  type: standard
7
7
  status: active
8
- updated: 2026-07-02
8
+ updated: 2026-07-08
9
9
  owners: [mhammontree]
10
- files: []
10
+ files:
11
+ - _underscore/Query.php
12
+ - _underscore/Database.php
13
+ - _underscore/Environment.php
11
14
  related:
12
15
  - ../apps/_underscore/architecture.md
13
16
  - ../apps/_underscore/features/per-client-database-connections.md
@@ -27,12 +30,22 @@ From a 2.0 app root (e.g. `worker2`): `chdir` into the app, require Composer aut
27
30
  `_underscore.php`, and set `ENVIRONMENT` before bootstrap:
28
31
 
29
32
  ```php
33
+ putenv('ENVIRONMENT=dev-markhammontree-laptop'); // REQUIRED, before requiring _underscore.php
34
+ // e.g. dev-<yourname>-laptop — matches your Config/<ENVIRONMENT>.ini
30
35
  chdir('/path/to/worker2');
31
36
  require 'vendor/autoload.php';
32
37
  require '_underscore.php'; // boots Loader/Config/etc.
33
- // ENVIRONMENT must be set (env var / server) so _Config picks the right INI
34
38
  ```
35
39
 
40
+ - **`ENVIRONMENT` is mandatory.** The bootstrap uses it to select `worker2/Config/<ENVIRONMENT>.ini`.
41
+ If it is unset, `_underscore.php` throws *"The environment variable 'ENVIRONMENT' is required and
42
+ has not been set"* (`_underscore/Environment.php:12`). Set it via `putenv(...)` in the script
43
+ before the `require`, or export it in the shell.
44
+ - **On Windows the shell is PowerShell** — set env vars as `$env:VAR='x'; php script.php`, **not**
45
+ the bash `VAR=x php script.php` prefix. The bash-style prefix silently does nothing in
46
+ PowerShell, so the script falls back to its defaults (a confusing "it ran but used the wrong
47
+ config" failure).
48
+
36
49
  ## You MUST pin the client DB explicitly
37
50
 
38
51
  `_underscore::DB_CLIENT` is a **logical alias**, not a schema name — there is no database literally
@@ -51,8 +64,41 @@ Without this, any `Model/Client/*` query resolves the unmapped alias and fails.
51
64
  schema you have locally/on the target env (internal testing uses `Client_True` = TOGA Technology).
52
65
  Remember the per-client **logs** connection trap too (see the per-client-database-connections doc).
53
66
 
67
+ ## Commit before you read your own writes (lazy-transaction trap)
68
+
69
+ Standalone scripts run under `_underscore`'s **lazy-transaction model with a separate read
70
+ connection**, so a write is invisible to a later read — and to the code under test — until it is
71
+ committed. Concretely:
72
+
73
+ - `_Database::register(..., alias: _underscore::DB_CLIENT)` sets up a pending transaction for that
74
+ DB. The **first** write (via `_Query`) flips autocommit **OFF** and opens the transaction
75
+ (`_underscore/Query.php` ~303–304, keyed by the database value passed to `_Query`).
76
+ - INSERTs therefore sit **uncommitted**. A subsequent `SELECT` on the read connection returns
77
+ nothing, so a read-back-by-marker returns `null` and dependent FK inserts fail (classic symptom:
78
+ `saleItemId = 0` FK violation).
79
+
80
+ **Pattern:** after seeding base rows, call
81
+ `_Database::transactionCommit(_underscore::DB_CLIENT)` (`_underscore/Database.php` ~165–212). This
82
+ commits **and** restores `autocommit(true)`, so all later writes — and reads of them — behave
83
+ normally. Order your script:
84
+
85
+ 1. seed base rows →
86
+ 2. **commit** →
87
+ 3. read ids back →
88
+ 4. insert dependent rows →
89
+ 5. assert →
90
+ 6. cleanup — and **commit the cleanup too**, so the `DELETE`s persist rather than being rolled
91
+ back when the script exits.
92
+
93
+ This is the same lazy-transaction write-drop family noted in the `_underscore` architecture doc;
94
+ it bites the standalone-script/verification case specifically. Demonstrated working in
95
+ `test/@Mark/Rate/verify_wholehome_per_address_guard.php`.
96
+
54
97
  ## Rules
55
98
 
56
99
  - Do not add or assume a PHPUnit suite for 2.0 backend work; write a `test`-repo script instead.
100
+ - Always set `ENVIRONMENT` before bootstrap (PowerShell: `$env:ENVIRONMENT='...'`, or `putenv`).
57
101
  - Always pin the concrete `Client_<Id>` schema to `DB_CLIENT` (and logs/archive if the code logs).
102
+ - **Commit seeded rows before you read them back** — the read connection cannot see uncommitted
103
+ writes; commit cleanup too so it persists.
58
104
  - Keep scripts in your per-dev `test` folder; never point them at production databases.
@@ -17,7 +17,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
17
17
 
18
18
  ## 2.0 framework
19
19
 
20
- - **_underscore** (_Underscore) _(framework core)_ — 25 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
20
+ - **_underscore** (_Underscore) _(framework core)_ — 26 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
21
21
  - **worker2** (Worker) — 27 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
22
22
  - **api2** (API) — 10 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
23
23
  - **dbchanges2** (Database Changes) _(framework core)_ — 3 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
@@ -8,5 +8,5 @@
8
8
  | [Rate SAML SSO](features/saml-sso.md) | 2.0 | Rate uses Azure AD as its IdP (`login.rate.com`). | _underscore/Model/Rate/ClientAuthentication.php, saml/Controller/Index.php, toga2-view/src/hooks/useAuthenticationFlow.ts |
9
9
  | [Service Card Entitlement Display](features/service-card-entitlements.md) | 2.0 | Rate's home and services pages display one service card per purchased entitlement. | src/components/ServiceCard/ServiceCard.tsx, src/components/ServiceCard/index.ts, src/hooks/useBundleServices.ts, src/pages/Home/api/homeApi.ts, src/pages/Home/view/HomePage.tsx, src/pages/Home/viewModels/useHomePageViewModel.ts, src/pages/Services/view/ServicesPage.tsx, src/pages/Services/viewModels/useServicePageViewModel.ts |
10
10
  | [Rate Service-Purchase Confirmation Emails (Tech / Warranty)](features/service-purchase-emails.md) | 2.0 | When a Rate customer purchases a service, a confirmation email is sent. | _underscore/Model/Rate/Entitlement.php, worker2/Worker/Notification/EmailTemplate.php, dbchanges2/Client_Rate/2026-06-30a - Rate purchase email templates.sql |
11
- | [Rate Whole Home Warranty Per-Address Purchase Guard](features/whole-home-warranty-purchase-guard.md) | 2.0 | A customer may hold **one active Whole Home Warranty (WH) per validated address, globally** (across all borrowers). | _underscore/Model/Rate/Entitlement.php, _underscore/Model/Client/Address.php, dbchanges2/Client_Rate/2026-07-07a - WholeHomeWarrantyPerAddressGuard.sql |
11
+ | [Rate Whole Home Warranty Per-Address Purchase Guard](features/whole-home-warranty-purchase-guard.md) | 2.0 | A customer may hold **one active Whole Home Warranty (WH) per validated address, globally** (across all borrowers). | _underscore/Model/Rate/Entitlement.php, _underscore/Model/Client/Address.php, dbchanges2/Client_Rate/2026-07-07a - WholeHomeWarrantyPerAddressGuard.sql, test/@Mark/Rate/verify_wholehome_per_address_guard.php |
12
12
  | [Rate](profile.md) | 2.0 | Rate is a mortgage/lending client. | |
@@ -6,12 +6,13 @@ project: _Underscore
6
6
  client: rate
7
7
  type: client-feature
8
8
  status: active
9
- updated: 2026-07-07
9
+ updated: 2026-07-08
10
10
  owners: [mhammontree]
11
11
  files:
12
12
  - _underscore/Model/Rate/Entitlement.php
13
13
  - _underscore/Model/Client/Address.php
14
14
  - dbchanges2/Client_Rate/2026-07-07a - WholeHomeWarrantyPerAddressGuard.sql
15
+ - test/@Mark/Rate/verify_wholehome_per_address_guard.php
15
16
  related:
16
17
  - clients/rate/profile.md
17
18
  - clients/rate/features/aig-contract-creation.md
@@ -113,6 +114,17 @@ suggested-vs-entered when `success && address1`, and a "couldn't verify" toaster
113
114
  [address-validation feature](../../../2.0/apps/_underscore/features/address-validation.md) for the
114
115
  endpoint mechanics.
115
116
 
117
+ ## Verification
118
+
119
+ A self-contained backend verification script lives at
120
+ `test/@Mark/Rate/verify_wholehome_per_address_guard.php` (run via PHP CLI with `ENVIRONMENT`
121
+ set, pinned to the real migrated **`Client_Rate`** schema — see the
122
+ [2.0 backend-testing standard](../../../2.0/standards/backend-testing.md)). It applies
123
+ `c_serviceAddressId` idempotently, seeds a token-tagged scratch WH graph (2 addresses / 2 items /
124
+ 2 active subscriptions / 2 entitlements), then exercises the pure helpers, the dedup matrix (via
125
+ reflection on the private methods), and the `prePost` branches, cleaning up in a `finally`. The
126
+ live carrier waterfall is opt-in via `RUN_LIVE=1` (defaults off). Verified **18/18 pass**.
127
+
116
128
  ## Gotchas / known issues
117
129
 
118
130
  - **TOCTOU on the uniqueness check (accepted).** The check-then-persist dedup is **not**
@@ -131,6 +143,9 @@ endpoint mechanics.
131
143
 
132
144
  ## Change history
133
145
 
146
+ - 2026-07-08 — Added a backend verification script
147
+ (`test/@Mark/Rate/verify_wholehome_per_address_guard.php`, 18/18 pass against the migrated
148
+ `Client_Rate` schema) and a Verification pointer. (mhammontree)
134
149
  - 2026-07-07 — Built the WH per-address purchase guard (TRUE-79533): `prePost` on
135
150
  `_Model_Rate_Entitlement` hard-blocks invalid addresses and second active WH at the same
136
151
  normalized address (global), adopts the carrier-normalized address onto the payload, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.288",
3
+ "version": "1.0.290",
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",