Repository navigation
docs(web/blog): LuCLI and the Zero-Docker Developer Experience (recover failed auto-deploy) - #2580
Conversation
…er failed auto-deploy) The scheduled auto-deploy for this post failed at 2026-05-11 08:19:00 with a rebase conflict on an unrelated file (multi-tenancy-built-in.md). Root cause: GitDeployer rebases the current branch onto origin/develop without ensuring the working tree is on develop first; when the wheels repo was left on a feature branch (peter/bot-convergence-loop) that had already-merged commits, the rebase replayed them and hit add/add. The export ran successfully (lastExportedAt=2026-05-11 08:19:00, body matches DB), so this is purely the missing commit. Same recovery pattern as #2551 (multi-tenancy). Companion fix landed in wheels-publishing-admin (PR #2) hardens GitDeployer to ensure develop checkout before deploy, so tomorrow's launch article does not hit the same trap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: This is a pure-docs recovery PR adding one new blog post file. The content is accurate, well-written, and honest about what is still in-progress. Commit message and frontmatter both follow established conventions. I have one factual inaccuracy in the CLI command list worth fixing before the post goes live.
Correctness
CLI command conflation in 'What ships in the 4.0 CLI'
File: web/content/blog/posts/lucli-zero-docker-developer-experience.md, around line 107
The post lists:
`wheels dbmigrate latest | up | down | info | diff` handles migrations, including auto-diff for model-versus-schema drift.
This conflates two separate commands into one pseudo-command:
- The standard migration runner in the LuCLI module (
cli/lucli/Module.cfc) iswheels migrate latest|up|down|info. The module'smigrate()function accepts those four actions and nothing else. - The auto-diff is a separate CommandBox-era surface:
wheels dbmigrate diff(cli/src/commands/wheels/dbmigrate/diff.cfc).
A reader trying wheels dbmigrate latest on a pure LuCLI install would reach the CommandBox command (if installed) or get an error, not the LuCLI migration runner. CLAUDE.md confirms the two surfaces separately: the Migrate row has wheels migrate latest|up|down|info, and the Auto-Migration Quick Reference separately documents wheels dbmigrate diff.
Suggested fix — split the bullet into two:
- `wheels migrate latest | up | down | info` runs database migrations.
- `wheels dbmigrate diff` generates migrations from model-vs-schema diffs (auto-migration).
Docs
The forward link to /posts/wheels-deploy-kamal-port/ resolves -- wheels-deploy-kamal-port.md exists in the blog posts directory. No action needed.
Frontmatter shape and field set match the existing multi-tenancy-built-in.md exactly (title, slug, publishedAt, updatedAt, author, tags, categories, excerpt, coverImage). No issues.
Commits
Single commit:
docs(web/blog): LuCLI and the Zero-Docker Developer Experience (recover failed auto-deploy)
Type docs, scope web/blog -- both on the commitlint allow-list. Subject uses mixed-case proper nouns (LuCLI) which is permitted. Header is 91 characters, under the 100-char cap. Commitlint should accept this.
Security
No code, no secrets, no fixtures. Clean.
The wheels dbmigrate conflation is the only factual issue worth fixing before the post goes live -- it will actively mislead readers following along on a pure LuCLI install. Everything else is in good shape.
Wheels Bot — Reviewer B (round 1)A's review is largely solid -- the SycophancyNone detected. A's "well-written and honest" and "everything else is in good shape" are backed by concrete checks (commit message length, frontmatter shape, forward-link existence), not empty praise. False positivesNone detected. A's claim about
The article smashes them into a single pseudo-command. A read the lines and the reference; the finding stands. Missed issues
File: The "What ships in the 4.0 CLI" section (diff line 117) reads:
CLAUDE.md documents the server commands as top-level:
A reader following the CLI reference section would try Suggested fix for that bullet: Verdict alignmentA used ConvergenceNot aligned. A needs to acknowledge the |
There was a problem hiding this comment.
Wheels Bot — Reviewer A response (round 1)
B is correct. I audited the CLI reference list in the diff sequentially, found the wheels dbmigrate conflation, and stopped looking. I did not scan the remaining bullets in the same list for the same class of error. The wheels server start | stop | status bullet is a second instance of the identical failure mode and I missed it.
Conceded points
-
wheels server start | stop | statusis factually wrong. Diff line ~117 (the CLI surface table, "What ships in the 4.0 CLI") reads:`wheels server start | stop | status` wraps the LuCLI server lifecycle.CLAUDE.md's Development Tools table documents the server commands as top-level:
wheels start|stop|status(noserverprefix). The blog post's own prose four paragraphs earlier (diff line ~84) also useswheels start:scaffold a throwaway app with
wheels new scratch && cd scratch && wheels startA reader following the CLI reference section and trying
wheels server starton a standard LuCLI install would get an error. Same failure mode as thewheels dbmigrateissue I flagged. B was right to call this out, and I was wrong to conclude the conflation was "the only factual issue."Suggested fix:
- `wheels start | stop | status` wraps the LuCLI server lifecycle.
Defended points
None. B raised no false positives against my review, and I have no new objections to B's analysis.
Updated verdict
Request changes. There are two confirmed factual CLI command errors in the "What ships in the 4.0 CLI" section: (1) wheels dbmigrate latest | up | down | info | diff conflating two separate surfaces, and (2) wheels server start | stop | status using a non-existent server subcommand prefix. Both should be fixed before the post goes live.
Two factual CLI errors flagged by wheels-bot review: - `wheels dbmigrate latest|up|down|info|diff` conflated two distinct surfaces. The LuCLI module exposes `wheels migrate latest|up|down|info`; `wheels dbmigrate diff` is the separate auto-migration surface. Split into two bullets so readers on a pure-LuCLI install run the right command. - `wheels server start|stop|status` used a non-existent `server` prefix. Server lifecycle is top-level: `wheels start|stop|status` (matches CLAUDE.md Development Tools table and the post's own prose four paragraphs earlier). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: This is a follow-up commit on a pure-docs blog post that addresses both factual CLI command errors flagged in the previous review. Both fixes are correct. The remaining file is clean. One pre-existing minor nit on engine support language is worth a quick pass before the post goes live, but it does not block the merge.
Correctness
Previous findings resolved.
The two CLI errors flagged in the prior review have been correctly addressed in commit 6d6647e:
-
wheels dbmigrate latest | up | down | info | diff→ split into two separate bullets:wheels migrate latest | up | down | info(LuCLI module, matches CLAUDE.md Development Tools table)wheels dbmigrate diff(auto-migration surface, matches CLAUDE.md Auto-Migration Quick Reference)
-
wheels server start | stop | status→wheels start | stop | status(top-level server commands, consistent with CLAUDE.md and with the post's own prose at line 84:wheels start).
Both fixes match the canonical surfaces documented in CLAUDE.md. The commit message attributes both changes explicitly and correctly.
Pre-existing minor nit: engine support claim (not introduced by this commit).
File: web/content/blog/posts/lucli-zero-docker-developer-experience.md, line 26
The framework supports Lucee 5, 6, 7, Adobe ColdFusion 2018, 2021, 2023, 2025, plus BoxLang, across seven databases.
CLAUDE.md states: "compose.yml also defines lucee5, adobe2018, adobe2021 services for historical reasons; they are NOT in the CI matrix and should be considered unsupported for new development." Framing all eight engine versions as uniformly "supported" may set false expectations for users targeting Lucee 5 or Adobe 2021. Consider tightening the sentence:
The framework targets Lucee 6, 7, Adobe ColdFusion 2023, 2025, and BoxLang across seven databases,
with legacy Compose definitions for Lucee 5, Adobe 2018, and Adobe 2021 that are not CI-gated.Or simply drop the legacy engines from the sentence and add a parenthetical if needed.
Minor nit: "Wheels CLI installers" link targets macOS-only repo.
File: web/content/blog/posts/lucli-zero-docker-developer-experience.md, line 133
The "Wheels CLI installers" anchor points to github.com/wheels-dev/homebrew-wheels. A Windows user clicking "Wheels CLI installers" would land on the Homebrew tap, not Scoop. Consider pointing the anchor to a neutral landing page or dropping the outer anchor and letting the inline Homebrew tap / scoop-wheels links carry the platform-specific navigation.
Commits
Both commits conform to commitlint:
| Commit | Type | Scope | Subject |
|---|---|---|---|
66827a2 |
docs |
web/blog |
LuCLI and the Zero-Docker Developer Experience (recover failed auto-deploy) |
6d6647e |
docs |
web/blog |
correct CLI surfaces in LuCLI post |
Both types and scopes are on the allow-list. Headers are under 100 characters. No ALL-CAPS subjects. Commit 6d6647e documents the "why" (bot review, specific error class, CLAUDE.md reference) in the body — good practice.
Security
No code, no secrets, no fixtures. Clean.
Tests
Not applicable — docs-only change.
The blocking issues from the previous review are resolved. The engine support nit and the installer link nit are worth a quick editorial pass but do not affect technical accuracy of the CLI surface being described. The post is safe to merge if the maintainer is comfortable with the current engine language.
…eline Two follow-on fixes after the detect-scope grep bug exposed a deeper design issue: 1. The content-only skip in #2581 applied to both PR and push events. For PR events, that's the friction-reducer we wanted. For push events to develop, it silently broke the blog baseline auto-refresh-and-commit dance, which lives inside the visual-regression job. After #2580 merged, the post-merge push couldn't refresh the baseline (detect-scope had crashed; even if it hadn't, content_only=true would have skipped the whole job), so every subsequent non-content PR trips on the stale baseline — exactly what's happening now on this hotfix PR. Fix: tighten the visual-regression `if:` to skip only on PR events with content_only=true. Push events always run, eating the few extra CI minutes so the maintenance contract holds. 2. Refresh blog.png from this PR's CI artifact. The previous baseline was screenshot before #2580 merged and is now 38k pixels off the current develop blog index. Pulling the actual.png from the visual-regression-diffs artifact and committing it here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eline (#2585) Two follow-on fixes after the detect-scope grep bug exposed a deeper design issue: 1. The content-only skip in #2581 applied to both PR and push events. For PR events, that's the friction-reducer we wanted. For push events to develop, it silently broke the blog baseline auto-refresh-and-commit dance, which lives inside the visual-regression job. After #2580 merged, the post-merge push couldn't refresh the baseline (detect-scope had crashed; even if it hadn't, content_only=true would have skipped the whole job), so every subsequent non-content PR trips on the stale baseline — exactly what's happening now on this hotfix PR. Fix: tighten the visual-regression `if:` to skip only on PR events with content_only=true. Push events always run, eating the few extra CI minutes so the maintenance contract holds. 2. Refresh blog.png from this PR's CI artifact. The previous baseline was screenshot before #2580 merged and is now 38k pixels off the current develop blog index. Pulling the actual.png from the visual-regression-diffs artifact and committing it here. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing nits surfaced by wheels-bot Reviewer A on the now-merged LuCLI post: - Engine support: the original sentence listed Lucee 5, Adobe 2018, and Adobe 2021 alongside the CI-gated engines, but CLAUDE.md explicitly notes those three are NOT in the matrix and should be considered unsupported for new development. Reframe so the CI matrix is what's "supported" and the legacy versions are called out as not CI-gated. - "Wheels CLI installers" anchor pointed only to homebrew-wheels — misleading for Windows readers. Drop the outer anchor so the inline Homebrew + scoop-wheels links carry platform-specific navigation. Both nits were flagged as non-blocking on PR #2580 and merged through; addressing them now as a follow-up so the published post is accurate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing nits surfaced by wheels-bot Reviewer A on the now-merged LuCLI post: - Engine support: the original sentence listed Lucee 5, Adobe 2018, and Adobe 2021 alongside the CI-gated engines, but CLAUDE.md explicitly notes those three are NOT in the matrix and should be considered unsupported for new development. Reframe so the CI matrix is what's "supported" and the legacy versions are called out as not CI-gated. - "Wheels CLI installers" anchor pointed only to homebrew-wheels — misleading for Windows readers. Drop the outer anchor so the inline Homebrew + scoop-wheels links carry platform-specific navigation. Both nits were flagged as non-blocking on PR #2580 and merged through; addressing them now as a follow-up so the published post is accurate. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Re-opens #2579 (which re-opened #2578) with the correct conventional-commits scope. Commitlint requires `web/blog`, not `blog`.
Summary
Recovery PR for today's scheduled blog post that failed to auto-deploy. Same pattern as #2551 (Multi-Tenancy recovery).
What happened
The publishing-admin scheduler ran at `2026-05-11 08:19:00`, successfully exported the markdown for this post, and then asked GitDeployer to commit + push it to `develop`. The deploy step failed:
```
2026-05-11 08:19:00 ok lucli-zero-docker-developer-experience
2026-05-11 08:19:00 deploy-fail lucli-zero-docker-developer-experience rebase-failed: Rebasing (1/1)
```
The rebase conflict was on a different file (`multi-tenancy-built-in.md`), not the lucli file. Root cause: GitDeployer naively runs `git rebase origin/develop` on whatever branch the wheels repo working tree happens to be on. At the time, that was `peter/bot-convergence-loop`, which carried already-merged commits — rebasing replayed them onto develop and hit add/add conflicts.
Article content
The post body was already up to date in SQLite (`posts.id=875`, body=12776 chars). After the failed deploy I made five follow-up edits today that the auto-deploy never had a chance to ship:
Why this is safe to merge
Companion PR (already merged)
wheels-dev/wheels-publishing-admin#2 hardens `GitDeployer.cfc` to switch to develop before deploying, which is the structural fix that prevents tomorrow's launch article from hitting the same trap. Merged.
Test plan
🤖 Generated with Claude Code