Files
hanzo.ai/app/sitemap.ts
zeekay d01992490a Every Enso figure is read from its research runs when a page opens, and the leaderboard snapshot is gone
/enso leads with three lines built from the enso.* runs: the router at
92.9% on GPQA Diamond, level with the pool's best single model, at $2.20,
5x less than Opus 4.8 (86.4%, $10.97); LiveCodeBench 93.7% at $3.06,
12.9x less than Opus 4.8 (72.0%, $39.43); and the pool's ceiling, 98.0%
(194/198) with four arms, said only as the ceiling the router is trained
toward. Under them a note says what that router was: enso-bench's at the
tag its run names, and the arms its notes count, not today's presets.
Every percentage and multiple is computed from the runs.

A board is each system's frontier run, else its v1 run (the same prompts;
v2 and max put others), over the whole set, none degraded. The GPQA and
LiveCodeBench boards draw on /enso, /models/enso and /benchmarks, the
GPQA one with the ceiling under it on /benchmarks/gpqa. /benchmarks' Enso
title, figure, hero tile and frontier (now accuracy against what the run
cost), the /models family card and the home tile read the same runs, and
each says the API is unreachable rather than show an older number.

lib/data/leaderboard.json and lib/leaderboard.ts are deleted: their Enso
tiers (98.0, 96.0, 92.9) were no run's, 98.0 being the pool's oracle.
With them go the vendor-reported field, the accuracy-at-cost scatter, the
reported-versus-measured browser, the shelf's Enso entries and the two
pages they generated, and the logo files only the scatter read. A preset
card keeps its name and rate and states no score. The gates serve
invented runs and hold every surface, the ceiling's figure and the
unreachable state to lib/enso.
2026-10-15 15:18:16 -07:00

112 lines
6.2 KiB
TypeScript

import type { MetadataRoute } from 'next'
import { readdirSync } from 'node:fs'
import { join } from 'node:path'
import { indexable } from '@/lib/publish'
import { changed, latest, routes, sources } from '@/lib/routes'
import { BENCHMARKS } from '@/lib/benchmarks'
import { GENERATED, LEDGER } from '@/lib/bench-data'
import { featured } from '@/lib/data/customers'
import { cloudPrimitiveSlugs } from '@/lib/data/cloud-primitives'
import { SOLUTIONS, href as solutionHref } from '@/lib/data/solutions'
import { OWNED } from '@/lib/go-modules'
import { INTEGRATIONS } from '@/lib/integrations'
import { LAYERS, href } from '@/lib/layers'
import { COMPARISONS } from '@/lib/comparisons'
import { legalSlugs } from '@/lib/legal'
import { careerSlugs } from '@/lib/careers'
import { COURSE_PAGES } from '@/app/(marketing)/university/courses-data'
import { canonicalOrg, getOrgAndSlug, modelPagePath } from '@/lib/models'
import { fetchModels } from '@/lib/models/served'
// Static export: emits /sitemap.xml at build by walking the App Router tree.
export const dynamic = 'force-static'
const BASE = 'https://hanzo.ai'
/**
* When a benchmark page last changed, which is when its RUNS last changed.
*
* A bench page is a rendering of a run file. Editing the prose beside a table
* does not make the result newer, and rerunning a benchmark does make it newer
* even if no file in this repository was touched by hand. So the date offered
* to a crawler is the `generated` stamp `node results.mjs` wrote into the run
* file itself — the only date here that means anything.
*
* Benchmarks whose runs carry no stamp are dated like every other page, by
* their files' last commit. A build timestamp would be a plausible-looking lie
* that changes on every deploy.
*/
const STAMPED = new Map([
...BENCHMARKS.filter((b) => b.data !== null).map((b): [string, Date] => [`/benchmarks/${b.slug}`, new Date(GENERATED[b.data!])]),
// A ledger page (/benchmarks/[slug]) is as new as its newest dated result.
...LEDGER.entries.flatMap((e): [string, Date][] => {
const days = LEDGER.results.filter((r) => r.entry === e.slug && r.date).map((r) => r.date!)
return e.own || !days.length ? [] : [[e.href, new Date(`${days.sort().at(-1)}T00:00:00Z`)]]
}),
])
/** A dynamic segment's directory, under the marketing group. */
const seg = (...parts: string[]) => join(process.cwd(), 'app', '(marketing)', ...parts)
const file = (...parts: string[]) => join(process.cwd(), ...parts)
/**
* The pages the dynamic segments generate, read from the data each segment
* generates them from, each with the files it is made of: the segment's own
* directory and its data. The tree walk cannot see them, and a public page left
* out of the sitemap is a page a crawler is never told about.
*/
async function generated(): Promise<[string, string[]][]> {
const { models } = await fetchModels()
const made = (dir: string, ...data: string[]) => [...readdirSync(dir).map((f) => join(dir, f)), ...data]
const layer = made(seg('products', '[layer]'), file('lib', 'layers.ts'))
const cloud = made(seg('cloud', '[slug]'), file('lib', 'data', 'cloud-primitives.ts'), file('lib', 'data', 'catalog.json'))
const customer = made(seg('customers', '[id]'), file('lib', 'data', 'customers.ts'))
const integration = made(seg('integrations', '[slug]'), file('lib', 'integrations.ts'))
const legal = made(seg('legal', '[slug]'))
const solution = made(seg('solutions', '[...slug]'), file('lib', 'data', 'solutions.ts'))
const org = made(seg('models', '[org]'), file('lib', 'data', 'models.json'))
const model = made(seg('models', '[org]', '[model]'), file('lib', 'data', 'models.json'))
const mod = made(seg('[...mod]'), file('lib', 'go-modules.ts'))
const compare = made(seg('compare', '[slug]'), file('lib', 'comparisons.ts'))
const course = made(seg('university', '[slug]'), seg('university', 'courses-data.ts'))
const career = made(seg('careers', '[slug]'), file('lib', 'careers.ts'))
const bench = made(seg('benchmarks', '[slug]'), file('lib', 'results.ts'), file('lib', 'data', 'benchmarks-kai.json'))
return [
...LAYERS.map((l): [string, string[]] => [href(l), layer]),
...COURSE_PAGES.map((c): [string, string[]] => [`/university/${c.slug}`, course]),
...careerSlugs.map((slug): [string, string[]] => [`/careers/${slug}`, career]),
...COMPARISONS.map((c): [string, string[]] => [`/compare/${c.slug}`, compare]),
...cloudPrimitiveSlugs.map((slug): [string, string[]] => [`/cloud/${slug}`, cloud]),
...featured.filter((s) => s.full).map((s): [string, string[]] => [`/customers/${s.id}`, customer]),
...INTEGRATIONS.map((i): [string, string[]] => [`/integrations/${i.slug}`, integration]),
...legalSlugs().map((slug): [string, string[]] => [`/legal/${slug}`, [...legal, file('content', 'legal', `${slug}.md`)]]),
...SOLUTIONS.map((s): [string, string[]] => [solutionHref(s), solution]),
...[...new Set(models.map((m) => `/models/${canonicalOrg(getOrgAndSlug(m.id).org)}`))].map((r): [string, string[]] => [r, org]),
...models.map((m): [string, string[]] => [modelPagePath(m.id), model]),
...OWNED.map((name): [string, string[]] => [`/${name}`, mod]),
...LEDGER.entries.filter((e) => !e.own).map((e): [string, string[]] => [e.href, bench]),
]
}
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
// The walk finds every page in the tree, including the ones nothing links to
// — which is what a sitemap is for, and why "it is not in the nav" was never
// a gate. Whether a route may be PUBLISHED is a separate question with one
// answer, in lib/publish.
const root = process.cwd()
const made = new Map<string, string[]>([
...routes(join(root, 'app')).map((r): [string, string[]] => [r.path, sources(r)]),
...(await generated()),
])
// When a page last changed is when the files it is made of last changed, by
// their last commit. A bench page is a rendering of a run file, so its date
// is the run's own stamp; see STAMPED.
const dates = changed(root, ['app', 'lib', 'content'])
return [...made.keys()].filter(indexable).map((route) => ({
url: BASE + (route === '/' ? '' : route),
lastModified: STAMPED.get(route) ?? latest(dates, root, made.get(route)!) ?? undefined,
changeFrequency: 'weekly' as const,
priority: route === '/' ? 1 : 0.7,
}))
}