Repository navigation
fix(cli): generated-app templates stop advertising broken wheels packages install verb - #2611
Conversation
…kages install` verb LuCLI's built-in extension installer intercepts the literal subcommand `install` across every module, so `wheels packages install <name>` never reaches Module.cfc — it prints "No git or extension dependencies to install" and exits without installing anything. The canonical install verb is `wheels packages add` (this is already documented in the PackagesMainCli header and in CLAUDE.md's packages quick reference). The generated-app templates shipped via `wheels new` still pointed users at the broken verb in two places — `_gitignore` and `app/plugins/README.md` — so every new app inherited misleading help text. Reword both to point at `wheels packages add`. Closes the CLI-side half of #2610. Docs sync (MDX guides, `.ai/wheels/`, `CLAUDE.md`) is handled separately by bot-update-docs.yml. Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
…`wheels packages add` Co-authored-by: claude[bot] <claude[bot]@users.noreply.github.com> Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Wheels Bot — Docs updatedAdded a doc commit to this PR:
|
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: This PR correctly fixes two template files from advertising the broken wheels install / wheels packages install verbs and adds a regression-guard spec. The changes are minimal, focused, and accurate. Verdict: comment — a couple of minor spec quality nits, nothing that blocks merge.
Correctness
The root cause is correctly diagnosed: LuCLI's built-in extension installer intercepts the literal subcommand install, so wheels packages install never reaches Module.cfc. The canonical verb is wheels packages add (confirmed by CLAUDE.md Package System section).
Both template files are correctly updated:
cli/lucli/templates/app/_gitignoreline 21:wheels installchanged towheels packages add <name>cli/lucli/templates/app/app/plugins/README.md: the oldgh repo cloneworkaround (labelled "Until Wheels 4.1 ships") is removed and replaced with the canonicalwheels packages addworkflow.
The CHANGELOG entry is well-formed under [Unreleased].
Tests
Nit 1: third it block is missing a FileExists guard.
vendor/wheels/tests/specs/packages/CliTemplateInstallVerbSpec.cfc lines 30-34:
it("the generated app's plugins/README points at the canonical wheels packages add verb", () => {
var path = ExpandPath("/cli/lucli/templates/app/app/plugins/README.md");
var contents = FileRead(path); // no FileExists guard
expect(contents).toInclude("wheels packages add");
});The second it block (lines 22-28) already calls expect(FileExists(path)).toBeTrue() before FileRead(). The third block omits it. If the file were missing the test would surface as an ENGINE ERROR rather than a test FAILURE, making CI failures less diagnostic. Suggested fix: add expect(FileExists(path)).toBeTrue(); before the FileRead() call.
Nit 2: _gitignore test is asymmetric — negative assertion only, no positive.
vendor/wheels/tests/specs/packages/CliTemplateInstallVerbSpec.cfc lines 15-20:
it("the generated app's _gitignore does not reference wheels install", () => {
var path = ExpandPath("/cli/lucli/templates/app/_gitignore");
expect(FileExists(path)).toBeTrue();
var contents = FileRead(path);
expect(contents).notToInclude("wheels install");
});The README tests pair a notToInclude with a toInclude assertion. The _gitignore test only guards the negative. A future edit could remove the wheels packages add comment entirely and the test would still pass. Adding expect(contents).toInclude("wheels packages add"); would close the gap.
Docs
The PR body correctly notes that MDX guides, .ai/wheels/, and CLAUDE.md follow-up is delegated to bot-update-docs.yml. Acceptable for a two-line template fix.
The added sentence in plugins/README.md — "Note: the install verb is add, not install." — is slightly redundant alongside the code block that already shows wheels packages add, but harmless as explicit disambiguation for users upgrading from 3.x muscle memory.
Commits
Single commit fix(cli): generated-app templates stop advertising broken wheels packages install verb — type fix, scope cli, subject under 100 chars, not ALL-CAPS. Signed-off-by: trailer present and matches the commit author. All commitlint checks pass.
Wheels Bot — Reviewer B (round 1)A's review is largely sound — the two spec nits are valid and well-cited against the actual source. Two issues B caught that A missed: (1) A states "Single commit" in the Commits section when there are actually two commits in this PR; (2) A did not flag the tutorial inconsistency in SycophancyNone detected. A backed every positive statement with a specific code citation. False positivesNone detected. Both nits are verified against the actual spec source:
Missed issues
Verdict alignmentA's ConvergenceNot aligned. A needs to respond to (a) the two-commit factual claim and (b) the tutorial code-block inconsistency. If A concedes the tutorial fix is worth doing, B would converge to |
There was a problem hiding this comment.
Wheels Bot Reviewer A\n\nTL;DR: The PR has grown from a single fix(cli) commit (two template edits + a spec) to a two-commit change that also sweeps the MDX guides. Both commits are correct and the docs coverage is solid. The two spec nits raised in the previous Reviewer A round are still unaddressed, and the new docs commit introduces two minor documentation inconsistencies. Nothing blocks merge; submitting as comment.\n\n---\n\n### Tests\n\nNit 1 (carry-forward): third it block — missing FileExists guard\n\nvendor/wheels/tests/specs/packages/CliTemplateInstallVerbSpec.cfc lines 29-33: The second it block (lines 22-28) correctly calls expect(FileExists(path)).toBeTrue() before FileRead(). The third block skips that guard. If the file were ever missing, the error would surface as an ENGINE ERROR rather than a test FAILURE, making CI failures harder to diagnose. Add expect(FileExists(path)).toBeTrue(); before the FileRead() call.\n\nNit 2 (carry-forward): _gitignore test has only a negative assertion\n\nLines 15-20: The README tests pair notToInclude with toInclude for symmetry. The _gitignore test guards only the negative. A future edit that removed the comment entirely would still pass. Adding expect(contents).toInclude("wheels packages add"); closes the gap.\n\n---\n\n### Docs\n\nNit 3 (new): install.mdx file not renamed — URL/title mismatch\n\nThe page title and sidebar label were updated to "add" in the frontmatter, but the file is still install.mdx, so Astro derives the URL as .../packages/install. The link in index.mdx line 34 reads [add](./install) — the anchor text says "add" but the URL says "install". For a page about a verb that was renamed precisely because "install" was confusing, the URL mismatch is a minor UX rough edge. The tidy fix is to rename the file to add.mdx and add a redirect entry for the old slug. If a rename is out of scope for this PR, a one-line note in the PR body acknowledging it is enough.\n\nNit 4 (new): tutorial code block vs aside are semantically misaligned\n\nweb/sites/guides/src/content/docs/v4-0-0-snapshot/start-here/tutorial/03-crud-scaffold.mdx lines 279-288 (post-merge state): The code block is labelled title="illustrative — do not type" and shows gh repo clone wheels-dev/wheels-hotwire vendor/wheels-hotwire. The updated Aside directly below it says "Use wheels packages add wheels-hotwire to install from the registry. The gh repo clone above is the manual fallback if the registry is unavailable." The two frames are contradictory: the code block title says "do not type" (teaching example), but the Aside calls it a "manual fallback" (active alternative). A reader following the tutorial cannot determine from context whether they should run gh repo clone or not. The cleaner fix is to update the code block to show wheels packages add wheels-hotwire as the primary example and demote gh repo clone to a collapsed note, which also lets the "do not type" label be dropped.\n\nMinor: PR body checklist is stale\n\nThe PR body marks "Framework Docs" as unchecked with a note that bot-update-docs.yml will handle it, but the second commit covers exactly those MDX guide updates. Worth ticking the checkbox to keep the checklist accurate.\n\n---\n\n### Commits\n\nBoth commits conform to commitlint.config.js:\n\n- fix(cli): generated-app templates stop advertising broken wheels packages install verb — type fix, scope cli, subject 77 chars, not ALL-CAPS, Signed-off-by trailer present.\n- docs(web/guides): replace broken wheels packages install verb with wheels packages add — type docs, scope web/guides, subject 72 chars, not ALL-CAPS, Signed-off-by trailer present.\n\nBoth messages explain the why (LuCLI interception of the install subcommand) rather than just the what.\n\n---\n\n
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: The PR has grown from a single fix(cli) commit (two template edits + a spec) to a two-commit change that also sweeps the MDX guides. Both commits are correct and the docs coverage is solid. The two spec nits raised in the previous Reviewer A round are still unaddressed, and the new docs commit introduces two minor documentation inconsistencies. Nothing blocks merge; submitting as comment.
Tests
Nit 1 (carry-forward): third it block — missing FileExists guard
vendor/wheels/tests/specs/packages/CliTemplateInstallVerbSpec.cfc lines 29-33:
it("the generated app's plugins/README points at the canonical wheels packages add verb", () => {
var path = ExpandPath("/cli/lucli/templates/app/app/plugins/README.md");
var contents = FileRead(path); // no FileExists() guard
expect(contents).toInclude("wheels packages add");
});The second it block (lines 22-28) correctly calls expect(FileExists(path)).toBeTrue() before FileRead(). The third block skips that guard. If the file were ever missing, the error would surface as an ENGINE ERROR rather than a test FAILURE, making CI failures harder to diagnose. Add expect(FileExists(path)).toBeTrue(); before the FileRead() call.
Nit 2 (carry-forward): _gitignore test has only a negative assertion
Lines 15-20:
it("the generated app's _gitignore does not reference wheels install", () => {
var path = ExpandPath("/cli/lucli/templates/app/_gitignore");
expect(FileExists(path)).toBeTrue();
var contents = FileRead(path);
expect(contents).notToInclude("wheels install"); // only negative
});The README tests pair notToInclude with toInclude for symmetry. The _gitignore test guards only the negative. A future edit that removed the comment entirely would still pass. Adding expect(contents).toInclude("wheels packages add"); closes the gap.
Docs
Nit 3 (new): install.mdx file not renamed — URL/title mismatch
The page title and sidebar label were updated to "add" in the frontmatter:
title: "wheels packages add"
sidebar:
label: "add"But the file is still install.mdx, so Astro derives the URL as .../packages/install. The link in index.mdx line 34 reads [add](./install) — the anchor text says "add" but the URL says "install". For a page about a verb that was renamed precisely because "install" was confusing, the URL mismatch is a minor UX rough edge. The tidy fix is to rename the file to add.mdx and add a redirect entry for the old slug. If a rename is out of scope for this PR, a one-line note in the PR body acknowledging it is enough.
Nit 4 (new): tutorial code block vs aside are semantically misaligned
web/sites/guides/src/content/docs/v4-0-0-snapshot/start-here/tutorial/03-crud-scaffold.mdx lines 279-288 (post-merge state):
The code block is labelled title="illustrative — do not type" and shows gh repo clone wheels-dev/wheels-hotwire vendor/wheels-hotwire. The updated Aside directly below it says "Use wheels packages add wheels-hotwire to install from the registry. The gh repo clone above is the manual fallback if the registry is unavailable."
The two frames are contradictory: the code block title says "do not type" (teaching example), but the Aside calls it a "manual fallback" (active alternative). A reader following the tutorial cannot determine from context whether they should run gh repo clone or not. The cleaner fix is to update the code block to show wheels packages add wheels-hotwire as the primary example and demote gh repo clone to a collapsed note, which also lets the "do not type" label be dropped.
Minor: PR body checklist is stale
The PR body marks "Framework Docs" as unchecked with a note that bot-update-docs.yml will handle it, but the second commit covers exactly those MDX guide updates. Worth ticking the checkbox to keep the checklist accurate.
Commits
Both commits conform to commitlint.config.js:
fix(cli): generated-app templates stop advertising broken wheels packages install verb— typefix, scopecli, subject 77 chars, not ALL-CAPS,Signed-off-bytrailer present.docs(web/guides): replace broken wheels packages install verb with wheels packages add— typedocs, scopeweb/guides, subject 72 chars, not ALL-CAPS,Signed-off-bytrailer present.
Both messages explain the why (LuCLI interception of the install subcommand) rather than just the what.
Pulls in PR #2611 ("wheels packages install" → "wheels packages add" cleanup) plus its companion CHANGELOG entry, _gitignore template fix, plugins/README cleanup, and the new CliTemplateInstallVerbSpec test. Conflict resolution: develop edited five files under v4-0-0-snapshot/ that this branch renamed to v4-0-0/ in commit 4a62207. Git's rename-detection picked the v4-0-1-snapshot/ clone as the move target (content was more similar there since the v4-0-0/ versions had the internal-link sed pass applied in commit 81316ba), so the merge auto-applied develop's content updates to v4-0-1-snapshot/ only. Mirrored those same content updates into v4-0-0/ by hand: copied each merged v4-0-1-snapshot/<path> over the v4-0-0/<path> counterpart and ran `sed 's|/v4-0-1-snapshot/|/v4-0-0/|g'` to restore the stable URL slug. End state: both directories carry develop's content updates, each with the correct URL slug for its channel. Files affected: - command-line-tools/commands/packages/index.mdx - command-line-tools/commands/packages/install.mdx - deployment/observability-and-logging.mdx - start-here/tutorial/03-crud-scaffold.mdx - upgrading/3x-to-4x.mdx Verified post-resolution: v4-0-0/<path> matches v4-0-1-snapshot/<path> modulo URL slugs (diff is purely /v4-0-0/ vs /v4-0-1-snapshot/ tokens). Signed-off-by: Peter Amiri <peter@alurium.com>
Summary
LuCLI's built-in extension installer intercepts the literal subcommand
installacross every module, sowheels packages install <name>never reachesModule.cfc— it printsNo git or extension dependencies to installand exits without installing anything. The canonical install verb iswheels packages add. The generated-app templates shipped viawheels newstill pointed users at the broken verb in two places, so every new app inherited misleading help text.This PR rewords the two template files to point at
wheels packages addand adds a regression-guard spec.Fixes #2610
Related Issue
Closes #2610
Type of Change
Feature Completeness Checklist
Signed-off-by:trailer present on the commit (git commit -s).vendor/wheels/tests/specs/packages/CliTemplateInstallVerbSpec.cfcis new: three assertions that all fail on the pre-fix tree and pass after the template edits.bot-update-docs.ymlhandles MDX-guide follow-ups.bot-update-docs.ymlhandles.ai/wheels/follow-ups.bot-update-docs.ymlhandlesCLAUDE.mdfollow-ups if needed.[Unreleased]section.grepagainst the spec's exact assertions (see Test Plan below). The wheels CLI was not installed in the bot's sandbox sobash tools/test-local.sh packagescould not run end-to-end here; the spec is straightforwardFileRead+toInclude/notToIncludechecks and runs through the normal core-test runner in CI.Test Plan
The spec asserts three deterministic file-content invariants that
grepcan verify standalone:CI will run the spec against the real test server (Lucee 7 + SQLite + the rest of the compat matrix) — the spec is in
vendor/wheels/tests/specs/packages/so it's part of the standard core suite.Screenshots / Output
n/a (template-file edits + spec).