# Phase 10 — Broaden strict-tool-schema fallback regex **Estimated time:** ~10 minutes **Touches:** `lib/dispatch/adapter/minimax.rb` (specifically `strict_grammar_error?`). ## Goal The Claude adapter retries a failed tool-using request with `strict: false` on tool definitions when Anthropic returns a 400 error like `"compiled grammar too large"` or `"schema too complex"`. The retry harness (`chat_streaming_with_strict_fallback`, `chat_non_streaming_with_strict_fallback`, the `@strict_disabled` flag) should be KEPT — it is harmless when not triggered and useful when it is. The matcher itself, currently keyed on Anthropic's exact wording, should be broadened so that an analogous MiniMax error message also fires the fallback. We don't yet know MiniMax's exact wording for this class of error (or whether they have one), so the new regex must be tolerant: match HTTP 400 responses whose error message mentions `grammar` or `schema` and a "too large" / "too complex" / "invalid" qualifier — case insensitive. ## Steps ### 1. Locate the matcher Find `def strict_grammar_error?` (or similarly named — search for `grammar` in `lib/dispatch/adapter/minimax.rb`). It currently looks like: ```ruby def strict_grammar_error?(err) return false unless err.is_a?(RequestError) return false unless err.status_code == 400 msg = err.message.to_s msg.match?(/compiled grammar too large/i) || msg.match?(/schema too complex/i) end ``` ### 2. Broaden the regex Replace the body with a more tolerant matcher: ```ruby STRICT_GRAMMAR_PATTERNS = [ /compiled\s+grammar\s+too\s+large/i, /schema\s+too\s+complex/i, /(?:grammar|schema).*?(?:too\s*(?:large|complex|big)|invalid|exceed)/i, /tool[_\s-]?schema.*(?:too\s*(?:large|complex)|exceed)/i ].freeze def strict_grammar_error?(err) return false unless err.is_a?(RequestError) return false unless err.status_code == 400 msg = err.message.to_s STRICT_GRAMMAR_PATTERNS.any? { |re| msg.match?(re) } end ``` Place `STRICT_GRAMMAR_PATTERNS` as a module-level constant (visibility private to `Dispatch::Adapter::MiniMax` is fine; it does not need to be exposed externally). ### 3. Confirm the retry harness still uses the predicate Find `chat_streaming_with_strict_fallback` and `chat_non_streaming_with_strict_fallback` (or whatever the harness methods are called). Both should call `strict_grammar_error?(error)` inside their `rescue RequestError => e` block. If they reference some older predicate name, update them to call the new one. DO NOT change the rest of the harness logic. The single-shot retry, the `@strict_disabled = true` latch, and the `disable_strict_tools: true` forwarding to `RequestBuilder.build` all stay. ## Acceptance criteria - The matcher returns `true` for a `RequestError` with status `400` and message `"compiled grammar too large for tool 'foo'"`. - The matcher returns `true` for a `RequestError` with status `400` and message `"Tool schema is too complex"`. - The matcher returns `true` for a `RequestError` with status `400` and message `"grammar exceeds maximum size"`. - The matcher returns `false` for a `RequestError` with status `400` and message `"missing required field: messages"`. - The matcher returns `false` for a `RequestError` with status `429`, even if the message contains `"grammar"` (status guard). - The matcher returns `false` for a non-`RequestError` exception. - `bundle exec rubocop --autocorrect-all` exits 0. ## Verification Run `run_tests` with `project_path=reference/dispatch-adapter-minimax`. Rubocop must be clean. `strict_fallback_spec.rb` failures referring to the broader matcher (e.g. tests asserting it does NOT fire on "grammar exceeds maximum size") are addressed in phase 16. Other failures must be investigated. Test coverage for the new regex variants is added in phase 16. Do NOT add specs here.