Model Inversion
Heuristic author-family detection and alternate review-model routing: built, default off, and not forwarded into native containers.
Status
Built and off by default in son-of-anton-review (feat/cloudflare-native). GILF_MODEL_INVERSION=1 enables the engine hook when supplied to the actual runner process. It can reroute the primary semantic review; planner and shadow-worker provider settings are separate.
Native forwarding gap: cloudflare-native/src/container-env.js does not forward GILF_MODEL_INVERSION, GILF_MODEL_INVERSION_MIN_CONFIDENCE or GILF_MODEL_INVERSION_MAP. The entrypoint does not pass an inversion override. Setting these only on the Worker does not enable inversion in the container. Code integration is needed before that deployment can use the settings.
| Setting | Default | Effect |
|---|---|---|
GILF_MODEL_INVERSION | off | Enable. Truthy values: 1, true, yes, on |
GILF_MODEL_INVERSION_MIN_CONFIDENCE | 0.5 | Skip inversion when detection confidence is below this (0 to 1) |
GILF_MODEL_INVERSION_MAP | built-in map | JSON override of family to provider/model routing |
Source: src/author-model.js, src/codex-review-runner.js (#chooseReviewProvider).
Why
Inversion is a routing heuristic: infer an authoring family from textual provenance and select a different family. The engine does not establish that this improves review accuracy, and inferred provenance is not proof of who authored the code.
Detection
detectAuthoringModel is a pure function. It reads no network, only the PR and its commits.
Inputs the runner passes:
| Input | Where it comes from |
|---|---|
| Commits | git log origin/<base>..HEAD, falling back to the last 30 commits. Trailers, message body, author name and email |
| Branch | PR head ref, matched on prefixes like claude/, codex/, copilot/, gemini/ |
| PR title and body | Explicit provenance phrases and product-name mentions |
Each hit becomes a weighted signal:
| Signal | Weight | Example |
|---|---|---|
Co-authored-by trailer or commit author | 1.0 | noreply@anthropic.com |
| Strong marker in text | 1.0 | Generated with Claude Code, codex[bot] |
| Branch prefix | 0.8 | codex/fix-retry |
| Name mention in title or body | 0.4 | ChatGPT, Gemini |
| Robot emoji | 0.2 | Only reinforces a family already seen in the same source |
Output: { family, confidence, signals }. Supported family labels are anthropic, openai, google, human and unknown. No matching signals returns human with confidence 1; that means “no supported model signal found,” not verified human authorship. Otherwise confidence is signal strength (1 - e^-score) scaled by agreement and rounded to two decimals. Diagnostic match text is clipped to 120 characters.
Routing
chooseReviewProvider returns a routing reason. These are helper results; when inversion is disabled, the runner returns before detection and does not create an analysis.modelInversion record.
| Reason | Meaning |
|---|---|
disabled | Helper received an off flag; the runner normally short-circuits before calling it |
low_confidence | Confidence below GILF_MODEL_INVERSION_MIN_CONFIDENCE |
no_target | Family maps to null (default for human and unknown) |
target_not_configured | Target provider has no credentials configured |
target_same_family | Target would be the same family as the author |
inverted | Review rerouted |
Default map routes through OpenRouter, the recommended provider:
{
"anthropic": { "provider": "openrouter", "model": "openai/gpt-4.1" },
"openai": { "provider": "openrouter", "model": "anthropic/claude-sonnet-4-5" },
"google": { "provider": "openrouter", "model": "anthropic/claude-sonnet-4-5" },
"human": null,
"unknown": null
}GILF_MODEL_INVERSION_MAP merges valid override entries onto the defaults. A null target disables a family. Invalid JSON retains the defaults; if routing reaches map resolution, the parse error is appended to no_target or inverted. Earlier disabled/low_confidence or target-configuration failures need not carry it.
For a directly launched engine process, this example enables inversion, raises the confidence threshold and opts into potentially paid OpenRouter targets:
export GILF_MODEL_INVERSION=1
export GILF_MODEL_INVERSION_MIN_CONFIDENCE=0.7
export GILF_MODEL_INVERSION_MAP='{"anthropic":{"provider":"openrouter","model":"openai/gpt-4.1"},"google":null}'
export GILF_OPENROUTER_REQUIRE_FREE=0Direct openai and anthropic targets are supported and the inversion record marks them paid: true. This is a routing annotation, not a billing quote or a guarantee that credentials/models are usable.
Where it plugs in
- The runner reaches the normal semantic-review branch. A docs-only or validation-failure shortcut bypasses inversion. Hypothesis-primary mode bypasses it only when usable swarm output is actually selected and prepared review-memory text is empty.
#chooseReviewProviderruns detection and routing, then emitsmodel_inversion_evaluatedwith thedescribeInversionstring, for examplemodel-inversion: author=anthropic -> review via openrouter/openai/gpt-4.1.- Evaluation is stored as
analysis.modelInversionwithfamily,confidence,inverted,reason,provider,model, commit count and the first eight signals.paidis only added on applicable routing branches. - If the inverted semantic provider throws, the runner emits
model_inversion_fallback, records the fallback and retries the configured provider once. If that also fails, the existing recovery logic may use usable swarm output, or a deterministic recovery whenGILF_PUBLISH_ON_CODEX_FAILURE=1; otherwise the review fails. That recovery flag is also absent from native container forwarding. - Any exception inside detection or routing is caught, logged as
model_inversion_failed, and the review continues uninverted.
Free-model guard
GILF_OPENROUTER_REQUIRE_FREE defaults on; only the exact value 0 disables it. For an OpenRouter inversion target, the runner fetches model metadata and requires zero prompt and completion prices. A price-check error or refusal records reason: openrouter_model_not_free and leaves the original provider selected.
The built-in target IDs are routing defaults, not embedded price guarantees. With the default guard, rerouting only occurs if the provider's returned metadata passes the zero-price check. To permit non-zero prices for the review:
# allow paid OpenRouter models for the whole review
export GILF_OPENROUTER_REQUIRE_FREE=0Alternatively, configure targets whose current metadata passes the free-model check. This guard is forwarded by the native container, but forwarding it does not enable the unforwarded inversion feature.
Caveats
- The native image containing
src/author-model.jsis not enough: the flag still has to reachCodexReviewRunner. No deployed inversion behavior is claimed here. - Detection is textual. A single product-name mention in PR title/body has weight 0.4 and confidence about 0.33, below the default threshold. Repeated or stronger provenance signals can increase confidence.
- The planner and shadow swarm retain their own settings. See Hypotheses and swarm.
Source evidence
son-of-anton-review/src/author-model.js:11-55,103-190,198-241.son-of-anton-review/src/codex-review-runner.js:2245-2270,2309-2314,2327-2329,2620-2709,3457-3509.son-of-anton-review/cloudflare-native/src/container-env.js:15-85;cloudflare-native/container/entrypoint.mjs:345-374.