# Proof audit, pass 1

PR [#32585](https://git.cafe/pingdotgg/t3code/pull/32585), branch `fix/issue-32575`, reviewed head [329de9bc42](https://git.cafe/pingdotgg/t3code/commit/329de9bc42f156de7ae6886bccbfc4256d163022), against `origin/main` [0a9abddaee](https://git.cafe/pingdotgg/t3code/commit/0a9abddaee00ff1495e77a03dd4fafa73c3cd4cb).

## Findings

Existing proof covers the reported bug in both changed callers. Do not recapture those rows merely because the background helper has no real-Pi transcript: its named regression test is valid proof for the changed selection behavior. A model-ID slash and a same-runtime model switch also already have proof.

The rows missing direct proof are **F05, F06, F10, F11, and F12** below. These are evidence gaps, not confirmed implementation defects. No evidence contradicts the fix. F05 and F06 can share one capture if it includes a unique both-slash selection before introducing the colliding pair. F10 and F11 can share one scripted session sequence. An added focused behavior test could close a deterministic parsing gap; the runtime column describes how to close it using the requested real-server capture approach.

The body transcript is attributed to [23049bc81b](https://git.cafe/pingdotgg/t3code/commit/23049bc81bec766f78737ff3020f72b7fe08ddba), not the requested merge head. The remote branch and local HEAD both identify the requested head; GitCafe metadata still names the older head. Compared with the transcript revision, the resolver, text-generation implementation, and text-generation tests are unchanged. Adapter changes inherited from main concern service tiers and prompt acknowledgements; the PR's model-resolution diff remains the same. I carry the relevant old proof forward and do not demand a duplicate runtime solely for the merge commit. Reported test passes are PR-body claims; this pass inspected their assertions without rerunning tests.

## Caller and interaction scope

- `resolvePiModelSlug` has exactly two production callers: adapter `applySelection` and text-generation `runPiJson`.
- Adapter `registerThread`, reached by ensure/resume, obtains the inventory once per runtime after a successful array result; failed/non-array discovery is eligible for retry on a later registration. User turns and explicit compact turns apply selection. A repeated selected slug skips `set_model`. Provider-created continuation turns and steering bypass this selection path. Returning to `default` restores the structured baseline pair without resolving a slug. Thinking, service-tier application, session model publication, and context-window tracking follow model selection.
- The text-generation caller spawns short-lived Pi with extensions and tools disabled and offline enabled. Every non-default request discovers inventory before selecting; default bypasses both requests. Commit suggestions, PR content, branch naming, thread title generation/regeneration, and transcription post-processing all use this same runner. Review guides are rejected by `withoutInvestigation` before the Pi runner (or rerouted by the server), so no Pi model-selection fixture is needed for them. There is no separate title/commit parser to recapture, and no UI render path.
- Web, desktop, mobile, MCP-originated commands, scheduled work, and local/remote/tunnel transports ultimately use these same server services. This diff changes no transport contract or client behavior. Other providers do not use this resolver.

## Fixture matrix

All identifiers in fixture recipes are synthetic. Never upload real runtime model identifiers, credentials, startup pairing links, or unredacted hub traffic. “Covered” accepts the existing transcript or the behavior tests in the three test files the body names. Shared-resolver cases need not be duplicated for each text-generation operation.

| ID / named fixture | Caller and input / interaction | Diff effect and expected behavior | Existing evidence | Status | Real-app seed / capture needed |
|---|---|---|---|---|---|
| F01 Ordinary reported pair | Adapter and background generation; provider and model IDs without internal slashes | Resolver now checks inventory first; outgoing pair is unchanged | Body's ordinary-provider main control; adapter ordinary-pair assertions in `resets applied thinking when returning to Pi default (failed first restore: %s)`; text-generation regression exercises the same exact-match caller branch | covered-by-existing | None; plain configured Pi provider is the control |
| F02 Reported slash provider | Adapter user turn; provider contains `/`, model ID is plain | Changed: select the whole reported provider, rather than its prefix before the first slash | Body's main failure / branch success transcript; named adapter regression `selects the provider and id Pi reported when either contains a slash` | covered-by-existing | None; the body's `--extension` provider registration is sufficient |
| F03 Background slash provider | All background operations sharing `runPiJson`; reported provider contains `/` | Changed: extra discovery request supplies the structured pair to `set_model`; extension registration is unavailable in this process | Named text-generation regression `selects the provider and id Pi reported when the provider contains a slash` asserts the exact outgoing pair through commit generation | covered-by-existing | None required; for optional real capture, use isolated `PI_CODING_AGENT_DIR/models.json`, not the repro extension, and trigger thread-title regeneration through server RPC |
| F04 Reported slash model ID | Shared resolver; provider plain, model ID contains `/` | Inventory matching preserves the complete model ID; guards against an incorrect last-slash implementation | Adapter regression's first turn asserts the exact slash-containing model ID; F03 proves the second caller uses this same resolver | covered-by-existing | None; no separate title / commit / client capture |
| F05 Both IDs contain slashes | Shared resolver; a unique reported pair such as synthetic provider `audit/hub` and model `family/model` | Changed: exact inventory pair must survive slashes on both sides simultaneously | Existing tests cover a slash on either side separately; no joint fixture or transcript | needs-capture | Register the synthetic pair in a Pi extension, select its slug through a T3 server turn, and record selected provider/model plus ACK and outcome. Use a local alias-forwarder to a real hub model if needed; keep its real identifier out of uploaded logs. A models.json registration also supports the background path, but duplicate captures of the resolver are unnecessary |
| F06 Colliding concatenated slugs | Inventory contains synthetic pairs (`audit/hub`, `family/model`) and (`audit`, `hub/family/model`), which share one slug | Changed: resolver chooses the first matching inventory pair. Discovery already deduplicates by slug in that order; selection must agree with the advertised first pair | Neither named regression includes a collision or ordering assertion | needs-capture | Register both pairs with a Pi extension; record raw ordered inventory privately and a sanitized pair mapping publicly. Select the one exposed slug through T3 RPC and verify first-pair selection. Reverse order in another fresh runtime if proving both orderings. Can extend F05's capture |
| F07 Unreported well-formed custom slug | Shared resolver receives empty/no matching inventory; includes ordinary provider with slash-containing model IDs, or an unavailable extension-only slug | Fallback preserves the first-slash split; an unavailable model remains an explicit Pi rejection, never silently defaulted | Adapter default-restore test asserts the exact ordinary pair with fake inventory empty. Text-generation test `names the model and the disabled extensions when Pi cannot load it` returns discovery success without inventory data, reaches `set_model`, checks the rejection, and asserts no prompt | covered-by-existing | None for this fallback branch. Stock real Pi uses the same available snapshot for inventory and `set_model`: a truly absent pair normally rejects. A custom model setting alone does not register it in Pi. Successful late availability belongs to F10 |
| F08 Default and reverse transition | Adapter initial default, explicit model → default, failed restore → retry; background `default` | Default bypasses resolver. Adapter restores structured baseline pair and thinking; background skips inventory and `set_model` | Adapter `resets applied thinking when returning to Pi default (failed first restore: %s)` and `preserves explicit thinking when switching models to %s in the same runtime`; background `runs Pi offline, since the process is stopped as soon as it answers` successfully generates with default | covered-by-existing | None; default provider/model spelling does not introduce a split because the baseline is already structured |
| F09 Stable inventory reuse and downstream options | Adapter switches between reported models over two turns; context capacity, explicit thinking, and service-tier behavior | Retained inventory replaces the discovery boolean; selecting a new slug uses cached pairs, then existing option/context handling continues | Named adapter regression selects the slash-model pair, settles the turn, then selects the slash-provider pair using the retained inventory. Existing thinking/default tests and `budgets legacy native history with Pi's selected model capacity` cover downstream state; `applies the selected service tier without changing thinking` covers inherited tier code | covered-by-existing | None; do not multiply every slug shape by every unchanged option, compact, continuation, and client path |
| F10 Registry changes after adapter cache | Adapter inventory is captured, then extension registration/reload adds a new pair. Test an ordinary provider and a slash provider absent from the captured list | New cached identity lookup cannot find a later pair. Ordinary provider still works by fallback; slash provider still falls back incorrectly and may reject. Successful initial inventory is not refreshed merely by a session switch. These are limits of the claimed fix, not a new regression claim | Two-turn regression uses an unchanged inventory; no late registration/reload fixture | needs-capture | Extension exposes a command that registers a provider after the first turn; drive command then explicit model selection through server RPC in the same runtime. Use one ordinary provider control and one slash provider. A session reload that changes provider registrations is an alternative. Capture discovery timing, real Pi availability, and T3 outcome; background requests are fresh and do not share this cache |
| F11 Inventory RPC failure / recovery | Both callers; discovery request returns a protocol error or times out, then select a known ordinary pair. Adapter later registration can retry discovery | Adapter retains prior best-effort fallback semantics but now lacks identity data; background adds a new fallible request and swallows its error before fallback. A slash provider cannot be reconstructed without inventory. Transport death must not be mislabelled as a recoverable inventory-only error | Status tests' optional-discovery failure concerns the separate status probe, not these callers. Text-generation fake's missing success payload is not a failed RPC. No named test reaches either caller's inventory-error catch | needs-capture | Not directly seedable using stock Pi models.json or supported provider registration: real Pi answers inventory synchronously from its model-runtime snapshot. Use a scratch protocol interposer that launches real Pi, preserves IDs, and fault-injects only the inventory response (clearly label it injected); forward all selection/prompt traffic to real Pi. Run a real T3 dev server against that binary. Adapter: fail first inventory, use ordinary fallback, then register again and allow discovery to prove retry. Background: invoke title regeneration with inventory error and ordinary fallback. A timeout is a separate transport timing mechanism, not another slug fixture |
| F12 Malformed unreported custom slug | Both callers; no slash, leading slash, or trailing slash; no exact inventory pair | Unchanged format rejection remains after a newly preceding inventory lookup (new network step in background). Must not prompt on default or send a malformed `set_model` | No named test or transcript supplies malformed selected slugs; extension-only `demo/model`-shaped rejection is not format rejection | needs-capture | Add synthetic malformed entries to isolated T3 `customModels` (schema accepts strings) and select through server RPC; use an ordinary Pi inventory. Invoke an adapter turn and title regeneration. Record the provider/model-format error, no selection request, and no prompt. One parameterized driver can cover the three invalid forms without paid model responses |
| F13 Extension-only background boundary | Picker inventory includes an extension provider; helper strips extension arguments and disables extension loading | Existing limitation remains: no background match; fallback `set_model` rejects with actionable extension/models.json guidance | Text-generation `names the model and the disabled extensions when Pi cannot load it` checks error detail and no prompt. Repro extension alone is not a seed for successful background generation | covered-by-existing | None; successful background slash-provider proof is F03, which models a reported models.json pair |

## Source anchors

- [Resolver](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/rpc.ts#L63): first exact string-concatenation match, then first-slash fallback and format guard.
- [Adapter registration](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/adapter.ts#L2470), [selection](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/adapter.ts#L2551), and [turn caller](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/adapter.ts#L2732).
- [Background runner](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/textGeneration.ts#L43), [shared operations](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-core/src/server/textGenerationOperations.ts#L74), and [extension stripping](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/mcpInjection.ts#L269).
- [Adapter regression and adjacent behavior tests](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/adapter.test.ts#L2277), [background tests](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/textGeneration.test.ts#L105), [status parsing / first-slug deduplication](https://git.cafe/pingdotgg/t3code/blob/329de9bc42f156de7ae6886bccbfc4256d163022/packages/provider-pi/src/server/status.ts#L97).
- Seeding feasibility also checked against installed Pi's `dist/modes/rpc/rpc-mode.js` (`set_model` and `get_available_models` both use `getAvailableSnapshot()`), `docs/custom-provider.md` (dynamic registration), and `docs/environment-variables.md` (isolated agent directory). These are local installed-source observations, not new runtime captures.

## Coverage and cleanup

Read-only review completed within the 45-minute budget: full five-file diff, both production callers, all shared background operations and server call sites, tests named in the PR body, default/restoration and discovery failure boundaries, installed Pi RPC implementation and seed feasibility. No code changes, test executions, real provider turns, dev servers, pushes, or comments. Only this scratch artifact was created by this reviewer; no process was started that needs stopping. The worktree was clean at the start and at the last source inspection. The final status check showed externally introduced uncommitted changes in adapter.ts, adapter.test.ts, and rpc.ts. Those subsequent edits are excluded: this matrix audits the requested committed head and its existing PR-body proof.

FRICTION:
forge | GitCafe PR metadata/body named the older head while the remote branch and requested checkout named the merged head | Refresh mirrored head metadata after pushing; resolved this audit with read-only remote refs and comparison against the body revision.
other | Assigned worktree gained external uncommitted changes after source inspection | Keep proof review pinned to the requested commit; later edits require their own audit.

VERDICT: INSUFFICIENT F05, F06, F10, F11, F12
