Problem
NEXTJS_SPEC hardcodes the lint command:
# desloppify/languages/_framework/frameworks/specs/nextjs.py:547
cmd="npx --no-install next lint --format json",
Next.js 16 removed the lint subcommand. The invocation is now parsed as next <dir>, so it exits with:
$ npx next lint
Invalid project directory provided, no such directory: /path/to/project/lint
This does not fail loudly. The scan records reduced coverage:
Coverage reduced (next_lint): next lint tooling unavailable (parser_error)
…and reports zero lint issues. A Next 16 codebase reads as lint-clean when it is not. On the project I hit this on, eslint reports 6 real warnings across 5 files that next_lint contributed nothing about.
Repro
Any project with next@>=16 installed:
desloppify scan --path .
# → "Coverage reduced (next_lint): next lint tooling unavailable (parser_error)"
Environment: desloppify 1.0, next 16.3.0, Python 3.14.3, macOS.
Suggested fix
Resolve the command from the installed Next.js major (read node_modules/next/package.json, not the declared range — ^15.0.0 can resolve to 16) and run ESLint directly on >=16. Convenient detail: eslint --format json emits exactly the [{filePath, messages}] shape parse_next_lint already parses, so the parser needs no change.
To keep this general, I added an optional ToolIntegration.cmd_resolver: Callable[[Path], str | None] resolved per scan root in _framework_tool_phase. When it is absent or returns None, behaviour is unchanged — so projects on Next <=15, or with nothing installed to inspect, keep the historical command.
Patch
I have a working, tested branch. Diff summary:
.../frameworks/phases.py | 34 ++++++---
.../frameworks/specs/nextjs.py | 46 +++++++++++-
.../frameworks/types.py | 6 ++
.../typescript/tests/test_ts_nextjs_framework.py | 75 ++++++++++++++++++++
4 files changed, 149 insertions(+), 12 deletions(-)
8 new tests cover: the version→command mapping across majors 14/15/16/17, v-prefixed versions, unreadable/absent package.json falling back to None, the spec actually declaring the resolver, and a behavioral test asserting the resolved command reaches the tool runner (verified to fail against pre-fix code, not just pass against post-fix).
Full suite: 6757 passed. Four failures exist on main before this change and are unrelated (test_ts_nextjs_framework is not among them):
desloppify/languages/ruby/tests/test_init.py::test_has_required_phases[Coupling + cycles + orphaned]
- 3 in
desloppify/tests/lang/common/test_bash_unused_imports.py
I could not push a branch (no write access to this repo). Happy to open a PR from a fork if that is useful — just say the word and I will send it.
Problem
NEXTJS_SPEChardcodes the lint command:Next.js 16 removed the
lintsubcommand. The invocation is now parsed asnext <dir>, so it exits with:This does not fail loudly. The scan records reduced coverage:
…and reports zero lint issues. A Next 16 codebase reads as lint-clean when it is not. On the project I hit this on,
eslintreports 6 real warnings across 5 files thatnext_lintcontributed nothing about.Repro
Any project with
next@>=16installed:Environment: desloppify 1.0, next 16.3.0, Python 3.14.3, macOS.
Suggested fix
Resolve the command from the installed Next.js major (read
node_modules/next/package.json, not the declared range —^15.0.0can resolve to 16) and run ESLint directly on >=16. Convenient detail:eslint --format jsonemits exactly the[{filePath, messages}]shapeparse_next_lintalready parses, so the parser needs no change.To keep this general, I added an optional
ToolIntegration.cmd_resolver: Callable[[Path], str | None]resolved per scan root in_framework_tool_phase. When it is absent or returnsNone, behaviour is unchanged — so projects on Next <=15, or with nothing installed to inspect, keep the historical command.Patch
I have a working, tested branch. Diff summary:
8 new tests cover: the version→command mapping across majors 14/15/16/17,
v-prefixed versions, unreadable/absentpackage.jsonfalling back toNone, the spec actually declaring the resolver, and a behavioral test asserting the resolved command reaches the tool runner (verified to fail against pre-fix code, not just pass against post-fix).Full suite: 6757 passed. Four failures exist on
mainbefore this change and are unrelated (test_ts_nextjs_frameworkis not among them):desloppify/languages/ruby/tests/test_init.py::test_has_required_phases[Coupling + cycles + orphaned]desloppify/tests/lang/common/test_bash_unused_imports.pyI could not push a branch (no write access to this repo). Happy to open a PR from a fork if that is useful — just say the word and I will send it.