# Phase 06 — Pricing zero **Estimated time:** ~15 minutes **Touches:** `lib/dispatch/adapter/minimax/pricing_table.rb`, `lib/dispatch/adapter/minimax/data/claude_pricing.json` (or whatever the JSON data file is named after phase 01), `lib/dispatch/adapter/minimax/response_builder.rb` (cost calculation). ## Goal Token Plan is request-quota, not per-token. Setting per-token rates would mislead callers. Instead, keep the `Usage#cost` field for API stability but always populate it as `0.0`. `PricingTable` becomes a stub: it answers `context_window` / `max_output_tokens` / `lookup` correctly for known MiniMax models, but `lookup` returns a `ModelPricing` whose four `*_per_mtok` fields are all zero. ## Steps ### 1. Replace the pricing JSON data file The current data file (likely `lib/dispatch/adapter/minimax/data/claude_pricing.json`) contains Anthropic per-MTok rates. Replace it with a MiniMax catalog containing zeros for every cost field. RENAME the file to `lib/dispatch/adapter/minimax/data/minimax_pricing.json`. ```json { "MiniMax-M2.7": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 }, "MiniMax-M2.7-highspeed": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 }, "MiniMax-M2.5": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 }, "MiniMax-M2.5-highspeed": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 }, "MiniMax-M2.1": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 }, "MiniMax-M2.1-highspeed": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 }, "MiniMax-M2": { "context_window": 204800, "max_output_tokens": 16384, "input_per_mtok": 0.0, "output_per_mtok": 0.0, "cache_read_per_mtok": 0.0, "cache_write_per_mtok": 0.0 } } ``` `max_output_tokens` is set to 16,384 because MiniMax's documented `max_tokens` field caps generation; the figure is a conservative default (the Anthropic SDK request shape uses `max_tokens` and MiniMax accepts up to whatever the model supports; we'll let MiniMax bound it server-side for anything larger). ### 2. Update `lib/dispatch/adapter/minimax/pricing_table.rb` - Change `DATA_PATH` to point at the new filename: `File.expand_path("data/minimax_pricing.json", __dir__)`. - Leave the four module-level helper methods (`lookup`, `context_window`, `max_output_tokens`, `known_ids`) UNCHANGED. They will return correct values from the new zeroed JSON. ### 3. Confirm `Usage#cost` plumbing In `lib/dispatch/adapter/minimax/response_builder.rb`, find the `build_usage` method (and / or `build_usage_cost` if separate). The existing logic computes cost as `(input_tokens * input_per_mtok / 1M) + …`. With every `*_per_mtok` field zero, this naturally evaluates to 0.0 — no logic change is needed. DO NOT short-circuit cost to a hardcoded `0.0`. Let it flow through the existing arithmetic so that if a future MiniMax pricing model is populated, the same plumbing will Just Work. If the existing code calls `pricing.input_per_mtok * input_tokens` and `pricing` can be `nil` for unknown models, ensure it gracefully returns `0.0` (not `nil`) when `pricing` is nil. Add a guard if missing: ```ruby return UsageCost.new(input_cost: 0.0, output_cost: 0.0, cache_read_cost: 0.0, cache_write_cost: 0.0, total_cost: 0.0) if pricing.nil? ``` (Field names should match whatever `Dispatch::Adapter::UsageCost` actually exposes — check the interface gem if uncertain.) ### 4. Delete or update specs that asserted on real prices If `spec/dispatch/adapter/minimax/pricing_table_spec.rb` has examples that expect non-zero values for Anthropic models, those examples will fail after this phase. Update them to reflect MiniMax's zero rates and the seven new model IDs. The full retarget is in phase 16, but minor adjustments here to keep the spec passing are fine — DO NOT weaken or skip examples; either rewrite them correctly now or expect their failures to be fixed in phase 16. If you choose to defer to phase 16, ensure the failures are clearly attributable to "expected Anthropic prices, got zero" (not a load error, not a syntax error, not a NoMethodError). ## Acceptance criteria - The JSON data file is named `minimax_pricing.json` and lives under `lib/dispatch/adapter/minimax/data/`. - `claude_pricing.json` does NOT exist. - `PricingTable.known_ids` returns exactly the 7 MiniMax model IDs. - `PricingTable.context_window("MiniMax-M2.7")` returns `204_800`. - `PricingTable.lookup("MiniMax-M2.7").input_per_mtok` is `0.0`. - `PricingTable.lookup("nonexistent-model")` returns `nil`. - `bundle exec rubocop --autocorrect-all` exits 0. ## Verification Run `run_tests` with `project_path=reference/dispatch-adapter-minimax`. Rubocop must be clean. The `pricing_table_spec.rb` failures are acceptable as long as they only stem from old Anthropic price assertions (retargeted in phase 16). Any failure NOT of that shape must be fixed before calling `ask_for_next_plan`.