feat(profile): use 5x8 rendering for opt-in Sol

This commit is contained in:
Steven Chong
2026-07-11 18:18:30 -04:00
parent 0025a6a2d5
commit 318d90e882
6 changed files with 22 additions and 32 deletions
+4 -6
View File
@@ -29,12 +29,10 @@ let runtimeModelBases: readonly string[] | null = null;
* - Opus 4.7/4.8 — worse at reading imaged content (FINDINGS.md 2026-06-16:
* Opus 4.8 ~2pp arithmetic, 6/15 dense-hex vs Fable 100/100).
* - GPT 5.5 — degrades on imaged history/context.
* - GPT 5.6 Sol — direct raw-image calls at both its 6×11 profile and the
* old shared 5×8 profile scored 0/4 exact with four confabulations. Its
* exact model profile remains available for explicit opt-in and retuning.
* - Grok 4.5 — packing + factsheet works for exact IDs, but pure-image is
* not Fable-level and the full quality suite is incomplete. Opt-in only
* until multi-seed + novel arithmetic clear a Fable-class bar.
* - GPT 5.6 Sol — 98/100 production arithmetic, but 79/93 completed gist,
* 4/15 completed guard confabulations, and 0/15 dense hex.
* - Grok 4.5 — 82/100 arithmetic, 83/98 gist, and 13/18 state tracking.
* Both profiles remain available for explicit opt-in.
* Silently imaging weak or unvalidated readers is the wrong default. */
const DEFAULT_MODEL_BASES = ['claude-fable-5'];
+6 -12
View File
@@ -104,11 +104,11 @@ export const DEFAULT_GPT_PROFILE: GptModelProfile = {
const GPT56_SOL_PROFILE: GptModelProfile = {
vision: { regime: 'patch', multiplier: 1, patchCap: 10000 },
stripCols: 126,
// Native 5×8 cells fit 152 columns at OpenAI's 768px short-side floor.
// Sol remains opt-in because broader recall is below the Fable bar.
stripCols: C,
maxHeightPx: H,
// Separate atlas selected by model id. Cell remains within OpenAI's 768px
// short-side floor (126 cols x 6px + padding = 764px).
style: { ...BASE_STYLE, font: 'jetbrains-mono-10' },
style: { ...BASE_STYLE, font: 'spleen-5x8' },
};
interface ProfileRule {
@@ -176,14 +176,8 @@ const BUILTIN_RULES: ProfileRule[] = [
},
},
// Grok (Responses path). Opt-in only (not Fable-level pure-image). Profile:
// Best stable pure-image recipe from brute force: stock Spleen 5×8, white AA,
// no grid, maxHeight 512, width 152 (768 short-side floor), plus an in-image
// IDS block is applied on every model path (appendIdsBlock); Grok still
// needs white AA + short pages. White+ids_block: 7/7 full 4/4 on grok-4.5
// pure-image (no factsheet).
// paperGray 240 without grid confabulates ports; grid alone does not fix hex.
// Fact-sheet remains optional defense in depth.
// Grok remains opt-in. It shares the 5×8 production stack but uses shorter
// pages because its dense-image recall falls with taller strips.
{
test: (m) => /^grok-/.test(m),
profile: {
+1 -3
View File
@@ -21,9 +21,7 @@
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createProxy } from '../src/core/proxy.js';
// These proxy-contract tests deliberately exercise the opt-in Sol transform.
// Snapshot the developer shell so the suite is deterministic now that Sol is
// intentionally absent from the built-in default scope.
// Pin the model scope so these proxy-contract tests stay independent of the developer shell.
let ambientPxpipeModels: string | undefined;
beforeAll(() => {
ambientPxpipeModels = process.env.PXPIPE_MODELS;
+2 -2
View File
@@ -931,8 +931,8 @@ describe('resolveGptProfile (Claude on Responses)', () => {
]) {
const sol = resolveGptProfile(model);
expect(sol.maxHeightPx, model).toBe(1932);
expect(sol.stripCols, model).toBe(126);
expect(sol.style.font, model).toBe('jetbrains-mono-10');
expect(sol.stripCols, model).toBe(152);
expect(sol.style.font, model).toBe('spleen-5x8');
}
for (const model of ['gpt-5.6', 'gpt-5.6-terra', 'gpt-5.6-terra[1m]']) {
const notSol = resolveGptProfile(model);
+5 -4
View File
@@ -83,6 +83,7 @@ describe('public library API', () => {
// null clears the override → back to the Fable-only default
setAllowedModelBases(null);
expect(isPxpipeSupportedModel('claude-fable-5')).toBe(true);
expect(isPxpipeSupportedGptModel('gpt-5.6-sol')).toBe(false);
expect(isPxpipeSupportedGptModel('grok-4.5')).toBe(false);
expect(isPxpipeSupportedModel('claude-opus-4-8')).toBe(false);
} finally {
@@ -90,7 +91,7 @@ describe('public library API', () => {
}
});
it('keeps GPT 5.6 Sol off by default but preserves exact opt-in aliases', () => {
it('keeps GPT 5.6 Sol aliases opt-in by default', () => {
expect(isPxpipeSupportedGptModel('gpt-5')).toBe(false);
expect(isPxpipeSupportedGptModel('gpt-5.5')).toBe(false);
expect(isPxpipeSupportedGptModel('gpt-5.5-codex')).toBe(false);
@@ -110,9 +111,9 @@ describe('public library API', () => {
expect(isPxpipeSupportedGptModel('gpt-5.6-terra')).toBe(false);
});
it('keeps Grok and Sol opt-in only (off by default, like Opus)', () => {
// Grok packing + factsheet helps exact IDs, but pure-image is not Fable-
// level and the full quality suite is incomplete — opt-in only.
it('keeps Grok and Sol opt-in by default', () => {
// Grok remains opt-in because its arithmetic, gist, and state results are
// below the Fable bar.
const prev = process.env.PXPIPE_MODELS;
try {
delete process.env.PXPIPE_MODELS;
+4 -5
View File
@@ -23,8 +23,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createProxy, type ProxyEvent } from '../src/core/proxy.js';
import { countTokens as o200k } from 'gpt-tokenizer/encoding/o200k_base';
// The GPT tests below drive 'gpt-5.6-sol', which is intentionally absent from
// the built-in default scope (Fable 5 + Grok 4.5). Pin PXPIPE_MODELS so the suite is
// The GPT tests below drive exact Sol. Pin PXPIPE_MODELS so the suite is
// deterministic regardless of the developer's shell (same convention as
// proxy-usage.test.ts) — without this, the file passes or fails depending on
// ambient env, which is exactly what broke CI.
@@ -162,10 +161,10 @@ describe('savings math — GPT, cross-checked against the real o200k tokenizer',
it('DECLINES A LOSER: refuses to image content where imaging would cost more than the real text', async () => {
// Dense long-line slab: few o200k text tokens relative to vision pages.
// (The old 2k prose fixture is now profitable under Sol 6×11 packing — ~216
// image vs ~500 text tokens — so it no longer exercises the decline path.)
// Use enough low-token-density alphabet runs to remain a loser under the denser
// Sol 5×8 packing; the gate must still reject it.
const sys = Array.from({ length: 80 }, (_, i) =>
`LINE${i} ` + 'abcdefghijklmnopqrstuvwxyz'.repeat(20),
`LINE${i} ` + 'abcdefghijklmnopqrstuvwxyz'.repeat(40),
).join('\n');
const realTok = o200k(sys);
const body = JSON.stringify({