From fa39aa240ee695358799338ac451fd5b982546eb Mon Sep 17 00:00:00 2001 From: Jordan Partridge Date: Thu, 11 Jun 2026 13:19:13 -0700 Subject: [PATCH 1/2] Sanitize embeddings text and make request errors visible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ollama embeddings silently returned empty arrays on failures, masking errors like "input length exceeds the context length". Large unicode content (emoji, pictographs, box-drawing chars) blows through BERT-style tokenizers' context windows (bge-large: 512 tokens), triggering the truncation check after token expansion—silent failure by default. This commit: - Adds EmbeddingTextSanitizer to strip emoji, pictographs, zero-width chars, and smart punctuation; collapses the extra spaces left behind. Ollama sanitizes by default; OpenAI opts out for backward compatibility. - Adds EmbeddingRequestException to extract and surface provider errors (OpenAI nested error.message, Ollama flat error field, raw body fallback). Both embeddings clients now throw descriptively instead of silencing failures. - Covers all new behavior in tests; suite passes at 100% coverage. Verified end-to-end against production Ollama instance. --- src/Embeddings/EmbeddingTextSanitizer.php | 57 ++++++++++ src/Embeddings/OllamaEmbeddings.php | 14 ++- src/Embeddings/OpenAiEmbeddings.php | 14 ++- src/Exceptions/EmbeddingRequestException.php | 36 ++++++ tests/Unit/EmbeddingTextSanitizerTest.php | 48 ++++++++ tests/Unit/EmbeddingsTest.php | 114 +++++++++++++++++-- 6 files changed, 271 insertions(+), 12 deletions(-) create mode 100644 src/Embeddings/EmbeddingTextSanitizer.php create mode 100644 src/Exceptions/EmbeddingRequestException.php create mode 100644 tests/Unit/EmbeddingTextSanitizerTest.php diff --git a/src/Embeddings/EmbeddingTextSanitizer.php b/src/Embeddings/EmbeddingTextSanitizer.php new file mode 100644 index 0000000..4728b27 --- /dev/null +++ b/src/Embeddings/EmbeddingTextSanitizer.php @@ -0,0 +1,57 @@ + "'", + "\u{2018}" => "'", + "\u{201C}" => '"', + "\u{201D}" => '"', + "\u{2014}" => '-', + "\u{2013}" => '-', + "\u{2026}" => '...', + "\u{2022}" => '-', + "\u{2192}" => '->', + "\u{2190}" => '<-', + "\u{2191}" => '^', + "\u{2193}" => 'v', + ]; + + /** + * Emoji, pictographs, dingbats, box-drawing, geometric shapes, arrows, + * variation selectors, and zero-width joiners. These carry no retrieval + * signal but expand into many byte-fallback tokens on BERT-style + * tokenizers, wasting a small context window (e.g. bge-large's 512 + * tokens) and triggering Ollama's truncation miscount, which rejects + * the request with "input length exceeds the context length". + */ + private const NOISE_PATTERN = '/[\x{20E3}\x{2190}-\x{21FF}\x{2300}-\x{23FF}\x{2500}-\x{25FF}\x{2600}-\x{27BF}\x{2B00}-\x{2BFF}\x{1F000}-\x{1FAFF}]/u'; + + /** + * Zero-width characters are deleted outright rather than replaced with + * a space, since they never occupy visual space between words. + */ + private const ZERO_WIDTH_PATTERN = '/[\x{200B}-\x{200D}\x{FE00}-\x{FE0F}]/u'; + + /** + * Normalize text before embedding. Lossy by design: the sanitized text + * is only used to generate the vector, never stored. + */ + public static function sanitize(string $text): string + { + $text = strtr($text, self::REPLACEMENTS); + $text = (string) preg_replace(self::ZERO_WIDTH_PATTERN, '', $text); + $text = (string) preg_replace(self::NOISE_PATTERN, ' ', $text); + $text = (string) preg_replace('/ {2,}/', ' ', $text); + + return (string) preg_replace('/ +$/m', '', $text); + } +} diff --git a/src/Embeddings/OllamaEmbeddings.php b/src/Embeddings/OllamaEmbeddings.php index 8d19338..08477a6 100644 --- a/src/Embeddings/OllamaEmbeddings.php +++ b/src/Embeddings/OllamaEmbeddings.php @@ -7,16 +7,20 @@ use Saloon\Exceptions\Request\RequestException; use TheShit\Vector\Contracts\EmbeddingClient; use TheShit\Vector\Embeddings\Requests\OllamaEmbedRequest; +use TheShit\Vector\Exceptions\EmbeddingRequestException; class OllamaEmbeddings implements EmbeddingClient { public function __construct( protected readonly OllamaConnector $connector, protected readonly string $model = 'bge-large', + protected readonly bool $sanitize = true, ) {} /** * @return array + * + * @throws EmbeddingRequestException */ public function embed(string $text): array { @@ -32,9 +36,15 @@ public function embed(string $text): array /** * @param array $texts * @return array> + * + * @throws EmbeddingRequestException */ public function embedBatch(array $texts): array { + if ($this->sanitize) { + $texts = array_map(EmbeddingTextSanitizer::sanitize(...), $texts); + } + $texts = array_values(array_filter($texts, fn (string $t): bool => trim($t) !== '')); if ($texts === []) { @@ -44,8 +54,8 @@ public function embedBatch(array $texts): array try { $response = $this->connector->send(new OllamaEmbedRequest($this->model, $texts)); $response->throw(); - } catch (RequestException) { - return array_fill(0, count($texts), []); + } catch (RequestException $exception) { + throw EmbeddingRequestException::fromSaloon($this->model, $exception); } /** @var array> $embeddings */ diff --git a/src/Embeddings/OpenAiEmbeddings.php b/src/Embeddings/OpenAiEmbeddings.php index 655e089..bf27df5 100644 --- a/src/Embeddings/OpenAiEmbeddings.php +++ b/src/Embeddings/OpenAiEmbeddings.php @@ -7,6 +7,7 @@ use Saloon\Exceptions\Request\RequestException; use TheShit\Vector\Contracts\EmbeddingClient; use TheShit\Vector\Embeddings\Requests\OpenAiEmbedRequest; +use TheShit\Vector\Exceptions\EmbeddingRequestException; class OpenAiEmbeddings implements EmbeddingClient { @@ -14,10 +15,13 @@ public function __construct( protected readonly OpenAiConnector $connector, protected readonly string $model = 'text-embedding-3-large', protected readonly ?int $dimensions = null, + protected readonly bool $sanitize = false, ) {} /** * @return array + * + * @throws EmbeddingRequestException */ public function embed(string $text): array { @@ -33,9 +37,15 @@ public function embed(string $text): array /** * @param array $texts * @return array> + * + * @throws EmbeddingRequestException */ public function embedBatch(array $texts): array { + if ($this->sanitize) { + $texts = array_map(EmbeddingTextSanitizer::sanitize(...), $texts); + } + $texts = array_values(array_filter($texts, fn (string $t): bool => trim($t) !== '')); if ($texts === []) { @@ -45,8 +55,8 @@ public function embedBatch(array $texts): array try { $response = $this->connector->send(new OpenAiEmbedRequest($this->model, $texts, $this->dimensions)); $response->throw(); - } catch (RequestException) { - return array_fill(0, count($texts), []); + } catch (RequestException $exception) { + throw EmbeddingRequestException::fromSaloon($this->model, $exception); } /** @var array}> $data */ diff --git a/src/Exceptions/EmbeddingRequestException.php b/src/Exceptions/EmbeddingRequestException.php new file mode 100644 index 0000000..435c3ff --- /dev/null +++ b/src/Exceptions/EmbeddingRequestException.php @@ -0,0 +1,36 @@ +getResponse(); + $status = $response->status(); + + try { + // OpenAI nests the message ({"error": {"message": ...}}), Ollama + // returns it flat ({"error": ...}). + $error = $response->json('error.message') ?? $response->json('error'); + } catch (JsonException) { + $error = null; + } + + if (! is_string($error) || $error === '') { + $error = $response->body(); + } + + return new self( + "Embedding request failed for model [{$model}] (HTTP {$status}): {$error}", + $status, + $exception, + ); + } +} diff --git a/tests/Unit/EmbeddingTextSanitizerTest.php b/tests/Unit/EmbeddingTextSanitizerTest.php new file mode 100644 index 0000000..07a1a15 --- /dev/null +++ b/tests/Unit/EmbeddingTextSanitizerTest.php @@ -0,0 +1,48 @@ +toBe($text); + }); + + it('strips emoji and pictographs', function (): void { + expect(EmbeddingTextSanitizer::sanitize("Fleet \u{1F692} module"))->toBe('Fleet module') + ->and(EmbeddingTextSanitizer::sanitize("done \u{2705} failed \u{274C}"))->toBe('done failed'); + }); + + it('strips variation selectors and zero-width joiners', function (): void { + expect(EmbeddingTextSanitizer::sanitize("plain\u{FE0F} text\u{200D}here"))->toBe('plain texthere'); + }); + + it('normalizes smart punctuation to ascii', function (): void { + expect(EmbeddingTextSanitizer::sanitize("\u{201C}it\u{2019}s fine\u{201D} \u{2014} mostly\u{2026}")) + ->toBe('"it\'s fine" - mostly...'); + }); + + it('converts common arrows to ascii', function (): void { + expect(EmbeddingTextSanitizer::sanitize("Service \u{2192} Action \u{2192} Data")) + ->toBe('Service -> Action -> Data'); + }); + + it('strips box drawing characters from ascii trees', function (): void { + expect(EmbeddingTextSanitizer::sanitize("\u{251C}\u{2500}\u{2500} src"))->toBe(' src'); + }); + + it('converts bullets to dashes', function (): void { + expect(EmbeddingTextSanitizer::sanitize("\u{2022} first item"))->toBe('- first item'); + }); + + it('collapses repeated spaces left by stripping', function (): void { + expect(EmbeddingTextSanitizer::sanitize("a \u{1F600} \u{1F600} b"))->toBe('a b'); + }); + + it('preserves newlines', function (): void { + expect(EmbeddingTextSanitizer::sanitize("line one\nline two"))->toBe("line one\nline two"); + }); +}); diff --git a/tests/Unit/EmbeddingsTest.php b/tests/Unit/EmbeddingsTest.php index ffe0e84..7c1beba 100644 --- a/tests/Unit/EmbeddingsTest.php +++ b/tests/Unit/EmbeddingsTest.php @@ -13,6 +13,7 @@ use TheShit\Vector\Embeddings\OpenAiEmbeddings; use TheShit\Vector\Embeddings\Requests\OllamaEmbedRequest; use TheShit\Vector\Embeddings\Requests\OpenAiEmbedRequest; +use TheShit\Vector\Exceptions\EmbeddingRequestException; describe('OllamaConnector', function (): void { it('resolves base url', function (): void { @@ -155,16 +156,75 @@ expect($client->embedBatch(['', ' ']))->toBe([]); }); - it('returns empty arrays on request failure', function (): void { + it('throws descriptive exception on request failure', function (): void { $connector = new OllamaConnector('http://localhost:11434'); $connector->withMockClient(new MockClient([ - OllamaEmbedRequest::class => MockResponse::make([], 500), + OllamaEmbedRequest::class => MockResponse::make([ + 'error' => 'the input length exceeds the context length', + ], 400), ])); $client = new OllamaEmbeddings($connector, 'bge-large'); - $result = $client->embed('hello'); - expect($result)->toBe([]); + $client->embed('hello'); + })->throws( + EmbeddingRequestException::class, + 'Embedding request failed for model [bge-large] (HTTP 400): the input length exceeds the context length', + ); + + it('falls back to raw body when error response is not json', function (): void { + $connector = new OllamaConnector('http://localhost:11434'); + $connector->withMockClient(new MockClient([ + OllamaEmbedRequest::class => MockResponse::make('upstream unavailable', 502), + ])); + + $client = new OllamaEmbeddings($connector, 'bge-large'); + + $client->embed('hello'); + })->throws( + EmbeddingRequestException::class, + 'Embedding request failed for model [bge-large] (HTTP 502): upstream unavailable', + ); + + it('sanitizes text before embedding by default', function (): void { + $connector = new OllamaConnector('http://localhost:11434'); + $mockClient = new MockClient([ + OllamaEmbedRequest::class => MockResponse::make([ + 'embeddings' => [[0.1, 0.2]], + ]), + ]); + $connector->withMockClient($mockClient); + + $client = new OllamaEmbeddings($connector, 'bge-large'); + $client->embed("hello \u{1F692} world"); + + $mockClient->assertSent( + fn ($request): bool => $request->body()->all()['input'] === ['hello world'], + ); + }); + + it('filters texts that sanitize to empty strings', function (): void { + $connector = new OllamaConnector('http://localhost:11434'); + $client = new OllamaEmbeddings($connector, 'bge-large'); + + expect($client->embedBatch(["\u{1F4A9}", "\u{2705}\u{2728}"]))->toBe([]); + }); + + it('skips sanitization when disabled', function (): void { + $connector = new OllamaConnector('http://localhost:11434'); + $mockClient = new MockClient([ + OllamaEmbedRequest::class => MockResponse::make([ + 'embeddings' => [[0.1, 0.2]], + ]), + ]); + $connector->withMockClient($mockClient); + + $client = new OllamaEmbeddings($connector, 'bge-large', sanitize: false); + $client->embed("hello \u{1F692} world"); + + $mockClient->assertSent( + fn ($request): bool => $request->body()->all()['input'] === ["hello \u{1F692} world"], + ); }); it('handles malformed embedding response', function (): void { @@ -262,16 +322,54 @@ expect($client->embedBatch(['', ' ']))->toBe([]); }); - it('returns empty arrays on request failure', function (): void { + it('throws descriptive exception on request failure', function (): void { $connector = new OpenAiConnector('https://api.openai.com', 'sk-test'); $connector->withMockClient(new MockClient([ - OpenAiEmbedRequest::class => MockResponse::make([], 500), + OpenAiEmbedRequest::class => MockResponse::make([ + 'error' => ['message' => 'Rate limit reached for requests'], + ], 429), ])); $client = new OpenAiEmbeddings($connector, 'text-embedding-3-large'); - $result = $client->embed('hello'); - expect($result)->toBe([]); + $client->embed('hello'); + })->throws( + EmbeddingRequestException::class, + 'Embedding request failed for model [text-embedding-3-large] (HTTP 429): Rate limit reached for requests', + ); + + it('does not sanitize by default', function (): void { + $connector = new OpenAiConnector('https://api.openai.com', 'sk-test'); + $mockClient = new MockClient([ + OpenAiEmbedRequest::class => MockResponse::make([ + 'data' => [['embedding' => [0.1]]], + ]), + ]); + $connector->withMockClient($mockClient); + + $client = new OpenAiEmbeddings($connector, 'text-embedding-3-large'); + $client->embed("hello \u{1F692} world"); + + $mockClient->assertSent( + fn ($request): bool => $request->body()->all()['input'] === ["hello \u{1F692} world"], + ); + }); + + it('sanitizes when enabled', function (): void { + $connector = new OpenAiConnector('https://api.openai.com', 'sk-test'); + $mockClient = new MockClient([ + OpenAiEmbedRequest::class => MockResponse::make([ + 'data' => [['embedding' => [0.1]]], + ]), + ]); + $connector->withMockClient($mockClient); + + $client = new OpenAiEmbeddings($connector, 'text-embedding-3-large', sanitize: true); + $client->embed("hello \u{1F692} world"); + + $mockClient->assertSent( + fn ($request): bool => $request->body()->all()['input'] === ['hello world'], + ); }); it('handles malformed data response', function (): void { From 5f64876c1c442b38680ff28c29b20540eb7ddde9 Mon Sep 17 00:00:00 2001 From: Jordan Partridge Date: Thu, 11 Jun 2026 17:16:14 -0700 Subject: [PATCH 2/2] chore: replace abandoned nunomaduro/pao with laravel/pao nunomaduro/pao no longer publishes dev-main, which broke composer resolution in CI. Swap to the maintained laravel/pao fork and bump Pest to satisfy its version constraint. --- composer.json | 2 +- composer.lock | 879 +++++++++++++++++++++++++++++--------------------- 2 files changed, 520 insertions(+), 361 deletions(-) diff --git a/composer.json b/composer.json index 936dbde..ecccb80 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "require-dev": { "laravel/framework": "^11.0|^12.0", "laravel/pint": "^1.0", - "nunomaduro/pao": "dev-main", + "laravel/pao": "^1.1", "opis/json-schema": "^2.6", "orchestra/testbench": "^9.0|^10.0", "pestphp/pest": "^4.0", diff --git a/composer.lock b/composer.lock index 6c1df68..444b43f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "627ebaa7c5c05d3c73529c1cb490574f", + "content-hash": "985597b6e02458ff0cfdb3bacdb5f8fb", "packages": [ { "name": "guzzlehttp/guzzle", @@ -619,16 +619,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { @@ -641,7 +641,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -666,7 +666,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -677,12 +677,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-04-13T15:52:40+00:00" } ], "packages-dev": [ @@ -908,6 +912,85 @@ ], "time": "2024-02-09T16:56:22+00:00" }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, { "name": "composer/semver", "version": "3.4.4", @@ -985,6 +1068,72 @@ ], "time": "2025-08-20T19:15:30+00:00" }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.3", @@ -1931,6 +2080,68 @@ }, "time": "2025-03-19T14:43:43+00:00" }, + { + "name": "laravel/agent-detector", + "version": "v2.0.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/agent-detector.git", + "reference": "90694b9256099591cf9e55d08c18ba7a00bf099f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/agent-detector/zipball/90694b9256099591cf9e55d08c18ba7a00bf099f", + "reference": "90694b9256099591cf9e55d08c18ba7a00bf099f", + "shasum": "" + }, + "require": { + "php": "^8.2.0" + }, + "require-dev": { + "laravel/pint": "^1.24.0", + "pestphp/pest": "^3.8.5|^4.1.0", + "pestphp/pest-plugin-type-coverage": "^3.0|^4.0.2", + "phpstan/phpstan": "^2.1.26", + "rector/rector": "^2.1.7", + "symfony/var-dumper": "^7.3.3" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Laravel\\AgentDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Detect if code is running in an AI agent or automated development environment", + "homepage": "https://github.com/laravel/agent-detector", + "keywords": [ + "Agent", + "ai", + "automation", + "claude", + "cursor", + "detection", + "devin", + "php" + ], + "support": { + "issues": "https://github.com/laravel/agent-detector/issues", + "source": "https://github.com/laravel/agent-detector" + }, + "time": "2026-04-29T18:32:34+00:00" + }, { "name": "laravel/framework", "version": "v12.56.0", @@ -2233,6 +2444,91 @@ }, "time": "2026-02-09T13:44:54+00:00" }, + { + "name": "laravel/pao", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pao.git", + "reference": "519eecdefb9d5da362876376b52207c8f11b477c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pao/zipball/519eecdefb9d5da362876376b52207c8f11b477c", + "reference": "519eecdefb9d5da362876376b52207c8f11b477c", + "shasum": "" + }, + "require": { + "laravel/agent-detector": "^2.0.2", + "php": "^8.3" + }, + "conflict": { + "laravel/framework": "<12.0.0", + "nunomaduro/collision": "<8.9.3", + "pestphp/pest": "<4.6.3 || >=6.0.0", + "phpunit/phpunit": "<12.5.23 || >=13.0.0 <13.1.7 || >=14.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.20.0", + "laravel/pint": "^1.29.1", + "orchestra/testbench": "^10.11.0 || ^11.1.0", + "pestphp/pest": "^4.7.2 || ^5.0.0", + "pestphp/pest-plugin-type-coverage": "^4.0.4 || ^5.0.0", + "phpstan/phpstan": "^2.2.1", + "rector/rector": "^2.4.5", + "symfony/process": "^7.4.8 || ^8.1.0", + "symfony/var-dumper": "^7.4.8 || ^8.1.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Laravel\\Pao\\Drivers\\Pest\\Plugin" + ] + }, + "laravel": { + "providers": [ + "Laravel\\Pao\\Laravel\\ServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Laravel\\Pao\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Agent-optimized output for PHP testing tools", + "keywords": [ + "Agent", + "PHPStan", + "ai", + "dev", + "paratest", + "pest", + "php", + "phpunit", + "rector", + "testing" + ], + "support": { + "issues": "https://github.com/laravel/pao/issues", + "source": "https://github.com/laravel/pao" + }, + "time": "2026-06-01T07:26:51+00:00" + }, { "name": "laravel/pint", "version": "v1.29.0", @@ -3615,23 +3911,23 @@ }, { "name": "nunomaduro/collision", - "version": "v8.9.2", + "version": "v8.9.4", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "6eb16883e74fd725ac64dbe81544c961ab448ba5" + "reference": "716af8f95a470e9094cfca09ed897b023be191a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/6eb16883e74fd725ac64dbe81544c961ab448ba5", - "reference": "6eb16883e74fd725ac64dbe81544c961ab448ba5", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/716af8f95a470e9094cfca09ed897b023be191a5", + "reference": "716af8f95a470e9094cfca09ed897b023be191a5", "shasum": "" }, "require": { "filp/whoops": "^2.18.4", "nunomaduro/termwind": "^2.4.0", "php": "^8.2.0", - "symfony/console": "^7.4.8 || ^8.0.4" + "symfony/console": "^7.4.8 || ^8.0.8" }, "conflict": { "laravel/framework": "<11.48.0 || >=14.0.0", @@ -3639,12 +3935,12 @@ }, "require-dev": { "brianium/paratest": "^7.8.5", - "larastan/larastan": "^3.9.3", - "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.2.0", - "laravel/pint": "^1.29.0", - "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.0.0", + "larastan/larastan": "^3.9.6", + "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.5.0", + "laravel/pint": "^1.29.1", + "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.2.1", "pestphp/pest": "^3.8.5 || ^4.4.3 || ^5.0.0", - "sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.0.0" + "sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.3.0" }, "type": "library", "extra": { @@ -3707,97 +4003,7 @@ "type": "patreon" } ], - "time": "2026-03-31T21:51:27+00:00" - }, - { - "name": "nunomaduro/pao", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/nunomaduro/pao.git", - "reference": "25557a77094f523a9807998d5018d13fa9a31c83" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/pao/zipball/25557a77094f523a9807998d5018d13fa9a31c83", - "reference": "25557a77094f523a9807998d5018d13fa9a31c83", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "php": "^8.3", - "shipfastlabs/agent-detector": "^1.1.0" - }, - "conflict": { - "nunomaduro/collision": "<8.9.2", - "pestphp/pest": "<4.4.3 || >=6.0", - "phpunit/phpunit": "<12.5.14 || >=13.0.0 <13.0.5 || >=14.0" - }, - "require-dev": { - "brianium/paratest": "^7.20", - "laravel/pint": "^1.29.0", - "pestphp/pest": "^4.4.3 || ^5.0.0", - "pestphp/pest-plugin-type-coverage": "^4.0.3 || ^5.0.0", - "phpstan/phpstan": "^2.1.46", - "rector/rector": "^2.3.9", - "symfony/process": "^7.4.5 || ^8.0.8", - "symfony/var-dumper": "^7.4.6 || ^8.0.8" - }, - "default-branch": true, - "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pao\\Drivers\\Pest\\Plugin" - ] - } - }, - "autoload": { - "files": [ - "src/Autoload.php" - ], - "psr-4": { - "Pao\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" - } - ], - "description": "Agent-optimized output for PHP testing tools", - "keywords": [ - "Agent", - "json", - "pest", - "php", - "phpunit", - "testing" - ], - "support": { - "issues": "https://github.com/nunomaduro/pao/issues", - "source": "https://github.com/nunomaduro/pao/tree/main" - }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2026-04-01T11:11:19+00:00" + "time": "2026-04-21T14:04:20+00:00" }, { "name": "nunomaduro/termwind", @@ -4497,41 +4703,43 @@ }, { "name": "pestphp/pest", - "version": "v4.4.5", + "version": "v4.7.2", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "9797a71dbc776f46d6fcacb708b002755da6f37a" + "reference": "40b88b62ef8a7c6fcae5fc28f1fa747f601c131b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/9797a71dbc776f46d6fcacb708b002755da6f37a", - "reference": "9797a71dbc776f46d6fcacb708b002755da6f37a", + "url": "https://api.github.com/repos/pestphp/pest/zipball/40b88b62ef8a7c6fcae5fc28f1fa747f601c131b", + "reference": "40b88b62ef8a7c6fcae5fc28f1fa747f601c131b", "shasum": "" }, "require": { "brianium/paratest": "^7.20.0", - "nunomaduro/collision": "^8.9.2", + "composer/xdebug-handler": "^3.0.5", + "nunomaduro/collision": "^8.9.4", "nunomaduro/termwind": "^2.4.0", "pestphp/pest-plugin": "^4.0.0", - "pestphp/pest-plugin-arch": "^4.0.0", + "pestphp/pest-plugin-arch": "^4.0.2", "pestphp/pest-plugin-mutate": "^4.0.1", "pestphp/pest-plugin-profanity": "^4.2.1", "php": "^8.3.0", - "phpunit/phpunit": "^12.5.16", - "symfony/process": "^7.4.8|^8.0.8" + "phpunit/phpunit": "^12.5.28", + "symfony/process": "^7.4.13|^8.1.0" }, "conflict": { "filp/whoops": "<2.18.3", - "phpunit/phpunit": ">12.5.16", + "phpunit/phpunit": ">12.5.28", "sebastian/exporter": "<7.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { + "mrpunyapal/peststan": "^0.2.10", "pestphp/pest-dev-tools": "^4.1.0", - "pestphp/pest-plugin-browser": "^4.3.0", - "pestphp/pest-plugin-type-coverage": "^4.0.3", - "psy/psysh": "^0.12.22" + "pestphp/pest-plugin-browser": "^4.3.1", + "pestphp/pest-plugin-type-coverage": "^4.0.4", + "psy/psysh": "^0.12.23" }, "bin": [ "bin/pest" @@ -4558,6 +4766,7 @@ "Pest\\Plugins\\Verbose", "Pest\\Plugins\\Version", "Pest\\Plugins\\Shard", + "Pest\\Plugins\\Tia", "Pest\\Plugins\\Parallel" ] }, @@ -4597,7 +4806,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v4.4.5" + "source": "https://github.com/pestphp/pest/tree/v4.7.2" }, "funding": [ { @@ -4609,7 +4818,7 @@ "type": "github" } ], - "time": "2026-04-03T13:43:28+00:00" + "time": "2026-06-01T06:08:59+00:00" }, { "name": "pestphp/pest-plugin", @@ -4683,26 +4892,26 @@ }, { "name": "pestphp/pest-plugin-arch", - "version": "v4.0.0", + "version": "v4.0.2", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-arch.git", - "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d" + "reference": "3fb0d02a91b9da504b139dc7ab2a31efb7c3215c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/25bb17e37920ccc35cbbcda3b00d596aadf3e58d", - "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/3fb0d02a91b9da504b139dc7ab2a31efb7c3215c", + "reference": "3fb0d02a91b9da504b139dc7ab2a31efb7c3215c", "shasum": "" }, "require": { "pestphp/pest-plugin": "^4.0.0", "php": "^8.3", - "ta-tikoma/phpunit-architecture-test": "^0.8.5" + "ta-tikoma/phpunit-architecture-test": "^0.8.7" }, "require-dev": { - "pestphp/pest": "^4.0.0", - "pestphp/pest-dev-tools": "^4.0.0" + "pestphp/pest": "^4.4.6", + "pestphp/pest-dev-tools": "^4.1.0" }, "type": "library", "extra": { @@ -4737,7 +4946,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.2" }, "funding": [ { @@ -4749,7 +4958,7 @@ "type": "github" } ], - "time": "2025-08-20T13:10:51+00:00" + "time": "2026-04-10T17:20:19+00:00" }, { "name": "pestphp/pest-plugin-mutate", @@ -5354,16 +5563,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "12.5.3", + "version": "12.5.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d" + "reference": "186dab580576598076de6818596d12b61801880e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b015312f28dd75b75d3422ca37dff2cd1a565e8d", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/186dab580576598076de6818596d12b61801880e", + "reference": "186dab580576598076de6818596d12b61801880e", "shasum": "" }, "require": { @@ -5372,16 +5581,15 @@ "ext-xmlwriter": "*", "nikic/php-parser": "^5.7.0", "php": ">=8.3", - "phpunit/php-file-iterator": "^6.0", "phpunit/php-text-template": "^5.0", "sebastian/complexity": "^5.0", - "sebastian/environment": "^8.0.3", - "sebastian/lines-of-code": "^4.0", + "sebastian/environment": "^8.1.2", + "sebastian/lines-of-code": "^4.0.1", "sebastian/version": "^6.0", "theseer/tokenizer": "^2.0.1" }, "require-dev": { - "phpunit/phpunit": "^12.5.1" + "phpunit/phpunit": "^12.5.28" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -5419,7 +5627,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.7" }, "funding": [ { @@ -5439,7 +5647,7 @@ "type": "tidelift" } ], - "time": "2026-02-06T06:01:44+00:00" + "time": "2026-06-01T13:24:19+00:00" }, { "name": "phpunit/php-file-iterator", @@ -5700,16 +5908,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.16", + "version": "12.5.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b2429f58ae75cae980b5bb9873abe4de6aac8b58" + "reference": "5895d05f5bf421ed230fbd76e1277e4b8955def4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b2429f58ae75cae980b5bb9873abe4de6aac8b58", - "reference": "b2429f58ae75cae980b5bb9873abe4de6aac8b58", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5895d05f5bf421ed230fbd76e1277e4b8955def4", + "reference": "5895d05f5bf421ed230fbd76e1277e4b8955def4", "shasum": "" }, "require": { @@ -5723,20 +5931,20 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.3", + "phpunit/php-code-coverage": "^12.5.6", "phpunit/php-file-iterator": "^6.0.1", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", "phpunit/php-timer": "^8.0.0", - "sebastian/cli-parser": "^4.2.0", - "sebastian/comparator": "^7.1.4", + "sebastian/cli-parser": "^4.2.1", + "sebastian/comparator": "^7.1.8", "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.4", - "sebastian/exporter": "^7.0.2", + "sebastian/environment": "^8.1.2", + "sebastian/exporter": "^7.0.3", "sebastian/global-state": "^8.0.2", "sebastian/object-enumerator": "^7.0.0", "sebastian/recursion-context": "^7.0.1", - "sebastian/type": "^6.0.3", + "sebastian/type": "^6.0.4", "sebastian/version": "^6.0.0", "staabm/side-effects-detector": "^1.0.5" }, @@ -5778,7 +5986,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.16" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.28" }, "funding": [ { @@ -5786,7 +5994,7 @@ "type": "other" } ], - "time": "2026-04-03T05:26:42+00:00" + "time": "2026-05-27T14:01:10+00:00" }, { "name": "psr/clock", @@ -6335,23 +6543,23 @@ }, { "name": "sebastian/cli-parser", - "version": "4.2.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04" + "reference": "7d05781b13f7dec9043a629a21d086ed74582a15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/90f41072d220e5c40df6e8635f5dafba2d9d4d04", - "reference": "90f41072d220e5c40df6e8635f5dafba2d9d4d04", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/7d05781b13f7dec9043a629a21d086ed74582a15", + "reference": "7d05781b13f7dec9043a629a21d086ed74582a15", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -6380,7 +6588,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.0" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.1" }, "funding": [ { @@ -6400,20 +6608,20 @@ "type": "tidelift" } ], - "time": "2025-09-14T09:36:45+00:00" + "time": "2026-05-17T05:29:34+00:00" }, { "name": "sebastian/comparator", - "version": "7.1.4", + "version": "7.1.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6" + "reference": "7c65c1e79836812819705b473a90c12399542485" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a7de5df2e094f9a80b40a522391a7e6022df5f6", - "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/7c65c1e79836812819705b473a90c12399542485", + "reference": "7c65c1e79836812819705b473a90c12399542485", "shasum": "" }, "require": { @@ -6421,10 +6629,10 @@ "ext-mbstring": "*", "php": ">=8.3", "sebastian/diff": "^7.0", - "sebastian/exporter": "^7.0" + "sebastian/exporter": "^7.0.3" }, "require-dev": { - "phpunit/phpunit": "^12.2" + "phpunit/phpunit": "^12.5.25" }, "suggest": { "ext-bcmath": "For comparing BcMath\\Number objects" @@ -6472,7 +6680,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.4" + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.8" }, "funding": [ { @@ -6492,7 +6700,7 @@ "type": "tidelift" } ], - "time": "2026-01-24T09:28:48+00:00" + "time": "2026-05-21T04:45:25+00:00" }, { "name": "sebastian/complexity", @@ -6621,23 +6829,23 @@ }, { "name": "sebastian/environment", - "version": "8.0.4", + "version": "8.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "7b8842c2d8e85d0c3a5831236bf5869af6ab2a11" + "reference": "9d32c685773823b1983e256ae4ecd48a10d6e439" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/7b8842c2d8e85d0c3a5831236bf5869af6ab2a11", - "reference": "7b8842c2d8e85d0c3a5831236bf5869af6ab2a11", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/9d32c685773823b1983e256ae4ecd48a10d6e439", + "reference": "9d32c685773823b1983e256ae4ecd48a10d6e439", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.26" }, "suggest": { "ext-posix": "*" @@ -6645,7 +6853,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "8.1-dev" } }, "autoload": { @@ -6673,7 +6881,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/8.0.4" + "source": "https://github.com/sebastianbergmann/environment/tree/8.1.2" }, "funding": [ { @@ -6693,29 +6901,29 @@ "type": "tidelift" } ], - "time": "2026-03-15T07:05:40+00:00" + "time": "2026-05-25T13:40:20+00:00" }, { "name": "sebastian/exporter", - "version": "7.0.2", + "version": "7.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7" + "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/016951ae10980765e4e7aee491eb288c64e505b7", - "reference": "016951ae10980765e4e7aee491eb288c64e505b7", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23", + "reference": "c5e21b5de653ce0a769fb36f5cdfcb5e7a32cf23", "shasum": "" }, "require": { "ext-mbstring": "*", "php": ">=8.3", - "sebastian/recursion-context": "^7.0" + "sebastian/recursion-context": "^7.0.1" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -6763,7 +6971,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.3" }, "funding": [ { @@ -6783,30 +6991,30 @@ "type": "tidelift" } ], - "time": "2025-09-24T06:16:11+00:00" + "time": "2026-05-20T04:37:17+00:00" }, { "name": "sebastian/global-state", - "version": "8.0.2", + "version": "8.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "ef1377171613d09edd25b7816f05be8313f9115d" + "reference": "b164d3274d6537ab462591c5755f76a8f5b1aae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/ef1377171613d09edd25b7816f05be8313f9115d", - "reference": "ef1377171613d09edd25b7816f05be8313f9115d", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b164d3274d6537ab462591c5755f76a8f5b1aae9", + "reference": "b164d3274d6537ab462591c5755f76a8f5b1aae9", "shasum": "" }, "require": { "php": ">=8.3", "sebastian/object-reflector": "^5.0", - "sebastian/recursion-context": "^7.0" + "sebastian/recursion-context": "^7.0.1" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.28" }, "type": "library", "extra": { @@ -6837,7 +7045,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.3" }, "funding": [ { @@ -6857,28 +7065,28 @@ "type": "tidelift" } ], - "time": "2025-08-29T11:29:25+00:00" + "time": "2026-06-01T15:10:33+00:00" }, { "name": "sebastian/lines-of-code", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f" + "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/97ffee3bcfb5805568d6af7f0f893678fc076d2f", - "reference": "97ffee3bcfb5805568d6af7f0f893678fc076d2f", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d543b8ef219dcd8da262cbb958639a96bedba10e", + "reference": "d543b8ef219dcd8da262cbb958639a96bedba10e", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", + "nikic/php-parser": "^5.7.0", "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -6907,15 +7115,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.0" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/lines-of-code", + "type": "tidelift" } ], - "time": "2025-02-07T04:57:28+00:00" + "time": "2026-05-19T16:22:07+00:00" }, { "name": "sebastian/object-enumerator", @@ -7109,23 +7329,23 @@ }, { "name": "sebastian/type", - "version": "6.0.3", + "version": "6.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d" + "reference": "82ff822c2edc46724be9f7411d3163021f602773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/e549163b9760b8f71f191651d22acf32d56d6d4d", - "reference": "e549163b9760b8f71f191651d22acf32d56d6d4d", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/82ff822c2edc46724be9f7411d3163021f602773", + "reference": "82ff822c2edc46724be9f7411d3163021f602773", "shasum": "" }, "require": { "php": ">=8.3" }, "require-dev": { - "phpunit/phpunit": "^12.0" + "phpunit/phpunit": "^12.5.25" }, "type": "library", "extra": { @@ -7154,7 +7374,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/6.0.3" + "source": "https://github.com/sebastianbergmann/type/tree/6.0.4" }, "funding": [ { @@ -7174,7 +7394,7 @@ "type": "tidelift" } ], - "time": "2025-08-09T06:57:12+00:00" + "time": "2026-05-20T06:45:45+00:00" }, { "name": "sebastian/version", @@ -7230,73 +7450,6 @@ ], "time": "2025-02-07T05:00:38+00:00" }, - { - "name": "shipfastlabs/agent-detector", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/shipfastlabs/agent-detector.git", - "reference": "eefb18b61968a59a0428a4f75bee2e21596fe949" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/shipfastlabs/agent-detector/zipball/eefb18b61968a59a0428a4f75bee2e21596fe949", - "reference": "eefb18b61968a59a0428a4f75bee2e21596fe949", - "shasum": "" - }, - "require": { - "php": "^8.2.0" - }, - "require-dev": { - "laravel/pint": "^1.24.0", - "pestphp/pest": "^3.8.5|^4.1.0", - "pestphp/pest-plugin-type-coverage": "^3.0|^4.0.2", - "phpstan/phpstan": "^2.1.26", - "rector/rector": "^2.1.7", - "symfony/var-dumper": "^7.3.3" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "AgentDetector\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Pushpak Chahjed", - "email": "pushpak1300@gmail.com" - } - ], - "description": "Detect if code is running in an AI agent or automated development environment", - "keywords": [ - "Agent", - "ai", - "automation", - "claude", - "cursor", - "detection", - "devin", - "php" - ], - "support": { - "issues": "https://github.com/shipfastlabs/agent-detector/issues", - "source": "https://github.com/shipfastlabs/agent-detector/tree/v1.1.0" - }, - "funding": [ - { - "url": "https://github.com/pushpak1300", - "type": "github" - } - ], - "time": "2026-03-11T22:59:30+00:00" - }, { "name": "spatie/invade", "version": "2.1.0", @@ -7487,16 +7640,16 @@ }, { "name": "symfony/console", - "version": "v7.4.8", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707" + "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", - "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", + "url": "https://api.github.com/repos/symfony/console/zipball/85095d2573eaefaf35e40b9513a9bf09f72cd217", + "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217", "shasum": "" }, "require": { @@ -7561,7 +7714,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.8" + "source": "https://github.com/symfony/console/tree/v7.4.13" }, "funding": [ { @@ -7581,7 +7734,7 @@ "type": "tidelift" } ], - "time": "2026-03-30T13:54:39+00:00" + "time": "2026-05-24T08:56:14+00:00" }, { "name": "symfony/css-selector", @@ -7821,16 +7974,16 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", "shasum": "" }, "require": { @@ -7844,7 +7997,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -7877,7 +8030,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" }, "funding": [ { @@ -7888,12 +8041,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/finder", @@ -8339,16 +8496,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -8398,7 +8555,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { @@ -8418,20 +8575,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.38.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "e9247d281d694a5120554d9afaf54e070e88a603" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603", + "reference": "e9247d281d694a5120554d9afaf54e070e88a603", "shasum": "" }, "require": { @@ -8480,7 +8637,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1" }, "funding": [ { @@ -8500,7 +8657,7 @@ "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2026-05-26T05:58:03+00:00" }, { "name": "symfony/polyfill-intl-idn", @@ -8591,16 +8748,16 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.38.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", + "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", "shasum": "" }, "require": { @@ -8652,7 +8809,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0" }, "funding": [ { @@ -8672,20 +8829,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-05-25T13:48:31+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.38.2", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "shasum": "" }, "require": { @@ -8737,7 +8894,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" }, "funding": [ { @@ -8757,20 +8914,20 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-05-27T06:59:30+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", "shasum": "" }, "require": { @@ -8821,7 +8978,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0" }, "funding": [ { @@ -8841,7 +8998,7 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-php83", @@ -9005,16 +9162,16 @@ }, { "name": "symfony/polyfill-php85", - "version": "v1.33.0", + "version": "v1.38.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", + "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", "shasum": "" }, "require": { @@ -9061,7 +9218,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1" }, "funding": [ { @@ -9081,7 +9238,7 @@ "type": "tidelift" } ], - "time": "2025-06-23T16:12:55+00:00" + "time": "2026-05-26T02:25:22+00:00" }, { "name": "symfony/polyfill-uuid", @@ -9168,16 +9325,16 @@ }, { "name": "symfony/process", - "version": "v7.4.8", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" + "reference": "f5804be144caceb570f6747519999636b664f24c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", - "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", + "url": "https://api.github.com/repos/symfony/process/zipball/f5804be144caceb570f6747519999636b664f24c", + "reference": "f5804be144caceb570f6747519999636b664f24c", "shasum": "" }, "require": { @@ -9209,7 +9366,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.8" + "source": "https://github.com/symfony/process/tree/v7.4.13" }, "funding": [ { @@ -9229,7 +9386,7 @@ "type": "tidelift" } ], - "time": "2026-03-24T13:12:05+00:00" + "time": "2026-05-23T16:05:06+00:00" }, { "name": "symfony/routing", @@ -9318,16 +9475,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.1", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", - "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", "shasum": "" }, "require": { @@ -9345,7 +9502,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -9381,7 +9538,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.0" }, "funding": [ { @@ -9401,24 +9558,24 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:30:57+00:00" + "time": "2026-03-28T09:44:51+00:00" }, { "name": "symfony/string", - "version": "v8.0.8", + "version": "v8.1.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ae9488f874d7603f9d2dfbf120203882b645d963" + "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ae9488f874d7603f9d2dfbf120203882b645d963", - "reference": "ae9488f874d7603f9d2dfbf120203882b645d963", + "url": "https://api.github.com/repos/symfony/string/zipball/afd5944f4005862d961efb85c8bbd5c523c4e3c9", + "reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9", "shasum": "" }, "require": { - "php": ">=8.4", + "php": ">=8.4.1", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-intl-grapheme": "^1.33", "symfony/polyfill-intl-normalizer": "^1.0", @@ -9471,7 +9628,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v8.0.8" + "source": "https://github.com/symfony/string/tree/v8.1.0" }, "funding": [ { @@ -9491,7 +9648,7 @@ "type": "tidelift" } ], - "time": "2026-03-30T15:14:47+00:00" + "time": "2026-05-29T05:06:50+00:00" }, { "name": "symfony/translation", @@ -9588,16 +9745,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.6.1", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977" + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", - "reference": "65a8bc82080447fae78373aa10f8d13b38338977", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", "shasum": "" }, "require": { @@ -9610,7 +9767,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -9646,7 +9803,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" }, "funding": [ { @@ -9666,7 +9823,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T13:41:35+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/uid", @@ -10233,16 +10390,16 @@ }, { "name": "webmozart/assert", - "version": "2.1.6", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8" + "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/ff31ad6efc62e66e518fbab1cde3453d389bcdc8", - "reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9007ea6f45ecf352a9422b36644e4bfc039b9155", + "reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155", "shasum": "" }, "require": { @@ -10258,7 +10415,11 @@ }, "type": "library", "extra": { + "psalm": { + "pluginClass": "Webmozart\\Assert\\PsalmPlugin" + }, "branch-alias": { + "dev-master": "2.0-dev", "dev-feature/2-0": "2.0-dev" } }, @@ -10289,16 +10450,14 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.1.6" + "source": "https://github.com/webmozarts/assert/tree/2.4.0" }, - "time": "2026-02-27T10:28:38+00:00" + "time": "2026-05-20T13:07:01+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "nunomaduro/pao": 20 - }, + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": {