gpt-5.4 @ low · codex-oauth

codex-oauthlow
config
gpt-5.4-eff-low--cli--codex-oauth--dev
batch
2026-07-19--unified
transport
codex-cli-oauth-chatgpt
protocol
cli · plan
served model
gpt-5.4
captured
Jul 18, 2026, 11:54 AM · N=2
variant
live
slot 0 · P-q · sandboxed iframe
gpt-5.4 @low · codex-oauth P-q slot 0 screenshot

The screenshot is the exact frozen pixels the similarity channels measured. Run live re-executes the raw output in a sandboxed iframe; its rendering depends on your browser and fonts and is not guaranteed to match the measured pixels.

similarity neighbors

within session 2026-07-19--unified

similarity measures convergence within this session — not quality.

Fidelity — does the card show the right data?

  • namematch
  • conditionmatch
  • datematch
  • max tempmatchshown: 25
  • min tempmatchshown: 16
  • hourlymatchcoverage 24/24 · 24 match · 0 mismatch · 0 not shown
  • request sidematch0 violation(s)

extractor fidelity-extractor-v1+Berlin-2026-07-15

Source — raw model output, one byte unchanged

download card.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=1280, initial-scale=1.0" />
  <title>Weather Card</title>
  <style>
    :root {
      --bg-1: #09111f;
      --bg-2: #14304b;
      --bg-3: #eabf6b;
      --panel: rgba(10, 16, 28, 0.72);
      --panel-strong: rgba(7, 12, 22, 0.86);
      --line: rgba(255, 255, 255, 0.12);
      --text: #f7f5ef;
      --muted: rgba(247, 245, 239, 0.68);
      --accent: #ffd38c;
      --accent-2: #8fd3ff;
      --cold: #7cc7ff;
      --warm: #ffb65c;
      --shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
    }

    * {
      box-sizing: border-box;
    }

    html, body {
      width: 1280px;
      height: 800px;
      margin: 0;
      overflow: hidden;
      font-family: Georgia, "Times New Roman", serif;
      color: var(--text);
      background:
        radial-gradient(circle at 15% 20%, rgba(255, 211, 140, 0.24), transparent 28%),
        radial-gradient(circle at 78% 18%, rgba(143, 211, 255, 0.18), transparent 30%),
        linear-gradient(135deg, var(--bg-1) 0%, var(--bg-2) 46%, #234a61 72%, var(--bg-3) 140%);
    }

    body::before,
    body::after {
      content: "";
      position: absolute;
      inset: 0;
      pointer-events: none;
    }

    body::before {
      background:
        linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
      background-size: 72px 72px;
      mask-image: linear-gradient(to bottom, rgba(0,0,0,0.55), transparent 90%);
    }

    body::after {
      background:
        radial-gradient(circle at 50% 120%, rgba(255, 236, 201, 0.2), transparent 34%),
        linear-gradient(to top, rgba(4, 8, 16, 0.35), transparent 40%);
    }

    .scene {
      position: relative;
      width: 100%;
      height: 100%;
      padding: 44px;
      display: grid;
      place-items: center;
    }

    .card {
      position: relative;
      width: 100%;
      height: 100%;
      border: 1px solid var(--line);
      border-radius: 34px;
      background:
        linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.02)),
        var(--panel);
      box-shadow: var(--shadow);
      backdrop-filter: blur(18px);
      overflow: hidden;
      display: grid;
      grid-template-columns: 1.15fr 1fr;
    }

    .card::before {
      content: "";
      position: absolute;
      inset: 0;
      background:
        radial-gradient(circle at 20% 25%, rgba(255, 211, 140, 0.14), transparent 20%),
        radial-gradient(circle at 82% 16%, rgba(143, 211, 255, 0.12), transparent 22%);
      pointer-events: none;
    }

    .left,
    .right {
      position: relative;
      padding: 42px 42px 36px;
    }

    .left {
      border-right: 1px solid var(--line);
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }

    .eyebrow {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      padding: 10px 16px;
      border: 1px solid rgba(255,255,255,0.1);
      border-radius: 999px;
      background: rgba(255,255,255,0.04);
      color: var(--muted);
      font-family: "Trebuchet MS", Verdana, sans-serif;
      font-size: 12px;
      letter-spacing: 0.18em;
      text-transform: uppercase;
    }

    .dot {
      width: 8px;
      height: 8px;
      border-radius: 999px;
      background: linear-gradient(135deg, var(--accent), #fff3d0);
      box-shadow: 0 0 20px rgba(255, 211, 140, 0.6);
    }

    .title-wrap {
      margin-top: 22px;
    }

    .location {
      margin: 0;
      font-size: 68px;
      line-height: 0.95;
      font-weight: 600;
      letter-spacing: -0.04em;
      max-width: 520px;
      text-wrap: balance;
    }

    .date {
      margin-top: 18px;
      color: var(--muted);
      font-size: 20px;
      line-height: 1.4;
      font-family: "Trebuchet MS", Verdana, sans-serif;
      letter-spacing: 0.04em;
      text-transform: uppercase;
    }

    .hero {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 26px;
      align-items: end;
      margin-top: 32px;
    }

    .temp-main {
      display: flex;
      align-items: flex-start;
      gap: 8px;
    }

    .temp-max {
      font-size: 132px;
      line-height: 0.82;
      font-weight: 600;
      letter-spacing: -0.08em;
      color: #fff7e7;
      text-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
    }

    .unit {
      margin-top: 16px;
      font-size: 28px;
      color: var(--accent);
      font-family: "Trebuchet MS", Verdana, sans-serif;
      letter-spacing: 0.08em;
    }

    .condition {
      align-self: center;
      padding-left: 10px;
    }

    .condition-name {
      font-size: 34px;
      line-height: 1.05;
      margin: 0 0 8px;
      font-weight: 600;
    }

    .condition-sub {
      color: var(--muted);
      font-size: 16px;
      line-height: 1.5;
      font-family: "Trebuchet MS", Verdana, sans-serif;
      max-width: 260px;
    }

    .stats {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 16px;
      margin-top: 34px;
    }

    .stat {
      min-height: 118px;
      border: 1px solid rgba(255,255,255,0.09);
      border-radius: 24px;
      background: rgba(255,255,255,0.045);
      padding: 18px 18px 16px;
    }

    .stat-label {
      color: var(--muted);
      font-family: "Trebuchet MS", Verdana, sans-serif;
      font-size: 12px;
      letter-spacing: 0.16em;
      text-transform: uppercase;
    }

    .stat-value {
      margin-top: 16px;
      font-size: 38px;
      line-height: 1;
      letter-spacing: -0.05em;
    }

    .stat-value.small {
      font-size: 26px;
      line-height: 1.1;
    }

    .footer-note {
      color: rgba(247, 245, 239, 0.56);
      font-size: 13px;
      line-height: 1.5;
      font-family: "Trebuchet MS", Verdana, sans-serif;
      letter-spacing: 0.03em;
    }

    .right {
      display: flex;
      flex-direction: column;
      min-width: 0;
    }

    .section-head {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 20px;
      margin-bottom: 22px;
    }

    .section-title {
      margin: 0;
      font-size: 32px;
      font-weight: 600;
      letter-spacing: -0.03em;
    }

    .section-meta {
      color: var(--muted);
      font-size: 14px;
      font-family: "Trebuchet MS", Verdana, sans-serif;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      white-space: nowrap;
    }

    .hourly-shell {
      position: relative;
      flex: 1;
      border: 1px solid rgba(255,255,255,0.09);
      border-radius: 28px;
      background:
        linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.015)),
        var(--panel-strong);
      overflow: hidden;
      padding: 24px 22px 16px;
    }

    .hourly-shell::before {
      content: "";
      position: absolute;
      inset: 0;
      background:
        linear-gradient(to bottom, rgba(255,255,255,0.035), transparent 20%),
        linear-gradient(to right, rgba(255,255,255,0.03) 1px, transparent 1px);
      background-size: 100% 100%, calc(100% / 6) 100%;
      pointer-events: none;
      opacity: 0.45;
    }

    .hourly-grid {
      position: relative;
      display: grid;
      grid-template-columns: repeat(6, minmax(0, 1fr));
      gap: 12px;
      height: 100%;
      align-content: start;
    }

    .hour {
      min-width: 0;
      padding: 14px 12px 12px;
      border-radius: 18px;
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.06);
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      gap: 18px;
      min-height: 118px;
      transform: translateY(18px);
      opacity: 0;
      animation: rise 700ms cubic-bezier(.2,.8,.2,1) forwards;
    }

    .hour:nth-child(odd) {
      background: rgba(255,255,255,0.055);
    }

    .hour-time {
      color: var(--muted);
      font-family: "Trebuchet MS", Verdana, sans-serif;
      font-size: 12px;
      letter-spacing: 0.14em;
      text-transform: uppercase;
    }

    .hour-temp {
      font-size: 30px;
      letter-spacing: -0.05em;
      line-height: 1;
    }

    .bar {
      height: 6px;
      border-radius: 999px;
      background: rgba(255,255,255,0.08);
      overflow: hidden;
    }

    .bar-fill {
      height: 100%;
      border-radius: inherit;
      background: linear-gradient(90deg, var(--cold), var(--accent-2), var(--warm), var(--accent));
      transform-origin: left center;
    }

    .status,
    .error {
      position: absolute;
      inset: 44px;
      display: grid;
      place-items: center;
      border-radius: 28px;
      background: rgba(7, 12, 22, 0.7);
      border: 1px solid rgba(255,255,255,0.08);
      text-align: center;
      padding: 32px;
      z-index: 5;
    }

    .status-text,
    .error-text {
      max-width: 520px;
    }

    .status-title,
    .error-title {
      margin: 0 0 10px;
      font-size: 36px;
      letter-spacing: -0.04em;
    }

    .status-copy,
    .error-copy {
      margin: 0;
      color: var(--muted);
      font-size: 16px;
      line-height: 1.6;
      font-family: "Trebuchet MS", Verdana, sans-serif;
    }

    .hidden {
      display: none;
    }

    @keyframes rise {
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }
  </style>
</head>
<body>
  <div class="scene">
    <div class="card">
      <div class="left">
        <div>
          <div class="eyebrow">
            <span class="dot"></span>
            <span>Daily Weather Card</span>
          </div>

          <div class="title-wrap">
            <h1 class="location" id="location">Berlin</h1>
            <div class="date" id="dateLabel">Loading date</div>
          </div>

          <div class="hero">
            <div class="temp-main">
              <div class="temp-max" id="tempMax">--</div>
              <div class="unit">°C</div>
            </div>
            <div class="condition">
              <h2 class="condition-name" id="condition">Loading</h2>
              <div class="condition-sub" id="conditionDetail">Fetching weather details for the requested date.</div>
            </div>
          </div>

          <div class="stats">
            <div class="stat">
              <div class="stat-label">Maximum</div>
              <div class="stat-value" id="statMax">--°</div>
            </div>
            <div class="stat">
              <div class="stat-label">Minimum</div>
              <div class="stat-value" id="statMin">--°</div>
            </div>
            <div class="stat">
              <div class="stat-label">Source Day</div>
              <div class="stat-value small" id="statDay">--</div>
            </div>
          </div>
        </div>

        <div class="footer-note">
          Conditions and temperatures are shown in UTC for the requested date.
        </div>
      </div>

      <div class="right">
        <div class="section-head">
          <h3 class="section-title">Hourly Temperatures</h3>
          <div class="section-meta" id="hourlyMeta">24 readings</div>
        </div>

        <div class="hourly-shell">
          <div class="hourly-grid" id="hourlyGrid"></div>
        </div>
      </div>

      <div class="status" id="status">
        <div class="status-text">
          <h2 class="status-title">Loading weather</h2>
          <p class="status-copy">Requesting the selected date from the local Open-Meteo compatible API.</p>
        </div>
      </div>

      <div class="error hidden" id="error">
        <div class="error-text">
          <h2 class="error-title">Weather data could not be loaded</h2>
          <p class="error-copy" id="errorCopy">Please try again later.</p>
        </div>
      </div>
    </div>
  </div>

  <script>
    const weatherCodeMap = {
      0: "Clear sky",
      1: "Mainly clear",
      2: "Partly cloudy",
      3: "Overcast",
      45: "Fog",
      48: "Depositing rime fog",
      51: "Light drizzle",
      53: "Moderate drizzle",
      55: "Dense drizzle",
      56: "Light freezing drizzle",
      57: "Dense freezing drizzle",
      61: "Slight rain",
      63: "Moderate rain",
      65: "Heavy rain",
      66: "Light freezing rain",
      67: "Heavy freezing rain",
      71: "Slight snow fall",
      73: "Moderate snow fall",
      75: "Heavy snow fall",
      77: "Snow grains",
      80: "Slight rain showers",
      81: "Moderate rain showers",
      82: "Violent rain showers",
      85: "Slight snow showers",
      86: "Heavy snow showers",
      95: "Thunderstorm",
      96: "Thunderstorm with hail",
      99: "Thunderstorm with heavy hail"
    };

    const statusEl = document.getElementById("status");
    const errorEl = document.getElementById("error");
    const errorCopyEl = document.getElementById("errorCopy");

    function showError(message) {
      statusEl.classList.add("hidden");
      errorEl.classList.remove("hidden");
      errorCopyEl.textContent = message || "Please try again later.";
    }

    function hideStatus() {
      statusEl.classList.add("hidden");
      errorEl.classList.add("hidden");
    }

    function getDefaultDateUTC() {
      return new Date().toISOString().slice(0, 10);
    }

    function parseParams() {
      const params = new URLSearchParams(window.location.search);
      const lat = Number(params.get("lat"));
      const lon = Number(params.get("lon"));
      const date = params.get("date") || getDefaultDateUTC();
      return {
        latitude: Number.isFinite(lat) ? lat : 52.52,
        longitude: Number.isFinite(lon) ? lon : 13.405,
        name: params.get("name") || "Berlin",
        date
      };
    }

    function formatDisplayDate(isoDate) {
      const [y, m, d] = isoDate.split("-").map(Number);
      const dt = new Date(Date.UTC(y, m - 1, d));
      return new Intl.DateTimeFormat("en-US", {
        weekday: "long",
        year: "numeric",
        month: "long",
        day: "numeric",
        timeZone: "UTC"
      }).format(dt);
    }

    function isPastDate(isoDate) {
      return isoDate < getDefaultDateUTC();
    }

    function clamp(value, min, max) {
      return Math.max(min, Math.min(max, value));
    }

    function tempText(value) {
      return `${Math.round(value)}°`;
    }

    function buildHourly(hours) {
      const grid = document.getElementById("hourlyGrid");
      grid.innerHTML = "";

      const temps = hours.map(h => h.temp);
      const min = Math.min(...temps);
      const max = Math.max(...temps);
      const span = Math.max(1, max - min);

      hours.forEach((hour, index) => {
        const card = document.createElement("div");
        card.className = "hour";
        card.style.animationDelay = `${index * 28}ms`;

        const pct = clamp(((hour.temp - min) / span) * 100, 6, 100);

        card.innerHTML = `
          <div class="hour-time">${hour.time}</div>
          <div class="hour-temp">${tempText(hour.temp)}</div>
          <div class="bar"><div class="bar-fill" style="width:${pct}%"></div></div>
        `;
        grid.appendChild(card);
      });

      document.getElementById("hourlyMeta").textContent = `${hours.length} readings`;
    }

    function updateUI(model, requestedName, requestedDate) {
      document.getElementById("location").textContent = requestedName;
      document.getElementById("dateLabel").textContent = formatDisplayDate(requestedDate);
      document.getElementById("tempMax").textContent = Math.round(model.max);
      document.getElementById("condition").textContent = weatherCodeMap[model.code] || "Unknown conditions";
      document.getElementById("conditionDetail").textContent = `High of ${tempText(model.max)}, low of ${tempText(model.min)}.`;
      document.getElementById("statMax").textContent = tempText(model.max);
      document.getElementById("statMin").textContent = tempText(model.min);
      document.getElementById("statDay").textContent = requestedDate;
      buildHourly(model.hours);
      hideStatus();
    }

    async function loadWeather() {
      const { latitude, longitude, name, date } = parseParams();

      if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
        showError("The date parameter must use YYYY-MM-DD.");
        return;
      }

      const endpoint = isPastDate(date) ? "/api/om/archive" : "/api/om/forecast";
      const url = new URL(endpoint, window.location.origin);
      url.searchParams.set("latitude", String(latitude));
      url.searchParams.set("longitude", String(longitude));
      url.searchParams.set("daily", "temperature_2m_max,temperature_2m_min,weather_code");
      url.searchParams.set("hourly", "temperature_2m");
      url.searchParams.set("timezone", "UTC");
      url.searchParams.set("temperature_unit", "celsius");
      url.searchParams.set("start_date", date);
      url.searchParams.set("end_date", date);

      try {
        const res = await fetch(url.toString(), { headers: { "Accept": "application/json" } });
        if (!res.ok) {
          throw new Error(`Request failed with status ${res.status}.`);
        }

        const data = await res.json();

        const daily = data && data.daily;
        const hourly = data && data.hourly;

        if (
          !daily ||
          !hourly ||
          !Array.isArray(daily.time) ||
          !Array.isArray(daily.temperature_2m_max) ||
          !Array.isArray(daily.temperature_2m_min) ||
          !Array.isArray(daily.weather_code) ||
          !Array.isArray(hourly.time) ||
          !Array.isArray(hourly.temperature_2m) ||
          daily.time.length === 0
        ) {
          throw new Error("Response format was incomplete.");
        }

        const dayIndex = daily.time.indexOf(date);
        if (dayIndex === -1) {
          throw new Error("Requested date was not returned by the API.");
        }

        const hours = [];
        for (let i = 0; i < hourly.time.length; i += 1) {
          const t = hourly.time[i];
          if (typeof t === "string" && t.startsWith(date)) {
            const hh = t.slice(11, 16);
            hours.push({
              time: hh,
              temp: hourly.temperature_2m[i]
            });
          }
        }

        if (!hours.length) {
          throw new Error("No hourly temperatures were returned for the requested date.");
        }

        updateUI({
          max: daily.temperature_2m_max[dayIndex],
          min: daily.temperature_2m_min[dayIndex],
          code: daily.weather_code[dayIndex],
          hours
        }, name, date);
      } catch (err) {
        showError(err && err.message ? err.message : "Weather data could not be loaded.");
      }
    }

    loadWeather();
  </script>
</body>
</html>

L1 — cheap deterministic descriptors

bytes total18,697html / css / js2,640 / 9,187 / 6,870
dom nodes50dom depth9
css rules49js presentyes
brightness43.7contrast27.9
colorfulness16.3whitespace79.2%

This slot's telemetry

prompt tokens0completion tokens11,519
total tokens0wall102.8 s
costrequest id
config.json545 B
{
  "N": 2,
  "auth": {
    "credential_ref": "WCB_NONE",
    "method": "oauth-login"
  },
  "billing": "plan",
  "config_id": "gpt-5.4-eff-low--cli--codex-oauth--dev",
  "effort": "low",
  "family": "gpt",
  "m": {
    "min": 2,
    "q": 2
  },
  "model_id": "gpt-5.4",
  "protocol": "cli",
  "served_model": "gpt-5.4",
  "telemetry": {
    "completion_tokens": 44880,
    "cost_usd": null,
    "prompt_tokens": null,
    "total_tokens": null,
    "wall_ms": 359416
  },
  "transport": "codex-cli-oauth-chatgpt",
  "vendor_sanction_ref": null
}
send-log2.5 KB
{
  "N": 2,
  "batch_id": "2026-07-17--dev-codex-oauth-gpt-5.4",
  "config_id": "gpt-5.4-eff-low--cli--codex-oauth--dev",
  "positions": [
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-17T13:59:21.331939+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-17T13:58:02.712857+00:00"
        }
      ],
      "block_index": 0,
      "model_reaching_attempt_index": 0,
      "slot_index": 0,
      "terminal_state": "valid",
      "variant": "P-min"
    },
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-17T14:01:07.607888+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-17T13:59:24.850108+00:00"
        }
      ],
      "block_index": 0,
      "model_reaching_attempt_index": 0,
      "slot_index": 0,
      "terminal_state": "valid",
      "variant": "P-q"
    },
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-17T14:02:48.749903+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-17T14:01:11.392546+00:00"
        }
      ],
      "block_index": 1,
      "model_reaching_attempt_index": 0,
      "slot_index": 1,
      "terminal_state": "valid",
      "variant": "P-q"
    },
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-17T14:04:13.899707+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-17T14:02:53.208420+00:00"
        }
      ],
      "block_index": 1,
      "model_reaching_attempt_index": 0,
      "slot_index": 1,
      "terminal_state": "valid",
      "variant": "P-min"
    }
  ],
  "retry_policy": {
    "max_unreachable_retries": 5,
    "rate_limit_backoff": {
      "max_attempts": 4,
      "max_total_ms": 60000
    }
  }
}