diff --git a/API.md b/API.md index d5f689d..ef31d6e 100644 --- a/API.md +++ b/API.md @@ -43,11 +43,13 @@ The main HTTP client for communicating with the Hellotext API. Makes an HTTP request to the Hellotext API. **Parameters:** + - `$method` - HTTP method (GET, POST, PATCH, PUT, DELETE) - `$path` - API endpoint path - `$data` - Request payload **Returns:** + ```php [ 'request' => [ @@ -61,6 +63,7 @@ Makes an HTTP request to the Hellotext API. ``` **Example:** + ```php use Hellotext\Api\Client; use Hellotext\Constants; @@ -85,6 +88,7 @@ $response = Client::post(Constants::API_ENDPOINT_PROFILES, [ Creates a client instance with a custom API suffix. Useful for testing. **Example:** + ```php $client = Client::with_sufix('/v2'); ``` @@ -110,10 +114,12 @@ Creates a new event tracker. If no session is provided, it attempts to retrieve Tracks an event with the given action and payload. **Parameters:** + - `$action` - Event action name (use constants from `Constants::EVENT_*`) - `$payload` - Event data **Example:** + ```php use Hellotext\Api\Event; use Hellotext\Constants; @@ -151,6 +157,7 @@ Accepts either a product ID or a `WC_Product` instance. Returns the adapted product payload. **Returns:** + ```php [ 'reference' => int, // Product ID @@ -168,6 +175,7 @@ Returns the adapted product payload. ``` **Example:** + ```php use Hellotext\Adapters\ProductAdapter; @@ -192,6 +200,7 @@ public function __construct(\WC_Order $order) Returns the adapted order payload. **Returns:** + ```php [ 'reference' => int, // Order ID @@ -240,6 +249,7 @@ public function __construct(float|string|null $price) Returns price in cents with currency. **Returns:** + ```php [ 'amount' => int, // Price in cents @@ -260,6 +270,7 @@ public function __construct(?int $user_id, array $billing = []) ``` **Parameters:** + - `$user_id` - WordPress user ID (null for guest checkout) - `$billing` - Billing data from checkout @@ -268,12 +279,14 @@ public function __construct(?int $user_id, array $billing = []) ##### `process(): void` Executes the profile creation/association flow: + 1. Checks if profile exists 2. Creates new profile if needed 3. Associates profile with session 4. Updates session metadata **Example:** + ```php use Hellotext\Services\CreateProfile; @@ -315,6 +328,7 @@ Decrypts an encrypted session string. Sets the `hello_session` cookie with proper expiration and security flags. **Example:** + ```php use Hellotext\Services\Session; @@ -384,6 +398,39 @@ Constants::EVENT_COUPON_REDEEMED // 'coupon.redeemed' ## WordPress Hooks +The plugin registers these WooCommerce and WordPress hooks: + +| Hook | Handler | Purpose | +| --------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `woocommerce_after_single_product` | `hellotext_product_viewed` | Track `product.viewed` | +| `woocommerce_after_cart` | `hellotext_trigger_cart_updated` | Compare current and previous cart state | +| `woocommerce_add_to_cart` | `hellotext_trigger_cart_updated` | Compare current and previous cart state | +| `woocommerce_cart_item_removed` | `hellotext_trigger_cart_updated` | Compare current and previous cart state | +| `woocommerce_after_cart_item_quantity_update` | `hellotext_trigger_cart_updated` | Compare current and previous cart state | +| `woocommerce_applied_coupon` | `hellotext_coupon_redeemed` | Track valid `coupon.redeemed` events | +| `woocommerce_after_order_details` | `hellotext_order_placed` | Track `order.placed` and persist encrypted session metadata on the order; render-based hook, so duplicate prevention is required | +| `woocommerce_order_status_changed` | `track_order_status` | Track `order.confirmed`, `order.cancelled`, and `order.delivered` | +| `woocommerce_order_refunded` | `hellotext_refund_created` | Track `refund.received` | +| `user_register` | `hellotext_user_registered` | Track customer registration/profile flow | +| `hellotext_woocommerce_cart_updated` | `hellotext_cart_updated` | Track `cart.added` and `cart.removed` | +| `update_option` | `custom_field_updated` | Recreate integration after Business ID changes | +| `admin_init` | `hellotext_settings_init` | Register plugin settings | +| `admin_head` / `wp_head` | `hellotext_script` | Inject frontend/admin scripts | + +## WooCommerce Compatibility + +Compatibility posture as of 2026-06-11. See [WooCommerce Compatibility and API Audit](docs/WOOCOMMERCE-AUDIT.md) for the full hook/API audit, HPOS assessment, compatibility matrix, and release recommendations. + +| Area | Status | Notes | +| ------------------------------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| WooCommerce order metadata | HPOS-aligned metadata access | Uses `WC_Order` metadata CRUD for Hellotext session metadata. | +| Order status and refund events | HPOS-aligned metadata access | Reads session metadata from the order object instead of `get_post_meta()`. | +| Product, cart, coupon events | Public hook/API usage | Uses WooCommerce hooks and objects, not order storage internals. | +| Automated tests | Mock-backed unit coverage | Event tests cover outbound payloads without real WordPress/WooCommerce runtime or HPOS datastore coverage. | +| Runtime verification | Required before declaration | Test with HPOS enabled and disabled in a real WooCommerce site before declaring formal compatibility in the plugin header/runtime. | + +Do not add a formal HPOS compatibility declaration until the release candidate has passed runtime checks on WooCommerce with HPOS enabled and disabled. + ### Actions #### `hellotext_create_profile` @@ -391,9 +438,11 @@ Constants::EVENT_COUPON_REDEEMED // 'coupon.redeemed' Triggers profile creation/association. **Parameters:** + - `$payload` - Either user ID (int) or billing data (array) **Usage:** + ```php // For logged-in user do_action('hellotext_create_profile', $user_id); @@ -431,6 +480,7 @@ The plugin respects the following environment variables: - `HELLOTEXT_API_URL` - Override API URL (development only) **Example (.htaccess):** + ```apache SetEnv APP_ENV development SetEnv HELLOTEXT_API_URL https://api-dev.hellotext.com @@ -454,6 +504,7 @@ try { ### Authentication All API requests include an `Authorization: Bearer` header with either: + - **Business ID** for event tracking - **Access Token** for profile/session management diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 10af1bb..f944d0d 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -46,6 +46,7 @@ composer install ``` This installs: + - Pest (testing framework) - Mockery (mocking library) - WordPress & WooCommerce stubs (for IDE autocomplete) @@ -177,6 +178,35 @@ The project uses [Pest](https://pestphp.com/) for testing. ./vendor/bin/paratest ``` +The Composer aliases used by CI and maintainers are: + +```bash +composer install +composer test +composer format:check +composer build +``` + +`composer build` installs production dependencies with `--no-dev --optimize-autoloader`. Do not use the build output for local development without reinstalling dev dependencies afterward. + +### Verified Local Flow + +Last verified: 2026-06-11 + +| Command | Result | Notes | +| ----------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `composer install` | Passed | Requires PHP 8.2+ and Composer 2. The local system Composer emitted PHP deprecation notices under PHP 8.4; dependencies still installed correctly. | +| `composer test` | Passed | Pest suite runs against WordPress/WooCommerce mocks, not a real WordPress install. | +| `composer format:check` | Passed | PHP CS Fixer warned when run under PHP 8.4 because the Composer platform is PHP 8.2.12. CI runs the style check on PHP 8.2. | +| `composer build` | Passed | Runs `composer install --no-dev --optimize-autoloader` and removes dev tooling from `vendor/`. Run `composer install` again afterward before continuing local development. | + +Setup assumptions: + +- PHP 8.2 or newer is available locally. +- Composer can install from the checked-in `composer.lock`. +- Tests do not require a real WordPress, WooCommerce, database, or Hellotext API connection. +- Outbound HTTP in tests is mocked through WordPress HTTP function stubs. + ### Writing Tests #### Unit Tests @@ -312,41 +342,45 @@ add_action('all', function($hook) { ### Pre-Release Checklist -- [ ] Run all tests: `./vendor/bin/pest` -- [ ] Check for PHP errors/warnings -- [ ] Test on fresh WordPress installation -- [ ] Test with WooCommerce latest version -- [ ] Verify settings page functionality -- [ ] Test event tracking in Hellotext dashboard -- [ ] Update documentation if API changed -- [ ] Update changelog.txt +- [ ] Confirm the version in `hellotext.php` matches the release tag. +- [ ] Update `changelog.txt` with user-facing changes, compatibility notes, and any known limitations. +- [ ] Review open dependency PRs and confirm there are no urgent security/runtime updates pending. +- [ ] Run `composer install` from a clean checkout. +- [ ] Run `composer test` and confirm all tests pass. +- [ ] Run `composer format:check` and confirm no style diff is reported. +- [ ] Run `composer build` and confirm production dependencies install with `--no-dev --optimize-autoloader`. +- [ ] Inspect the production `vendor/` tree enough to confirm dev-only packages such as Pest, Mockery, stubs, PHPUnit, and PHP CS Fixer are not included in the release build. +- [ ] Verify `.distignore` excludes development files from the release zip: `.github/`, `tests/`, `composer.json`, `composer.lock`, `DEVELOPMENT.md`, and `API.md`. +- [ ] Smoke test the plugin zip in a clean WordPress/WooCommerce site. +- [ ] Confirm settings save correctly: Business ID, access token, webchat ID, placement, and behavior. +- [ ] Confirm script/webchat injection renders on the storefront when configured. +- [ ] Smoke test tracking for product view, cart add/remove, coupon redemption, checkout/order placement, order status change, refund, user registration, plugin activation, and plugin deactivation. +- [ ] Smoke test classic template pages and WooCommerce Cart/Checkout blocks separately for product, cart, and checkout coverage. +- [ ] Smoke test order placement, order status, and refund flows with WooCommerce HPOS enabled and disabled. +- [ ] Record WooCommerce API/HPOS compatibility notes in the release description if anything changed. +- [ ] Run `composer install` again after build validation to restore dev dependencies before more local work. ### Creating a Release 1. **Tag the release:** + ```bash git tag -a v1.3.0 -m "Release version 1.3.0" git push origin v1.3.0 ``` 2. **Build release package:** -```bash + +````bash # Remove dev dependencies composer install --no-dev -# Create zip -cd .. -zip -r hellotext-wordpress-1.3.0.zip hellotext-wordpress \ - -x "hellotext-wordpress/.git/*" \ - -x "hellotext-wordpress/tests/*" \ - -x "hellotext-wordpress/node_modules/*" -``` - -3. **Create GitHub release:** - - Go to Releases → Draft new release - - Select the tag - - Upload the zip file - - Add release notes from changelog +3. **Verify the generated release:** + - Download the release zip from GitHub. + - Confirm files excluded by `.distignore` are not included: `.github/`, `tests/`, `composer.json`, `composer.lock`, `DEVELOPMENT.md`, and `API.md`. + - Confirm runtime files are included: `hellotext.php`, `src/`, `vendor/`, `README.md`, and `changelog.txt` if present. + - Install the zip in a clean WordPress/WooCommerce site. + - Confirm the release asset installs and activates without PHP warnings in `debug.log`. ### Post-Release @@ -354,18 +388,38 @@ zip -r hellotext-wordpress-1.3.0.zip hellotext-wordpress \ 2. Announce release to team 3. Monitor error logs for issues +### Dependency Update Triage + +Use this checklist before merging dependency-only PRs: + +- Confirm the diff is limited to dependency metadata or the expected workflow file. +- Confirm GitHub reports the PR as mergeable. +- Confirm required CI checks pass. +- Prefer merging patch/minor test stub updates independently from runtime code changes. +- For GitHub Action major updates, inspect the action release notes before merging. + +Dependency PRs reviewed during this maintenance pass: + +- Keep dependency-only lockfile refreshes separate from runtime compatibility changes. +- Prefer one broad lock refresh over multiple older overlapping Dependabot PRs when it carries newer compatible versions and CI passes. +- For GitHub Action major updates, inspect the action release notes and verify the generated zip on the next tagged release because release publishing only runs on tags. + +See also [WooCommerce Compatibility and API Audit](docs/WOOCOMMERCE-AUDIT.md) for hook, HPOS, and release compatibility notes. + ## Contributing ### Workflow 1. **Fork & Clone** + ```bash git clone https://github.com/YOUR_USERNAME/hellotext-wordpress.git cd hellotext-wordpress composer install -``` +```` 2. **Create Feature Branch** + ```bash git checkout -b feature/my-new-feature ``` @@ -376,17 +430,20 @@ git checkout -b feature/my-new-feature - Update documentation 4. **Run Tests** + ```bash ./vendor/bin/pest ``` 5. **Commit** + ```bash git add . git commit -m "feat: add new feature" ``` Use [Conventional Commits](https://www.conventionalcommits.org/): + - `feat:` - New feature - `fix:` - Bug fix - `docs:` - Documentation @@ -394,6 +451,7 @@ Use [Conventional Commits](https://www.conventionalcommits.org/): - `refactor:` - Code refactoring 6. **Push & PR** + ```bash git push origin feature/my-new-feature ``` @@ -458,6 +516,7 @@ function hellotext_track_new_action($data): void { **Issue**: Mockery errors or WordPress function not found **Solution**: Ensure WordPress and WooCommerce stubs are installed: + ```bash composer require --dev php-stubs/wordpress-stubs php-stubs/woocommerce-stubs ``` diff --git a/README.md b/README.md index 9f0a551..9e83b36 100644 --- a/README.md +++ b/README.md @@ -21,31 +21,31 @@ Download **[the latest version](https://github.com/hellotext/hellotext-wordpress ## Installation -Visit the control panel of your WordPress site where you manage your WooCommerce store, and from the *Plugins* section, click on *Add New Plugin*. +Visit the control panel of your WordPress site where you manage your WooCommerce store, and from the _Plugins_ section, click on _Add New Plugin_. -At the top, click on *Upload Plugin*. +At the top, click on _Upload Plugin_. -Click the button to choose the Hellotext plugin you downloaded in *.zip* format from your files. +Click the button to choose the Hellotext plugin you downloaded in _.zip_ format from your files. -Select the file from where you downloaded it (typically in the *Downloads* folder) and confirm to upload it to WordPress. +Select the file from where you downloaded it (typically in the _Downloads_ folder) and confirm to upload it to WordPress. -Click on *Install Now* to install the plugin. +Click on _Install Now_ to install the plugin. -Once installed, click on *Activate Plugin* to activate it. +Once installed, click on _Activate Plugin_ to activate it. -Your plugin is now activated. You can check that it has been correctly installed and activated from *Plugins* by clicking on *Installed Plugins*. +Your plugin is now activated. You can check that it has been correctly installed and activated from _Plugins_ by clicking on _Installed Plugins_. You should see Hellotext as shown in the image below. @@ -57,21 +57,21 @@ With the Hellotext plugin already installed, let's configure it. The first thing you need to do is obtain your business identifier in Hellotext. -From your Hellotext business panel, visit the *Settings* section and you will find it below your business name. +From your Hellotext business panel, visit the _Settings_ section and you will find it below your business name. Select and copy this identifier as you will need to add it to your WooCommerce site. -From the *Extensions* section in your WooCommerce site, click on Hellotext. +From the _Extensions_ section in your WooCommerce site, click on Hellotext. -Paste the business identifier you copied from Hellotext into the *Business ID* field. +Paste the business identifier you copied from Hellotext into the _Business ID_ field. -Go back to Hellotext and, from the *Authorizations* section, click on *Create new token*. +Go back to Hellotext and, from the _Authorizations_ section, click on _Create new token_. @@ -83,9 +83,9 @@ Once created, click on the indicated icon to copy your created token. -Now, go back to your WooCommerce panel and paste the authorization token into the *Access Token* field. +Now, go back to your WooCommerce panel and paste the authorization token into the _Access Token_ field. -Click on *Save Changes* to save the changes. +Click on _Save Changes_ to save the changes. @@ -117,12 +117,31 @@ For developers looking to integrate, extend, or contribute to this plugin: - **[API Documentation](API.md)** - Complete API reference for classes, methods, and hooks - **[Development Guide](DEVELOPMENT.md)** - Setup, testing, and contribution guidelines -### Requirements +- **[WooCommerce API Audit](docs/WOOCOMMERCE-AUDIT.md)** - Hook, HPOS, and compatibility audit notes + +## Requirements - PHP 8.2 or higher - WordPress 5.0 or higher - WooCommerce 5.0 or higher +## Compatibility Matrix + +| Layer | Declared support | Tested in CI | Notes | +| ----------------- | ------------------------ | --------------------------------------------------- | ---------------------------------------------------------------------------------- | +| PHP | 8.2+ | 8.2, 8.3, 8.4, 8.5 | Composer platform is pinned to PHP 8.2.12. | +| WordPress | 5.0+ | Mock-backed unit tests only, no WordPress runtime | Runtime smoke testing is required before release. | +| WooCommerce | 5.0+ | Mock-backed unit tests only, no WooCommerce runtime | HPOS, Cart/Checkout blocks, and block-theme behavior require manual smoke testing. | +| WooCommerce stubs | Not a runtime dependency | Locked through Composer dev dependencies | Used for development/test confidence only. | +| Release package | GitHub tag workflow | Tag workflow only runs on `v*` tags | Verify the generated zip contents before publishing. | + +## Compatibility Notes + +- Order session metadata uses WooCommerce order CRUD methods instead of direct post meta APIs. +- Before each release, test event tracking with WooCommerce HPOS enabled and disabled. +- Classic template hooks and WooCommerce Cart/Checkout blocks should be smoke tested separately. +- Formal WooCommerce HPOS compatibility declaration is deferred until manual runtime smoke testing passes. + ## Support Need help? diff --git a/docs/WOOCOMMERCE-AUDIT.md b/docs/WOOCOMMERCE-AUDIT.md new file mode 100644 index 0000000..3f23d54 --- /dev/null +++ b/docs/WOOCOMMERCE-AUDIT.md @@ -0,0 +1,97 @@ +# WooCommerce Compatibility and API Audit + +Last reviewed: 2026-06-11 + +This audit covers the WooCommerce and WordPress integration points used by the Hellotext WooCommerce plugin. It is intentionally maintenance-focused: it documents current hooks, validates order access against current WooCommerce HPOS guidance, and records practical release risks without changing Hellotext API contracts. + +## References + +- WooCommerce APIs overview: +- WooCommerce block hooks reference: +- WooCommerce HPOS extension recipe book: +- WooCommerce Code Reference: +- WordPress Plugin Handbook hooks and activation/deactivation APIs: + +## Summary + +The plugin uses WooCommerce PHP hooks and WooCommerce objects for the customer activity it tracks. Order session metadata access follows HPOS guidance where the plugin uses `wc_get_order()`, `$order->get_meta()`, `$order->update_meta_data()`, and `$order->save()` instead of direct post meta functions. + +This is not a full runtime compatibility claim. The current tests use mocks and do not prove behavior against a real WooCommerce HPOS datastore, Cart/Checkout blocks, or block themes. + +Do not declare HPOS compatibility yet. Add the declaration only after a manual runtime smoke test passes with WooCommerce HPOS enabled and disabled in a real WordPress/WooCommerce install. + +## Hook and API Matrix + +| Area | Hook/API | Handler | Current status | Notes | +| --- | --- | --- | --- | --- | +| Product views | `woocommerce_after_single_product` | `hellotext_product_viewed()` | Classic template coverage | This is a classic template hook. Confirm behavior with block themes before claiming full block-theme coverage. | +| Cart updates | `woocommerce_add_to_cart` | `hellotext_trigger_cart_updated()` | Appropriate | Mutation hook is still a valid WooCommerce cart hook. Tests cover event creation with mocks. | +| Cart removals | `woocommerce_cart_item_removed` | `hellotext_trigger_cart_updated()` | Appropriate | Tests cover `cart.removed` payloads. | +| Cart quantity changes | `woocommerce_after_cart_item_quantity_update` | `hellotext_trigger_cart_updated()` | Appropriate | Tests cover quantity increases and no-op unchanged carts. | +| Cart page diff check | `woocommerce_after_cart` | `hellotext_trigger_cart_updated()` | Works for classic cart template | This hook does not cover all Cart block render paths. Future block-specific coverage should be evaluated. | +| Coupon redemption | `woocommerce_applied_coupon` | `hellotext_coupon_redeemed()` | Appropriate | Handler validates the coupon before sending `coupon.redeemed`; tests cover valid and invalid coupons. | +| Order placement | `woocommerce_after_order_details` | `hellotext_order_placed()` | Render-based hook with duplicate risk | This hook can fire on thank-you/order details and My Account view-order screens. Add or keep an idempotency guard before relying on it, and evaluate `woocommerce_thankyou` for classic checkout plus `woocommerce_store_api_checkout_order_processed` for Checkout block support. | +| Order status changes | `woocommerce_order_status_changed` | `track_order_status()` | Appropriate | Handler maps `processing`, `cancelled`, and `completed` to Hellotext events. Uses WooCommerce order object/meta access. | +| Refunds | `woocommerce_order_refunded` | `hellotext_refund_created()` | Appropriate | Handler loads orders/refunds with WooCommerce APIs and reads session meta with `$order->get_meta()`. | +| User registration | `user_register` | `hellotext_user_registered()` | Appropriate WordPress hook | Tests cover profile creation flow with mocked HTTP. | +| Profile creation | `hellotext_create_profile` | Closure in `CreateProfile.php` | Internal plugin hook | Used by event flows to associate logged-in users/sessions. | +| Plugin deactivation | `register_deactivation_hook()` and `hellotext_remove_integration` | `hellotext_deactivate()` and closure in `AppRemoved.php` | Appropriate WordPress APIs | Tests cover DELETE request shape for integration cleanup. | +| Plugin uninstall | `register_uninstall_hook()` | `uninstall()` | Appropriate WordPress API | Cleans Hellotext options and WooCommerce API keys. | +| Settings | WordPress Settings API | `src/Misc/Settings.php` | Appropriate | Stores Business ID, access token, and webchat options using WordPress options. | +| Webchat injection | WordPress script/footer hooks | `src/Misc/Scripts.php` | Appropriate WordPress APIs | Verify rendered script manually in a real WordPress page during release smoke testing. | +| WooCommerce API keys | Direct `$wpdb` against `{$prefix}woocommerce_api_keys` | `src/Events/AppInstalled.php`, `hellotext.php` uninstall | Acceptable exception | WooCommerce API keys are not order data and are not part of HPOS order storage. No WooCommerce CRUD replacement is required for this table access. | + +## HPOS Assessment + +WooCommerce HPOS changes where order data is stored. The HPOS recipe book recommends avoiding direct WordPress post/postmeta APIs for order data and using WooCommerce CRUD APIs instead. + +The plugin's order session metadata paths are aligned with that guidance: + +- `src/Adapters/OrderAdapter.php` loads numeric orders with `wc_get_order()`. +- `src/Events/OrderPlaced.php` stores the Hellotext session with `$order->update_meta_data(Constants::META_SESSION, ...)` and `$order->save()`. +- `src/Events/OrderStatus.php` reads the stored session with `$order->get_meta(Constants::META_SESSION, true)`. +- `src/Events/RefundReceived.php` loads the order with `wc_get_order($order_id)` and reads session metadata with `$order->get_meta(Constants::META_SESSION, true)`. +- The plugin does not query `shop_order` posts or use direct post meta functions for order session metadata. + +The test suite uses WordPress/WooCommerce mocks, so it validates code behavior and request shape but not a real HPOS datastore. Because of that, the formal declaration is deferred. + +## Runtime Gaps To Smoke Test + +- Classic product page and block-theme product page behavior. +- Classic cart page and Cart block behavior. +- Classic checkout and Checkout block order placement behavior. +- Duplicate `order.placed` prevention when an order details page is revisited. +- HPOS enabled and disabled order placement, status change, and refund flows. + +## Deferred HPOS Declaration + +After a real WooCommerce smoke test passes with HPOS enabled and disabled, add this to the main plugin file: + +```php +add_action('before_woocommerce_init', function () { + if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true); + } +}); +``` + +Do not add this declaration until manual runtime testing confirms product view, cart, coupon, checkout, status transition, refund, settings, deactivation, and webchat behavior in a real store with HPOS both enabled and disabled. + +## Compatibility Matrix + +| Layer | Declared | CI-tested | Stub-tested | Assumed or manual-only | +| --- | --- | --- | --- | --- | +| PHP | README requires PHP 8.2+; Composer platform is PHP 8.2.12 | GitHub Actions runs Pest on PHP 8.2, 8.3, 8.4, and 8.5; format check on PHP 8.2 in CI | Not applicable | Local contributor machines may run newer PHP; PHP CS Fixer warns when run outside project platform. | +| WordPress | README requires WordPress 5.0+ | No full WordPress runtime in CI | `php-stubs/wordpress-stubs` is locked to 6.9.x after dependency refresh | Runtime compatibility with each supported WordPress version is manual-only. | +| WooCommerce | README requires WooCommerce 5.0+ | No full WooCommerce runtime in CI | `php-stubs/woocommerce-stubs` is locked to 10.x after dependency refresh | HPOS, Cart/Checkout blocks, and block themes require manual smoke testing. | +| Hellotext API | Existing plugin endpoints and payload contracts | HTTP calls are intercepted in tests | Not applicable | Real API authentication and dashboard ingestion require staging/production smoke testing. | +| Release package | `.github/workflows/release.yml` builds tag-triggered zip | Release workflow runs only on `v*` tags | Not applicable | Zip contents and installability must be checked after each tagged release. | + +## Recommendations + +1. Keep the HPOS declaration deferred until manual smoke testing passes with HPOS on and off. +2. Add or keep an idempotency guard around `order.placed` while `woocommerce_after_order_details` remains the hook. +3. Evaluate replacing `woocommerce_after_order_details` with a checkout-completion hook such as `woocommerce_thankyou` for classic checkout, while separately evaluating Checkout block coverage through Store API hooks. +4. Document classic-template limitations for `woocommerce_after_single_product`, `woocommerce_after_cart`, and any block-theme gaps in release notes until runtime coverage is confirmed. +5. Consider migrating cart diff state from `$_SESSION` to WooCommerce session storage (`WC()->session`) in a future compatibility-focused PR. +6. Continue using WooCommerce CRUD methods for all future order/refund metadata reads and writes.