Skip to content

fix(css): print a CSS-optimizer hint a reader can actually run - #3597

Merged
kojiwakayama merged 5 commits into
mainfrom
fix/dx-20260811-r2-26
Aug 12, 2026
Merged

fix(css): print a CSS-optimizer hint a reader can actually run#3597
kojiwakayama merged 5 commits into
mainfrom
fix/dx-20260811-r2-26

Conversation

@kojiwakayama

@kojiwakayama kojiwakayama commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

The regression

0.1.1229 (commit d1bedfe, #3575) added an install suggestion to the missing
CSS-optimizer warning. Every veryfront build and veryfront serve in a
veryfront init scaffold printed:

! No CSSOptimizationEngine registered; emitting unminified CSS. Install one with: deno add @veryfront/ext-css-lightning

A reader who runs that command does not get a CSS optimizer.

Reproduced against published 0.1.1229

$ npm exec -y -- veryfront@0.1.1229 init idx26-app --template minimal --runtime node
$ ./node_modules/.bin/veryfront build
  ! No CSSOptimizationEngine registered; emitting unminified CSS. Install one with: deno add @veryfront/ext-css-lightning

$ deno add @veryfront/ext-css-lightning
error: @veryfront/ext-css-lightning is missing a prefix.
       Did you mean `deno add npm:@veryfront/ext-css-lightning`?

Two independent problems:

  1. The command is invalid. Deno resolves an unprefixed specifier against
    JSR. @veryfront/ext-css-lightning is on npm (registry.npmjs.org → 200);
    jsr.io has no @veryfront scope (→ 404). The npm: prefix is required.
    Separately, the scaffold that prints this is an npm project with
    package-lock.json and npm scripts, so a deno command is the wrong tool
    even when it is spelled correctly.

  2. Installing is not sufficient. ext-css-lightning is
    selection: "explicit" in src/extensions/first-party-defaults.ts, so it
    registers nothing until the project composes it. On published 0.1.1229:

    step warning dist/_vf/css/*.css
    scaffold as-is printed 110,550 bytes, unminified
    npm install @veryfront/ext-css-lightning still printed 110,550 bytes, unminified
    + extensions: [extCSSLightning()] in veryfront.config.ts gone 89,449 bytes, minified

    So a hint that stops at the install leaves the reader exactly where they
    started, having installed a package that does nothing.

What is left after #3600

#3600 landed on main while this branch was open and fixed problem 2: the
warning now states the effect in active voice and names the composition step.
It fixed problem 1 only by retreating from it — it names the package rather
than giving any command, so the reader is told what to install but not how,
and the answer differs per project.

This branch, rebased onto that copy, restores the command and makes it a
correct one. Only the install clause changes:

-Install @veryfront/ext-css-lightning, then add it to "extensions" in veryfront.config.ts
+Install one with: deno add npm:@veryfront/ext-css-lightning, then add it to "extensions" in veryfront.config.ts

The change

src/extensions/install-command.ts formats the install command from the files
that own the project's dependencies — the lockfile first, then deno.json,
then package.json — falling back to the running runtime's client only when
nothing is readable. It normalises away an npm: prefix a recommendation
may already carry (the RedisRuntimeProvider entry does). The CSS warning uses
it.

The lockfile decides which npm-family client owns the project, because
package.json alone cannot: it is identical under npm, pnpm, and Yarn. pnpm and
Yarn keep that lockfile at the workspace root while each member holds only a
package.json, so a member directory is searched upward for it (bounded at four
levels). deno.json still short-circuits ahead of the walk, since Deno resolves
dependencies from the manifest itself.

Only an npm-family lockfile can claim a package.json during that walk. A
deno.lock in some enclosing repository — a --runtime node scaffold checked
out inside a Deno repo, for example — must not turn the hint into deno add,
which is the same failure the PR opened with.

Following the manifest rather than the runtime matters because the compiled
Deno binary builds --runtime node scaffolds: telling one of those to run
deno add writes a deno.json the project's own npm ci ignores, so the
optimizer would vanish on the next Node build (raised in review).

New output, run with this branch's CLI under Deno in the same directory, with
only the manifest changing:

# package.json only
! Veryfront emits unminified CSS because no CSS optimizer is active. Install one with: npm install @veryfront/ext-css-lightning, then add it to "extensions" in veryfront.config.ts

# deno.json added
! Veryfront emits unminified CSS because no CSS optimizer is active. Install one with: deno add npm:@veryfront/ext-css-lightning, then add it to "extensions" in veryfront.config.ts

And the formatter run directly against real directories on disk, before and
after the lockfile table was shared (deno run --allow-read --allow-env, one
line per directory):

### BEFORE — every npm-family project got the same answer
/tmp/repro-3597/pnpm-app            -> npm  | npm install @veryfront/ext-css-lightning
/tmp/repro-3597/yarn-app            -> npm  | npm install @veryfront/ext-css-lightning
/tmp/repro-3597/ws/packages/app     -> npm  | npm install @veryfront/ext-css-lightning
### AFTER
/tmp/repro-3597/pnpm-app            -> pnpm | pnpm add @veryfront/ext-css-lightning
/tmp/repro-3597/yarn-app            -> yarn | yarn add @veryfront/ext-css-lightning
/tmp/repro-3597/ws/packages/app     -> pnpm | pnpm add @veryfront/ext-css-lightning

The third directory holds only a package.json; the pnpm-lock.yaml that
names its client is two levels up at the workspace root.

Both commands were run for real: npm install @veryfront/ext-css-lightning
installs, and deno add npm:@veryfront/ext-css-lightning writes
"@veryfront/ext-css-lightning": "npm:@veryfront/ext-css-lightning@^0.1.1229"
into deno.json. Following the full hint clears the warning and minifies the
stylesheet, as the table above shows.

One lockfile table, two readers

The formatter stays in src/extensions/, because the warning is emitted from
the CSS pipeline and that pipeline cannot import the CLI layer. But the
knowledge it needs — which file means which client — is now owned once, in
src/utils/package-client.ts, and cli/utils/package-manager.ts reads it from
there instead of keeping its own copy.

That direction is the only one the boundary lints allow, and it is also the
right one: cli/utils/package-manager.ts is async, logs through cliLogger,
and shells out via runCommand, none of which belongs in a build-time warning
path. scripts/lint/enforce-cli-boundary.ts bans #veryfront/* imports from
cli/, so the CLI reaches the table through the veryfront/utils/package-client
package surface, the same way it already reaches veryfront/utils/case-utils
and veryfront/utils/import-lockfile.

Sharing it matters because the CLI runs the install during veryfront init
and the framework prints the install command afterwards. If those two read the
same pnpm-lock.yaml differently, the reader is told to run npm install in a
project pnpm owns, which writes a conflicting package-lock.json and leaves
pnpm-lock.yaml stale — and the next frozen-lockfile CI run rejects it.

Tests

src/html/styles-builder/css-provider-session.test.ts — new case asserts the
emitted warning carries one of the five runnable install commands (spelled
out as literals, so a regressed formatter cannot satisfy it by agreeing with
itself), never the deno add @veryfront/… form, and names
veryfront.config.ts.

#3600's own case in that file asserted deno add never appears at all. That
assertion was written when no command was correct; deno add npm: is correct
for a project whose deno.json owns its dependencies, and the repo's own test
run is such a project. It is narrowed to the bare-specifier form that actually
fails — deno add @veryfront/ — which is the same string this branch's case
excludes. Its companion assertions (composition step named, contract name
absent, warned once) are untouched.

src/extensions/install-command.test.ts — the manifest- and lockfile-to-command
mapping (all five clients spelled out as literals), the pnpm/Yarn workspace-root
lockfile a member directory does not hold, a member's own lockfile winning over
the root's, an enclosing deno.lock not claiming a Node package, the runtime
fallback, and the npm:-prefixed recommendation that would otherwise produce
npm install npm:@veryfront/ext-redis.

cli/utils/package-manager.test.ts — a case that walks every entry in
LOCKFILE_CLIENTS and asserts detectPackageManager (CLI) and
detectProjectInstallTarget (framework) return the same client for the same
directory. This is the regression test for the finding itself: the two cannot
drift apart without it failing.

Not fixed here

Two pre-existing sites still print the same unrunnable deno add <bare specifier> form for a missing contract, and neither mentions composition:

  • src/extensions/contracts.ts:25 (and the detail on :27) — the
    MISSING_EXTENSION_ERROR raised for any unresolved contract
  • src/server/bootstrap.ts:118 — the Bundler precondition failure

They predate 0.1.1229 and are asserted by four existing test files, so they
are left for a separate change. The formatter they need is now in place.

No doc change required

No page in docs/ or in veryfront-docs prints the command, so there is no
live URL to re-check for this one.

Summary by CodeRabbit

  • New Features

    • Installation guidance now adapts to the project’s package manager and runtime, including Bun, Deno, and npm.
    • Commands are formatted consistently, including correct handling of npm-prefixed packages.
    • Missing CSS optimization guidance now includes executable installation commands and configuration steps.
  • Bug Fixes

    • Improved fallback behavior when project manifests or working directories cannot be read.
    • Prevented invalid or duplicated package-manager prefixes in installation recommendations.
  • Tests

    • Added coverage for runtime detection, manifest precedence, fallback behavior, and installation command formatting.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kojiwakayama, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0487dcaa-09b1-4f61-9fd6-bd6d524f0911

📥 Commits

Reviewing files that changed from the base of the PR and between 08b8835 and 4d73917.

📒 Files selected for processing (7)
  • cli/utils/package-manager.test.ts
  • cli/utils/package-manager.ts
  • deno.json
  • src/extensions/install-command.test.ts
  • src/extensions/install-command.ts
  • src/html/styles-builder/css-provider-session.test.ts
  • src/utils/package-client.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ccb7a5e3-64cc-4f2c-b0a7-e9b5e3cf1a76

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee5098 and 08b8835.

📒 Files selected for processing (4)
  • src/extensions/install-command.test.ts
  • src/extensions/install-command.ts
  • src/html/styles-builder/css-provider-session.test.ts
  • src/html/styles-builder/tailwind-compiler.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/html/styles-builder/tailwind-compiler.ts
  • src/html/styles-builder/css-provider-session.test.ts

📝 Walkthrough

Walkthrough

The PR adds project and runtime-aware installation command formatting. It updates missing CSS optimizer warnings to use formatted commands and describe veryfront.config.ts registration. Tests cover target detection, command formatting, and warning content.

Changes

Runtime-aware installation guidance

Layer / File(s) Summary
Format runtime-specific install commands
src/extensions/install-command.ts, src/extensions/install-command.test.ts
The helper detects Bun, Deno, and npm targets from project manifests or runtime fallback. It formats commands and normalizes npm: prefixes. Tests cover manifests, runtimes, and missing manifests.
Integrate formatted commands into optimizer warnings
src/html/styles-builder/tailwind-compiler.ts, src/html/styles-builder/css-provider-session.test.ts
Missing CSS optimizer warnings now include runtime-specific installation commands and the required veryfront.config.ts registration step. Tests verify the guidance.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: kwakayama

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: updating the CSS-optimizer hint with an installation command that users can run.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dx-20260811-r2-26

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/html/styles-builder/css-provider-session.test.ts`:
- Around line 275-279: Update the assertion in the relevant test to construct
the expected install command directly from the active runtimeKind, using literal
npm, Deno, or Bun command strings as appropriate. Do not call
formatInstallCommand() for the expected warning text; ensure the test verifies
the concrete command emitted for the selected runtime and add or update the
focused failing test before implementation changes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 25fa95c7-adcc-4002-9666-65d9bfe631d5

📥 Commits

Reviewing files that changed from the base of the PR and between 2c2753d and 035e2d9.

📒 Files selected for processing (4)
  • src/extensions/install-command.test.ts
  • src/extensions/install-command.ts
  • src/html/styles-builder/css-provider-session.test.ts
  • src/html/styles-builder/tailwind-compiler.ts

Comment thread src/html/styles-builder/css-provider-session.test.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 035e2d9d99

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/html/styles-builder/tailwind-compiler.ts
@kojiwakayama
kojiwakayama force-pushed the fix/dx-20260811-r2-26 branch from 4ec9b52 to 776ffb6 Compare August 11, 2026 20:37
0.1.1229 started telling every build without a CSS optimizer to run
`deno add @veryfront/ext-css-lightning`. Following that instruction fails
twice over. Deno reads an unprefixed specifier as JSR, and jsr.io hosts no
`@veryfront` scope, so the command exits with "@veryfront/ext-css-lightning
is missing a prefix"; and the hint is printed by builds that overwhelmingly
run under Node, where a Deno command is a non-sequitur.

Correcting the command alone would still leave the reader stuck.
ext-css-lightning is `selection: "explicit"` in first-party-defaults.ts:
installing it registers nothing. Verified against published 0.1.1229 --
`npm install @veryfront/ext-css-lightning` in a `veryfront init` scaffold
left the warning printing and the stylesheet at 110,550 unminified bytes.
Adding `extensions: [extCSSLightning()]` to veryfront.config.ts cleared the
warning and produced 89,449 minified bytes.

So format the install command from the runtime that is printing it, and name
the composition step the install does not perform. The formatter lives in
src/extensions/ rather than reusing cli/utils/package-manager.ts because the
warning is emitted from the CSS pipeline, which cannot import the CLI layer.

Two other sites still print the same unrunnable `deno add <bare specifier>`
form for missing contracts -- src/extensions/contracts.ts:25 and
src/server/bootstrap.ts:118. Both predate this release and are left for a
separate change; the formatter they need is now in place.
Review follow-up. Selecting the command from the runtime executing Veryfront
is wrong for the compiled Deno binary, which builds `--runtime node`
scaffolds: it told those projects to run `deno add npm:@veryfront/ext-css-
lightning`, which writes a deno.json that the project's own `npm ci` ignores,
so the optimizer disappears on the next Node build.

Read the manifest that owns dependencies instead (bun lock, then deno.json,
then package.json), and fall back to the runtime's client only when no
manifest is readable. Verified with this branch's CLI run under Deno:
a package.json-only scaffold now prints `npm install @veryfront/ext-css-
lightning`, and the same directory with a deno.json prints
`deno add npm:@veryfront/ext-css-lightning`.

The warning test now pins the three runnable commands as literals rather than
asking the formatter what it would emit, so a formatter that regressed could
not satisfy the assertion by agreeing with itself.
@kojiwakayama
kojiwakayama force-pushed the fix/dx-20260811-r2-26 branch from 776ffb6 to 2ae9dc8 Compare August 12, 2026 04:00
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026

@kwakayama kwakayama left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • [Medium] src/extensions/install-command.ts:28-40 models only npm, Bun, and Deno. Thus a normal project with package.json plus pnpm-lock.yaml or yarn.lock falls through to "npm" and emits npm install at src/extensions/install-command.ts:99-100. This contradicts the stated goal of a command the project can use: pnpm and Yarn are first-class documented install paths (docs/getting-started/installation.md:24-30), and the existing CLI detector explicitly recognizes both lockfiles (cli/utils/package-manager.ts:58-64). Following the warning creates a conflicting package-lock.json and leaves the pnpm/Yarn lock stale, so frozen-lockfile CI will reject the change. Add pnpm/Yarn targets (pnpm add/yarn add), detect their lockfiles (including workspace-root lockfiles where applicable), and cover them in src/extensions/install-command.test.ts.

Score breakdown: correctness 32/40, tests 14/20, reliability/security 15/15, maintainability 13/15, scope/docs 8/10.

Review-Gate:
Reviewer: Codex
Reviewed-SHA: 2ae9dc8
Score: 82/100
Actionable-Findings: 1
Verdict: REQUEST_CHANGES

@kwakayama kwakayama added the needs-human-input Maintainer action required label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@kwakayama
kwakayama removed this pull request from the merge queue due to a manual request Aug 12, 2026
The install hint modelled only npm, Bun, and Deno. `MANIFESTS` listed
`bun.lock`, `bun.lockb`, `deno.json`, `deno.jsonc`, and `package.json`, so a
pnpm or Yarn project -- both first-class documented install paths -- matched
`package.json` and fell to the `default` arm of `formatInstallCommand`, which
prints `npm install`. Running it writes a conflicting `package-lock.json` and
leaves `pnpm-lock.yaml` or `yarn.lock` stale, so the next frozen-lockfile CI run
rejects the change. The CLI's own detector already read both lockfiles, so
`veryfront init` and the warning it later prints disagreed with each other.

The lockfile/manifest table now lives once, in `src/utils/package-client.ts`.
`cli/utils/package-manager.ts` reads it through the
`veryfront/utils/package-client` package surface instead of keeping its own
copy; `enforce-cli-boundary.ts` allows that direction and bans the reverse, and
the CLI detector is async and shells out, so it cannot serve a build-time
warning path.

Detection reads the lockfile first, because `package.json` is identical under
npm, pnpm, and Yarn. pnpm and Yarn workspaces keep that lockfile at the root
while members hold only a `package.json`, so a `package.json`-only directory is
searched upward, bounded at four levels. Only an npm-family lockfile may claim
it: a `deno.lock` in an enclosing repository must not turn the hint into
`deno add`, which is the failure this module exists to avoid. `deno.json` still
short-circuits ahead of the walk.

`formatInstallCommand` gained `pnpm add` and `yarn add`.

`cli/utils/package-manager.test.ts` walks every `LOCKFILE_CLIENTS` entry and
asserts the CLI and framework detectors return the same client for the same
directory, so the two cannot drift apart again.
@kojiwakayama

Copy link
Copy Markdown
Contributor Author

Review-Gate finding: confirmed in source, fixed

[Medium] src/extensions/install-command.ts models only npm, Bun, and Deno — real.

What I read at 08b8835, not what the review said:

  • src/extensions/install-command.ts:35-41MANIFESTS held exactly five entries:
    bun.lock, bun.lockbbun; deno.json, deno.jsoncdeno; package.jsonnpm.
    No pnpm-lock.yaml, no yarn.lock, and no lockfile at all for the npm family.
  • src/extensions/install-command.ts:94-101 — the switch carried cases for deno and
    bun only; everything else fell to default: return \npm install ${bareName}`. Combined with the table above, *any* project holding a package.json— pnpm, Yarn, or npm — was printednpm install`.
  • cli/utils/package-manager.ts:58-64LOCKFILES did list pnpm-lock.yamlpnpm
    and yarn.lockyarn. So the disagreement was real and internal: veryfront init
    ran pnpm install, and the CSS warning then told the same reader to run npm install.
  • docs/getting-started/installation.md:25 and :29pnpm add veryfront and
    yarn add veryfront are documented, first-class install paths.

Reproduced with the branch's own formatter against real directories on disk
(deno run --allow-read --allow-env, one line per directory):

### BEFORE
/tmp/repro-3597/pnpm-app            -> npm  | npm install @veryfront/ext-css-lightning
/tmp/repro-3597/yarn-app            -> npm  | npm install @veryfront/ext-css-lightning
/tmp/repro-3597/ws/packages/app     -> npm  | npm install @veryfront/ext-css-lightning
### AFTER
/tmp/repro-3597/pnpm-app            -> pnpm | pnpm add @veryfront/ext-css-lightning
/tmp/repro-3597/yarn-app            -> yarn | yarn add @veryfront/ext-css-lightning
/tmp/repro-3597/ws/packages/app     -> pnpm | pnpm add @veryfront/ext-css-lightning

The third directory holds only a package.json; its pnpm-lock.yaml is two levels up at
the workspace root — the case the review asked to be covered explicitly.

What changed

One table, two readers — the shared code you asked for. The lockfile/manifest table now
lives once, in the new src/utils/package-client.ts, and cli/utils/package-manager.ts
reads it from there via the veryfront/utils/package-client package surface rather than
keeping its own LOCKFILES copy.

I checked the boundary lints before choosing the direction, as asked.
scripts/lint/enforce-cli-boundary.ts:23,66-75 bans #veryfront/* imports from cli/ but
permits veryfront/* package surfaces — the same route cli/ already uses for
veryfront/utils/case-utils and veryfront/utils/import-lockfile. So clisrc is
allowed and srccli is not, which settles the direction. It is also the right
direction on the merits: detectPackageManager is async, logs through cliLogger, and
its module shells out via runCommand — none of that belongs on a build-time warning path.
lint:cli-boundary, lint:module-boundaries, and lint:dependency-boundaries all pass.

Detection now reads the lockfile, then walks to the workspace root. package.json alone
is byte-identical under npm, pnpm, and Yarn, so it cannot name the client; the lockfile can.
pnpm and Yarn workspaces keep that lockfile at the root while members hold only a
package.json, so a package.json-only directory is searched upward (bounded at four
levels). deno.json short-circuits ahead of the walk, since Deno resolves dependencies from
the manifest itself.

One case the finding did not name, which the walk introduced and which I closed: only an
npm-family lockfile may claim a package.json. A deno.lock in an enclosing repository —
a --runtime node scaffold checked out inside a Deno repo — must not flip the hint to
deno add, which is the exact failure this PR opened with.

formatInstallCommand gained pnpm add and yarn add.

Tests

  • src/extensions/install-command.test.ts — all five clients spelled out as string literals
    (a regressed formatter cannot satisfy them by agreeing with itself); pnpm, Yarn, npm and
    Deno lockfiles beside a package.json; the workspace-root pnpm-lock.yaml a member does
    not hold; a member's own lockfile winning over the root's; an enclosing deno.lock not
    claiming a Node package.
  • cli/utils/package-manager.test.ts — a case that walks every entry of LOCKFILE_CLIENTS
    and asserts detectPackageManager (CLI) and detectProjectInstallTarget (framework)
    return the same client for the same directory. That is the regression test for the finding
    itself: the two detectors cannot drift apart again without it going red.
  • src/html/styles-builder/css-provider-session.test.ts — the runnable-command list widened
    from three to five.

Gates

deno task fmt:check, deno task typecheck, deno task lint:ci (which includes
lint:module-boundaries, lint:dependency-boundaries, docs:api-reference:check), and the
full deno task test:unit — all green on Deno 2.7.7. Only an imports entry was added to
deno.json; the exports map is untouched, so the generated API reference does not move.

@kojiwakayama kojiwakayama mentioned this pull request Aug 12, 2026
@kojiwakayama

Copy link
Copy Markdown
Contributor Author

The P2 on package-manager detection is fixed as of cc9581cd, which post-dates the reviewed SHA 2ae9dc89.

src/extensions/install-command.ts now resolves the client from the shared LOCKFILE_CLIENTS table in #veryfront/utils/package-client.ts — the same source the CLI detector reads — so a pnpm-lock.yaml or yarn.lock project is told to run pnpm add / yarn add rather than npm install. Sharing the table was deliberate: two detectors that can disagree would be a worse defect than the one being fixed. Covered in install-command.test.ts by iterating every lockfile in the table.

Queueing on that basis. Happy to revisit if the gate re-runs and disagrees.

@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 12, 2026
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit d5a0383 Aug 12, 2026
35 checks passed
@kojiwakayama
kojiwakayama deleted the fix/dx-20260811-r2-26 branch August 12, 2026 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human-input Maintainer action required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants