Maintenance and quality pass. No public API breaks. Reviewed jointly with Codex/GPT-5.5.
Fixed
- Safe EXPLAIN —
RecommendationServicenow resolves the captured query's own connection and runs a non-executingEXPLAIN(neverEXPLAIN ANALYZE), with a per-driver statement form (pgsql/mysql→EXPLAIN,sqlite→EXPLAIN QUERY PLAN, others skipped). Multi-statement input is rejected and EXPLAIN failures are reported without breaking analysis. The previousexplain analysewas Postgres-only and could actually execute captured production SQL (e.g.UPDATE/DELETE). - Retryable recommendations — a record is only marked
is_analyzedwhen the AI returns a non-empty recommendation. Empty results stayis_analyzed=falseand are retried on the next scheduledslower:analyze. The command now prints anAnalyzed | Skippedsummary. - No more swallowed errors —
createRecordreports failures viareport()(without the raw SQL) and catchesThrowable, so logging slow queries can never break the request. - Correct iteration —
slower:cleanandslower:analyzeswitched tochunkById.
Changed
- Default
recommendation_model: deprecatedgpt-4(shut down 2026-10-23) →gpt-5.4-mini. PinSLOWER_AI_RECOMMENDATION_MODEL=gpt-4to keep old behaviour. - CI now tests PHP 8.4 (matrix: 8.2/8.3/8.4 × L10–13).
openai-php/laravel→^0.18.0,dependabot/fetch-metadata→2.5.0.
Documentation / internals
- README config example synced with
slower.php,ai_servicedriver switch documented, broken third-party screenshot removed, upgrade note added. OpenAiDrivernow type-hintsOpenAI\Contracts\ClientContract(substitutable/fakeable).- +13 behavior tests (
RecommendationServiceTest, extendedCommandsTest,SlowLogFactory). Suite: 39 passed. PHPStan level 5: clean. Pint: clean.
Full Changelog: v2.1.0...v2.2.0