#!/usr/bin/env node /** * model-mortality.mjs · HOW LONG DOES AN AI-VISIBILITY STUDY STAY REPRODUCIBLE? (2026-09-23) * * ═══════════════════════════════════════════════════════════════════════════════════════════════ * THE FINDING THIS EXISTS TO MEASURE REPEATEDLY. * Lattice published an AI-search disagreement index in June 2026 across a named engine panel. In * September 2026, probed live: FOUR of the five Groq-hosted models in that panel return * model_not_found. The study cannot be re-run. Not "is expensive to re-run" — cannot, at any price, * because the instruments no longer exist. * ★ EVERY PUBLISHED AI-VISIBILITY BENCHMARK HAS A SHELF LIFE, AND NOBODY PRINTS AN EXPIRY DATE. * * WHY IT MATTERS COMMERCIALLY, NOT JUST ACADEMICALLY. A vendor's visibility dashboard is a claim * about a model that may be gone next quarter. If the instrument expires, then a CONTINUOUS series * captured while the models were alive is the only asset that cannot be reconstructed later — you * can buy compute, you cannot buy a snapshot of a model that has been retired. * * ⛔ WHAT THIS DOES NOT CLAIM. A model_not_found is a claim about THIS provider's catalogue on THIS * date, not about the weights existing in the world. Llama 3.3 still exists; Groq stopped serving * it. The finding is about REPRODUCIBILITY OF A HOSTED MEASUREMENT, which is what every vendor in * this category actually sells, and the distinction is printed in the output so nobody overstates it. * * ⚠️ A probe needs a POSITIVE CONTROL or it cannot tell "model retired" from "my key died". Every * run asks a known-good model first and refuses to report if that fails. * * usage: node variance/model-mortality.mjs [--write] */ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; const HERE = import.meta.dirname; const WRITE = process.argv.includes('--write'); const key = (n) => { const p = path.join(os.homedir(), `.${n}`); return fs.existsSync(p) ? fs.readFileSync(p, 'utf8').trim().split('\n')[0].trim() : null; }; /* The engine roster this estate has USED in a published or frozen artifact, with when it was last seen working. Sources: tracker-core.mjs UNAVAILABLE map, collect.js ENGINE_META, and the frozen snapshots in tracker/snapshots/. ⛔ Only models we actually ran — not a catalogue of everything that ever existed, which would make the mortality rate meaningless. */ const ROSTER = [ { id: 'gpt-oss-120b', lab: 'OpenAI (open weights)', host: 'Groq', model: 'openai/gpt-oss-120b', firstUsed: '2026-07-18', provider: 'groq' }, { id: 'gpt-oss-20b', lab: 'OpenAI (open weights)', host: 'Groq', model: 'openai/gpt-oss-20b', firstUsed: '2026-09-23', provider: 'groq' }, { id: 'llama-3.3-70b', lab: 'Meta', host: 'Groq', model: 'llama-3.3-70b-versatile', firstUsed: '2026-06-19', lastSeen: '2026-08-17', provider: 'groq' }, { id: 'llama-4-scout', lab: 'Meta', host: 'Groq', model: 'meta-llama/llama-4-scout-17b-16e-instruct', firstUsed: '2026-06-19', lastSeen: '2026-07-08', provider: 'groq' }, { id: 'qwen-3.6-27b', lab: 'Alibaba', host: 'Groq', model: 'qwen/qwen3.6-27b', firstUsed: '2026-07-18', lastSeen: '2026-09-01', provider: 'groq' }, { id: 'compound', lab: 'Groq', host: 'Groq', model: 'groq/compound', firstUsed: '2026-06-19', provider: 'groq' }, { id: 'compound-mini', lab: 'Groq', host: 'Groq', model: 'groq/compound-mini', firstUsed: '2026-06-19', provider: 'groq' }, { id: 'gemini-2.5-flash', lab: 'Google', host: 'Google', model: 'gemini-2.5-flash', firstUsed: '2026-06-19', provider: 'gemini' }, { id: 'gemini-2.5-flash-lite', lab: 'Google', host: 'Google', model: 'gemini-2.5-flash-lite', firstUsed: '2026-09-05', provider: 'gemini' }, ]; const CONTROL = { provider: 'groq', model: 'openai/gpt-oss-120b' }; async function probe(provider, model) { try { if (provider === 'groq') { const k = key('groq-api-key'); if (!k) return { state: 'NO KEY' }; const r = await fetch('https://api.groq.com/openai/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + k }, body: JSON.stringify({ model, messages: [{ role: 'user', content: 'hi' }], max_tokens: 2 }) }); const j = await r.json(); if (j.choices) return { state: 'ALIVE' }; const s = JSON.stringify(j.error || j); return { state: /model_not_found|does not exist|decommission/i.test(s) ? 'RETIRED' : /rate|quota|429/i.test(s) ? 'QUOTA' : 'ERROR', detail: s.slice(0, 90) }; } if (provider === 'gemini') { const k = key('gemini-api-keys') || key('gemini-api-key'); if (!k) return { state: 'NO KEY' }; const r = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${k}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: 'hi' }] }] }) }); const j = await r.json(); if (j.candidates) return { state: 'ALIVE' }; const s = JSON.stringify(j.error || j); // ⚠️ A 429 means the model IS there and the quota is not. Never score that as retired. return { state: /RESOURCE_EXHAUSTED|429|quota/i.test(s) ? 'QUOTA (alive)' : /not found|NOT_FOUND|not supported/i.test(s) ? 'RETIRED' : 'ERROR', detail: s.slice(0, 90) }; } return { state: 'UNKNOWN PROVIDER' }; } catch (e) { return { state: 'ERROR', detail: String(e.message).slice(0, 90) }; } } const ctl = await probe(CONTROL.provider, CONTROL.model); if (ctl.state !== 'ALIVE') { console.error(`REFUSED: positive control (${CONTROL.model}) is ${ctl.state}. Cannot tell a retired model from a broken key. ${ctl.detail || ''}`); process.exit(3); } console.log(`positive control OK (${CONTROL.model} answers)\n`); const results = []; for (const m of ROSTER) { const r = await probe(m.provider, m.model); results.push({ ...m, ...r }); console.log(` ${String(r.state).padEnd(14)} ${m.id.padEnd(22)} ${m.lab} via ${m.host}`); await new Promise((s) => setTimeout(s, 400)); } const retired = results.filter((r) => r.state === 'RETIRED'); const alive = results.filter((r) => r.state === 'ALIVE' || r.state === 'QUOTA (alive)'); console.log(`\nroster: ${results.length} models this estate has actually run`); console.log(` alive : ${alive.length}`); console.log(` RETIRED: ${retired.length} (${Math.round(100 * retired.length / results.length)}% of the roster)`); if (retired.length) { const spans = retired.filter((r) => r.lastSeen).map((r) => (new Date(r.lastSeen) - new Date(r.firstUsed)) / 86400000); if (spans.length) console.log(` median observed service life before retirement: ${Math.round(spans.sort((a, b) => a - b)[Math.floor(spans.length / 2)])} days`); } console.log('\n⛔ RETIRED means this PROVIDER no longer serves this model id on this date. The weights may'); console.log(' still exist elsewhere. The claim is about the reproducibility of a HOSTED measurement,'); console.log(' which is what AI-visibility products actually sell.'); if (WRITE) { const out = path.join(HERE, `model-mortality-${new Date().toISOString().slice(0, 10)}.json`); fs.writeFileSync(out, JSON.stringify({ _contract: 'Live availability of models this estate has run in a published or frozen artifact. RETIRED = provider returns model_not_found on this date; it is not a claim that the weights ceased to exist. Positive control required.', probedAtUTC: new Date().toISOString(), control: CONTROL.model, roster: results.length, alive: alive.length, retired: retired.length, results, }, null, 1) + '\n'); console.log(`\nWROTE ${path.basename(out)}`); }