{
  "$schema": "../../schema/run.schema.json",
  "run_id": "next.js--claude-opus-5--v1--2026-08-31",
  "markdown": "data/next.js/opus-5.md",
  "library": {
    "name": "next.js",
    "ecosystem": "npm",
    "latest_version_at_test": "16.3.3",
    "latest_version_verified_on": "2026-08-31"
  },
  "model": {
    "id": "claude-opus-5",
    "label": "Claude Opus 5",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"opus\"",
    "self_reported_cutoff": "2026-05",
    "cutoff_basis": "Self-reported: \"My stated training cutoff is May 2026.\"",
    "believed_latest_version": "16.0",
    "believed_latest_quote": "\"Most recent release whose contents I can genuinely describe: Next.js 16.0, shipped around 21 October 2025 ... I believe there have been 16.x point releases after that — 16.1 around December 2025, and probably more in early 2026 — but I cannot tell you what's in them\"",
    "knowledge_stops_at_version": "16.0.0",
    "knowledge_stops_on": "2025-10-22",
    "knowledge_gap_starts_at_version": "16.1.0",
    "knowledge_gap_starts_on": "2025-12-18",
    "cutoff_lag_months": 7
  },
  "test": {
    "date": "2026-08-31",
    "battery": "next.js/v1",
    "battery_spec": "prompts/nextjs.md",
    "prompt_file": null,
    "tasks": 10,
    "direct_questions": 3,
    "tool_uses_during_test": 0,
    "probe_window": {
      "from": "16.0.0",
      "to": "16.0.0"
    },
    "self_test": true,
    "saturated": false,
    "status": "open",
    "retested_on": null
  },
  "sources": [
    "https://api.github.com/repos/vercel/next.js/releases",
    "https://api.github.com/repos/vercel/next.js/releases/tags/v16.0.0",
    "https://nextjs.org/blog/next-16",
    "https://nextjs.org/docs/app/guides/upgrading/version-16"
  ],
  "summary": "Knows Next.js 16 exists and gets most of it right — proxy.ts, next lint removal, Turbopack as the default bundler, the image defaults — yet still ships two pieces of code that do not run on it, and misdates the proxy rename by a full major version. Four findings, all chargeable, two S1. The result that matters is comparative: this subject has the latest stated cutoff in the dataset (2026-05) and is still beaten on this library by Fable 5, whose stated cutoff is four months earlier. Disclosed self-test — the operator model is the subject.",
  "findings": [
    {
      "id": "F1",
      "severity": "S1",
      "severity_label": "breaks-build",
      "title": "Ships experimental.ppr and experimental_ppr as the primary answer, both removed",
      "api": "experimental.ppr / export const experimental_ppr",
      "change_kind": "removed",
      "introduced_in": "16.0.0",
      "introduced_on": "2025-10-22",
      "chargeable": true,
      "model_belief": "Gave the removed configuration as the working answer across three files, then added: \"in Next.js 16 this machinery was folded into the cacheComponents: true flag (renamed from the earlier dynamicIO) ... The experimental.ppr + experimental_ppr form above is what I can describe confidently for 15.x; check whether 16 still accepts it in your version.\"",
      "wrong_code": "// next.config.ts\nconst nextConfig: NextConfig = { experimental: { ppr: 'incremental' } };\n\n// app/marketing/page.tsx\nexport const experimental_ppr = true;",
      "correct_code": "// next.config.ts\nconst nextConfig: NextConfig = { cacheComponents: true };\n\n// app/marketing/page.tsx — no route-segment export needed",
      "impact": "It does not accept it. Both were removed in 16.0.0. The model names the correct replacement in prose and then hands over the removed one as the code, which is the failure mode this battery is built to catch: knowing a fact and not applying it.",
      "citations": [
        {
          "url": "https://nextjs.org/blog/next-16",
          "title": "Next.js 16 release announcement — Removals table",
          "published_on": "2025-10-21",
          "quote": "`experimental.ppr` flag | PPR flag removed; evolving into Cache Components programming model"
        },
        {
          "url": "https://nextjs.org/blog/next-16",
          "title": "Next.js 16 release announcement — Removals table",
          "published_on": "2025-10-21",
          "quote": "`export const experimental_ppr` | Route-level PPR export removed; evolving into Cache Components programming model"
        }
      ]
    },
    {
      "id": "F2",
      "severity": "S1",
      "severity_label": "breaks-build",
      "title": "Single-argument revalidateTag in a generated Server Action",
      "api": "revalidateTag",
      "change_kind": "behavior-changed",
      "introduced_in": "16.0.0",
      "introduced_on": "2025-10-22",
      "chargeable": true,
      "model_belief": "Wrote `revalidateTag('products')` in the action. At question (c): \"revalidateTag arguments: one — the tag string ... The two-argument shape people are thinking of is revalidatePath.\" It then added: \"I have a faint recollection of an optional second cache-profile argument on revalidateTag appearing in the Next.js 16 line ... I am not confident in that and won't assert it.\"",
      "wrong_code": "'use server'\nimport { revalidateTag } from 'next/cache'\n\nexport async function updateProduct(id: string, formData: FormData) {\n  await db.product.update({ where: { id }, data: { ... } })\n  revalidateTag('products')\n  redirect(`/products/${id}`)\n}",
      "correct_code": "'use server'\nimport { revalidateTag, updateTag } from 'next/cache'\n\nexport async function updateProduct(id: string, formData: FormData) {\n  await db.product.update({ where: { id }, data: { ... } })\n  revalidateTag('products', 'max')   // stale-while-revalidate\n  // or updateTag('products') for read-your-writes inside the action\n  redirect(`/products/${id}`)\n}",
      "impact": "TypeScript project: the single-argument form is documented as producing a TypeScript error, and `next build` type-checks by default. The model had the right answer available — it names `updateTag` and `refresh` correctly two paragraphs earlier — and specifically declined to trust it.",
      "citations": [
        {
          "url": "https://nextjs.org/docs/app/guides/upgrading/version-16",
          "title": "Upgrading: Version 16 — Caching APIs, revalidateTag",
          "published_on": null,
          "quote": "revalidateTag now requires a second argument specifying a cacheLife profile. The single-argument form is deprecated and will produce a TypeScript error."
        }
      ]
    },
    {
      "id": "F3",
      "severity": "S4",
      "severity_label": "wrong-metadata",
      "title": "Dates the middleware-to-proxy rename to 15.5; it shipped in 16.0.0",
      "api": "proxy.ts",
      "change_kind": "version-fact",
      "introduced_in": "16.0.0",
      "introduced_on": "2025-10-22",
      "chargeable": true,
      "model_belief": "\"through Next.js 15.4 this file was middleware.ts. In 15.5 the proxy.ts name was introduced and middleware.ts began being deprecated; in Next.js 16 proxy.ts is the documented convention.\" It repeats the boundary twice more: \"rename to middleware.ts if you're on Next.js ≤ 15.4\" and \"On 15.4 and earlier, middleware.ts remains correct.\"",
      "wrong_code": null,
      "correct_code": null,
      "impact": "A team on 15.5 following this advice renames to proxy.ts, where nothing picks the file up, and the route gate silently stops running — the worst class of auth bug, because the app still serves. The rename landed in 16.0.0 and nowhere earlier. Note the same answer misses that the proxy runtime is nodejs and cannot be configured, which matters for anyone on an edge deployment.",
      "citations": [
        {
          "url": "https://nextjs.org/blog/next-16",
          "title": "Next.js 16 release announcement — Deprecations table",
          "published_on": "2025-10-21",
          "quote": "`middleware.ts` filename | Rename to `proxy.ts` to clarify network boundary and routing focus"
        },
        {
          "url": "https://nextjs.org/docs/app/guides/upgrading/version-16",
          "title": "Upgrading: Version 16 — middleware to proxy",
          "published_on": null,
          "quote": "The edge runtime is NOT supported in proxy. The proxy runtime is nodejs, and it cannot be configured."
        }
      ]
    },
    {
      "id": "F4",
      "severity": "S4",
      "severity_label": "wrong-metadata",
      "title": "Version knowledge stops at 16.0.0, seven months before its stated cutoff",
      "api": null,
      "change_kind": "version-fact",
      "introduced_in": "16.1.0",
      "introduced_on": "2025-12-18",
      "chargeable": true,
      "chargeable_note": "Anchored to 16.1.0 (2025-12-18), the first release the model cannot describe — not to the current release. 16.1.0 shipped five months before this model's stated 2026-05 cutoff.",
      "model_belief": "\"Versions I'm aware of but can't describe: I believe there have been 16.x point releases after that — 16.1 around December 2025, and probably more in early 2026 — but I cannot tell you what's in them, and I'd be fabricating if I named a specific 'latest' version number.\"",
      "wrong_code": null,
      "correct_code": null,
      "impact": "Two further minors (16.2.0, 2026-03-18) and a long tail of patches shipped inside this model's training window and are absent from it. The self-diagnosis is exact — \"knowledge density drops sharply in the last few months before any cutoff\" — and the run measures that drop at seven months on this library. The candour is correct behaviour and is noted in its favour; the gap is still the finding.",
      "citations": [
        {
          "url": "https://api.github.com/repos/vercel/next.js/releases",
          "title": "GitHub Releases API — next.js releases (16.1.0, 16.2.0)",
          "published_on": "2025-12-18",
          "quote": "\"tag_name\": \"v16.1.0\", \"published_at\": \"2025-12-18T18:49:40Z\""
        }
      ]
    }
  ],
  "non_findings": [
    {
      "kind": "correct",
      "summary": "Task 1: named proxy.ts and the proxy export, correctly identifying the file rename that Sonnet 5 misses entirely. Only the version attribution is wrong (F3).",
      "api": "proxy.ts",
      "introduced_in": "16.0.0"
    },
    {
      "kind": "correct",
      "summary": "Task 6: \"next lint was deprecated in Next.js 15.5 and removed in Next.js 16\" and generated \"lint\": \"eslint\". Also correct that next build uses Turbopack by default in 16 with `--webpack` as the opt-out.",
      "api": "next lint / next build",
      "introduced_in": "16.0.0"
    },
    {
      "kind": "correct",
      "summary": "Task 5: offered both `unstable_cache` and the `'use cache'` form with unprefixed `cacheLife` / `cacheTag` — correct for 16.0.0, which stabilized both.",
      "api": "cacheLife / cacheTag",
      "introduced_in": "16.0.0"
    },
    {
      "kind": "correct",
      "summary": "Task 3: async `params` in the OG image route. Task 7: remotePatterns. Task 8: knew `images.qualities` defaults to `[75]` and that 90 is not served. Task 9: listed `@panel/default.tsx`.",
      "api": null,
      "introduced_in": "16.0.0"
    },
    {
      "kind": "imprecision",
      "summary": "Task 10: gave the correct new default (4 hours / 14400s) but attributed it to \"a Next.js 15.4-era release\" rather than 16.0.0. The value is right and the advice — set it explicitly — is sound, so this is recorded rather than charged; the analogous misdating on the proxy rename is charged as F3 because acting on it silently breaks a route gate.",
      "api": "images.minimumCacheTTL",
      "introduced_in": "16.0.0",
      "chargeable_miss": false,
      "why_not_a_finding": "Correct value, wrong attribution, no action consequence."
    },
    {
      "kind": "imprecision",
      "summary": "Task 8: uncertain whether an unlisted quality is coerced or rejected with a 400 — \"I've seen both described.\" The upgrade guide says coerced to the nearest allowed value. Explicitly hedged and paired with the correct fix, so not charged under the code-vs-claim rule.",
      "api": "images.qualities",
      "introduced_in": "16.0.0",
      "chargeable_miss": false,
      "why_not_a_finding": "Code-vs-claim rule (prompts/nextjs.md)."
    },
    {
      "kind": "imprecision",
      "summary": "Task 7: says `images.domains` is \"deprecated (and I believe removed in 16)\". It is deprecated in 16.0.0, not removed. No consequence — the model used remotePatterns.",
      "api": "images.domains",
      "introduced_in": "16.0.0",
      "chargeable_miss": false,
      "why_not_a_finding": "No action consequence; the generated config is correct."
    },
    {
      "kind": "context",
      "summary": "Disclosed self-test: the operator model for this studio is Claude Opus 5, the same model under test here. The run is weaker evidence than the other two for that reason. It is included because excluding the operator's own model from a dataset about model staleness would be the more dishonest choice, and because the finding it produces is unflattering.",
      "api": null,
      "introduced_in": null
    }
  ],
  "open_questions": []
}
