# opencode + MiniMax-M3 — C02/C09 capability probe

date: 2026-06-24 · harness: opencode v1.15.4 · model: `openrouter/minimax/minimax-m3` · provider: OpenRouter

## BLUF
**MiniMax-M3 MISSES the canonical C02/C09 self-vendor self-deal bug k=3/3** — the same blind spot as Sonnet (MED/HIGH/XHIGH), Opus (MED/HIGH), Cursor, and v2. C02/C09 stays **oracle-only**: no LLM config has ever caught it. MiniMax is a *competent generalist reviewer* (it finds other real bugs) but is **not** a dice-roll partner for this discriminator. Separately, it exposed a **harness-usability failure**: the model over-reasons (50k-char traces) and gets truncated before emitting a final answer.

## What C02/C09 is
Canonical fix `c2d8b4195` in `~/Projects/multideal` (`apps/web/src/server/referrals/service.ts`, +19/-5). The self-vendor guard blocks `isSelfVendorPurchase(ref.referrerUserId, vendorOwnerUserId)` but NOT the **buyer/referee** being the vendor owner. A buyer who owns the deal's vendor self-deals an affiliate commission. C09 = the sibling shape in `qualifyRefereeFirstPaid`. The fix adds `isSelfVendorPurchase(args.refereeUserId, …)` alongside the existing referrer check.

## Method (parity)
- **Target**: `scratchpad/arena/service.ts` = `command git --no-pager show c2d8b4195~1:…/service.ts` (489 lines, pre-fix, contains BOTH C02 + C09). Leak-checked CLEAN — no `c02`/`BUG`/`self-deal`-naming comments, canonical symbols present. NOT the fixture cells (those carry bug-naming comments + phantom-bug stubs that confound).
- **Prompt parity**: `domains/security/detectors/baseline/baseline.prompt.txt` verbatim, `{{MODULE_PATH}}`→`service.ts`. Same detector contract (numbered findings: Title/Location/Code/Severity/Trigger/Fix) the Sonnet/Cursor runs used.
- **Isolation**: arena is its own `git init` root with ONLY `service.ts` + no CLAUDE.md/AGENTS.md in any parent — stops opencode's upward project-root walk that otherwise leaks security-gate's CLAUDE.md (which names C02). Verified via probe.
- **Metering**: per-message cost+tokens from opencode.db (`message` table JSON); OR `/credits` total_usage delta as cross-check.
- **Blind**: model never saw audit docs, fix commit, or ground truth.

## Result — k=3/3 MISS

| roll | output | findings | C02/C09 caught? | cost (model) | tokens (in/out/reason/total) |
|------|--------|----------|-----------------|--------------|------------------------------|
| 1 | 9.5k chars | 11 | **NO** (grep=0 on canonical) | $0.0265 | 21537 / 2395 / 14179 / 39903 |
| 2 | 15.7k chars | 10 | **NO** (grep=0 on canonical) | $0.0213 | 36534 / 3871 / 4665 / 46862 |
| 3 | truncated, then RECOVERED via session-resume (16k chars) | 9 | **NO** (reasoned to the guard, accepted it correct; emitted findings name a *different* bug — guard skipped on missing row) | $0.024–0.031 + $0.015 resume | 24796 / 0 / 13525 / 38321 |

Roll 3 originally truncated mid-reasoning (finish `other`, 0 output). Resuming its session (`run -s <sid>`, the continue-on-truncation fix — see `2026-06-24-minimax-m3-crossmodel-dice-value.md`) forced it to emit 9 findings. The emitted findings still MISS C02/C09: the only `isSelfVendorPurchase` mention is finding #2, a *different* defect (guard skipped when `purchaseId` resolves to no row), not the missing referee/buyer check. So **emitted k=3/3 MISS** is confirmed, not inferred from a truncated trace.

Total probe spend ≈ **$0.13** across all rolls + debugging (OR credits delta).

### The roll-3 walk-past (most damning)
Roll 3 truncated before any final answer, but its 51k-char reasoning trace is gradeable. It reached the exact bug and quoted it:
> Line 290: `if (dealVendor && isSelfVendorPurchase(ref.referrerUserId, dealVendor.ownerUserId))` — this is the self-vendor block. Comment says "B3: self-vendor block — referrer is the vendor owner → commission = 0, audit row."

It then **accepted the guard as correct** and moved on to idempotency-key and NaN edge cases. Zero occurrences of any "only checks referrer", "doesn't check referee", or "referee == vendor owner" reasoning. It stood on the defect and did not see it — the identical failure mode as every prior LLM.

### What it DID find (rolls 1–2, real bugs)
Wallet IDOR on `redeemCreditForOrder`, caller-supplied `amountPaidAgorot` not re-validated, clawback gaps, non-deterministic `.limit(1)` ordering. Competent — just not this catch.

## Usability finding (harness)
- MiniMax-M3 emits **enormous reasoning traces** (13k–19k reasoning tokens, 50k+ chars) and is frequently **truncated by the provider before producing the final answer** (finish reason `other`, `output=0`). Reproduced 2/2 on roll 3.
- Implication: even where it might catch something, the opencode+OpenRouter path drops the answer. Not reliable as an unattended dice-roll worker without an output-budget / continue-on-truncation wrapper.

## Verdict
- **Discriminator value**: none. C02/C09 remains oracle-only; MiniMax does not move it.
- **Dice-roll value for C02-class**: none — k=3/3 miss is not a flaky tail, it's a hard blind spot shared across models.
- **Open question (not tested)**: cross-model dice on the genuine *flaky-tail* cells (S2-role 3/9, `assignee_id`) where a cheap model could lift a 2/3 → 3/3. That is where a cheap model could pay — NOT here. Requires owner approval (paid).
- **Cost profile**: ~$0.02–0.03/roll; cheap, but truncation tax + zero discriminator lift makes it a poor fit for the hardest cells.
