Browse Source

merge: fix/drift-refresh — refresh 4 skills to current majors (verifier drift)

typescript-ops (TS 6 / Zod 4 / Valibot 1), vue-ops (Nuxt 4), mcp-ops
(fastmcp 3 + spec URL move), migrate-ops (Laravel 13, Python 3.14,
Node 26, TS 6, Go 1.26, PHP 8.5). All staleness verifiers green in
--offline and --live on 2026-07-05.

Re-run scripts/install.ps1 so the global ~/.claude copy picks these up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0xDarkMatter 3 weeks ago
parent
commit
d67c862b19

+ 24 - 2
skills/mcp-ops/SKILL.md

@@ -12,7 +12,7 @@ metadata:
 
 
 Comprehensive patterns for building, testing, and deploying Model Context Protocol servers in Python and TypeScript.
 Comprehensive patterns for building, testing, and deploying Model Context Protocol servers in Python and TypeScript.
 
 
-> Ecosystem facts verified as of 2026-07.
+> Ecosystem facts verified as of 2026-07-05 (standalone FastMCP at major 3).
 
 
 ## MCP Architecture Quick Reference
 ## MCP Architecture Quick Reference
 
 
@@ -142,6 +142,28 @@ uv add mcp[cli]
 # Or:       uv run mcp run server.py
 # Or:       uv run mcp run server.py
 ```
 ```
 
 
+**Two Python FastMCPs — know which you're on.** The official `mcp` SDK bundles a frozen
+1.x-era FastMCP (`from mcp.server.fastmcp import FastMCP`, used in the samples above —
+stable, minimal). The standalone `fastmcp` package (gofastmcp.com) is where active
+development happens and is at **major 3**: same decorator surface, plus auth, proxying,
+OpenAPI generation, and a test client. To use it:
+
+```bash
+uv add fastmcp
+```
+
+```python
+from fastmcp import FastMCP   # standalone FastMCP 3 — not mcp.server.fastmcp
+
+mcp = FastMCP("my-server")    # v3: constructor is identity/behaviour only;
+                              # transport config moved to run()/serve time
+```
+
+FastMCP 3 breaking changes (from 2.x): 16 deprecated constructor kwargs removed
+(transport settings now passed at serve time), `ui=` replaced by `app=`,
+`ctx.set_state()`/`ctx.get_state()` are now async with session-scoped persistence, and
+the metadata namespace changed from `_fastmcp` to `fastmcp`.
+
 ## TypeScript SDK Quick Start
 ## TypeScript SDK Quick Start
 
 
 ```typescript
 ```typescript
@@ -328,7 +350,7 @@ The canonical fact set lives in [`assets/mcp-facts.json`](assets/mcp-facts.json)
 
 
 ## See Also
 ## See Also
 
 
-- **MCP Specification**: https://spec.modelcontextprotocol.io
+- **MCP Specification**: https://modelcontextprotocol.io/specification/latest (the old spec.modelcontextprotocol.io subdomain no longer resolves)
 - **Python SDK**: https://github.com/modelcontextprotocol/python-sdk
 - **Python SDK**: https://github.com/modelcontextprotocol/python-sdk
 - **TypeScript SDK**: https://github.com/modelcontextprotocol/typescript-sdk
 - **TypeScript SDK**: https://github.com/modelcontextprotocol/typescript-sdk
 - **Official MCP Servers**: https://github.com/modelcontextprotocol/servers
 - **Official MCP Servers**: https://github.com/modelcontextprotocol/servers

+ 5 - 5
skills/mcp-ops/assets/mcp-facts.json

@@ -3,9 +3,9 @@
   "schema": "claude-mods.mcp-ops.facts/v1",
   "schema": "claude-mods.mcp-ops.facts/v1",
   "as_of": "2026-07-05",
   "as_of": "2026-07-05",
   "spec": {
   "spec": {
-    "url": "https://spec.modelcontextprotocol.io",
-    "prose_token": "spec.modelcontextprotocol.io",
-    "_comment": "The MCP specification URL cited in See Also. --offline asserts the token is named in the skill prose; --live expects the URL to answer HTTP 200 (after redirects)."
+    "url": "https://modelcontextprotocol.io/specification/latest",
+    "prose_token": "modelcontextprotocol.io/specification",
+    "_comment": "The MCP specification URL cited in See Also (moved off the spec. subdomain, which stopped resolving by 2026-07). --offline asserts the token is named in the skill prose; --live expects the URL to answer HTTP 200 (after redirects)."
   },
   },
   "packages": {
   "packages": {
     "@modelcontextprotocol/sdk": {
     "@modelcontextprotocol/sdk": {
@@ -35,10 +35,10 @@
     "fastmcp": {
     "fastmcp": {
       "registry": "pypi",
       "registry": "pypi",
       "role": "FastMCP high-level framework (gofastmcp.com)",
       "role": "FastMCP high-level framework (gofastmcp.com)",
-      "sampled_major": 2,
+      "sampled_major": 3,
       "track_major": true,
       "track_major": true,
       "prose_token": "fastmcp",
       "prose_token": "fastmcp",
-      "_comment": "The standalone FastMCP package (FastMCP 2 +). Named in prose as FastMCP and via gofastmcp.com; matched case-insensitively."
+      "_comment": "The standalone FastMCP package, documented at major 3 (constructor identity-only, async ctx state, fastmcp meta namespace). Named in prose as FastMCP and via gofastmcp.com; matched case-insensitively."
     }
     }
   }
   }
 }
 }

+ 6 - 1
skills/mcp-ops/references/server-architecture.md

@@ -87,7 +87,12 @@ Servers declare what they support during initialization:
 
 
 ## FastMCP Server Setup (Python)
 ## FastMCP Server Setup (Python)
 
 
-FastMCP is the recommended high-level API for Python MCP servers.
+FastMCP is the recommended high-level API for Python MCP servers. Two variants exist:
+the frozen 1.x-era version bundled in the official SDK (`from mcp.server.fastmcp import
+FastMCP`, used below) and the actively developed standalone `fastmcp` package at major 3
+(`from fastmcp import FastMCP`). The decorator surface shown here works on both; on
+standalone FastMCP 3, transport configuration moves out of the constructor to serve time,
+and `ctx.set_state()`/`ctx.get_state()` are async.
 
 
 ### Basic Server
 ### Basic Server
 
 

+ 14 - 14
skills/migrate-ops/SKILL.md

@@ -1,6 +1,6 @@
 ---
 ---
 name: migrate-ops
 name: migrate-ops
-description: "Framework and language migration patterns - version upgrades, breaking changes, dependency audit, safe rollback. Use for: migrate, migration, upgrade, version bump, breaking changes, deprecation, dependency audit, npm audit, pip-audit, codemod, jscodeshift, rector, rollback, semver, changelog, framework upgrade, language upgrade, React 19, Vue 3, Next.js App Router, Laravel 11, Angular, Python 3.12, Node 22, TypeScript 5, Go 1.22, Rust 2024, PHP 8.4."
+description: "Framework and language migration patterns - version upgrades, breaking changes, dependency audit, safe rollback. Use for: migrate, migration, upgrade, version bump, breaking changes, deprecation, dependency audit, npm audit, pip-audit, codemod, jscodeshift, rector, rollback, semver, changelog, framework upgrade, language upgrade, React 19, Vue 3, Next.js App Router, Laravel 13, Angular, Python 3.14, Node 26, TypeScript 6, Go 1.26, Rust 2024, PHP 8.5."
 license: MIT
 license: MIT
 allowed-tools: "Read Edit Write Bash Glob Grep Agent"
 allowed-tools: "Read Edit Write Bash Glob Grep Agent"
 metadata:
 metadata:
@@ -12,7 +12,7 @@ metadata:
 
 
 Comprehensive migration skill covering framework upgrades, language version bumps, dependency auditing, breaking change detection, codemods, and rollback strategies.
 Comprehensive migration skill covering framework upgrades, language version bumps, dependency auditing, breaking change detection, codemods, and rollback strategies.
 
 
-> Ecosystem facts verified as of 2026-07.
+> Ecosystem facts verified as of 2026-07-05.
 
 
 ## Migration Strategy Decision Tree
 ## Migration Strategy Decision Tree
 
 
@@ -23,7 +23,7 @@ What kind of migration are you performing?
 │  └─ In-place upgrade
 │  └─ In-place upgrade
 │     Update dependency, run tests, deploy
 │     Update dependency, run tests, deploy
-├─ Major framework version (React 18→19, Vue 2→3, Laravel 10→11)
+├─ Major framework version (React 18→19, Vue 2→3, Laravel 12→13)
 │  │
 │  │
 │  ├─ Codebase < 50k LOC, good test coverage (>70%)
 │  ├─ Codebase < 50k LOC, good test coverage (>70%)
 │  │  └─ Big Bang Migration
 │  │  └─ Big Bang Migration
@@ -49,7 +49,7 @@ What kind of migration are you performing?
 │        Pros: highest confidence, catch subtle differences
 │        Pros: highest confidence, catch subtle differences
 │        Cons: double infrastructure cost, comparison logic
 │        Cons: double infrastructure cost, comparison logic
-└─ Language version upgrade (Python 3.9→3.12, Node 18→22)
+└─ Language version upgrade (Python 3.12→3.14, Node 22→26)
    └─ In-place upgrade with CI matrix
    └─ In-place upgrade with CI matrix
       Test against both old and new versions in CI
       Test against both old and new versions in CI
       Drop old version support once all tests pass
       Drop old version support once all tests pass
@@ -84,13 +84,13 @@ Which framework are you upgrading?
 │  ├─ Tool: Migration build (@vue/compat) for incremental migration
 │  ├─ Tool: Migration build (@vue/compat) for incremental migration
 │  └─ Load: ./references/framework-upgrades.md
 │  └─ Load: ./references/framework-upgrades.md
-├─ Laravel 10 → 11
-│  ├─ Check: Adopt slim application skeleton
-│  ├─ Check: Update config file structure (consolidated configs)
-│  ├─ Check: Review per-second scheduling changes
-│  ├─ Check: Update Dumpable trait usage
+├─ Laravel 12 → 13
+│  ├─ Check: PHP 8.3 is now the minimum (8.5 supported)
+│  ├─ Check: Cache/Redis key prefixes now use hyphenated suffixes
+│  ├─ Check: Adopt native PHP attributes (models, jobs, controllers) — optional
+│  ├─ Check: Queue routing by class via Queue::route(...) — optional
 │  ├─ Tool: laravel shift (automated upgrade service)
 │  ├─ Tool: laravel shift (automated upgrade service)
-│  └─ Load: ./references/framework-upgrades.md
+│  └─ Load: ./references/framework-upgrades.md (covers 10→11 in depth; 12→13 is near zero-break)
 ├─ Angular (any major version)
 ├─ Angular (any major version)
 │  ├─ Check: Run ng update for guided migration
 │  ├─ Check: Run ng update for guided migration
@@ -197,7 +197,7 @@ How do you detect breaking changes?
 | **Next.js** | next-codemod | `npx @next/codemod@latest` | Next.js version upgrades |
 | **Next.js** | next-codemod | `npx @next/codemod@latest` | Next.js version upgrades |
 | **Vue** | vue-codemod | `npx @vue/codemod src/` | Vue 2 to 3 transforms |
 | **Vue** | vue-codemod | `npx @vue/codemod src/` | Vue 2 to 3 transforms |
 | **PHP** | Rector | `vendor/bin/rector process src` | PHP version + framework upgrades |
 | **PHP** | Rector | `vendor/bin/rector process src` | PHP version + framework upgrades |
-| **Python** | pyupgrade | `pyupgrade --py312-plus *.py` | Python version syntax upgrades |
+| **Python** | pyupgrade | `pyupgrade --py314-plus *.py` | Python version syntax upgrades |
 | **Python** | django-upgrade | `django-upgrade --target-version 5.0 *.py` | Django version upgrades |
 | **Python** | django-upgrade | `django-upgrade --target-version 5.0 *.py` | Django version upgrades |
 | **Go** | gofmt | `gofmt -w .` | Go formatting updates |
 | **Go** | gofmt | `gofmt -w .` | Go formatting updates |
 | **Go** | gofix | `go fix ./...` | Go API changes |
 | **Go** | gofix | `go fix ./...` | Go API changes |
@@ -266,13 +266,13 @@ Migration failed or caused issues — how to roll back?
 
 
 | File | Contents | Lines |
 | File | Contents | Lines |
 |------|----------|-------|
 |------|----------|-------|
-| `references/framework-upgrades.md` | React 18→19, Next.js Pages→App Router, Vue 2→3, Laravel 10→11, Angular, Django upgrade paths | ~700 |
-| `references/language-upgrades.md` | Python 3.9→3.13, Node 18→22, TypeScript 4→5, Go 1.20→1.23, Rust 2021→2024, PHP 8.1→8.4 | ~600 |
+| `references/framework-upgrades.md` | React 18→19, Next.js Pages→App Router, Vue 2→3, Laravel 10→13, Angular, Django upgrade paths | ~700 |
+| `references/language-upgrades.md` | Python 3.9→3.14, Node 18→26, TypeScript 4→6, Go 1.20→1.26, Rust 2021→2024, PHP 8.1→8.5 | ~650 |
 | `references/dependency-management.md` | Audit tools, update strategies, lock files, monorepo deps, supply chain security | ~550 |
 | `references/dependency-management.md` | Audit tools, update strategies, lock files, monorepo deps, supply chain security | ~550 |
 
 
 ## Staleness verifier
 ## Staleness verifier
 
 
-This skill hardcodes specific framework/language target versions (React 19, Laravel 11, Python 3.12, Node 22, TypeScript 5, Go 1.22, Rust 2024, PHP 8.4). [`scripts/check-migrate-facts.py`](scripts/check-migrate-facts.py) guards them against silent drift:
+This skill hardcodes specific framework/language target versions (React 19, Laravel 13, Python 3.14, Node 26, TypeScript 6, Go 1.26, Rust 2024, PHP 8.5). [`scripts/check-migrate-facts.py`](scripts/check-migrate-facts.py) guards them against silent drift:
 
 
 ```bash
 ```bash
 # Structural (PR CI, no network): every catalogued target version still appears
 # Structural (PR CI, no network): every catalogued target version still appears

+ 19 - 19
skills/migrate-ops/assets/migrate-facts.json

@@ -12,38 +12,38 @@
     },
     },
     {
     {
       "label": "Laravel",
       "label": "Laravel",
-      "version": "11",
+      "version": "13",
       "where": ["description", "body"],
       "where": ["description", "body"],
-      "pattern": "laravel[^\\n]*\\b11\\b",
-      "live": {"source": "endoflife", "product": "laravel", "compare": "major", "documented": "11"}
+      "pattern": "laravel[^\\n]*\\b13\\b",
+      "live": {"source": "endoflife", "product": "laravel", "compare": "major", "documented": "13"}
     },
     },
     {
     {
       "label": "Python",
       "label": "Python",
-      "version": "3.12",
+      "version": "3.14",
       "where": ["description", "body"],
       "where": ["description", "body"],
-      "pattern": "python[^\\n]*3\\.12\\b",
-      "live": {"source": "endoflife", "product": "python", "compare": "line", "documented": "3.12"}
+      "pattern": "python[^\\n]*3\\.14\\b",
+      "live": {"source": "endoflife", "product": "python", "compare": "line", "documented": "3.14"}
     },
     },
     {
     {
       "label": "Node",
       "label": "Node",
-      "version": "22",
+      "version": "26",
       "where": ["description", "body"],
       "where": ["description", "body"],
-      "pattern": "node[^\\n]*\\b22\\b",
-      "live": {"source": "endoflife", "product": "nodejs", "compare": "major", "documented": "22"}
+      "pattern": "node[^\\n]*\\b26\\b",
+      "live": {"source": "endoflife", "product": "nodejs", "compare": "major", "documented": "26"}
     },
     },
     {
     {
       "label": "TypeScript",
       "label": "TypeScript",
-      "version": "5",
+      "version": "6",
       "where": ["description", "body"],
       "where": ["description", "body"],
-      "pattern": "typescript[^\\n]*\\b5\\b",
-      "live": {"source": "npm", "product": "typescript", "compare": "major", "documented": "5"}
+      "pattern": "typescript[^\\n]*\\b6\\b",
+      "live": {"source": "npm", "product": "typescript", "compare": "major", "documented": "6"}
     },
     },
     {
     {
       "label": "Go",
       "label": "Go",
-      "version": "1.22",
+      "version": "1.26",
       "where": ["description", "body"],
       "where": ["description", "body"],
-      "pattern": "go[^\\n]*1\\.22\\b",
-      "live": {"source": "endoflife", "product": "go", "compare": "line", "documented": "1.22"}
+      "pattern": "go[^\\n]*1\\.26\\b",
+      "live": {"source": "endoflife", "product": "go", "compare": "line", "documented": "1.26"}
     },
     },
     {
     {
       "label": "Rust",
       "label": "Rust",
@@ -51,14 +51,14 @@
       "where": ["description", "body"],
       "where": ["description", "body"],
       "pattern": "rust[^\\n]*2024\\b",
       "pattern": "rust[^\\n]*2024\\b",
       "live": null,
       "live": null,
-      "_comment": "Rust 2024 is an EDITION (reached stable with Rust 1.85), not a semver major tracked on endoflife.date's product list. Live-checked nowhere; offline-only."
+      "_comment": "Rust 2024 is an EDITION (reached stable with Rust 1.85), not a semver major tracked on endoflife.date's product list. Still the newest edition as of 2026-07 (next expected 2027). Live-checked nowhere; offline-only."
     },
     },
     {
     {
       "label": "PHP",
       "label": "PHP",
-      "version": "8.4",
+      "version": "8.5",
       "where": ["description", "body"],
       "where": ["description", "body"],
-      "pattern": "php[^\\n]*8\\.4\\b",
-      "live": {"source": "endoflife", "product": "php", "compare": "line", "documented": "8.4"}
+      "pattern": "php[^\\n]*8\\.5\\b",
+      "live": {"source": "endoflife", "product": "php", "compare": "line", "documented": "8.5"}
     }
     }
   ]
   ]
 }
 }

+ 25 - 1
skills/migrate-ops/references/framework-upgrades.md

@@ -325,7 +325,7 @@ npm test
 
 
 ---
 ---
 
 
-## Laravel 10 to 11
+## Laravel 10 to 13
 
 
 ### Pre-Upgrade Checklist
 ### Pre-Upgrade Checklist
 
 
@@ -431,6 +431,30 @@ php artisan config:show
 php artisan route:list
 php artisan route:list
 ```
 ```
 
 
+### Continuing to Laravel 12 and 13
+
+Upgrade one major at a time (11 → 12 → 13); both steps are deliberately light.
+
+**Laravel 12** (Feb 2025) — maintenance-focused: minimal breaking changes, dependency
+bumps, and new starter kits (React/Vue/Livewire). Most apps upgrade by updating
+`composer.json` constraints and re-running the suite.
+
+**Laravel 13** (Mar 2026) — stability-first with an AI/DX push:
+- **Requires PHP 8.3+** (supports through PHP 8.5) — upgrade the runtime first
+- Default cache and Redis key prefixes now use hyphenated suffixes — irrelevant if your
+  config files already pin these values, breaking if you shared a store across versions
+- New (opt-in): first-party Laravel AI SDK, native PHP attributes across models/jobs/
+  controllers/authorization, `Queue::route(...)` class-based queue routing, query-builder
+  vector similarity search (pgvector)
+- Laravel Shift remains the automated PR-based upgrade path
+
+```bash
+# Per major: bump constraint, update, test
+composer require laravel/framework:^13.0 --with-all-dependencies
+php artisan config:show cache   # verify key-prefix expectations
+php artisan test
+```
+
 ---
 ---
 
 
 ## Angular Version Upgrades
 ## Angular Version Upgrades

+ 159 - 13
skills/migrate-ops/references/language-upgrades.md

@@ -4,7 +4,7 @@ Detailed upgrade paths for major programming language version transitions.
 
 
 ---
 ---
 
 
-## Python 3.9 to 3.13
+## Python 3.9 to 3.14
 
 
 ### Python 3.10 (from 3.9)
 ### Python 3.10 (from 3.9)
 
 
@@ -140,6 +140,34 @@ rg "typing\.re\." .
 python3.13t script.py  # if built with --disable-gil
 python3.13t script.py  # if built with --disable-gil
 ```
 ```
 
 
+### Python 3.14 (from 3.13)
+
+**Key Features Gained:**
+- Deferred evaluation of annotations by default (PEP 649/749) — inspect via `annotationlib`; `from __future__ import annotations` is no longer needed
+- Template strings / t-strings (PEP 750)
+- Free-threaded build officially supported (PEP 779 — still a separate build, no longer "experimental")
+- Multiple interpreters in the stdlib (`concurrent.interpreters`, PEP 734)
+- Zstandard compression (`compression.zstd`, PEP 784)
+- Safe external debugger interface (`sys.remote_exec`)
+
+**Breaking Changes:**
+- `asyncio.get_event_loop()` no longer creates a new event loop — use `asyncio.run()` or `get_running_loop()`
+- Long-deprecated `ast` aliases (`ast.Num`, `ast.Str`, `ast.Bytes`, ...) removed — use `ast.Constant`
+- Annotation-introspection code that reads `__annotations__` eagerly may see deferred semantics — migrate to `annotationlib`
+
+**Migration Commands:**
+```bash
+# Find eager-annotation assumptions
+rg "from __future__ import annotations" .   # now redundant (harmless to keep)
+rg "__annotations__" .                       # candidates for annotationlib
+
+# Find event-loop creation via the removed pattern
+rg "asyncio\.get_event_loop\(\)" .
+
+# Modernize syntax to the new floor
+pyupgrade --py314-plus **/*.py
+```
+
 ### Python Version Upgrade Summary
 ### Python Version Upgrade Summary
 
 
 | From → To | Key Action | Biggest Risk |
 | From → To | Key Action | Biggest Risk |
@@ -148,10 +176,11 @@ python3.13t script.py  # if built with --disable-gil
 | 3.10 → 3.11 | Replace `toml` with `tomllib`, enjoy speed boost | `smtpd` removal |
 | 3.10 → 3.11 | Replace `toml` with `tomllib`, enjoy speed boost | `smtpd` removal |
 | 3.11 → 3.12 | Remove `distutils`/`imp`, adopt type syntax | `distutils` full removal, sqlite3 adapter changes |
 | 3.11 → 3.12 | Remove `distutils`/`imp`, adopt type syntax | `distutils` full removal, sqlite3 adapter changes |
 | 3.12 → 3.13 | Remove deprecated stdlib modules | Large number of removed stdlib modules |
 | 3.12 → 3.13 | Remove deprecated stdlib modules | Large number of removed stdlib modules |
+| 3.13 → 3.14 | Adopt deferred annotations + t-strings | `asyncio.get_event_loop()` no longer creates a loop |
 
 
 ---
 ---
 
 
-## Node.js 18 to 22
+## Node.js 18 to 26
 
 
 ### Node.js 20 (from 18)
 ### Node.js 20 (from 18)
 
 
@@ -233,16 +262,48 @@ node --experimental-require-module app.js
 # Replace: chokidar/nodemon → node --watch
 # Replace: chokidar/nodemon → node --watch
 ```
 ```
 
 
+### Node.js 24 (from 22)
+
+**Key Features Gained:**
+- `require()` of ESM modules enabled by default (no flag)
+- V8 13.6 — `Float16Array`, `RegExp.escape`, `Error.isError`, explicit resource management (`await using`)
+- `URLPattern` as a global
+- Permission model stable (flag renamed to `--permission`)
+- npm 11, Undici 7
+
+**Breaking Changes:**
+- Windows native builds drop MSVC (ClangCL toolchain) — affects native-addon build pipelines
+- Assorted deprecated API removals (`url.parse()` further discouraged — use `URL`)
+
+**Migration Commands:**
+```bash
+nvm install 24
+nvm use 24
+# FROM node:24-alpine
+
+npm rebuild                      # native modules against new ABI
+rg "require\(['\"]\./.*\.mjs" .  # spots that relied on require(esm) flags
+```
+
+### Node.js 26 (from 24)
+
+Node 26 is the Current line (April 2026); it enters Active LTS in October 2026. For
+production, upgrade LTS-to-LTS: 22 → 24 now, 24 → 26 once 26 is LTS. The mechanics are
+the same as every even-major bump: rebuild native modules, re-run the test suite on the
+new V8, and update `FROM node:26` images plus CI matrices when you cut over.
+
 ### Node.js Version Upgrade Summary
 ### Node.js Version Upgrade Summary
 
 
 | From → To | Key Action | Biggest Risk |
 | From → To | Key Action | Biggest Risk |
 |-----------|-----------|--------------|
 |-----------|-----------|--------------|
 | 18 → 20 | Rebuild native modules, test URL parsing | Stricter URL validation, loader hooks off-thread |
 | 18 → 20 | Rebuild native modules, test URL parsing | Stricter URL validation, loader hooks off-thread |
 | 20 → 22 | Rebuild native modules, check glibc version | Native module compatibility, header validation |
 | 20 → 22 | Rebuild native modules, check glibc version | Native module compatibility, header validation |
+| 22 → 24 | Adopt require(esm), permission model | Native-addon toolchain change on Windows |
+| 24 → 26 | LTS-to-LTS bump when 26 enters LTS (Oct 2026) | Riding the Current line before LTS |
 
 
 ---
 ---
 
 
-## TypeScript 4.x to 5.x
+## TypeScript 4.x to 6.0
 
 
 ### TypeScript 5.0 (from 4.9)
 ### TypeScript 5.0 (from 4.9)
 
 
@@ -295,27 +356,65 @@ rg '"suppressExcessPropertyErrors"' tsconfig.json
 | **5.6** | Iterator helper methods, `--noUncheckedSideEffectImports` |
 | **5.6** | Iterator helper methods, `--noUncheckedSideEffectImports` |
 | **5.7** | `--rewriteRelativeImportExtensions`, `--target es2024` |
 | **5.7** | `--rewriteRelativeImportExtensions`, `--target es2024` |
 
 
+### TypeScript 6.0 (from 5.x)
+
+The last release on the JavaScript-based compiler — 6.0 modernises defaults as the
+bridge to the native (Go) compiler in TypeScript 7.
+
+**Key Features Gained:**
+- `es2025` target/lib with types for Temporal, `Map.getOrInsert`, `RegExp.escape`
+- Better inference for `this`-less functions; `#/` subpath-import support
+- `--stableTypeOrdering` flag to ease 6.0 → 7.0 migration diffing
+- Large-monorepo `tsc --watch` rebuilds significantly faster
+
+**Breaking Changes:**
+- `strict: true` is now the **default** — configs that never set it surface new errors
+- Defaults changed: `module: esnext`, `target: es2025`
+- Removed: `moduleResolution: classic`; `module: amd/umd/system/none`; minimum `target` is ES2015 (`es5` deprecated)
+- `esModuleInterop` / `allowSyntheticDefaultImports` can no longer be set to `false`
+- Namespace-with-class merging requires explicit `export`
+
+**Migration Commands:**
+```bash
+npm install -D typescript@6
+
+# Find options 6.0 removed or hard-wires
+rg '"moduleResolution":\s*"classic"' tsconfig.json
+rg '"module":\s*"(amd|umd|system|none)"' tsconfig.json
+rg '"esModuleInterop":\s*false' tsconfig.json
+rg '"target":\s*"es5"' -i tsconfig.json
+
+# Surface the strict-by-default delta before committing to it
+npx tsc --noEmit
+```
+
 ### Migration Strategy
 ### Migration Strategy
 
 
 ```
 ```
 TypeScript version upgrade approach:
 TypeScript version upgrade approach:
-├─ Minor version (5.x → 5.y)
+├─ Minor version (x.y → x.z)
 │  └─ Generally safe, just update and fix new errors
 │  └─ Generally safe, just update and fix new errors
-│     npm install -D typescript@5.y
+│     npm install -D typescript@latest
 │     npx tsc --noEmit
 │     npx tsc --noEmit
-└─ Major version (4.x → 5.x)
-   ├─ 1. Update tsconfig.json (remove deleted options)
-   ├─ 2. Install typescript@5
-   ├─ 3. Run tsc --noEmit, fix errors
-   ├─ 4. Decide on decorator strategy (legacy vs ECMAScript)
-   └─ 5. Consider adopting moduleResolution: "bundler"
+├─ Major version (4.x → 5.x)
+│  ├─ 1. Update tsconfig.json (remove deleted options)
+│  ├─ 2. Install typescript@5
+│  ├─ 3. Run tsc --noEmit, fix errors
+│  ├─ 4. Decide on decorator strategy (legacy vs ECMAScript)
+│  └─ 5. Consider adopting moduleResolution: "bundler"
+│
+└─ Major version (5.x → 6.0)
+   ├─ 1. Set strict: true explicitly and fix errors BEFORE upgrading
+   ├─ 2. Replace removed module/moduleResolution options
+   ├─ 3. Install typescript@6, run tsc --noEmit
+   └─ 4. Pin the target you actually ship (defaults moved to es2025)
 ```
 ```
 
 
 ---
 ---
 
 
-## Go 1.20 to 1.23
+## Go 1.20 to 1.26
 
 
 ### Go 1.21 (from 1.20)
 ### Go 1.21 (from 1.20)
 
 
@@ -403,6 +502,27 @@ rg "\.Stop\(\)" . --glob "*.go"  # Review timer stop behavior
 rg "\.Reset\(" . --glob "*.go"   # Review timer reset behavior
 rg "\.Reset\(" . --glob "*.go"   # Review timer reset behavior
 ```
 ```
 
 
+### Go 1.24 – 1.26 (from 1.23)
+
+**Key Features Gained:**
+- **1.24**: generic type aliases; `tool` directives in go.mod (tracked tool deps); `os.Root` (filesystem-scoped file access); Swiss-table map implementation (runtime perf); `weak` package; `runtime.AddCleanup` (successor to `SetFinalizer`)
+- **1.25**: container-aware `GOMAXPROCS` (respects cgroup CPU limits); `testing/synctest` for concurrent-code tests; experimental green-tea GC
+- **1.26**: current stable line — as with every Go release, review the release notes for `go vet`/runtime deltas; language changes remain rare and gated on the `go` directive
+
+**Breaking Changes:**
+- Effectively none at the language level (Go 1 compatibility promise); behavior deltas are gated on the `go` directive version in go.mod, so bumps activate deliberately
+
+**Migration Commands:**
+```bash
+go mod edit -go=1.26
+go mod tidy
+go vet ./...
+govulncheck ./...
+
+# Adopt tool directives (1.24+) — replaces tools.go pattern
+go get -tool golang.org/x/tools/cmd/stringer
+```
+
 ### Go Version Upgrade Summary
 ### Go Version Upgrade Summary
 
 
 | From → To | Key Action | Biggest Risk |
 | From → To | Key Action | Biggest Risk |
@@ -410,6 +530,7 @@ rg "\.Reset\(" . --glob "*.go"   # Review timer reset behavior
 | 1.20 → 1.21 | Update go.mod toolchain, adopt slog | Toolchain directive in go.mod |
 | 1.20 → 1.21 | Update go.mod toolchain, adopt slog | Toolchain directive in go.mod |
 | 1.21 → 1.22 | Enjoy loop variable fix, adopt enhanced routing | Loop variable semantics (usually fixes bugs) |
 | 1.21 → 1.22 | Enjoy loop variable fix, adopt enhanced routing | Loop variable semantics (usually fixes bugs) |
 | 1.22 → 1.23 | Replace x/exp packages, adopt iterators | Timer/Ticker behavior change |
 | 1.22 → 1.23 | Replace x/exp packages, adopt iterators | Timer/Ticker behavior change |
+| 1.23 → 1.26 | Bump go directive stepwise, adopt tool directives + os.Root | Runtime perf deltas (Swiss maps, GC) in hot paths |
 
 
 ---
 ---
 
 
@@ -471,7 +592,7 @@ cargo doc --no-deps  # check documentation builds
 
 
 ---
 ---
 
 
-## PHP 8.1 to 8.4
+## PHP 8.1 to 8.5
 
 
 ### PHP 8.2 (from 8.1)
 ### PHP 8.2 (from 8.1)
 
 
@@ -580,6 +701,30 @@ vendor/bin/rector process src --set php84
 rg "function \w+\([^)]*\w+ \$\w+ = null" src/ --glob "*.php"
 rg "function \w+\([^)]*\w+ \$\w+ = null" src/ --glob "*.php"
 ```
 ```
 
 
+### PHP 8.5 (from 8.4)
+
+**Key Features Gained:**
+- Pipe operator `|>` for left-to-right call chaining
+- `array_first()` and `array_last()`
+- `#[\NoDiscard]` attribute (warn when a return value is ignored)
+- Fatal errors now include backtraces
+- `clone with` — update readonly/other properties during clone
+
+**Breaking Changes:**
+- Minor-release discipline: mostly new deprecations rather than removals; run the suite with deprecations surfaced (`error_reporting(E_ALL)`) before and after
+
+**Migration Commands:**
+```bash
+vendor/bin/rector process src --set php85
+
+# Adopt the pipe operator where nested calls hurt readability
+# Old: trim(strtolower($name))
+# New: $name |> strtolower(...) |> trim(...)
+
+# Replace reset()/end() misuse for first/last element
+rg "\breset\(|\bend\(" src/ --glob "*.php"   # candidates for array_first/array_last
+```
+
 ### PHP Version Upgrade Summary
 ### PHP Version Upgrade Summary
 
 
 | From → To | Key Action | Biggest Risk |
 | From → To | Key Action | Biggest Risk |
@@ -587,6 +732,7 @@ rg "function \w+\([^)]*\w+ \$\w+ = null" src/ --glob "*.php"
 | 8.1 → 8.2 | Fix dynamic properties, deprecation warnings | Dynamic properties deprecated |
 | 8.1 → 8.2 | Fix dynamic properties, deprecation warnings | Dynamic properties deprecated |
 | 8.2 → 8.3 | Adopt typed constants, #[Override] | array_sum/array_product behavior |
 | 8.2 → 8.3 | Adopt typed constants, #[Override] | array_sum/array_product behavior |
 | 8.3 → 8.4 | Adopt property hooks, asymmetric visibility | Implicit nullable deprecation |
 | 8.3 → 8.4 | Adopt property hooks, asymmetric visibility | Implicit nullable deprecation |
+| 8.4 → 8.5 | Adopt pipe operator, array_first/array_last | New deprecations surfacing in dependencies |
 
 
 ---
 ---
 
 

+ 49 - 8
skills/typescript-ops/SKILL.md

@@ -12,7 +12,7 @@ metadata:
 
 
 Comprehensive TypeScript skill covering the type system, generics, and production patterns.
 Comprehensive TypeScript skill covering the type system, generics, and production patterns.
 
 
-> Ecosystem facts verified as of 2026-07.
+> Ecosystem facts verified as of 2026-07-05 (TypeScript 6, Zod 4, Valibot 1).
 
 
 **Staleness check:** `python scripts/check-typescript-facts.py --offline` asserts the
 **Staleness check:** `python scripts/check-typescript-facts.py --offline` asserts the
 catalogued version-bearing facts (TypeScript major, zod, valibot) are still named in the
 catalogued version-bearing facts (TypeScript major, zod, valibot) are still named in the
@@ -162,21 +162,57 @@ type StringKeys<T> = {
 
 
 **Deep dive**: Load `./references/generics-patterns.md` for advanced type-level programming, recursive types, template literal types.
 **Deep dive**: Load `./references/generics-patterns.md` for advanced type-level programming, recursive types, template literal types.
 
 
+## Modern Language Features (TypeScript 5.x → 6.0)
+
+| Feature | Since | What It Gives You |
+|---------|-------|-------------------|
+| `satisfies` operator | 4.9 | Check a value against a type without widening it |
+| Standard (TC39) decorators | 5.0 | `@decorator` on classes/methods without `experimentalDecorators` |
+| `const` type parameters | 5.0 | `function f<const T>(x: T)` infers literal types without `as const` at call sites |
+| `using` declarations | 5.2 | Explicit resource management (`Symbol.dispose`), auto-cleanup at scope exit |
+| Inferred type predicates | 5.5 | `arr.filter(x => x !== null)` narrows without a hand-written `x is T` guard |
+| `verbatimModuleSyntax` | 5.0 | Enforces `import type` for type-only imports — replaces `importsNotUsedAsValues` |
+
+```typescript
+// const type parameters (5.0) - literal inference without as const
+function routes<const T extends readonly string[]>(paths: T): T { return paths; }
+const r = routes(["/home", "/about"]); // readonly ["/home", "/about"], not string[]
+
+// using declarations (5.2) - deterministic cleanup
+function readConfig() {
+    using file = openFile("config.json"); // file[Symbol.dispose]() runs at scope exit
+    return parse(file.contents);
+}
+
+// Inferred type predicates (5.5) - no manual guard needed
+const names = ["a", null, "b"].filter(x => x !== null); // string[], not (string | null)[]
+```
+
+### TypeScript 6.0 (Current Major)
+
+TS 6.0 is the last release on the JavaScript-based compiler — it exists to bridge to the
+native (Go) compiler in TS 7, so its headline is stricter, modernised defaults:
+
+- **`strict: true` is the default** — a tsconfig that never set it now gets full strict checks
+- **Defaults modernised**: `module: esnext`, `target: es2025`; `es2025` lib ships types for Temporal, `Map.getOrInsert`, `RegExp.escape`
+- **Legacy options removed**: `moduleResolution: classic`; `module: amd/umd/system/none`; minimum `target` is now ES2015 (`es5` deprecated)
+- **Interop always on**: `esModuleInterop` / `allowSyntheticDefaultImports` can no longer be disabled
+- New `--stableTypeOrdering` flag eases 6.0 → 7.0 migration diffing
+
 ## tsconfig Quick Reference
 ## tsconfig Quick Reference
 
 
 ```jsonc
 ```jsonc
 {
 {
     "compilerOptions": {
     "compilerOptions": {
-        // Strict mode (always enable)
+        // Strict mode (default in TS 6; state it explicitly anyway)
         "strict": true,               // Enables all strict checks
         "strict": true,               // Enables all strict checks
         "noUncheckedIndexedAccess": true,  // arr[0] is T | undefined
         "noUncheckedIndexedAccess": true,  // arr[0] is T | undefined
 
 
-        // Module system
+        // Module system (TS 6 defaults to module: esnext; interop is always on)
         "module": "esnext",           // or "nodenext" for Node
         "module": "esnext",           // or "nodenext" for Node
         "moduleResolution": "bundler", // or "nodenext"
         "moduleResolution": "bundler", // or "nodenext"
-        "esModuleInterop": true,
 
 
-        // Output
+        // Output (TS 6 defaults target to es2025; min supported is es2015)
         "target": "es2022",
         "target": "es2022",
         "outDir": "dist",
         "outDir": "dist",
         "declaration": true,          // Generate .d.ts
         "declaration": true,          // Generate .d.ts
@@ -230,16 +266,16 @@ getUser(userId);   // OK
 getUser(orderId);  // Error: OrderId not assignable to UserId
 getUser(orderId);  // Error: OrderId not assignable to UserId
 ```
 ```
 
 
-## Runtime Validation (Zod)
+## Runtime Validation (Zod 4)
 
 
 ```typescript
 ```typescript
 import { z } from "zod";
 import { z } from "zod";
 
 
-// Define schema
+// Define schema (Zod 4: string formats are top-level - z.email(), not z.string().email())
 const UserSchema = z.object({
 const UserSchema = z.object({
     id: z.number(),
     id: z.number(),
     name: z.string().min(1),
     name: z.string().min(1),
-    email: z.string().email(),
+    email: z.email(),
     role: z.enum(["admin", "user"]),
     role: z.enum(["admin", "user"]),
     settings: z.object({
     settings: z.object({
         theme: z.enum(["light", "dark"]).default("light"),
         theme: z.enum(["light", "dark"]).default("light"),
@@ -254,6 +290,11 @@ const user = UserSchema.parse(untrustedData);       // throws on invalid
 const result = UserSchema.safeParse(untrustedData);  // returns { success, data/error }
 const result = UserSchema.safeParse(untrustedData);  // returns { success, data/error }
 ```
 ```
 
 
+**Zod 4 changes to know** (if you learned Zod 3): string formats moved to the top level
+(`z.email()`, `z.uuid()`, `z.url()` — the `z.string().email()` method form is deprecated);
+error customisation unified under a single `error` param (`invalid_type_error` /
+`required_error` dropped); much faster parsing and a tree-shakeable `zod/mini` entry point.
+
 ## Reference Files
 ## Reference Files
 
 
 Load these for deep-dive topics. Each is self-contained.
 Load these for deep-dive topics. Each is self-contained.

+ 7 - 7
skills/typescript-ops/assets/typescript-facts.json

@@ -3,25 +3,25 @@
   "schema": "claude-mods.typescript-ops.facts/v1",
   "schema": "claude-mods.typescript-ops.facts/v1",
   "as_of": "2026-07-05",
   "as_of": "2026-07-05",
   "registry": "https://registry.npmjs.org",
   "registry": "https://registry.npmjs.org",
-  "currency_note": "> Ecosystem facts verified as of 2026-07.",
+  "currency_note": "> Ecosystem facts verified as of 2026-07-05 (TypeScript 6, Zod 4, Valibot 1).",
   "packages": [
   "packages": [
     {
     {
       "name": "typescript",
       "name": "typescript",
-      "documented_major": 4,
+      "documented_major": 6,
       "role": "language",
       "role": "language",
-      "where": "references/config-strict.md (useUnknownInCatchVariables, TS 4.4+); references/type-system.md (in/out variance annotations, TypeScript 4.7+). The skill never anchors a TS 5 feature, so its newest documented floor is the 4.x line."
+      "where": "SKILL.md (Modern Language Features 5.x -> 6.0: satisfies, standard decorators, const type params, using, inferred predicates; TS 6.0 defaults section); references/config-strict.md (strict default in 6.0, removed module/moduleResolution options). Historical feature floors (TS 4.4+, 4.7+) remain as floors, not currency anchors."
     },
     },
     {
     {
       "name": "zod",
       "name": "zod",
-      "documented_major": 3,
+      "documented_major": 4,
       "role": "runtime validation (default choice)",
       "role": "runtime validation (default choice)",
-      "where": "SKILL.md (Runtime Validation); references/ecosystem.md (z.infer, z.discriminatedUnion, z.coerce). z.object/.infer/.discriminatedUnion/.coerce are the Zod 3+ surface."
+      "where": "SKILL.md (Runtime Validation (Zod 4): top-level z.email(), unified error param, zod/mini); references/ecosystem.md (z.uuid/z.email top-level formats, unified error param, discriminatedUnion, coerce)."
     },
     },
     {
     {
       "name": "valibot",
       "name": "valibot",
-      "documented_major": 0,
+      "documented_major": 1,
       "role": "runtime validation (tree-shakeable alt)",
       "role": "runtime validation (tree-shakeable alt)",
-      "where": "references/ecosystem.md (v.pipe, v.InferOutput, v.safeParse, v.picklist). Valibot shipped as 0.x through the period this skill was written."
+      "where": "references/ecosystem.md (stable since 1.0; v.pipe, v.InferOutput, v.safeParse, v.picklist)."
     }
     }
   ]
   ]
 }
 }

+ 8 - 9
skills/typescript-ops/references/config-strict.md

@@ -16,7 +16,7 @@
 
 
 ### Enable the Full Strict Suite
 ### Enable the Full Strict Suite
 
 
-`"strict": true` is shorthand for enabling all individual strict flags at once. Always enable it.
+`"strict": true` is shorthand for enabling all individual strict flags at once. Always enable it. Since TypeScript 6.0 it is the **default** — a tsconfig that never set `strict` now gets the full suite, so a project upgrading to TS 6 may surface long-hidden errors; set `"strict": false` only as a deliberate, temporary migration step.
 
 
 ```json
 ```json
 {
 {
@@ -243,16 +243,15 @@ const y: string = legacyApi.getValue();
     "moduleResolution": "Bundler"
     "moduleResolution": "Bundler"
   }
   }
 }
 }
-
-// For browser projects with no bundler (rare)
-{
-  "compilerOptions": {
-    "module": "ESNext",
-    "moduleResolution": "Classic"  // avoid - use Bundler or Node16
-  }
-}
 ```
 ```
 
 
+**TypeScript 6.0 removals**: `moduleResolution: "Classic"` and `module: "amd" / "umd" /
+"system" / "none"` were removed outright, and `esModuleInterop` /
+`allowSyntheticDefaultImports` can no longer be set to `false` (the safe interop behaviour
+is always on). Defaults are now `module: "esnext"` and `target: "es2025"`; the minimum
+`target` is ES2015. If a legacy tsconfig names any removed option, migrate to `Bundler`
+or `Node16`/`NodeNext` before upgrading.
+
 ### Understand ESM vs CJS Interop Issues
 ### Understand ESM vs CJS Interop Issues
 
 
 With `Node16`/`NodeNext`, you must use explicit `.js` extensions in relative imports (even for `.ts` files).
 With `Node16`/`NodeNext`, you must use explicit `.js` extensions in relative imports (even for `.ts` files).

+ 10 - 6
skills/typescript-ops/references/ecosystem.md

@@ -17,16 +17,16 @@
 
 
 ### Use Zod for Schema Validation with Type Inference
 ### Use Zod for Schema Validation with Type Inference
 
 
-Zod is the most widely adopted runtime validation library. Define a schema once; infer the TypeScript type from it.
+Zod is the most widely adopted runtime validation library. Define a schema once; infer the TypeScript type from it. As of Zod 4, string formats are top-level functions (`z.email()`, `z.uuid()`, `z.url()`) — the Zod 3 method forms (`z.string().email()`) are deprecated.
 
 
 ```typescript
 ```typescript
 import { z } from 'zod';
 import { z } from 'zod';
 
 
-// Define schema
+// Define schema (Zod 4 syntax)
 const UserSchema = z.object({
 const UserSchema = z.object({
-  id: z.string().uuid(),
+  id: z.uuid(),
   name: z.string().min(1).max(100),
   name: z.string().min(1).max(100),
-  email: z.string().email(),
+  email: z.email(),
   age: z.number().int().min(0).max(150).optional(),
   age: z.number().int().min(0).max(150).optional(),
   role: z.enum(['admin', 'user', 'moderator']),
   role: z.enum(['admin', 'user', 'moderator']),
   createdAt: z.coerce.date(),
   createdAt: z.coerce.date(),
@@ -68,6 +68,10 @@ const EvenNumberSchema = z.number().refine(
   { message: 'Number must be even' }
   { message: 'Number must be even' }
 );
 );
 
 
+// Custom error messages (Zod 4: one unified `error` param replaces
+// invalid_type_error / required_error / errorMap)
+const AgeSchema = z.number({ error: 'Age must be a number' }).int().min(0);
+
 // Discriminated union (Zod version)
 // Discriminated union (Zod version)
 const ApiResponseSchema = z.discriminatedUnion('status', [
 const ApiResponseSchema = z.discriminatedUnion('status', [
   z.object({ status: z.literal('success'), data: z.unknown() }),
   z.object({ status: z.literal('success'), data: z.unknown() }),
@@ -78,7 +82,7 @@ type ApiResponse = z.infer<typeof ApiResponseSchema>;
 
 
 ### Use Valibot as a Tree-Shakeable Alternative
 ### Use Valibot as a Tree-Shakeable Alternative
 
 
-Valibot has an almost identical API to Zod but is tree-shakeable by design, resulting in much smaller bundles for edge/browser deployments.
+Valibot (stable since 1.0) covers the same ground as Zod but is tree-shakeable by design, resulting in much smaller bundles for edge/browser deployments. Zod 4's `zod/mini` entry point narrows the gap, but valibot's pipe composition remains the smallest-bundle option.
 
 
 ```typescript
 ```typescript
 import * as v from 'valibot';
 import * as v from 'valibot';
@@ -183,7 +187,7 @@ export const appRouter = t.router({
       }),
       }),
 
 
     create: t.procedure
     create: t.procedure
-      .input(z.object({ name: z.string(), email: z.string().email() }))
+      .input(z.object({ name: z.string(), email: z.email() }))
       .mutation(async ({ input }) => {
       .mutation(async ({ input }) => {
         return await db.user.create({ data: input });
         return await db.user.create({ data: input });
       }),
       }),

+ 11 - 7
skills/vue-ops/SKILL.md

@@ -1,6 +1,6 @@
 ---
 ---
 name: vue-ops
 name: vue-ops
-description: "Vue 3 development patterns, Composition API, Pinia state management, Vue Router, and Nuxt 3. Use for: vue, vuejs, composition api, pinia, vue router, nuxt, nuxt3, script setup, composable, reactive, defineProps, defineEmits, defineModel, v-model, provide inject, vue3."
+description: "Vue 3 development patterns, Composition API, Pinia state management, Vue Router, and Nuxt 4. Use for: vue, vuejs, composition api, pinia, vue router, nuxt, nuxt4, nuxt3, script setup, composable, reactive, defineProps, defineEmits, defineModel, v-model, provide inject, vue3."
 license: MIT
 license: MIT
 allowed-tools: "Read Write Bash"
 allowed-tools: "Read Write Bash"
 metadata:
 metadata:
@@ -10,9 +10,9 @@ metadata:
 
 
 # Vue Operations
 # Vue Operations
 
 
-Comprehensive Vue 3 reference covering Composition API, Pinia, Vue Router, Nuxt 3, and testing — production patterns with TypeScript throughout.
+Comprehensive Vue 3 reference covering Composition API, Pinia, Vue Router, Nuxt 4, and testing — production patterns with TypeScript throughout.
 
 
-> Vue 3 / Nuxt 3 ecosystem facts verified as of 2026-07.
+> Vue 3 / Nuxt 4 ecosystem facts verified as of 2026-07-05.
 
 
 ---
 ---
 
 
@@ -367,7 +367,11 @@ declare module 'vue-router' {
 
 
 ---
 ---
 
 
-## Nuxt 3 Decision Tree
+## Nuxt 4 Decision Tree
+
+Nuxt 4's flagship change over Nuxt 3 is the `app/` source directory (app code separated
+from `server/` and root config — see [./references/nuxt.md](./references/nuxt.md)); the
+rendering strategies below are unchanged.
 
 
 ```
 ```
 What rendering strategy does my app need?
 What rendering strategy does my app need?
@@ -450,12 +454,12 @@ What rendering strategy does my app need?
 |------|-------------|
 |------|-------------|
 | [./references/composition-api.md](./references/composition-api.md) | Composables, provide/inject, template refs, custom directives, Teleport, Suspense, slots, transitions, v-model deep patterns |
 | [./references/composition-api.md](./references/composition-api.md) | Composables, provide/inject, template refs, custom directives, Teleport, Suspense, slots, transitions, v-model deep patterns |
 | [./references/state-routing.md](./references/state-routing.md) | Pinia advanced patterns (plugins, SSR, store composition), Vue Router (guards, meta typing, scroll behavior, transitions) |
 | [./references/state-routing.md](./references/state-routing.md) | Pinia advanced patterns (plugins, SSR, store composition), Vue Router (guards, meta typing, scroll behavior, transitions) |
-| [./references/nuxt.md](./references/nuxt.md) | Nuxt 3 data fetching, server routes, middleware, plugins, modules, SEO, deployment, Nuxt Content |
+| [./references/nuxt.md](./references/nuxt.md) | Nuxt 4 directory structure, data fetching, server routes, middleware, plugins, modules, SEO, deployment, Nuxt Content |
 | [./references/testing.md](./references/testing.md) | Vitest setup, Vue Test Utils, Pinia/Router testing, composable testing, MSW, Playwright, Nuxt test utils |
 | [./references/testing.md](./references/testing.md) | Vitest setup, Vue Test Utils, Pinia/Router testing, composable testing, MSW, Playwright, Nuxt test utils |
 
 
 ## Staleness Verifier
 ## Staleness Verifier
 
 
-This skill encodes fast-moving facts (the Vue 3 minor-version gates, the Nuxt 3
+This skill encodes fast-moving facts (the Vue 3 minor-version gates, the Nuxt 4
 meta-framework, the ecosystem package stack). [`scripts/check-vue-facts.py`](scripts/check-vue-facts.py)
 meta-framework, the ecosystem package stack). [`scripts/check-vue-facts.py`](scripts/check-vue-facts.py)
 guards them against silent drift — internal consistency in PR CI, live
 guards them against silent drift — internal consistency in PR CI, live
 major-version drift in the scheduled freshness job:
 major-version drift in the scheduled freshness job:
@@ -466,7 +470,7 @@ major-version drift in the scheduled freshness job:
 python3 skills/vue-ops/scripts/check-vue-facts.py --offline        # exit 0 consistent, 10 drift
 python3 skills/vue-ops/scripts/check-vue-facts.py --offline        # exit 0 consistent, 10 drift
 
 
 # Live (weekly freshness job, never blocks a PR): is any documented major
 # Live (weekly freshness job, never blocks a PR): is any documented major
-# now behind npm's latest dist-tag? (e.g. Nuxt 4 while the prose says Nuxt 3.)
+# now behind npm's latest dist-tag? (e.g. Nuxt 5 while the prose says Nuxt 4.)
 python3 skills/vue-ops/scripts/check-vue-facts.py --live           # exit 10 a major moved ahead, 7 npm unreachable
 python3 skills/vue-ops/scripts/check-vue-facts.py --live           # exit 10 a major moved ahead, 7 npm unreachable
 ```
 ```
 
 

+ 3 - 3
skills/vue-ops/assets/vue-facts.json

@@ -1,5 +1,5 @@
 {
 {
-  "_comment": "Canonical fast-moving facts the vue-ops skill encodes. scripts/check-vue-facts.py asserts SKILL.md + references name these consistently (--offline) and probes the npm registry for major-version drift (--live). Edit deliberately: a change here is a skill-content decision, not housekeeping. documented_major is the major the skill's prose commits to (vue 3, nuxt 3) or the current tracked major for ecosystem libs the prose names without pinning a version.",
+  "_comment": "Canonical fast-moving facts the vue-ops skill encodes. scripts/check-vue-facts.py asserts SKILL.md + references name these consistently (--offline) and probes the npm registry for major-version drift (--live). Edit deliberately: a change here is a skill-content decision, not housekeeping. documented_major is the major the skill's prose commits to (vue 3, nuxt 4) or the current tracked major for ecosystem libs the prose names without pinning a version.",
   "schema": "claude-mods.vue-ops.facts/v1",
   "schema": "claude-mods.vue-ops.facts/v1",
   "as_of": "2026-07-05",
   "as_of": "2026-07-05",
   "vue_major": 3,
   "vue_major": 3,
@@ -8,11 +8,11 @@
     "define_model": "Vue 3.4",
     "define_model": "Vue 3.4",
     "define_options": "Vue 3.3",
     "define_options": "Vue 3.3",
     "use_template_ref": "Vue 3.5",
     "use_template_ref": "Vue 3.5",
-    "nuxt_major": "Nuxt 3"
+    "nuxt_major": "Nuxt 4"
   },
   },
   "packages": {
   "packages": {
     "vue":               { "documented_major": 3, "prose": ["Vue 3"],              "role": "core (Composition API, <script setup>)" },
     "vue":               { "documented_major": 3, "prose": ["Vue 3"],              "role": "core (Composition API, <script setup>)" },
-    "nuxt":              { "documented_major": 3, "prose": ["Nuxt 3"],             "role": "meta-framework (SSR/SSG/ISR, App Router host)" },
+    "nuxt":              { "documented_major": 4, "prose": ["Nuxt 4"],             "role": "meta-framework (SSR/SSG/ISR, app/ srcDir host)" },
     "pinia":             { "documented_major": 3, "prose": ["pinia"],              "role": "store" },
     "pinia":             { "documented_major": 3, "prose": ["pinia"],              "role": "store" },
     "vue-router":        { "documented_major": 5, "prose": ["vue-router"],         "role": "routing" },
     "vue-router":        { "documented_major": 5, "prose": ["vue-router"],         "role": "routing" },
     "@vueuse/core":      { "documented_major": 14, "prose": ["VueUse"],            "role": "composable collection" },
     "@vueuse/core":      { "documented_major": 14, "prose": ["VueUse"],            "role": "composable collection" },

+ 53 - 11
skills/vue-ops/references/nuxt.md

@@ -1,17 +1,50 @@
-# Nuxt 3 Reference
+# Nuxt 4 Reference
 
 
-Production patterns for Nuxt 3: rendering modes, data fetching, server routes, middleware, plugins, modules, SEO, deployment, and Nuxt Content.
+Production patterns for Nuxt 4: directory structure, rendering modes, data fetching, server routes, middleware, plugins, modules, SEO, deployment, and Nuxt Content.
 
 
 ---
 ---
 
 
 ## Architecture Overview
 ## Architecture Overview
 
 
-Nuxt 3 is built on:
+Nuxt 4 is built on:
 - **Nitro** — universal server engine (runs on Node, Cloudflare Workers, Deno, Bun, etc.)
 - **Nitro** — universal server engine (runs on Node, Cloudflare Workers, Deno, Bun, etc.)
 - **Vite** — fast dev server and build tool
 - **Vite** — fast dev server and build tool
-- **Vue 3** — Composition API throughout
+- **Vue 3** — Composition API throughout (Nuxt 4.4+ ships Vue Router v5)
 - **Auto-imports** — no need to import `ref`, `computed`, `useFetch`, etc. — Nuxt imports them automatically
 - **Auto-imports** — no need to import `ref`, `computed`, `useFetch`, etc. — Nuxt imports them automatically
-- **File-based routing** — `pages/` directory maps to routes
+- **File-based routing** — `app/pages/` directory maps to routes
+
+---
+
+## Directory Structure (the Nuxt 4 change)
+
+Application code lives under `app/` (the srcDir); server code and config stay at the root. This separates app-environment code from server-environment code — faster dev-server boot, better IDE type inference per environment.
+
+```
+my-app/
+├── app/                  # srcDir — everything that runs in the Vue app
+│   ├── assets/
+│   ├── components/
+│   ├── composables/
+│   ├── layouts/
+│   ├── middleware/       # route middleware (client navigation)
+│   ├── pages/
+│   ├── plugins/
+│   ├── utils/
+│   ├── app.vue
+│   └── error.vue
+├── public/
+├── server/               # stays at root — Nitro (api/, routes/, middleware/)
+├── shared/               # code shared by app/ and server/ — import via #shared
+├── nuxt.config.ts
+└── package.json
+```
+
+Key rules:
+- **`~/` and `@/` resolve to `app/`**, not the project root. Helpers that sat at root level and were imported with `~/` need to move into `app/` (or `shared/`) or get an explicit alias.
+- **`shared/`** is the sanctioned home for code both environments import (types, validators, constants) via the `#shared` alias — server code must not import from `app/`.
+- **Auto-imports scan `app/`** — `app/composables/`, `app/components/`, `app/utils/` work exactly as their root-level Nuxt 3 counterparts did.
+
+**Nuxt 3 differences**: in Nuxt 3 all of these directories sat at the project root and `~/` pointed to the root. Nuxt 4 auto-detects the old flat layout and keeps working with it, so migration is mechanical — move the app directories (plus `app.vue` / `error.vue`) into `app/` and fix any `~/` imports that referenced root-level files.
 
 
 ---
 ---
 
 
@@ -61,12 +94,17 @@ export default defineNuxtConfig({
 
 
 ### useFetch — SSR-safe primary fetching
 ### useFetch — SSR-safe primary fetching
 
 
+Nuxt 4 semantics: `data`/`error` default to `undefined` (Nuxt 3 used `null`), results are
+shallow-reactive by default (`deep: false`), requests sharing a key are deduplicated and
+their state is cleaned up when the last consuming component unmounts. The `pending` ref is
+deprecated — branch on `status` (`'idle' | 'pending' | 'success' | 'error'`) instead.
+
 ```vue
 ```vue
 <script setup lang="ts">
 <script setup lang="ts">
 interface Post { id: number; title: string; body: string }
 interface Post { id: number; title: string; body: string }
 
 
 // Automatically de-duplicates on server/client, serializes for hydration
 // Automatically de-duplicates on server/client, serializes for hydration
-const { data: post, pending, error, refresh } = await useFetch<Post>(
+const { data: post, status, error, refresh } = await useFetch<Post>(
   '/api/posts/1',
   '/api/posts/1',
   {
   {
     key: 'post-1',                      // deduplicate key (auto-generated if omitted)
     key: 'post-1',                      // deduplicate key (auto-generated if omitted)
@@ -146,11 +184,11 @@ try {
 ```vue
 ```vue
 <script setup lang="ts">
 <script setup lang="ts">
 // lazy: true — don't block render, data loads async
 // lazy: true — don't block render, data loads async
-const { data: comments, pending } = useFetch('/api/comments', { lazy: true })
+const { data: comments, status } = useFetch('/api/comments', { lazy: true })
 </script>
 </script>
 
 
 <template>
 <template>
-  <div v-if="pending" class="skeleton">Loading comments...</div>
+  <div v-if="status === 'pending'" class="skeleton">Loading comments...</div>
   <CommentList v-else :comments="comments" />
   <CommentList v-else :comments="comments" />
 </template>
 </template>
 ```
 ```
@@ -204,7 +242,7 @@ import { z } from 'zod'
 
 
 const CreateUserSchema = z.object({
 const CreateUserSchema = z.object({
   name: z.string().min(2).max(100),
   name: z.string().min(2).max(100),
-  email: z.string().email(),
+  email: z.email(),
   role: z.enum(['user', 'admin']).default('user'),
   role: z.enum(['user', 'admin']).default('user'),
 })
 })
 
 
@@ -588,7 +626,7 @@ useHead({
 ### Error page (error.vue)
 ### Error page (error.vue)
 
 
 ```vue
 ```vue
-<!-- error.vue — root level, replaces app.vue on error -->
+<!-- app/error.vue — replaces app.vue on error -->
 <script setup lang="ts">
 <script setup lang="ts">
 const props = defineProps<{
 const props = defineProps<{
   error: {
   error: {
@@ -747,8 +785,12 @@ export default defineNuxtConfig({
 
 
 ### Querying content
 ### Querying content
 
 
+> The examples below use the Nuxt Content v2 `queryContent()` API. Nuxt Content v3
+> replaces it with typed collections (`content.config.ts` + `queryCollection()`); check
+> which major the project uses before reaching for either API.
+
 ```vue
 ```vue
-<!-- pages/blog/[slug].vue -->
+<!-- app/pages/blog/[slug].vue -->
 <script setup lang="ts">
 <script setup lang="ts">
 const route = useRoute()
 const route = useRoute()