From 03619785648919c33ec6a1aa2bc0d92da72fee56 Mon Sep 17 00:00:00 2001 From: Nikolay Strikhar Date: Mon, 24 Aug 2026 13:28:43 +0200 Subject: [PATCH 1/2] Raise the container contract floor past the namespace rename `^1.0` resolved as low as 1.0.0, where the interface is StellarWP\Container\ContainerInterface. Config and Provider import StellarWP\ContainerContract\ContainerInterface, which the package did not declare until 1.0.2 -- so a host already pinning the older line for another StellarWP package got a type hint naming a class that does not exist, and a TypeError from Config::set_container() at plugins_loaded priority 0. 1.1 rather than 1.0.2 because the floor has a second, quieter constraint: 1.0.x declares get() with no generic annotation, so every container resolution in src/ is mixed and PHPStan level 9 cannot type one of them. 1.1.0 is where `@return ($id is class-string ? T : mixed)` arrives, and it is the oldest release this library's own analysis gate passes against. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5c28716..703d790 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ }, "require": { "php": ">=7.4", - "stellarwp/container-contract": "^1.0" + "stellarwp/container-contract": "^1.1" }, "require-dev": { "codeception/module-asserts": "^1.0", From da2856c8ef3c302ca7c045d99e6ccf02a696eff9 Mon Sep 17 00:00:00 2001 From: Nikolay Strikhar Date: Mon, 24 Aug 2026 14:42:40 +0200 Subject: [PATCH 2/2] Record why the contract floor is 1.1, and why nothing resolves it in CI --- AGENTS.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 653b680..dfed12c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -429,7 +429,20 @@ jargon for mu-plugin autoloading — Packagist's top results for it are all that **Floors:** PHP `>=7.4`, WordPress 6.4 (for the `wp_admin_notice_markup` filter). WordPress is not a Composer dependency, so its floor lives in the README only. -**Production dependencies:** `stellarwp/container-contract` only. `lucatume/di52` is dev-only. +**Production dependencies:** `stellarwp/container-contract` at `^1.1`, and nothing else. `lucatume/di52` +is dev-only. + +The floor is `^1.1` because `^1.0` claims two things that are not true of this library. Below 1.0.2 +the interface is `StellarWP\Container\ContainerInterface`, so the class `Config::set_container()` +type-hints does not exist. Below 1.1.0 it exists but `get()` carries no `@template`, so every +container resolution in `src/` is `mixed` and level 9 can type none of them. Raise it, never lower +it. + +It is accurate rather than load-bearing, and does not earn a CI leg that resolves it. `uplink`, +`telemetry` and `schema` all require `^1.0`, which admits 1.1.2 — so Composer hands a real host tree +the top of the range whatever we declare, and reaching the floor takes a stale lock or an explicit +pin. A job installing the lower bound would guard a line nobody has a reason to edit, at the price +of going red whenever a dev dependency moved the contract. **Class naming is `Snake_Case`** (`Sub_Plugin`, `Conflict_Policy`, `Config_Exception`). Method names are fully spelled out; config keys are descriptive and WordPress-centric.