v1.108.271 - A stock Nuxt 4 project is not an empty one
Two defects, both found by reading a contributor's pull request rather than by a report.
Nuxt 4's default layout indexed zero routes (#434)
NuxtContextProvider probed folder_path / "pages" and returned when absent, while detect() passed on nuxt.config.* either way. Nuxt 4 changed the default srcDir to app/, so every stock Nuxt 4 project reported the framework as detected and zero routes, silently.
A zero that cannot distinguish "this project has no routes" from "we looked in the wrong directory" is exactly what the absence contract exists to prevent.
It was found while reviewing PR #433, which fixes the identical defect in the Next.js provider. @lilubot found a defect class; we had been treating it as one framework's problem, and nobody had reported the Nuxt half.
Three probes were wrong, not one. _parse_pages and _build_auto_import_map (composables/, utils/) both move under app/. The auto-import one carries the knock-on cost: an empty map makes _build_auto_import_edges return early, so every synthetic edge for Nuxt's implicit imports disappears.
_parse_server_api was already correct and is untouched: server/ stays at the project root in the Nuxt 4 layout.
_resolve_src_dir reads srcDir from config first, because that is the actual answer. Probing is the documented fallback and requires a Nuxt-shaped child, because plenty of projects have an unrelated app/ and guessing wrong relocates the entire scan.
The nuxt profile now names both layouts; nestjs gained its missing JavaScript variants (#435). The next profile is deliberately excluded while PR #433 is open, so its author does not inherit a conflict; the test exempts it by name.
get_dead_code_v2 advised a parameter it did not accept (#436)
Two warnings told callers to pass entry_point_patterns. The function had no such parameter, the schema exposed none, and the dispatcher forwarded nothing. It belonged to find_dead_code.
Both warnings fire on the degenerate path, which is the moment the tool is telling you its own answer is untrustworthy and offering a remedy that did not exist.
The parameter now works at all three layers and feeds Signal 1 through the same hook package.json roots use. _matches_any_pattern is imported from find_dead_code, never reimplemented.
Note: fnmatch does not treat ** as recursive. handlers/**/*.py will not match handlers/h.py; use handlers/*.py, or a bare filename to match at any depth.
The general guard matters more than the instance: a test walks every tool module's AST and asserts each Pass <name> in a warning names a real parameter of that function. No docstring review catches this class, because the sentence is correct English about a real feature belonging to a different tool.
Also in this release
benchmarks/codex_surface/ measures jCodeMunch's net token effect on Codex CLI. Its first run is a negative result and its arm numbers should not be quoted: every arm difference was smaller than the baseline's own run-to-run spread.
One measurement did survive, and it corrects a claim made in this repository: 86% of baseline input is cached, so the tool-schema block is paid at full rate roughly once and at cache-read rates thereafter. Any framing of "24,007 tokens in every request" is wrong.
Verification
Local suite 7625 passed / 7 skipped / 0 failed; Python 3.13 clean env 7619 passed / 13 skipped / 0 failed. ruff check src/ clean. CI green on the release commit. New tests proven non-vacuous: 15 of 18 fail pre-fix for #434, 8 for #436.